def group_compatible_matches(matches):
    """ Groups matches into compatible sets of indices of non-conflicting matches.
        Indices are given by the positions in the matches list.
        :param matches A list of Matches.

        :return A list of sets of integers. Each set is unique and contains matches indices
                of compatible Matches.
    """
    are_all_clashes = True
    clash_pairs = []
    for i in range(len(matches)):
        for j in range(i + 1, len(matches)):
            if i != j:
                if matches[i].is_compatible(matches[j]):
                    are_all_clashes = False
                else:
                    clash_pairs.append((i, j))
                    clash_pairs.append((j, i))
    combinations = [{i} for i in range(len(matches))]
    if are_all_clashes:
        return combinations
    for i in range(len(matches)):
        for comb in combinations:
            if i not in comb:
                if comb.union({i}) in combinations:
                    combinations.remove(comb)
                    break
                clash = False
                for match_id in comb:
                    if (i, match_id) in clash_pairs:
                        clash = True
                        break
                if not clash:
                    comb.add(i)
    return combinations


def _secure_compare(x, y):
    """
    Compare 2 strings securely in order to avoid
    a timing attack
    """
    if len(x) != len(y):
        return False
    result = 0
    for a, b in zip(x, y):
        result |= ord(a) ^ ord(b)
    return result == 0


@staticmethod
def dim_ouput(output_id, percent, ramp):
    """Generate a dim command for a single output-port.

        :param    int    output_it:    Output id 0..3
        :param    int    percent:      Brightness in percent 0..100
        :param    int    ramp:         Ramp value
        :return:    The PCK command (without address header) as text
        :rtype:    str
        """
    if output_id < 0 or output_id > 3:
        raise ValueError('Invalid output_id.')
    percent_round = int(round(percent * 2))
    ramp = int(ramp)
    if percent_round % 2 == 0:
        pck = 'A{:d}DI{:03d}{:03d}'.format(output_id + 1, percent_round //
            2, ramp)
    else:
        pck = 'O{:d}DI{:03d}{:03d}'.format(output_id + 1, percent_round, ramp)
    return pck


def decgift(giftID=int, count=int):
    """Release some reference to a their-reference 'giftID' that was
        sent earlier."""
    return None


@classmethod
def from_path(cls, path):
    """Create a new registry from a text file.

        Parameters
        ----------
        path : str
            Path to a text file of Standard Names.

        Returns
        -------
        NamesRegistry
            A newly-created registry filled with names from the file.
        """
    return cls(path)


def allZero(buffer):
    """
    Tries to determine if a buffer is empty.

    @type buffer: str
    @param buffer: Buffer to test if it is empty.

    @rtype: bool
    @return: C{True} if the given buffer is empty, i.e. full of zeros,
        C{False} if it doesn't.
    """
    allZero = True
    for byte in buffer:
        if byte != 0:
            allZero = False
            break
    return allZero


def _set_is_decoded(sender, instance, **kwargs):
    """Returns true if payload_decoded has data"""
    instance.is_decoded = instance.payload_decoded != ''


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

        :returns: this backend supports items resuming
        """
    return True


def load_twitter(finder, module):
    """the twitter module tries to load the simplejson, json and django.utils
       module in an attempt to locate any module that will implement the
       necessary protocol; ignore these modules if they cannot be found."""
    module.IgnoreName('json')
    module.IgnoreName('simplejson')
    module.IgnoreName('django.utils')


def initialize():
    """Instantiates the cache area to be ready for updates"""


def load_numpy_linalg(finder, module):
    """the numpy.linalg module implicitly loads the lapack_lite module; make
       sure this happens"""
    finder.IncludeModule('numpy.linalg.lapack_lite')


def log_to_console(settings):
    """
    Update settings to make all loggers use the console.

    **Example usage**

    >>> import collections
    >>> settings = collections.namedtuple('settings', ['DEBUG', 'LOGGING'])
    >>> settings.DEBUG = True
    >>> settings.LOGGING = {
    ...     'version': 1,
    ...     'loggers': {
    ...         'django': {
    ...             'handlers': ['file'], 'level': 'INFO', 'propagate': True
    ...         },
    ...         'django.request': {
    ...             'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True
    ...         },
    ...         'mysite': {
    ...             'handlers': ['console'], 'level': 'INFO', 'propagate': True
    ...         }
    ...     }
    ... }
    >>> expected_settings = collections.namedtuple('settings', ['DEBUG', 'LOGGING'])
    >>> expected_settings.DEBUG = True
    >>> expected_settings.LOGGING = {
    ...     'version': 1,
    ...     'loggers': {
    ...         'django': {
    ...             'handlers': ['console'], 'level': 'INFO', 'propagate': True
    ...         },
    ...         'django.request': {
    ...             'handlers': ['console'], 'level': 'ERROR', 'propagate': True
    ...         },
    ...         'mysite': {
    ...             'handlers': ['console'], 'level': 'INFO', 'propagate': True
    ...         }
    ...     }
    ... }
    >>> log_to_console(settings)
    >>> settings.LOGGING == expected_settings.LOGGING
    True
    """
    for logger in settings.LOGGING['loggers']:
        settings.LOGGING['loggers'][logger]['handlers'] = ['console']


def is_action_allowed(action, silent=False):
    """Checks whether the action is allowed on the context.
        Adds warnings and errors unless ``silent=True`` is passed.
        """


def viewvalues(mapping):
    """
    Get a value view to a mapping

    :type mapping: dict
    """
    try:
        return mapping.viewvalues()
    except AttributeError:
        return mapping.values()


def registerNotifier(observerfn, *args, **kwargs):
    """ Register callback which is called for notification. """


def decompose_seeds(seq, seedsize):
    """Break up a sequence into seeds.

    Seeds are essentially k-mers, but we use different terminology for here two
    reasons.

    1. These sequences are used specifically as anchors.
    2. We want to distinguish between k size (for k-mer counting) and seed size
       (for definining reference target sequences), which often have different
       optimal values.
    """
    for i in range(len(seq) - seedsize + 1):
        yield seq[i:i + seedsize]


def select_more(use_face_step: bool=True):
    """Select more vertices, edges or faces connected to initial selection

    :param use_face_step: Face Step, Connected faces (instead of edges)
    :type use_face_step: bool
    """
    pass


@classmethod
def from_string(cls, rgb_hex_str):
    """
        Return a new instance from an RGB color hex string like ``'3C2F80'``.
        """
    r = int(rgb_hex_str[:2], 16)
    g = int(rgb_hex_str[2:4], 16)
    b = int(rgb_hex_str[4:], 16)
    return cls(r, g, b)


def _get_instance(cls):
    """
        gets the registered instance.

        :rtype: object
        """
    return cls._instances.get(str(cls))


@staticmethod
def __convert_indexes_to_movestring(_x, _y):
    """Convert the move from board x,y indexes to <row><col> format (e.g. "A1")."""
    x_to_row = {(0): 'A', (1): 'B', (2): 'C'}
    y_to_col = {(0): '1', (1): '2', (2): '3'}
    mstring = ''
    mstring += x_to_row[_x]
    mstring += y_to_col[_y]
    return mstring


@classmethod
def _is_non_Exif_APP1_segment(cls, stream, offset):
    "\n        Return True if the APP1 segment at *offset* in *stream* is NOT an\n        Exif segment, as determined by the ``'Exif\x00\x00'`` signature at\n        offset 2 in the segment.\n        "
    stream.seek(offset + 2)
    exif_signature = stream.read(6)
    return exif_signature != b'Exif\x00\x00'


@staticmethod
def _get_parent_dn(dn):
    """
        Gets the dn of the parent object
        Meant to be overridden by inheriting classes.
        Raises exception if not overridden.

        :returns: string containing dn
        """
    return dn.split('/sys/cdp/inst')[0]


def p_binary(t):
    """binary : START_BLOCK bytes END_BLOCK"""
    t[0] = ''.join(map(chr, t[2]))


@classmethod
def remove_finalizer(cls, id):
    """Removes a finalizer associated with this id.

        :param id: The id of the object for which the finalizer will be
            deleted.
        """
    cls.finalizers.pop(id, None)


def _keys(obj):
    """Return iter-/generator, preferably.
    """
    return getattr(obj, 'iterkeys', obj.keys)()


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

        :param EmmChangePolicyType val:
        :rtype: EventType
        """
    return cls('emm_change_policy', val)


def s_remove(p_map, p_key, p_default=None):
    """
    s_remove(p_map, p_key)->p_value
    """
    if p_map is not None and p_key in p_map:
        p_value = p_map[p_key]
        p_map.remove(p_key)
        return p_value
    else:
        return p_default


def encode_tick_rule_array(tick_rule_array: list) ->str:
    """
    Encode array of tick signs (-1, 1, 0)

    :param tick_rule_array: (list) of tick rules
    :return: (str) encoded message
    """
    message = ''
    for element in tick_rule_array:
        if element == 1:
            message += 'a'
        elif element == -1:
            message += 'b'
        elif element == 0:
            message += 'c'
        else:
            raise ValueError('Unknown value for tick rule: {}'.format(element))
    return message


def frame_offset(delta: int=0):
    """Move current frame forward/backward by a given number

    :param delta: Delta
    :type delta: int
    """
    pass


def getMetaData():
    """
        Get node's meta data.

        The meta data must be a superset of the configuration options, and
        also at least should have a C{pubsub#node_type} entry.

        @return: C{dict} of meta data.
        """


def unbox(data, c_type=None, ffi=ffi, nullable=False):
    """
    Try to return something to pass to low-level ffi calls.
    For a cffi type, return data.
    For a Struct, return the wrapper's cdata.
    Else try to use data as a ffi initializer for c_type.
    """
    if not isinstance(data, ffi.CData):
        try:
            return data.cdata
        except AttributeError:
            if data is None and nullable:
                return ffi.NULL
            if c_type:
                return ffi.new(c_type, data)
    return data


def _convert_out_to_series(x, dates, name):
    """
    Convert x to a DataFrame where x is a string in the format given by
    x-13arima-seats output.
    """
    from io import StringIO
    from pandas import read_csv
    out = read_csv(StringIO(x), skiprows=2, header=None, sep='\t', engine=
        'python')
    return out.set_index(dates).rename(columns={(1): name})[name]


def base_rel_pointer(node=None, parent=None, attr_index=None, rawdata=None,
    new_value=None, **kwargs):
    """
    Pointer getter/setter for getting and setting pointers
    relative to the base_address in the xbe_image_header.
    """
    path = kwargs.get('p_path')
    if parent is None:
        raise KeyError('Cannot get or set base address relative ' +
            'pointers without the parent.')
    if path == '':
        raise KeyError('Cannot get or set base address relative ' +
            'pointers without a path to the pointer.')
    this_tag = parent.get_root()
    base_addr = this_tag.data.xbe_image_header.base_address
    if new_value is None:
        return parent.get_neighbor(path) - base_addr
    return parent.set_neighbor(path, new_value + base_addr)


