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

        :param DeviceLinkSuccessDetails val:
        :rtype: EventDetails
        """
    return cls('device_link_success_details', val)


def clip_path(surface, node):
    """Store a clip path definition."""
    if 'id' in node:
        surface.paths[node['id']] = node


@classmethod
def dict_to_row(cls, observation_data):
    """
        Takes a dictionary of observation data and converts it to a list
        of fields according to AAVSO visual format specification.

        :param cls: current class
        :param observation_data: a single observation as a dictionary
        """
    row = []
    row.append(observation_data['name'])
    row.append(observation_data['date'])
    row.append(observation_data['magnitude'])
    comment_code = observation_data.get('comment_code', 'na')
    if not comment_code:
        comment_code = 'na'
    row.append(comment_code)
    comp1 = observation_data.get('comp1', 'na')
    if not comp1:
        comp1 = 'na'
    row.append(comp1)
    comp2 = observation_data.get('comp2', 'na')
    if not comp2:
        comp2 = 'na'
    row.append(comp2)
    chart = observation_data.get('chart', 'na')
    if not chart:
        chart = 'na'
    row.append(chart)
    notes = observation_data.get('notes', 'na')
    if not notes:
        notes = 'na'
    row.append(notes)
    return row


def get_members():
    """Return a sequence of all members of all mailing lists.

        The members are sorted first by fully-qualified mailing list name,
        then by subscribed email address, then by role.  Because the user may
        be a member of the list under multiple roles (e.g. as an owner and as
        a digest member), the member can appear multiple times in this list.
        Roles are sorted by: owner, moderator, member.

        :return: The list of all members.
        :rtype: list of `IMember`
        """


@staticmethod
def colorize_errors(event, colored):
    """
        Highlights some commonly known Lambda error cases in red:
            - Nodejs process crashes
            - Lambda function timeouts
        """
    nodejs_crash_msg = 'Process exited before completing request'
    timeout_msg = 'Task timed out'
    if nodejs_crash_msg in event.message or timeout_msg in event.message:
        event.message = colored.red(event.message)
    return event


@staticmethod
def ordered_first(nodeset):
    """
        Returns the node ordered earliest in the document from a given nodeset

        :param list[expatriate.Node] nodeset: The nodeset
        :rtype: expatriate.Node
        """
    if len(nodeset) == 0:
        raise ValueError('Cannot determine the first node of an empty nodeset')
    first = nodeset[0]
    for n in nodeset[1:]:
        if n.get_document_order() < first.get_document_order():
            first = n
    return first


def get_util(nodes):
    """ Return a tuple of cpu and memory percent values.
    """
    all_metrics = {'total_cpus_alloc': 0, 'total_cpus_idle': 0,
        'total_cpus_down': 0, 'total_cpus_config': 0, 'total_memory_alloc':
        0, 'total_memory_idle': 0, 'total_memory_down': 0,
        'total_memory_config': 0, 'total_nodes_mixed': 0,
        'total_nodes_alloc': 0, 'total_nodes_idle': 0, 'total_nodes_down':
        0, 'total_nodes_config': 0}
    for node in nodes:
        nodeinfo = nodes.get(node)
        state = nodeinfo.get('state').upper()
        cpus_alloc = nodeinfo.get('alloc_cpus')
        cpus_total = nodeinfo.get('cpus')
        memory_alloc = nodeinfo.get('alloc_mem')
        memory_real = nodeinfo.get('real_memory')
        all_metrics['total_nodes_config'] += 1
        all_metrics['total_cpus_config'] += cpus_total
        all_metrics['total_memory_config'] += memory_real
        if 'DOWN' in state or 'DRAIN' in state:
            all_metrics['total_nodes_down'] += 1
            all_metrics['total_cpus_down'] += cpus_total
            all_metrics['total_memory_down'] += memory_real
        else:
            all_metrics['total_cpus_alloc'] += cpus_alloc
            all_metrics['total_cpus_idle'] += cpus_total - cpus_alloc
            all_metrics['total_memory_alloc'] += memory_alloc
            all_metrics['total_memory_idle'] += memory_real - memory_alloc
            if 'ALLOCATED' in state:
                all_metrics['total_nodes_alloc'] += 1
            elif 'MIXED' in state:
                all_metrics['total_nodes_mixed'] += 1
            elif 'IDLE' in state:
                all_metrics['total_nodes_idle'] += 1
    return all_metrics


def serialize_skycoord(o):
    """
    Serializes an :obj:`astropy.coordinates.SkyCoord`, for JSONification.

    Args:
        o (:obj:`astropy.coordinates.SkyCoord`): :obj:`SkyCoord` to be serialized.

    Returns:
        A dictionary that can be passed to :obj:`json.dumps`.
    """
    representation = o.representation.get_name()
    frame = o.frame.name
    r = o.represent_as('spherical')
    d = dict(_type='astropy.coordinates.SkyCoord', frame=frame,
        representation=representation, lon=r.lon, lat=r.lat)
    if len(o.distance.unit.to_string()):
        d['distance'] = r.distance
    return d


def get_chain_length(ve, orientation):
    """Returns the 2d length of a given ViewEdge."""
    from freestyle.chainingiterators import pyChainSilhouetteGenericIterator
    length = 0.0
    _it = pyChainSilhouetteGenericIterator(False, False)
    _it.begin = ve
    _it.current_edge = ve
    _it.orientation = orientation
    _it.init()
    while not _it.is_end:
        length += _it.object.length_2d
        if _it.is_begin:
            break
        _it.increment()
    _it.begin = ve
    _it.current_edge = ve
    _it.orientation = orientation
    if not _it.is_begin:
        _it.decrement()
        while not (_it.is_end or _it.is_begin):
            length += _it.object.length_2d
            _it.decrement()
    return length


def filtered_words(words, mapping):
    """    Go through a sequence of words. Words occuring in mapping are replaced,
    others are passed on as-is.
    """
    for word in words:
        yield mapping.get(word, word)


def lambd_CO2_SO4_HMW84(T, P):
    """n-a: carbon-dioxide sulfate [HMW84]."""
    lambd = 0.097
    valid = T == 298.15
    return lambd, valid


def sigma_Bird_Stewart_Lightfoot_boiling(Vb):
    """Calculates Lennard-Jones molecular diameter.
    Uses molar volume of liquid at boiling. CSP method by [1]_.

    .. math::
        \\sigma = 1.166V_{b,liq}^{1/3}

    Parameters
    ----------
    Vb : float
        Boiling molar volume of liquid [m^3/mol]

    Returns
    -------
    sigma : float
        Lennard-Jones collision integral, [Angstrom]

    Notes
    -----
    Original units of Vb are mL/mol.

    Examples
    --------
    >>> sigma_Bird_Stewart_Lightfoot_boiling(0.0001015)
    5.439018856944655

    References
    ----------
    .. [1] Bird, R. Byron, Warren E. Stewart, and Edwin N. Lightfoot.
       Transport Phenomena, Revised 2nd Edition. New York:
       John Wiley & Sons, Inc., 2006
    """
    Vb = Vb * 1000000.0
    sigma = 1.166 * Vb ** (1 / 3.0)
    return sigma


def to_int(val):
    """Convert val to int (or raise Exception)

    :param val: value to convert
    :type val:
    :return: int(float(val))
    :rtype: int
    """
    try:
        return int(val)
    except ValueError:
        return int(float(val))


def url_add(url, **kwargs):
    """
    Return the url adding the given section into the url

    examples:
    >>> url_add('http://acme.org/abc', qs='page=4')
    'http://acme.org/abc?page=4'
    >>> url_add('http://acme.org/abc?page=1', qs='name=xyz')
    'http://acme.org/abc?page=1&name=xyz'
    >>> url_add('http://acme.org/abc?a=b&page=1', qs='name=xyz')
    'http://acme.org/abc?a=b&page=1&name=xyz'
    >>> url_add('http://acme.org/abc?a=b', qs=['page=1', 'c=d'])
    'http://acme.org/abc?a=b&page=1&c=d'
    """
    if 'qs' in kwargs:
        qs = kwargs['qs']
        if type(qs) not in (tuple, list):
            qs = [qs]
        if '?' not in url:
            return url + '?' + '&'.join(qs)
        else:
            return url + '&' + '&'.join(qs)
    return url


def dBinaryRochedz(r, D, q, F):
    """
    Computes a derivative of the potential with respect to z.

    @param r:      relative radius vector (3 components)
    @param D:      instantaneous separation
    @param q:      mass ratio
    @param F:      synchronicity parameter
    """
    return -r[2] * (r[0] * r[0] + r[1] * r[1] + r[2] * r[2]) ** -1.5 - q * r[2
        ] * ((r[0] - D) * (r[0] - D) + r[1] * r[1] + r[2] * r[2]) ** -1.5


@classmethod
def get_image_format(cls):
    """
        Return icon format, without dot.

        For example: 'png'.
        """
    return 'png'


def mark_sharp(clear: bool=False, use_verts: bool=False):
    """(Un)mark selected edges as sharp

    :param clear: Clear
    :type clear: bool
    :param use_verts: Vertices, Consider vertices instead of edges to select which edges to (un)tag as sharp
    :type use_verts: bool
    """
    pass


def find(function, list):
    """ Returns the first item in the list for which function(item) is True, None otherwise.
    """
    for item in list:
        if function(item):
            return item


def to_bundle_ingest_dirname(ts):
    """Convert a pandas Timestamp into the name of the directory for the
    ingestion.

    Parameters
    ----------
    ts : pandas.Timestamp
        The time of the ingestions

    Returns
    -------
    name : str
        The name of the directory for this ingestion.
    """
    return ts.isoformat().replace(':', ';')


def dump_response(r, line_break=b'\r\n', encoding='UTF-8'):
    """    Return a byte-string representation of the given response, as for a HTTP
    response.
    """
    output = []
    output.append(r.status.encode('ascii'))
    output.append(line_break)
    for k, v in sorted(r.headers):
        output.append(k.encode('ascii'))
        output.append(b': ')
        output.append(v.encode('ascii'))
        output.append(line_break)
    output.append(line_break)
    output.extend(r.content_iterator)
    s = b''.join(output)
    if encoding:
        return s.decode(encoding)
    return s


def cast_to_dtype(array, dtype):
    """
    Cast the given numpy array to the given dtype and returns the result.
    If the input array dtype is already equal to the given dtype, the input array is returned.

    :param array: a numpy array
    :param dtype: a numpy dtype
    :return: a numpy array
    """
    if array.dtype != dtype:
        array = array.astype(dtype)
    return array


def float_format(number):
    """Format a float to a precision of 3, without zeroes or dots"""
    return ('%.3f' % number).rstrip('0').rstrip('.')


def normalize_file_permissions(st_mode):
    """Normalize the permission bits in the st_mode field from stat to 644/755

    Popular VCSs only track whether a file is executable or not. The exact
    permissions can vary on systems with different umasks. Normalising
    to 644 (non executable) or 755 (executable) makes builds more reproducible.
    """
    new_mode = (st_mode | 420) & ~91
    if st_mode & 64:
        new_mode |= 73
    return new_mode


def decode_response(client_message, to_object=None):
    """ Decode response from client message"""
    parameters = dict(response=None)
    parameters['response'] = client_message.read_bool()
    return parameters


def websocket_recv_nb(request_context=None):
    """Receives data from websocket (non-blocking variant).

    :param request_context:

    :rtype: bytes|str

    :raises IOError: If unable to receive a message.
    """


def par_to_model(dataset, pars):
    """Update model in dataset with a list of free parameters factors"""
    for i, p in enumerate(dataset.models.parameters.free_parameters):
        p.factor = pars[i]


@staticmethod
def normalize_exception(exc):
    """
        Given a SyntaxError from a marker evaluation, normalize the error
        message:
         - Remove indications of filename and line number.
         - Replace platform-specific error messages with standard error
           messages.
        """
    subs = {'unexpected EOF while parsing': 'invalid syntax',
        'parenthesis is never closed': 'invalid syntax'}
    exc.filename = None
    exc.lineno = None
    exc.msg = subs.get(exc.msg, exc.msg)
    return exc


@classmethod
def canEmulateNetworkConditions(cls):
    """Tells whether emulation of network conditions is supported.
        """
    return cls.build_send_payload('canEmulateNetworkConditions', {}
        ), cls.convert_payload({'result': {'class': bool, 'optional': False}})


def data_resolution_and_offset(data):
    """
    >>> data_resolution_and_offset(numpy.array([1.5, 2.5, 3.5]))
    (1.0, 1.0)
    >>> data_resolution_and_offset(numpy.array([5, 3, 1]))
    (-2.0, 6.0)
    """
    res = (data[data.size - 1] - data[0]) / (data.size - 1.0)
    off = data[0] - 0.5 * res
    return res.item(), off.item()


def no_trend(*args, **kwargs):
    """
    Zero trend dummy function.

    Parameters
    ----------
    *args : any
        Ignored arguments.
    **kwargs : any
        Ignored keyword arguments.

    Returns
    -------
    float
        A zero trend given as single float.

    """
    return 0.0


def weakref(callback=None):
    """Return a weakref to the specification

        This method is, regrettably, needed to allow weakrefs to be
        computed to security-proxied specifications.  While the
        zope.interface package does not require zope.security or
        zope.proxy, it has to be able to coexist with it.

        """


def IdealTransformer(a=1.0):
    """Ideal Transformer

    Ports 1 and 2 are the primary.

    Ports 3 and 4 are the secondary.

    The dot is on ports 1 and 3.

    a is the turns ratio specified as (secondary/primary) windings

    @param a float (optional) turns ratio (defaults to 1)
    @return the s-parameter matrix of an ideal transformer
    """
    a = float(a)
    D = a * a + 1.0
    return [[1.0 / D, a * a / D, a / D, -a / D], [a * a / D, 1.0 / D, -a /
        D, a / D], [a / D, -a / D, a * a / D, 1.0 / D], [-a / D, a / D, 1.0 /
        D, a * a / D]]


@staticmethod
def _get_disk_level(lsblk_disk_line):
    """ Helper to parse disk hierarchy returned by 'lsblk' """
    level = 0
    for c in lsblk_disk_line:
        if c in ['`', '|', '-', ' ']:
            level = level + 1
        else:
            break
    return level, lsblk_disk_line[level:]


def process_passphrase(proc, passphrase, double_take=False):
    """
    This will enter the `passphrase` interactively given the pexpect child program, `proc`.
    """
    proc.expect('Enter passphrase:\r\n')
    proc.sendline(passphrase)
    if double_take:
        proc.expect('Repeat the passphrase:\r\n')
        proc.sendline(passphrase)
        proc.expect('\n')


@staticmethod
def _validate_design(ft):
    """ validates design dictionaries for required fields"""
    required_fields = ['id', 'name', 'description', 'metabolites',
        'reactions', 'genes']
    for field in required_fields:
        if field not in ft:
            return False
    return True


@staticmethod
def clear():
    """
        Clear everything on the display.
        """


def fix_trigger_debounce(message_type, msg_tow, numofmsg, debouncetime):
    """
    Rids all false triggers caused by switch debounce

    Parameters
    ----------
    message_type : list
      names of message type
    msg_tow : list
      TOW values of the corresponding messages
    numofmsg : integer
      Count of the number of messages in the list
    debouncetime = integer
      Time in ms of how long to consider a debounce
    """
    prev_trigger_tow = 0
    itt = 0
    while itt < numofmsg:
        if msg_tow[itt] - prev_trigger_tow < debouncetime and message_type[itt
            ] == 'MsgExtEvent':
            msg_tow[itt] = 0
        elif message_type[itt] == 'MsgExtEvent':
            prev_trigger_tow = msg_tow[itt]
        itt += 1
    return


def urijoin(*args):
    """Joins given arguments into a URI.

    Trailing and leading slashes are stripped for each argument.

    This code is based on a Rune Kaagaard's answer on Stack Overflow.
    See http://stackoverflow.com/questions/1793261 for more into. The
    code was licensed as cc by-sa 3.0.

    :params *args: list of arguments to join

    :returns: a URI string
    """
    return '/'.join(map(lambda x: str(x).strip('/'), args))


def _trim(docstring):
    """Return a trimmed docstring.

    Code taken from 'PEP 257 -- Docstring Conventions' article.
    """
    if not docstring:
        return ''
    lines = docstring.expandtabs().splitlines()
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = len(line) - len(stripped)
    trimmed = [lines[0].strip()]
    for line in lines[1:]:
        trimmed.append(line[indent:].rstrip())
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    return '\n'.join(trimmed)


def channels_collapse(all: bool=True):
    """Collapse (i.e. close) all selected expandable animation channels

    :param all: All, Collapse all channels (not just selected ones)
    :type all: bool
    """
    pass


def is_interactive_shell_example_line(func_start_index, py_module_str):
    """
    Get a boolean value of whether the target function is
    docstring of interactive shell string (e.g., `>>> def sample():`).

    Parameters
    ----------
    func_start_index : int
        The index of the string at the start of the function.
    py_module_str : str
        String of target module.

    Returns
    -------
    result_bool : bool
        If the target function is a interactive shell docstring string,
        True will be set.
    """
    pre_str = py_module_str[func_start_index - 20:func_start_index]
    pre_str = pre_str.split('\n')[-1]
    is_in = '>>> ' in pre_str
    if is_in:
        return True
    is_in = '... ' in pre_str
    if is_in:
        return True
    return False


def serial_listen_ports(migrate_data):
    """Returns ports serial from a LibvirtLiveMigrateData"""
    ports = []
    if migrate_data.obj_attr_is_set('serial_listen_ports'):
        ports = migrate_data.serial_listen_ports
    return ports


def new_lcc_datasets_db(basedir):
    """
    This generates an lcc-datasets DB in the basedir.

    """
    from .backend import datasets
    return datasets.sqlite_make_lcc_datasets_db(basedir)


@classmethod
def RegisterPlugins(cls, plugin_classes):
    """Registers analysis plugin classes.

    The analysis plugin classes are identified based on their lower case name.

    Args:
      plugin_classes (list[type]): classes of the analysis plugin.

    Raises:
      KeyError: if an analysis plugin class is already set for the corresponding
          name.
    """
    for plugin_class in plugin_classes:
        cls.RegisterPlugin(plugin_class)


@staticmethod
def _one_fakeret_node(all_edges):
    """
        Pick the first Ijk_FakeRet edge from all_edges, and return the destination node.

        :param list all_edges: A list of networkx.Graph edges with data.
        :return:               The first FakeRet node, or None if nothing is found.
        :rtype:                CFGNode or None
        """
    for _, dst, data in all_edges:
        if data.get('jumpkind', None) == 'Ijk_FakeRet':
            return dst
    return None


@classmethod
def supported(cls, conn):
    """Return whether host based authentication is supported"""
    return conn.host_based_auth_supported()


def add_listener(registry, listener):
    """
    Adds a listener in the registry, if it is not yet in

    :param registry: A registry (a list)
    :param listener: The listener to register
    :return: True if the listener has been added
    """
    if listener is None or listener in registry:
        return False
    registry.append(listener)
    return True


def mem_quiver(datax, datay, ax, cells, p, cmap=None):
    """
    Sets up a quiver plot for membrane vectors with tail at cell centres.

    Parameters
    -----------

    datax, datay    Data vectors defined on membrane midpoints
    cells           Instance of cells module
    p               Instance of parameters module
    ax              Existing figure axis to plot currents on

    Returns
    --------
    mvects             Container for quiver plot
    ax                  Modified axis

    """
    scaleval = p.um * p.wsx * 0.8
    mvects = ax.quiver(cells.cell_centres[:, (0)][cells.mem_to_cells] * p.
        um, cells.cell_centres[:, (1)][cells.mem_to_cells] * p.um, datax *
        cells.R[cells.mem_to_cells] * p.um, datay * cells.R[cells.
        mem_to_cells] * p.um, scale=scaleval, color=p.vcolor, cmap=cmap)
    ax.axis('equal')
    ax.axis([cells.xmin * p.um, cells.xmax * p.um, cells.ymin * p.um, cells
        .ymax * p.um])
    return mvects, ax


def lookup(obj, name):
    """
    Return attribute or item with the given name in collection `obj`.

    :raise LookupError:
      If `obj` has no attribute nor item with the given name.

    This is meant for cases when different versions of an API may
    either return a dictionary (hence, key/``__getitem__``-based
    lookup) or an object/namespace (hence, ``.``/``getattr``-style
    lookup) and you want to handle them in a uniform way.

    The following examples demo it::

      >>> D = {'a':1, 'b':2}
      >>> lookup(D, 'a')
      1
      >>> lookup(D, 'c')
      Traceback (most recent call last):
        ...
      LookupError: Object ... has no attribute nor key named `c`

      >>> class X(object):
      ...   a = 1
      ...   b = 2
      >>> x = X()
      >>> lookup(x, 'a')
      1
      >>> lookup(x, 'c')
      Traceback (most recent call last):
        ...
      LookupError: Object ... has no attribute nor key named `c`
    """
    try:
        return getattr(obj, name)
    except AttributeError:
        pass
    try:
        return obj[name]
    except (KeyError, TypeError):
        pass
    raise LookupError('Object {0} has no attribute nor key named `{1}`'.
        format(obj, name))


@staticmethod
def instrument_help_block_message():
    """Assemble a block of relevant help text to be returned with an invalid request."""
    message = (
        'You must supply either a instrument id (like "/instrumentinfo/<instrument_id>")'
        )
    message += (
        ' or search for one using the form "/instrumentinfo/search/<search_term_1>+<search_term_2>"'
        )
    return message


def na_ratio(ts: 'TimeSeries') ->float:
    """
    Computes the ratio of missing values in percent.

    :param ts: The TimeSeries to check for missing values.
    :return: A float, the percentage of missing values in `ts`.
    """
    return 100 * ts.pd_series().isnull().sum() / len(ts)


@property
def is_switch(G):
    """
        A game is a switch if it's left and right options are numbers, and G_L > G_R.

        Returns
        -------
        number : bool
            Whether G is a switch or not.
        """
    if len(G._left) == len(G._right) == 1:
        G_L = next(iter(G._left))
        G_R = next(iter(G._right))
        if G_L.is_number and G_R.is_number and G_L > G_R:
            return True
    return False


def get_results_for_storage_index(storage_index):
    """Retrive the ICheckResults instance for the given (binary)
        storage index. Raises KeyError if there are no results for that
        storage index."""


def asnumpy(input):
    """Convert the input tensor to numpy array.

    The data is copied.

    Parameters
    ----------
    input : Tensor
        The input tensor.

    Returns
    -------
    numpy.ndarray
        Numpy array.
    """
    pass


@staticmethod
def _single_elem_getter_func(x):
    """
        Method to get the text value of simple XML element that does not contain child nodes.
        """
    return x.text


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


def _get_message(record):
    """Replacement for logging.LogRecord.getMessage
    that uses the new-style string formatting for
    it's messages"""
    msg = str(record.msg)
    args = record.args
    if args:
        if not isinstance(args, tuple):
            args = args,
        msg = msg.format(*args)
    return msg


