def cmd_update(txn, path, value, _args):
    """Update raw key value."""
    txn.raw.update(path, value)


@staticmethod
def p_pa_blob(p):
    """pa_blob : PA_BLOB"""
    p[0] = p[1]


def get_incremental_iteration_dets(for_el):
    """
    Look for the pattern:

    pets = ['cat', 'dog']
    for i in range(len(pets)):
        print(f"My {pets[i]}")

    For/target/Name id = i
        iter/Call/func/Name id = range
                  args/Call/func/Name id = len
                            args/Name id = pets

    ... Subscript/value/Name id = pets
                  slice/Index/value/Name = i
    """
    target_name_els = for_el.xpath('target/Name')
    if not target_name_els:
        return None
    index_name = target_name_els[0].get('id')
    iterator_func_name_els = for_el.xpath('iter/Call/func/Name')
    if not iterator_func_name_els:
        return None
    range_iterator_func = iterator_func_name_els[0].get('id') == 'range'
    if not range_iterator_func:
        return None
    iter_arg_func_name_els = for_el.xpath('iter/Call/args/Call/func/Name')
    if not iter_arg_func_name_els:
        return None
    len_inside = iter_arg_func_name_els[0].get('id') == 'len'
    if not len_inside:
        return None
    len_arg_name_els = for_el.xpath('iter/Call/args/Call/args/Name')
    if not len_arg_name_els:
        return None
    iterable_name = len_arg_name_els[0].get('id')
    if not iterable_name:
        return None
    subscript_name_els = for_el.xpath(
        'descendant-or-self::Subscript/value/Name')
    if not subscript_name_els:
        return None
    subscript_name = subscript_name_els[0].get('id')
    slicing_iterable = iterable_name == subscript_name
    if not slicing_iterable:
        return None
    slice_index_name_els = for_el.xpath(
        'descendant-or-self::Subscript/slice/Index/value/Name')
    if not slice_index_name_els:
        return None
    slice_index_name = slice_index_name_els[0].get('id')
    slicing_by_range_val = slice_index_name == index_name
    if not slicing_by_range_val:
        return None
    return index_name, iterable_name


def broadcast_power(lhs=None, rhs=None, name=None, attr=None, out=None, **
    kwargs):
    """Returns result of first array elements raised to powers from second array, element-wise with broadcasting.

    Example::

       x = [[ 1.,  1.,  1.],
            [ 1.,  1.,  1.]]

       y = [[ 0.],
            [ 1.]]

       broadcast_power(x, y) = [[ 2.,  2.,  2.],
                                [ 4.,  4.,  4.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_extended.cc:L45

    Parameters
    ----------
    lhs : Symbol
        First input to the function
    rhs : Symbol
        Second input to the function

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

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


def mode(HEARTBEAT):
    """return flight mode number"""
    from pymavlink import mavutil
    if HEARTBEAT.type == mavutil.mavlink.MAV_TYPE_GCS:
        return None
    return HEARTBEAT.custom_mode


@classmethod
def from_dict(cls, data):
    """Create a ContentSet instance from the API response data"""
    return cls(contentset_id=data['id'], name=data['name'], description=
        data['description'], is_default=bool(data['isDefault']))


def list_remote_files(tag, sat_id):
    """Lists files available for Demeter.

    Note
    ----
    Unfortunately, obtaining a list of remote files is not
    avilable for this instrument. This function is expected
    by pysat thus it is located here as a placeholder.

    Parameters
    ----------
    tag : (string or NoneType)
        Denotes type of file to load.  Accepted types are <tag strings>.
        (default=None)
    sat_id : (string or NoneType)
        Specifies the satellite ID for a constellation.  Not used.
        (default=None)

    """
    print('Remote file lists are not supported for Demeter.')
    return


@classmethod
def new(cls, cipher_name, key, iv, mac_alg=b'', mac_key=b'', etm=False):
    """Construct a new SSH packet encryption object"""
    raise NotImplementedError


def raise_import_error_with_hint(dep):
    """Raises an import error and gives a helpful message for installing the
    missing dependency.

    :param dep: the missing dependency.

    """
    raise ImportError(
        '`{0}` is required. Install it with `pip install {0}` or `easy_install {0}` if you are not using pip. For more details, visit http://pip-installer.org.'
        .format(dep))


def to_bytes(x):
    """Convert an integer to bytes."""
    return x.to_bytes(2, 'big')


def timeChangingSpeed(v0, vf, a, TPR):
    """for decelerations, a < 0"""
    return TPR - (vf - v0) / a


def format_as(format_string):
    """format_as(form)(obj) = form % obj

    Useful to format many objects with the same format string.

    >>> list(map(format_as("0x%x"), [0, 1, 10, 11, 15]))
    ['0x0', '0x1', '0xa', '0xb', '0xf']
    """
    return lambda obj: format_string % obj


def _pair_members_to_new_node(dm, i, j, disallow_negative_branch_length):
    """Return the distance between a new node and decendants of that new node.

    Parameters
    ----------
    dm : skbio.DistanceMatrix
        The input distance matrix.
    i, j : str
        Identifiers of entries in the distance matrix to be collapsed (i.e.,
        the descendents of the new node, which is internally represented as
        `u`).
    disallow_negative_branch_length : bool
        Neighbor joining can result in negative branch lengths, which don't
        make sense in an evolutionary context. If `True`, negative branch
        lengths will be returned as zero, a common strategy for handling this
        issue that was proposed by the original developers of the algorithm.

    """
    n = dm.shape[0]
    i_to_j = dm[i, j]
    i_to_u = 0.5 * i_to_j + (dm[i].sum() - dm[j].sum()) / (2 * (n - 2))
    if disallow_negative_branch_length and i_to_u < 0:
        i_to_u = 0
    j_to_u = i_to_j - i_to_u
    if disallow_negative_branch_length and j_to_u < 0:
        j_to_u = 0
    return i_to_u, j_to_u


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


def get_scales(args, reg_params):
    """
    Calculate the scaling factors from the coordinate space of the raw data
    (which the cell positions are defined in) to the (usually downsampled)
    reference space that the deformation field is defined in.
    :param args:
    :param reg_params:
    :return:
    """
    x_scale = args.x_pixel_um / float(reg_params.atlas_x_pix_size)
    y_scale = args.y_pixel_um / float(reg_params.atlas_y_pix_size)
    z_scale = args.z_pixel_um / float(reg_params.atlas_z_pix_size)
    return x_scale, y_scale, z_scale


def count_junctions(graph):
    """Return the number of junctions in graph"""
    junc_count = 0
    for node in graph.nodes():
        if graph.in_degree(node) > 1:
            junc_count += 1
        if graph.out_degree(node) > 1:
            junc_count += 1
    return junc_count


def get_data_names(data, data_names):
    """
    Get default names for data fields if none are given based on the data.

    Examples
    --------

    >>> import numpy as np
    >>> east, north, up = [np.arange(10)]*3
    >>> get_data_names((east,), data_names=None)
    ('scalars',)
    >>> get_data_names((east, north), data_names=None)
    ('east_component', 'north_component')
    >>> get_data_names((east, north, up), data_names=None)
    ('east_component', 'north_component', 'vertical_component')
    >>> get_data_names((up, north), data_names=('ringo', 'george'))
    ('ringo', 'george')

    """
    if data_names is not None:
        if len(data) != len(data_names):
            raise ValueError(
                'Data has {} components but only {} names provided: {}'.
                format(len(data), len(data_names), str(data_names)))
        return data_names
    data_types = [('scalars',), ('east_component', 'north_component'), (
        'east_component', 'north_component', 'vertical_component')]
    if len(data) > len(data_types):
        raise ValueError(' '.join([
            'Default data names only available for up to 3 components.',
            "Must provide custom names through the 'data_names' argument."]))
    return data_types[len(data) - 1]


def select_nth(nth: int=2, skip: int=1, offset: int=0):
    """Deselect every other vertex

    :param nth: Nth Selection
    :type nth: int
    :param skip: Skip
    :type skip: int
    :param offset: Offset
    :type offset: int
    """
    pass


def ReadCIF(URLorFile):
    """Open a CIF, which may be specified as a file name or as a URL using PyCifRW
    (from James Hester).
    The open routine gets confused with DOS names that begin with a letter and colon
    "C:\\dir" so this routine will try to open the passed name as a file and if that
    fails, try it as a URL

    :param str URLorFile: string containing a URL or a file name. Code will try first
      to open it as a file and then as a URL.

    :returns: a PyCifRW CIF object.
    """
    import CifFile as cif
    try:
        fp = open(URLorFile, 'r')
        cf = cif.ReadCif(fp)
        fp.close()
        return cf
    except IOError:
        return cif.ReadCif(URLorFile)


@staticmethod
def domain_log(logs):
    """
        list logs:  The list of nameserversets to be pretty printed.
        """
    if 'resData' in logs:
        logs = logs['resData']
    count, total = 0, len(logs['domain'])
    output = '\n%i log entries:\n' % total
    for log in logs['domain']:
        count += 1
        output += (
            """%i of %i - %s status: '%s' price: %.2f invoice: %s date: %s remote address: %s
