def addService(service):
    """
        Add a service to this collection.
        """


def _write_names(names, names_dst):
    """Write the contents of a list to a file."""
    with open(names_dst, 'w+', newline='\n') as f:
        f.write('\n'.join(names))


@classmethod
def from_mask(cls, mask):
    """Returns a User object from a string like 'nick!user@host'.
        """
    nick, h = mask.split('!', 1)
    ident, host = h.split('@', 1)
    return cls(nick, ident, host)


def fib(n):
    """Fibonacci example function

    Args:
      n (int): integer

    Returns:
      int: n-th Fibonacci number
    """
    assert n > 0
    a, b = 1, 1
    for i in range(n - 1):
        a, b = b, a + b
    return a


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 get_apps(verbose=True):
    """
    Returns all apps as a list
    """
    try:
        from balsam.core.models import ApplicationDefinition as App
        apps = App.objects.all()
    except:
        apps = None
    return apps


@classmethod
def release_all(cls):
    """释放当前使用的所有设备的instrument
        """
    for device_udid in cls.instances:
        cls.instances(device_udid).release()


def sp_msg(text: str) ->None:
    """
    Output a message.
    """
    print(text)


def __call__():
    """ Returns the URL for the user
        """


def SizeBenefitMat(t):
    """Maturity benefit per policy"""
    return 0


def object_name(obj):
    """Get the qualified name of an object. This will obtain both the module
    name from `__module__` and object name from `__name__`, and concatenate
    those with a '.'. Examples:

    >>> from math import sin
    >>> object_name(sin)
    'math.sin'

    >>> def f(x):
    ...     return x*x
    ...
    >>> object_name(f)
    '__main__.f'

    To have a qualified name, an object must be defined as a class or function
    in a module (``__main__`` is also a module). A normal instantiated object
    does not have a qualified name, even if it is defined and importable from a
    module.  Calling |object_name| on such an object will raise
    :py:exc:`AttributeError`.

    .. |object_name| replace:: :py:func:`object_name`"""
    return obj.__module__ + '.' + obj.__qualname__


def set_configuration(configuration):
    """
        Set the configuration for a given tile
        """


def select_row():
    """Select a row of control points including active one

    """
    pass


def in6_mactoifaceid(mac, ulbit=None):
    """
    Compute the interface ID in modified EUI-64 format associated
    to the Ethernet address provided as input.
    value taken by U/L bit in the interface identifier is basically
    the reversed value of that in given MAC address it can be forced
    to a specific value by using optional 'ulbit' parameter.
    """
    if len(mac) != 17:
        return None
    m = ''.join(mac.split(':'))
    if len(m) != 12:
        return None
    first = int(m[0:2], 16)
    if ulbit is None or not (ulbit == 0 or ulbit == 1):
        ulbit = [1, '-', 0][first & 2]
    ulbit *= 2
    first = '%.02x' % (first & 253 | ulbit)
    eui64 = first + m[2:4] + ':' + m[4:6] + 'FF:FE' + m[6:8] + ':' + m[8:12]
    return eui64.upper()


def add_extra_nonce_to_tx_extra(extra, extra_nonce):
    """
    Appends nonce extra to the extra buffer
    :param extra:
    :param extra_nonce:
    :return:
    """
    if len(extra_nonce) > 255:
        raise ValueError('Nonce could be 255 bytes max')
    extra += b'\x02' + len(extra_nonce).to_bytes(1, 'big') + extra_nonce
    return extra


@staticmethod
def merge_codegen_params(old_params, args, mapping_tuples):
    """
        Merge any codegen params found in old_params and args.
        Return updated args

        :param old_params: List of Resilient Objects (normally result of calling customize_py.codegen_reload_data())
        :type old_params: List
        :param args: Namespace of all args passed from command line
        :type args: argparse.Namespace
        :param mapping_tuples: List of Tuples e.g. [("arg_name", "old_param_name")]
        :type mapping_tuples: List
        :return: The 'merged' args
        :rtype: argparse.Namespace
        """
    for m in mapping_tuples:
        all_obj_names_wanted = set()
        arg_name = m[0]
        old_param_name = m[1]
        arg = getattr(args, arg_name)
        if arg:
            all_obj_names_wanted = set(arg)
        setattr(args, arg_name, list(all_obj_names_wanted.union(set(
            old_params.get(old_param_name, [])))))
    return args


def removeEscapes(value, quoted=0):
    """Remove escapes from in front of quotes (which IRAF seems to
    just stick in for fun sometimes.)  Remove \\-newline too.
    If quoted is true, removes all blanks following \\-newline
    (which is a nasty thing IRAF does for continuations inside
    quoted strings.)
    XXX Should we remove \\ too?
    """
    i = value.find('\\"')
    while i >= 0:
        value = value[:i] + value[i + 1:]
        i = value.find('\\"', i + 1)
    i = value.find("\\'")
    while i >= 0:
        value = value[:i] + value[i + 1:]
        i = value.find("\\'", i + 1)
    i = value.find('\\\n')
    while i >= 0:
        j = i + 2
        if quoted:
            for c in value[i + 2:]:
                if c not in ' \t':
                    break
                j = j + 1
        value = value[:i] + value[j:]
        i = value.find('\\\n', i + 1)
    return value


def native_pathsep(path):
    """Replace the path separator with the systems native os.sep.

    """
    pass


def __get_item_indices_per_cluster(k, labels):
    """Get a 2-D array where the array at position i holds the indices of all items in cluster i"""
    indices_per_cluster = [[] for x in range(k)]
    for i in range(len(labels)):
        indices_per_cluster[labels[i]].append(i)
    return indices_per_cluster


def batch_iter(data, batch_size, batch_size_fn=None, batch_size_multiple=1):
    """Yield elements from data in chunks of batch_size, where each chunk size
    is a multiple of batch_size_multiple.

    This is an extended version of torchtext.data.batch.
    """
    if batch_size_fn is None:

        def batch_size_fn(new, count, sofar):
            return count
    minibatch, size_so_far = [], 0
    for ex in data:
        minibatch.append(ex)
        size_so_far = batch_size_fn(ex, len(minibatch), size_so_far)
        if size_so_far >= batch_size:
            overflowed = 0
            if size_so_far > batch_size:
                overflowed += 1
            if batch_size_multiple > 1:
                overflowed += (len(minibatch) - overflowed
                    ) % batch_size_multiple
            if overflowed == 0:
                yield minibatch
                minibatch, size_so_far = [], 0
            else:
                yield minibatch[:-overflowed]
                minibatch = minibatch[-overflowed:]
                size_so_far = 0
                for i, ex in enumerate(minibatch):
                    size_so_far = batch_size_fn(ex, i + 1, size_so_far)
    if minibatch:
        yield minibatch


def sum_stats(stats_data):
    """
    Summarize the bounces, complaints, delivery attempts and rejects from a
    list of datapoints.
    """
    t_bounces = 0
    t_complaints = 0
    t_delivery_attempts = 0
    t_rejects = 0
    for dp in stats_data:
        t_bounces += int(dp['Bounces'])
        t_complaints += int(dp['Complaints'])
        t_delivery_attempts += int(dp['DeliveryAttempts'])
        t_rejects += int(dp['Rejects'])
    return {'Bounces': t_bounces, 'Complaints': t_complaints,
        'DeliveryAttempts': t_delivery_attempts, 'Rejects': t_rejects}


def read_history():
    """Reloads history and bookmarks

    """
    pass


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

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


def _print_summary_network(network, network_file):
    """ Print summary information about a network """
    print(network)
    for name, station in network.stations.items():
        print('  ' + str(station))
    print('')


def select_loose(extend: bool=False):
    """Select loose geometry based on the selection mode

    :param extend: Extend, Extend the selection
    :type extend: bool
    """
    pass


def node_copy_color():
    """Copy color to all selected nodes

    """
    pass


def null_logger(_stmt, _args):
    """
    A logger that discards everything sent to it.
    """
    pass


def equals_lf(line):
    """Return True if line (a text or bytestring) equals '
'."""
    return line == ('\n' if isinstance(line, str) else b'\n')


@staticmethod
def validate_string(cls, value):
    """Override this method to do your own input validation on the input
        string. This is called before converting the incoming string to the
        native python value."""
    return cls.Attributes.nillable or value is not None


def getRelativeContentURL(content):
    """ Return the site-relative URL for 'content', as a string.

        o The site is the parent of the tool.

        o This is helpful for virtual hosting situations.

        o Same method as 'getRelativeURL()'

        o Permission:  Public
        """