def predict_engine_start_stop(start_stop_prediction_model, times,
    velocities, accelerations, engine_coolant_temperatures,
    state_of_charges, gears):
    """
    Predicts if the engine is on and when the engine starts.

    :param start_stop_prediction_model:
        Engine start/stop prediction model.
    :type start_stop_prediction_model: EngineStartStopModel

    :param times:
        Time vector [s].
    :type times: numpy.array

    :param velocities:
        Velocity vector [km/h].
    :type velocities: numpy.array

    :param accelerations:
        Acceleration vector [m/s2].
    :type accelerations: numpy.array

    :param engine_coolant_temperatures:
        Engine coolant temperature vector [°C].
    :type engine_coolant_temperatures: numpy.array

    :param state_of_charges:
        State of charge of the battery [%].

        .. note::

            `state_of_charges` = 99 is equivalent to 99%.
    :type state_of_charges: numpy.array

    :param gears:
        Gear vector [-].
    :type gears: numpy.array

    :return:
        If the engine is on and when the engine starts [-, -].
    :rtype: numpy.array, numpy.array
    """
    return start_stop_prediction_model(times, velocities, accelerations,
        engine_coolant_temperatures, state_of_charges, gears)


def _torads(in_file, fmap_range=None, newpath=None):
    """
    Convert a field map to rad/s units.

    If fmap_range is None, the range of the fieldmap
    will be automatically calculated.

    Use fmap_range=0.5 to convert from Hz to rad/s

    """
    from math import pi
    import nibabel as nb
    from nipype.utils.filemanip import fname_presuffix
    out_file = fname_presuffix(in_file, suffix='_rad', newpath=newpath)
    fmapnii = nb.load(in_file)
    fmapdata = fmapnii.get_fdata(dtype='float32')
    if fmap_range is None:
        fmap_range = max(abs(fmapdata.min()), fmapdata.max())
    fmapdata = fmapdata * (pi / fmap_range)
    out_img = nb.Nifti1Image(fmapdata, fmapnii.affine, fmapnii.header)
    out_img.set_data_dtype('float32')
    out_img.to_filename(out_file)
    return out_file, fmap_range


def run(rank, size):
    """ Distributed function to be implemented later. """
    pass


@staticmethod
def setup_subparser(parser, cmd=None):
    """
        Set up a subparser for 'install'
        """
    group = parser.add_argument_group('Install arguments' if cmd ==
        'install' else 'Update arguments')
    group.add_argument('packages', help=
        'List of packages to install/update', action='append', default=[],
        nargs='*', metavar='PACKAGES')
    group.add_argument('--print-tree', help='Print dependency tree', action
        ='store_true')
    group.add_argument('--no-deps', help=
        'Skip dependencies (may cause builds to fail!)', action='store_true')
    group.add_argument('--verify', help='Verify installs were successful',
        action='store_true')
    if cmd == 'install':
        group.add_argument('--static', help=
            'Build package(s) statically (implies source build)', action=
            'store_true')
        group.add_argument('--deps-only', help=
            'Only install the dependencies, not the requested packages',
            action='store_true')
        group.add_argument('-u', '--update', help=
            'If packages are already installed, update them instead.',
            action='store_true')
    elif cmd == 'update':
        group.add_argument('-a', '--all', help=
            'Update all packages installed to current prefix, including dependencies.'
            , action='store_true')


def _test_args():
    """Extra arguments to use when zipline's automated tests run this example.
    """
    import pandas as pd
    return {'start': pd.Timestamp('2004', tz='utc'), 'end': pd.Timestamp(
        '2008', tz='utc')}


def get_empty_lines(text):
    """Get number of empty lines before and after text."""
    before = len(text) - len(text.lstrip('\n'))
    after = len(text) - len(text.strip('\n')) - before
    return before, after


def subDict(d, allowedkeys, flip=False):
    """ Returns a new dictionary with a subset of the entries of d
    that have on of the (dis-)allowed keys."""
    res = {}
    for k, v in list(d.items()):
        if (k in allowedkeys) ^ flip:
            res[k] = v
    return res


def pad_line(line):
    """Helper function to pad line to 80 characters in case it is shorter"""
    size_of_line = len(line)
    if size_of_line < 80:
        padding = 80 - size_of_line + 1
        line = line.strip('\n') + ' ' * padding + '\n'
    return line[:81]


def getReplies():
    """
        Return a sequence of the DiscussionResponse objects which are
        associated with this Discussable

        Permissions: View
        Returns: sequence of DiscussionResponses
        """


def build_pagination(page, limit, total):
    """ Generate the paging element of the results
    :rtype : object
    """
    pages = total / limit + min(1, total % limit)
    prev = max(1, page - 1) if page > 1 else None
    next = min(pages, page + 1) if page < pages else None
    return locals()


def extract(expr, name, name_index):
    """extract named part of expression, using name_index

    :param str expr: the lucene expression
    :param str name: name of the part to extract
    :param dict name_index: the dict obtained from :py:func:`name_index`
    """
    return expr[name_index[name][0]:name_index[name][0] + name_index[name][1]]


def _modify_proxy_request_test_only(unused_request):
    """Hook for modifying the request before making a fetch (test-only)."""


def _windows_covers(windows, rrtype):
    """
    Check to see if an NSECx windows list covers a type.

    :param list windows: An NSEC or NSEC3 windows list.
    :param int rrtype: The dns.rdatatype to test.
    :return: True if the windows covers the type; False if not.
    """
    window = rrtype // 256
    for win in windows:
        if win[0] == window:
            bitmap = win[1]
            offset = rrtype % 256
            byte = offset // 8
            if bitmap and len(bitmap) >= byte + 1:
                bit = offset % 8
                return bool(bitmap[byte] & 128 >> bit)
    return False


def import_string(import_name, silent=False):
    """Imports an object based on a string.  This is useful if you want to
    use import paths as endpoints or something similar.  An import path can
    be specified either in dotted notation (``xml.sax.saxutils.escape``)
    or with a colon as object delimiter (``xml.sax.saxutils:escape``).

    If the `silent` is True the return value will be `None` if the import
    fails.

    :return: imported object
    """
    try:
        if ':' in import_name:
            module, obj = import_name.split(':', 1)
        elif '.' in import_name:
            items = import_name.split('.')
            module = '.'.join(items[:-1])
            obj = items[-1]
        else:
            return __import__(import_name)
        return getattr(__import__(module, None, None, [obj]), obj)
    except (ImportError, AttributeError):
        if not silent:
            raise


def truncate(string, width):
    """
    Truncates/pads the string to be the the specified length,
    including ellipsis dots if truncation occurs.
    """
    if len(string) > width:
        return string[:width - 3] + '...'
    else:
        return string.ljust(width)


def lchop(string, prefix):
    """Removes a prefix from string

    :param string: String, possibly prefixed with prefix
    :param prefix: Prefix to remove from string
    :returns: string without the prefix
    """
    if string.startswith(prefix):
        return string[len(prefix):]
    return string


def split_after(iterable, pred):
    """Yield lists of items from *iterable*, where each list ends with an
    item where callable *pred* returns ``True``:

        >>> list(split_after('one1two2', lambda s: s.isdigit()))
        [['o', 'n', 'e', '1'], ['t', 'w', 'o', '2']]

        >>> list(split_after(range(10), lambda n: n % 3 == 0))
        [[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]]

    """
    buf = []
    for item in iterable:
        buf.append(item)
        if pred(item) and buf:
            yield buf
            buf = []
    if buf:
        yield buf


def unpad_body(body):
    """ Pad a Sphinx message body. """
    body = bytes(body)
    l = len(body) - 1
    x_marker = bytes(b'\x7f')[0]
    f_marker = bytes(b'\xff')[0]
    while body[l] == f_marker and l > 0:
        l -= 1
    if body[l] == x_marker:
        ret = body[:l]
    else:
        ret = b''
    return ret


def atomic_number(atom):
    """Get the atomic number for an atom.

    Parameters
    ----------
    atom : rdkit.Chem.rdchem.Atom
        RDKit atom instance.

    Returns
    -------
    list
       List containing one int only.
    """
    return [atom.GetAtomicNum()]


def link_make(replace: bool=False):
    """Makes a link between selected output in input sockets

    :param replace: Replace, Replace socket connections with the new links
    :type replace: bool
    """
    pass


@classmethod
def get_from_string(cls, code_string):
    """
        Get a Computer object with given identifier string in the format
        label@machinename. See the note below for details on the string
        detection algorithm.

        .. note:: the (leftmost) '@' symbol is always used to split code
            and computername. Therefore do not use
            '@' in the code name if you want to use this function
            ('@' in the computer name are instead valid).

        :param code_string: the code string identifying the code to load

        :raise aiida.common.NotExistent: if no code identified by the given string is found
        :raise aiida.common.MultipleObjectsError: if the string cannot identify uniquely
            a code
        :raise aiida.common.InputValidationError: if code_string is not of string type

        """
    from aiida.common.exceptions import NotExistent, MultipleObjectsError, InputValidationError
    try:
        label, sep, machinename = code_string.partition('@')
    except AttributeError as exception:
        raise InputValidationError(
            'the provided code_string is not of valid string type')
    try:
        return cls.get_code_helper(label, machinename)
    except NotExistent:
        raise NotExistent('{} could not be resolved to a valid code label'.
            format(code_string))
    except MultipleObjectsError:
        raise MultipleObjectsError('{} could not be uniquely resolved'.
            format(code_string))


@classmethod
def save(cls, corpus, file_path, **kwargs):
    """Save a *corpus* in Parsed CONLL-U format to CONLL-U file"""
    with open(file_path, mode='wt', encoding='utf-8') as f:
        for line in cls.get_as_text(corpus, **kwargs):
            print(line, end='', file=f)