"""
             % (count, total, log['domain'], log['status'], log['price'],
            log['invoice'], log['date'], log['remoteAddr']))
        output += "           user text: '%s'\n" % log['userText'].replace('\n'
            , '\n           ')
    return output


@classmethod
def version_incremental_update(cls, options):
    """Performs incremental update of the content-view's version"""
    cls.command_sub = 'version incremental-update'
    if options is None:
        options = {}
    return cls.execute(cls._construct_command(options), output_format='csv')


def to_string(option, value):
    """
    Converts any values to strings when appropriate
    """
    try:
        value = value.__str__()
    except AttributeError:
        pass
    return option, value


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
         {
            "dynamic":true,
                "properties": {
                    "data": {
                        "properties": {
                            "versions_data": {
                                "dynamic":false,
                                "properties": {}
                            }
                        }
                    }
                }
        }
        """
    return {'items': mapping}


def _reduced_kernel_size_for_small_input(input_tensor, kernel_size):
    """Define kernel size which is automatically reduced for small input.

  If the shape of the input images is unknown at graph construction time this
  function assumes that the input images are is large enough.

  Args:
    input_tensor: input tensor of size [batch_size, height, width, channels].
    kernel_size: desired kernel size of length 2: [kernel_height, kernel_width]

  Returns:
    a tensor with the kernel size.

  TODO(jrru): Make this function work with unknown shapes. Theoretically, this
  can be done with the code below. Problems are two-fold: (1) If the shape was
  known, it will be lost. (2) inception.slim.ops._two_element_tuple cannot
  handle tensors that define the kernel size.
      shape = tf.shape(input_tensor)
      return = tf.stack([tf.minimum(shape[1], kernel_size[0]),
                         tf.minimum(shape[2], kernel_size[1])])

  """
    shape = input_tensor.get_shape().as_list()
    if shape[1] is None or shape[2] is None:
        kernel_size_out = kernel_size
    else:
        kernel_size_out = [min(shape[1], kernel_size[0]), min(shape[2],
            kernel_size[1])]
    return kernel_size_out


@staticmethod
def is_inactive():
    """
        Verify if the interface state is Inactive
        """
    return False


def _difference(data, names):
    """Data condition x subject"""
    data_differences = []
    diffnames = []
    diffnames_2lines = []
    for i, (name1, data1) in enumerate(zip(names, data)):
        for name2, data2 in zip(names[i + 1:], data[i + 1:]):
            data_differences.append(data1 - data2)
            diffnames.append('-'.join([name1, name2]))
            diffnames_2lines.append('-\n'.join([name1, name2]))
    return data_differences, diffnames, diffnames_2lines


def enable_subscriptions():
    """Enable subscriptions in that part of the site.
        """


def stash(create_new: bool=True):
    """Store this action in the NLA stack as a non-contributing strip for later use

    :param create_new: Create New Action, Create a new action once the existing one has been safely stored
    :type create_new: bool
    """
    pass


@classmethod
def create_instance_from_series(cls, series):
    """
        Create resolver cache instance from KomaPy series.

        :param series: KomaPy series config instance.
        :type series: :class:`komapy.series.Series`
        :return: KomaPy resolver cache instance.
        :rtype: :class:`komapy.cache.ResolverCache`
        """
    config = cls.get_resolver_cache_config(series)
    return cls(config)


def get_version(nb):
    """Get the version of a notebook.

    Parameters
    ----------
    nb : dict
        NotebookNode or dict containing notebook data.

    Returns
    -------
    Tuple containing major (int) and minor (int) version numbers
    """
    major = nb.get('nbformat', 1)
    minor = nb.get('nbformat_minor', 0)
    return major, minor


def bech32_polymod(values):
    """Internal function that computes the Bech32 checksum."""
    generator = [996825010, 642813549, 513874426, 1027748829, 705979059]
    chk = 1
    for value in values:
        top = chk >> 25
        chk = (chk & 33554431) << 5 ^ value
        for i in range(5):
            chk ^= generator[i] if top >> i & 1 else 0
    return chk


@classmethod
def from_box(cls, box, width=0.01, color=(0, 0, 0, 1)):
    """Duck type the box from a valid input.

        Boxes can be a list, dictionary, or object with attributes.
        """
    try:
        Lx = box.Lx
        Ly = box.Ly
        Lz = getattr(box, 'Lz', 0)
        xy = getattr(box, 'xy', 0)
        xz = getattr(box, 'xz', 0)
        yz = getattr(box, 'yz', 0)
    except AttributeError:
        try:
            Lx = box['Lx']
            Ly = box['Ly']
            Lz = box.get('Lz', 0)
            xy = box.get('xy', 0)
            xz = box.get('xz', 0)
            yz = box.get('yz', 0)
        except (IndexError, KeyError, TypeError):
            if not len(box) in [2, 3, 6]:
                raise ValueError(
                    'List-like objects must have length 2, 3, or 6 to be converted to a box.'
                    )
            Lx = box[0]
            Ly = box[1]
            Lz = box[2] if len(box) > 2 else 0
            xy, xz, yz = box[3:6] if len(box) == 6 else (0, 0, 0)
    return cls(Lx=Lx, Ly=Ly, Lz=Lz, xy=xy, xz=xz, yz=yz, width=width, color
        =color)


def _del(isdsAppliance, uuid):
    """
    Remove all UUIDs - should be everything pertaining to an advanced tuning parameter "key"

    :param isdsAppliance:
    :param uuid:
    :return:
    """
    ret_obj = isdsAppliance.create_return_object()
    ret_obj['data'] = []
    for u in uuid:
        r = isdsAppliance.invoke_delete(
            'Deleting existing advanced tuning parameter',
            '/adv_params/{0}'.format(u))
        ret_obj['changed'] = ret_obj['changed'] or r['changed']
        ret_obj['data'].append(r['data'])
        ret_obj['warnings'].extend(r['warnings'])
        ret_obj['rc'] += r['rc']
    return ret_obj


def casedict2xlsx():
    """
    Convert a full Cases.cases dict to Excel spreadsheets
    """


def fsplit(pred, objs):
    """Split a list into two classes according to the predicate."""
    t = []
    f = []
    for obj in objs:
        if pred(obj):
            t.append(obj)
        else:
            f.append(obj)
    return t, f


def logger_via_cli(opts, **kwargs):
    """
    Build and initialize logger from CLI specification.

    :param argparse.Namespace opts: parse of command-line interface
    :param kwargs: keyword arguments to pass along to underlying logmuse function
    :return logging.Logger: newly created and configured logger
    """
    from copy import deepcopy
    import logmuse
    kwds = deepcopy(kwargs)
    kwds.setdefault('strict', False)
    return logmuse.logger_via_cli(opts, **kwds)


def get_all(isamAppliance, instance_id, check_mode=False, force=False):
    """
    Retrieving the current administration pages root contents
    """
    return isamAppliance.invoke_get(
        'Retrieving the current administration pages root contents',
        '/wga/reverseproxy/{0}/management_root?recursive=yes'.format(
        instance_id))


def get_vault_lock(accountId=None, vaultName=None):
    """
    This operation retrieves the following attributes from the lock-policy subresource set on the specified vault:
    A vault lock is put into the InProgress state by calling  InitiateVaultLock . A vault lock is put into the Locked state by calling  CompleteVaultLock . You can abort the vault locking process by calling  AbortVaultLock . For more information about the vault locking process, Amazon Glacier Vault Lock .
    If there is no vault lock policy set on the vault, the operation returns a 404 Not found error. For more information about vault lock policies, Amazon Glacier Access Control with Vault Lock Policies .
    See also: AWS API Documentation

    Examples
    The example retrieves the attributes from the lock-policy subresource set on the vault named examplevault.
    Expected Output:

    :example: response = client.get_vault_lock(
        vaultName='string'
    )

    :type accountId: string
    :param accountId: The AccountId value is the AWS account ID of the account that owns the vault. You can either specify an AWS account ID or optionally a single '- ' (hyphen), in which case Amazon Glacier uses the AWS account ID associated with the credentials used to sign the request. If you use an account ID, do not include any hyphens ('-') in the ID.
            Note: this parameter is set to '-' bydefault if no value is not specified.

    :type vaultName: string
    :param vaultName: [REQUIRED]
            The name of the vault.

    :rtype: dict
    :return: {
        'Policy': 'string',
        'State': 'string',
        'ExpirationDate': 'string',
        'CreationDate': 'string'
    }

    :returns:
    accountId (string) -- The AccountId value is the AWS account ID of the account that owns the vault. You can either specify an AWS account ID or optionally a single '- ' (hyphen), in which case Amazon Glacier uses the AWS account ID associated with the credentials used to sign the request. If you use an account ID, do not include any hyphens ('-') in the ID.

    Note: this parameter is set to "-" bydefault if no value is not specified.

    vaultName (string) -- [REQUIRED]
    The name of the vault.

    """
    pass


@classmethod
def _unpack_new(cls, raw, offset, t, length, prev):
    """
    Unpacks the body portion of this option type into a new object

    Override me.
    """
    raise RuntimeError('Not implemented')


def print_info(kind, source):
    """Prints the source code.

    ``kind`` is usually either ``"Original"`` or ``"Transformed"``
    """
    print(f'==========={kind}============')
    print(source)
    print('-----------------------------')


@staticmethod
def _order_mapping(alterations):
    """Creates mapping of alterations to consecutive numeric values.

        Format: {type}_{value} --> {index}. Used when pivoting matrix, to ensure
        priority is followed when converting from long format to matrix.
        """
    order_mapping, colors = {}, []
    for data_type, val_order in alterations:
        for val, color in val_order:
            key = data_type + '_' + val
            order_mapping[key] = len(order_mapping)
            colors.append(color)
    return order_mapping, colors


def _get_column_letter(col_idx):
    """Convert a column number into a column letter (3 -> 'C')

    Right shift the column col_idx by 26 to find column letters in reverse
    order.  These numbers are 1-based, and can be converted to ASCII
    ordinals by adding 64.

    """
    if not 1 <= col_idx <= 18278:
        raise ValueError('Invalid column index {0}'.format(col_idx))
    letters = []
    while col_idx > 0:
        col_idx, remainder = divmod(col_idx, 26)
        if remainder == 0:
            remainder = 26
            col_idx -= 1
        letters.append(chr(remainder + 64))
    return ''.join(reversed(letters))


def gather_row(data, row_index):
    """Slice out the data given the row index.

    Parameters
    ----------
    data : Tensor
        The data tensor
    row_index : Tensor
        A 1-D integer tensor containing which rows to be sliced out.

    Returns
    -------
    Tensor
        The sliced data. The first dimension should equal to ``len(row_index)``.
    """
    pass


def _create_gcp_network_tag_id(vpc_partial_uri, tag):
    """
    Generate an ID for a GCP network tag
    :param vpc_partial_uri: The VPC that this tag applies to
    :return: An ID for the GCP network tag
    """
    return f'{vpc_partial_uri}/tags/{tag}'


def get_region(context):
    """
    Return the AWS account region for the executing lambda function.

    Args:
        context: AWS lambda Context Object http://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns:
        str : AWS Account Region

    """
    return str(context.invoked_function_arn.split(':')[3])


def load_ftplib(finder, module):
    """the ftplib module attempts to import the SOCKS module; ignore this
       module if it cannot be found"""
    module.IgnoreName('SOCKS')


def law_convolution(A, B):
    """ Construct the convolution of two laws (sum of independent variables from two input laws)
    :param A: first input law (dictionnary)
    :param B: second input law (dictionnary)
    """
    C = {}
    for a in A:
        for b in B:
            c = a + b
            C[c] = C.get(c, 0) + A[a] * B[b]
    return C


def merge_chunk_data(output_file='merged_idx_contig_hit_size_cov.txt', *files):
    """Merge chunk data from different networks

    Similarly to merge_network, this merges any number of chunk data files.

    Parameters
    ---------
    output_file : file, str, or pathlib.Path, optional
        The output file to write the merged chunk data files into. Default is
        merged_idx_contig_hit_size_cov.txt
    `*files` : file, str or pathlib.Path
        The chunk data files to merge.
    """
    chunks = dict()
    for chunk_file in files:
        with open(chunk_file) as chunk_file_handle:
            for line in chunk_file_handle:
                chunk_id, chunk_name, hit, size, cov = line.split('\t')
                try:
                    chunks[chunk_id]['hit'] += hit
                    chunks[chunk_id]['cov'] += cov
                except KeyError:
                    chunks[chunk_id] = {'name': chunk_name, 'hit': hit,
                        'size': size, 'cov': cov}
    sorted_chunks = sorted(chunks)
    with open(output_file, 'w') as output_handle:
        for chunk_id in sorted_chunks:
            my_chunk = chunks[chunk_id]
            name, hit, size, cov = my_chunk['name'], my_chunk['hit'], my_chunk[
                'size'], my_chunk['cov']
            my_line = '{}\t{}\t{}\t{}\t{}'.format(chunk_id, name, hit, size,
                cov)
            output_handle.write(my_line)


@staticmethod
def get_library_paths():
    """Override this method to return an iterable of possible library_paths
        to try in case that no argument is given.
        """
    return 'unset',


def errno_from_exception(e):
    """Provides the errno from an Exception object.

    There are cases that the errno attribute was not set so we pull
    the errno out of the args but if someone instantiates an Exception
    without any args you will get a tuple error. So this function
    abstracts all that behavior to give you a safe way to get the
    errno.
    """
    if hasattr(e, 'errno'):
        return e.errno
    elif e.args:
        return e.args[0]
    else:
        return None


def _fix2comp(num):
    """Convert from two's complement to negative."""
    assert 0 <= num < 2 ** 32
    if num & 2 ** 31:
        return num - 2 ** 32
    else:
        return num