def print_paths(changes, to_string=None, prepend_header=None):
    """ Print the path changelog

    Formats the changelog into a print-friendly list of
    strings.

    Parameters:
        changes (dict):
            A dictionary of changes between two releases
        to_string (bool):
            If True, returns a single string

    Returns:
        A string list of print-formatted changes
    """
    diffs = []
    if prepend_header and 'releases' in changes:
        new_name = changes['releases']['new']
        old_name = changes['releases']['old']
        diffs = ['Changes: {0} from {1}'.format(new_name.upper(), old_name.
            upper())]
        diffs.append(' ')
    if changes['paths']['new']:
        diffs.append('New Paths:')
        diffs.append('----------')
        for name, template in changes['paths']['new'].items():
            diffs.append('{0}: {1}'.format(name, template))
    if changes['paths']['updated']:
        diffs.append(' ')
        diffs.append('Updated Paths:')
        diffs.append('--------------')
        for name, vals in changes['paths']['updated'].items():
            diffs.append('{0}: '.format(name))
            diffs.append('   from: {0}'.format(vals['from']))
            diffs.append('   to: {0}'.format(vals['to']))
    if to_string:
        diffs = '\n'.join(diffs)
    return diffs


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

    :param conditions: Conditions on which to filter before running the metric.
    :type conditions: list
    :param df: Dataframe on which to run the metric
    :type df: DataFrame
    """
    for cond in conditions:
        assert cond['column'
            ] in df.columns, 'Column %s in conditions %s is not part of the df' % (
            cond['column'], cond)


@classmethod
def slice(cls, *args, **kwargs):
    """Take a slice of a DataSetFamily to produce a dataset
        indexed by asset and date.

        Parameters
        ----------
        *args
        **kwargs
            The coordinates to fix along each extra dimension.

        Returns
        -------
        dataset : DataSet
            A regular pipeline dataset indexed by asset and date.

        Notes
        -----
        The extra dimensions coords used to produce the result are available
        under the ``extra_coords`` attribute.
        """
    coords, hash_key = cls._canonical_key(args, kwargs)
    try:
        return cls._slice_cache[hash_key]
    except KeyError:
        pass
    Slice = cls._make_dataset(coords)
    cls._slice_cache[hash_key] = Slice
    return Slice


def pgettext(msgid: str, msgctxt: str):
    """Try to translate the given msgid (with optional msgctxt).

    :param msgid: The string to translate.
    :type msgid: str
    :param msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).
    :type msgctxt: str
    :return:  The translated string (or msgid if no translation was found).
    """
    pass


def _update_chain_stats(sample_index, chain_stats, trans_key, trans_stats):
    """Update chain statistics arrays for current chain iteration."""
    if trans_stats is not None:
        if sample_index == 0 and trans_key not in chain_stats:
            raise KeyError(
                f'Transition {trans_key} returned statistics but has no statistic_types attribute.'
                )
        for key, val in trans_stats.items():
            if sample_index == 0 and key not in chain_stats[trans_key]:
                raise KeyError(
                    f'Transition {trans_key} returned {key} statistic but it is not included in its statistic_types attribute.'
                    )
            chain_stats[trans_key][key][sample_index] = val


def pack_table(pbest, abest, iers, rec, param_columns, amp_column,
    ier_column=None):
    """
    Pack fitting parameters into table

    Parameters
    ----------
    pbest : list
        List of best-fit parameters.  See :py:func:`fit_NDregion` for format.
    abest : list
        List of best-fit amplitudes.
    iers : list
        List of fitting error return values.
    rec : recarray
        Records array (table) to save fitting parameters into. Updated with
        fitting parameter in place.
    param_columns : list
        List of parameter columns in rec. Format is the same as pbest.
    amp_columns : str
        Name of amplitude column in rec.
    ier_column : str or None, optional
        Name of column in rec to save iers to. None will not record this in the
        table.

    """
    rec[amp_column] = abest
    for dbest, dcolumns in zip(zip(*pbest), param_columns):
        for p, c in zip(zip(*dbest), dcolumns):
            rec[c] = p
    if ier_column is not None:
        rec[ier_column] = iers


def objects(daterange=None, human_resource=None, costunit=None):
    """ Returns a list of all contained time entries, optionally only for a given human resource
            or cost unit
        """


@classmethod
def split(cls, s):
    """
        Split the TZ from string.
        @param s: A string containing a timezone
        @type s: str
        @return: The split parts.
        @rtype: tuple
        """
    m = cls.pattern.search(s)
    if m is None:
        return s,
    x = m.start(0)
    return s[:x], s[x:]


def calculate_co2_emissions(fuel_consumptions, fuel_carbon_content):
    """
    Calculates instantaneous CO2 emission vector [CO2g/s].

    :param fuel_consumptions:
        The instantaneous fuel consumption vector [g/s].
    :type fuel_consumptions: numpy.array

    :param fuel_carbon_content:
        Fuel carbon content [CO2g/g].
    :type fuel_carbon_content: float

    :return:
        CO2 instantaneous emissions vector [CO2g/s].
    :rtype: numpy.array
    """
    return fuel_consumptions * fuel_carbon_content


def dnaa_max(dnaa_boxes, ORI_rrnas, sequence_length, name):
    """
    Finds the 1000 bp interval containing the greatest amount of bp in dnaA boxes

    :param dnaa_boxes:      dnaA boxes
    :param ORI_rrnas:       Predicted interval for ORI from rRNAs
    :param sequence_length: The length of the entire sequence
    :param name:            Species
    :return:                Index with maximum number of dnaA box bases
    """
    start = ORI_rrnas[0]
    end = ORI_rrnas[1]
    """Dictionary for storing the dnaa boxes and their information"""
    dnaa_dict = dict()
    for rec in dnaa_boxes:
        if rec[0] <= rec[1]:
            dnaa_dict[rec[0]] = [rec[0], rec[1], rec[2]]
        else:
            dnaa_dict[rec[1]] = [rec[1], rec[0], rec[2]]
    keylist = sorted(dnaa_dict)
    motifs_sorted = {}
    """Dictionary for storing sorted dnaA boxes"""
    for key in keylist:
        motifs_sorted[key] = dnaa_dict[key]
    window_size = 1000
    dnaa_list = [0] * sequence_length
    dnaa_count = [0] * sequence_length
    """If the interval does not span over the end and beginning of the sequence,
    loop over the interval and save the bp that are within dnaA boxes,
    and count the number of bp within a 1000 bp window.
    If the interval does span the end and beginning, loop between the start of the interval
    and end of sequence, and beginning of sequence to the end of the interval. Save and count."""
    if start <= end:
        for dnaa in motifs_sorted:
            if start <= motifs_sorted[dnaa][0
                ] <= end and start <= motifs_sorted[dnaa][1] <= end:
                for y in range(motifs_sorted[dnaa][0], motifs_sorted[dnaa][1]):
                    dnaa_list[y] = dnaa_list[y] + 1
        for i in range(start, end, 500):
            if i < end - window_size - 1:
                dnaa_count[i] = sum(dnaa_list[i:i + window_size])
            else:
                for x in range(window_size):
                    dnaa_count[i] = sum(dnaa_list[i - x:i - x + window_size])
    elif start > end:
        for dnaa in motifs_sorted:
            if 0 <= motifs_sorted[dnaa][0] <= end and 0 <= motifs_sorted[dnaa][
                1] <= end or start <= motifs_sorted[dnaa][0
                ] <= sequence_length and start <= motifs_sorted[dnaa][1
                ] <= sequence_length:
                for y in range(motifs_sorted[dnaa][0], motifs_sorted[dnaa][1]):
                    dnaa_list[y] = dnaa_list[y] + 1
            elif start <= motifs_sorted[dnaa][0
                ] <= sequence_length and 0 <= motifs_sorted[dnaa][1] <= end:
                for y in range(motifs_sorted[dnaa][0], sequence_length):
                    dnaa_list[y] = dnaa_list[y] + 1
                for y in range(0, motifs_sorted[dnaa][1]):
                    dnaa_list[y] = dnaa_list[y] + 1
        for i in range(start, sequence_length, 500):
            if i < end - window_size - 1:
                dnaa_count[i] = sum(dnaa_list[i:i + window_size])
            else:
                for x in range(window_size):
                    dnaa_count[i] = sum(dnaa_list[i - x:i - x + window_size])
        for i in range(0, end, 500):
            if i < end - window_size - 1:
                dnaa_count[i] = sum(dnaa_list[i:i + window_size])
            else:
                for x in range(window_size):
                    dnaa_count[i] = sum(dnaa_list[i - x:i - x + window_size])
    """Find the maximum number and the index where this occurs"""
    dif_max = dnaa_count.index(max(dnaa_count))
    return dif_max


def degrees_to_cardinal(d):
    """ Convert degrees to cardinal direction

    Thanks to https://gist.github.com/RobertSudwarts/acf8df23a16afdb5837f
    :param d:
    :return:
    """
    dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW',
        'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
    ix = int((d + 11.25) / 22.5)
    return dirs[ix % 16]


def degrees(data=None, name=None, attr=None, out=None, **kwargs):
    """Converts each element of the input array from radians to degrees.

    .. math::
       degrees([0, \\pi/2, \\pi, 3\\pi/2, 2\\pi]) = [0, 90, 180, 270, 360]

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

       - degrees(default) = default
       - degrees(row_sparse) = row_sparse
       - degrees(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L274

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

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

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


def init_dic_with(dic, key, default_value):
    """
    Inits dic[key] with default value, if key isn't in dic yet
    :param dic: A dictionary
    :param key: A key for dic
    :param default_value: Value to set dic[key] to if key isn't in dic
    :return: dic[key]
    """
    try:
        _ = dic[key]
    except KeyError:
        dic[key] = default_value
    return dic[key]


def qual(klass):
    """
    Convert a class to a string representation, which is the name of the module
    plut a dot plus the name of the class.

    :returns: fully qualified module and class name
    """
    return klass.__module__ + '.' + klass.__name__


def tweets_from_BSON_file_IT(tweetfile):
    """
    Returns an iterator over tweets from the given raw Mongo BSON file.
    """
    raise NotImplementedError()


def user_chat(line):
    """
        Parse a message sent by user to the game chat.

        Input:
        `line`      # A string describing message sent by user to the game
                    # chat. Starts with 'Chat' prefix and contains sender's
                    # callsign and a body of the message. Example:
                    # "Chat: user0: \\tmessage"

        Output:
        An object providing information about message and its sender if the
        input line was successfully parsed. Otherwise `None`.
        """


def _adjust_step_size_pid(dt, rel_change, rel_change_step, vsimex_tol, k_P,
    k_I, k_D, dt_bounds, s_bounds):
    """
    Adjust the step size using the PID controller.
    """
    mult = (rel_change[1] / rel_change_step) ** k_P * (vsimex_tol /
        rel_change_step) ** k_I * (rel_change[0] ** 2 / rel_change[1] /
        rel_change_step) ** k_D
    if mult > s_bounds[1]:
        mult = s_bounds[1]
    elif mult < s_bounds[0]:
        mult = s_bounds[0]
    new_dt = mult * dt[2]
    if new_dt > dt_bounds[1]:
        new_dt = dt_bounds[1]
    elif new_dt < dt_bounds[0]:
        new_dt = dt_bounds[0]
    dt = dt[1], dt[2], new_dt
    rel_change = rel_change[1], rel_change_step
    return dt, rel_change


def not_(child):
    """Select devices that does not match the given selectors.

    >>> not_(and_(tag('sports'), tag('business')))
    {'not': {'and': [{'tag': 'sports'}, {'tag': 'business'}]}}

    """
    return {'not': child}


def new():
    """Add new particle settings

    """
    pass


def are_equal_regardless_of_order(seq1, seq2):
    """
    Do `seq1` and `seq2` contain the same elements, same number of times?

    Disregards order of elements.

    Currently will fail for items that have problems with comparing.
    """
    from combi._python_toolbox import nifty_collections
    return nifty_collections.Bag(seq1) == nifty_collections.Bag(seq2)


def delete():
    """Delete selected time marker(s)

    """
    pass


def comment():
    """Convert selected text to comment

    """
    pass


def line_indices_conservative(cell1, cell2):
    """
    Takes two cells in the grid (each described by a pair of integer
    indices), and returns a list of the cells in the grid that are on the
    line segment between the cells.  This is a conservative version.
    """
    i0, j0 = cell1
    i1, j1 = cell2
    assert type(i0) == int, 'Args to line_indices must be pairs of integers'
    assert type(j0) == int, 'Args to line_indices must be pairs of integers'
    assert type(i1) == int, 'Args to line_indices must be pairs of integers'
    assert type(j1) == int, 'Args to line_indices must be pairs of integers'
    ans = [(i0, j0)]
    di = i1 - i0
    dj = j1 - j0
    t = 0.5
    if abs(di) > abs(dj):
        m = float(dj) / float(di)
        t += j0
        if di < 0:
            di = -1
        else:
            di = 1
        m *= di
        while i0 != i1:
            i0 += di
            t1 = t + m
            if int(t1) == int(t):
                ans.append((i0, int(t1)))
            else:
                ans.append((i0 - di, int(t1)))
                ans.append((i0, int(t)))
                ans.append((i0, int(t1)))
            t = t1
    elif dj != 0:
        m = float(di) / float(dj)
        t += i0
        if dj < 0:
            dj = -1
        else:
            dj = 1
        m *= dj
        while j0 != j1:
            j0 += dj
            t1 = t + m
            if int(t1) == int(t):
                ans.append((int(t1), j0))
            else:
                ans.append((int(t1), j0 - dj))
                ans.append((int(t), j0))
                ans.append((int(t1), j0))
            t = t1
    return ans


def __getitem__(specification):
    """
        Returns a cached instance for given :term:`specification`. Raises
        `KeyError` if there is none.

        :raises:
            KeyError
        """


def values_iterator(dictionary):
    """Add support for python2 or 3 dictionary iterators."""
    try:
        v = dictionary.itervalues()
    except:
        v = dictionary.values()
    return v


def get_client_ip(request):
    """Get the IP address of the client, taking into account the X-Forwarded-For header"""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        return x_forwarded_for.split(',')[0]
    return request.META.get('REMOTE_ADDR')


@classmethod
def merge(cls, trees):
    """
        Merge a collection of AttrTree objects.
        """
    first = trees[0]
    for tree in trees:
        first.update(tree)
    return first


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


def remove(uid):
    """ Remove mapping. """


@staticmethod
def exists(request_handler, name) ->bool:
    """Check whether a hook with the name (case sensitive) exists

        :param request_handler:
        :param name: Hook name
        :return: bool
        """
    data = request_handler.make_request('GET', '/hooks')
    for item in data:
        if item['displayName'] == name:
            return True
    return False


def standard_score(x):
    """
    Compute a standard score, defined as (x - min(x)) / (max(x) - min(x)).

    Parameters
    ----------
    x : :class:`numpy.ndarray`
        Numeric array.

    Returns
    -------
    :class:`numpy.ndarray`
        Transformed array.
    """
    return (x - x.min()) / (x.max() - x.min())


def colocar_imagem(img1, img2, x, y):
    """
    Coloca img1 sobre a img2 na posição x e y.
    :param img1: Imagem
    :param img2: Imagem
    :param x: Int
    :param y: Int
    :return: Imagem
    """
    img2.blit(img1, (x - img1.get_width() // 2, y - img1.get_height() // 2))
    return img2


def set_flag_byte_if_at_end_of_data(character_position, data_len, rgb_values):
    """
    The lsb of the blue value of a pixel is our flag bit this will always be zero until the end of our data.
    """
    if character_position == data_len - 1:
        rgb_values[-1] |= 1


def _sc_encode(gain, peak):
    """Encode ReplayGain gain/peak values as a Sound Check string.
    """
    peak *= 32768.0
    g1 = int(min(round(10 ** (gain / -10) * 1000), 65534))
    g2 = int(min(round(10 ** (gain / -10) * 2500), 65534))
    uk = 0
    values = g1, g1, g2, g2, uk, uk, int(peak), int(peak), uk, uk
    return u' %08X' * 10 % values


def _group_tuples(inputs):
    """Helper that groups a `list` of `tuple`s based on the elements at index 0.

    Given a `list` of `tuple`s, return a `dict` mapping from every unique first
    element in the list to the lists containing the rest of the elements.
    Example:
        [(a,2,3),(b,1,1),(b,1,2),(a,1,1)] -> {a:[(2,3),(1,1)], b:[(1,1),(1,2)]}

    Args:
        input: Python `list` of tuples to group.

    Returns:
        Python `dict` containing groups.
    """
    groups = {}
    for item in inputs:
        current_groups = groups.get(item[0], [])
        current_groups.append(item[1:])
        groups[item[0]] = current_groups
    return groups


@classmethod
def post_request(cls, target, instance_key, dev_mode=False, data={},
    url_override=False):
    """
        public class method - make a get request to the api
        """
    operator = cls(instance_key, dev_mode=dev_mode)
    return operator.post_request_inner(target, data, url_override=url_override)


def determine_scaling_factor(money_endowment: int) ->float:
    """
    Compute the scaling factor based on the money amount.

    :param money_endowment: the endowment of money for the agent
    :return: the scaling factor
    """
    scaling_factor = 10.0 ** (len(str(money_endowment)) - 1)
    return scaling_factor


def elseIf(a_number):
    """ A simple function with an if else structure"""
    x = a_number
    if x > 1:
        print('Your number is positive')
    elif x < 1:
        print('Your number is negative')
    else:
        print('You gave a zero')


def drop_duplicates_agg(df, colsgroupby, cols2aggf, test=False):
    """
    colsgroupby: unique names ~index
    cols2aggf: rest of the cols `unique_dropna_str` for categories
    """
    if test:
        print(df.shape)
        print(df.drop_duplicates(subset=colsgroupby).shape)
    dfdupagg = df.loc[(df.duplicated(subset=colsgroupby, keep=False)), :
        ].groupby(colsgroupby).agg(cols2aggf)
    df_ = df.drop_duplicates(subset=colsgroupby, keep=False)
    if test:
        print(df_.shape)
    dfout = df_.append(dfdupagg, sort=True)
    if test:
        print(dfout.shape)
    return dfout


@classmethod
def worldYZ(cls):
    """Construct the world YZ frame.

        Returns
        -------
        :class:`compas.geometry.Frame`
            The world YZ frame.

        Examples
        --------
        >>> frame = Frame.worldYZ()
        >>> frame.point
        Point(0.000, 0.000, 0.000)
        >>> frame.xaxis
        Vector(0.000, 1.000, 0.000)
        >>> frame.yaxis
        Vector(0.000, 0.000, 1.000)
        """
    return cls([0, 0, 0], [0, 1, 0], [0, 0, 1])


def _prefix_ga(value):
    """Prefix a string with 'ga:' if it is not already

    Sort values may be prefixed with '-' to indicate negative sort.

    >>> _prefix_ga('foo')
    'ga:foo'
    >>> _prefix_ga('ga:foo')
    'ga:foo'
    >>> _prefix_ga('-foo')
    '-ga:foo'
    >>> _prefix_ga('-ga:foo')
    '-ga:foo'
    """
    prefix = ''
    if value[0] == '-':
        value = value[1:]
        prefix = '-'
    if not value.startswith('ga:'):
        prefix += 'ga:'
    return prefix + value


def is_hashable(arg):
    """Return True if hash(arg) will succeed, False otherwise.

    Some types will pass a test against collections.Hashable but fail when they
    are actually hashed with hash().

    Distinguish between these and other types by trying the call to hash() and
    seeing if they raise TypeError.

    Examples
    --------
    >>> a = ([],)
    >>> isinstance(a, collections.Hashable)
    True
    >>> is_hashable(a)
    False
    """
    try:
        hash(arg)
    except TypeError:
        return False
    else:
        return True


def setsvnProxy(host, port):
    """Sets the svn commands needed to use a proxy
    """
    global proxycmds
    proxycmds = []
    host = host.strip()
    port = port.strip()
    if not host:
        return
    proxycmds.append('--config-option')
    proxycmds.append('servers:global:http-proxy-host=' + host)
    if port:
        proxycmds.append('--config-option')
        proxycmds.append('servers:global:http-proxy-port=' + port)


def removeAttribute(selector, name):
    """ Remove attribute from node defined by selector """


def summarize_timesteps(hdf5_file):
    """Summarizes total read/write bytes at each timestamp.

    Summarizes read/write bytes for each time step using the HDF5 interface
    instead of converting to a DataFrame or TimeSeries first.  Returns a dict
    of form::

        {
            "1546761600": {
                "read_bytes": 6135848142.0,
                "write_bytes": 6135848142.0
            },
            "1546761630": {
                "read_bytes": 5261439143.0,
                "write_bytes": 6135848142.0
            },
            "1546761660": {
                "read_bytes": 4321548241.0
                "write_bytes": 6135848142.0,
            },
            ...
        }

    """
    datasets = {'/datatargets/writebytes': 'write_bytes',
        '/datatargets/readbytes': 'read_bytes'}
    results = {}
    for dataset_name in datasets.keys():
        timestamps = hdf5_file.get_timestamps(dataset_name)[...]
        sum_bytes = hdf5_file[dataset_name][:, :].sum(axis=1)
        for index, timestamp in enumerate(timestamps):
            output_key = datasets.get(dataset_name)
            output_val = sum_bytes[index]
            timestamp_str = str(timestamp)
            if timestamp_str not in results:
                results[timestamp_str] = {}
            results[timestamp_str][output_key] = output_val
    return results


@classmethod
def clean_tags(cls, hdxobject, log_deleted=True):
    """Clean tags in an HDX object according to tags cleanup spreadsheet

        Args:
            hdxobject (T <= HDXObject): HDX object such as dataset
            log_deleted (bool): Whether to log informational messages about deleted tags. Defaults to True.

        Returns:
            Tuple[List[str], List[str]]: Tuple containing list of mapped tags and list of deleted tags and tags not added
        """
    tags = hdxobject._get_tags()
    hdxobject['tags'] = list()
    return cls.add_mapped_tags(hdxobject, tags, log_deleted=log_deleted)


def _get_proj_info():
    """Information on system PROJ

    Returns
    -------
    proj_info: dict
        system PROJ information
    """
    import pyproj
    from pyproj.exceptions import DataDirError
    try:
        data_dir = pyproj.datadir.get_data_dir()
    except DataDirError:
        data_dir = None
    blob = [('pyproj', pyproj.__version__), ('PROJ', pyproj.
        __proj_version__), ('data dir', data_dir)]
    return dict(blob)


def f4(x):
    """Piecewise linear, left and right discontinuous at x=1, the root."""
    if x > 1:
        return 1.0 + 0.1 * x
    if x < 1:
        return -1.0 + 0.1 * x
    return 0


def FixValence(El):
    """Returns the element symbol, even when a valence is present"""
    if '+' in El[-1]:
        num = El[-2]
        El = El.split(num)[0] + '+' + num
    if '+0' in El:
        El = El.split('+0')[0]
    if '-' in El[-1]:
        num = El[-2]
        El = El.split(num)[0] + '-' + num
    if '-0' in El:
        El = El.split('-0')[0]
    return El


def timedelta_total_seconds(delta):
    """Helper method to determine the total number of seconds
    from a timedelta.

    Args:
        delta (timedelta): A timedelta to convert to seconds.
    """
    return delta.days * 24 * 60 * 60 + delta.seconds


def transform(x, X, R):
    """Transform a Potential Truth Table
    Entry into a different variable space.
    For example if we have the
    entry [True, True, False] representing
    values of variable [A, B, C] in X
    and we want to transform into
    R which has variables [C, A] we
    will return the entry [False, True].
    Here X represents the argument list
    for the clique set X and R represents
    the argument list for the sepset.
    This implies that R is always a subset
    of X"""
    entry = []
    for r in R:
        pos = X.index(r)
        entry.append(x[pos])
    return tuple(entry)


@classmethod
def _get_raw_integration_smearing_method(cls, calc, **kwargs):
    """Return the smearing method name as string, as specified in the input parameters (if specified).

        If not 'smearing' is not
        specified, but 'occupations' == 'smearing', string with default
        value 'gaussian' is returned, as specified in
        http://www.quantum-espresso.org/wp-content/uploads/Doc/INPUT_PW.html
        """
    parameters = calc.inputs.parameters
    smearing = None
    try:
        smearing = parameters.get_dict()['SYSTEM']['smearing']
    except KeyError:
        pass
    if smearing is None:
        try:
            if parameters.get_dict()['SYSTEM']['occupations'] == 'smearing':
                smearing = 'gaussian'
        except KeyError:
            pass
    return smearing


def psi_Mg_MgOH_Cl_HMW84(T, P):
    """c-c'-a: magnesium magnesium-hydroxide chloride [HMW84]."""
    psi = 0.028
    valid = T == 298.15
    return psi, valid


@classmethod
def validate(cls, value: str):
    """Validate the notes value."""
    if not isinstance(value, str):
        raise ValueError(f'Notes need to be of type str not {type(value)}.')
    return value


def join_on_key(key, a, b):
    """Join two iterables on a shared key.

    This will merge the object in a and the object in b that have
    the same value for key.  It will drop an unpaired objects.  It
    assumes the values for key are unique in each of a and b.
    For keys shared between a and b, the b value will be used.
    """
    a_store = {}
    b_store = {}
    a_iter = a.__iter__()
    b_iter = b.__iter__()
    a_active = True
    b_active = True
    while a_active or b_active:
        if a_active:
            try:
                x = next(a_iter)
                x = dict(x)
                if x[key] in b_store:
                    y = b_store.pop(x[key])
                    x.update(y)
                    yield x
                else:
                    a_store[x[key]] = x
            except StopIteration:
                a_active = False
        if b_active:
            try:
                y = next(b_iter)
                if y[key] in a_store:
                    x = a_store.pop(y[key])
                    x.update(y)
                    yield x
                else:
                    b_store[y[key]] = y
            except StopIteration:
                b_active = False


def listify(o):
    """
    If `o` is already a list return it as is; if `o` is a tuple returns a list
    containing the elements contained in the tuple; otherwise returns a list
    with `o` being its only element
    """
    if isinstance(o, list):
        return o
    if isinstance(o, tuple):
        return list(o)
    return [o]


def normalize_path(working_dir, filename):
    """Normalize the path of a filename relative to a specific directory."""
    path = filename
    if not path.is_absolute():
        path = working_dir / path
    return path.resolve()


def _create_combined_set(words, startindex):
    """
    Combines a single string wrapped in parenthesis from a list of words.
    Example: ['feature1', 'or', '(feature2', 'and', 'feature3)'] -> '(feature2 and feature3)'
    :param words: List of words
    :param startindex: Index of starting parenthesis.
    :return: string
    """
    counter = 0
    for i, word in enumerate(words[startindex:]):
        if ')' in word and counter == 0:
            return ' '.join(words[startindex:startindex + i + 1]), i
        elif ')' in word and counter != 0:
            amount = word.count(')')
            counter -= amount
        if '(' in word:
            counter += word.count('(')
        if counter == 0:
            return ' '.join(words[startindex:startindex + i + 1]), i
    return None, 0


def fib(n):
    """Fibonacci example function

    Args:
      n (int): integer

    Returns:
      int: n-th Fibonacci number
    """
    assert n > 0
    a, b = 1, 1
    for i in range(n - 1):
        a, b = b, a + b
    return a


def execute_commands() ->dict:
    """Lists the available sub-commands of the 'chado execute' command with corresponding descriptions"""
    return {'audit_backup': 'backs up the audit tables to a separate schema'}


def transform_tensor_lon_lat_rad_2_sphericalPolar(tensor):
    """Function transforming the components of a tensor from a zonal-meridional-radial basis to a spherical-polar basis."""
    import numpy as np
    transformationMatrix = np.array([[0.0, 0.0, 1.0], [0.0, -1.0, 0.0], [
        1.0, 0.0, 0.0]])
    transformed_Tensor = np.dot(np.dot(transformationMatrix, np.array(
        tensor)), transformationMatrix)
    return transformed_Tensor


def datetime_to_str(value, fmt='%Y-%m-%d %H:%M:%S'):
    """ 时间类型转换为字符串。datetime to string.

    :type value: datetime.datetime
    :type fmt: str
    :rtype: str
    """
    return value.strftime(fmt)


@classmethod
def get_items(cls, sql, table=None, select_list=['*'], order_str='',
    filter_str=''):
    """
            select_list = [*],
            order_str = ''
        """
    table = table if table else cls.table
    selects = ','.join(select_list)
    cmd = f'select {selects} from {table} {filter_str} {order_str}'
    sql.cursor.execute(cmd)
    return sql.cursor.fetchall()


def scale_kappa_QEPWtoSI(temp, volume, timestep):
    """
    Conversion factor for the thermal conductivity from Quantum Espresso PW/HARTREE-HEATCURRENT units to SI units.
    INPUT:
    temp      =  temperature [ K ]
    volume    =  cell volume [ A^3 ]
    timestep  =  integration time step [ fs ]
    """
    kB = 1.3806504
    NA = 6.02214
    massunit = 1.660538921
    charge = 1.6021765
    J_PWtoMETAL = 1.0 / 6.719329152e-06
    return (charge / temp
        ) ** 2 / kB / volume * timestep * 10000.0 * J_PWtoMETAL ** 2


@staticmethod
def pretty_print(record):
    """
        Print the query result as a table.
        :param record: The result of the query as dict.
        """
    for key, value in record.items():
        print('----------------------------------------')
        print('{:<15} {:<25}'.format(key, value))


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

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


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


@staticmethod
def _build_scan_args(cursor, pattern, count):
    """
        Construct arguments list for SCAN, SSCAN, HSCAN, ZSCAN commands
        """
    args = [cursor]
    if pattern is not None:
        args.extend(('MATCH', pattern))
    if count is not None:
        args.extend(('COUNT', count))
    return args


def stress_radiation(ra_24):
    """
    Computes the stress for plants when there is not sufficient radiation

    .. math ::
        S_{r}=\\frac{S^{\\downarrow}}{\\left(S^{\\downarrow}+60.\\right)}
        \\left(1+\\frac{60}{500}\\right)

    Parameters
    ----------
    ra_24 : float
        daily solar radiation
        :math:`S^{\\downarrow}`
        [Wm-2]

    Returns
    -------
    stress_rad : float
        stress factor for radiation
        :math:`S_{r}`
        [-]

    Examples
    --------
    >>> import ETLook.stress as stress
    >>> stress.stress_radiation()
    0.0
    >>> stress.stress_radiation(500)
    1.0
    >>> stress.stress_radiation(700)
    1.0
    >>> stress.stress_radiation(250)
    0.90322580645161288
    """
    stress = ra_24 / (ra_24 + 60.0) * (1 + 60.0 / 500.0)
    stress = stress.clip(0, 1)
    return stress


@staticmethod
def get_jenkins_plugin_name():
    """Gets the name of the Jenkins plugin associated with this PyJen plugin

        This static method is used by the PyJen plugin API to associate this
        class with a specific Jenkins plugin, as it is encoded in the config.xml

        :rtype: :class:`str`
        """
    return 'subversion'


def literal_compile(s):
    """Compile a sql expression with bind params inlined as literals.

    Parameters
    ----------
    s : Selectable
        The expression to compile.

    Returns
    -------
    cs : str
        An equivalent sql string.
    """
    return str(s.compile(compile_kwargs={'literal_binds': True}))


def debugger():
    """
    Drop to a debugger using pudb if available and pdb if not
    """
    try:
        import pudb as pdb
    except ImportError:
        import pdb
    return pdb


def list_to_str(list_of_str):
    """
    Converts list of string to comma separated string
    Parameters
    ----------
    list_of_str : list of str

    Returns
    -------
    str
    """
    if list_of_str is None:
        return None
    return ','.join(list_of_str)


def _remove_tags(tag_dict: dict, tag_key_list: [str]) ->dict:
    """
    Removes the requested tags from the tag dictionary.

    :param tag_dict: The tag dictionary to remove tags from
    :param tag_key_list: A list of the tag keys to be removed
    :return: Returns the tag dictionary with the requested keys removed
    """
    new_dict = tag_dict
    for tag in tag_key_list:
        del new_dict[tag]
    return new_dict


@classmethod
def from_body(cls, packet_body):
    """Return a packet object from a packet body."""
    params = {}
    for (attrib_name, attrib_type), value in zip(cls.attributes, packet_body):
        params[attrib_name] = value
    return cls(**params)


def untranslateName(s):
    """Undo Python conversion of CL parameter or variable name."""
    s = s.replace('DOT', '.')
    s = s.replace('DOLLAR', '$')
    if s[:2] == 'PY':
        s = s[2:]
    s = s.replace('.PY', '.')
    return s


def AddResultScalar(*args, **kwargs):
    """ Stub Anduin function."""
    print('AddResultScalar', args, kwargs)


def make_client(instance):
    """Returns a network proxy"""
    from .interconnectivityclient.v1 import client as interconnectivity_client
    c = interconnectivity_client.Client(session=instance.session)
    return c


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


@classmethod
def reset(cls):
    """Reset the signal logs and return last signal `(signum, frame, time)`.
        """
    res = None
    with cls._lock:
        if hasattr(cls, '_last_signal'):
            res = cls._last_signal
            del cls._last_signal
        cls._signals_raised = {}
    return res


@classmethod
def from_lines(cls, lines, grid=None, active_area=None, isfr=None, model=
    None, model_length_units='undefined', minimum_reach_length=None,
    cull_flowlines_to_active_area=True, consolidate_conductance=False,
    one_reach_per_cell=False, model_name=None, **kwargs):
    """
        Create an instance of Riv from an SFRmaker.lines object.

        Parameters
        ----------
        lines : SFRmaker.lines instance :
        grid :
        active_area :
        isfr :
        model :
        model_length_units :
        minimum_reach_length :
        cull_flowlines_to_active_area :
        consolidate_conductance :
        one_reach_per_cell :
        model_name :
        kwargs :

        Returns
        -------
        riv : SFRmaker.RivData instance
        """
    raise NotImplementedError('from_lines not implemented yet.')


@classmethod
def HomogeneousMODISBRDF(cls, par1, par2, par3):
    """Parameterisation for a surface BRDF based on the MODIS Operational BRDF model.

        The parameters are:

        - Weight for lambertian kernel
        - Weight for Ross Thick kernel
        - Weight for Li Spare kernel

        """
    return (
        '0 Homogeneous surface\n1 (directional effects)\n10 (MODIS BRDF model)\n%f %f %f\n'
         % (par1, par2, par3))


def pad_packed_tensor(input, lengths, value, l_min=None):
    """Pads a packed batch of variable length tensors with given value.

    Parameters
    ----------
    input : Tensor
        The input tensor with shape :math:`(N, *)`
    lengths : list or tensor
        The array of tensor lengths (of the first dimension) :math:`L`.
        It should satisfy :math:`\\sum_{i=1}^{B}L_i = N`,
        where :math:`B` is the length of :math:`L`.
    value : float
        The value to fill in the tensor.
    l_min : int or None, defaults to None.
        The minimum length each tensor need to be padded to, if set to None,
        then there is no minimum length requirement.

    Returns
    -------
    Tensor
        The obtained tensor with shape :math:`(B, \\max(\\max_i(L_i), l_{min}), *)`
    """
    pass


@classmethod
def undo(cls):
    """Undoes the last performed action.
        """
    return cls.build_send_payload('undo', {}), None


def minmax(min_value, value, max_value):
    """
    Restrict value to [min_value; max_value]

    >>> minmax(-2, -3, 10)
    -2
    >>> minmax(-2, 27, 10)
    10
    >>> minmax(-2, 0, 10)
    0
    """
    return min(max(min_value, value), max_value)


def exclude_columns(table, excluded=()):
    """
    Helper method that helps in filtering out columns based
    on the column name.

    :param table: pandas DataFrame
    :param excluded: (tuple) optional columns to be excluded
    :return: modified pandas DataFrame
    """
    if excluded is not None:
        assert hasattr(excluded, '__iter__')
        try:
            table = table.drop(list(excluded), axis=1)
        except ValueError:
            pass
    return table


def fmodifier_copy():
    """Copy the F-Modifier(s) of the active F-Curve

    """
    pass


@staticmethod
def apply_custom_crop(image, crop_coordinates):
    """
        The format of the image `crop_coordinates` should be [x, y, width, height] and PIL cropping format is
        [left, upper, right, lower].
        """
    crop_x, crop_y, crop_w, crop_h = crop_coordinates
    left = crop_x
    upper = crop_y
    right = crop_x + crop_w
    lower = crop_y + crop_h
    coordinates = [left, upper, right, lower]
    return image.crop(coordinates)


def load_volume_maps(directory, map_names=None, deferred=True):
    """Read a number of Nifti volume maps from a directory.

    Args:
        directory (str): the directory from which we want to read a number of maps
        map_names (list or tuple): the names of the maps we want to use. If given we only use and return these maps.
        deferred (boolean): if True we return an deferred loading dictionary instead of a dictionary with the values
            loaded as arrays.

    Returns:
        dict: A dictionary with the volumes. The keys of the dictionary are the filenames (without the extension) of the
            files in the given directory.
    """
    from mdt.lib.nifti import get_all_nifti_data
    return get_all_nifti_data(directory, map_names=map_names, deferred=deferred
        )


def intensity_localization_2steps_fv(data3dr, voxelsize_mm, seeds=None,
    unique_cls=None):
    """
    Use organ_localizator features plus intensity features

    :param data3dr:
    :param voxelsize_mm:
    :param seeds:
    :param unique_cls:
    :return:
    """
    import scipy
    import numpy as np
    import os.path as op
    try:
        from lisa import organ_localizator
    except:
        import organ_localizator
    fv = []
    f0 = scipy.ndimage.filters.gaussian_filter(data3dr, sigma=0.5).reshape(
        -1, 1)
    f1 = scipy.ndimage.filters.gaussian_filter(data3dr, sigma=3).reshape(-1, 1)
    ol = organ_localizator.OrganLocalizator()
    ol.load(op.expanduser('~/lisa_data/liver.ol.p'))
    fdall = ol.feature_function(data3dr, voxelsize_mm)
    middle_liver = ol.predict_w(data3dr, voxelsize_mm, 0.85)
    mn = np.median(data3dr[middle_liver == 1])
    fdn = np.ones(f0.shape) * mn
    fv = np.concatenate([f0, f1, fdall, fdn], 1)
    if seeds is not None:
        sd = seeds.reshape(-1, 1)
        selection = np.in1d(sd, unique_cls)
        fv = fv[selection]
        sd = sd[selection]
        return fv, sd
    return fv


def _update_monitor_stats(sample_index, chain_stats, monitor_stats,
    monitor_dict):
    """Update dictionary of per-iteration monitored statistics."""
    for trans_key, stats_key in monitor_stats:
        if sample_index == 0 and not (trans_key in chain_stats and
            stats_key in chain_stats[trans_key]):
            raise KeyError(
                f'Statistics key pair {trans_key, stats_key} to be monitoredis not present in chain statistics returned by transitions.'
                )
        val = chain_stats[trans_key][stats_key][sample_index]
        if stats_key not in monitor_dict:
            monitor_dict[stats_key] = val
        else:
            monitor_dict[f'{trans_key}.{stats_key}'] = val


def simple_defaults(defaults_dic):
    """
    Simplifies defaults.

    :param defaults_dic: a dictionary of the form { visualProperty_A:value_A, visualProperty_B:value_B, ..}

    :returns: a list of dictionaries with each item corresponding to a given key in defaults_dic
    """
    defaults = []
    for d in defaults_dic.keys():
        dic = {}
        dic['visualProperty'] = d
        dic['value'] = defaults_dic[d]
        defaults.append(dic)
    return defaults


def abuts(a, b):
    """Return True if a and b "touch" the same interbase coordinate without overlapping (symmetric)"""
    return a.start == b.end or a.end == b.start


def tw2pw(thrusttoweight, speed, etap):
    """Converts thrust to weight to power to weight (propeller-driven aircraft)

    **Parameters**

    thrusttoweight
        thrust to weight ratio (non-dimensional)

    speed
        ground speed (in m/s if output in Watts / Newton is required)

    etap
        propeller efficiency (non-dimensional), float

    **Returns**

        power to weight ratio (in W/N if speed is in m/s)

    **See also** ``powerrequired``

    **Notes**

    1. A note on units. If the input speed is in m/s, the other two inputs being
    non-dimensional, the output product is also in m/s, which is equal to W/N
    (W / N = (J/s) / N = (Nm/s) / N = m/s).

    2. The speed input is a kinematic quantity, not an airspeed, so it is generally
    a ground speed (GS) or a true airspeed (TAS) if we are assuming zero wind.

    3. The inputs to the function are scalars or a mix of scalars and `numpy`
    arrays.

    **Example**::

        from ADRpy import constraintanalysis as ca
        from ADRpy import atmospheres as at
        from ADRpy import unitconversions as co

        designbrief = {'stloadfactor': 2, 'turnalt_m': 3050, 'turnspeed_ktas': 140}

        etap = {'turn': 0.85}

        designperformance = {'CLmaxclean': 1.45, 'CDminclean': 0.02541,
                                'etaprop': etap}

        designdef = {'aspectratio': 10, 'sweep_le_deg': 2,
                        'sweep_mt_deg': 0, 'bpr': -1}

        TOW_kg = 1500

        designatm = at.Atmosphere()
        concept = ca.AircraftConcept(designbrief, designdef,
                                        designperformance, designatm)

        wingloading_pa = 1000

        twreq, _, _ = concept.twrequired_trn(wingloading_pa)

        turnspeed_mpstas = co.kts2mps(designbrief['turnspeed_ktas'])

        pw_trn_wpn = ca.tw2pw(twreq, turnspeed_mpstas, etap['turn'])
        pw_trn_hpkg = co.wn2hpkg(pw_trn_wpn)
        p_trn_hp = pw_trn_hpkg * TOW_kg

        print(p_trn_hp)

    Output::

        318.691213406

    """
    return thrusttoweight * speed / etap


def build_feedbackfeed_absolute_url(domain_scheme, group_id, instance_id=
    'devilry_group_student'):
    """
    Build the absolute url to a feedbackfeed.

    Args:
        domain_scheme: The scheme and host. E.g http://www.example.com/.
        group_id: AssignmentGroup id.
        crinstance_id: Cradmin instance id.

    Returns:
        str: Absolute url to feedbackfeed.
    """
    from django_cradmin.crinstance import reverse_cradmin_url
    domain_url_start = domain_scheme.rstrip('/')
    absolute_url = '{}{}'.format(domain_url_start, reverse_cradmin_url(
        instanceid=instance_id, appname='feedbackfeed', roleid=group_id))
    return absolute_url


def commonprefix(m):
    """Given a list of strings, returns the longest common prefix"""
    if not m:
        return ''
    s1 = min(m)
    s2 = max(m)
    for i, c in enumerate(s1):
        if c != s2[i]:
            return s1[:i]
    return s1


def _gpath(path):
    """
        "https://test.backlog.jp/" -> "https://test.backlog.jp/"
        "https://test.backlog.jp" -> "https://test.backlog.jp/"
    """
    if path == '':
        return './'
    elif path.endswith('/'):
        return path
    else:
        return path + '/'


@classmethod
def set(cls, key):
    """Set the Subscription Key."""
    cls.key = key


def _trunc(f, minpoly, p):
    """
    Compute the reduced representation of a polynomial `f` in
    `\\mathbb Z_p[z] / (\\check m_{\\alpha}(z))[x]`

    Parameters
    ==========

    f : PolyElement
        polynomial in `\\mathbb Z[x, z]`
    minpoly : PolyElement
        polynomial `\\check m_{\\alpha} \\in \\mathbb Z[z]`, not necessarily
        irreducible
    p : Integer
        prime number, modulus of `\\mathbb Z_p`

    Returns
    =======

    ftrunc : PolyElement
        polynomial in `\\mathbb Z[x, z]`, reduced modulo
        `\\check m_{\\alpha}(z)` and `p`

    """
    ring = f.ring
    minpoly = minpoly.set_ring(ring)
    p_ = ring.ground_new(p)
    return f.trunc_ground(p).div([minpoly, p_])[1].trunc_ground(p)


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


def skip_redundant(iterable, skipset=None):
    """Redundant items are repeated items or items in the original skipset."""
    if skipset is None:
        skipset = set()
    for item in iterable:
        if item not in skipset:
            skipset.add(item)
            yield item


@staticmethod
def iter_params():
    """return (ADD key1, XOR key2)"""
    for add_key in range(1, 256):
        for xor_key in range(1, 256):
            yield add_key, xor_key


@staticmethod
def _actual_phy(dphy, bit):
    """Return the actual output phase.
        Due to the resolution of the DDS, the actual output phase
        may be (a bit) different than the queried.
        :param dphy: Phase register value (int).
        :param bit: Number of bits used for the phase resolution (int)
        :returns: Actual output phase offset in degree (float).
        """
    return float(360 * dphy) / (1 << bit)


def update_maintenance_window(WindowId=None, Name=None, Schedule=None,
    Duration=None, Cutoff=None, AllowUnassociatedTargets=None, Enabled=None):
    """
    Updates an existing Maintenance Window. Only specified parameters are modified.
    See also: AWS API Documentation

    :example: response = client.update_maintenance_window(
        WindowId='string',
        Name='string',
        Schedule='string',
        Duration=123,
        Cutoff=123,
        AllowUnassociatedTargets=True|False,
        Enabled=True|False
    )

    :type WindowId: string
    :param WindowId: [REQUIRED]
            The ID of the Maintenance Window to update.

    :type Name: string
    :param Name: The name of the Maintenance Window.

    :type Schedule: string
    :param Schedule: The schedule of the Maintenance Window in the form of a cron or rate expression.

    :type Duration: integer
    :param Duration: The duration of the Maintenance Window in hours.

    :type Cutoff: integer
    :param Cutoff: The number of hours before the end of the Maintenance Window that Systems Manager stops scheduling new tasks for execution.

    :type AllowUnassociatedTargets: boolean
    :param AllowUnassociatedTargets: Whether targets must be registered with the Maintenance Window before tasks can be defined for those targets.

    :type Enabled: boolean
    :param Enabled: Whether the Maintenance Window is enabled.

    :rtype: dict
    :return: {
        'WindowId': 'string',
        'Name': 'string',
        'Schedule': 'string',
        'Duration': 123,
        'Cutoff': 123,
        'AllowUnassociatedTargets': True|False,
        'Enabled': True|False
    }

    """
    pass


def elem_C_fit(params, w):
    """
    Fit Function: -C-
    """
    C = params['C']
    return 1 / (C * (w * 1.0j))


@classmethod
def from_cdtclass(cls, cdt, vname, **kwds):
    """
        Declaration of C member

        Parameters
        ----------
        cdt : class
            This class must have the following two attributes

            _ctype_ : ctype
                It will be used for field of `SimObject._struct_`
                (subclass of `ctypes.Structure`).
                It must be an attribute of the *class* `cdt`,
                ie., accessible via `cdt._ctype_`.
            _cdata_ : data
                It will be passed to `SimObject._struct_`
                (instance of `ctypes.Structure` subclass).
                This is required only for instance of the class, so that
                you can set this in `cdt.__init__`.
        vname : str
            Name of C member

        """
    if not hasattr(cdt, '_ctype_'):
        raise ValueError('%r (cdt of %s) does not have _ctype_ attribute' %
            (cdt, vname))
    parsed = cls()
    parsed.cdt = cdt
    parsed.vname = vname
    parsed.valtype = 'object'
    if 'default' in kwds:
        parsed.has_default = True
        parsed.default = kwds['default']
    else:
        parsed.has_default = False
    return parsed


def prepare_lookup_value(key, value):
    """
    Return a lookup value prepared to be used in queryset filtering.
    """
    if key.endswith('__in'):
        value = value.split(',')
    elif key.endswith('__isnull'):
        value = value.lower() not in ('', 'false', '0')
    return value


def assert_qubo_equal(qubo1, qubo2):
    """ Assert the given QUBOs are identical.

    Args:
        qubo1 (dict[(label, label), float]): QUBO to be compared.

        qubo2 (dict[(label, label), float]): QUBO to be compared.
    """
    msg = 'QUBO should be an dict instance.'
    assert isinstance(qubo1, dict), msg
    assert isinstance(qubo2, dict), msg
    assert len(qubo1) == len(qubo2
        ), "Number of elements in QUBO doesn't match."
    for (label1, label2), value in qubo1.items():
        if (label1, label2) in qubo2:
            if qubo2[label1, label2] != value:
                assert qubo2[label1, label2
                    ] == value, "Value of {key} doesn't match".format(key=(
                    label1, label2))
        elif (label2, label1) in qubo2:
            if qubo2[label2, label1] != value:
                assert qubo2[label2, label1
                    ] == value, "Value of {key} doesn't match".format(key=(
                    label2, label1))
        else:
            raise AssertionError("Key: {key} of qubo1 isn't contained in qubo2"
                .format(key=(label1, label2)))


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

        :param WriteConflictError val:
        :rtype: WriteError
        """
    return cls('conflict', val)


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up an SUPLA switch based on existing config."""
    pass


def _to_micros(dur):
    """Convert duration 'dur' to microseconds."""
    return int(dur.total_seconds() * 1000000.0)


def crosscorrelation(x, y, lag=None, verbose=True):
    """Compute lead-lag correlations between 2 time series.

    <x>,<y>: 1-D time series.
    <lag>: lag option, could take different forms of <lag>:
          if 0 or None, compute ordinary correlation and p-value;
          if positive integer, compute lagged correlation with lag
          upto <lag>;
          if negative integer, compute lead correlation with lead
          upto <-lag>;
          if pass in an list or tuple or array of integers, compute
          lead/lag correlations at different leads/lags.

    Note: when talking about lead/lag, uses <y> as a reference.
    Therefore positive lag means <x> lags <y> by <lag>, computation is
    done by shifting <x> to the left hand side by <lag> with respect to
    <y>.
    Similarly negative lag means <x> leads <y> by <lag>, computation is
    done by shifting <x> to the right hand side by <lag> with respect to
    <y>.

    Return <result>: a (n*2) array, with 1st column the correlation
    coefficients, 2nd column correpsonding p values.

    Currently only works for 1-D arrays.
    """
    import numpy
    from scipy.stats import pearsonr
    if len(x) != len(y):
        raise 'Input variables of different lengths.'
    if numpy.isscalar(lag):
        if abs(lag) >= len(x):
            raise 'Maximum lag equal or larger than array.'
        if lag < 0:
            lag = -numpy.arange(abs(lag) + 1)
        elif lag == 0:
            lag = [0]
        else:
            lag = numpy.arange(lag + 1)
    elif lag is None:
        lag = [0]
    else:
        lag = numpy.asarray(lag)
    result = []
    if verbose:
        print
        '\n#<lagcorr>: Computing lagged-correlations at lags:', lag
    for ii in lag:
        if ii < 0:
            result.append(pearsonr(x[:ii], y[-ii:]))
        elif ii == 0:
            result.append(pearsonr(x, y))
        elif ii > 0:
            result.append(pearsonr(x[ii:], y[:-ii]))
    result = numpy.asarray(result)
    return result


def listenUDT(port, protocol, interface='', maxPacketSize=8192, backlog=50):
    """
        Connects a given DatagramProtocol to the given numeric UDT port.

        @return: object which provides L{IListeningPort}.
        """


def revoke_cache_security_group_ingress(CacheSecurityGroupName=None,
    EC2SecurityGroupName=None, EC2SecurityGroupOwnerId=None):
    """
    Revokes ingress from a cache security group. Use this operation to disallow access from an Amazon EC2 security group that had been previously authorized.
    See also: AWS API Documentation

    :example: response = client.revoke_cache_security_group_ingress(
        CacheSecurityGroupName='string',
        EC2SecurityGroupName='string',
        EC2SecurityGroupOwnerId='string'
    )

    :type CacheSecurityGroupName: string
    :param CacheSecurityGroupName: [REQUIRED]
            The name of the cache security group to revoke ingress from.

    :type EC2SecurityGroupName: string
    :param EC2SecurityGroupName: [REQUIRED]
            The name of the Amazon EC2 security group to revoke access from.

    :type EC2SecurityGroupOwnerId: string
    :param EC2SecurityGroupOwnerId: [REQUIRED]
            The AWS account number of the Amazon EC2 security group owner. Note that this is not the same thing as an AWS access key ID - you must provide a valid AWS account number for this parameter.

    :rtype: dict
    :return: {
        'CacheSecurityGroup': {
            'OwnerId': 'string',
            'CacheSecurityGroupName': 'string',
            'Description': 'string',
            'EC2SecurityGroups': [
                {
                    'Status': 'string',
                    'EC2SecurityGroupName': 'string',
                    'EC2SecurityGroupOwnerId': 'string'
                },
            ]
        }
    }

    :returns:
    AuthorizeCacheSecurityGroupIngress
    CreateCacheSecurityGroup
    RevokeCacheSecurityGroupIngress

    """
    pass


def _bytearray_comparator(a, b):
    """Implements a comparator using the lexicographical ordering of octets as unsigned integers."""
    a_len = len(a)
    b_len = len(b)
    i = 0
    while i < a_len and i < b_len:
        a_byte = a[i]
        b_byte = b[i]
        if a_byte != b_byte:
            if a_byte - b_byte < 0:
                return -1
            else:
                return 1
        i += 1
    len_diff = a_len - b_len
    if len_diff < 0:
        return -1
    elif len_diff > 0:
        return 1
    else:
        return 0


def id_to_python_variable(symbol_id, constant=False):
    """
    This function defines the format for the python variable names used in find_symbols
    and to_python. Variable names are based on a nodes' id to make them unique
    """
    if constant:
        var_format = 'self.const_{:05d}'
    else:
        var_format = 'self.var_{:05d}'
    return var_format.format(symbol_id).replace('-', 'm')


def normalize_img_array(img, dtype='float32'):
    """ rescale to [-1.0, 1.0] """
    img = img.astype(dtype)
    return img / 255.0


def median(array, width=None, axis=None, even=False):
    """Replicate the IDL ``MEDIAN()`` function.

    Parameters
    ----------
    array : array-like
        Compute the median of this array.
    width : :class:`int`, optional
        Size of the neighborhood in which to compute the median (*i.e.*,
        perform median filtering).  If omitted, the median of the whole
        array is returned.
    axis : :class:`int`, optional
        Compute the median over this axis for a multi-dimensional array.  If
        ommitted, the median over the entire array will be returned.  If
        set, this function will behave as though `even` is ``True``.
    even : :class:`bool`, optional
        If set to ``True``, the median of arrays with an even number of elements
        will be the average of the middle two values.

    Returns
    -------
    array-like
        The median of the array.

    Raises
    ------
    :exc:`ValueError`
        If `width` is set, and the input `array` is not 1 or 2 dimensional.

    Notes
    -----
    * For arrays with an even number of elements, the :func:`numpy.median`
      function behaves like ``MEDIAN(array, /EVEN)``, so the absence of
      the `even` keyword has to turn *off* that behavior.
    * For median filtering, this uses :func:`scipy.signal.medfilt` and
      :func:`scipy.signal.medfilt2d` under the hood, but patches up the
      values on the array boundaries to match the return values of the
      IDL ``MEDIAN()`` function.
    """
    import numpy as np
    from scipy.signal import medfilt, medfilt2d
    if width is None:
        if axis is None:
            f = array.flatten()
            if f.size % 2 == 1 or even:
                return np.median(array)
            else:
                i = f.argsort()
                return f[i[f.size // 2]]
        else:
            return np.median(array, axis=axis)
    elif array.ndim == 1:
        medarray = medfilt(array, min(width, array.size))
        istart = int((width - 1) / 2)
        iend = array.size - int((width + 1) / 2)
        i = np.arange(array.size)
        w = (i < istart) | (i > iend)
        medarray[w] = array[w]
        return medarray
    elif array.ndim == 2:
        medarray = medfilt2d(array, min(width, array.size))
        istart = int((width - 1) / 2)
        iend = array.shape[0] - int((width + 1) / 2), array.shape[1] - int(
            (width + 1) / 2)
        i = np.arange(array.shape[0])
        j = np.arange(array.shape[1])
        w = (i < istart) | (i > iend[0]), (j < istart) | (j > iend[1])
        medarray[(w[0]), :] = array[(w[0]), :]
        medarray[:, (w[1])] = array[:, (w[1])]
        return medarray
    else:
        raise ValueError('Invalid number of dimensions for input array!')


def _extract_options(args, parameterized=[]):
    """
    Parse command-line arguments, removing options prefixed by "--" from the
    given list and returning them as a dictionary.
    """
    options = {}
    while len(args) > 1 and args[1].startswith('--'):
        option = args.pop(1)[2:]
        if option in parameterized:
            options[option] = args.pop(1)
        else:
            options[option] = None
    return options


def postgres_migration_prep(apps, schema_editor):
    """
    Set null text fields to empty string to workaround incompatibility with migration 0003 on postgres
    See https://github.com/dj-stripe/dj-stripe/issues/850
    """
    Account = apps.get_model('djstripe', 'Account')
    BankAccount = apps.get_model('djstripe', 'BankAccount')
    Card = apps.get_model('djstripe', 'Card')
    Charge = apps.get_model('djstripe', 'Charge')
    Customer = apps.get_model('djstripe', 'Customer')
    Event = apps.get_model('djstripe', 'Event')
    Invoice = apps.get_model('djstripe', 'Invoice')
    Payout = apps.get_model('djstripe', 'Payout')
    Plan = apps.get_model('djstripe', 'Plan')
    Product = apps.get_model('djstripe', 'Product')
    Refund = apps.get_model('djstripe', 'Refund')
    Source = apps.get_model('djstripe', 'Source')
    Transfer = apps.get_model('djstripe', 'Transfer')
    model_fields = [(Account, ('business_name', 'business_primary_color',
        'business_url', 'payout_statement_descriptor',
        'product_description', 'support_url')), (BankAccount, (
        'account_holder_name',)), (Card, ('address_city', 'address_country',
        'address_line1', 'address_line1_check', 'address_line2',
        'address_state', 'address_zip', 'address_zip_check', 'country',
        'cvc_check', 'dynamic_last4', 'fingerprint', 'name',
        'tokenization_method')), (Charge, ('failure_code',
        'failure_message', 'receipt_email', 'receipt_number',
        'statement_descriptor', 'transfer_group')), (Customer, (
        'business_vat_id', 'currency', 'email')), (Event, (
        'idempotency_key', 'request_id')), (Invoice, ('hosted_invoice_url',
        'invoice_pdf', 'number', 'statement_descriptor')), (Payout, (
        'failure_code', 'failure_message', 'statement_descriptor')), (Plan,
        ('aggregate_usage', 'billing_scheme', 'nickname')), (Product, (
        'caption', 'statement_descriptor', 'unit_label')), (Refund, (
        'failure_reason', 'reason', 'receipt_number')), (Source, (
        'currency', 'statement_descriptor')), (Transfer, ('transfer_group',))]
    for model, fields in model_fields:
        for field in fields:
            filter_param = {'{}__isnull'.format(field): True}
            update_param = {field: ''}
            model.objects.filter(**filter_param).update(**update_param)


def uint2int64(value):
    """
    Convert an unsigned 64 bits integer into a signed 64 bits integer.

    >>> print(uint2int64(1))
    1
    >>> print(uint2int64(2**64 + 1))  # ignore bits larger than 64 bits
    1
    >>> print(uint2int64(18446744073709551615))
    -1
    >>> print(uint2int64(18446744073709551614))
    -2
    """
    value = value & 18446744073709551615
    if value & 9223372036854775808:
        return value - 18446744073709551616
    else:
        return value


def cdd(d, k):
    """ Conditionally delete key (or list of keys) 'k' from dict 'd' """
    if not isinstance(k, list):
        k = [k]
    for i in k:
        if i in d:
            d.pop(i)


@classmethod
def get_member_lists(klass):
    """
        A hook for dynamically customising the members of this list group.

        Returns an iterable of PatientLists
        Defaults to the `.member_lists` property
        """
    for l in klass.member_lists:
        yield l


def mpi_local_comm():
    """Split MPI communicator based on shmem capability to produce a node-local
    communicator.

    Requires MPI implementation version >= 3
    """
    from mpi4py import MPI
    return MPI.COMM_WORLD.Split_type(MPI.COMM_TYPE_SHARED)


def set_persistent_base():
    """Reset the copy of the mesh that is being sculpted on

    """
    pass


def clear_bit_k(int_val, k):
    """Clears the bit at offset k"""
    return int_val & ~(1 << k)


def ic_to_soil_type(df):
    """
    Assign the soil type to the corresponding Ic.

    :param df: (DataFrame) Original DataFrame.
    :return: (DataFrame) Updated DataFrame.
    """
    df = df.assign(soil_type='')
    ic_mask = df['type_index'].values > 3.6
    df.loc[ic_mask, 'soil_type'] = 'Peat'
    ic_mask = df['type_index'].values <= 3.6
    df.loc[ic_mask, 'soil_type'] = 'Clays - silty clay to clay'
    ic_mask = df['type_index'].values <= 2.95
    df.loc[ic_mask, 'soil_type'] = 'Silt mixtures - clayey silt to silty clay'
    ic_mask = df['type_index'].values <= 2.6
    df.loc[ic_mask, 'soil_type'] = 'Sand mixtures - silty sand to sandy silt'
    ic_mask = df['type_index'].values <= 2.05
    df.loc[ic_mask, 'soil_type'] = 'Sands - clean sand to silty sand'
    ic_mask = df['type_index'].values <= 1.31
    df.loc[ic_mask, 'soil_type'] = 'Gravelly sand to dense sand'
    return df


def dids_for_key(key):
    """the document ids for *key* (as a set)."""


@classmethod
def create(cls, key, crt):
    """ Add a new crt in the hosted cert store. """
    options = {'crt': crt, 'key': key}
    return cls.call('cert.hosted.create', options)


def get_config_interfaces_name_by_type(config_interfaces, type_str):
    """
    Extract interface names matching specific type from Interface config
    :param config_interfaces: Interfaces config dict
    :param type_str: Type string to match
    :return: List of Interface names matching type_str
    """
    interface_name_list = []
    for name, config_interface in config_interfaces.items():
        if config_interface.get('type') == type_str:
            interface_name_list.append(name)
    return interface_name_list


def zf(s):
    """
    Number digit with a '0'
    """
    s = str(s)
    if len(s) == 1:
        return '0' + s
    else:
        return s


def _check_params(p, speciesDict, xb):
    """
    Check to see if any of the parameters in p fall outside the range
        given in speciesDict or on the boundaries

    **Parameters**

    :p: (3,) ndarray

        array with form [[N1, b1, z1], ...]

    :speciesDict: dictionary

        dictionary with properties giving the max and min
        values appropriate for each parameter N,b, and z.

    :xb: (N) ndarray

        wavelength array [nm]

    **Returns**
    -------
    :check: int

        0 if all values are fine
        999 if any values fall outside acceptable range
    """
    minz = xb[0] / speciesDict['wavelength'][0] - 1
    maxz = xb[-1] / speciesDict['wavelength'][0] - 1
    check = 0
    if any(p[:, (0)] >= speciesDict['maxN']) or any(p[:, (0)] <=
        speciesDict['minN']) or any(p[:, (1)] >= speciesDict['maxb']) or any(
        p[:, (1)] <= speciesDict['minb']) or any(p[:, (2)] >= maxz) or any(
        p[:, (2)] <= minz):
        check = 999
    return check


def make_grasp_phenotype_file(fn, pheno, out):
    """
    Subset the GRASP database on a specific phenotype.

    Parameters
    ----------
    fn : str
        Path to GRASP database file.

    pheno : str
        Phenotype to extract from database.

    out : sttr
        Path to output file for subset of GRASP database.
    """
    import subprocess
    c = 'awk -F "\\t" \'NR == 1 || $12 == "{}" \' {} > {}'.format(pheno.
        replace("'", '\\x27'), fn, out)
    subprocess.check_call(c, shell=True)


def plot_confusion_matrix(conf_matrix, classes=None, normalize=False, title
    ='Confusion Matrix', cmap=None, print_raw_matrix=False, fig_size=(5, 5),
    show_help=False):
    """Check if Normalization Option is Set to True. If so, normalize the raw confusion matrix before visualizing
    #Other code should be equivalent to your previous function.
    Note: Taken from bs_ds and modified"""
    import itertools
    import numpy as np
    import matplotlib.pyplot as plt
    cm = conf_matrix
    if cmap == None:
        cmap = plt.get_cmap('Blues')
    fmt = '.2f' if normalize else 'd'
    fontDict = {'title': {'fontsize': 16, 'fontweight': 'semibold', 'ha':
        'center'}, 'xlabel': {'fontsize': 14, 'fontweight': 'normal'},
        'ylabel': {'fontsize': 14, 'fontweight': 'normal'}, 'xtick_labels':
        {'fontsize': 10, 'fontweight': 'normal', 'rotation': 45, 'ha':
        'right'}, 'ytick_labels': {'fontsize': 10, 'fontweight': 'normal',
        'rotation': 0, 'ha': 'right'}, 'data_labels': {'ha': 'center',
        'fontweight': 'semibold'}}
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, (np.newaxis)]
    fig, ax = plt.subplots(figsize=fig_size)
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title, **fontDict['title'])
    plt.colorbar()
    if classes is None:
        classes = ['negative', 'positive']
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, **fontDict['xtick_labels'])
    plt.yticks(tick_marks, classes, **fontDict['ytick_labels'])
    thresh = cm.max() / 2.0
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt), color='darkgray', **fontDict[
            'data_labels'])
    plt.tight_layout()
    plt.ylabel('True label', **fontDict['ylabel'])
    plt.xlabel('Predicted label', **fontDict['xlabel'])
    fig = plt.gcf()
    plt.show()
    if print_raw_matrix:
        print_title = 'Raw Confusion Matrix Counts:'
        print('\n', print_title)
        print(conf_matrix)
    if show_help:
        print(
            """For binary classifications:
        [[0,0(true_neg),  0,1(false_pos)]
        [1,0(false_neg), 1,1(true_pos)] ]

        to get vals as vars:
        >>  tn,fp,fn,tp=confusion_matrix(y_test,y_hat_test).ravel()
                """
            )
    return fig