def primitive_nurbs_surface_sphere_add(radius: float=1.0, view_align: bool=
    False, enter_editmode: bool=False, location: float=(0.0, 0.0, 0.0),
    rotation: float=(0.0, 0.0, 0.0), layers: bool=(False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False, False, False, False, False)):
    """Construct a Nurbs surface Sphere

    :param radius: Radius
    :type radius: float
    :param view_align: Align to View, Align the new object to the view
    :type view_align: bool
    :param enter_editmode: Enter Editmode, Enter editmode when adding this object
    :type enter_editmode: bool
    :param location: Location, Location for the newly added object
    :type location: float
    :param rotation: Rotation, Rotation for the newly added object
    :type rotation: float
    :param layers: Layer
    :type layers: bool
    """
    pass


@staticmethod
def p_annotation_optional_list_optional(p):
    """annotation_optional_list_optional : empty
                                             | annotation_optional_list"""
    p[0] = tuple() if p[1] is None else p[1]


@classmethod
def type_key(cls):
    """ Get the key used to store data type on an instance

        Override this method to use a different name for 'data_type'
        """
    return cls.__type_key


def make_loss(data=None, out=None, name=None, **kwargs):
    """Make your own loss function in network construction.

    This operator accepts a customized loss function symbol as a terminal loss and
    the symbol should be an operator with no backward dependency.
    The output of this function is the gradient of loss with respect to the input data.

    For example, if you are a making a cross entropy loss function. Assume ``out`` is the
    predicted output and ``label`` is the true label, then the cross entropy can be defined as::

      cross_entropy = label * log(out) + (1 - label) * log(1 - out)
      loss = make_loss(cross_entropy)

    We will need to use ``make_loss`` when we are creating our own loss function or we want to
    combine multiple loss functions. Also we may want to stop some variables' gradients
    from backpropagation. See more detail in ``BlockGrad`` or ``stop_gradient``.

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

       - make_loss(default) = default
       - make_loss(row_sparse) = row_sparse

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

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

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

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


def delete(project, version=None):
    """Delete the egg stored for the given project and version. If should
        also delete the project if no versions are left"""


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise `ImportError` if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


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


def write_fasta(trans_groups, wd):
    """
    Writes the translations in `trans_dict` to a fasta_file in `wd`.
    :param trans_groups: dictionary mapping translations to their
    associated GeneIDs
    :param wd: the temporary working directory for phameration
    :return:
    """
    print('Begin writing genes to fasta...')
    fasta = open(f'{wd}/input.fasta', 'w')
    for translation in trans_groups.keys():
        fasta.write(f'>{trans_groups[translation][0]}\n{translation}\n')
    fasta.close()


def iter_slices(string, slice_length):
    """Iterate over slices of a string."""
    pos = 0
    while pos < len(string):
        yield string[pos:pos + slice_length]
        pos += slice_length


def dist_acc(dist, thr=0.5):
    """ Return percentage below threshold while ignoring values with a -1 """
    dist = dist[dist != -1]
    if len(dist) > 0:
        return 1.0 * (dist < thr).sum().item() / len(dist)
    else:
        return -1


def _unary(space, const, name):
    """
    Reduce the domain of variable name to be node-consistent with this
    constraint, i.e. remove those values for the variable that are not
    consistent with the constraint.

    returns True if the domain of name was modified
    """
    if not name in const.vnames:
        return False
    if space.variables[name].discrete:
        values = const.domains[name]
    else:
        values = const.domains[name]
    space.domains[name] = space.domains[name].intersection(values)
    return True


def calculate_band_stats(transmitters):
    """Helper function to provide data and labels for bands associated with
    transmitters provided"""
    band_label = []
    band_data = []
    bands = [{'lower_limit': 0, 'upper_limit': 30000000, 'label': 'HF'}, {
        'lower_limit': 30000000, 'upper_limit': 300000000, 'label': 'VHF'},
        {'lower_limit': 300000000, 'upper_limit': 1000000000, 'label':
        'UHF'}, {'lower_limit': 1000000000, 'upper_limit': 2000000000,
        'label': 'L'}, {'lower_limit': 2000000000, 'upper_limit':
        4000000000, 'label': 'S'}, {'lower_limit': 4000000000,
        'upper_limit': 8000000000, 'label': 'C'}, {'lower_limit':
        8000000000, 'upper_limit': 12000000000, 'label': 'X'}, {
        'lower_limit': 12000000000, 'upper_limit': 18000000000, 'label':
        'Ku'}, {'lower_limit': 18000000000, 'upper_limit': 27000000000,
        'label': 'K'}, {'lower_limit': 27000000000, 'upper_limit':
        40000000000, 'label': 'Ka'}]
    for band in bands:
        filtered = transmitters.filter(downlink_low__gte=band['lower_limit'
            ], downlink_low__lt=band['upper_limit']).count()
        band_label.append(band['label'])
        band_data.append(filtered)
    band_data_sorted, band_label_sorted = list(zip(*sorted(zip(band_data,
        band_label), reverse=True)))
    return band_label_sorted, band_data_sorted


def sign_bit(p1):
    """Return the signedness of a point p1"""
    return p1[1] % 2 if p1 else 0


@staticmethod
def level_matches(level, consumer_level):
    """
        >>> l = Logger([])
        >>> l.level_matches(3, 4)
        False
        >>> l.level_matches(3, 2)
        True
        >>> l.level_matches(slice(None, 3), 3)
        False
        >>> l.level_matches(slice(None, 3), 2)
        True
        >>> l.level_matches(slice(1, 3), 1)
        True
        >>> l.level_matches(slice(2, 3), 1)
        False
        """
    if isinstance(level, slice):
        start, stop = level.start, level.stop
        if start is not None and start > consumer_level:
            return False
        if stop is not None and stop <= consumer_level:
            return False
        return True
    else:
        return level >= consumer_level


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


def quadts(ctx, *args, **kwargs):
    """
        Performs tanh-sinh quadrature. The call

            quadts(func, *points, ...)

        is simply a shortcut for:

            quad(func, *points, ..., method=TanhSinh)

        For example, a single integral and a double integral:

            quadts(lambda x: exp(cos(x)), [0, 1])
            quadts(lambda x, y: exp(cos(x+y)), [0, 1], [0, 1])

        See the documentation for quad for information about how points
        arguments and keyword arguments are parsed.

        See documentation for TanhSinh for algorithmic information about
        tanh-sinh quadrature.
        """
    kwargs['method'] = 'tanh-sinh'
    return ctx.quad(*args, **kwargs)


def get_sequence(df, target_col, seq_len, dropna=True):
    """
    Create a shifted sequence for time series data
    The input dataframe should have date / sequence id as index and the time series as column

    == Arguments ==
    df: pd.DataFrame
        time series in dataframe format

    target_col: string
        column name of the time series

    seq_len: int
        how many shifted sequence to generate

    dropna: bool
        remove missing value using df.dropna()
    """
    df_new = df.copy()
    if dropna:
        df_new.dropna(inplace=True)
    cols = df_new.columns
    for i in range(seq_len - 1, 0, -1):
        for col in cols:
            df_new[f'{col}_t-{i}'] = df_new[col].shift(i)
    for col in cols:
        df_new[f'{col}_t+0'] = df_new[col]
    df_new['target'] = df_new[target_col].shift(-1)
    df_new.drop(columns=cols, inplace=True)
    df_new.dropna(inplace=True)
    return df_new


def is_hitachi(dicom_input):
    """
    Use this function to detect if a dicom series is a hitachi dataset

    :param dicom_input: directory with dicom files for 1 scan of a dicom_header
    """
    header = dicom_input[0]
    if 'Manufacturer' not in header or 'Modality' not in header:
        return False
    if header.Modality.upper() != 'MR':
        return False
    if 'HITACHI' not in header.Manufacturer.upper():
        return False
    return True


@staticmethod
def near(lat, lng, max_dist=None, unit_miles=False):
    """Find document near a point.

        For example:: find all document with in 25 miles radius from 32.0, -73.0.
        """
    filters = {'$nearSphere': {'$geometry': {'type': 'Point', 'coordinates':
        [lng, lat]}}}
    if max_dist:
        if unit_miles:
            max_dist = max_dist / 1609.344
        filters['$nearSphere']['$maxDistance'] = max_dist
    return filters


@staticmethod
def load_from_dict(d):
    """
        Creates a Rule from the dictionary generated by to_dict function
        :param d: a dictionary containing all slot of the Rule
        :return: a Rule object
        """
    output = eval(d['type'])()
    for slot in output.__slots__:
        output.__setattr__(slot, d[slot])
    return output


def select_input(rows, desc=None, initial=None):
    """
    Creates html select elements from the sequence 'rows', with an initial value of
    ``initial`` if it is not None and some options description to the element if 'desc'
    is not none
    """
    _l_attrib_str = []
    for k in desc.keys():
        _l_attrib_str.extend([' ', k, "='", desc[k], "'"])
    attrib_str = ''.join(_l_attrib_str)
    options_str = []
    for row in rows:
        opt_template, prefx = "<option value='{0}'{1}>{0}</option>", ''
        if initial is not None and initial == row[0]:
            prefx = " selected='selected'"
        options_str.append(opt_template.format(row[0], prefx))
    return '<select{0}>{1}</select>'.format(attrib_str, ''.join(options_str))


@classmethod
def get_length(cls):
    """Return the number of fields in this type of packet"""
    return len(cls.__cls_fields)


@classmethod
def id2url(cls, _id):
    """Overloaded in child classes provided by backends."""
    raise NotImplementedError()


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


def invite():
    """ Send invitation to attendees retrieved by the enumerator.
        """


@classmethod
def find(cls, db, name):
    """Find a group by name.
        Returns None if not found.
        """
    return db.query(cls).filter(cls.name == name).first()


def quote(path):
    """ Return a path with quotes added if it contains spaces.  path is the
    path.
    """
    if ' ' in path:
        path = '"%s"' % path
    return path


def _read_in_chunks(file_object, chunk_size=1024):
    """Lazy function (generator) to read a file piece by piece.
    Default chunk size: 1k."""
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data


def getLocalTime(utc_dt, tz):
    """Return local timezone time
    """
    import pytz
    local_tz = pytz.timezone(tz)
    local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
    return local_dt


def _is_sequence(arg):
    """Return True if the argument is a sequence (but not a string)"""
    return not hasattr(arg, 'strip') and (hasattr(arg, '__getitem__') or
        hasattr(arg, '__iter__'))


def properties():
    """Toggle the properties region visibility

    """
    pass


@classmethod
def id_field_name(cls):
    """
        If only one primary_key, then return it. Otherwise, raise ValueError.

        :rtype: str
        """
    if cls._cache_id_field_name is None:
        pk_names = cls.pk_names()
        if len(pk_names) == 1:
            cls._cache_id_field_name = pk_names[0]
        else:
            raise ValueError('{classname} has more than 1 primary key!'.
                format(classname=cls.__name__))
    return cls._cache_id_field_name


def get_querystring_fields(serializer, arg_name):
    """
    Gets a list of fields from the querystring that exist in the serializer

    """
    if 'request' in serializer.context:
        fields = serializer.context['request'].query_params.get(arg_name, None)
        if fields:
            fields = fields.split(',')
            allowed = set(fields)
            existing = set(serializer.fields.keys())
            return allowed & existing
    return None


def describe_log_groups(logGroupNamePrefix=None, nextToken=None, limit=None):
    """
    Lists the specified log groups. You can list all your log groups or filter the results by prefix. The results are ASCII-sorted by log group name.
    See also: AWS API Documentation

    :example: response = client.describe_log_groups(
        logGroupNamePrefix='string',
        nextToken='string',
        limit=123
    )

    :type logGroupNamePrefix: string
    :param logGroupNamePrefix: The prefix to match.

    :type nextToken: string
    :param nextToken: The token for the next set of items to return. (You received this token from a previous call.)

    :type limit: integer
    :param limit: The maximum number of items returned. If you don't specify a value, the default is up to 50 items.

    :rtype: dict
    :return: {
        'logGroups': [
            {
                'logGroupName': 'string',
                'creationTime': 123,
                'retentionInDays': 123,
                'metricFilterCount': 123,
                'arn': 'string',
                'storedBytes': 123
            },
        ],
        'nextToken': 'string'
    }

    """
    pass


def get_scale_properties():
    """Returns the scale defined in configuration registry"""


def _disables_array_ufunc(obj):
    """True when __array_ufunc__ is set to None."""
    try:
        return obj.__array_ufunc__ is None
    except AttributeError:
        return False


def uniform_draw_feat_class(data_df, target_name, draw_size):
    """ Sample out 1 particular class out of the full data uniformly in a predefined sample size,
    segregate pandas dataframe into their respective target classes. """
    target_class_dfs = {}
    n_classes = data_df[target_name].unique()
    for unique_class in n_classes:
        class_i_df = data_df[data_df[target_name] == unique_class]
        class_i_df = class_i_df.reset_index().drop(columns=['index'])
        target_class_dfs[unique_class] = class_i_df
    uniform_class_sample_draws = {}
    for unique_class in n_classes:
        unif_samples = target_class_dfs[unique_class].sample(n=draw_size,
            replace=True)
        uniform_class_sample_draws[unique_class] = unif_samples
    return uniform_class_sample_draws


def get_access_token_from_request(request):
    """Helper function to obtain the OIDC AT from the flask request variable"""
    token = None
    try:
        if 'Authorization' in request.headers and request.headers[
            'Authorization'].startswith('Bearer '):
            temp = request.headers['Authorization'].split(
                'authorization header: ')[0]
            token = temp.split(' ')[1]
        elif 'access_token' in request.form:
            token = request.form['access_token']
        elif 'access_token' in request.args:
            token = request.args['access_token']
        return token
    except AttributeError:
        return None


def bind(object):
    """Return a copy of this field which is bound to context.

        The copy of the Field will have the 'context' attribute set
        to 'object'.  This way a Field can implement more complex
        checks involving the object's location/environment.

        Many fields don't need to be bound. Only fields that condition
        validation or properties on an object containing the field
        need to be bound.
        """


@staticmethod
def make_rating_manually(block, q_rate):
    """
        Returns q_rate if the block is not rated manually.

        Parameters
        ----------
        q_rate : float
            The rate to be returned
        block
            Block for which the rate is returned

        Returns
        -------
        rate
            Return q_rate if the block is not manually rated.
            If it is rated manually return 'Manually rated'

        """
    rate = None
    if block.is_manually_rated:
        rate = 'Manually Rated'
    else:
        rate = q_rate
    return rate


def _get_func_code(obj):
    """Get funcion code."""
    return obj.__code__


@staticmethod
def time_from_ms(ms):
    """
        Converts milliseconds into a mm:ss formatted string.

        Arguments:
        ms: Number of milliseconds.

        Returns: String-formatted time period in mm:ss.
        """
    ms = int(ms)
    minutes = str(ms // 60000).zfill(2)
    seconds = str(ms // 1000 % 60).zfill(2)
    return '%s:%s' % (minutes, seconds)


@staticmethod
def _from_db_object(obj, db_obj):
    """Converts a database entity to a formal object.

        :param obj: An object of the class.
        :param db_obj: A DB model of the object
        :return: The object of the class with the database entity added
        """
    for field in obj.fields:
        obj[field] = db_obj[field]
    obj.obj_reset_changes()
    return obj


def reset_default_theme():
    """Reset to the default theme colors

    """
    pass


@staticmethod
def get_values(data):
    """Return median of bernoulli distributed layer
        calculated from expected values. """
    return (data > 0.5).astype(float)


def read_pts(filename):
    """A helper function to read the 68 ibug landmarks from a .pts file."""
    with open(filename) as f:
        lines = f.read().splitlines()
    lines = lines[3:71]
    shapes = []
    ibug_index = 1
    for l in lines:
        coords = l.split()
        shapes.append([float(coords[0]), float(coords[1])])
    return shapes


@staticmethod
def addable_cells(obj):
    """
        No cell should be added in isolation
        except for linear graphs

        TESTS ::

            sage: from sage.graphs.generators.basic import GridGraph
            sage: from sage_widget_adapters.graphs.graph_grid_view_adapter import GraphGridViewAdapter
            sage: g = GridGraph((2,3))
            sage: GraphGridViewAdapter.addable_cells(g)
            []
            sage: g = GridGraph((1,3))
            sage: GraphGridViewAdapter.addable_cells(g)
            [(0, 3)]
        """
    if not obj.num_verts():
        return [(0, 0)]
    row_max, col_max = 0, 0
    for t in obj.vertex_iterator():
        row_max = max(row_max, t[0])
        col_max = max(col_max, t[1])
        if row_max > 0 and col_max > 0:
            return []
    if row_max > 0:
        return [(row_max + 1, 0)]
    elif col_max > 0:
        return [(0, col_max + 1)]
    return [(0, 1), (1, 0)]


def filter_out_hydrogens(mol):
    """Get indices for non-hydrogen atoms.

    Parameters
    ----------
    mol : rdkit.Chem.rdchem.Mol
        RDKit molecule instance.

    Returns
    -------
    indices_left : list of int
        Indices of non-hydrogen atoms.
    """
    indices_left = []
    for i, atom in enumerate(mol.GetAtoms()):
        atomic_num = atom.GetAtomicNum()
        if atomic_num != 1:
            indices_left.append(i)
    return indices_left


@classmethod
def new(cls, **kwargs):
    """Create a new instance of this resource.

        When creating the instance set the ``_synchronized`` parameter
        of :class:`Resource` to ``False`` to indicate that the resource does
        not yet exist on the server side. This marks all attributes passed
        in ``**kwargs`` as "dirty" on the resource, and thusly tracked
        as necessary in subsequent calls such as :meth:`update`.

        :param dict kwargs: Each of the named arguments will be set as
                            attributes on the resulting Resource object.
        """
    return cls(_synchronized=False, **kwargs)


def strip_figures(figure):
    """
	Strips a figure into multiple figures with a trace on each of them

	Parameters:
	-----------
		figure : Figure
			Plotly Figure
	"""
    fig = []
    for trace in figure['data']:
        fig.append(dict(data=[trace], layout=figure['layout']))
    return fig


def _thread_done(gt, *args, **kwargs):
    """Callback function to be passed to GreenThread.link() when we spawn()
    Calls the :class:`ThreadGroup` to notify if.

    """
    kwargs['group'].thread_done(kwargs['thread'])


def reformat_language_tuple(langval):
    """Produce standardly-formatted language specification string using given language tuple.

    :param langval: `tuple` in form ('<language>', '<language variant>'). Example: ('en', 'US')
    :return: `string` formatted in form '<language>-<language-variant>'
    """
    if langval:
        langval_base, langval_variant = langval
        if langval_variant:
            langval_base = '{0}-{1}'.format(langval_base, langval_variant)
        return langval_base
    else:
        return None


def parse_host_port(hp, default_port=0):
    """
    Parse host/port from string

    Doesn't work with IPv6

    Args:
        hp: host/port string to parse
        default_port: default port if no port is specified (default: 0)

    Returns:
        tuple (host, port)
    """
    if hp.find(':') == -1:
        return hp, default_port
    else:
        host, port = hp.rsplit(':', 1)
        return host, int(port)


def _keys(true, false, default):
    """
    Format keys used for yes/no with the default in upper case

    eg with default=False and y/n for the keys, this should return '[y/N]'
    """
    true = default and true.upper() or true.lower()
    false = not default and false.upper() or false.lower()
    return ' [{}/{}]'.format(true, false)


def __call__(value, system):
    """ Call the renderer with the result of the
        view (``value``) passed in and return a result (a string or
        unicode object useful as a response body).  Values computed by
        the system are passed by the system in the ``system``
        parameter, which is a dictionary.  Keys in the dictionary
        include: ``view`` (the view callable that returned the value),
        ``renderer_name`` (the template name or simple name of the
        renderer), ``context`` (the context object passed to the
        view), and ``request`` (the request object passed to the
        view)."""


def callWhenRunning(callable, *args, **kw):
    """
        Call a function when the reactor is running.

        If the reactor has not started, the callable will be scheduled
        to run when it does start. Otherwise, the callable will be invoked
        immediately.

        @param callable: the callable object to call later.

        @param args: the arguments to call it with.

        @param kw: the keyword arguments to call it with.

        @return: None if the callable was invoked, otherwise a system
                 event id for the scheduled call.
        """


def do_OP_EQUAL(vm):
    """
    >>> s = [b'string1', b'string1']
    >>> do_OP_EQUAL(s)
    >>> print(s == [b''])
    True
    >>> s = [b'string1', b'string2']
    >>> do_OP_EQUAL(s)
    >>> print(s == [b''])
    True
    """
    v1, v2 = [vm.pop() for i in range(2)]
    vm.append(vm.bool_to_script_bytes(v1 == v2))


@classmethod
def from_unicode(cls, source, text_encoding='auto', bytes_encoding='auto'):
    """ The from_unicode() constructor is called to encode a source
            string into a PdfString that is suitable for inclusion in a PDF.

            NOTE:  There is no magic in the encoding process.  A user
            can certainly do his own encoding, and simply initialize a
            PdfString() instance with his encoded string.  That may be
            useful, for example, to add line breaks to make it easier
            to load PDFs into editors, or to not bother to escape balanced
            parentheses, or to escape additional characters to make a PDF
            more readable in a file editor.  Those are features not
            supported by this method.

            from_unicode() can use a heuristic to figure out the best
            encoding for the string, or the user can control the process
            by changing the text_encoding parameter to 'pdfdocencoding'
            or 'utf16', and/or by changing the bytes_encoding parameter
            to 'literal' or 'hex' to force particular conversion methods.

            The function will raise an exception if it cannot perform
            the conversion as requested by the user.
        """
    if text_encoding != 'utf16':
        force_pdfdoc = text_encoding == 'pdfdocencoding'
        if text_encoding != 'auto' and not force_pdfdoc:
            raise ValueError('Invalid text_encoding value: %s' % text_encoding)
        if source.startswith(cls.bad_pdfdoc_prefix):
            if force_pdfdoc:
                raise UnicodeError(
                    'Prefix of string %r cannot be encoded in pdfdocencoding' %
                    source[:20])
        else:
            try:
                raw = source.encode('pdfdocencoding')
            except UnicodeError:
                if force_pdfdoc:
                    raise
            else:
                return cls.from_bytes(raw, bytes_encoding)
    raw = cls.bytes_bom + source.encode('utf-16-be')
    encoding = 'hex' if bytes_encoding == 'auto' else bytes_encoding
    return cls.from_bytes(raw, encoding)


def compress_pubkey(pubkey: bytes) ->bytes:
    """Take a an uncompressed pubkey, return the compressed representation"""
    pub = pubkey[1:] if len(pubkey) == 65 else pubkey
    parity = (pub[-1] & 1) + 2
    compressed = bytes([parity]) + pub[:32]
    return compressed


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

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

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


def quote_split(sep, string):
    """
    Splits the strings into pieces divided by sep, when sep in not inside quotes.
    """
    if len(sep) != 1:
        raise Exception('Separation string must be one character long')
    retlist = []
    squote = False
    dquote = False
    left = 0
    i = 0
    while i < len(string):
        if string[i] == '"' and not dquote:
            if not squote:
                squote = True
            elif i + 1 < len(string) and string[i + 1] == '"':
                i += 1
            else:
                squote = False
        elif string[i] == "'" and not squote:
            if not dquote:
                dquote = True
            elif i + 1 < len(string) and string[i + 1] == "'":
                i += 1
            else:
                dquote = False
        elif string[i] == sep and not dquote and not squote:
            retlist.append(string[left:i])
            left = i + 1
        i += 1
    retlist.append(string[left:])
    return retlist


def writable(path):
    """Return boolean indicating whether a file at path is writable.

        Note that a true value should be returned if the file doesn't
        exist but its directory is writable.

        """


@classmethod
def output(cls, file_desc):
    """
        Output all message to the given file handler.
        The heap is unaltered, see clear()
        """
    for message, level, _ in cls.__pending_messages:
        print(level, ':', message, file=file_desc)


def pseudocoral(lat, lon, sst, sss=None, d18O=None, species='default', b1=
    0.3007062, b2=0.2619054, b3=0.436509, b4=0.1552032, b5=0.15):
    """
    DOCSTRING: Function 'pseudocoral' produces a d18O-coral record given SST, SSS, and global position.
       The function is based on the forward model published by [Thompson, 2011]:
       <Thompson, D. M., T. R. Ault, M. N. Evans, J. E. Cole, and J. Emile-Geay (2011),
       Comparison of observed and simulated tropical climate trends using a forward
       model of coral δ18O, Geophys.Res.Lett., 38, L14706, doi:10.1029/2011GL048224.>
       Returns a numpy array that is the same size and shape as the input vectors for SST, SSS.

    Input parameters:
        Latitude    [lat]       [-90, 90]
        Longitude   [lon]       [0, 360]
        SST         [SST]       SST ANOMALY Units = degrees Celsius
        SSS         [SSS]       SSS ANOMALY Units = PSU
        Please note that input files must be read in as 1-D vectors.

    Output:
        Returns a Numpy Array, ['coral'], which is saved in the main program.
        Optional Inputs: Please note that the function will use default params for
        d18O vs. SSS, a, and b unless specified and placed in the appropriate location as shown below.
        delta_18O [permil]: If the user does not have an input field for d18O, you must put -1 in its
        position in the call and use the equation for SSS below.
        **Note: [always use d18O (seawater) if available!]**
        The user may specify values for parameters a and b in the coral d18O forward model,
        which are currently set to the following default values:
        a = coral - SST regression, accounting for species-dependent variations in the SST-18O dependence.
        The code assigns this value universally at -.22, but published values vary by species/genus (i.e. Moses, 2006)
        Specify keyword input 'species=' to set slope:
        species =
                "Default":      a = -0.22
                "Porites_sp":   a = -.26178
                "Porites_lob":  a = -.19646
                "Porites_lut":  a = -.17391
                "Porites_aus":  a = -.21
                "Montast":      a = -.22124
                "Diploas":      a = -.14992
        b = d18O-SSS slope, as defined by location in: Legrande & Schmidt, (2006)
                <LeGrande, A. N., and G. A. Schmidt (2006), Global gridded data set of the oxygen isotopic          composition in seawater, Geophys. Res. Lett., 33, L12604, doi:10.1029/2006GL026011.>
                b1 = 0.31   [Red Sea]
                b2 = 0.27   [Tropical Pacific]
                b3 = 0.45   [South Pacific]
                b4 = 0.16   [Indian Ocean]
                b5 = 0.15   [Tropical Atlantic Ocean/Caribbean]
    Example of use: Call function 'pseudocoral' to calculate d18O_coral timeseries, lacking d18O sw
    but specifying own numeric parameters for a, b.
    pseudocoral(lat,lon,SST,SSS,-1,species="default",b1,b2,b3,b4,b5)
    """
    if species == 'Porites_sp':
        a = -0.26178
    elif species == 'Porites_lob':
        a = -0.19646
    elif species == 'Porites_lut':
        a = -0.17391
    elif species == 'Porites_aus':
        a = -0.21
    elif species == 'Montast':
        a = -0.22124
    elif species == 'Diploas':
        a = -0.14992
    elif species == 'default':
        a = -0.22
    else:
        a = -0.22
    V_corr = 0.97002
    slope1 = V_corr * b1
    slope2 = V_corr * b2
    slope3 = V_corr * b3
    slope4 = V_corr * b4
    slope5 = V_corr * b5
    if lon >= 32.83 and lon <= 43.5 and lat >= 12.38 and lat <= 28.5:
        b = slope1
    elif lon <= 120.0:
        b = slope4
    elif lon >= 270.0 and lat >= 10.0:
        b = slope5
    elif lat > -5.0 and lat <= 13.0:
        b = slope2
    elif lat <= -5.0:
        b = slope3
    else:
        b = slope2
    if d18O is None:
        coral = a * sst + b * sss
    else:
        coral = a * sst + 0.97002 * d18O
    return coral


def partial_sum(x):
    """ Returns an iterator over the partial sums in a given iterable.

		# Arguments

		x: iterable. The iterable to return partial sums for.

		# Return value

		At each iteration, yields the most recent partial sum, beginning with
		`x[0]`.
	"""
    result = 0
    for i in x:
        result += i
        yield result


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

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

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

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

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

    """
    pass