def dpt_to_int(dpt: str) ->int:
    """Convert a dpt to an int"""
    if type(dpt) is int:
        return int(dpt)
    if dpt[0] == 'Z':
        return 0
    if dpt[1].upper() == 'A' or dpt[1].upper() == 'B':
        return 20
    else:
        return int(dpt)


@staticmethod
def _prepare_parameter_names(parameter_names):
    """
        Used for removing the '_' character from the parameter_names.
        """
    result = {}
    for param in parameter_names:
        result[param] = param.replace('_', '')
    return result


def convex_hull(delete_unused: bool=True, use_existing_faces: bool=True,
    make_holes: bool=False, join_triangles: bool=True, face_threshold:
    float=0.698132, shape_threshold: float=0.698132, uvs: bool=False, vcols:
    bool=False, seam: bool=False, sharp: bool=False, materials: bool=False):
    """Enclose selected vertices in a convex polyhedron

    :param delete_unused: Delete Unused, Delete selected elements that are not used by the hull
    :type delete_unused: bool
    :param use_existing_faces: Use Existing Faces, Skip hull triangles that are covered by a pre-existing face
    :type use_existing_faces: bool
    :param make_holes: Make Holes, Delete selected faces that are used by the hull
    :type make_holes: bool
    :param join_triangles: Join Triangles, Merge adjacent triangles into quads
    :type join_triangles: bool
    :param face_threshold: Max Face Angle, Face angle limit
    :type face_threshold: float
    :param shape_threshold: Max Shape Angle, Shape angle limit
    :type shape_threshold: float
    :param uvs: Compare UVs
    :type uvs: bool
    :param vcols: Compare VCols
    :type vcols: bool
    :param seam: Compare Seam
    :type seam: bool
    :param sharp: Compare Sharp
    :type sharp: bool
    :param materials: Compare Materials
    :type materials: bool
    """
    pass


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


def dyn2kin(dyn, density):
    """

    Convert from dynamic to kinematic viscosity.

    Parameters
    ----------
    dyn: ndarray, scalar
        The dynamic viscosity of the lubricant.
    density: ndarray, scalar
        The density of the lubricant.

    Returns
    -------
    kin: ndarray, scalar
        The kinematic viscosity of the lubricant.

    """
    kin = dyn / density
    return kin