def string_to_int_list(job_range):
    """
    Receives a string in the form of "1,2,3-10,20" etc, and returns a list of integers
    represented by the input.
    """
    result = set()
    for part in job_range.split(','):
        if '-' in part:
            a, b = part.split('-')
            a, b = int(a), int(b)
            for i in range(a, b + 1):
                result.add(i)
        else:
            a = int(part)
            result.add(a)
    return sorted(result)


def shortest_loop(code):
    """Sorts crossing by shortest loop described"""
    return sorted(code, key=lambda x: abs(abs(x[0]) - abs(x[1])))


@staticmethod
def addable_cells(obj):
    """
        List object addable cells
        TESTS ::

            sage: from sage.combinat.skew_tableau import SkewTableau
            sage: from sage_widget_adapters.combinat.skew_tableau_grid_view_adapter import SkewTableauGridViewAdapter
            sage: st = SkewTableau([[None, None, None, 1], [None, None, 2], [None, 1], [4]])
            sage: SkewTableauGridViewAdapter.addable_cells(st)
            [(0, 2), (1, 1), (2, 0), (0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]
        """
    return obj.shape().inner().corners() + obj.shape().outer().outside_corners(
        )


def get_logs_with_no_nodes_number(schema_editor):
    """ Get the number of the log records that don't correspond to a node """
    with schema_editor.connection.cursor() as cursor:
        cursor.execute(
            """
            SELECT COUNT(*) FROM db_dblog
            WHERE
                (db_dblog.objname LIKE 'node.%') AND NOT EXISTS
                (SELECT 1 FROM db_dbnode WHERE db_dbnode.id = db_dblog.objpk LIMIT 1)
            """
            )
        return cursor.fetchall()[0][0]