def repack_fileheader(dic):
    """
    Repack blockheader dic bit flag parameters into status and mode.
    """
    dic['status'] = dic['S_DATA'] * 1 + dic['S_SPEC'] * 2 + dic['S_32'
        ] * 4 + dic['S_FLOAT'] * 8 + dic['S_COMPLEX'] * 16 + dic[
        'S_HYPERCOMPLEX'] * 32 + dic['S_ACQPAR'] * 128 + dic['S_SECND'
        ] * 256 + dic['S_TRANSF'] * 512 + dic['S_NP'] * 2048 + dic['S_NF'
        ] * 4096 + dic['S_NI'] * 8192 + dic['S_NI2'] * 16384
    return dic


def difference(image1, image2):
    """
    Returns the absolute value of the pixel-by-pixel difference between the two
    images.

    .. code-block:: python

        out = abs(image1 - image2)

    :rtype: :py:class:`~PIL.Image.Image`
    """
    image1.load()
    image2.load()
    return image1._new(image1.im.chop_difference(image2.im))


def setValveState(*args):
    """Access and changes protected valve state class data. The returned value representation is a 1 by 11 integer numpy array. This approach is a secure method to access and change saved system valve state values.

    Parameters
    ----------
    valve_state : int numby array
        Values for valve state range from 0 for 'Safe' to 1 for 'Active'.
    valve : str
        Set strings range from 'a-k' for each test stand valve.
    value : int
        Set valve values from 0 for 'Safe' to 1 for 'Active'.

    Returns
    -------
    valve_state : int numpy array
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] = 'Safe' system valve state.
    """
    if args[1] == 'a':
        args[0].valve_a = args[2]
    elif args[1] == 'b':
        args[0].valve_b = args[2]
    elif args[1] == 'c':
        args[0].valve_c = args[2]
    elif args[1] == 'd':
        args[0].valve_c = args[2]
    elif args[1] == 'e':
        args[0].valve_e = args[2]
    elif args[1] == 'f':
        args[0].valve_f = args[2]
    elif args[1] == 'g':
        args[0].valve_g = args[2]
    elif args[1] == 'h':
        args[0].valve_h = args[2]
    elif args[1] == 'i':
        args[0].valve_i = args[2]
    elif args[1] == 'j':
        args[0].valve_j = args[2]
    elif args[1] == 'k':
        args[0].valve_k = args[2]
    return args[0]