def vertex_color_levels(offset: float=0.0, gain: float=1.0):
    """Adjust levels of vertex colors

    :param offset: Offset, Value to add to colors
    :type offset: float
    :param gain: Gain, Value to multiply colors by
    :type gain: float
    """
    pass


def potrf(A=None, out=None, name=None, **kwargs):
    """Performs Cholesky factorization of a symmetric positive-definite matrix.
    Input is a tensor *A* of dimension *n >= 2*.

    If *n=2*, the Cholesky factor *B* of the symmetric, positive definite matrix *A* is
    computed. *B* is triangular (entries of upper or lower triangle are all zero), has
    positive diagonal entries, and:

      *A* = *B* \\* *B*\\ :sup:`T`  if *lower* = *true*
      *A* = *B*\\ :sup:`T` \\* *B*  if *lower* = *false*

    If *n>2*, *potrf* is performed separately on the trailing two dimensions for all inputs
    (batch mode).

    .. note:: The operator supports float32 and float64 data types only.

    Examples::

       Single matrix factorization
       A = [[4.0, 1.0], [1.0, 4.25]]
       potrf(A) = [[2.0, 0], [0.5, 2.0]]

       Batch matrix factorization
       A = [[[4.0, 1.0], [1.0, 4.25]], [[16.0, 4.0], [4.0, 17.0]]]
       potrf(A) = [[[2.0, 0], [0.5, 2.0]], [[4.0, 0], [1.0, 4.0]]]

    Defined in src/operator/tensor/la_op.cc:L214

    Parameters
    ----------
    A : NDArray
        Tensor of input matrices to be decomposed

    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 path_shift(script_name, path_info, shift=1):
    """ Shift path fragments from PATH_INFO to SCRIPT_NAME and vice versa.

        :return: The modified paths.
        :param script_name: The SCRIPT_NAME path.
        :param script_name: The PATH_INFO path.
        :param shift: The number of path fragments to shift. May be negative to
          change the shift direction. (default: 1)
    """
    if shift == 0:
        return script_name, path_info
    pathlist = path_info.strip('/').split('/')
    scriptlist = script_name.strip('/').split('/')
    if pathlist and pathlist[0] == '':
        pathlist = []
    if scriptlist and scriptlist[0] == '':
        scriptlist = []
    if 0 < shift <= len(pathlist):
        moved = pathlist[:shift]
        scriptlist = scriptlist + moved
        pathlist = pathlist[shift:]
    elif 0 > shift >= -len(scriptlist):
        moved = scriptlist[shift:]
        pathlist = moved + pathlist
        scriptlist = scriptlist[:shift]
    else:
        empty = 'SCRIPT_NAME' if shift < 0 else 'PATH_INFO'
        raise AssertionError('Cannot shift. Nothing left from %s' % empty)
    new_script_name = '/' + '/'.join(scriptlist)
    new_path_info = '/' + '/'.join(pathlist)
    if path_info.endswith('/') and pathlist:
        new_path_info += '/'
    return new_script_name, new_path_info


def calculate_shape(new_shape, orig_shape):
    """Calculate a new image shape given the desired width and/or height.

    Parameters
    ----------
    new_shape : tuple
        The desired height and/or width of the image. Each may be None.
    orig_shape : tuple
        The shape of the original image. Will be used to calculate the
        width and height in case one or both are None.

    Returns
    -------
    tuple
        The output shape

    """
    if new_shape is None:
        return orig_shape
    height, width = new_shape
    if height is None:
        if width is not None:
            height = width * orig_shape[0] / orig_shape[1]
        else:
            height = orig_shape[0]
            width = orig_shape[1]
    elif width is None:
        width = height * orig_shape[1] / orig_shape[0]
    return int(height), int(width)


def listSearchCriteria():
    """Return a list of our search criteria objects.
        """


def print_unicode(msg, end='\n', err='?'):
    """print `msg`, replacing unicode characters with `err` upon failure"""
    for c in msg:
        try:
            print(c, end='')
        except UnicodeEncodeError:
            print(err, end='')
    print('', end=end)


def bit(value, i):
    """Extract the i-th bit out of value."""
    return 1 if value & 1 << i else 0


@classmethod
def set_label(cls, label):
    """
        update the internal counter if needed
        """
    if len(label) == 1:
        code = ord(label) - 97
    elif len(label) == 2:
        code = (ord(label[0]) - 96) * 26 + (ord(label[1]) - 97)
    else:
        code = (ord(label[0]) - 96) * 26 * 26 + (ord(label[1]) - 97) * 26 + (
            ord(label) - 97)
    if cls.last_label <= code:
        cls.last_label = code + 1
    return code


def safe_repr(obj, clip=None):
    """
    Convert object to string representation, yielding the same result a `repr`
    but catches all exceptions and returns 'N/A' instead of raising the
    exception. Strings may be truncated by providing `clip`.

    >>> safe_repr(42)
    '42'
    >>> safe_repr('Clipped text', clip=8)
    'Clip..xt'
    >>> safe_repr([1,2,3,4], clip=8)
    '[1,2..4]'
    """
    try:
        s = repr(obj)
        if not clip or len(s) <= clip:
            return s
        else:
            return s[:clip - 4] + '..' + s[-2:]
    except:
        return 'N/A'


def getid(obj):
    """Wrapper to get  object's ID.

    Abstracts the common pattern of allowing both an object or an
    object's ID (UUID) as a parameter when dealing with relationships.
    """
    try:
        return obj.id
    except AttributeError:
        return obj


def flatten_cluster(cluster):
    """Set the altitudes for all detectors in a cluster object to z=0

    Modify the given cluster by setting the z coordinates of the stations
    and detectors to 0.

    :param cluster: :class:`BaseCluster` object.

    """
    for station in cluster.stations:
        station.z = [0.0] * len(station.z)
        for detector in station.detectors:
            detector.z = [0.0] * len(detector.z)


def create_tape_with_barcode(GatewayARN=None, TapeSizeInBytes=None,
    TapeBarcode=None):
    """
    Creates a virtual tape by using your own barcode. You write data to the virtual tape and then archive the tape. This operation is only supported in the tape gateway architecture.
    See also: AWS API Documentation

    Examples
    Creates a virtual tape by using your own barcode.
    Expected Output:

    :example: response = client.create_tape_with_barcode(
        GatewayARN='string',
        TapeSizeInBytes=123,
        TapeBarcode='string'
    )

    :type GatewayARN: string
    :param GatewayARN: [REQUIRED]
            The unique Amazon Resource Name (ARN) that represents the gateway to associate the virtual tape with. Use the ListGateways operation to return a list of gateways for your account and region.

    :type TapeSizeInBytes: integer
    :param TapeSizeInBytes: [REQUIRED]
            The size, in bytes, of the virtual tape that you want to create.
            Note
            The size must be aligned by gigabyte (1024*1024*1024 byte).

    :type TapeBarcode: string
    :param TapeBarcode: [REQUIRED]
            The barcode that you want to assign to the tape.

    :rtype: dict
    :return: {
        'TapeARN': 'string'
    }

    """
    pass


def class_info(cls):
    """ Return the information about activity.

        Returns
        -------
        : dict
            Information about class of activity.
        """
    return cls._class_info


def parse_tokens(parser, tokens):
    """
    Shortcut for parsing args/kwargs from a list of tokens
    """
    args = []
    kwargs = []
    for token in tokens:
        if '=' in token:
            key, token = token.split('=')
            kwargs.append((key, parser.compile_filter(token)))
        else:
            args.append(parser.compile_filter(token))
    return args, dict(kwargs)


def finish_stroke():
    """End and keep the current sketch stroke

    """
    pass


@classmethod
def as_version(cls, number):
    """Convert version number to version object"""
    if isinstance(number, cls):
        return number
    return cls([number])


def func_gte(parser, x, y):
    """Returns true, if ``x`` is greater than or equals ``y``."""
    try:
        if int(x) >= int(y):
            return '1'
    except ValueError:
        pass
    return ''


def ping(*args, **kwargs):
    """
    Check if current application is running.

    :return: Pong response.
    """
    return {'pong': True}


def create_snapshot(ReplicationGroupId=None, CacheClusterId=None,
    SnapshotName=None):
    """
    Creates a copy of an entire cache cluster or replication group at a specific moment in time.
    See also: AWS API Documentation

    :example: response = client.create_snapshot(
        ReplicationGroupId='string',
        CacheClusterId='string',
        SnapshotName='string'
    )

    :type ReplicationGroupId: string
    :param ReplicationGroupId: The identifier of an existing replication group. The snapshot is created from this replication group.

    :type CacheClusterId: string
    :param CacheClusterId: The identifier of an existing cache cluster. The snapshot is created from this cache cluster.

    :type SnapshotName: string
    :param SnapshotName: [REQUIRED]
            A name for the snapshot being created.

    :rtype: dict
    :return: {
        'Snapshot': {
            'SnapshotName': 'string',
            'ReplicationGroupId': 'string',
            'ReplicationGroupDescription': 'string',
            'CacheClusterId': 'string',
            'SnapshotStatus': 'string',
            'SnapshotSource': 'string',
            'CacheNodeType': 'string',
            'Engine': 'string',
            'EngineVersion': 'string',
            'NumCacheNodes': 123,
            'PreferredAvailabilityZone': 'string',
            'CacheClusterCreateTime': datetime(2015, 1, 1),
            'PreferredMaintenanceWindow': 'string',
            'TopicArn': 'string',
            'Port': 123,
            'CacheParameterGroupName': 'string',
            'CacheSubnetGroupName': 'string',
            'VpcId': 'string',
            'AutoMinorVersionUpgrade': True|False,
            'SnapshotRetentionLimit': 123,
            'SnapshotWindow': 'string',
            'NumNodeGroups': 123,
            'AutomaticFailover': 'enabled'|'disabled'|'enabling'|'disabling',
            'NodeSnapshots': [
                {
                    'CacheClusterId': 'string',
                    'NodeGroupId': 'string',
                    'CacheNodeId': 'string',
                    'NodeGroupConfiguration': {
                        'Slots': 'string',
                        'ReplicaCount': 123,
                        'PrimaryAvailabilityZone': 'string',
                        'ReplicaAvailabilityZones': [
                            'string',
                        ]
                    },
                    'CacheSize': 'string',
                    'CacheNodeCreateTime': datetime(2015, 1, 1),
                    'SnapshotCreateTime': datetime(2015, 1, 1)
                },
            ]
        }
    }

    :returns:
    General purpose:
    Current generation: cache.t2.micro , cache.t2.small , cache.t2.medium , cache.m3.medium , cache.m3.large , cache.m3.xlarge , cache.m3.2xlarge , cache.m4.large , cache.m4.xlarge , cache.m4.2xlarge , cache.m4.4xlarge , cache.m4.10xlarge
    Previous generation: cache.t1.micro , cache.m1.small , cache.m1.medium , cache.m1.large , cache.m1.xlarge

    Compute optimized: cache.c1.xlarge
    Memory optimized:
    Current generation: cache.r3.large , cache.r3.xlarge , cache.r3.2xlarge , cache.r3.4xlarge , cache.r3.8xlarge
    Previous generation: cache.m2.xlarge , cache.m2.2xlarge , cache.m2.4xlarge

    """
    pass


def addQuotationTag(quoteIndexToNode):
    """
        Add the tag "QUOTATION" to all nodes in quoteIndexToNode.
    """
    for c in quoteIndexToNode.values():
        c.namedEntityTag = 'QUOTATION'


def x_pixels_to_domain(pixels, axis, layout):
    """ Convert a pixel distance to a domain distance """
    domain = axis.domain
    a = domain / layout.chart_width
    shift = a * pixels
    return shift


@classmethod
def _build_query_languages(cls, language=None):
    """
        Build the languages used to provide the Label Service within the SPARQL Query.

        Args:
            language (Optional[str]): Set the Primary language. If not set, will default to Meta Option.

        Returns (str):

        """
    return f'{language or cls.Meta.language},{cls.Meta.fallback_languages}'


def color(teffs):
    """
    Conventional color descriptions of stars.
    Source: https://en.wikipedia.org/wiki/Stellar_classification
    """
    colors = []
    for t in teffs:
        if t >= 7500:
            colors.append('blue_white')
        elif t >= 6000:
            colors.append('white')
        elif t >= 5200:
            colors.append('yellowish_white')
        elif t >= 3700:
            colors.append('pale_yellow_orange')
        else:
            colors.append('light_orange_red')
    return colors


@classmethod
def global_config(cls, key, *args):
    """ This reads or sets the global settings stored in class.settings. """
    if args:
        cls.settings = cls.settings.copy()
        cls.settings[key] = args[0]
    else:
        return cls.settings[key]


@classmethod
def __insert_into(cls, table: str=None, **kwargs) ->str:
    """        Build insert statement.

        :param table:
            target table name from the data base

        :return
            MySQL insert statement
        """
    cols = ','.join(['%s'] * len(kwargs)) % tuple(kwargs.keys())
    vals = []
    for v in kwargs.values():
        if v != 'NULL' and isinstance(v, str):
            vals = vals + [f"'{v}'"]
        else:
            vals = vals + [str(v)]
    vals = ','.join(vals)
    que = f'INSERT INTO {table} ({cols}) VALUES ({vals})'
    return que


def encode_synchsafe_int(i, per_byte):
    """Encode synchsafe integers for ID3v2 tags."""
    if i > 2 ** (per_byte * 4) - 1:
        raise ValueError(
            f'{i} is too large to be represented by a synchsafe integer with {per_byte} bits per byte.'
            )
    v = 0
    mask = 127
    value = i
    while mask ^ 2147483647 > 0:
        v = value & ~mask
        v = v << 8 - per_byte
        v = v | value & mask
        mask = (mask + 1 << 8) - 1
        value = v
    return value.to_bytes(4, byteorder='big')


def copy_service_to_services_forward(apps, schema_editor):
    """Copy the service from ForeignKeyField to ManyToManyField."""
    Incident = apps.get_model('statusboard', 'incident')
    db_alias = schema_editor.connection.alias
    for i in Incident.objects.using(db_alias).filter(service__isnull=False
        ).all():
        i.services.add(i.service)
        i.save()


@classmethod
def return_or_raise(cls, response, expected_status_code):
    """Check for ``expected_status_code``."""
    try:
        if response.status_code in expected_status_code:
            return response
    except TypeError:
        if response.status_code == expected_status_code:
            return response
    raise cls(response)


def is_unknown_license(lic_key):
    """
    Return True if a license key is for some lesser known or unknown license.
    """
    return lic_key.startswith(('unknown', 'other-')) or 'unknown' in lic_key


def list_to_file(filename, data):
    """Makes a text document from a :py:obj:`list`  of data, with each line of the document being one item from the list
     and outputs the document into a file.

     :param file_handle filename: A path to the output file.
     :param data: A Python :py:obj:`list`.
     """
    with open(filename + '.txt', 'wt') as out_file:
        for line in data:
            out_file.write(str(line) + '\n')


def stencil_reset_transform(mask: bool=False):
    """Reset the stencil transformation to the default

    :param mask: Modify Mask Stencil, Modify either the primary or mask stencil
    :type mask: bool
    """
    pass


def fix_value(synonym, final):
    """Fix value for synonym"""
    if not synonym.value or synonym.value == 'now(n/a)':
        return
    if final.value and final.value != 'now(n/a)':
        return
    final.value = synonym.value


def d2h(d):
    """Convert degrees into hours."""
    return d * (24.0 / 360.0)


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


def canonical_object():
    """The current "canonical" object.

        That is, the current object unless this object is the default page
        in its folder, in which case the folder is returned.
        """


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

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


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


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

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


@staticmethod
def long_name_type():
    """
        Returns the long name type for this port.

        :returns: string
        """
    return 'POS'


def get_buildsys_types():
    """Returns the available build system implementations - cmake, make etc."""
    from rez.plugin_managers import plugin_manager
    return plugin_manager.get_plugins('build_system')


def get_rule_doc(name):
    """Decode and return the docstring(s) of a sequana/snakemake rule."""
    try:
        from sequana import Module
        rule = Module(name)
        filename = rule.path + '/%s.rules' % name
        data = open(filename, 'r').read()
    except ValueError:
        data = open(name, 'r').read()
    if name.endswith('_dynamic'):
        name = name[:-8]
    rulename_tag = 'rule %s' % name
    if rulename_tag in data:
        data = data.split(rulename_tag, 1)[1]
    else:
        return 'no docstring found for %s ' % name
    single = data.find("'''")
    double = data.find('"""')
    if single > 0 and double > 0:
        if single > double:
            quotes = '"""'
        else:
            quotes = "'''"
    elif single > 0:
        quotes = "'''"
    elif double > 0:
        quotes = '"""'
    else:
        return 'no docstring found for %s ' % name
    start = data.find(quotes)
    end = data[start + 3:].find(quotes) + start + 3
    if end == -1 or end < start:
        return 'no end of docstring found for %s ' % name
    docstring = data[start + 3:end]
    return docstring