def print_detailed_event_metrics(detailed_event_results):
    """
    Print totals for each event category

    Example:
        >>> print_detailed_event_metrics(test_r)
        Detailed event results:
             Actual events:
                 deletions:		1	12.50% of actual events
                 merged:		3	37.50% of actual events
                 fragmented:		1	12.50% of actual events
                 frag. and merged:	1	12.50% of actual events
                 correct:		2	25.00% of actual events
            Detected events:
                 insertions:		1	11.11% of detected events
                 merging:		1	11.11% of detected events
                 fragmenting:		4	44.44% of detected events
                 frag. and merging:	1	11.11% of detected events
                 correct:		2	22.22% of detected events

    """
    print('Detailed event results:')
    print('\tActual events:')
    print('\t\tdeletions:\t\t\t' + str(detailed_event_results['D']) + '\t' +
        '{0:.2f}'.format(detailed_event_results['D'] * 100 /
        detailed_event_results['total_gt']) + '% of actual events')
    print('\t\tmerged:\t\t\t\t' + str(detailed_event_results['M']) + '\t' +
        '{0:.2f}'.format(detailed_event_results['M'] * 100 /
        detailed_event_results['total_gt']) + '% of actual events')
    print('\t\tfragmented:\t\t\t' + str(detailed_event_results['F']) + '\t' +
        '{0:.2f}'.format(detailed_event_results['F'] * 100 /
        detailed_event_results['total_gt']) + '% of actual events')
    print('\t\tfrag. and merged:\t' + str(detailed_event_results['FM']) +
        '\t' + '{0:.2f}'.format(detailed_event_results['FM'] * 100 /
        detailed_event_results['total_gt']) + '% of actual events')
    print('\t\tcorrect:\t\t\t' + str(detailed_event_results['C']) + '\t' +
        '{0:.2f}'.format(detailed_event_results['C'] * 100 /
        detailed_event_results['total_gt']) + '% of actual events')
    print('\tDetected events:')
    print('\t\tinsertions:\t\t\t' + str(detailed_event_results["I'"]) +
        '\t' + '{0:.2f}'.format(detailed_event_results["I'"] * 100 /
        detailed_event_results['total_det']) + '% of detected events')
    print('\t\tmerging:\t\t\t' + str(detailed_event_results["M'"]) + '\t' +
        '{0:.2f}'.format(detailed_event_results["M'"] * 100 /
        detailed_event_results['total_det']) + '% of detected events')
    print('\t\tfragmenting:\t\t' + str(detailed_event_results["F'"]) + '\t' +
        '{0:.2f}'.format(detailed_event_results["F'"] * 100 /
        detailed_event_results['total_det']) + '% of detected events')
    print('\t\tfrag. and merging:\t' + str(detailed_event_results["FM'"]) +
        '\t' + '{0:.2f}'.format(detailed_event_results["FM'"] * 100 /
        detailed_event_results['total_det']) + '% of detected events')
    print('\t\tcorrect:\t\t\t' + str(detailed_event_results['C']) + '\t' +
        '{0:.2f}'.format(detailed_event_results['C'] * 100 /
        detailed_event_results['total_det']) + '% of detected events')


def get_project_requests(rd, project_id, request_state):
    """ Get Project's Merge Requests
    :param rd: Redis Object Instance
    :param project_id: Project Identifier (int)
    :param request_state: Optional Type Identifier (string)
    :return: Merge Requests (List)
    """
    return False


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

        :param SharedFileMetadata val:
        :rtype: GetFileMetadataIndividualResult
        """
    return cls('metadata', val)


@classmethod
def _PerformValidation(cls):
    """Determine whether the content model should be validated for this class.

        In the absence of context, this returns C{True} iff both binding and
        document validation are in force.

        @deprecated: use L{_GetValidationConfig} and check specific requirements."""
    vo = cls._validationConfig_
    return vo.forBinding and vo.forDocument


def pr(x):
    """ Display a value and return it; useful for lambdas. """
    print(x)
    return x


def remodnav_reader(data, screensize, pursuits=False):
    """
    Helper function to read and preprocess REMoDNaV data for use in
    interactive python sessions.

    :param data: path to a REMoDNaV output
    :param screensize: list, screendimensions in x and y direction
    :param pursuits: if True, pursuits will be relabeled to fixations
    """
    from multimatch_gaze.tests import utils as ut
    data = ut.read_remodnav(data)
    try:
        assert len(screensize) == 2
    except:
        raise ValueError(
            'Screensize should be the dimensions of thescreen in x and y direction, such as [1000, 800]. I received {}.'
            .format(screensize))
    if pursuits:
        data = ut.pursuits_to_fixations(data)
    data = ut.preprocess_remodnav(data, screensize)
    return data


def splitter(structured):
    """
    Separates structured data into a list of actives or a list of decoys. actives are labeled with a '1' in their status
    fields, while decoys are labeled with a '0' in their status fields.
    :param structured: either roc_structure or score_structure.
    roc_structure: list [(id, best_score, best_query, status, fpf, tpf), ..., ]
    score_structure: list [(id, best_score, best_query, status, net decoy count, net active count), ...,]
    :return: actives: list [(id, best_score, best_query, status = 1, fpf/net decoy count, tpf/net active count), ..., ]
    :return decoys: list [(id, best_score, best_query, status = 0, fpf/net decoy count, tpf/net active count), ..., ]
    """
    actives = []
    decoys = []
    for mol in structured:
        status = mol[3]
        if status == '1':
            actives.append(mol)
        elif status == '0':
            decoys.append(mol)
    return actives, decoys


def default_commit_veto(request, response):
    """
    When used as a commit veto, the logic in this function will cause the
    transaction to be aborted if:

    - An ``X-Tm`` response header with the value ``abort`` (or any value
      other than ``commit``) exists.

    - The response status code starts with ``4`` or ``5``.

    Otherwise the transaction will be allowed to commit.
    """
    xtm = response.headers.get('x-tm')
    if xtm is not None:
        return xtm != 'commit'
    return response.status.startswith(('4', '5'))


def cp_serializer(raw_cp, channel='0'):
    """
    Serializses RS-UV3 Channel Parameters into a Dictionary.

    :param channel: Channel Parameters.
    :type channe: str
    :returns: Dictionary of Channel Parameters.
    :rtype: dict
    """
    params = ('tx_frequency', 'rx_frequency', 'tone_frequency',
        'squelch_mode', 'power')
    channel_params = dict(zip(params, raw_cp.split()))
    channel_params['channel'] = channel
    return channel_params


def sec2hms(seconds):
    """
    Convert seconds into a string with hours, minutes and seconds.

    Parameters:

    * seconds : float
        Time in seconds

    Returns:

    * time : str
        String in the format ``'%dh %dm %2.5fs'``

    Example::

        >>> print sec2hms(62.2)
        0h 1m 2.20000s
        >>> print sec2hms(3862.12345678)
        1h 4m 22.12346s

    """
    h = int(seconds / 3600)
    m = int((seconds - h * 3600) / 60)
    s = seconds - h * 3600 - m * 60
    return '%dh %dm %2.5fs' % (h, m, s)


def getRealtimeStations():
    """ Get a list of realtime stations available from CDIP's thredds catalog"""
    from lxml import etree
    from urllib.request import urlopen
    parser = etree.HTMLParser()
    with urlopen(
        'http://thredds.cdip.ucsd.edu/thredds/catalog/cdip/realtime/catalog.xml'
        ) as f:
        tree = etree.parse(f, parser)
    root = tree.getroot()
    stations = []
    for dataset in root.iterfind('.//dataset/dataset'):
        stations.append(dataset.get('name')[0:3])
    return stations


@classmethod
def wrap_modes(cls, modes, limit, max_modes_per_msg=0):
    """
        IRC specific: Takes a list of modes and wraps it across multiple lines.
        """
    strings = []
    queued_modes = []
    total_length = 0
    last_prefix = '+'
    orig_modes = modes.copy()
    modes = list(modes)
    while modes:
        next_mode = modes.pop(0)
        modechar, arg = next_mode
        prefix = modechar[0]
        if prefix not in '+-':
            prefix = last_prefix
            modechar = prefix + modechar
            next_mode = modechar, arg
        next_length = 1
        if prefix != last_prefix:
            next_length += 1
        last_prefix = prefix
        if arg:
            next_length += 1
            next_length += len(arg)
        assert next_length <= limit, 'wrap_modes: Mode %s is too long for the given length %s' % (
            next_mode, limit)
        if next_length + total_length <= limit and (not max_modes_per_msg or
            len(queued_modes) < max_modes_per_msg):
            total_length += next_length
            cls._log_debug_modes('wrap_modes: Adding mode %s to queued modes',
                str(next_mode))
            queued_modes.append(next_mode)
            cls._log_debug_modes('wrap_modes: queued modes: %s', queued_modes)
        else:
            strings.append(cls.join_modes(queued_modes))
            queued_modes.clear()
            cls._log_debug_modes(
                'wrap_modes: cleared queue (length %s) and now adding %s',
                limit, str(next_mode))
            queued_modes.append(next_mode)
            total_length = next_length
    else:
        strings.append(cls.join_modes(queued_modes))
    cls._log_debug_modes('wrap_modes: returning %s for %s', strings, orig_modes
        )
    return strings


def mutual_info_run_check(when, then, df):
    """
    Check for consistency between parameters and the dataframe, an assertion
    error will incur if the check is not passed.

    :param when: First column on which to run the metric
    :type when: str/int
    :param then: Second column on which to run the metric
    :type then: str/int
    :param df: Dataframe on which to run the metric
    :type df: DataFrame
    """
    assert when in df.columns, "Column '%s' is not a column part of the dataframe" % when
    assert then in df.columns, "Column '%s' is not a column part of the dataframe" % then
    assert when != then, 'When and then must differ'


def store_wallet(file_path, json_string) ->int:
    """ Store wallet information file in JSON format.
    :param file_path: The path where the file will be saved. type(str)
    :param json_string: Contents of key_store_file. type(str)
    :return: Predefined exit code
    """
    pass


def _computer_test_get_jobs(transport, scheduler, authinfo):
    """Internal test to check if it is possible to check the queue state.

    :param transport: an open transport
    :param scheduler: the corresponding scheduler class
    :param authinfo: the AuthInfo object (from which one can get computer and aiidauser)
    :return: tuple of boolean indicating success or failure and an optional string message
    """
    found_jobs = scheduler.get_jobs(as_dict=True)
    return True, '{} jobs found in the queue'.format(len(found_jobs))


@staticmethod
def drag_to_offset(origin_el, xoffset, yoffset):
    """
        Holds down the left mouse button on the source element,
           then moves to the target offset and releases the mouse button.

        :Args:
         - source: The element to mouse down.
         - xoffset: X offset to move to.
         - yoffset: Y offset to move to.
         :type origin_el: WebElement
         :rtype: WebDriver
        """
    return origin_el.drag_to_offset(xoffset, yoffset)


def resize_graph(dot, size_per_element=0.15, min_size=12):
    """Resize the graph according to how much content it contains.

    Modify the graph in place.
    """
    num_rows = len(dot.body)
    content_size = num_rows * size_per_element
    size = max(min_size, content_size)
    size_str = str(size) + ',' + str(size)
    dot.graph_attr.update(size=size_str)