def check_qt(target_config):
    """ Check the Qt installation.  target_config is the target configuration.
    """
    if target_config.qmake_spec == 'win32-g++':
        target_config.qmake_variables.append('QMAKE_CFLAGS += -mstackrealign')
        target_config.qmake_variables.append('QMAKE_CXXFLAGS += -mstackrealign'
            )


@staticmethod
def logging_disabled(*args, **kwargs):
    """Use this instead of self.log to indicate that logging is not
        currently active.
        """
    raise Exception('Logging is currently disabled!')


def p_track_index(t):
    """track_flag : INDEX TIMESTAMP"""
    from audiotools.toc import TOCFlag_INDEX
    from fractions import Fraction
    t[0] = TOCFlag_INDEX(Fraction(t[2], 75))


def get_index(i, j, k, N1, N2=None, N0=None):
    """Gets 1D index from 3D indices. Assumes row-major ordering. WARNING: N0 is passed last when all of N0,N1,N2 are specified!

    Parameters
    ----------
    i : int
        3D index x
    j : int
        3D index y
    k : int
        3D index z
    N1 : int
        size of the array y
    N2 : int, optional, default=N1
        size of the array z
    N0 : int, optional, default=N1
        size of the array x

    Returns
    -------
    Id : int
        corresponding 1D index

    """
    N2 = N2 or N1
    return k + N2 * (j + N1 * i)