def circumcircle_of_a_triangle(a, b, c):
    """
    Calculates the radius and area of the circumcircle of a triangle given the three sides.

    s = (a + b + c) / 2
    _circumcirle_radius = r = (a * b * c) / (s * (s - a) * (s - b) * (s - c))**(1/4)
    _circumcirle_area = Sc = pi * (r ** 2)
    _triangle_area = St = (s * (s - a) * (s - b) * (s - c))**0.5
    return r,Sc,St
    """
    pass


@classmethod
def load(cls, load_path, env=None, custom_objects=None, **kwargs):
    """
        Load the model from file

        :param load_path: (str or file-like) the saved parameter location
        :param env: (Gym Environment) the new environment to run the loaded model on
            (can be None if you only need prediction from a trained model)
        :param custom_objects: (dict) Dictionary of objects to replace
            upon loading. If a variable is present in this dictionary as a
            key, it will not be deserialized and the corresponding item
            will be used instead. Similar to custom_objects in
            `keras.models.load_model`. Useful when you have an object in
            file that can not be deserialized.
        :param kwargs: extra arguments to change the model when loading
        """
    data, params = cls._load_from_file(load_path, custom_objects=custom_objects
        )
    if 'policy_kwargs' in kwargs and kwargs['policy_kwargs'] != data[
        'policy_kwargs']:
        raise ValueError(
            'The specified policy kwargs do not equal the stored policy kwargs. Stored kwargs: {}, specified kwargs: {}'
            .format(data['policy_kwargs'], kwargs['policy_kwargs']))
    model = cls(policy=data['policy'], env=None, _init_setup_model=False)
    model.__dict__.update(data)
    model.__dict__.update(kwargs)
    model.set_env(env)
    model.setup_model()
    model.load_parameters(params)
    return model