def surround_previous_word(input_str):
    """
    Surround last word in string with parentheses. If last non-whitespace character
    is delimiter, do nothing
    """
    start = None
    end = None
    for i, char in enumerate(reversed(input_str)):
        if start is None:
            if char in '{}()[]<>?|':
                return input_str
            elif char != ' ':
                start = i
        elif char in '{}()[]<>?| ':
            end = i
            break
    if start is None:
        return input_str
    if end is None:
        end = len(input_str)
    new_str = ''
    for i, char in enumerate(reversed(input_str)):
        if char == ' ' and i + 1 == start:
            continue
        if i == start:
            new_str += ') '
        elif i == end:
            new_str += '('
        new_str += char
    if end == len(input_str):
        new_str += '('
    return new_str[::-1]


def primes(imax):
    """
    Returns prime numbers up to imax.

    Parameters
    ----------
    imax: int
        The number of primes to return. This should be less or equal to 10000.

    Returns
    -------
    result: list
        The list of prime numbers.
    """
    p = list(range(10000))
    result = []
    k = 0
    n = 2
    if imax > 10000:
        raise ValueError('imax should be <= 10000')
    while len(result) < imax:
        i = 0
        while i < k and n % p[i] != 0:
            i = i + 1
        if i == k:
            p[k] = n
            k = k + 1
            result.append(n)
            if k > 10000:
                break
        n = n + 1
    return result


def to_2tuple(value):
    """Return value or (value, value) if value is not a tuple."""
    if isinstance(value, tuple):
        return value
    if isinstance(value, list):
        return tuple(value)
    return value, value


def f_factor(p, t):
    """Enhancement factor for calculating mole fraction.

    Parameters
    ----------
    p : float
        Pressure in Pascal.
    t : float
        Temperature in degree Celsius.

    Returns
    -------
    f : float
        Enhancement factor needed in calculation of mole fraction.

    Notes
    -----
    See section A-II of
    http://emtoolbox.nist.gov/Wavelength/Documentation.asp.

    """
    alpha = 1.00062
    beta = 3.14e-08
    gamma = 5.6e-07
    return alpha + beta * p + gamma * t ** 2


def scrolls(legion_name):
    """Returns a list of Legion scrolls defined on cluster.

    :param str|unicode legion_name:

    :rtype: list
    """
    return []


def formula(foyer_fiscal, period):
    """
        Attention : cette formule est susceptible de contenir des erreurs pour les années avant 2013 (cf. commentaires sur assiette_csg_revenus_capital)

        Notes sur le champ de cette variable :
            Cette assiette de plus-values est partielle. De nombreux types de plus-values sont
            manquants, rien que parmi les plus-values déclarées dans la déclaration de revenus
            au titre de l'impôt sur le revenu. Ceci s'explique par la complexité de la législation sur
            la prise en compte des plus-values dans le calcul des prélèvements sociaux (exemple : plus-values
            réalisées sur PEA taxables selon les règles en vigueur l'année de réalisation et non l'année de retrait,
            plus-values taxées après report, et taxables parfois selon la législation en vigueur au moment du report et non
            pas au moment de la taxation, etc.).
            Critère de choix : on part des dénombrements fiscaux de la déclaration 2042 des revenus 2016
            (montants totaux déclarés au niveau national pour chaque case), et on constate que les cases 3VH, 3VG,
            3SG, 3SL, 3VA, 3VB, 3VO, 3VP, 3VZ, 3VW, 3WG, 3WH et 3WM représentent à elles seules 88% des
            montants associés aux plus-values (cases de classe 3). On se limite donc aux
            plus-values associées à ces cases. Parmi ces cases, certaines ne donnent pas lieu à une imposition
            pendant l'année courante du fait d'un report ou sursis d'imposition (3WG, 3WH, 3WM), ou ne sont
            tout simplement pas comptabilisées dans l'assiette CSG (3VH, 3VW). Au total, le nombre de cases
            est fortement réduit, mais en ne perdant potentiellement qu'une faible partie des plus-values présentes
            dans l'assiette CSG (même en excluant ces cases importantes mais non sujettes à imposition, les cases
            restantes représentent 82% des montants de l'ensemble des cases de classe 3 (hors cases supprimées).
            NB : en plus des cases les plus importantes, on inclut aussi 3WE, car les abattements
            renseignés dans les cases 3SG et 3SL peuvent aussi être associés à des montants nets renseignés en 3WE.

        Notes concernant les plus-values immobilières :
            (1) Les plus-values immobilières déclarées en 3VZ sont les plus-values nettes sousmises à
                l'impôt sur le revenu. Or, les prélèvements sociaux sont appliqués aussi sur une valeure
                nette, mais déterminée via des abattements différents de ceux de l'impôt sur le revenu
                (cf. formulaire 2048-IMM de 2018 par exemple pour une explication). On ignore ces
                différences d'abattement, et on suppose que la valeur nette au sens des prélèvements
                sociaux est la même que celle au sens de l'impôt sur le revenu.
            (2) On ne compte pas la case 3VW dans la base soumise aux prélèvements sociaux. Ce montant,
                exonéré de l'impôt sur le revenu, semble être exonéré aussi des prélèvements sociaux,
                même s'il est déclaré dans la déclaration de revenus : cf. art. L136-7 du CSS, qui
                cite l'art. 150 U du CGI.
        """
    f3vg = foyer_fiscal('f3vg', period)
    f3sg = foyer_fiscal('f3sg', period)
    f3sl = foyer_fiscal('f3sl', period)
    f3va_2014 = foyer_fiscal('f3va_2014', period)
    f3we = foyer_fiscal('f3we', period)
    f3vz = foyer_fiscal('f3vz', period)
    return f3vg + f3sg + f3sl + f3va_2014 + f3vz + f3we


def get_lightgbm_estimator(pygbm_estimator):
    """Return an unfitted LightGBM estimator with matching hyperparams.

    This utility function takes care of renaming the PyGBM parameters into
    their LightGBM equivalent parameters.
    """
    from lightgbm import LGBMRegressor
    from lightgbm import LGBMClassifier
    from .gradient_boosting import GradientBoostingClassifier
    pygbm_params = pygbm_estimator.get_params()
    if pygbm_params['loss'] == 'auto':
        raise ValueError(
            'auto loss is not accepted. We need to know if the problem is binary or multiclass classification.'
            )
    if pygbm_params['scoring'] is not None:
        raise NotImplementedError('Early stopping should be deactivated.')
    loss_mapping = {'least_squares': 'regression_l2', 'binary_crossentropy':
        'binary', 'categorical_crossentropy': 'multiclass'}
    lgbm_params = {'objective': loss_mapping[pygbm_params['loss']],
        'learning_rate': pygbm_params['learning_rate'], 'n_estimators':
        pygbm_params['max_iter'], 'num_leaves': pygbm_params[
        'max_leaf_nodes'], 'max_depth': pygbm_params['max_depth'],
        'min_data_in_leaf': pygbm_params['min_samples_leaf'], 'lambda_l2':
        pygbm_params['l2_regularization'], 'max_bin': pygbm_params[
        'max_bins'], 'min_data_in_bin': 1, 'min_sum_hessian_in_leaf': 0.001,
        'min_gain_to_split': 0, 'verbosity': 10 if pygbm_params['verbose'] else
        0, 'boost_from_average': True}
    if pygbm_params['loss'] == 'categorical_crossentropy':
        lgbm_params['min_sum_hessian_in_leaf'] *= 2
        lgbm_params['learning_rate'] *= 2
    if isinstance(pygbm_estimator, GradientBoostingClassifier):
        Est = LGBMClassifier
    else:
        Est = LGBMRegressor
    return Est(**lgbm_params)


def start(human_resource=None, costunit=None, default=None):
    """ Returns the estimated start date and time, optionally only for a given human resource
            or cost unit
        """


def parse_pwr(dictionary):
    """Gets power supply info from an assumed pwr_supply component"""
    name = '_'.join(dictionary['Board Extra'].lower().split(' '))
    props = {}
    for k, v in dictionary['properties'].items():
        new_key = k.split('Board ')[1]
        props[new_key] = v
    return {name: props}


def edit(text=None, editor=None, env=None, require_save=True, extension=
    '.txt', filename=None):
    """Edits the given text in the defined editor.  If an editor is given
    (should be the full path to the executable but the regular operating
    system search path is used for finding the executable) it overrides
    the detected editor.  Optionally, some environment variables can be
    used.  If the editor is closed without changes, `None` is returned.  In
    case a file is edited directly the return value is always `None` and
    `require_save` and `extension` are ignored.

    If the editor cannot be opened a :exc:`UsageError` is raised.

    Note for Windows: to simplify cross-platform usage, the newlines are
    automatically converted from POSIX to Windows and vice versa.  As such,
    the message here will have ``\\n`` as newline markers.

    :param text: the text to edit.
    :param editor: optionally the editor to use.  Defaults to automatic
                   detection.
    :param env: environment variables to forward to the editor.
    :param require_save: if this is true, then not saving in the editor
                         will make the return value become `None`.
    :param extension: the extension to tell the editor about.  This defaults
                      to `.txt` but changing this might change syntax
                      highlighting.
    :param filename: if provided it will edit this file instead of the
                     provided text contents.  It will not use a temporary
                     file as an indirection in that case.
    """
    from ._termui_impl import Editor
    editor = Editor(editor=editor, env=env, require_save=require_save,
        extension=extension)
    if filename is None:
        return editor.edit(text)
    editor.edit_file(filename)


def get_passphrase(words, n_words, sep, gen):
    """Get a random n-word passphrase from the word set."""
    passwords = gen.sample(words, n_words)
    return sep.join(passwords)


def receive_v2_membership_report(group_state: 'GroupState'):
    """
    Received IGMP Membership Report packet regarding group GroupState
    """
    group_state.group_state_logger.debug(
        'Querier MembersPresent: receive_v2_membership_report')
    group_state.set_timer()


def abs_sign(a, b):
    """ The absolute value of A with the sign of B."""
    return abs(a) if b >= 0 else -abs(a)


def selectBy(connection=None, **attrs):
    """
        Performs a ``SELECT`` in the given `connection` (or default
        connection).

        Each of the keyword arguments should be a column, and the
        equality comparisons will be ``ANDed`` together to produce the
        result.
        """


def euler_filter():
    """Fix large jumps and flips in the selected Euler Rotation F-Curves arising from rotation values being clipped when baking physics

    """
    pass


@classmethod
def deregister(cls, component):
    """Remove a component from the registry."""
    try:
        cls._components.remove(component)
    except ValueError:
        pass
    for class_ in component.__mro__:
        for interface in class_.__dict__.get('_implements', ()):
            implementers = cls._registry.get(interface)
            try:
                implementers.remove(component)
            except ValueError:
                pass