def ocean_sigma_coordinate(sigma, eta, depth):
    """
    Creates a dimensioned version of ocean sigma coordinate.

    z(n, k, j, i) = eta(n, j, i) + sigma(k) *
                    (depth(j, i) + eta(n, j, i))

    """
    return eta + sigma * (depth + eta)


def format_size(size):
    """Return file size as string from byte size."""
    for unit in ('B', 'KB', 'MB', 'GB', 'TB'):
        if size < 2048:
            return '%.f %s' % (size, unit)
        size /= 1024.0


def _setup_demands(specs):
    """Setup demand model"""
    specs['DEMAND'] = specs['DEMAND_SECTION']


def starttime(t):
    """
Fixes the start time of observations taken with LAT. This assumes that the
time array in your light curve is in days already, and the beginning of
your analysis coincides with t0 for LAT.

:param t: array with input times given in days, with t0 coinciding with the beginning of LAT
:returns: t (days), t (years)
    """
    import pendulum
    tp = pendulum.create(2008, 8, 4, 15, 43, 37) - pendulum.create(2008, 1, 1)
    t0 = tp.days
    t = t - t[0] + t0
    ty = 2008.0 + t / 365.0
    return t, ty


def classify_marked_tagnames(tagnames):
    """splits tagnames into two lists: those that have
    a '*' in the end and those that don't"""
    pure_tags = list()
    wildcards = list()
    for tagname in tagnames:
        if tagname.endswith('*'):
            wildcards.append(tagname)
        else:
            pure_tags.append(tagname)
    return pure_tags, wildcards