def split_first(s, delims):
    """
    Given a string and an iterable of delimiters, split on the first found
    delimiter. Return two split parts and the matched delimiter.

    If not found, then the first part is the full input string.

    Example::

        >>> split_first('foo/bar?baz', '?/=')
        ('foo', 'bar?baz', '/')
        >>> split_first('foo/bar?baz', '123')
        ('foo/bar?baz', '', None)

    Scales linearly with number of delims. Not ideal for large number of delims.
    """
    min_idx = None
    min_delim = None
    for d in delims:
        idx = s.find(d)
        if idx < 0:
            continue
        if min_idx is None or idx < min_idx:
            min_idx = idx
            min_delim = d
    if min_idx is None or min_idx < 0:
        return s, '', None
    return s[:min_idx], s[min_idx + 1:], min_delim


def mapping_2cols(orig_df, colx, coly):
    """
    return dict mapping vals in colx to coly. Order is important.
    """
    return dict(orig_df[[colx, coly]].drop_duplicates().values)


@staticmethod
def gauss(n, a, b, pivot):
    """Gaussian elimination"""
    for i in range(n):
        if i < n - 1:
            a, b = pivot(n, i, a, b)
        a[i, i] = 1 / a[i, i]
        b[i] *= a[i, i]
        if i < n - 1:
            for j in range(i + 1, n + 1):
                a[i, j] *= a[i, i]
            for k in range(i + 1, n):
                b[k] -= a[k, i] * b[i]
                for j in range(i + 1, n):
                    a[k, j] -= a[k, i] * a[i, j]
    for i in range(n - 2, -1, -1):
        for j in range(i + 1, n):
            b[i] -= a[i, j] * b[j]
    return a, b


def prop_nodes(graph, nodes_generator, message_func='default', reduce_func=
    'default', apply_node_func='default'):
    """Functional method for :func:`dgl.DGLGraph.prop_nodes`.

    Parameters
    ----------
    node_generators : generator
        The generator of node frontiers.
    message_func : callable, optional
        The message function.
    reduce_func : callable, optional
        The reduce function.
    apply_node_func : callable, optional
        The update function.

    See Also
    --------
    dgl.DGLGraph.prop_nodes
    """
    graph.prop_nodes(nodes_generator, message_func, reduce_func,
        apply_node_func)


def _pyhastls():
    """Returns true iff Python has TLS support, false otherwise."""
    try:
        import ssl
        getattr(ssl, 'HAS_TLS', False)
        return True
    except ImportError:
        return False


def dotnorm(arg, coords):
    """normal component"""
    return sum(arg * coords.normal(), -1)


def load_handlers(name):
    """Load the (URL pattern, handler) tuples for each component."""
    mod = __import__(name, fromlist=['default_handlers'])
    return mod.default_handlers


@classmethod
def name_of_class(cls) ->str:
    """
        A string name for the class, with the prior suffix removed.
        """
    return cls.__name__.replace('WidthModifier', '')


def specific_area_mesh(voidage, d):
    """Calculates the specific area of a wire mesh, as used in demisters or
    filters. Shown in [1]_, and also self-evident and non-empirical.
    Makes the ideal assumption that wires never touch.

    .. math::
        S = \\frac{4(1-\\epsilon)}{d_{wire}}

    Parameters
    ----------
    voidage : float
        Voidage of the mesh []
    d : float
        Diameter of the wires making the mesh, [m]

    Returns
    -------
    S : float
        Specific area of the mesh [m^2/m^3]

    Notes
    -----
    Should be preferred over manufacturer data. Can also be used to show that
    manufacturer's data is inconsistent with their claimed voidage and wire
    diameter.

    Examples
    --------
    >>> specific_area_mesh(voidage=.934, d=3e-4)
    879.9999999999994

    References
    ----------
    .. [1] Helsør, T., and H. Svendsen. "Experimental Characterization of
       Pressure Drop in Dry Demisters at Low and Elevated Pressures." Chemical
       Engineering Research and Design 85, no. 3 (2007): 377-85.
       doi:10.1205/cherd06048.
    """
    return 4 * (1 - voidage) / d


def below_above_gen(x, y):
    """
    (y, x) if x > y else (x, y)
    :param x: 支持比较操作的对象
    :param y: 支持比较操作的对象
    """
    return (y, x) if x > y else (x, y)


def describe_builtin(obj):
    """ Describe a builtin function if obj.__doc__
    available.

    Parameters
    ----------
    obj : python object

    Returns
    -------
    iterator : builtin args
    """
    docstr = obj.__doc__
    args = ''
    if docstr:
        items = docstr.split('\n')
        if items:
            func_descr = items[0]
            s = func_descr.replace(obj.__name__, '')
            idx1 = s.find('(')
            idx2 = s.find(')', idx1)
            if idx1 != -1 and idx2 != -1 and idx2 > idx1 + 1:
                args = s[idx1 + 1:idx2]
                for arg in args:
                    yield arg
    if args == '':
        yield None


def _part(string):
    """Transform a part string (I, II or III) into an integer"""
    if string == 'I':
        return 1
    elif string == 'II':
        return 2
    elif string == 'III':
        return 3
    elif string == 'IV':
        return 4


@classmethod
def _load_model(cls, model_path):
    """
        Load model from cli. Derived classes must implement this method if they
        support loading from disk.

        Parameters
        ----------
        model_path : 'str'
            Path from which to load model

        Returns
        -------
        model
        """
    pass


def plural(n, singular, plural, with_number=True):
    """Return the singular or plural form of a word, according to the number.

    If ``with_number`` is true (default), the return value will be the number
    followed by the word. Otherwise the word alone will be returned.
    """
    if n == 1:
        form = singular
    else:
        form = plural
    if with_number:
        return '%s %s' % (n, form)
    else:
        return form


@staticmethod
def create_checkpoint(initial_position):
    """Returns a checkpoint object that will begin reading the log file from the specified position.

        @param initial_position: The byte position in the file where copying should begin.

        @return: The check point representing the position of the iterator.
        @rtype: dict
        """
    return {'initial_position': initial_position}


def case_toggle():
    """Toggle font case

    """
    pass


