def _unique_resource_identifier_from_kwargs(**kwargs):
    """Chooses an identifier given different choices

    The unique identifier in BIG-IP's REST API at the time of this writing
    is called 'name'. This is in contrast to the unique identifier that is
    used by iWorkflow and BIG-IQ which at some times is 'name' and other
    times is 'uuid'.

    For example, in iWorkflow, there consider this URI

      * https://10.2.2.3/mgmt/cm/cloud/tenants/{0}/services/iapp

    Then consider this iWorkflow URI

      * https://localhost/mgmt/cm/cloud/connectors/local/{0}

    In the first example, the identifier, {0}, is what we would normally
    consider a name. For example, "tenant1". In the second example though,
    the value is expected to be what we would normally consider to be a
    UUID. For example, '244bd478-374e-4eb2-8c73-6e46d7112604'.

    This method only tries to rectify the problem of which to use.

    I believe there might be some change that the two can appear together,
    although I have not yet experienced it. If it is possible, I believe it
    would happen in BIG-IQ/iWorkflow land where the UUID and Name both have
    significance. That's why I deliberately prefer the UUID when it exists
    in the parameters sent to the URL.

    :param kwargs:
    :return:
    """
    name = kwargs.pop('name', '')
    uuid = kwargs.pop('uuid', '')
    id = kwargs.pop('id', '')
    if uuid:
        return uuid, kwargs
    elif id:
        return id, kwargs
    else:
        return name, kwargs


def style_param_plot(ax):
    """Apply style and aesthetics to a peaks plot.

    Parameters
    ----------
    ax : matplotlib.Axes
        Figure axes to apply styling to.
    """
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_linewidth(1.5)
    ax.spines['bottom'].set_linewidth(1.5)
    for item in [ax.xaxis.label, ax.yaxis.label]:
        item.set_fontsize(20)
    ax.tick_params(axis='both', which='major', labelsize=16)
    if ax.get_legend_handles_labels()[0]:
        legend = ax.legend(prop={'size': 16})
        for handle in legend.legendHandles:
            handle._sizes = [100]


def locate(xx, iis, iie, x):
    """Return value `j` such that `x` is between `xx[j]` and `xx[j+1]`, where
    `xx` is an array of length `n`, and `x` is a given value. `xx` must be
    monotonic, either increasing or decreasing (GSLIB version).
    :param xx: array
    :param iis: start point
    :param iie: end point
    :param x: given value
    :return: TODO
    """
    n = len(xx)
    if iis <= 0:
        iis = 0
    if iie >= n:
        iie = n - 1
    jl = iis - 1
    ju = iie
    if xx[n - 1] <= x:
        j = iie
        return j
    while ju - jl > 1:
        jm = int((ju + jl) / 2)
        if (xx[iie] > xx[iis]) == (x > xx[jm]):
            jl = jm
        else:
            ju = jm
    j = jl
    return j


def dms(dec):
    """converts decimal degree coordinates to a usgs station id
    :param dec: latitude or longitude value in decimal degrees
    :return: usgs id value

    .. note:: https://help.waterdata.usgs.gov/faq/sites/do-station-numbers-have-any-particular-meaning
    """
    DD = str(int(abs(dec)))
    MM = str(int((abs(dec) - int(DD)) * 60)).zfill(2)
    SS = str(int(round(((abs(dec) - int(DD)) * 60 - int(MM)) * 60, 0))).zfill(2
        )
    if SS == '60':
        MM = str(int(MM) + 1)
        SS = '00'
    if MM == '60':
        DD = str(int(DD) + 1)
        MM = '00'
    return DD + MM + SS


def __give_index(elem, array):
    """
     Return the index of elem in array
     """
    mylist = array.tolist()
    return mylist.index(elem)


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 global_config(cls, key, *args):
    """ This reads or sets the global settings stored in class.settings. """
    if args:
        cls.settings = cls.settings.copy()
        cls.settings[key] = args[0]
    else:
        return cls.settings[key]


def _set_start_from_first_child(node):
    """Set the start attributes of this node from its first child."""
    try:
        first_child = next(node.get_children())
    except StopIteration:
        pass
    else:
        node.fromlineno = first_child.fromlineno
        node.col_offset = first_child.col_offset
    return node


def beautify_fill(angle_limit: float=3.14159):
    """Rearrange some faces to try to get less degenerated geometry

    :param angle_limit: Max Angle, Angle limit
    :type angle_limit: float
    """
    pass


def _adapt_children_trials(node, children_trials_nodes):
    """Adapt trials from the children recursively

    .. note::

        To call with node.map(fct, node.children) to connect with children

    """
    for child in children_trials_nodes:
        adapter = child.item['experiment'].refers['adapter']
        for subchild in child:
            subchild.item['trials'] = adapter.backward(subchild.item['trials'])
    return node.item, children_trials_nodes


@classmethod
def get_dialect_cls(cls, url):
    """Given a URL, return the :class:`.Dialect` that will be used.

        This is a hook that allows an external plugin to provide functionality
        around an existing dialect, by allowing the plugin to be loaded
        from the url based on an entrypoint, and then the plugin returns
        the actual dialect to be used.

        By default this just returns the cls.

        .. versionadded:: 1.0.3

        """
    return cls


def validate():
    """Validate the address type, True if valid, else False."""


def compute_srec_checksum(srec):
    """
        Compute the checksum byte of a given S-Record
        Returns: The checksum as a string hex byte (ex: "0C")
    """
    data = srec[2:len(srec)]
    sum = 0
    for position in range(0, len(data), 2):
        current_byte = data[position:position + 2]
        int_value = int(current_byte, 16)
        sum += int_value
    hex_sum = hex(sum)
    least_significant_byte = hex_sum[len(hex_sum) - 2:]
    least_significant_byte = least_significant_byte.replace('x', '0')
    int_lsb = int(least_significant_byte, 16)
    computed_checksum = ~int_lsb & 255
    return computed_checksum


@classmethod
def update_or_create(cls, attributes, values=None):
    """
        Create or update a record matching the attributes, and fill it with values.

        :param attributes: The instance attributes
        :type attributes: dict

        :param values: The values
        :type values: dict

        :return: The new instance
        :rtype: Model
        """
    instance = cls.first_or_new(**attributes)
    if values is None:
        values = {}
    instance.fill(**values).save()
    return instance


def out_64(library, session, space, offset, data, extended=False):
    """Write in an 64-bit value from the specified memory space and offset.

    Corresponds to viOut64* functions of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param space: Specifies the address space. (Constants.*SPACE*)
    :param offset: Offset (in bytes) of the address or register from which to read.
    :param data: Data to write to bus.
    :param extended: Use 64 bits offset independent of the platform.
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    if extended:
        return library.viOut64Ex(session, space, offset, data)
    else:
        return library.viOut64(session, space, offset, data)


def execusercustomize():
    """Run custom user specific code, if available."""
    try:
        import usercustomize
    except ImportError:
        pass


@classmethod
def create(cls, value=None, signal=None):
    """
        Create an instance of either a return value or an exit signal.
        The other parameter must be None.
        """
    if value is None and signal is None:
        raise ValueError('Need return value or exit signal for ProcessExitCode'
            )
    if value is not None and signal is not None:
        raise ValueError(
            'Cannot create ProcessExitCode with both value and signal')
    if value is not None and not 0 <= value <= 255:
        raise ValueError('Invalid value {} for return value'.format(value))
    if signal is not None and not 1 <= signal <= 127:
        raise ValueError('Invalid value {} for exit signal'.format(value))
    exitcode = (value or 0) * 256 + (signal or 0)
    return cls(exitcode, value, signal)


def generateTeXQuery(s):
    """
	Returns the texit latex query for the argument latex string.
	"""
    return 'http://tex.sh/tex/$' + s + '$.png'


def request_is_rebuild(spec_obj):
    """Returns True if request is for a rebuild.

    :param spec_obj: An objects.RequestSpec to examine (or None).
    """
    if not spec_obj:
        return False
    if 'scheduler_hints' not in spec_obj:
        return False
    check_type = spec_obj.scheduler_hints.get('_nova_check_type')
    return check_type == ['rebuild']


def enStr2(easting, northing, prec, *extras):
    """DEPRECATED, use function L{enstr2}.
    """
    from pygeodesy.streprs import enstr2
    return enstr2(easting, northing, prec, *extras)


def convert_template_project(_project):
    """ Convert Template Project """
    pass


def theta_H_Li_PK74(T, P):
    """c-c': hydrogen lithium [PK74]."""
    theta = 0.015
    valid = T == 298.15
    return theta, valid


def remove_outer_square_brackets(text):
    """
    Checks that test is of the form "[...]" and returns result between
    brackets.

    >>> remove_outer_square_brackets("[a*b*c]")
    'a*b*c'
    >>> remove_outer_square_brackets("[[a,b]")
    '[a,b'
    """
    if text[0] != '[' or text[-1] != ']':
        raise ValueError('Error while parsing: outer square brackets missing')
    return text[1:-1]


def is_number(var):
    """
    Checks whether an string is a number, if is already an integer or float it also returns True

    :param factor: :py:func:`str` :py:func:`int` :py:func:`float` variable to check

    :returns: :py:func:`boolean` True when input variable is a number otherwise False

    """
    try:
        float(var)
        return True
    except ValueError:
        return False


@staticmethod
def _prior_timepoint_generator(ts_group, cond):
    """
        Yield the previous timepoint condition name and delt until it gets back to the first timepoint
        :param cond:
        """
    prev_cond, prev_delt = ts_group[cond][0]
    while prev_cond is not None:
        yield prev_cond, prev_delt
        prev_cond, prev_delt = ts_group[prev_cond][0]


@staticmethod
def run_periodic():
    """Method executed every interval."""
    pass


def get_context(obj):
    """Search for a context manager"""
    try:
        return obj._contexts[-1]
    except (AttributeError, IndexError):
        pass
    try:
        return obj._model._contexts[-1]
    except (AttributeError, IndexError):
        pass
    return None


@classmethod
def _decr_instances(cls, instance):
    """
        Remove from list and reposition other bars
        so that newer bars won't overlap previous bars
        """
    with cls._lock:
        try:
            cls._instances.remove(instance)
        except KeyError:
            pass
        if not instance.gui:
            for inst in cls._instances:
                if hasattr(inst, 'pos') and inst.pos > abs(instance.pos):
                    inst.clear(nolock=True)
                    inst.pos -= 1
        if not cls._instances and cls.monitor:
            try:
                cls.monitor.exit()
                del cls.monitor
            except AttributeError:
                pass
            else:
                cls.monitor = None


def method_not_allowed(environ, start_response):
    """Default WSGI 405 app."""
    start_response('405 Method Not Allowed', [('Allow', ', '.join(environ[
        'selector.methods'])), ('Content-Type', 'text/plain')])
    return [
        """405 Method Not Allowed

The method specified in the Request-Line is not allowed for the resource identified by the Request-URI."""
        ]