def wrapper(executable):
    """
    Wrapper function for any container specific usage.
    This function will be called by pilot.util.container.execute() and prepends the executable with a container command.

    :param executable: command to be executed (string).
    :return: executable wrapped with container command (string).
    """
    return executable


@classmethod
def create_module(cls, spec):
    """Use default semantics for module creation."""


def optparser(args):
    """Constructs a dictionary of settings from the values the user
    provides to the ArgumentParser. Used in Package.new() and for
    """
    return {'venv': args.venv, 'minimal': args.minimal, 'strict': args.
        strict, 'pkgname': args.pkgname, 'author': args.author, 'email':
        args.email, 'version': args.version, 'classifiers': [], 'url': args
        .url, 'desc': args.desc, 'readme': args.readme}


def __extract_desired_params(boolean_list: list, parameter_list: list):
    """
    Function which takes 2 lists, one with booleans and one with any other data types.
    Returns a list with all values of the parameter list which had the same indices as
    the True booleans in the boolean list
    :param boolean_list:    List of True or False
    :param parameter_list:  List of parameters
    :return: List of parameters that coincide with True items in boolean list
    """
    if len(boolean_list) != len(parameter_list):
        raise IndexError('Input sizes do not match')
    result = []
    for boolean, item in zip(boolean_list, parameter_list):
        if boolean is True:
            result.append(item)
    return result


def from_maybe(default, maybe):
    """
    Helper for translating code using Haskell's:

        fromMaybe default maybe

    (typically, the argument order feels back-to-front for python code
    but it's easier to translate code if we keep it the same)
    """
    return maybe if maybe is not None else default


def _get_number_of_children(base, tag):
    """Count all child elements with a given tag.

    Args:
        base: The base node element. (lxml node)
        tag: Child elements group tag used to select the elements. (string)

    Returns:
        A int number of the found child elements with the id.
    """
    counter = 0
    for node in base:
        if node.tag.replace('{http://www.rdml.org}', '') == tag:
            counter += 1
    return counter


def p_statements(p):
    """statements : statement
                 | statements statement """
    if len(p) == 2:
        p[0] = p[1]
    else:
        p[0] = ['STATEMENTS', p[1][1] + [p[2]]]


def get_workers(app):
    """Get all workers connected to a celery application.

    :param `celery.Celery` app: the celery application
    :return: A list of all connected workers
    :rtype: list
    """
    i = app.control.inspect()
    workers = i.ping()
    if workers is None:
        return []
    return [*workers]


def delete_method_response(restApiId=None, resourceId=None, httpMethod=None,
    statusCode=None):
    """
    Deletes an existing  MethodResponse resource.
    See also: AWS API Documentation

    :example: response = client.delete_method_response(
        restApiId='string',
        resourceId='string',
        httpMethod='string',
        statusCode='string'
    )

    :type restApiId: string
    :param restApiId: [REQUIRED]
            The RestApi identifier for the MethodResponse resource.

    :type resourceId: string
    :param resourceId: [REQUIRED]
            The Resource identifier for the MethodResponse resource.

    :type httpMethod: string
    :param httpMethod: [REQUIRED]
            The HTTP verb of the Method resource.

    :type statusCode: string
    :param statusCode: [REQUIRED]
            The status code identifier for the MethodResponse resource.

    """
    pass


def linear_1d(module, grad_input, grad_output):
    """No change made to gradients."""
    return None


def check_above(site, molecule):
    """
    This function can check whether all atoms in molecule are above the adsorption site

    Parameters:

    site:
        Numpy Array. The adsorption site that we want

    molecule:
        Atoms Object. The adsorbates.

    Return:
        Boolean. Shows whether the molecule is above the surface or not.
    """
    for atom in molecule:
        if atom.position[2] < site[2]:
            return False
    return True


@staticmethod
def value_from_buffer(bfr):
    """ Parse an extensible byte serialised unsigned int from a buffer.

        Continuation octets have their high bit set.
        The value is big-endian.

        This is the go for reading from a stream. If you already have
        a bare bytes instance then `cs.serialise.get_uint` may be better.
    """
    n = 0
    b = 128
    while b & 128:
        bs = bfr.take(1)
        b = bs[0]
        n = n << 7 | b & 127
    return n


@staticmethod
def _state_to_drugstr(s, sb=None):
    """Converts state (e.g., [1,1,0]) to drug-string (e.g., "2,3")
        """
    if s.count(1) == 0:
        return 0
    n = len(s)
    snums = []
    for i in range(n):
        if s[n - i - 1] == 1:
            snums.append(str(i + 1))
    if sb is None:
        return ','.join(snums)
    sbnums = []
    for i in range(n):
        if sb[n - i - 1] == 1:
            sbnums.append(str(i + 1))
    sbnums = [i for i in sbnums if not i in snums]
    return ','.join(snums), ','.join(sbnums)


def contains(key_words, line):
    """If a line contains one of the word in key_words."""
    for word in key_words:
        if word in line:
            return True
    return False


def ghost_curves_clear():
    """Clear F-Curve snapshots (Ghosts) for active Graph Editor

    """
    pass


def quote_string(s: str, force: bool=False) ->str:
    """Sometimes wraps strings in double quotes, depending on the content and force parameter.

    Description:
        This function provides conditional wrapping of strings inside double quotes.
        If the input string contains a space, OR force is set to True, then the input string will
        always be quoted.
        If the input string does not contain a space, AND force is set to False, then the input
        string is returned unmodified.

    Args:
        s: The string that needs to be wrapped in quotes (maybe)
        force (optional): Whether to force quotes around the string even if not needed. Defaults to False.

    Examples:
        >>> quote_string("nevermore", False)
        'nevermore'
        >>> quote_string("nevermore")
        'nevermore'
        >>> quote_string("nevermore", True)
        '"nevermore"'
        >>> quote_string("never more", False)
        '"never more"'

    Returns:
        The string, maybe wrapped in double quotes
    """
    return f'"{s}"' if force or ' ' in s else s


@classmethod
def binary(cls, key, data):
    """returns an ApeTagItem of binary data

        key is an ASCII string, data is a binary string"""
    return cls(1, 0, key, data)


def is_python_proxy(parameter):
    """Determines whether parameter is a Python Proxy, i.e., it has a Java
    internal class with an `implements` member.

    :param parameter: the object to check.
    :rtype: True if the parameter is a Python Proxy
    """
    try:
        is_proxy = len(parameter.Java.implements) > 0
    except Exception:
        is_proxy = False
    return is_proxy


def hexToBin(hexStr, numOfBits):
    """Converts hex string to binary

    :param hexStr: Hex value in string format
    :type hexStr: str
    :param numOfBits: Number of bits to convert
    :type numOfBits: int

    :return: bits representing the hex values
    """
    return bin(int(hexStr, 16))[2:].zfill(numOfBits)


def str_repr(string):
    """
    >>> print(str_repr('test'))
    'test'
    >>> print(str_repr(u'test'))
    'test'
    """
    result = repr(string)
    if result.startswith('u'):
        return result[1:]
    else:
        return result


def moderateMail(request):
    """
           Processes an HTTP request for information on what to do with a
           specific mail message in the moderation queue.  Expects the request
           to contain an 'action' ('approve' or 'discard'), a 'pin' used to
           authenticate the moderator, and an 'mid' which is the id of the
           mail object in the moderation queue.  Expects a request variable
           'Mail' containing the mail message with headers
        """


def _name(ref):
    """Return the username or email of a reference."""
    return ref.get('username', ref.get('email'))


def get_msec_to_frame(frame_rate):
    """Get the function to convert from frame time (ms) to frame number"""
    return lambda msec: msec * frame_rate / 1000.0


def dtostr(date):
    """Format date accordingly to linky API"""
    return date.strftime('%d/%m/%Y')


def __piecewise(*args):
    """
    Eval entry for piecewise functions
    """
    args = list(args)
    sol = None
    if len(args) % 2:
        args.append(True)
    for i, arg in enumerate(args):
        if not i % 2:
            continue
        if arg:
            sol = args[i - 1]
            break
    return sol


def listify(item):
    """
    If item is not a list, return it as a list

    :param item: Item which may or may not be a list
    :return: List
    """
    if isinstance(item, tuple):
        return list(item)
    if not isinstance(item, list):
        return [item]
    return item