def _inject_mutations_1D_X(phi, dt, xx, theta0, beta, alpha):
    """
    Inject novel mutations for a timestep.
    """
    factor = 2.0 / (1.0 + 2.0 * beta) * (1.0 / (alpha + 1.0) + beta)
    phi[1] += dt / xx[1] * theta0 / 2.0 * factor * 2.0 / (xx[2] - xx[0])
    return phi


def filename():
    """ return an associated filename, or `None` """


def get_environment_var_name_from_string(string):
    """ Strips out the Variable name from a string
    :param string: e.g. $MY_PATH:$YOUR_PATH
    :return string: e.g. MY_PATH
    """
    key = ''
    for char in string:
        if char.isalpha() or char.isdigit() or char == '_':
            key += char
        else:
            return key
    return key


def color_scale_columns(df, matplotlib_cmap='Greens', subset=None):
    """DataFrame Styler:
    Takes a df, any valid matplotlib colormap column names
    (matplotlib.org/tutorials/colors/colormaps.html) and
    returns a dataframe with a gradient colormap applied to column values.

    Example:
    df_styled = color_scale_columns(df,cmap = "YlGn",subset=['Columns','to','color'])

    Parameters:
    -----------
        df:
            DataFrame containing columns to style.
    subset:
         Names of columns to color-code.
    cmap:
        Any matplotlib colormap.
        https://matplotlib.org/tutorials/colors/colormaps.html

    Returns:
    ----------
        df_style:
            styled dataframe.

    """
    from IPython.display import display
    import seaborn as sns
    cm = matplotlib_cmap
    df_style = df.style.background_gradient(cmap=cm, subset=subset)
    return df_style


def _describe_timeseries(ts):
    """
    Describes a cmf timeseries with its start, end, step, min, mean and max.

    :param: ts: a cmf.timeseries
    :return: None
    """
    if ts:
        return (
            '{count} values from {start:%Y-%m-%d} to {end:%Y-%m-%d} step {step}, min/mean/max  {min:0.5g} / {mean:0.5g} / {max:0.5g}'
            .format(count=len(ts), start=ts.begin.AsPython(), end=ts.end.
            AsPython(), step=ts.step, min=ts.min(), mean=ts.mean(), max=ts.
            max()))
    else:
        return '~'


@staticmethod
def static_example():
    """
        @return a boolean
        """
    return True


@classmethod
def from_surface(cls, vertices, nvertex, name='Other'):
    """
        Creates a new BrainModelAxis axis describing the vertices on a surface

        Parameters
        ----------
        vertices : array_like
            indices of the vertices on the surface
        nvertex : int
            total number of vertices on the surface
        name : str
            Name of the brain structure (e.g. 'CortexLeft' or 'CortexRight')

        Returns
        -------
        BrainModelAxis which covers (part of) the surface
        """
    cifti_name = cls.to_cifti_brain_structure_name(name)
    return cls(cifti_name, vertex=vertices, nvertices={cifti_name: nvertex})


def lennard_jones(rsq, epsilon, sigma):
    """
    Lennard-Jones potential.

    u(r) = 4 * epsilon * [(r/sigma)^12 - (r/sigma)^6]
    """
    sigsq = sigma ** 2
    u = 4 * epsilon * ((sigsq / rsq) ** 6 - (sigsq / rsq) ** 3)
    w = 24 * epsilon * (2 * (sigsq / rsq) ** 6 - (sigsq / rsq) ** 3) / rsq
    h = 96 * epsilon * (7 * (sigsq / rsq) ** 6 - 2 * (sigsq / rsq) ** 3
        ) / rsq ** 2
    return u, w, h


def normalizeBox(box):
    """
    Convert any negative measurements in the current
    box to positive, and adjust the origin.
    """
    x, y, w, h = box
    if w < 0:
        x += w + 1
        w *= -1
    if h < 0:
        y += h + 1
        h *= -1
    return x, y, w, h


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


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


@staticmethod
def default_update(action):
    """
        Default value of :attr:`update`.  Literally performs:

        ..  code-block:: python

            action.tree[action.key] = action.value

        :param UpdateAction action: Current action object

        """
    action.tree[action.key] = action.value


def transform(cluster_location, data, verbose=False):
    """
    Trainsform values around significant cluster
    """
    i = cluster_location[0]
    j = cluster_location[1]
    n = len(data)
    t = 1 - data[j] + data[i]
    new_data = []
    for k in range(n):
        if 0 <= k and k <= i:
            new_data.append(data[k] / t)
        elif i + 1 <= k and k <= n - 1 - j + i:
            new_data.append((data[k + j - i] - data[j] + data[i]) / t)
        if verbose == True:
            print(f'repositioning data: [ {k} : , {data[k]} ] \n')
    return new_data


def duplicate_move(GRAPH_OT_duplicate=None, TRANSFORM_OT_transform=None):
    """Make a copy of all selected keyframes and move them

    :param GRAPH_OT_duplicate: Duplicate Keyframes, Make a copy of all selected keyframes
    :param TRANSFORM_OT_transform: Transform, Transform selected items by mode type
    """
    pass


def _object_from_string(instance, vstr):
    """
    Create a Pyomo object from a string; it is attached to instance
    args:
        instance: a concrete pyomo model
        vstr: a particular Var or Param (e.g. "pp.Keq_a[2]")
    output:
        the object
    NOTE: We need to deal with blocks
          and with indexes that might really be strings or ints
    """
    l = vstr.find('[')
    if l == -1:
        indexstr = None
        basestr = vstr
    else:
        r = vstr.find(']')
        indexstr = vstr[l + 1:r]
        basestr = vstr[:l]
    parts = basestr.split('.')
    name = parts[-1]
    retval = instance
    for i in range(len(parts) - 1):
        retval = getattr(retval, parts[i])
    retval = getattr(retval, name)
    if indexstr is None:
        return retval
    try:
        indexstr = int(indexstr)
    except:
        pass
    return retval[indexstr]


def pairwise_squared_distance(x):
    """
    x : (n_samples, n_points, dims)
    return : (n_samples, n_points, n_points)
    """
    x2s = (x * x).sum(-1, keepdim=True)
    return x2s + x2s.transpose(-1, -2) - 2 * x @ x.transpose(-1, -2)


@classmethod
def dependents_key_for(cls, job_id):
    """The Redis key that is used to store job dependents hash under."""
    return '{0}{1}:dependents'.format(cls.redis_job_namespace_prefix, job_id)


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 cross_vectors(u, v):
    """Compute the cross product of two vectors.

    Parameters
    ----------
    u : tuple, list, Vector
        XYZ components of the first vector.
    v : tuple, list, Vector
        XYZ components of the second vector.

    Returns
    -------
    cross : list
        The cross product of the two vectors.

    Notes
    -----
    The xyz components of the cross product of two vectors :math:`\\mathbf{u}`
    and :math:`\\mathbf{v}` can be computed as the *minors* of the following matrix:

    .. math::
       :nowrap:

        \\begin{bmatrix}
        x & y & z \\\\
        u_{x} & u_{y} & u_{z} \\\\
        v_{x} & v_{y} & v_{z}
        \\end{bmatrix}

    Therefore, the cross product can be written as:

    .. math::
       :nowrap:

        \\mathbf{u} \\times \\mathbf{v}
        =
        \\begin{bmatrix}
        u_{y} * v_{z} - u_{z} * v_{y} \\\\
        u_{z} * v_{x} - u_{x} * v_{z} \\\\
        u_{x} * v_{y} - u_{y} * v_{x}
        \\end{bmatrix}

    Examples
    --------
    >>> cross_vectors([1.0, 0.0, 0.0], [0.0, 1.0, 0.0])
    [0.0, 0.0, 1.0]

    """
    return [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[
        1] - u[1] * v[0]]


def srm_to_l(srm):
    """
    Convert the SRM value to Lovibond
    https://en.wikipedia.org/wiki/Standard_Reference_Method
    """
    return (srm + 0.76) / 1.3546


def _is_forked(gate):
    """Determine if a gate is forked.

    Args:
        gate (pyquil.quil.Gate): The gate that should be checked

    Returns:
        bool: True if the gate is forked, False otherwise
    """
    return 'FORKED' in gate.modifiers


def decode_to_string(toDecode):
    """
    This function is needed for Python 3,
    because a subprocess can return bytes instead of a string.
    """
    try:
        return toDecode.decode('utf-8')
    except AttributeError:
        return toDecode


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