def _print_summary_instrumentation(instrumentation):
    """ Print summary information about an instrumentation file """
    print(f"FACILITY: {instrumentation.facility['reference_name']}")
    print(f'REVISION: {instrumentation.revision}')
    print(20 * '=')
    print('INSTRUMENTS:')
    instrumentation.print_elements()
    print(20 * '=')
    if instrumentation.verify_individuals():
        print('All instruments have a generic counterpart')
    print(20 * '=')
    print('Checking dependencies on instrument_components_file')
    file_exists, n_components, n_found, n_cites = (instrumentation.
        check_dependencies(print_names=True))
    if not file_exists:
        print(
            f'Instrument_Components file not found: {instrumentation.components_file}'
            )
    elif n_components == n_found:
        print('Found all {:d} specied functional components ({:d} total cites)'
            .format(n_components, n_cites))
    else:
        print('MISSING {:d} of {:d} specied functional components '.format(
            n_components - n_found, n_components))


def interaction_exist(interaction, interactions, interaction_1_key=
    'uniprot_1', interaction_2_key='uniprot_2'):
    """
    Checks if interaction already exists in first dataframe.
    """
    if len(interactions[(interactions[interaction_1_key] == interaction[
        interaction_1_key]) & (interactions[interaction_2_key] ==
        interaction[interaction_2_key])]):
        return True
    if len(interactions[(interactions[interaction_2_key] == interaction[
        interaction_1_key]) & (interactions[interaction_1_key] ==
        interaction[interaction_2_key])]):
        return True
    return False


def Format():
    """ Return the DCMI Format element (resource format).

        o Result is the resource's MIME type (e.g. 'text/html',
          'image/png', etc.).

        o Permission:  View
        """


def is_endpoint(G, node, strict=True):
    """
    Return True if the node is a "real" endpoint of an edge in the network,     otherwise False. OSM data includes lots of nodes that exist only as points     to help streets bend around curves. An end point is a node that either:     1) is its own neighbor, ie, it self-loops.     2) or, has no incoming edges or no outgoing edges, ie, all its incident         edges point inward or all its incident edges point outward.     3) or, it does not have exactly two neighbors and degree of 2 or 4.     4) or, if strict mode is false, if its edges have different OSM IDs.     Parameters
    ----------
    G : networkx multidigraph
    node : int
        the node to examine
    strict : bool
        if False, allow nodes to be end points even if they fail all other rules         but have edges with different OSM IDs
    Returns
    -------
    bool
    """
    neighbors = set(list(G.predecessors(node)) + list(G.successors(node)))
    n = len(neighbors)
    d = G.degree(node)
    if node in neighbors:
        return True
    elif G.out_degree(node) == 0 or G.in_degree(node) == 0:
        return True
    elif not (n == 2 and (d == 2 or d == 4)):
        return True
    elif not strict:
        osmids = []
        for u in G.predecessors(node):
            for key in G[u][node]:
                osmids.append(G.edges[u, node, key]['osmid'])
        for v in G.successors(node):
            for key in G[node][v]:
                osmids.append(G.edges[node, v, key]['osmid'])
        return len(set(osmids)) > 1
    else:
        return False


def getLinesFromLogFile(stream):
    """
    Returns all lines written to the passed in stream
    """
    stream.flush()
    stream.seek(0)
    lines = stream.readlines()
    return lines


@classmethod
def __repr__(cls):
    """The string representation of the object.

        :return: the string representation
        :rtype: str
        """
    return '<{}.{}>'.format(cls.__module__, cls.__qualname__)


def import_path(name):
    """ import a callable from full module.callable name """
    modname, _, attr = name.rpartition('.')
    if not modname:
        return __import__(attr)
    m = __import__(modname, fromlist=[attr])
    return getattr(m, attr)


@staticmethod
def lattice_const_AB(latA, latB, x, name=''):
    """
        method to calculated the interpolation of lattice parameters and unit
        cell angles of the Alloy. By default linear interpolation between the
        value of material A and B is performed.

        Parameters
        ----------
        latA, latB :    float or vector
            property (lattice parameter/angle) of material A and B.  A property
            can be a scalar or vector.
        x :             float
            fraction of material B in the alloy.
        name :          str, optional
            label of the property which is interpolated. Can be 'a', 'b', 'c',
            'alpha', 'beta', or 'gamma'.
        """
    return (latB - latA) * x + latA


def get_op_by_tx(block, tx_id):
    """Return the operation data by block num and tx id

    :param block (int): Block number
    :param tx_id (str): Transaction ID
    :return (dict): Operation data
    """
    for transaction in block['transactions']:
        if transaction['transaction_id'] == tx_id:
            return transaction['operations'][0][1]
    raise ValueError('Invalid transaction ID')


def _find_routine_config(config, instance, routine_name):
    """Attempts to find the config for a routine based on the bases of the
    class of the instance.
    """
    bases = instance.__class__.__mro__
    for base in bases:
        full_name = '{}.{}'.format(base.__module__, base.__name__)
        if full_name not in config['patch']:
            continue
        config_routines = config['patch'][full_name]['routines']
        if routine_name in config_routines:
            return config_routines[routine_name]
    return {}


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


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

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


def convert_uint32_to_array(value):
    """
    Converts a int to an array of 4 bytes (little endian)

    :param int value: int value to convert to list
    :return list[int]: list with 4 bytes
    """
    byte0 = value & 255
    byte1 = value >> 8 & 255
    byte2 = value >> 16 & 255
    byte3 = value >> 24 & 255
    return [byte0, byte1, byte2, byte3]


@classmethod
def isFilename(class_, name):
    """Does p_name correspond to a filename ?"""
    qm = name.find('?')
    return '.' in name if qm == -1 else name.find('.', 0, qm) != -1


def TKgrid_configColRange(root, cols=[]):
    """configures range of columns. adding weight of 1
    input could be a list, range or integer
    integer will be taken as a range"""
    if type(cols) == type(1):
        cols = range(cols)
    for i in cols:
        root.grid_columnconfigure(i, weight=1)


def cut_value(graph, flow, cut):
    """
    Calculate the value of a cut.

    @type graph: digraph
    @param graph: Graph

    @type flow: dictionary
    @param flow: Dictionary containing a flow for each edge.

    @type cut: dictionary
    @param cut: Dictionary mapping each node to a subset index. The function only considers the flow between
    nodes with 0 and 1.

    @rtype: float
    @return: The value of the flow between the subsets 0 and 1
    """
    S = []
    T = []
    for node in cut.keys():
        if cut[node] == 0:
            S.append(node)
        elif cut[node] == 1:
            T.append(node)
    value = 0
    for node in S:
        for neigh in graph.neighbors(node):
            if neigh in T:
                value = value + flow[node, neigh]
        for inc in graph.incidents(node):
            if inc in T:
                value = value - flow[inc, node]
    return value


@classmethod
def get_catalog(klass, name):
    """
        Returns a Catalog object representing the catalog
        given by name.
        """
    if name not in list(klass.catalog_class_map.keys()):
        raise ValueError("unknown catalog '%s'" % name)
    try:
        catalog = klass.catalog_instance_map[name]
    except KeyError:
        catalogClass = klass.catalog_class_map[name]
        catalog = catalogClass()
        klass.catalog_instance_map[name] = catalog
    return catalog


def stroke_smooth(repeat: int=1, factor: float=0.5, only_selected: bool=
    True, smooth_position: bool=True, smooth_thickness: bool=True,
    smooth_strength: bool=False, smooth_uv: bool=False):
    """Smooth selected strokes

    :param repeat: Repeat
    :type repeat: int
    :param factor: Factor
    :type factor: float
    :param only_selected: Selected Points, Smooth only selected points in the stroke
    :type only_selected: bool
    :param smooth_position: Position
    :type smooth_position: bool
    :param smooth_thickness: Thickness
    :type smooth_thickness: bool
    :param smooth_strength: Strength
    :type smooth_strength: bool
    :param smooth_uv: UV
    :type smooth_uv: bool
    """
    pass


def my_sqrt(x):
    """Computes the square root of x, using the Newton-Raphson method"""
    approx = None
    guess = x / 2
    while approx != guess:
        approx = guess
        guess = (approx + x / approx) / 2
    return approx


def default_filter(src, dst):
    """The default progress/filter callback; returns True for all files"""
    return dst


def check_valid(line0, line1):
    """
    Check if a file is valid Glove format.

    Args:
        line0 (bytes): First line of the file
        line1 (bytes): Second line of the file

    Returns:
        boo: ``True`` if it is valid. ``False`` if it is invalid.

    """
    data = line0.strip().split(b' ')
    if len(data) <= 2:
        return False
    try:
        map(float, data[2:])
    except:
        return False
    return True


def compatibility_from_options(working_dir, options=None, environment=None):
    """Get compose v3 compatibility from --compatibility option
       or from COMPOSE_COMPATIBILITY environment variable."""
    compatibility_option = options.get('--compatibility')
    compatibility_environment = environment.get_boolean('COMPOSE_COMPATIBILITY'
        )
    return compatibility_option or compatibility_environment


def lower_first_transform(word: str, index: int):
    """
    Lower-case the first word in a series of words

    Parameters
    ----------
    word : str
        Word to lower or upper case.
    index : int
        Index of word in original string of words. If `index == 0`, `word`
        will be lower-cased, every other word will be capitalized.

    Returns
    -------
    w : str
        Transformed word.
    """
    return word.lower() if index == 0 else word.capitalize()


def plot_dlc01_powercurve(sim_ids, post_dirs, run_dirs, fig_dir_base):
    """
    Create power curve based on steady DLC01 results
    Use the same format as for HS2 for easy comparison!
    """


@staticmethod
def _find_prev_sample(sample, prev_samples):
    """Finds the previous VM Sample for a given current sample.

        :param sample: The current sample.
        :param prev_samples: The previous samples to search through.
        :return: The previous sample, if it exists.  None otherwise.
        """
    if prev_samples is None:
        return None
    for prev_sample in prev_samples:
        if prev_sample.id == sample.id and prev_sample.name == sample.name:
            return prev_sample
    return None


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

        :param MemberSetProfilePhotoType val:
        :rtype: EventType
        """
    return cls('member_set_profile_photo', val)


def con5code(code):
    """
    hkcode contain 5 digitals
    series converter ,map function
    """
    if code[0] != '8':
        code = '0' + code[0:4]
    else:
        code = code[0:5]
    return code


def lengths_offsets_split(value):
    """ Split the given comma separated values to multiple integer values"""
    values = []
    for item in value.split(','):
        item = int(item)
        values.append(item)
    return values


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

    The ".dev0" means dirty.

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


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

        :param MemberSuggestType val:
        :rtype: EventType
        """
    return cls('member_suggest', val)