def _earlyoptarg(arg, shortlist, namelist):
    """Check if the given arg is a valid unabbreviated option

    Returns (flag_str, has_embedded_value?, embedded_value, takes_value?)

    >>> def opt(arg):
    ...     return _earlyoptarg(arg, b'R:q', [b'cwd=', b'debugger'])

    long form:

    >>> opt(b'--cwd')
    ('--cwd', False, '', True)
    >>> opt(b'--cwd=')
    ('--cwd', True, '', True)
    >>> opt(b'--cwd=foo')
    ('--cwd', True, 'foo', True)
    >>> opt(b'--debugger')
    ('--debugger', False, '', False)
    >>> opt(b'--debugger=')  # invalid but parsable
    ('--debugger', True, '', False)

    short form:

    >>> opt(b'-R')
    ('-R', False, '', True)
    >>> opt(b'-Rfoo')
    ('-R', True, 'foo', True)
    >>> opt(b'-q')
    ('-q', False, '', False)
    >>> opt(b'-qfoo')  # invalid but parsable
    ('-q', True, 'foo', False)

    unknown or invalid:

    >>> opt(b'--unknown')
    ('', False, '', False)
    >>> opt(b'-u')
    ('', False, '', False)
    >>> opt(b'-ufoo')
    ('', False, '', False)
    >>> opt(b'--')
    ('', False, '', False)
    >>> opt(b'-')
    ('', False, '', False)
    >>> opt(b'-:')
    ('', False, '', False)
    >>> opt(b'-:foo')
    ('', False, '', False)
    """
    if arg.startswith(b'--'):
        flag, eq, val = arg.partition(b'=')
        if flag[2:] in namelist:
            return flag, bool(eq), val, False
        if flag[2:] + b'=' in namelist:
            return flag, bool(eq), val, True
    elif arg.startswith(b'-') and arg != b'-' and not arg.startswith(b'-:'):
        flag, val = arg[:2], arg[2:]
        i = shortlist.find(flag[1:])
        if i >= 0:
            return flag, bool(val), val, shortlist.startswith(b':', i + 1)
    return b'', False, b'', False


def ellipse_mode(mode='CENTER'):
    """Change the ellipse and circle drawing mode for the p5.renderer.

    :param mode: The new mode for drawing ellipses. Should be one of
        {'CORNER', 'CORNERS', 'CENTER', 'RADIUS'}. This defaults to
        'CENTER' so calling ellipse_mode without parameters will reset
        the sketch's ellipse mode.
    :type mode: str

    """
    global _ellipse_mode
    _ellipse_mode = mode


def reply_903(bot, data):
    """
        Authentication Reply
    """
    data_split = data.split()
    if data_split[-1] == 'successful':
        bot.sasl_authentication_success = True
        bot.send_message('CAP END')
    else:
        bot.sasl_authentication_success = False


def to_locale(language, to_lower=False):
    """
    Turns a language name (en-us) into a locale name (en_US). If 'to_lower' is
    True, the last component is lower-cased (en_us).
    """
    p = language.find('-')
    if p >= 0:
        if to_lower:
            return language[:p].lower() + '_' + language[p + 1:].lower()
        else:
            if len(language[p + 1:]) > 2:
                return language[:p].lower() + '_' + language[p + 1].upper()
                +language[p + 2:].lower()
            return language[:p].lower() + '_' + language[p + 1:].upper()
    else:
        return language.lower()


def save_xarray_to_HDF5(dataArray, filename, complib=None):
    """Save the xarray DataArray to HDF file using pandas HDFStore

    attrs will be saved as metadata via pickle

    requries pytables

    complib : {'zlib', 'bzip2', 'lzo', 'blosc', None}, default None"""
    from pandas import HDFStore
    f = HDFStore(filename, mode='w', complib=complib)
    f.put('data', dataArray.to_pandas())
    if len(dataArray.attrs) > 0:
        f.get_storer('data').attrs.metadata = dataArray.attrs
    f.close()


def add_resource_routes(config, route_name, resource_class, path):
    """
    Add routes to the config for a resource_class and path.
    We also add a route for no method passed.
    """
    config.add_route(name=route_name, pattern='/%s/{method}' % path,
        factory=resource_class)
    config.add_route(name=route_name + '.nomethod', pattern='/%s' % path,
        factory=resource_class)


@staticmethod
def _get_fc_port_value(metric, data):
    """
        function that returns the data from the managed object
        :param metric:
        :param data:
        :return:
        """
    if metric == 'network.fc.tx.rate':
        return float(float(data.FcStats.bytes_tx_delta) / 60 * 8 / 1000000000)
    elif metric == 'network.fc.rx.rate':
        return float(float(data.FcStats.bytes_rx_delta) / 60 * 8 / 1000000000)
    elif metric == 'network.fc.err.rx.crc':
        return float(data.FcErrStats.crc_rx_delta)
    elif metric == 'network.fc.err.rx.discard':
        return float(data.FcErrStats.discard_rx_delta)
    elif metric == 'network.fc.err.rx':
        return float(data.FcErrStats.rx_delta)
    elif metric == 'network.fc.err.signal_losses':
        return float(data.FcErrStats.signal_losses_delta)
    elif metric == 'network.fc.err.link.failure':
        return float(data.FcErrStats.link_failures_delta)
    elif metric == 'network.fc.link.speed':
        return float(data.oper_speed.replace('gbps', ''))
    elif metric == 'network.fc.err.rx.too_short':
        return float(data.FcErrStats.too_short_rx_delta)
    elif metric == 'network.fc.err.rx.too_long':
        return float(data.FcErrStats.too_long_rx_delta)
    elif metric == 'network.fc.err.tx':
        return float(data.FcErrStats.tx_delta)
    else:
        return None


def create_readme(data):
    """
    Create README.md text for the given module data.
    """
    out = ['Modules\n========\n\n']
    for module in sorted(data.keys()):
        desc = ''.join(data[module]).strip().split('\n')[0]
        format_str = '\n**[{name}](#{name})** — {desc}\n'
        out.append(format_str.format(name=module, desc=desc))
    for module in sorted(data.keys()):
        out.append('\n---\n\n### {name}\n\n{details}\n'
            .format(name=module, details=''.join(data[module]).strip()))
    return ''.join(out)


def normalize(text, locale=None, max_length=None):
    """The normalize method takes and input unicode text and an optional
           locale string and returns a normalized version of the text.
           If the locale is not None the ouput might differ dependent on the
           locale. The max_length argument allows you to override the default
           values used by the normalizers on a case-by-case basis.
        """


def set_max_img_views_before_warning(new_value):
    """Set the number of open views which triggers a warning.

    If `None` or a negative number, disable the memory warning.
    """
    global MAX_IMG_VIEWS_BEFORE_WARNING
    MAX_IMG_VIEWS_BEFORE_WARNING = new_value


def stamp_experiment(base_feature, method_name, atlas, smoothing_param,
    node_size):
    """Constructs a string to uniquely identify a given feature extraction method."""
    expt_id = '{}_{}_{}_smoothing{}_size{}'.format(method_name,
        base_feature, atlas, smoothing_param, node_size)
    return expt_id


def SGpolar(SGData):
    """
    Determine identity of polar axes if any
    """
    POL = '', 'x', 'y', 'x y', 'z', 'x z', 'y z', 'xyz', '111'
    NP = [1, 2, 4]
    NPZ = [0, 1]
    for M, T in SGData['SGOps']:
        for i in range(3):
            if M[i][i] <= 0.0:
                NP[i] = 0
        if M[0][2] > 0:
            NPZ[0] = 8
        if M[1][2] > 0:
            NPZ[1] = 0
    NPol = (NP[0] + NP[1] + NP[2] + NPZ[0] * NPZ[1]) * (1 - int(SGData[
        'SGInv']))
    return POL[NPol]


def safeToInt(value, default=0):
    """Convert value to integer or just return 0 if we can't

       >>> safeToInt(45)
       45

       >>> safeToInt("42")
       42

       >>> safeToInt("spam")
       0

       >>> safeToInt([])
       0

       >>> safeToInt(None)
       0

       >>> safeToInt(None, default=-1)
       -1
    """
    try:
        return int(value)
    except (ValueError, TypeError):
        return default


@classmethod
def shorten_media_id(cls, media_id):
    """
        Returns the shortcode for a media id

        :param media_id: string in the format id format: AAA_BB where AAA is the pk, BB is user_id
        :return:
        """
    internal_id = int(str(media_id).split('_')[0])
    return cls.shorten_id(internal_id)


def get_roles_for_principal(principal):
    """Return the role grants for the principal

        The role grants are an iterable of role, setting tuples, where
        setting is either Allow or Deny.
        """


def bet_sizing(bs_dict, proba, ratio):
    """
    Gets bet sizing given a bet sizing dictionary and prediction proba and ratio brackets.
    :param bs_dict: (pandas DataFrame) truth table for bet sizing
    :param proba: (int) Proba bracket
    :param ratio: (int) Ratio bracket

    :return: Bet Sizing for given 'predict_proba' and 'ratio' bracket given a truth table
    :rtype: float
    """
    return bs_dict.loc[proba, ratio]


def __contains__(changeid):
    """Whether a changeset exists."""


def gru_unit(**kwargs):
    """
    We cannot pass param_attr or bias_attr to paddle.fluid.layers.gru_unit yet.
    """
    raise NotImplementedError()


def get_volume_shape(vol):
    """Returns the shape of a gridded volume"""
    return len(vol.tensor_u), len(vol.tensor_v), len(vol.tensor_w)


def set_prefs(prefs):
    """This function is called before opening the project"""
    prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', '.hg',
        '.svn', '_svn', '.git']
    prefs['save_objectdb'] = True
    prefs['compress_objectdb'] = False
    prefs['automatic_soa'] = True
    prefs['soa_followed_calls'] = 0
    prefs['perform_doa'] = True
    prefs['validate_objectdb'] = True
    prefs['max_history_items'] = 32
    prefs['save_history'] = True
    prefs['compress_history'] = False
    prefs['indent_size'] = 4
    prefs['extension_modules'] = []
    prefs['import_dynload_stdmods'] = True
    prefs['ignore_syntax_errors'] = False
    prefs['ignore_bad_imports'] = False


def CleanString(s):
    """Cleans up string.

    Doesn't catch everything, appears to sometimes allow double underscores
    to occur as a result of replacements.
    """
    punc = ' ', '-', "'", '.', '&', '&', '+', '@'
    pieces = []
    for part in s.split():
        part = part.strip()
        for p in punc:
            part = part.replace(p, '_')
        part = part.strip('_')
        part = part.lower()
        pieces.append(part)
    return '_'.join(pieces)


def parseVariable(toks):
    """Called by the parser created by :func:`makeParser`. Parses a variable
    identifier, returning an integer ID.
    """
    return toks[1]


@classmethod
def create(cls, *args, **kwargs):
    """Create factory method for instantiating devices. Takes the source JSON object
        and figures out which type of class it should make and then calls the constructor.
        """
    allowed_devices = ['Controller', 'RoomStat', 'iTRV']
    classname = kwargs['ProductType']
    if classname not in allowed_devices:
        raise Exception('Invalid Device')
    cls = globals()[classname]
    return cls(*args, **kwargs)