def onlywhite(line):
    """Return true if the line does only consist of whitespace characters."""
    for c in line:
        if c is not ' ' and c is not '  ':
            return c is ' '
    return line


def _filename(repo):
    """name of a tagcache file for a given repo or repoview"""
    filename = b'tags2'
    if repo.filtername:
        filename = b'%s-%s' % (filename, repo.filtername)
    return filename


def calc_reduction_layers(num_cells, num_reduction_layers):
    """Figure out what layers should have reductions."""
    reduction_layers = []
    for pool_num in range(1, num_reduction_layers + 1):
        layer_num = float(pool_num) / (num_reduction_layers + 1) * num_cells
        layer_num = int(layer_num)
        reduction_layers.append(layer_num)
    return reduction_layers


@classmethod
def has_attr(cls, attr_name):
    """Check to see if an attribute is defined for the model."""
    if attr_name in cls.attrs:
        return True
    if isinstance(cls.primary_key_name, str
        ) and cls.primary_key_name == attr_name:
        return True
    if isinstance(cls.primary_key_name, tuple
        ) and attr_name in cls.primary_key_name:
        return True
    if cls.timestamps is not None and attr_name in cls.timestamps:
        return True
    return False


def redirect_show(show_tuple, redirections, tracker_list):
    """ Use a redirection dictionary and return the new show ID and episode acordingly """
    if not redirections:
        return show_tuple
    show, ep = show_tuple
    showlist = tracker_list[0]
    if show['id'] in redirections:
        for redirection in redirections[show['id']]:
            src_eps, dst_id, dst_eps = redirection
            if src_eps[1] == -1 and ep > src_eps[0] or ep in range(src_eps[
                0], src_eps[1] + 1):
                new_show_id = dst_id
                new_ep = ep + (dst_eps[0] - src_eps[0])
                if new_show_id in showlist:
                    return showlist[new_show_id], new_ep
    return show_tuple


def green_schedule():
    """Switches to another green thread.

    .. note:: Alias for ``suspend``.

    * http://uwsgi.readthedocs.io/en/latest/Async.html#suspend-resume

    :type: bool
    """
    return False


def set_config_file(config_file):
    """
    Public function to allow other modules to change the config file
    This does not load the settings into the config parser
    :param config_file:
    :return:
    """
    global _user_config_file
    _user_config_file = config_file


def decode_string(s):
    """Decode bytes array
    """
    try:
        s = s.decode('utf-8')
    except AttributeError:
        pass
    return s


def parse_host(host, default_user=None, default_port=None):
    """Parses host entries of the form "[user@]host[:port]".

    Returns a (host, port, user) triple.
    """
    user = default_user
    port = default_port
    if '@' in host:
        user, host = host.split('@', 1)
    if ':' in host:
        host, port = host.rsplit(':', 1)
    return host, port, user


@staticmethod
def perform_task(task, result_queue, **kwargs):
    """Function to be overwritten that performs the tasks from the list"""
    raise NotImplementedError()


def show_pockets(pocket_dict):
    """get a pocket_dict from the get_pockets() function"""
    for v in pocket_dict.values():
        for obj in v.values():
            obj.show()


def boil_down(args):
    """
    just report hits
    """
    with open('binary_hits_boiled_down.csv', 'w') as fout:
        with open('binary_hits.csv', 'r') as fin:
            genes = fin.readline().strip().split(',')
            for line in fin:
                bits = line.strip().split(',')
                for i, bit in enumerate(bits):
                    if i == 0:
                        fout.write(bit + ',')
                    if bit == '1':
                        fout.write(genes[i] + ',')
                fout.write('\n')


def overlap(a, b):
    """Intersection of sets

    "Mention-based" measure in CoNLL; #3 in CEAF paper
    """
    return len(a & b)


@staticmethod
def table_row_divider(col_widths, style='='):
    """
        Create row divider for use in an RST table. This is mostly an internal helper function
        used by RSTTable.render but can be useful otherwise as well.

        :param col_widths: List of ints with the width of the columns of the table
        :param style: string with the style to be used for the row divider. Default: style='='
        :return: Python string with the row divider text
        """
    out = '    '
    for cw in col_widths:
        out += '+' + (cw + 2) * style
    out += '+\n'
    return out


def saveTxt(x, path):
    """ save given string or list of strings to filepath

    params
    =============================
    x: str or list, list of str
    path: str, file path
    """
    with open(path, 'w') as f:
        if isinstance(x, list):
            for i in x:
                f.write('%s\n' % i)
        else:
            f.write(str(x))


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


def byte_alignment(bytes):
    """Returns alignment in powers of two of data with length `bytes`

       >>> [(i, byte_alignment (i)) for i in range (-3, 3)]
       [(-3, 1), (-2, 2), (-1, 1), (0, 0), (1, 1), (2, 2)]
       >>> [(i, byte_alignment (i)) for i in range (3, 10)]
       [(3, 1), (4, 4), (5, 1), (6, 2), (7, 1), (8, 8), (9, 1)]
    """
    return (bytes ^ bytes - 1) & bytes


@staticmethod
def _map_gen_gids(res_gids, gen_index):
    """
        Map resource gids from techmap to gen gids in .h5 source file

        Parameters
        ----------
        res_gids : ndarray
            resource gids from techmap
        gen_index : ndarray
            Equivalent gen gids to resource gids

        Returns
        -------
        gen_gids : ndarray
            gen gid to excl mapping
        res_gids : ndarray
            updated resource gid to excl mapping
        """
    mask = (res_gids >= len(gen_index)) | (res_gids == -1)
    res_gids[mask] = -1
    gen_gids = gen_index[res_gids]
    gen_gids[mask] = -1
    res_gids[gen_gids == -1] = -1
    return gen_gids, res_gids


def get_machine_revision():
    """
    Get the machine revision.

    A return value of None indicates an error (possibly because its
    not running on an RPI).
    Otherwise the return value is the revision code.

    """
    revision_code = None
    try:
        with open('/proc/cpuinfo', 'rb') as fp:
            for line in fp:
                if ':' not in line:
                    continue
                key, _, value = line.partition(':')
                key = key.strip().lower()
                value = value.strip().lower()
                if key == 'revision':
                    revision_code = value
                    break
    except IOError:
        return None
    else:
        return revision_code


def _new_object(cls):
    """Helper function for pickle"""
    return cls.__new__(cls)


def _build_pem(tls_cert):
    """Generate PEM encoded TLS certificate data

    :param tls_cert: TLS certificate
    :returns: PEm encoded certificate data
    """
    pem = ()
    if tls_cert.intermediates:
        for c in tls_cert.intermediates:
            pem = pem + (c,)
    if tls_cert.certificate:
        pem = pem + (tls_cert.certificate,)
    if tls_cert.private_key:
        pem = pem + (tls_cert.private_key,)
    return '\n'.join(pem)


@staticmethod
def get_not_implemented():
    """Not implemented warning."""
    return [{'title': 'not implemented'}]


def t_DYNAMIC_BOOTP_CLIENTS(t):
    """dynamic\\ bootp\\ clients"""
    return t


def get_coordination_number(connector):
    """
    This function can help us determine the coordination number of the top layer of the surface.

    Parameters:

    connector: the connector variable created by connection_matrix

    Return:
        A dictionary. {atom_index: coordination_number}
    """
    coord_num = {}
    for atom_index in connector:
        coord_num[atom_index] = len(connector[atom_index])
    return coord_num


def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    """
    Checks if two floating point numbers are almost equal
    """
    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)


def inline_hook(tokens):
    """Removes `_inline`, `__inline`, and `__forceinline`"""
    for token in tokens:
        if token not in ('_inline', '__inline', '__forceinline'):
            yield token


def store_is_remote(store):
    """Determine whether a given store is remote"""
    return store.startswith('http')


def _pipe_segment_with_colons(align, colwidth):
    """Return a segment of a horizontal line with optional colons which
    indicate column's alignment (as in `pipe` output format)."""
    w = colwidth
    if align in ['right', 'decimal']:
        return '-' * (w - 1) + ':'
    elif align == 'center':
        return ':' + '-' * (w - 2) + ':'
    elif align == 'left':
        return ':' + '-' * (w - 1)
    else:
        return '-' * w


def enable_cache():
    """
    Enables the internal cache.

    Note that this function will not clear the cache in any case, for that
    functionality see :func:`clear_cache`.
    """
    global _cache_enabled
    _cache_enabled = True