@staticmethod
def argument_shorthand(tree):
    """
        Try to convert argument to shorthand syntax if possible.
        """
    assert tree.data == 'arguments'
    if len(tree.children) == 1:
        path = tree.child(0).follow_node_chain(['expression', 'entity', 'path']
            )
        if path is not None:
            tree.children = [path.child(0), tree.children[0]]


def normalize_hkid(hkid):
    """Normalize a hkid so that it is safe to compare with other normalized hkids."""
    return hkid.lower()


@classmethod
def sort(cls, *columns):
    """
        Shortcut for smart_query() method
        Example 1:
            User.sort('first_name','-user_id')
        This is equal to
            db.query(User).order_by(*User.order_expr('first_name','-user_id'))

        Example 2:
            columns = ['first_name','-user_id']
            User.sort(*columns)
        This is equal to
            columns = ['first_name','-user_id']
            db.query(User).order_by(*User.order_expr(*columns))

        Exanple 3 (with joins):
            Post.sort('comments___rating', 'user___name').all()
        """
    return cls.smart_query({}, columns)


def _set(context, obj, name, value):
    """ convenience method to set values """
    setattr(obj, context.md_core_model['mappings'][name], value)


def lasttrim(character, trim_this):
    """Get all contents after specified character

    ex: lasttrim('.', string)
    """
    trimmed = trim_this[trim_this.rindex(character) + 1:]
    return trimmed


def usage_percent(used, total, round_=None):
    """Calculate percentage usage of 'used' against 'total'."""
    try:
        ret = float(used) / total * 100
    except ZeroDivisionError:
        return 0.0
    else:
        if round_ is not None:
            ret = round(ret, round_)
        return ret


def unique_order(seq):
    """Removes duplicates while preserving order"""
    uniq = list()
    for element in seq:
        if element not in uniq:
            uniq.append(element)
    return uniq


@classmethod
def with_params(cls, xid, path, watch, data, offset, size, client, server):
    """
    Build a ClientMessage with the given params, possibly parsing some more.

    This must be overridden by subclasses so the specific parameters to each subclass
    can be extracted.

    :param xid: the transaction id associated with this ClientMessage
    :param path: the path associated with this ClientMessage, if any
    :param watch: a boolean indicating if watch on the path should be set
    :param data: the remaining data of the associated data packet
    :param offset: the offset from which the data should be read
    :param size: the total size of this ClientMessage
    :param client: the ip:port generating this ClientMessage

    :returns: Returns an instance of the specific ClientMessage subclass.
    :raises DeserializationError: if parsing the ClientMessage fails.
    """
    return cls(size, xid, path, client, watch, server)


def escape(s, quote=False):
    """Replace special characters "&", "<" and ">" to HTML-safe sequences.  If
    the optional flag `quote` is `True`, the quotation mark character is
    also translated.

    There is a special handling for `None` which escapes to an empty string.

    :param s: the string to escape.
    :param quote: set to true to also escape double quotes.
    """
    if s is None:
        return ''
    if not isinstance(s, (str, bytes)):
        s = str(s)
    if isinstance(s, bytes):
        try:
            s.decode('ascii')
        except UnicodeDecodeError:
            s = s.decode('utf-8', 'replace')
    s = s.replace('&', '&').replace('<', '<').replace('>', '>')
    if quote:
        s = s.replace('"', '"')
    return s


def vertex_parent_set():
    """Parent selected objects to the selected vertices

    """
    pass


@staticmethod
def get_cronitor_id(kwargs):
    """Retrieves Cronitor ID passed through cron job params,
        removes it from the params.
        """
    return (kwargs or {}).pop('cronitor_id', None)


def get_class_name(obj):
    """Get class name in dot separete notation

        >>> from datetime import datetime
        >>> obj = datetime.datetime(2000, 1, 1)
        >>> get_class_name(obj) -> "datetime.datetime"

        >>> from collections import deque
        >>> obj = deque([1, 2, 3])
        >>> get_class_name(obj) -> "collections.deque"
    """
    return obj.__class__.__module__ + '.' + obj.__class__.__name__


def str2port(s):
    """Convert a string to a network port number.

    :param str s: the string to convert
    :return: port number
    :rtype: int
    :raises ValueError: if ``s`` cannot be converted to a number in [0..65535]

    .. versionadded:: 0.5.0
    """
    port = int(s)
    if 0 <= port <= 65535:
        return port
    raise ValueError('not a valid port number: %d' % port)


def _lrp_meanStopFluor(fluor, tarGroup, vecTarget, stopCyc, vecSkipSample,
    vecNoPlateau):
    """Return the mean of the stop fluor or the max fluor if all rows have no plateau.

    Args:
        fluor: The array with the fluorescence values
        tarGroup: The target number
        vecTarget: The vector with the targets numbers
        stopCyc: The vector with the stop cycle of the log lin phase
        vecSkipSample: Skip the sample
        vecNoPlateau: True if there is no plateau

    Returns:
        The meanMax fluorescence.
    """
    meanMax = 0.0
    maxFluor = 1e-07
    cnt = 0
    if tarGroup is None:
        for aRow in range(0, fluor.shape[0]):
            if not vecSkipSample[aRow]:
                if not vecNoPlateau[aRow]:
                    cnt += 1
                    meanMax += fluor[aRow, stopCyc[aRow] - 1]
                else:
                    for i in range(0, fluor.shape[1]):
                        if fluor[aRow, i] > maxFluor:
                            maxFluor = fluor[aRow, i]
    else:
        for aRow in range(0, fluor.shape[0]):
            if tarGroup == vecTarget[aRow] and not vecSkipSample[aRow]:
                if not vecNoPlateau[aRow]:
                    cnt += 1
                    meanMax += fluor[aRow, stopCyc[aRow] - 1]
                else:
                    for i in range(0, fluor.shape[1]):
                        if fluor[aRow, i] > maxFluor:
                            maxFluor = fluor[aRow, i]
    if cnt > 0:
        meanMax = meanMax / cnt
    else:
        meanMax = maxFluor
    return meanMax


def dumps(frozen_traceback):
    """
    Returns the FrozenTraceback object as a byte string
    """
    return frozen_traceback.to_bytes()


def wrap_node_data_lookup(uuid_to_devices):
    """given a uuid to devices map, returns dictionary like the following:
    {'parameter_defaults':
      {'NodeDataLookup':
        {'32e87b4c-c4a7-41be-865b-191684a6883b': {'devices': ['/dev/sdc']}},
        {'ea6a84d6-cf89-4fe2-b7bd-869b3fe4dd6b': {'devices': ['/dev/sdc']}}}}
    """
    node_data_lookup = {}
    node_data_lookup['NodeDataLookup'] = uuid_to_devices
    output = {}
    output['parameter_defaults'] = node_data_lookup
    return output


@classmethod
def has_archiving(cls):
    """Returns whether it supports archiving items on the fetch process.

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


@classmethod
def parse(cls, name, data_size, reader, parsers):
    """given a 4 byte name, data_size int, BitstreamReader
        and dict of {"atom":handler} sub-parsers,
        returns an atom of this class"""
    assert name == b'mdhd'
    version, flags = reader.parse('8u 24u')
    if version == 0:
        atom_format = '32u 32u 32u 32u'
    else:
        atom_format = '64U 64U 32u 64U'
    created_utc_date, modified_utc_date, sample_rate, track_length = (reader
        .parse(atom_format))
    language = reader.parse('1p 5u 5u 5u')
    quality = reader.read(16)
    return cls(version=version, flags=flags, created_utc_date=
        created_utc_date, modified_utc_date=modified_utc_date, sample_rate=
        sample_rate, track_length=track_length, language=language, quality=
        quality)


def unique_node_name_from_input(node_name):
    """Replaces invalid characters in input names to get a unique node name."""
    return node_name.replace(':', '__port__').replace('^', '__hat__')


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


@classmethod
def get_container_name(cls):
    """ Returns the name of the container class.
		"""
    return 'batch_normalization'


def match_file(patterns, file):
    """
	Matches the file to the patterns.

	*patterns* (:class:`~collections.abc.Iterable` of :class:`~pathspec.pattern.Pattern`)
	contains the patterns to use.

	*file* (:class:`str`) is the normalized file path to be matched
	against *patterns*.

	Returns :data:`True` if *file* matched; otherwise, :data:`False`.
	"""
    matched = False
    for pattern in patterns:
        if pattern.include is not None:
            if file in pattern.match((file,)):
                matched = pattern.include
    return matched


def _restore_original(word):
    """If the `word` is a Quoted string, restores it to original.
    """
    if getattr(word, 'is_single_quoted', False):
        return "'%s'" % word
    if getattr(word, 'is_double_quoted', False):
        return '"%s"' % word
    return word


def _short_circuit():
    """Should processing be short-circuited?

        :return: True if the file processing loop should exit before it's
            finished processing each message in the current slice of hash
            space.  False tells _one_iteration() to continue processing until
            the current snapshot of hash space is exhausted.
        :rtype: bool
        """


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


def get_package_data():
    """Get Package Data for utilipy.astro.instruments.filtertransforms.MegaCam_PanSTARRS."""
    return {'utilipy.astro.instruments.filtertransforms.MegaCam_PanSTARRS':
        ['data/*']}


@classmethod
def GetJobGroup(cls, repository):
    """
        A single repository/branch combination can create many jobs, depending on the job matrix.

        This variable is used to identify jobs within the same group.

        :param Repository repository:
            A repository that can contain jobs

        :returns unicode:
            Job group for the given repository
        """
    return repository.name + '-' + repository.branch


def to_bool(arg):
    """
    Return a boolean value based on `arg`.
    """
    if arg is None or isinstance(arg, bool):
        return arg
    if isinstance(arg, str):
        arg = arg.lower()
    if arg in ('yes', 'on', '1', 'true', 1):
        return True
    return False


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 merge_status_dict(d1, d2):
    """
    Given two TweetResult dictionaries, merge them into one status dictionary.
    Does not modify either dictionary, and rather makes a new one.
    """
    results = dict()
    for term, statuses in d1.items():
        if term not in results:
            results[term] = list()
        for status in statuses:
            results[term].append(status)
    for term, statuses in d2.items():
        if term not in results:
            results[term] = list()
        for status in statuses:
            results[term].append(status)
    return results


def _select_between_braces(s, original_name):
    """ Assuming s starts with an opening brace, return the part between
    braces and the position of the comma's at the root level.
    """
    assert s[0] == '('
    level = 0
    commas = []
    for i in range(len(s)):
        if s[i] == '(':
            level += 1
        elif s[i] == ')':
            level -= 1
            if level == 0:
                break
        elif level == 1 and s[i] == ',':
            commas.append(i - 1)
    if level != 0:
        raise TypeError(
            f"No end-brace in ShaderType string '{original_name}': '{s}'")
    return s[1:i], commas


def nspin(calc, val):
    """https://www.quantum-espresso.org/Doc/INPUT_PW.html#nspin
    """
    assert val in [2, 4]
    assert calc.get_param('occupations')
    assert calc.get_param('smearing')
    assert calc.get_param('degauss')
    if val == 4:
        assert calc.get_param('noncolin')
    moments = calc.atoms.get_initial_magnetic_moments()
    assert moments.any()


def is_published():
    """Checks whether the current context is currently published.
        """


def generate_cert_override(overrides):
    """
    Generate the contents for a cert_override.txt file with entries for
    the given CertOverrideEntry objects.
    """
    contents = """# PSM Certificate Override Settings file