def _binary_search(esum, A, a, b):
    """
    >>> A = [(2, 2, 2, 2), (2, 3, 3), (3, 3, 2), (4, 4)]
    >>> _binary_search((4, 4), A, 0, len(A)-1)
    True
    >>> _binary_search((4, 4), A, 0, len(A)-2)
    False
    >>> _binary_search((5, 5), A, 0, len(A)-1)
    False
    """
    while a <= b:
        mid = (a + b) // 2
        if A[mid] == esum:
            return True
        if esum < A[mid]:
            b = mid - 1
        else:
            a = mid + 1
    return False


@classmethod
def space(cls):
    """Creates space Chunk.

    Returns:
      A chunk (:obj:`budou.chunk.Chunk`)
    """
    chunk = cls(u' ', cls._SPACE_POS)
    return chunk


def plugin_settings(settings):
    """
    Injects local settings into django settings
    """
    env_tokens = getattr(settings, 'ENV_TOKENS', {})
    auth_tokens = getattr(settings, 'AUTH_TOKENS', {})
    if env_tokens.get('ANALYTICS_API_URL'):
        settings.ANALYTICS_API_CLIENT['url'] = env_tokens['ANALYTICS_API_URL']
    if auth_tokens.get('ANALYTICS_API_KEY'):
        settings.ANALYTICS_API_CLIENT['token'] = auth_tokens[
            'ANALYTICS_API_KEY']


def has_units(obj):
    """Determine if a Python object has associated units.

    Args:
        obj (object): Object to be tested for units.

    Returns:
        bool: True if the object has units, False otherwise.

    """
    return hasattr(obj, 'units')


def std(array, *args, **kwargs):
    """
    Computes the standard deviation.

    See Also
    --------
    Array.std
    """
    return array.std(*args, **kwargs)