def dB_to_linear(dB):
    """ conversion from decibel scale to linear scale

    Parameters
    ------------
    dB : float
        quantity in dB units

    Returns
    --------
    linear : float
        quantity in linear units
    """
    return 10 ** (dB / 10.0)


def write_long(encoder, datum, schema=None):
    """int and long values are written using variable-length, zig-zag coding.
    """
    encoder.write_long(datum)


def parse_time(time):
    """
    Parses the given time into days, hours, minutes and seconds.
    Useful for formatting time yourself.

    Parameters
    ----------
    time: :class:`int`
        The time in milliseconds.

    Returns
    -------
    Tuple[:class:`int`, :class:`int`, :class:`int`, :class:`int`]
    """
    days, remainder = divmod(time / 1000, 86400)
    hours, remainder = divmod(remainder, 3600)
    minutes, seconds = divmod(remainder, 60)
    return days, hours, minutes, seconds


def _ta_append(list_of_tensors, value):
    """Append a value to the end of a list of PyTorch tensors."""
    list_of_tensors.append(value)
    return list_of_tensors


def search_greater(values, target):
    """
    Return the first index for which target is greater or equal to the first
    item of the tuple found in values
    """
    first = 0
    last = len(values)
    while first < last:
        middle = (first + last) // 2
        if values[middle][0] < target:
            first = middle + 1
        else:
            last = middle
    return first