# This is a generated file!  Do not edit.
"""
    for override in overrides:
        contents += '\t'.join([override.host + ':' + override.port,
            override.fingerprint_algorithm, override.fingerprint, str(
            override.mask), override.db_key]) + '\n'
    return contents


def containsOnly(seq, aset):
    """ Check if sequence "seq" contains ONLY letters in set "aset" """
    for c in seq:
        if c not in aset:
            return False
    return True


def disable_admin_access(session, return_type=None, **kwargs):
    """
    Disable Admin acccess

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    path = '/api/users/admin_access/disable.json'
    return session.post_api(path=path, return_type=return_type, **kwargs)


def bound(lower, x, higher):
    """Returns x bounded by a maximum and minimum value. Equivalent to:
    return min(max(x, lower), higher)
    """
    return lower if x <= lower else higher if x >= higher else x


def fail_on_shallow(wd):
    """experimental, may change at any time"""
    if wd.is_shallow():
        raise ValueError(
            '%r is shallow, please correct with "git fetch --unshallow"' %
            wd.path)


def _append_dicts(x, y):
    """python2 compatible way to append 2 dictionaries
    """
    z = x.copy()
    z.update(y)
    return z


def gettext(msg):
    """
    Return the localized translation of message, based on the current global domain, language, and locale directory.
    This function is usually aliased as _() in the local namespace.

    @param msg: string
        The key message.
    @return: string
        The translated message.
    """
    assert isinstance(msg, str), 'Invalid key message %s' % msg
    return msg


def _as_tuple(item):
    """Ensure an item is a tuple."""
    if item is None:
        return None
    elif not isinstance(item, tuple):
        return item,
    else:
        return item


def select(extend: bool=False, deselect: bool=False, toggle: bool=False,
    deselect_all: bool=False, location: float=(0.0, 0.0)):
    """Select spline points

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    :param deselect: Deselect, Remove from selection
    :type deselect: bool
    :param toggle: Toggle Selection, Toggle the selection
    :type toggle: bool
    :param deselect_all: Deselect On Nothing, Deselect all when nothing under the cursor
    :type deselect_all: bool
    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


@staticmethod
def is_processing_instruction(obj):
    """Is processing instruction."""
    import bs4
    return isinstance(obj, bs4.ProcessingInstruction)


def _tgrep_parens_action(_s, _l, tokens):
    """
    Builds a lambda function representing a predicate on a tree node
    from a parenthetical notation.
    """
    assert len(tokens) == 3
    assert tokens[0] == '('
    assert tokens[2] == ')'
    return tokens[1]


@staticmethod
def CreateFromImage(image):
    """
        Create a GraphicsContext associated with a :class:`wx.Image`.

        The image specifies the size of the context as well as whether alpha is
        supported (if :meth:`wx.Image.HasAlpha()`) or not and the initial contents of
        the context. The image object must have a life time greater than
        that of the new context as the context copies its contents back to the
        image when it is destroyed.

        Not implemented yet...
        """
    raise NotImplementedError


def edit_matching_entry(program, arguments):
    """Edit the matching entry."""
    entry = program.select_entry(*arguments)
    entry.context.execute('pass', 'edit', entry.name)


@classmethod
def has_index(cls, name=None, columns=None):
    """Check if the table has an index (other than primary key)

        Search either by index name or by column name

        Args:
            name (:obj:`str`): Index name to check
            columns (:obj:`list`): List of columns making the index

        Returns:
            True or False

        Raises:
            SystemExit: If `table` object does not exists
        """
    if not cls.table_exists():
        return False
    if name is not None:
        return cls._has_named_index(name)
    if columns is not None:
        return cls._has_columns_index(columns)
    return False


def _deduplicate(indicator_list):
    """Deduplicate the list of indicators of compromise."""
    return list(set(indicator_list))


def sec_to_time(seconds):
    """Transform seconds into a formatted time string.

    Parameters
    -----------
    seconds : int
        Seconds to be transformed.

    Returns
    -----------
    time : string
        A well formatted time string.
    """
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    return '%02d:%02d:%02d' % (h, m, s)


@staticmethod
def is_wet_text_record(record):
    """Return true if WARC record is a WET text/plain record"""
    return (record.rec_type == 'conversion' and record.content_type ==
        'text/plain')


def get_opening_type(zone):
    """Return the result of the type guessing from name."""
    if 'MOTION' in zone['name']:
        return 'motion'
    if 'KEY' in zone['name']:
        return 'safety'
    if 'SMOKE' in zone['name']:
        return 'smoke'
    if 'WATER' in zone['name']:
        return 'water'
    return 'opening'


def success(exitcode, message):
    """
    Raise an IO Error if the return code from a subprocess is non-zero

    :param exitcode: The return code from a subprocess run
    :param message: A custom message if the process failed
    :raises: ChildProcessError
    """
    if exitcode != 0:
        raise ChildProcessError('Command returned non-zero exit status: %s' %
            message)


@staticmethod
def _add_func(functype, obj, funcname, func):
    """
        Adds `func` to `obj` as `funcname` using `setattr()`, but adds
        `funcname` to set given by `obj._extrattrs[functype]` for tracking
        purposes.
        """
    if funcname not in obj._extra_attrs[functype]:
        obj._extra_attrs[functype].append(funcname)
    setattr(obj, funcname, func)


def getOrder(original):
    """Return the optionally reordered fields.

        'original' is a dictionary where the keys are the names of
        schemata and the values are lists of field names, in order.

        The method should return a new such dictionary with re-ordered
        lists.

        It is recommended to use an OrderedDict (available as
        Products.Archetypes.utils.OrderedDict) to guarantee proper ordering
        of schemata.
        """


def add_member_dicts(graph):
    """
    Add names and bigs to the node attribute dictionaries in the graph, based
    on the values provided by pydot.
    """
    for key in graph.nodes_iter():
        graph.node[key].update({'name': key})
    for parent, child in graph.edges_iter():
        graph.node[child]['big_name'] = graph.node[parent]['name']


@staticmethod
def get_message(build, commit):
    """Extract the message from the commit or comment.

        Arguments:
          build (:py:class:`dict`): The JSON data from the response.
          commit (:py:class:`dict`): The JSON data from the response.

        Returns:
          :py:class:`str`: The commit or comment message.

        """
    return build.get('comment') or commit.get('message')


def getExceptionMessage(exceptionDetails: dict) ->str:
    """Get exception message from `exceptionDetails` object."""
    exception = exceptionDetails.get('exception')
    if exception:
        return exception.get('description') or exception.get('value')
    message = exceptionDetails.get('text', '')
    stackTrace = exceptionDetails.get('stackTrace', dict())
    if stackTrace:
        for callframe in stackTrace.get('callFrames'):
            location = str(callframe.get('url', '')) + ':' + str(callframe.
                get('lineNumber', '')) + ':' + str(callframe.get(
                'columnNumber'))
            functionName = callframe.get('functionName', '<anonymous>')
            message = message + f'\n    at {functionName} ({location})'
    return message


def delimiter_groups(line, begin_delim=begin_delim, end_delim=end_delim):
    """Split a line into alternating groups.
       The first group cannot have a line feed inserted,
       the next one can, etc.
    """
    text = []
    line = iter(line)
    while True:
        for item in line:
            text.append(item)
            if item in begin_delim:
                break
        if not text:
            break
        yield text
        level = 0
        text = []
        for item in line:
            if item in begin_delim:
                level += 1
            elif item in end_delim:
                level -= 1
                if level < 0:
                    yield text
                    text = [item]
                    break
            text.append(item)
        else:
            assert not text, text
            break


@classmethod
def dark_blue(cls):
    """A factory method that returns a :class:`Colour` with a value of ``0x206694``."""
    return cls(2123412)


def read_file(filename, mode='r'):
    """read_text file and return string of content
    """
    with open(filename, mode) as filey:
        content = filey.read()
    return content


def efficiency(Voc, Isc, FF, A=1):
    """Return the efficiency of a solar cell (units not percentage)given Voc (volts), Isc in (amps) and  FF (units).
    also works for Jsc since area of 1 is assumed
    """
    return 1000 * Voc * Isc * FF / A


def setup_cellview(ax, system, scale=1):
    """Builds the particle position visualisation pane.

    Parameters
    ----------
    ax: Axes object
        The axes position that the pane should be placed in.
    system: System
        The whole system information.
    scale: float (optional)
        The amount by which the particle size should be scaled down.
    """
    xpos = system.particles['xposition']
    ypos = system.particles['yposition']
    mk = 6.00555e-08 / (system.box_length - 2.2727e-10) - 1e-10 / scale
    ax.plot(xpos, ypos, 'o', markersize=mk, markeredgecolor='black', color=
        '#34a5daff')
    ax.set_xlim([0, system.box_length])
    ax.set_ylim([0, system.box_length])
    ax.set_xticks([])
    ax.set_yticks([])


def char2hex(a: str):
    """Convert a hex character to its integer value.

    '0' becomes 0, '9' becomes 9
    'A' becomes 10, 'F' becomes 15
    'a' becomes 10, 'f' becomes 15

    Returns -1 on error.

    """
    if '0' <= a <= '9':
        return ord(a) - 48
    elif 'A' <= a <= 'F':
        return ord(a) - 55
    elif 'a' <= a <= 'f':
        return ord(a) - 87
    return -1


def bird_hulstrom80_aod_bb(aod380, aod500):
    """
    Approximate broadband aerosol optical depth.

    Bird and Hulstrom developed a correlation for broadband aerosol optical
    depth (AOD) using two wavelengths, 380 nm and 500 nm.

    Parameters
    ----------
    aod380 : numeric
        AOD measured at 380 nm
    aod500 : numeric
        AOD measured at 500 nm

    Returns
    -------
    aod_bb : numeric
        broadband AOD

    See also
    --------
    kasten96_lt

    References
    ----------
    .. [1] Bird and Hulstrom, "Direct Insolation Models" (1980)
       `SERI/TR-335-344 <http://www.nrel.gov/docs/legosti/old/344.pdf>`_

    .. [2] R. E. Bird and R. L. Hulstrom, "Review, Evaluation, and Improvement
       of Direct Irradiance Models", Journal of Solar Energy Engineering
       103(3), pp. 182-192 (1981)
       :doi:`10.1115/1.3266239`
    """
    return 0.27583 * aod380 + 0.35 * aod500