def validate_type(input, *types):
    """Raise TypeError if the type of ``input`` is one of the args

    If the input value is one of the types specified, just return
    the input value.

    """
    if not isinstance(input, types):
        raise TypeError('Input expected to one of following types: %s' % (
            types,))
    return input


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

        :param LookupError val:
        :rtype: ExportError
        """
    return cls('path', val)


def manage_addUser(REQUEST, kwargs):
    """ Create a new user record. If REQUEST is not None, it will be
        used to retrieve the values for the user record.

        To use this method from Python you must pass None as the REQUEST
        argument and a dictionary called *kwargs* containing key/value pairs
        for the user record attributes.

        The dictionary of values passed in, be it REQUEST or kwargs, must at
        the very least contain the following keys and values:

        o *cn* or *uid* (depending on what you set the RDN attribute to)

        o *user_pw* (the new user record's password)

        o *confirm_pw* (This must match password)

        o all attributes your user record LDAP schema must contain (consult
          your LDAP server schema)

        Only those attributes and values are used that are specified on the
        LDAP Schema tab of your LDAPUserFolder.

        Permission: *Manage users*
        """


@classmethod
def from_pixels_and_mask(cls, pixels, mask):
    """Create *Coordinates* from a list of coordinates in pixel units and a mask which allows these coordinates to
        be converted to scaled units."""
    coordinates = []
    for coordinate_set in pixels:
        coordinates.append([mask.geometry.
            scaled_coordinates_from_pixel_coordinates(pixel_coordinates=
            coordinates) for coordinates in coordinate_set])
    return cls(coordinates=coordinates)


def delManager(userid):
    """Removes an user from all Plone sites
        """


def size_to_kb_mb_string(data_size: int, as_additional_info: bool=False) ->str:
    """Returns human-readable string with kilobytes or megabytes depending on the data_size range.

		:param data_size: data size in bytes to convert
		:param as_additional_info:
		if True, the dynamic data appear in round bracket after the number in bytes. e.g. '12345678 bytes (11.7 MB)'
		if False, only the dynamic data is returned e.g. '11.7 MB' """
    if data_size < 1024:
        as_additional_info = False
        dynamic = f'{data_size} bytes'
    elif data_size < 1048576:
        dynamic = f'{data_size / 1024:0.1f} kB'
    else:
        dynamic = f'{data_size / 1048576:0.1f} MB'
    if as_additional_info:
        return f'{data_size} bytes ({dynamic})'
    else:
        return dynamic


def where(query):
    """
    Simply returns the given query to the scope builder. Useful when you need
    to combine arbritary query elements with other scopes.
    """
    return query


@classmethod
def background(cls, *args):
    """Background distribution"""
    raise NotImplementedError


def suspend():
    """
        Invoked when notification for this listener is being temporarily
        suspended.

        This should clean up any ephemeral resources held by this listener and
        generally prepare to not do anything for a while.
        """


def _lorentzian(x, p):
    """Define the lorentzian fit."""
    numerator = p[1] ** 2
    denominator = (x - p[0]) ** 2 + p[1] ** 2
    return p[2] * (numerator / denominator) - p[3]


@classmethod
def getSupportedSymbols(cls):
    """Returns the list of supported symbol names.

        :rtype: tuple of str
        """
    return tuple(cls._SUPPORTED_SYMBOLS.keys())


def toUnicode(value):
    """Returns the given argument as a unicode object.

    @param value: A UTF-8 encoded string or a unicode (coercable) object
    @type message: str or unicode

    @returns: Unicode object representing the input value.
    """
    if isinstance(value, bytes):
        return value.decode('utf-8')
    return str(value)


@staticmethod
def header_info():
    """Gets header information for the csv of this listing"""
    return ['price', 'drive_time', 'walk_time', 'total_cost', 'address',
        'url', 'utils_cost', 'drive_cost', 'walk_cost']


def fix(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise rounded value to the nearest \\
    integer towards zero of the input.

    Example::

       fix([-2.1, -1.9, 1.9, 2.1]) = [-2., -1.,  1., 2.]

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

       - fix(default) = default
       - fix(row_sparse) = row_sparse
       - fix(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_basic.cc:L875

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

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

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


def pformat(obj, verbose=False):
    """Prettyprint an object.  Either use the `pretty` library or the
    builtin `pprint`.
    """
    try:
        from pretty import pretty
        return pretty(obj, verbose=verbose)
    except ImportError:
        from pprint import pformat
        return pformat(obj)


def Kelvin_C(Celsius):
    """Usage: Convert to Kelvin from Celsius
    Kelvin_C(Celsius)"""
    return Celsius + 273.15


def norm(x1, x2=None):
    """
Normalizes x1. If also given as input x2, then normalizes x1 to x2.

:param x1: input array
:param x2: optional
:returns: normalized x1
	"""
    if x2 is None:
        return x1 / x1.max()
    else:
        return x1 * x2.max() / x1.max()


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


def geometry_column_name(gdf):
    """Get geometry column name, fall back to 'geometry'
    """
    try:
        geom_col = gdf.geometry.name
    except AttributeError:
        geom_col = 'geometry'
    return geom_col


def _ADDS_immediate(cpu, res_op, reg_op, imm_op):
    """
        ADDS (immediate).

        :param res_op: destination register.
        :param reg_op: source register.
        :param imm_op: immediate.
        """
    cpu._adds_subs_immediate(res_op, reg_op, imm_op, mnem='adds')


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

        :returns: this backend does not supports items resuming
        """
    return False


def _fuzzy_group(args, quick_exit=False):
    """
    Return True if all args are True, None if there is any None else False
    unless ``quick_exit`` is True (then return None as soon as a second False
    is seen.

     ``_fuzzy_group`` is like ``fuzzy_and`` except that it is more
    conservative in returning a False, waiting to make sure that all
    arguments are True or False and returning None if any arguments are
    None. It also has the capability of permiting only a single False and
    returning None if more than one is seen. For example, the presence of a
    single transcendental amongst rationals would indicate that the group is
    no longer rational; but a second transcendental in the group would make the
    determination impossible.

    Examples
    ========

    By default, multiple Falses mean the group is broken:

    >>> _fuzzy_group([False, False, True])
    False

    If multiple Falses mean the group status is unknown then set
    `quick_exit` to True so None can be returned when the 2nd False is seen:

    >>> _fuzzy_group([False, False, True], quick_exit=True)

    But if only a single False is seen then the group is known to
    be broken:

    >>> _fuzzy_group([False, True, True], quick_exit=True)
    False

    """
    saw_other = False
    for a in args:
        if a is True:
            continue
        if a is None:
            return
        if quick_exit and saw_other:
            return
        saw_other = True
    return not saw_other


@staticmethod
def elide(input_str, max_len=255):
    """ only in case the passed string is longer than 'max_len', it applies elision """
    if len(input_str) > max_len:
        return input_str[:max_len] + '[..]'
    return input_str


def shift_pos(pos, label_shift):
    """shift a pos by (sx, xy) pixels"""
    shiftx = label_shift[0]
    shifty = label_shift[1]
    pos2 = pos.copy()
    for key, position in pos2.items():
        pos2[key] = position[0] + shiftx, position[1] + shifty
    return pos2


def find_first_listed_qtr(quarterly_submissions, s):
    """
    Finds the first qtr for which the company published at least one report.

    :param quarterly_submissions: dictionary of submissions indexes by qtr
    :param s: Settings dictionary
    :return: bool for success and first qtr when the company was listed.
    """
    flag_listed = False
    for qtr in s['list_qtr']:
        if len(quarterly_submissions[qtr]) == 0:
            continue
        else:
            flag_listed = True
            break
    return flag_listed, qtr


@staticmethod
def remove_timeout(handle):
    """
        Cancel asyncio.Handle

        :type handle: asyncio.Handle
        :rtype: bool
        """
    return handle.cancel()


def subtract_electronic_background(signal, background_signal):
    """
    Subtract the electronic background profile from the signal.

    The signal can be either a 1D array or a 2D array with dimensions (time, range).

    Parameters
    ----------
    signal: int or float array
       The lidar signal profile.
    background_signal: int or float array
       Electronic background profile.

    Returns
    -------
    output_singal: array
       The array with the corrected signal.
    """
    corrected_signal = signal - background_signal
    return corrected_signal


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up a Nest Cam.

    No longer in use.
    """


def _process_occurs_attrs(node):
    """Process the min/max occurrence indicators"""
    max_occurs = node.get('maxOccurs', '1')
    min_occurs = int(node.get('minOccurs', '1'))
    if max_occurs == 'unbounded':
        max_occurs = 'unbounded'
    else:
        max_occurs = int(max_occurs)
    return min_occurs, max_occurs


def template_name_from_class_name(class_name):
    """ Remove the last 'Template' in the name. """
    suffix = 'Template'
    output = class_name
    if class_name.endswith(suffix):
        output = class_name[:-len(suffix)]
    return output


def db2mag(xdb):
    """Convert decibels (dB) to magnitude

    .. doctest::

        >>> from spectrum import db2mag
        >>> db2mag(-20)
        0.1

    .. seealso:: :func:`pow2db`
    """
    return 10.0 ** (xdb / 20.0)


def getMaxAmplitude(sampleWidth):
    """Gets the maximum possible amplitude for a given sample width"""
    return 2 ** (sampleWidth * 8 - 1) - 1


def discard():
    """Discard the current draft information for the next request.

        For example, this could expire a cookie.
        """


def add_marker_at_click():
    """Place new marker at the desired (clicked) position

    """
    pass


@staticmethod
def on_transport_factory_preparation(transport_factory):
    """Plugin hook to intercept/manipulate newly created Transport factories
        before first invocation."""


def cpdb_import(cpe_config, filename):
    """
    Starts the dialog to import basedata from latex files.
    """
    from chessproblem.ui.database.file_importer import import_all_from_tex
    from chessproblem.model.db import DbService
    db_service = DbService(cpe_config.database_url)
    import_all_from_tex(db_service, filename)


def graph2data(graph):
    """Returns the index and data of a sparse matrix.

    Parameters
    ----------
    graph : csr_matrix
        A sparse matrix of the edges in a graph and corresponding node indexes.

    Returns
    -------
    index1, index2 : array
        Arrays of the node indices of the graph.
    weights : array
        An array of the weights of each edge in the graph.
    """
    graph = graph.tocoo()
    weights = graph.data
    index1 = graph.row
    index2 = graph.col
    return index1, index2, weights


@staticmethod
def p_a2ml_taggedstruct_member(p):
    """a2ml_taggedstruct_member : a2ml_taggedstruct_definition SEMICOLON
                                    | PARENTHESE_OPEN a2ml_taggedstruct_definition PARENTHESE_CLOSE ASTERISK SEMICOLON
                                    | a2ml_block_definition SEMICOLON
                                    | PARENTHESE_OPEN a2ml_block_definition PARENTHESE_CLOSE ASTERISK SEMICOLON"""


@classmethod
def register_class(cls, register_cls, map_kwargs=None):
    """Add a route class to :attr:`_base_store`, appling mapping from
        :func:`get_register_class_map` where required. This route class will
        be instantiated (with kwargs from :func:`get_base_store_kwargs`)
        when the Router is itself instiated, using
        :func:`register_base_store`.

        :argument register_cls: Object to register (usually Route or
                                Router classes, but could be anything
                                because of possible mapping in
                                :func:`get_register_class_map_kwargs`)
        :argument map_kwargs: Argument to pass to mapping value if
                              entity gets transformed.
        :type map_kwargs: dict

        :returns: The registered class, transformed by class register
                  mappings if there was a matching mapping
        :rtype: class

        >>> from mock import Mock
        >>> mock_entity_instance = Mock()
        >>> mock_entity = Mock()
        >>> mock_entity.side_effect = [mock_entity_instance]
        >>> mock_mapping_func = Mock()
        >>> mock_mapping_func.side_effect = [mock_entity]
        >>>
        >>> class Class:
        ...  pass
        >>>
        >>> class Store(EntityStore):
        ...   @classmethod
        ...   def get_register_class_map(self):
        ...     return {Class: mock_mapping_func}
        >>>
        >>> Store.register_class(Class) is mock_entity
        True
        >>>
        >>> Store._base_store == [mock_entity]
        True
        >>>
        >>> store = Store()
        >>> store._store == [mock_entity_instance]
        True
        """
    register_class_map = cls.get_register_class_map()
    if register_class_map:
        if map_kwargs is None:
            map_kwargs = {}
        map_kwargs = dict(cls.get_register_class_map_kwargs(), **map_kwargs)
        register_cls = cls.register_apply_map(register_cls,
            register_class_map, map_kwargs)
    cls._base_store.append(register_cls)
    return register_cls


@staticmethod
def list_node_connections(node):
    """
        Returns all connections of the given node
        :param node: str
        :return: list(str)
        """
    raise NotImplementedError(
        'abstract DCC function list_node_connections() not implemented!')


def outdent(all=False):
    """
    Decrements global indenting level.
    Should be called whenever leaving a structural logging section.
    """
    global __level
    if all:
        __level = 0
    else:
        __level -= 1


@staticmethod
def _wrap_pack(value, packer):
    """Return `value` encoded as bytes using `packer`.

        Parameters
        ----------
        value
            The value to encode.
        packer : callable
            A callable function to use to pack the data as bytes. The
            `packer` should return the packed bytes. Example:
            struct.Struct('>I').pack

        Returns
        -------
        bytes
        """
    return packer(value)


def rgb(red: int, green: int, blue: int, background=False) ->str:
    """Return the ANSI escape that generates the color"""
    if background:
        return '\x1b[48;2;' + str(red) + ';' + str(green) + ';' + str(blue
            ) + 'm'
    else:
        return '\x1b[38;2;' + str(red) + ';' + str(green) + ';' + str(blue
            ) + 'm'


def google_text_emphasis(style):
    """return a list of all emphasis modifiers of the element"""
    emphasis = []
    if 'text-decoration' in style:
        emphasis.append(style['text-decoration'])
    if 'font-style' in style:
        emphasis.append(style['font-style'])
    if 'font-weight' in style:
        emphasis.append(style['font-weight'])
    return emphasis


def to_bytes(str_or_bytes):
    """
        转换 str_or_bytes 为 bytes

        - if hasattr(str_or_bytes, 'encode'), 转换

    :param str_or_bytes:
    :return:
    """
    return str_or_bytes.encode() if hasattr(str_or_bytes, 'encode'
        ) else str_or_bytes


@classmethod
def match(cls, *args):
    """Match to return the plugin which is appropriate to load"""


def grab_elevation(g):
    """Grab site elevation from proxychimp.Guts"""
    victim = g.pull_section('Site Information')[0]
    elevation = None
    for ln in victim:
        if 'Elevation:' in ln:
            ln_split = ln.split(':')
            elevation = float(ln_split[-1])
    return elevation


@classmethod
def fromkeys(cls, iterable, value='', mutable=False, encoding=None):
    """
        Return a new QueryDict with keys (may be repeated) from an iterable and
        values from value.
        """
    q = cls('', mutable=True, encoding=encoding)
    for key in iterable:
        q.appendlist(key, value)
    if not mutable:
        q._mutable = False
    return q


def _cuda_irfft_get(x, n, axis=-1):
    """Compute irfft and get."""
    import cupy
    return cupy.fft.irfft(x, n=n, axis=axis).get()


def _update_host_personality(module, array, answer=False):
    """Change host personality. Only called when supported"""
    personality = array.get_host(module.params['host'], personality=True)[
        'personality']
    if personality is None and module.params['personality'] != 'delete':
        try:
            array.set_host(module.params['host'], personality=module.params
                ['personality'])
            answer = True
        except Exception:
            module.fail_json(msg='Personality setting failed.')
    if personality is not None:
        if module.params['personality'] == 'delete':
            try:
                array.set_host(module.params['host'], personality='')
                answer = True
            except Exception:
                module.fail_json(msg='Personality deletion failed.')
        elif personality != module.params['personality']:
            try:
                array.set_host(module.params['host'], personality=module.
                    params['personality'])
                answer = True
            except Exception:
                module.fail_json(msg='Personality change failed.')
    return answer


def get_station(seedid):
    """Station name from seed id"""
    st = seedid.rsplit('.', 2)[0]
    if st.startswith('.'):
        st = st[1:]
    return st


def _dataset_file_id_migration(client):
    """Ensure dataset files have a fully qualified url."""
    for dataset in client.datasets.values():
        for file_ in dataset.files:
            if not file_._id.startswith('https'):
                file_._id = file_.default_id()
        dataset.to_yaml()


def cDiff():
    """
    Return the kernel source of cDiff.
    """
    R = """
        KERNEL void cDiff(  GLOBAL_MEM    const    int            *order2,
                                               GLOBAL_MEM     const   float2     *indata,
                                               GLOBAL_MEM                  float2     *outdata)
        {
        const unsigned int gid =  get_global_id(0);
        const unsigned int ind = order2[gid];
        outdata[gid]=indata[ind]- indata[gid];
        };
        """
    return R


def trim_trailing(scores, threshold):
    """
    Trim low quality bases from the 3'-end of the sequence.
    """
    threshold = abs(threshold)
    position = 0
    for position, basescore in enumerate(scores[::-1]):
        if basescore >= threshold:
            break
    return 0, position


def get_grammar_arrows(p, start):
    """Get the links between grammar nodes.

    Yield pairs (2-tuples).  Each tuple ``(head, tail)`` means that tail is in
    the right side of some production ``head ::= ... tail ...``.

    """
    rules = list(p.rules[start])
    seen = set()
    while rules:
        head, prod = rules.pop(0)
        seen.add(head)
        new = set()
        for which in prod:
            if which not in new and which not in seen:
                new.add(which)
                yield head, which
                rules.extend(p.rules.get(which, []))


def str_(data):
    """ Python 2 and 3 safe str(),
        for when Python 3 uses Bytes where Python 2 used Strings.
        Should be used anywhere you would use the str() function.
    """
    if isinstance(data, (bytes, bytearray)):
        return data.decode()
    return str(data)


def dispatch_hook(key, hooks, hook_data, **kwargs):
    """Dispatches a hook dictionary on a given piece of data."""
    hooks = hooks or dict()
    if key in hooks:
        hooks = hooks.get(key)
        if hasattr(hooks, '__call__'):
            hooks = [hooks]
        for hook in hooks:
            _hook_data = hook(hook_data, **kwargs)
            if _hook_data is not None:
                hook_data = _hook_data
    return hook_data


@classmethod
def get_type(cls):
    """
        This function is called when the unmounted type (Enum instance)
        is mounted (as a Field, InputField or Argument)
        """
    return cls


def client_encoding_decoding_point_f() ->str:
    """
    provides method code to encode and decode response data
    """
    py_code = """
    def _encode(self, data, format=None):
        ""\"
        Abstracted encoding point. Mount your custom function.
        Focus here is on built in JSON.

        Args:
            data(): python object
            format(str): json or url

        Returns:
            data_encoded: :func:`json.dumps` and encode from utf-8 to binary

        ""\"
        if type(data) is bytes:
            return data
        if format == 'url':
            return (urllib.parse.urlencode(data)).encode('utf-8')
        if format is None:
            return (json.dumps(data)).encode('utf-8')
        elif format == 'json':
            return (json.dumps(data)).encode('utf-8')
        else:
            msg = f"received format = {format}.\\nUse 'json' or 'url'.\\n 'json' is default."
            raise NotImplementedError(msg)

    def _decode(self, data):
        ""\"
        abstracted decoding point
        Mount your custom function. Focus here is on JSON.

        Args:
            data: python object (dict, list, ...)

        Returns:
           data_decoded: first decode from binary to utf-8 and parse with
                         built-in :func:`json.loads`
        ""\"

        return json.loads(data.decode('utf-8'))
    """
    return py_code


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

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

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


def gather(reference, indices):
    """Retrieves the elements of indices `indices` in the tensor `reference`.

    # Arguments
        reference: A tensor.
        indices: An integer tensor of indices.

    # Returns
        A tensor of same type as `reference`.
    """
    y = reference[indices]
    if hasattr(reference, '_keras_shape') and hasattr(indices, '_keras_shape'):
        y._keras_shape = indices._keras_shape + reference._keras_shape[1:]
    return y


def curses_available():
    """Check if the curses package from stdlib is available.

    Usually not available for windows, but its presence indicates that the
    terminal is capable of displaying some UI.

    Returns:
        bool: result of check
    """
    try:
        import curses
        return True
    except ImportError:
        return False


def write_graph(path, dot_graph, _format, prog, **pydot_args):
    """Write DOT graph to file.

    Parameters
    ----------
    path
    dot_graph
    _format
    prog
    pydot_args

    Returns
    -------

    """
    import os
    path = os.path.normpath(path)
    return dot_graph.write(path, format=_format, prog=prog, **pydot_args)


def calculate_ecef_velocity(inst):
    """
    Calculates spacecraft velocity in ECEF frame.

    Presumes that the spacecraft velocity in ECEF is in
    the input instrument object as position_ecef_*. Uses a symmetric
    difference to calculate the velocity thus endpoints will be
    set to NaN. Routine should be run using pysat data padding feature
    to create valid end points.

    Parameters
    ----------
    inst : pysat.Instrument
        Instrument object

    Returns
    -------
    None
        Modifies pysat.Instrument object in place to include ECEF velocity
        using naming scheme velocity_ecef_* (*=x,y,z)

    """
    x = inst['position_ecef_x']
    vel_x = (x.values[2:] - x.values[0:-2]) / 2.0
    y = inst['position_ecef_y']
    vel_y = (y.values[2:] - y.values[0:-2]) / 2.0
    z = inst['position_ecef_z']
    vel_z = (z.values[2:] - z.values[0:-2]) / 2.0
    inst[1:-1, ('velocity_ecef_x')] = vel_x
    inst[1:-1, ('velocity_ecef_y')] = vel_y
    inst[1:-1, ('velocity_ecef_z')] = vel_z
    inst.meta['velocity_ecef_x'] = {'units': 'km/s', 'desc':
        'Velocity of satellite ' + 'calculated with respect to ECEF frame.'}
    inst.meta['velocity_ecef_y'] = {'units': 'km/s', 'desc':
        'Velocity of satellite ' + 'calculated with respect to ECEF frame.'}
    inst.meta['velocity_ecef_z'] = {'units': 'km/s', 'desc':
        'Velocity of satellite ' + 'calculated with respect to ECEF frame.'}
    return


def merge_section_dicts(lower, higher):
    """
    Merges the section dictionaries. The values of higher will take
    precedence over the ones of lower. Lower will hold the modified dict in
    the end.

    :param lower:  A section.
    :param higher: A section which values will take precedence over the ones
                   from the other.
    :return:       The merged dict.
    """
    for name in higher:
        if name in lower:
            lower[name].update(higher[name], ignore_defaults=True)
        else:
            lower[name] = higher[name]
    return lower


@classmethod
def encode_data(cls, obj, typedef):
    """Encode an object's data.

        Args:
            obj (object): Object to encode.
            typedef (dict): Type definition that should be used to encode the
                object.

        Returns:
            string: Encoded object.

        """
    mod = obj.__module__
    fun = obj.__name__
    out = '%s:%s' % (mod, fun)
    return out


def _is_unorderable_exception(e: TypeError) ->bool:
    """
    Check if the exception raised is an unorderable exception.

    Parameters
    ----------
    e : Exception or sub-class
        The exception object to check.

    Returns
    -------
    bool
        Whether or not the exception raised is an unorderable exception.
    """
    return "'>' not supported between instances of" in str(e)


def boolean(num):
    """Валидатор для объектов, приводимых к булеву типу"""
    return bool(num)


def get_ethinca_orders():
    """
    Returns the dictionary mapping TaylorF2 PN order names to twice-PN
    orders (powers of v/c)
    """
    ethinca_orders = {'zeroPN': 0, 'onePN': 2, 'onePointFivePN': 3, 'twoPN':
        4, 'twoPointFivePN': 5, 'threePN': 6, 'threePointFivePN': 7}
    return ethinca_orders


def myround(num, base=50):
    """
    Round a number to a nearest number specified by `base`.
    >>> myround(110380, base=50)
    >>> 110400
    :param num: number to round
    :param base: number to which to round to nearest
    :return: rounded number
    """
    return int(base * round(float(num) / base))


def dispose_resources(device):
    """Release internal resources allocated by the object.

    Sometimes you need to provide deterministic resources
    freeing, for example to allow another application to
    talk to the device. As Python does not provide deterministic
    destruction, this function releases all internal resources
    allocated by the device, like device handle and interface
    policy.

    After calling this function, you can continue using the device
    object normally. If the resources will be necessary again, it
    will be allocated automatically.
    """
    device._ctx.dispose(device)


@staticmethod
def _productid_selector(details: dict) ->str:
    """从传入的商品信息中选择数量最多的那一个的ID"""
    if not details:
        return str()
    exchanged = dict(zip(details.values(), details.keys()))
    maxgood = exchanged[max(exchanged)]
    return str(maxgood.id)


def sorted_median(a):
    """Compute the median for a 1-D numpy array that is already sorted

    Parameters
    ----------
    a : numpy.ndarray
        list of values what will be processed.

    Returns
    -------
    med : numpy.float32
        median value
    """
    ll = len(a)
    if ll % 2 == 1:
        med = a[ll // 2]
    else:
        med = 0.5 * (a[ll // 2] + a[ll // 2 - 1])
    return med


def slice2enlist(s, n):
    """Convert a slice object into a list of (new, old) tuples."""
    if isinstance(s, slice):
        return enumerate(range(*s.indices(n)))
    return enumerate(s)


def Windows(Scanner):
    """
    e.g., TeamViewer as a UI client.
    """

    def __init__(self):
        pass


def segment(filenames, format, **options):
    """Segment the given pcap file(s) by one or more thresholds
    (``nbytes``, ``npackets``, ``nseconds``).  New segment filenames
    are determined based on the ``strftime(3)`` ``format`` string
    and the timestamp of the first packet in the file.

    :param filenames: Single filename (string) or list of filenames
    :param format:    Output filename in ``strftime(3)`` format
    :param nbytes:    Rollover after writing N bytes
    :param npackets:  Rollover after writing N packets
    :param nseconds:  Rollover after N seconds have elapsed between
                      the first and last packet timestamp in the file.
    :param dryrun:    Simulate file writes and output log messages.
    """
    output = open(format, rollover=True, **options)
    if isinstance(filenames, str):
        filenames = [filenames]
    for filename in filenames:
        with open(filename, 'r') as stream:
            for header, packet in stream:
                output.write(packet, header)
    output.close()


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


def contains_true(i):
    """Return True if input contains True

    i -- any object that implements __contains__

    Returns True if True is in the input. Both True and 1 count as True.
    Helper function for ConflictMatrix object.
    """
    try:
        if True in i:
            return True
        return False
    except TypeError:
        return False


def describe_reserved_instances_offerings(DryRun=None,
    ReservedInstancesOfferingIds=None, InstanceType=None, AvailabilityZone=
    None, ProductDescription=None, Filters=None, InstanceTenancy=None,
    OfferingType=None, NextToken=None, MaxResults=None, IncludeMarketplace=
    None, MinDuration=None, MaxDuration=None, MaxInstanceCount=None,
    OfferingClass=None):
    """
    Describes Reserved Instance offerings that are available for purchase. With Reserved Instances, you purchase the right to launch instances for a period of time. During that time period, you do not receive insufficient capacity errors, and you pay a lower usage rate than the rate charged for On-Demand instances for the actual time used.
    If you have listed your own Reserved Instances for sale in the Reserved Instance Marketplace, they will be excluded from these results. This is to ensure that you do not purchase your own Reserved Instances.
    For more information, see Reserved Instance Marketplace in the Amazon Elastic Compute Cloud User Guide .
    See also: AWS API Documentation

    :example: response = client.describe_reserved_instances_offerings(
        DryRun=True|False,
        ReservedInstancesOfferingIds=[
            'string',
        ],
        InstanceType='t1.micro'|'t2.nano'|'t2.micro'|'t2.small'|'t2.medium'|'t2.large'|'t2.xlarge'|'t2.2xlarge'|'m1.small'|'m1.medium'|'m1.large'|'m1.xlarge'|'m3.medium'|'m3.large'|'m3.xlarge'|'m3.2xlarge'|'m4.large'|'m4.xlarge'|'m4.2xlarge'|'m4.4xlarge'|'m4.10xlarge'|'m4.16xlarge'|'m2.xlarge'|'m2.2xlarge'|'m2.4xlarge'|'cr1.8xlarge'|'r3.large'|'r3.xlarge'|'r3.2xlarge'|'r3.4xlarge'|'r3.8xlarge'|'r4.large'|'r4.xlarge'|'r4.2xlarge'|'r4.4xlarge'|'r4.8xlarge'|'r4.16xlarge'|'x1.16xlarge'|'x1.32xlarge'|'i2.xlarge'|'i2.2xlarge'|'i2.4xlarge'|'i2.8xlarge'|'i3.large'|'i3.xlarge'|'i3.2xlarge'|'i3.4xlarge'|'i3.8xlarge'|'i3.16xlarge'|'hi1.4xlarge'|'hs1.8xlarge'|'c1.medium'|'c1.xlarge'|'c3.large'|'c3.xlarge'|'c3.2xlarge'|'c3.4xlarge'|'c3.8xlarge'|'c4.large'|'c4.xlarge'|'c4.2xlarge'|'c4.4xlarge'|'c4.8xlarge'|'cc1.4xlarge'|'cc2.8xlarge'|'g2.2xlarge'|'g2.8xlarge'|'cg1.4xlarge'|'p2.xlarge'|'p2.8xlarge'|'p2.16xlarge'|'d2.xlarge'|'d2.2xlarge'|'d2.4xlarge'|'d2.8xlarge'|'f1.2xlarge'|'f1.16xlarge',
        AvailabilityZone='string',
        ProductDescription='Linux/UNIX'|'Linux/UNIX (Amazon VPC)'|'Windows'|'Windows (Amazon VPC)',
        Filters=[
            {
                'Name': 'string',
                'Values': [
                    'string',
                ]
            },
        ],
        InstanceTenancy='default'|'dedicated'|'host',
        OfferingType='Heavy Utilization'|'Medium Utilization'|'Light Utilization'|'No Upfront'|'Partial Upfront'|'All Upfront',
        NextToken='string',
        MaxResults=123,
        IncludeMarketplace=True|False,
        MinDuration=123,
        MaxDuration=123,
        MaxInstanceCount=123,
        OfferingClass='standard'|'convertible'
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type ReservedInstancesOfferingIds: list
    :param ReservedInstancesOfferingIds: One or more Reserved Instances offering IDs.
            (string) --

    :type InstanceType: string
    :param InstanceType: The instance type that the reservation will cover (for example, m1.small ). For more information, see Instance Types in the Amazon Elastic Compute Cloud User Guide .

    :type AvailabilityZone: string
    :param AvailabilityZone: The Availability Zone in which the Reserved Instance can be used.

    :type ProductDescription: string
    :param ProductDescription: The Reserved Instance product platform description. Instances that include (Amazon VPC) in the description are for use with Amazon VPC.

    :type Filters: list
    :param Filters: One or more filters.
            availability-zone - The Availability Zone where the Reserved Instance can be used.
            duration - The duration of the Reserved Instance (for example, one year or three years), in seconds (31536000 | 94608000 ).
            fixed-price - The purchase price of the Reserved Instance (for example, 9800.0).
            instance-type - The instance type that is covered by the reservation.
            marketplace - Set to true to show only Reserved Instance Marketplace offerings. When this filter is not used, which is the default behavior, all offerings from both AWS and the Reserved Instance Marketplace are listed.
            product-description - The Reserved Instance product platform description. Instances that include (Amazon VPC) in the product platform description will only be displayed to EC2-Classic account holders and are for use with Amazon VPC. (Linux/UNIX | Linux/UNIX (Amazon VPC) | SUSE Linux | SUSE Linux (Amazon VPC) | Red Hat Enterprise Linux | Red Hat Enterprise Linux (Amazon VPC) | Windows | Windows (Amazon VPC) | Windows with SQL Server Standard | Windows with SQL Server Standard (Amazon VPC) | Windows with SQL Server Web | Windows with SQL Server Web (Amazon VPC) | Windows with SQL Server Enterprise | Windows with SQL Server Enterprise (Amazon VPC) )
            reserved-instances-offering-id - The Reserved Instances offering ID.
            scope - The scope of the Reserved Instance (Availability Zone or Region ).
            usage-price - The usage price of the Reserved Instance, per hour (for example, 0.84).
            (dict) --A filter name and value pair that is used to return a more specific list of results. Filters can be used to match a set of resources by various criteria, such as tags, attributes, or IDs.
            Name (string) --The name of the filter. Filter names are case-sensitive.
            Values (list) --One or more filter values. Filter values are case-sensitive.
            (string) --

    :type InstanceTenancy: string
    :param InstanceTenancy: The tenancy of the instances covered by the reservation. A Reserved Instance with a tenancy of dedicated is applied to instances that run in a VPC on single-tenant hardware (i.e., Dedicated Instances).
            Important: The host value cannot be used with this parameter. Use the default or dedicated values only.
            Default: default

    :type OfferingType: string
    :param OfferingType: The Reserved Instance offering type. If you are using tools that predate the 2011-11-01 API version, you only have access to the Medium Utilization Reserved Instance offering type.

    :type NextToken: string
    :param NextToken: The token to retrieve the next page of results.

    :type MaxResults: integer
    :param MaxResults: The maximum number of results to return for the request in a single page. The remaining results of the initial request can be seen by sending another request with the returned NextToken value. The maximum is 100.
            Default: 100

    :type IncludeMarketplace: boolean
    :param IncludeMarketplace: Include Reserved Instance Marketplace offerings in the response.

    :type MinDuration: integer
    :param MinDuration: The minimum duration (in seconds) to filter when searching for offerings.
            Default: 2592000 (1 month)

    :type MaxDuration: integer
    :param MaxDuration: The maximum duration (in seconds) to filter when searching for offerings.
            Default: 94608000 (3 years)

    :type MaxInstanceCount: integer
    :param MaxInstanceCount: The maximum number of instances to filter when searching for offerings.
            Default: 20

    :type OfferingClass: string
    :param OfferingClass: The offering class of the Reserved Instance. Can be standard or convertible .

    :rtype: dict
    :return: {
        'ReservedInstancesOfferings': [
            {
                'ReservedInstancesOfferingId': 'string',
                'InstanceType': 't1.micro'|'t2.nano'|'t2.micro'|'t2.small'|'t2.medium'|'t2.large'|'t2.xlarge'|'t2.2xlarge'|'m1.small'|'m1.medium'|'m1.large'|'m1.xlarge'|'m3.medium'|'m3.large'|'m3.xlarge'|'m3.2xlarge'|'m4.large'|'m4.xlarge'|'m4.2xlarge'|'m4.4xlarge'|'m4.10xlarge'|'m4.16xlarge'|'m2.xlarge'|'m2.2xlarge'|'m2.4xlarge'|'cr1.8xlarge'|'r3.large'|'r3.xlarge'|'r3.2xlarge'|'r3.4xlarge'|'r3.8xlarge'|'r4.large'|'r4.xlarge'|'r4.2xlarge'|'r4.4xlarge'|'r4.8xlarge'|'r4.16xlarge'|'x1.16xlarge'|'x1.32xlarge'|'i2.xlarge'|'i2.2xlarge'|'i2.4xlarge'|'i2.8xlarge'|'i3.large'|'i3.xlarge'|'i3.2xlarge'|'i3.4xlarge'|'i3.8xlarge'|'i3.16xlarge'|'hi1.4xlarge'|'hs1.8xlarge'|'c1.medium'|'c1.xlarge'|'c3.large'|'c3.xlarge'|'c3.2xlarge'|'c3.4xlarge'|'c3.8xlarge'|'c4.large'|'c4.xlarge'|'c4.2xlarge'|'c4.4xlarge'|'c4.8xlarge'|'cc1.4xlarge'|'cc2.8xlarge'|'g2.2xlarge'|'g2.8xlarge'|'cg1.4xlarge'|'p2.xlarge'|'p2.8xlarge'|'p2.16xlarge'|'d2.xlarge'|'d2.2xlarge'|'d2.4xlarge'|'d2.8xlarge'|'f1.2xlarge'|'f1.16xlarge',
                'AvailabilityZone': 'string',
                'Duration': 123,
                'UsagePrice': ...,
                'FixedPrice': ...,
                'ProductDescription': 'Linux/UNIX'|'Linux/UNIX (Amazon VPC)'|'Windows'|'Windows (Amazon VPC)',
                'InstanceTenancy': 'default'|'dedicated'|'host',
                'CurrencyCode': 'USD',
                'OfferingType': 'Heavy Utilization'|'Medium Utilization'|'Light Utilization'|'No Upfront'|'Partial Upfront'|'All Upfront',
                'RecurringCharges': [
                    {
                        'Frequency': 'Hourly',
                        'Amount': 123.0
                    },
                ],
                'Marketplace': True|False,
                'PricingDetails': [
                    {
                        'Price': 123.0,
                        'Count': 123
                    },
                ],
                'OfferingClass': 'standard'|'convertible',
                'Scope': 'Availability Zone'|'Region'
            },
        ],
        'NextToken': 'string'
    }

    """
    pass


def __call__(context, request):
    """ render the template/view """


def cat_emoji():
    """
    a silly function used by the article and page generators to add an emoji
    metadata value.
    """
    return '🐱'


def send(fd_or_data, data=None):
    """Puts data into file descriptor.

    * One argument. Data to write into request file descriptor.
    * Two arguments. 1. File descriptor; 2. Data to write.

    :param df_or_data:

    :param data:

    :rtype: bool
    """
    return False


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

    The ".dev0" means dirty.

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


@classmethod
def get_dependants(cls, dist):
    """Yield dependant user packages for a given package name."""
    for package in cls.installed_distributions:
        for requirement_package in package.requires():
            requirement_name = requirement_package.project_name
            if requirement_name.lower() == dist.lower():
                yield package


def context_enabled(raise404=False):
    """
        If syndication is enabled on the context
        """


@classmethod
def create(cls, root, definitions):
    """
        Create an object based on the root tag name.

        @param root: An XML root element.
        @type root: L{Element}
        @param definitions: A definitions object.
        @type definitions: L{Definitions}
        @return: The created object.
        @rtype: L{WObject}

        """
    fn = cls.tags.get(root.name)
    if fn is not None:
        return fn(root, definitions)


def _format_decimal_coords(ra, dec):
    """
    Print *decimal degree* RA/Dec values in an IPAC-parseable form
    """
    return '{0} {1:+}'.format(ra, dec)


@classmethod
def sql_schema(cls, *args, **kwargs):
    """
        Generate the base table schema for the main GlycanRecord table.

        Parameters
        ----------
        inherits: dict
            Metadata extensions to include in the table schema

        Yields
        ------
        str:
            An SQL script block describing the GlycanRecord table. Descendants
            may yield additional statements.
        """
    ext_stmts = []
    meta_map = dict(cls.__column_data_map)
    meta_map.update(kwargs.get('inherits', {}))
    for name, type_transformer in meta_map.items():
        template = '{name} {type}\n'.format(name=name, type=type_transformer[0]
            )
        ext_stmts.append(template)
    ext_def = ', '.join(ext_stmts)
    if len(ext_def) > 0:
        ext_def = ', ' + ext_def
    schema = cls.__table_schema__.format(table_name=cls.table_name)
    schema = schema.replace('/*rest*/', ext_def)
    yield schema


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

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

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


def _check_device(module, device):
    """
    Check if device already exists and the state.
    Args:
        module: Ansible module.
        device: device to be checked.

    Returns: bool, device state

    """
    lsdev_cmd = module.get_bin_path('lsdev', True)
    rc, lsdev_out, err = module.run_command(['%s' % lsdev_cmd, '-C', '-l',
        '%s' % device])
    if rc != 0:
        module.fail_json(msg='Failed to run lsdev', rc=rc, err=err)
    if lsdev_out:
        device_state = lsdev_out.split()[1]
        return True, device_state
    device_state = None
    return False, device_state


def reading_frame_to_offset(reading_frame_at_start_of_sequence):
    """
    Given a reading frame (how many nucleotides into a codon) at the
    start of a cDNA sequence, return the number of nucleotides which need
    to be trimmed to start on a complete codon.

    Parameters
    ----------

    reading_frame_at_start_of_sequence : int

    Returns an int
    """
    if reading_frame_at_start_of_sequence < 0:
        raise ValueError("Reading frame can't be negative: %d" % (
            reading_frame_at_start_of_sequence,))
    elif reading_frame_at_start_of_sequence > 2:
        raise ValueError('Reading frame must be within 0 and 2, not %d' % (
            reading_frame_at_start_of_sequence,))
    return (3 - reading_frame_at_start_of_sequence) % 3


@classmethod
def _put(cls, client, auth, endpoint, flavor, compress, secure, timeout,
    args, callback):
    """Implementation of verb PUT"""
    return cls.__create(endpoint).secure(*cls.__secure(secure)).as_(flavor
        ).auth(client.credentials, method=auth).until(*timeout).compress(
        compress).put(args, callback=callback)


def set_platform_application_attributes(PlatformApplicationArn=None,
    Attributes=None):
    """
    Sets the attributes of the platform application object for the supported push notification services, such as APNS and GCM. For more information, see Using Amazon SNS Mobile Push Notifications . For information on configuring attributes for message delivery status, see Using Amazon SNS Application Attributes for Message Delivery Status .
    See also: AWS API Documentation

    :example: response = client.set_platform_application_attributes(
        PlatformApplicationArn='string',
        Attributes={
            'string': 'string'
        }
    )

    :type PlatformApplicationArn: string
    :param PlatformApplicationArn: [REQUIRED]
            PlatformApplicationArn for SetPlatformApplicationAttributes action.

    :type Attributes: dict
    :param Attributes: [REQUIRED]
            A map of the platform application attributes. Attributes in this map include the following:
            PlatformCredential -- The credential received from the notification service. For APNS/APNS_SANDBOX, PlatformCredential is private key. For GCM, PlatformCredential is 'API key'. For ADM, PlatformCredential is 'client secret'.
            PlatformPrincipal -- The principal received from the notification service. For APNS/APNS_SANDBOX, PlatformPrincipal is SSL certificate. For GCM, PlatformPrincipal is not applicable. For ADM, PlatformPrincipal is 'client id'.
            EventEndpointCreated -- Topic ARN to which EndpointCreated event notifications should be sent.
            EventEndpointDeleted -- Topic ARN to which EndpointDeleted event notifications should be sent.
            EventEndpointUpdated -- Topic ARN to which EndpointUpdate event notifications should be sent.
            EventDeliveryFailure -- Topic ARN to which DeliveryFailure event notifications should be sent upon Direct Publish delivery failure (permanent) to one of the application's endpoints.
            SuccessFeedbackRoleArn -- IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf.
            FailureFeedbackRoleArn -- IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf.
            SuccessFeedbackSampleRate -- Sample rate percentage (0-100) of successfully delivered messages.
            (string) --
            (string) --

    """
    pass


def add_vertex(location: float=(0.0, 0.0)):
    """Add vertex to active spline

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


@classmethod
def get_default(cls):
    """Get the default client options set

        Returns a flag with all the default client options set"""
    flags = 0
    for option in cls.default:
        flags |= option
    return flags


def get_first_tarfile_member(tar_file):
    """
    Returns a file like object of the first member of the given tarfile.

    :param tar_file: The tarfile object to get the first member of
    :type tar_file: tarfile.TarFile

    :return: A file like object containing the data of the first member in the given tarfile

    :raise AssertionError: If the given tar file does not contain members
    """
    member = tar_file.next()
    if member is None:
        raise AssertionError('Given tarfile does not contain a member')
    return tar_file.extractfile(member)


def pre_delete_title(instance, **kwargs):
    """ Update article.languages
    """
    if instance.article.languages:
        languages = instance.article.languages.split(',')
    else:
        languages = []
    if instance.language in languages:
        languages.remove(instance.language)
        instance.article.languages = ','.join(languages)
        instance.article._publisher_keep_state = True
        instance.article.save(no_signals=True)


def get_normal_points(cx, cy, cos_t, sin_t, length):
    """
    For a line passing through (*cx*, *cy*) and having an angle *t*, return
    locations of the two points located along its perpendicular line at the
    distance of *length*.
    """
    if length == 0.0:
        return cx, cy, cx, cy
    cos_t1, sin_t1 = sin_t, -cos_t
    cos_t2, sin_t2 = -sin_t, cos_t
    x1, y1 = length * cos_t1 + cx, length * sin_t1 + cy
    x2, y2 = length * cos_t2 + cx, length * sin_t2 + cy
    return x1, y1, x2, y2


def file_len(fname):
    """
	Function to count number of lines in a file
	"""
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1


def view_all(fit_view: bool=False):
    """View the entire image

    :param fit_view: Fit View, Fit frame to the viewport
    :type fit_view: bool
    """
    pass


def solve(f, M0, e, h):
    """ Newton-Raphson solver for eccentricity anomaly
    from https://stackoverflow.com/questions/20659456/python-implementing-a-numerical-equation-solver-newton-raphson
    Inputs:
        f (function): function to solve (transcendental ecc. anomaly function)
        M0 (float): mean anomaly
        e (float): eccentricity
        h (float): termination criteria for solver
    Returns: nextE (float): converged solution for eccentric anomaly
        Written by Logan Pearce, 2019
    """
    import numpy as np
    if M0 / (1.0 - e) - np.sqrt(6.0 * (1 - e) / e) <= 0:
        E0 = M0 / (1.0 - e)
    else:
        E0 = (6.0 * M0 / e) ** (1.0 / 3.0)
    lastE = E0
    nextE = lastE + 10 * h
    number = 0
    while abs(lastE - nextE) > h and number < 1001:
        new = f(nextE, e, M0)
        lastE = nextE
        nextE = lastE - new / (1.0 - e * np.cos(lastE))
        number = number + 1
        if number >= 1000:
            nextE = float('NaN')
    return nextE


def _is_descriptor(obj):
    """Returns True if obj is a descriptor, False otherwise."""
    return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj,
        '__delete__')


def sequence_termnum(nth, first_term, common_difference):
    """Usage: Find the term number in a sequence"""
    return (nth - first_term) / common_difference + 1


def get_shortest_path_to_point(controller, initial_position, target_position):
    """
    Computes the shortest path to a point from an initial position using an agent controller
    :param controller: agent controller
    :param initial_position: dict(x=float, y=float, z=float) with the desired initial rotation
    :param target_position: dict(x=float, y=float, z=float) representing target position
    :return:
    """
    event = controller.step(action='GetShortestPathToPoint', position=
        initial_position, x=target_position['x'], y=target_position['y'], z
        =target_position['z'])
    if event.metadata['lastActionSuccess']:
        return event.metadata['actionReturn']['corners']
    else:
        raise ValueError("Unable to find shortest path to point '{}'".
            format(target_position))


def rc4(buffer, key):
    """
    Encrypt / decrypt the content of `buffer` using RC4 algorithm.

    Parameters
    ----------
    buffer : bytes
        The bytes sequence to encrypt or decrypt.

    key : bytes
        The key to be used to perform the cryptographic operation.

    Returns
    -------
    A bytes sequence representing the transformed input.

    More information
    ----------------
    Adapted from http://cypherpunks.venona.com/archive/1994/09/msg00304.html
    """
    state = list(range(256))
    x = 0
    y = 0
    index1 = 0
    index2 = 0
    for counter in range(256):
        index2 = (key[index1] + state[counter] + index2) % 256
        state[counter], state[index2] = state[index2], state[counter]
        index1 = (index1 + 1) % len(key)
    output = [0] * len(buffer)
    for i in range(len(buffer)):
        x = (x + 1) % 256
        y = (state[x] + y) % 256
        state[x], state[y] = state[y], state[x]
        xorIndex = (state[x] + state[y]) % 256
        output[i] = buffer[i] ^ state[xorIndex]
    return bytes(output)


def _Underride(d, **options):
    """Add key-value pairs to d only if key is not in d.

    If d is None, create a new dictionary.

    d: dictionary
    options: keyword args to add to d
    """
    if d is None:
        d = {}
    for key, val in options.items():
        d.setdefault(key, val)
    return d


def read_from_input(file_path):
    """File reading helper"""
    f = open(file_path, 'r')
    r = f.read()
    f.close()
    return r


def multi_key_gitlab(value):
    """
    Returns the username, if an exception occurs None is returned.

    Parameters
    ----------
    value: dict
        A dictionary of GitLab.

    Returns
    -------
    value: str or None
        Username or none.
    """
    try:
        return value['owner']['username']
    except (KeyError, TypeError):
        return None


def plot_xsf(el):
    """
    Plots the xray scattering factors for the given element.

    :Parameters:
        *el* : Element

    :Returns: None
    """
    import pylab
    xsf = el.xray.sftable
    pylab.title('X-ray scattering factors for ' + el.name)
    pylab.plot(xsf[0], xsf[1])
    pylab.plot(xsf[0], xsf[2])
    pylab.xlabel('Energy (keV)')
    pylab.ylabel('Scattering factor')
    pylab.legend(['f1', 'f2'])
    pylab.show()


@classmethod
def from_hex(cls, hex_str):
    """Instantiate from a hexadecimal string."""
    return cls(bytes.fromhex(hex_str))


def all_vs_all_pcr(df_boolean, outfile):
    """
    Creates all vs all pcr input to check for off target PCR amplification.
    This function assumes you used the output created from primer_cross_hyb.py
    Args:
        df_boolean (pd.DataFrame): dataframe with removed cross hybridizing primers
    Returns:
        nothing: writes a file output
    """
    no_dimer_df = df_boolean
    all_vs_all = open(outfile, 'w')
    for seqid, primer_left in zip(no_dimer_df['Sequence ID'], no_dimer_df[
        'Primer Left Seq']):
        for primer_right in no_dimer_df['Primer Right Seq']:
            all_vs_all.write(str(seqid) + '\t' + str(primer_left) + '\t' +
                str(primer_right) + '\n')
    for seqid, primer_right in zip(no_dimer_df['Sequence ID'], no_dimer_df[
        'Primer Right Seq']):
        for primer_left in no_dimer_df['Primer Left Seq']:
            all_vs_all.write(str(seqid) + '\t' + str(primer_right) + '\t' +
                str(primer_left) + '\n')
    for seqid, primer_left in zip(no_dimer_df['Sequence ID'], no_dimer_df[
        'Primer Left Seq']):
        for primer_left2 in no_dimer_df['Primer Left Seq']:
            all_vs_all.write(str(seqid) + '\t' + str(primer_left) + '\t' +
                str(primer_left2) + '\n')
    for seqid, primer_right in zip(no_dimer_df['Sequence ID'], no_dimer_df[
        'Primer Right Seq']):
        for primer_right2 in no_dimer_df['Primer Right Seq']:
            all_vs_all.write(str(seqid) + '\t' + str(primer_right) + '\t' +
                str(primer_right2) + '\n')
    all_vs_all.close()


def validate_alpha(char: str) ->bool:
    """
    Checks if a character has its place in a variable name.
    Args:
        char (str): The character to validate.

    Returns:
        Whether or not the character is valid.
    """
    return char.isalpha() or char == '_' or char == '.'


@staticmethod
def _reattach_blank(lines, signal_boundaries=False):
    """
        Reattach blank lines to the preceding non-blank line.

        Initial blank lines are prepended to the first non-
        blank line.

        If signal_boundaries is True, the position of the blank
        lines is signaled through yielding None.
        This boundary is always signaled at the beginning, even
        if there are no leading blank lines.
        """
    last = ''
    for line in lines:
        last += line
        if line.strip():
            break
    if signal_boundaries and last:
        yield None
    boundary = False
    for line in lines:
        if not line.strip():
            boundary = True
            last += line
        else:
            yield last
            last = line
            if signal_boundaries and boundary:
                yield None
                boundary = False
    if last:
        yield last


@classmethod
def _create_bits_by_thousand_rocks(cls, figure, data_by_year, shifts, bits):
    """Bits by thousand rock mass."""
    bit_by_rock = figure.add_subplot(224)
    bits_by_thousand_rocks1 = bits[0] / (data_by_year[shifts[0]].rock_mass /
        1000)
    bits_by_thousand_rocks2 = bits[1] / (data_by_year[shifts[1]].rock_mass /
        1000)
    bit_by_rock.plot(data_by_year[shifts[0]].month, bits_by_thousand_rocks1,
        marker='D', markersize=4)
    bit_by_rock.plot(data_by_year[shifts[1]].month, bits_by_thousand_rocks2,
        marker='D', markersize=4)
    bit_by_rock.legend(['Смена 1', 'Смена 2'])
    bit_by_rock.set_ylabel('коронок / 1000м³ горной массы')
    bit_by_rock.set_xlabel('месяцы')
    bit_by_rock.grid(b=True, linestyle='--', linewidth=0.5)
    bit_by_rock.set_title('Коронок на тысячу кубов горной массы.')


def node_lists_with_cuboids(node_lists_flat):
    """Finds adjacent points in node_lists_flat and converts them to cuboids for data efficiency"""
    node_lists = {}
    for item, v in node_lists_flat.items():
        node_lists[item] = []
        vs = sorted(v)
        while len(vs) > 0:
            start_x, start_y, start_z = vs[0]
            dx, dy, dz = 0, 0, 0
            tfx, tfy, tfz = True, True, True
            while tfx or tfy or tfz:
                if tfx:
                    x = start_x + dx + 1
                    for y in range(start_y, start_y + dy + 1):
                        for z in range(start_z, start_z + dz + 1):
                            if not (x, y, z) in vs:
                                tfx = False
                    if tfx:
                        dx += 1
                if tfy:
                    y = start_y + dy + 1
                    for x in range(start_x, start_x + dx + 1):
                        for z in range(start_z, start_z + dz + 1):
                            if not (x, y, z) in vs:
                                tfy = False
                    if tfy:
                        dy += 1
                if tfz:
                    z = start_z + dz + 1
                    for x in range(start_x, start_x + dx + 1):
                        for y in range(start_y, start_y + dy + 1):
                            if not (x, y, z) in vs:
                                tfz = False
                    if tfz:
                        dz += 1
            if dx == 0 and dy == 0 and dz == 0:
                node_lists[item].append((start_x, start_y, start_z))
            else:
                node_lists[item].append(((start_x, start_y, start_z), (
                    start_x + dx, start_y + dy, start_z + dz)))
            for x in range(start_x, start_x + dx + 1):
                for y in range(start_y, start_y + dy + 1):
                    for z in range(start_z, start_z + dz + 1):
                        vs.remove((x, y, z))
    return node_lists


def write_embedded_list(data_list, save_path, sep=' '):
    """
    将一个嵌套的list写入文本中,一行写入一个list,list的元素使用sep连接
    :return:
    """
    with open(save_path, 'w') as w:
        if data_list is None or len(data_list) == 0:
            return
        for embedded_list in data_list:
            w.write(sep.join(embedded_list))
            w.write('\n')


def get_layer(model, idx):
    """ Returns the layer of the corresponding index of the model."""
    return list(model.children())[idx]


@classmethod
def program_name(cls):
    """Return the name of the program that this main window represents"""
    return 'Clustering'


def ols_formula(df, dependent_var, *excluded_cols):
    """
    Generates the R style formula for statsmodels (patsy) given
    the dataframe, dependent variable and optional excluded columns
    as strings
    """
    df_columns = list(df.columns.values)
    df_columns.remove(dependent_var)
    for col in excluded_cols:
        df_columns.remove(col)
    return dependent_var + ' ~ ' + ' + '.join(df_columns)


def kinetic_energy(be, hv, psi):
    """Calculates the kinetic energy (KE) with a Mg source (Dalhousie default):

    be  : binding energy (BE [eV])
    psi : Work function (Psi [eV])
    hv  : Phonton energy (h*nu [eV])
    """
    return hv - be - psi


def migrate_flags(apps, schema_editor):
    """Update the repo_scope flag."""
    Addon = apps.get_model('addons', 'Addon')
    db_alias = schema_editor.connection.alias
    Addon.objects.using(db_alias).filter(name__in=(
        'weblate.discovery.discovery', 'weblate.git.squash')).update(repo_scope
        =True)
    Addon.objects.using(db_alias).filter(name__in=(
        'weblate.removal.comments', 'weblate.removal.suggestions')).update(
        project_scope=True)


def format_to_str(value, empty_value='--', format_string='%0.2f'):
    """
    Format value with format_string when evaluated as True
    else return the empty value
    """
    if not value:
        return empty_value
    return format_string % value


@classmethod
def create_with_dst_resource_provisioning(cls, cli, src_resource_id,
    dst_resource_config, max_time_out_of_sync, name=None, remote_system=
    None, src_spa_interface=None, src_spb_interface=None, dst_spa_interface
    =None, dst_spb_interface=None, dst_resource_element_configs=None,
    auto_initiate=None, hourly_snap_replication_policy=None,
    daily_snap_replication_policy=None, replicate_existing_snaps=None,
    no_async_snap_replication=None):
    """
        Create a replication session along with destination resource
        provisioning.

        :param cli: the rest cli.
        :param src_resource_id: id of the replication source, could be
            lun/fs/cg.
        :param dst_resource_config: `UnityResourceConfig` object. The user
            chosen config for destination resource provisioning. `pool_id` and
            `size` are required for creation.
        :param max_time_out_of_sync: maximum time to wait before syncing the
            source and destination. Value `-1` means the automatic sync is not
            performed. `0` means it is a sync replication.
        :param name: name of the replication.
        :param remote_system: `UnityRemoteSystem` object. The remote system to
            which the replication is being configured. When not specified, it
            defaults to local system.
        :param src_spa_interface: `UnityRemoteInterface` object. The
            replication interface for source SPA.
        :param src_spb_interface: `UnityRemoteInterface` object. The
            replication interface for source SPB.
        :param dst_spa_interface: `UnityRemoteInterface` object. The
            replication interface for destination SPA.
        :param dst_spb_interface: `UnityRemoteInterface` object. The
            replication interface for destination SPB.
        :param dst_resource_element_configs: List of `UnityResourceConfig`
            objects. The user chose config for each of the member element of
            the destination resource.
        :param auto_initiate: indicates whether to perform the first
            replication sync automatically.
            True - perform the first replication sync automatically.
            False - perform the first replication sync manually.
        :param hourly_snap_replication_policy: `UnitySnapReplicationPolicy`
            object. The policy for replicating hourly scheduled snaps of the
            source resource.
        :param daily_snap_replication_policy: `UnitySnapReplicationPolicy`
            object. The policy for replicating daily scheduled snaps of the
            source resource.
        :param replicate_existing_snaps: indicates whether or not to replicate
            snapshots already existing on the resource.
        :param no_async_snap_replication: whether or not snap replication is
            enabled in asynchronous replication session. When enabled, snap
            replication is controlled by snap replication policy setting or
            user action.
        :return: the newly created replication session.
        """
    req_body = cli.make_body(srcResourceId=src_resource_id,
        dstResourceConfig=dst_resource_config, maxTimeOutOfSync=
        max_time_out_of_sync, name=name, remoteSystem=remote_system,
        srcSPAInterface=src_spa_interface, srcSPBInterface=
        src_spb_interface, dstSPAInterface=dst_spa_interface,
        dstSPBInterface=dst_spb_interface, dstResourceElementConfigs=
        dst_resource_element_configs, autoInitiate=auto_initiate,
        hourlySnapReplicationPolicy=hourly_snap_replication_policy,
        dailySnapReplicationPolicy=daily_snap_replication_policy,
        replicateExistingSnaps=replicate_existing_snaps,
        noAsyncSnapReplication=no_async_snap_replication)
    resp = cli.type_action(cls().resource_class,
        'createReplicationSessionWDestResProvisioning', **req_body)
    resp.raise_if_err()
    session_resp = resp.first_content['id']
    return cls.get(cli, _id=session_resp['id'])


def r_polar(system='wgs84'):
    """ Defines polar radius according to a specific system

        :date: 20.10.2014

        :author: Jalal Matar

        :param system: defines the measurments
          system (iau, krassowsky or wgs84)

        :returns: polar radius
    """
    if system == 'iau':
        r_po = 6356775.0
    elif system == 'krassowski':
        r_po = 6356863.01877
    elif system == 'wgs84':
        r_po = 6356752.31425
    return r_po


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


@classmethod
def specification(cls):
    """
        Should return dict {ns => {code: direction}}. ns and code should be either both strings or
          either both integers. When being declared, cantrips.protocol.messaging.formats.CommandSpec
          should be used, considering the cls.COMMAND_FORMAT value (see the formatted(prop) method).
        """
    raise NotImplementedError


def get_resource_url(resource, href, **kwargs):
    """Return the canonical URL for displaying the given resource.

        :param resource: a `Resource`
        :param href: an `Href` used for creating the URL

        Note that if there's no special rule associated to this realm for
        creating URLs (i.e. the standard convention of using realm/id applies),
        then it's OK to not define this method.
        """


def get_newick_string(source_path, type='nwk'):
    """
    Get the newick tree as string from a newick file, a hdf5 file or from the note tag of an orthoXML
    Args:
        | newick_source: path of the file
        | type: type of file where to fetch the newick tree. Available: "nwk", "h5" and "orthoXML"
    """
    if type == 'nwk':
        with open(source_path, 'r') as nwk_file:
            return nwk_file.read()
    elif type == 'phylip':
        pass
    elif type == 'h5':
        pass
    elif type == 'orthoXML':
        pass


def should_build_with_cython(previous_cython_version, is_release):
    """
    Returns the previously used Cython version (or 'unknown' if not
    previously built) if Cython should be used to build extension modules from
    pyx files.
    """
    have_cython = False
    try:
        from Cython import __version__ as cython_version
        have_cython = True
    except ImportError:
        pass
    if have_cython and (not is_release or previous_cython_version == 'unknown'
        ):
        return cython_version
    else:
        return False


def mesh_split_edge(mesh, u, v, t=0.5, allow_boundary=False):
    """Split and edge by inserting a vertex along its length.

    Parameters
    ----------
    mesh : compas.datastructures.Mesh
        Instance of a mesh.
    u : str
        The key of the first vertex of the edge.
    v : str
        The key of the second vertex of the edge.
    t : float (0.5)
        The position of the inserted vertex.
        The value should be between 0.0 and 1.0
    allow_boundary : bool (False)
        Split edges on the boundary.

    Returns
    -------
    int
        The key of the inserted vertex.

    Raises
    ------
    ValueError
        If u and v are not neighbors.

    """
    if t <= 0.0:
        raise ValueError('t should be greater than 0.0.')
    if t >= 1.0:
        raise ValueError('t should be smaller than 1.0.')
    fkey_uv = mesh.halfedge[u][v]
    fkey_vu = mesh.halfedge[v][u]
    if not allow_boundary:
        if fkey_uv is None or fkey_vu is None:
            return
    x, y, z = mesh.edge_point(u, v, t)
    w = mesh.add_vertex(x=x, y=y, z=z)
    mesh.halfedge[u][w] = fkey_uv
    mesh.halfedge[w][v] = fkey_uv
    del mesh.halfedge[u][v]
    if fkey_uv is not None:
        j = mesh.face[fkey_uv].index(v)
        mesh.face[fkey_uv].insert(j, w)
    mesh.halfedge[v][w] = fkey_vu
    mesh.halfedge[w][u] = fkey_vu
    del mesh.halfedge[v][u]
    if fkey_vu is not None:
        i = mesh.face[fkey_vu].index(u)
        mesh.face[fkey_vu].insert(i, w)
    return w


@staticmethod
def _import_elfi():
    """Import any need libraries needed for this classes opertation. Mainly ELFI"""
    from sys import platform
    if platform == 'darwin':
        import matplotlib
        matplotlib.use('PS')
    import elfi
    return elfi


def ADX(df, n):
    """
    Average Directional Movement Index
    """


def chomp(line):
    """
    Returns a string stripped of its trailing newline character
    """
    assert line[-1] == '\n'
    return line[:-1]


def write_output(port, value):
    """Write a value to a GPIO."""
    import RPi.GPIO as GPIO
    GPIO.output(port, value)


def choice(first_parser, second_parser):
    """Try one parser and try a second one if the first one fails

    This behaves the same way as ``first_parser | second_parser`` would.
    """
    return first_parser | second_parser


def draw_rivers_on_image(world, target, factor=1):
    """Draw only the rivers, it expect the background to be in place
    """
    for y in range(world.height):
        for x in range(world.width):
            if world.is_land((x, y)) and world.river_map[y, x] > 0.0:
                for dx in range(factor):
                    for dy in range(factor):
                        target.set_pixel(x * factor + dx, y * factor + dy,
                            (0, 0, 128, 255))
            if world.is_land((x, y)) and world.lake_map[y, x] != 0:
                for dx in range(factor):
                    for dy in range(factor):
                        target.set_pixel(x * factor + dx, y * factor + dy,
                            (0, 100, 128, 255))


def validate_fillna_kwargs(value, method, validate_scalar_dict_value=True):
    """
    Validate the keyword arguments to 'fillna'.

    This checks that exactly one of 'value' and 'method' is specified.
    If 'method' is specified, this validates that it's a valid method.

    Parameters
    ----------
    value, method : object
        The 'value' and 'method' keyword arguments for 'fillna'.
    validate_scalar_dict_value : bool, default True
        Whether to validate that 'value' is a scalar or dict. Specifically,
        validate that it is not a list or tuple.

    Returns
    -------
    value, method : object
    """
    from pandas.core.missing import clean_fill_method
    if value is None and method is None:
        raise ValueError("Must specify a fill 'value' or 'method'.")
    elif value is None and method is not None:
        method = clean_fill_method(method)
    elif value is not None and method is None:
        if validate_scalar_dict_value and isinstance(value, (list, tuple)):
            raise TypeError(
                f'"value" parameter must be a scalar or dict, but you passed a "{type(value).__name__}"'
                )
    elif value is not None and method is not None:
        raise ValueError("Cannot specify both 'value' and 'method'.")
    return value, method


def arg_byref(args, offset=-1):
    """Return the pointer argument's by-reference value."""
    return args[offset]._obj.value


def djb_hash(s):
    """Return the value of DJB's hash function for byte string *s*"""
    h = 5381
    for c in s:
        h = ((h << 5) + h ^ c) & 4294967295
    return h