def to_eigen(plink_pref, eigen_pref):
    """Converts a PED/MAP 1/2 PLINK file to EIGENSOFT ind/snp/geno.

    :param plink_pref: PLINK prefix (recode12)
    :param eigen_pref: EIGENSOFT prefix
    """
    f = open(plink_pref + '.ped')
    iw = open(eigen_pref + '.ind', 'w')
    snps = {}
    for l in f:
        toks = l.rstrip().replace(' ', '\t').split('\t')
        ind = toks[0] + '/' + toks[1]
        iw.write(ind + '\tU\tControl\n')
        for li in range(len(toks[6:]) // 2):
            a1 = toks[2 * li + 6]
            a2 = toks[2 * li + 6 + 1]
            if a1 not in ['1', '2'] or a2 not in ['1', '2']:
                snps[li] = snps.get(li, '') + '9'
            else:
                snps[li] = snps.get(li, '') + str(int(a1 == '1') + int(a2 ==
                    '1'))
    iw.close()
    f = open(plink_pref + '.map')
    sw = open(eigen_pref + '.snp', 'w')
    for l in f:
        toks = l.rstrip().split('\t')
        chro = toks[0]
        sw.write('%s\t%s\t0.0\t%s\n' % (toks[1], chro, toks[3]))
    sw.close()
    f.close()
    gw = open(eigen_pref + '.geno', 'w')
    poses = list(snps.keys())
    poses.sort()
    for pos in poses:
        gw.write(snps[pos] + '\n')
    gw.close()
    f.close()


def print_repo(repo):
    """Print basic information of given repository."""
    print(repo.full_name)
    if repo.description:
        print('\tDescription: {}'.format(repo.description))
    if repo.fork:
        print('\tForked     : from {}'.format(repo._parent.full_name))
    print('\tUpdated    : {} / {} day(s) ago'.format(repo.updated_at, repo.
        neglected_days))
    print('\tSize       : {} KB'.format(repo.size))


@classmethod
def get_saved_info_schema(cls, resource_type):
    """Returns the saved info schema for a resource type

        :returns: a dictionary representing the schema
        """
    raise NotImplementedError


def iteritemsOlderThan(secondsOld):
    """
        Return the an iterator over (key, value) tuples for items older than the given secondsOld.
        """


def is_select(status):
    """Returns true if the first word in status is 'select'."""
    if not status:
        return False
    return status.split(None, 1)[0].lower() == 'select'


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

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

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


def get_collection():
    """Get the entire collection.

        GET /entity -> 200 OK, list of members

        If a query parameter named $$ is present on the request, it must be
        a JSON object with keys that correspond to the keyword args of the
        context's `get_collection` method. The object will be JSON-decoded,
        but no further processing will be done on the resulting dict (i.e.,
        types won't be coerced, etc).

        """


def tags_dlcs(master):
    """
    Initiate tags that are defined in the DLC spreadsheets
    """
    master.tags['[t0]'] = 0
    master.tags['[time stop]'] = 0
    master.tags['[Case folder]'] = 'test'
    master.tags['[Case id.]'] = 'test'
    master.tags['[Windspeed]'] = 8
    master.tags['[wdir]'] = 0
    master.tags['[wdir_rot]'] = 0
    master.tags['[seed]'] = None
    master.tags['[tu_model]'] = 0
    master.tags['[TI]'] = 0
    master.tags['[Turb base name]'] = 'none'
    master.tags['[turb_dx]'] = 1.0
    master.tags['[shear_exp]'] = 0.2
    master.tags['[wsp factor]'] = 1.0
    master.tags['[gust]'] = False
    master.tags['[gust_type]'] = ''
    master.tags['[G_A]'] = ''
    master.tags['[G_phi0]'] = ''
    master.tags['[G_t0]'] = ''
    master.tags['[G_T]'] = ''
    master.tags['[Rotor azimuth]'] = 0
    master.tags['[Free shaft rot]'] = ''
    master.tags['[init_wr]'] = 0.5
    master.tags['[Pitch 1 DLC22b]'] = 0
    master.tags['[Rotor locked]'] = False
    master.tags['[Time stuck DLC22b]'] = -1
    master.tags['[Cut-in time]'] = -1
    master.tags['[Cut-out time]'] = -1
    master.tags['[Stop type]'] = -1
    master.tags['[Pitvel 1]'] = 4
    master.tags['[Pitvel 2]'] = 6
    master.tags['[Grid loss time]'] = 1000
    master.tags['[out_format]'] = 'hawc_binary'
    master.tags['[Time pitch runaway]'] = 1000
    master.tags['[Induction]'] = 1
    master.tags['[Dyn stall]'] = 1
    master.tags['[MannAlfaEpsilon]'] = 1.0
    master.tags['[MannL]'] = 29.4
    master.tags['[MannGamma]'] = 3.0
    master.tags['[turb_nr_u]'] = 8192
    master.tags['[turb_nr_v]'] = 32
    master.tags['[turb_nr_w]'] = 32
    master.tags['[turb_dx]'] = 1
    master.tags['[turb_dy]'] = 6.5
    master.tags['[turb_dz]'] = 6.5
    master.tags['[high_freq_comp]'] = 1
    return master


def persist_scopinfos(run, invalidReason, count):
    """Persists the given information about SCoPs"""
    from benchbuild.utils import schema as s
    session = run.session


def replace_space(t):
    """Replace embedded spaces in a token with unicode line char to allow for split/join"""
    return t.replace(' ', '▁')


@classmethod
def _parse_url(cls, url):
    """Map github url to local directory
        """
    github_url = 'https://github.com/'
    if not url.startswith(github_url):
        raise ValueError("url of the permalink: {0} doesn't start with {1}"
            .format(url, github_url))
    url_dir = url[len(github_url):]
    if '/tree/' not in url_dir:
        raise ValueError(
            "'/tree/' missing in the url {0}. Typical github format " +
            'is github.com/<user>/<repo>/tree/<commit>/<directory>')
    url_dir = url_dir.replace('/tree', '')
    user, repo, commit, model = url_dir.split('/', 3)
    model = model.rstrip('/')
    return user, repo, commit, model


def _bool(val):
    """A wrapper around standard bool() which doesn't throw on NumPy arrays"""
    try:
        return bool(val)
    except ValueError:
        return False


def _resource_property_keys(resource):
    """Returns a list of all get_param lookup keys for the given resource.

    :type resource: tuskar.templates.heat.Resource
    :return: list of property names; empty list if none are found
    :rtype: [str]
    """
    keys = []
    for rp in resource.properties:
        if rp.name in ('resource_def', 'resource'):
            for rpv in rp.value['properties'].values():
                if isinstance(rpv, dict) and 'get_param' in rpv:
                    keys.append(rpv['get_param'])
        elif isinstance(rp.value, dict) and 'get_param' in rp.value:
            keys.append(rp.value['get_param'])
    return keys


@classmethod
def get(cls, pk=None, label=None, machinename=None):
    """
        Get a Computer object with given identifier string, that can either be
        the numeric ID (pk), or the label (and computername) (if unique).

        :param pk: the numeric ID (pk) for code
        :param label: the code label identifying the code to load
        :param machinename: the machine name where code is setup

        :raise aiida.common.NotExistent: if no code identified by the given string is found
        :raise aiida.common.MultipleObjectsError: if the string cannot identify uniquely
            a code
        :raise aiida.common.InputValidationError: if neither a pk nor a label was passed in
        """
    from aiida.common.exceptions import NotExistent, MultipleObjectsError, InputValidationError
    from aiida.orm.utils import load_code
    if pk:
        code_int = int(pk)
        try:
            return load_code(pk=code_int)
        except NotExistent:
            raise ValueError('{} is not valid code pk'.format(pk))
        except MultipleObjectsError:
            raise MultipleObjectsError(
                "More than one code in the DB with pk='{}'!".format(pk))
    elif label != None:
        return cls.get_code_helper(label, machinename)
    else:
        raise InputValidationError(
            'Pass either pk or code label (and machinename)')


def handle_click(click, **callbacks):
    """Handle `click` as returned by `delay.wait_for_clicks`

    `callbacks` maps 'buttonN' keys to callables, N being the number of a
    mouse button starting at 1.

    `click` is passed on to the callback.
    """
    if click is None:
        return
    else:
        button = 'button' + str(click.get('button'))
        try:
            callback = callbacks[button]
        except KeyError:
            pass
        else:
            callback(click)


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


def neat_print(d):
    """ Function print dictionary in the console with tab between key and values

    parameters:
    d (dictionary): The object to print
    """
    for key, value in d.items():
        print(key, '\t', value)


def _format_windows_for_key(primary_key, output, return_primary_key=True):
    """Format the windows powershell output that uses 'Format-Line'
       into a dict of dicts.
    """
    primary_key = primary_key.strip()
    lines = {}
    one_item = {}
    key_value = ''
    for line in output:
        line_data = line.split(':')
        if len(line_data) > 1:
            this_key = line_data[0].strip()
            this_data = line_data[1].strip()
            if len(line_data) > 2:
                this_data = ':'.join(line_data[1:]).strip()
            if this_key != primary_key:
                one_item.update({this_key: this_data})
            else:
                key_value = this_data
        elif line == '':
            if one_item:
                lines[key_value] = one_item
                one_item = {}
                key_value = ''
        else:
            this_data = line.strip()
            appended_data = one_item[this_key] + this_data
            one_item.update({this_key: appended_data})
    if return_primary_key:
        return {primary_key: lines}
    else:
        return lines


def _colorize(stack_status, args):
    """
    Color the output, COMPLETE = green, FAILED = red, IN_PROGRESS = yellow.

    :param stack_status: stack status
    :param args: args
    :return: colorized status string
    """
    if not args.color:
        return stack_status
    end = '0m'
    status_to_color = {'COMPLETE': '0;32m', 'FAILED': '0;31m',
        'IN_PROGRESS': '10;33m'}
    for status_label in status_to_color:
        if status_label in stack_status:
            return '\x1b[%s%s\x1b[%s' % (status_to_color[status_label],
                stack_status, end)


@classmethod
def from_config(cls, xknx, name, config):
    """Initialize object from configuration structure."""
    group_address_long = config.get('group_address_long')
    group_address_short = config.get('group_address_short')
    group_address_position = config.get('group_address_position')
    group_address_position_state = config.get('group_address_position_state')
    group_address_angle = config.get('group_address_angle')
    group_address_angle_state = config.get('group_address_angle_state')
    travel_time_down = config.get('travel_time_down', cls.
        DEFAULT_TRAVEL_TIME_DOWN)
    travel_time_up = config.get('travel_time_up', cls.DEFAULT_TRAVEL_TIME_UP)
    invert_position = config.get('invert_position', False)
    invert_angle = config.get('invert_angle', False)
    return cls(xknx, name, group_address_long=group_address_long,
        group_address_short=group_address_short, group_address_position=
        group_address_position, group_address_position_state=
        group_address_position_state, group_address_angle=
        group_address_angle, group_address_angle_state=
        group_address_angle_state, travel_time_down=travel_time_down,
        travel_time_up=travel_time_up, invert_position=invert_position,
        invert_angle=invert_angle)


@staticmethod
def _get_parent_node(path, delimiter='/'):
    """Get path to the first direct parent of current leaf"""
    endpos = len(path)
    if path[-1:] == delimiter:
        endpos -= 1
    return path[:path.rfind(delimiter, 0, endpos) + 1]


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

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

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

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

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

    """
    pass


def size():
    """Return the current size of the cache in byte.
        """


def name_matches_object(name, *objects, **kwargs):
    """Determine if a resource name could have been created by given objects.

    The object(s) must implement RandomNameGeneratorMixin.

    It will often be more efficient to pass a list of classes to
    name_matches_object() than to perform multiple
    name_matches_object() calls, since this function will deduplicate
    identical name generation options.

    :param name: The resource name to check against the object's
                 RESOURCE_NAME_FORMAT.
    :param *objects: Classes or objects to fetch random name
                     generation parameters from.
    :param **kwargs: Additional keyword args. See the docstring for
                     RandomNameGenerator.name_matches_object() for
                     details on what args are recognized.
    :returns: bool
    """
    unique_rng_options = {}
    for obj in objects:
        key = obj._get_resource_name_format(
            ), obj._get_resource_name_allowed_characters()
        if key not in unique_rng_options:
            unique_rng_options[key] = obj
    return any(obj.name_matches_object(name, **kwargs) for obj in
        unique_rng_options.values())


def get_default_fixture_name(func):
    """get the default fixture name for a function"""
    return getattr(func, 'default_fixture_name', None)


def select_config(name, config):
    """Retrieves the element with the regarding name from the config."""
    for item in config:
        if item['name'] == name:
            return item
    return None


def get_nextupsegs(graph_r, upsegs):
    """Get adjacent upsegs for a list of segments
    as a single flat list.

    Parameters
    ----------
    graph_r : dict
        Dictionary of upstream routing connections.
        (keys=segments, values=adjacent upstream segments)
    upsegs : list
        List of segments

    Returns
    -------
    nextupsegs : list
        Flat list of next segments upstream from upsegs
    """
    nextupsegs = set()
    for s in upsegs:
        nextupsegs.update(graph_r[s])
    return nextupsegs


def nv_tuple_list_replace(l, v):
    """ replace a tuple in a tuple list
    """
    _found = False
    for i, x in enumerate(l):
        if x[0] == v[0]:
            l[i] = v
            _found = True
    if not _found:
        l.append(v)


def get_md5_file_hash(filename):
    """Calculates the MD5 hash of a file

    :param str filename: The filename (including the path) of the file
    :return: Md5 hash of the file
    :rtype: str
    """
    import hashlib
    BLOCKSIZE = 65536
    hasher = hashlib.md5()
    with open(filename, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while len(buf) > 0:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)
    return hasher.hexdigest()


@staticmethod
def in_out_quart(progress):
    """.. image:: images/anim_in_out_quart.png
        """
    p = progress * 2
    if p < 1:
        return 0.5 * p * p * p * p
    p -= 2
    return -0.5 * (p * p * p * p - 2.0)


@classmethod
def GetFormatSpecification(cls):
    """Retrieves the format specification.

    Returns:
      FormatSpecification: a format specification or None if not available.
    """
    return


def _handle_save_freq_options(save_freq, total_steps=300):
    """Handle multiple string options for save_freq (see docs for fdg_plus_images)
       total_steps is the number of time steps d3 seems to takes in the sim (always 300?)
       Returns:
       save_freq: JS-friendly format (integer or 'null')
       ignore_first: boolean flag that controls which svgs get processed to images"""
    ignore_first = save_freq == 'last'
    sf_dict = {None: 'null', 'first_last': total_steps - 1, 'last':
        total_steps - 1, 'first': 10000000, 'all': 1, (-1): total_steps - 1}
    save_freq = sf_dict[save_freq] if save_freq in sf_dict else save_freq
    return save_freq, ignore_first


def lookup(data, *args):
    """Return result of sequence of lookups on data."""
    for arg in args:
        if isinstance(arg, int):
            data = data[arg]
        elif isinstance(arg, str):
            data = data[arg]
        elif isinstance(arg, tuple):
            key, value = arg
            for item in data:
                if item[key] == value:
                    data = item
                    break
            else:
                raise LookupError
    return data


def doRead():
    """
        Some data is available for reading on your descriptor.

        @return: If an error is encountered which causes the descriptor to
            no longer be valid, a L{Failure} should be returned.  Otherwise,
            C{None}.
        """


def PmfProbLess(pmf1, pmf2):
    """Probability that a value from pmf1 is less than a value from pmf2.

    Args:
        pmf1: Pmf object
        pmf2: Pmf object

    Returns:
        float probability
    """
    total = 0
    for v1, p1 in pmf1.Items():
        for v2, p2 in pmf2.Items():
            if v1 < v2:
                total += p1 * p2
    return total


def is_channels_first(data_format):
    """
    Is tested data format channels first.

    Parameters:
    ----------
    data_format : str, default 'channels_last'
        The ordering of the dimensions in tensors.

    Returns
    -------
    bool
        A flag.
    """
    return data_format == 'channels_first'


def height(image):
    """Returns the height of the numpy image in pixels."""
    return image.shape[0]


def isiterable(obj, reject_string=True):
    """convenience tool to detect if something is iterable.
    in python3, strings count as iterables to we have the option to exclude them

    Parameters:
    -----------
    obj : object to analyse
    reject_string : bool, whether to ignore strings

    Returns:
    --------
    bool, if the object is itereable.
    """
    iterable = hasattr(obj, '__len__')
    if reject_string:
        iterable = iterable and not isinstance(obj, str)
    return iterable


def heap_item(clock, record, shard):
    """Create a tuple of (ordering, (record, shard)) for use in a RecordBuffer."""
    ordering = record['meta']['created_at']
    second_ordering = int(record['meta']['sequence_number'])
    total_ordering = ordering, second_ordering, clock()
    return total_ordering, record, shard


def serial_listen_addr(migrate_data):
    """Returns listen address serial from a LibvirtLiveMigrateData"""
    listen_addr = None
    if migrate_data.obj_attr_is_set('serial_listen_addr'):
        listen_addr = migrate_data.serial_listen_addr
    return listen_addr


def compute_F1(precision, recall):
    """ Compute F1 score """
    return 2 * recall * precision / (recall + precision)


def cut_multicam(camera: int=1):
    """Cut multi-cam strip and select camera

    :param camera: Camera
    :type camera: int
    """
    pass


def _decorate(fn, key=None, value=None):
    """Add the garcon property to the function.

    Args:
        fn (callable): The function to alter.
        key (string): The key to set (optional.)
        value (any): The value to set (optional.)
    """
    if not hasattr(fn, '__garcon__'):
        setattr(fn, '__garcon__', dict())
    if key:
        fn.__garcon__.update({key: value})


def register_default(cls, key, default_value):
    """Register a default value for a given key."""
    cls._defaults[key] = default_value


def event_auth_to_requests(eventmatch, headers):
    """Convert the eventmatch authentication to requests arguments."""
    requests_kwargs = {}
    if eventmatch.get('auth').get('type', None) == 'basic':
        auth_obj = eventmatch.get('auth').get('basic', {})
        requests_kwargs['auth'] = auth_obj.get('username', ''), auth_obj.get(
            'password', '')
    elif eventmatch.get('auth').get('type', None) == 'header':
        auth_obj = eventmatch.get('auth').get('header', {})
        headers['Authorization'] = '{} {}'.format(auth_obj.get('type', ''),
            auth_obj.get('credentials', ''))
    return requests_kwargs


def clamp(value, minimum, maximum, on_clamped=None):
    """Clamps a value to ensure its >= minimum and <= maximum."""
    if minimum > maximum:
        raise ValueError(
            "Provided minimum '%s' must be less than or equal to the provided maximum '%s'"
             % (minimum, maximum))
    if value > maximum:
        value = maximum
        if on_clamped is not None:
            on_clamped()
    if value < minimum:
        value = minimum
        if on_clamped is not None:
            on_clamped()
    return value


@classmethod
def template_for(cls, attr_code):
    """
        Returns an attribute template for attribute with a given code.
        """
    try:
        return cls.objects.get(code=attr_code).template
    except cls.DoesNotExist:
        return None


def defaultCheckCommand(command, status, output, error):
    """Raise an error if the exit status is nonzero"""
    if status:
        raise RuntimeError('Could not execute "%s":\n%s' % (command, output +
            error))


def getInputValue():
    """
        Return value suitable for the widget's field.

        The widget must return a value that can be legally assigned to
        its bound field or otherwise raise ``WidgetInputError``.

        The return value is not affected by `setRenderedValue()`.
        """


def e_z(z, **cosmo):
    """The unitless Hubble expansion rate at redshift z.

    In David Hogg's (arXiv:astro-ph/9905116v4) formalism, this is
    equivalent to E(z), defined in his eq. 14.

    Modified (JBJ, 29-Feb-2012) to include scalar w parameter

    """
    if 'w' in cosmo:
        return (cosmo['omega_M_0'] * (1 + z) ** 3.0 + cosmo['omega_k_0'] *
            (1 + z) ** 2.0 + cosmo['omega_lambda_0'] * (1 + z) ** (1 +
            cosmo['w'])) ** 0.5
    else:
        return (cosmo['omega_M_0'] * (1 + z) ** 3.0 + cosmo['omega_k_0'] *
            (1 + z) ** 2.0 + cosmo['omega_lambda_0']) ** 0.5


def get_abstract(s):
    """Get author full name from the signature.

    Parameters
    ----------
    :param s: dict
        Signature

    Returns
    -------
    :returns: string
        Normalized author name
    """
    v = s['publication']['abstract']
    v = v if v else ''
    return v


def _clip(sid, prefix):
    """Clips a prefix from the beginning of a string if it exists.

    Warnings
    --------
    This method is intended for internal use only.

    """
    return sid[len(prefix):] if sid.startswith(prefix) else sid


def _parsems(value):
    """Parse a I[.F] seconds value into (seconds, microseconds)."""
    if '.' not in value:
        return int(value), 0
    else:
        i, f = value.split('.')
        return int(i), int(f.ljust(6, '0')[:6])


def get_unique_triangles(triangles):
    """Yield unique triangles.

    >>> list(get_unique_triangles([(0, 1, 2), (1, 1, 0), (2, 1, 0), (1, 0, 0)]))
    [(0, 1, 2), (0, 2, 1)]
    >>> list(get_unique_triangles([(0, 1, 2), (1, 1, 0), (2, 0, 1)]))
    [(0, 1, 2)]
    """
    _added_triangles = set()
    for v0, v1, v2 in triangles:
        if v0 == v1 or v1 == v2 or v2 == v0:
            continue
        if v0 < v1 and v0 < v2:
            verts = v0, v1, v2
        elif v1 < v0 and v1 < v2:
            verts = v1, v2, v0
        elif v2 < v0 and v2 < v1:
            verts = v2, v0, v1
        if verts not in _added_triangles:
            yield verts
            _added_triangles.add(verts)


def GetMerkleRoot(header):
    """

    gets the merkle root of the transactions contained in the block

    """
    pass


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

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

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


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


def UNUSED(param):
    """Mark unused parameters and variables"""
    del param


def energy_value(h, J, sol):
    """
    Obtain energy of an Ising solution for a given Ising problem (h,J).

    :param h: External magnectic term of the Ising problem. List.
    :param J: Interaction term of the Ising problem. Dictionary.
    :param sol: Ising solution. List.
    :return: Energy of the Ising string.
    :rtype: Integer or float.

    """
    ener_ising = 0
    for elm in J.keys():
        if elm[0] == elm[1]:
            raise TypeError(
                'Interaction term must connect two different variables')
        else:
            ener_ising += J[elm] * int(sol[elm[0]]) * int(sol[elm[1]])
    for i in range(len(h)):
        ener_ising += h[i] * int(sol[i])
    return ener_ising


def add_column_parameter(params, name, dataset, args, key):
    """Add a Mimir lens parameter to the given list. This is a shortcut to add
    a column parameter to a list of arguments for a lens.

    params: list
        List of Mimir lens parameters
    name: string
        Name of the parameter
    dataset: vizier.datastore.base.DatasetHandle
        Dataset handle
    args : dict(dict())
        Dictionary of command arguments
    key : string
        Argument name
    """
    column_id = args.get_value(key, raise_error=False)
    if column_id is None:
        return
    column = dataset.column_by_id(column_id)
    params.append(name + '(' + column.name_in_rdb + ')')


def list_facet_attributes(SchemaArn=None, Name=None, NextToken=None,
    MaxResults=None):
    """
    Retrieves attributes attached to the facet.
    See also: AWS API Documentation

    :example: response = client.list_facet_attributes(
        SchemaArn='string',
        Name='string',
        NextToken='string',
        MaxResults=123
    )

    :type SchemaArn: string
    :param SchemaArn: [REQUIRED]
            The ARN of the schema where the facet resides.

    :type Name: string
    :param Name: [REQUIRED]
            The name of the facet whose attributes will be retrieved.

    :type NextToken: string
    :param NextToken: The pagination token.

    :type MaxResults: integer
    :param MaxResults: The maximum number of results to retrieve.

    :rtype: dict
    :return: {
        'Attributes': [
            {
                'Name': 'string',
                'AttributeDefinition': {
                    'Type': 'STRING'|'BINARY'|'BOOLEAN'|'NUMBER'|'DATETIME',
                    'DefaultValue': {
                        'StringValue': 'string',
                        'BinaryValue': b'bytes',
                        'BooleanValue': True|False,
                        'NumberValue': 'string',
                        'DatetimeValue': datetime(2015, 1, 1)
                    },
                    'IsImmutable': True|False,
                    'Rules': {
                        'string': {
                            'Type': 'BINARY_LENGTH'|'NUMBER_COMPARISON'|'STRING_FROM_SET'|'STRING_LENGTH',
                            'Parameters': {
                                'string': 'string'
                            }
                        }
                    }
                },
                'AttributeReference': {
                    'TargetFacetName': 'string',
                    'TargetAttributeName': 'string'
                },
                'RequiredBehavior': 'REQUIRED_ALWAYS'|'NOT_REQUIRED'
            },
        ],
        'NextToken': 'string'
    }

    :returns:
    (string) --
    (string) --

    """
    pass


@staticmethod
def calculate_order(order_function, system, xyz=None, vel=None, box=None):
    """Return the order parameter.

        This method is just to help to calculate the order parameter
        in cases where only the engine can do it.

        Parameters
        ----------
        order_function : object like :py:class:`.OrderParameter`
            The object used for calculating the order parameter(s).
        system : object like :py:class:`.System`
            The system containing the current positions and velocities.
        xyz : numpy.array, optional
            The positions to use. Typically for internal engines, this
            is not needed. It is included here as it can be used for
            testing and also to be compatible with the generic function
            defined by the parent.
        vel : numpy.array, optional
            The velocities to use.
        box : numpy.array, optional
            The current box vectors.

        Returns
        -------
        out : list of floats
            The calculated order parameter(s).

        """
    if any((xyz is None, vel is None, box is None)):
        return order_function.calculate(system)
    system.particles.pos = xyz
    system.particles.vel = vel
    system.box.update_size(box)
    return order_function.calculate(system)


@classmethod
def resume(cls, signals=None):
    """Resumes the specified signals."""
    if signals is None:
        signals = set(cls._signals_suspended)
    for signum in signals:
        cls._signals_suspended.discard(signum)


def paths_prob_to_edges_flux(paths_prob):
    """Chops a list of paths into its edges, and calculate the probability
    of that edge across all paths.

    Parameters
    ----------
    paths: list of tuples
        list of the paths.

    Returns
    -------
    edge_flux: dictionary
        Edge tuples as keys, and probabilities as values.
    """
    edge_flux = {}
    for path, prob in paths_prob.items():
        for i in range(len(path) - 1):
            edge = path[i], path[i + 1]
            if edge in edge_flux:
                edge_flux[edge] += prob
            else:
                edge_flux[edge] = prob
    return edge_flux


def StripIndents(msg, singleLine=False):
    """Strip indentation from multiline strings"""
    msg1 = msg.replace('\n ', '\n')
    while msg != msg1:
        msg = msg1
        msg1 = msg.replace('\n ', '\n')
    msg = msg.replace('\n\t', '\n')
    if singleLine:
        return msg.replace('\n', ' ')
    return msg


def check_ast_errors(expr_eval):
    """Check for errors derived from asteval."""
    if len(expr_eval.error) > 0:
        expr_eval.raise_exception(None)


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

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


def indexof(coll, item, start=0, default=None):
    """Return the index of the item in the collection

    :param coll: iterable
    :param item: scalar
    :param start: (optional) The start index
    :default: The default value of the index if the item is not in the collection

    :returns: idx -- The index of the item in the collection

    >>> monties = ['Eric', 'John', 'Terry', 'Terry', 'Graham', 'Mickael']
    >>> indexof(monties, 'Terry')
    2

    >>> indexof(monties, 'Terry', start=3)
    3

    >>> indexof(monties, 'Terry', start=4) is None
    True

    """
    if item in coll[start:]:
        return list(coll).index(item, start)
    else:
        return default


def adjust_disp(ncoeff, coeff, delta_offset1, shifta1, inang_info,
    delta_tan, delta_row, binaxis1):
    """Adjust the dispersion coefficients.

    The changes to the coefficients are for the incidence angle
    correction, the offset from the SHIFTA1 keyword, and the tilt
    of the slit.  The coefficients will be modified in-place.

    Parameters
    ----------
    ncoeff : int
        number of dispersion coefficients
    coeff : ndarray of float64
        array of dispersion coefficients, modified in-place
    delta_offset1 : float
        incidence angle offset in degrees
    shifta1 : float
        MSM offset (ref. pixels) in the dispersion direction
    delta_tan : float
        difference in tangents of slit angle and ref angle
    delta_row : float
        difference between current row number and CRPIX2
    binaxis1 : float
        binning factor in dispersion direction
    inang_info : rec_array
        rows from the incidence-angle table

    """
    iac_ncoeff1 = inang_info.field('ncoeff1')[0]
    iac_coeff1 = inang_info.field('coeff1')[0]
    iac_ncoeff2 = inang_info.field('ncoeff2')[0]
    iac_coeff2 = inang_info.field('coeff2')[0]
    for i in range(iac_ncoeff1):
        coeff[i] += iac_coeff1[i] * delta_offset1
    if iac_ncoeff2 > 0:
        coeff[0] += iac_coeff2[0] * delta_offset1
    if iac_ncoeff2 > 1:
        coeff[1] += iac_coeff2[1] * delta_offset1 ** 2
    coeff[0] += shifta1
    coeff[0] += delta_tan * delta_row * binaxis1


def holling_type_0(coefficient):
    """ constant respone (implicit linear),
		compartment size independent """
    return coefficient


@staticmethod
def request_relays_status():
    """Generate a relays-status request.

        :return: The PCK command (without address header) as text
        :rtype:    str
        """
    return 'SMR'


def p_expr_AND(p):
    """expr : expr AND expr"""
    p[0] = 'AND', p[1], p[3]


def remove_initial_data(apps, schema_editor):
    """This function does nothing. The below code is commented out together
    with an explanation of why we don't need to bother reversing any of the
    initial data"""
    pass


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 bytes_2_str(bytes_str):
    """
    用于将bytes 类型转换为 str 类型
    :param bytes_str:
    :return:
    """
    return str(bytes_str, encoding='GBK')