def which_pools(r):
    """Return a list of pools indexes (in range(32)) that are to be included during reseed number r.

    According to _Practical Cryprography_, chapter 10.5.2 "Pools":

        "Pool P_i is included if 2**i is a divisor of r.  Thus P_0 is used
        every reseed, P_1 every other reseed, P_2 every fourth reseed, etc."
    """
    assert r >= 1
    retval = []
    mask = 0
    for i in range(32):
        if r & mask == 0:
            retval.append(i)
        else:
            break
        mask = mask << 1 | 1
    return retval


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

        :param TeamFolderRenameDetails val:
        :rtype: EventDetails
        """
    return cls('team_folder_rename_details', val)


def extract_bits(data, shift, length):
    """Extract a portion of a bit string. Similar to substr()."""
    bitmask = (1 << length) - 1 << shift
    return (data & bitmask) >> shift


def forg(x, prec=3):
    """
    Yanked from the code for Statsmodels\\iolib\\summary.py
    and adjusted
    """
    if prec == 3:
        if abs(x) >= 10000.0 or abs(x) < 0.0001:
            return '%9.3g' % x
        else:
            return '%9.3f' % x
    elif prec == 4:
        if abs(x) >= 10000.0 or abs(x) < 0.0001:
            return '%10.4g' % x
        else:
            return '%10.4f' % x
    else:
        raise NotImplementedError


def __call__():
    """Return query string in dict-format.
        """


def reversed_enumerate(iterable):
    """
    As of Python 3.8 you still can't reverse an enumerate object.
    So, until that is possible, this exists.
    """
    return zip(reversed(range(len(iterable))), reversed(iterable))


@classmethod
def fromFile(cls, filePath, unk02=0):
    """
        Load a SWAR from a filesystem file.
        """
    with open(filePath, 'rb') as f:
        return cls(f.read(), unk02=0)


def _delete_original_test_method(target_cls, name):
    """
    Delete an original test method with the given name.

    :param target_cls:
        Target class.
    :type target_cls:
        `class`
    :param name:
        Name of the method to remove.
    :type name:
        `unicode`
    :return:
        True if the original method existed
    :rtype:
        `bool`
    """
    attribute = getattr(target_cls, name, None)
    if attribute and not getattr(attribute, 'genty_generated_test', None):
        try:
            delattr(target_cls, name)
        except AttributeError:
            pass
        return True
    else:
        return False


def _submit_args_to_dict(firmware='', profile=''):
    """Return kwargs for this arguments. Remove empty values"""
    kwargs = {}
    if firmware:
        kwargs['firmware'] = firmware
    if profile:
        kwargs['profile'] = profile
    return kwargs


def randomDelay(volume, saturationDegree):
    """Computes the random delay = queueing time for M/D/1"""
    return saturationDegree ** 2 / (2 * volume * (1 - saturationDegree))


def session_new(_, __, *args, **kwargs):
    """Monkey patch Session.__new__() to create a SessionTracing object"""
    from requests_opentracing import SessionTracing
    return SessionTracing.__new__(SessionTracing)


def update_quotas(neutron, project_id, network_quotas):
    """
    Updates the networking quotas for a given project
    :param neutron: the Neutron client
    :param project_id: the project's ID that requires quota updates
    :param network_quotas: an object of type NetworkQuotas containing the
                           values to update
    :return:
    """
    update_body = dict()
    update_body['security_group'] = network_quotas.security_group
    update_body['security_group_rule'] = network_quotas.security_group_rule
    update_body['floatingip'] = network_quotas.floatingip
    update_body['network'] = network_quotas.network
    update_body['port'] = network_quotas.port
    update_body['router'] = network_quotas.router
    update_body['subnet'] = network_quotas.subnet
    return neutron.update_quota(project_id, {'quota': update_body})


def assert_called(_mock_self):
    """assert that the mock was called at least once."""
    self = _mock_self
    if self.call_count == 0:
        msg = "Expected '%s' to have been called." % self._mock_name or 'mock'
        raise AssertionError(msg)


def convert_sign(byte):
    """
    Convert between signed and unsigned bytes.
    """
    if byte < 0:
        return 256 + byte
    elif byte > 127:
        return -256 + byte
    return byte


def fill(template, hostdata, dnsdata=False):
    """Fills a generic template
    Replaces a lot of repeated code"""
    if dnsdata:
        template.names = hostdata['names']
        template.cnames = hostdata['cnames']
        template.mxs = hostdata['mxs']
    template.host = hostdata['host']
    template.interfaces = hostdata['interfaces']
    template.ips = hostdata['ips']
    return template


@classmethod
def _group_paths_without_options(cls, line_parse_result):
    """
        Given a parsed options specification as a list of groups, combine
        groups without options with the first subsequent group which has
        options.
        A line of the form
            'A B C [opts] D E [opts_2]'
        results in
            [({A, B, C}, [opts]), ({D, E}, [opts_2])]
        """
    active_pathspecs = set()
    for group in line_parse_result:
        active_pathspecs.add(group['pathspec'])
        has_options = ('norm_options' in group or 'plot_options' in group or
            'style_options' in group)
        if has_options:
            yield active_pathspecs, group
            active_pathspecs = set()
    if active_pathspecs:
        yield active_pathspecs, {}


def is_enum_namestack(nameStack):
    """Determines if a namestack is an enum namestack"""
    if not nameStack:
        return False
    if nameStack[0] == 'enum':
        return True
    if len(nameStack) > 1 and nameStack[0] == 'typedef' and nameStack[1
        ] == 'enum':
        return True
    return False


@classmethod
def load(cls, path: str, **kwargs) ->'Configuration':
    """Loads a configuration object from the file path specified.

        Parameters
        ----------
        path : str
            File path to load the configuration object from.
        kwargs : optional
            Additional parameters to pass through to the `loads` call.

        Returns
        -------
        Configuration
            The :obj:`Configuration` object loaded from the `path`
            given.

        See Also
        --------
        loads

        """
    with open(path, 'r') as fin:
        text = fin.readlines()
    return cls.loads(''.join(text), **kwargs)


def get_cache_half_life(connection: 'Connection') ->float:
    """
    Get the current setting for cache half-life.

    Parameters
    ----------
    connection : "Connection"

    Returns
    -------
    float
        Cache half-life setting

    """
    sql = 'SELECT cache_half_life()'
    return float(connection.fetch(sql)[0][0])


def next(session):
    """
        Return the next free integer in the sequence.
        It is the responsibility of the implementation of this
        interface to ensure that it can only ever return an
        integer once, no matter what happens.

        :param session:
          The :class:`~sqlalchemy.orm.session.Session` to use to
          obtain and store data needed to support the sequence
          implementation.
        """


def list_projects():
    """Return the list of available projects"""


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

        :param ShowcasePostCommentDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_post_comment_details', val)


def lookup(code, _cache={}):
    """Lookup an error code or class code and return its symbolic name.

    Raise `KeyError` if the code is not found.
    """
    if _cache:
        return _cache[code]
    tmp = {}
    for k, v in globals().items():
        if isinstance(v, str) and len(v) in (2, 5):
            tmp[v] = k
    assert tmp
    _cache.update(tmp)
    return _cache[code]


def bitarray_to_int(b):
    """Convert a bitarray to an integer."""
    if not len(b):
        return 0
    return int(b.to01(), 2)


def duration_split(duration):
    """Return a tuple of 'int' : (days, hours, minutes, seconds,
    miliseconds, microseconds) coresponding to <duration> float
    expressed in seconds.
    """
    us_in_ms = 1000 * duration - int(1000 * duration)
    nb_us = us_in_ms * 1000
    us = us_in_ms / 1000.0
    duration = duration - us
    ms = duration - int(duration)
    nb_ms = ms * 1000
    duration = duration - ms
    nb_minutes, nb_seconds = divmod(duration, 60)
    nb_hours, nb_minutes = divmod(nb_minutes, 60)
    nb_days, nb_hours = divmod(nb_hours, 24)
    debug = False
    if debug:
        print('-------------------------')
        print('d=%f' % duration)
        print('us=%f' % nb_us)
        print('ms=%f' % nb_ms)
        print('s=%f' % nb_seconds)
        print('mn=%f' % nb_minutes)
    return nb_days, nb_hours, nb_minutes, nb_seconds, nb_ms, nb_us


def nessus_snmpscan_loopy(var1, reporthost, snmp_obs, var2):
    """ Specific Nessus loop to find all SNMP issues """
    for reportitem in reporthost.findall('ReportItem'):
        if int(reportitem.get('pluginID')) in snmp_obs.keys():
            if var1 == 'addr':
                var2.append(reporthost.get('name') + ':' + reportitem.get(
                    'port'))
            elif var1 == 'obs':
                var2.append(snmp_obs.get(int(reportitem.get('pluginID'))))


@classmethod
def from_string(cls, pid):
    """Parse a PID from its string representation.

    PIDs may be represented as name@ip:port, e.g.

    .. code-block:: python

        pid = PID.from_string('master(1)@192.168.33.2:5051')

    :param pid: A string representation of a pid.
    :type pid: ``str``
    :return: The parsed pid.
    :rtype: :class:`PID`
    :raises: ``ValueError`` should the string not be of the correct syntax.
    """
    try:
        id_, ip_port = pid.split('@')
        ip, port = ip_port.split(':')
        port = int(port)
    except ValueError:
        raise ValueError('Invalid PID: %s' % pid)
    return cls(ip, port, id_)


def overlapping_chunks(sequence, size, overlap):
    """Return iterator over overlapping chunks of sequence.

    Examples
    --------
    >>> list(overlapping_chunks('ATCG'*4, 4, 2))
    [(0, 'ATCGATCG'), (4, 'ATCGATCG'), (8, 'ATCGATCG')]

    """
    index = 0
    while index < len(sequence) - 2 * overlap:
        yield index, sequence[index:index + size + 2 * overlap]
        index += size


def visibilitytoggle(o_ctrlr):
    """
    input blender logic:
        Mesh
        controller type='PYTHON' mode='MODULE'
        sensor type='KEYBOARD' name='VisibilityKey'

    description:
        togglel controller.owner object between visible and invisible
    """
    if o_ctrlr.sensors['SensVisibilityKey'].positive:
        for _ in o_ctrlr.sensors['SensVisibilityKey'].events:
            if o_ctrlr.owner.visible == True:
                o_ctrlr.owner.visible = False
                print('visibility : {} off'.format(o_ctrlr.sensors[
                    'SensVisibilityKey'].key))
            else:
                o_ctrlr.owner.visible = True
                print('visibility : {} on'.format(o_ctrlr.sensors[
                    'SensVisibilityKey'].key))


def write_file(filename, filecontent):
    """Write `filecontent` to `filename`.

    :param str filename:
        Absolute pathname of the file.
    :param str filecontent:
        Data to write to `filename`.

    """
    file_ = None
    try:
        file_ = open(filename, 'w')
        file_.write(filecontent)
        file_.close()
    except IOError:
        print('Error creating and writing content to {}'.format(filename))
        exit(1)


def check_shell(cmd, shell=None):
    """
    Determine whether a command appears to involve shell process(es).
    The shell argument can be used to override the result of the check.

    :param str cmd: Command to investigate.
    :param bool shell: override the result of the check with this value.
    :return bool: Whether the command appears to involve shell process(es).
    """
    if isinstance(shell, bool):
        return shell
    return '|' in cmd or '>' in cmd or '*' in cmd


def nice64(src):
    """ Returns src base64-encoded and formatted nicely for our XML. """
    return src.encode('base64').replace('\n', '')


def _munge_to_length(string, min_length, max_length):
    """Pad/truncates a string"""
    if len(string) < min_length:
        string += '_' * (min_length - len(string))
    if len(string) > max_length:
        string = string[:max_length]
    return string


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


@classmethod
def hascreds(cls, config):
    """Determine if the given configuration has proper credentials

        Parameters
        ----------
        cls : class
            A Session class.
        config : dict
            GDAL configuration as a dict.

        Returns
        -------
        bool

        """
    return NotImplemented