def commutator(expr1, expr2):
    """Returns [expr1, expr2] = expr1 * expr2 - expr2 * expr1.

    Args:
        expr1 (Expr, Term or Pauli operator): Pauli's expression.
        expr2 (Expr, Term or Pauli operator): Pauli's expression.

    Returns:
        Expr: expr1 * expr2 - expr2 * expr1.
    """
    expr1 = expr1.to_expr().simplify()
    expr2 = expr2.to_expr().simplify()
    return (expr1 * expr2 - expr2 * expr1).simplify()


@classmethod
def get_network_by_symbol(cls, symbol: str):
    """
        Returns network instance by its symbol.

        Args:
            symbol (str): network symbol

        Returns:
            Network object

        Raises:
            RuntimeError: if there is no network with given symbol.

        Example:
            >>> from clove.network.base import BaseNetwork
            >>> BaseNetwork.get_network_by_symbol('BTC')
            <clove.network.bitcoin.Bitcoin at 0x7f5a84b233c8>

        """
    if not cls.networks:
        cls.set_symbol_mapping()
    symbol = symbol.upper()
    if symbol not in cls.networks:
        raise RuntimeError(f'{symbol} network is not supported.')
    return cls.networks[symbol]()


def make_mega_cell(atoms, traAN, traBN, traCN, vectors, alt_multi=False):
    """
    Make a bigger supercell out of an input cell.

    The cell is multiplied positively and negatively through each lattice
    vector so that the supercluster ends up being
    (1+2*traAN)*(1+2*traBN)*(1+2*traCN) times larger. For example if the
    input is 1,1,1 for a cubic unit cell, the output will be the original unit
    cell surrounded by 26 other unit cells forming a total 3x3x3 cube.

    Alternatively, the multiplication can be centered around a corner of the
    unit cell instead of the centre. In that case the supercluster ends up being
    only (2*traAN)*(2*traBN)*(2*traCN)

    Parameters
    ----------
    atoms : list of Atom objects
        Atoms in the cell
    traAN,traBN,traCN : ints
        Number of times the cell should be multiplied in each cell direction,
        positively and negatively
    vectors : 3x3 matrix
        Lattice vectors
    alt_multi : bool
        Determines the kind of multiplication. True is centre of the cell as
        the origin, False is corner of the cell.
    Returns
    -------
    mega_cell : list of Atom objects
        The resulting supercell

    """
    mega_cell = []
    if alt_multi:
        traA = range(-traAN, traAN)
        traB = range(-traBN, traBN)
        traC = range(-traCN, traCN)
    else:
        traA = range(-traAN, traAN + 1)
        traB = range(-traBN, traBN + 1)
        traC = range(-traCN, traCN + 1)
    for i in traA:
        for j in traB:
            for k in traC:
                traX = vectors[0][0] * i + vectors[1][0] * j + vectors[2][0
                    ] * k
                traY = vectors[0][1] * i + vectors[1][1] * j + vectors[2][1
                    ] * k
                traZ = vectors[0][2] * i + vectors[1][2] * j + vectors[2][2
                    ] * k
                for atom in atoms:
                    mega_cell.append(atom.translated(traX, traY, traZ))
    return mega_cell


def check_bye_user(username):
    """ Boolean return when username matches ``byecmds`` in ini cfg. """
    from x84.bbs import get_ini
    matching = get_ini(section='matrix', key='byecmds', split=True)
    return matching and username in matching


@classmethod
def event(cls, title, text, tags=None, **kwargs):
    """
        Record a timing metric.

        Note that an event title is not a metric name, so no
        DATADOG_STATS_PREFIX value is prepended to it.

        Args:
            title (str): Event title
            text (str or None): Optional event text (string), supports
                MarkDown (see http://docs.datadoghq.com/guides/markdown/ )
            tags (list or dict): miscellaneous tags to describe the value
        """
    cls.stats().event(title, text, tags=cls._convert_tags(tags), **kwargs)


@staticmethod
def calculate_flag(sfw: bool=True, nsfp: bool=False, nsfw: bool=False, nsfl:
    bool=False) ->int:
    """
        Used to calculate flags for the post requests

        sfw = 1
        nsfw = 2
        sfw + nsfw = 3
        nsfl = 4
        nsfw + nsfl = 6
        sfw + nsfw + nsfl = 7
        nsfp = 8
        sfw + nsfp = 9
        sfw + nsfp + nsfw = 11
        sfw + nsfp + nsfw + nsfl = 15

        Parameters
        ----------
        :param sfw: bool
        :param nsfp: bool
        :param nsfw: bool
        :param nsfl: bool
        :return: Calculated flag for requests
        """
    flag = 0
    flag += 1 if sfw else 0
    flag += 2 if nsfw else 0
    flag += 4 if nsfl else 0
    flag += 8 if nsfp and sfw else 0
    return flag


@classmethod
def closure_childref(cls):
    """How to refer to children in the closure tree"""
    return '%sclosure_parents' % cls._toplevel().__name__.lower()


def change_speed(body, speed=1):
    """Change the voice speed of the wave body."""
    if speed == 1:
        return body
    length = int(len(body) * speed)
    rv = bytearray(length)
    step = 0
    for v in body:
        i = int(step)
        while i < int(step + speed) and i < length:
            rv[i] = v
            i += 1
        step += speed
    return rv


def setterToOthers(*setters):
    """
    Create a setter that will dispatch to a list of other setters.

    @param setters: arguments[callable]
        The setters to delegate the set to.
    """
    assert setters, 'At least a setter is required'
    if __debug__:
        for setter in setters:
            assert callable(setter), 'Invalid setter %s' % setter

    def setter(obj, value):
        for setter in setters:
            setter(obj, value)
    return setter


def learning_curves(history):
    """Plot the learning curves of loss and macro f1 score"""
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    macro_f1 = history.history['macro_f1']
    val_macro_f1 = history.history['val_macro_f1']
    return loss, val_loss, macro_f1, val_macro_f1


def calculate_importance_delta(classes, universal_set, linked_nodes, n, **
    kwargs):
    """
    Calculates importance of a single midpoint using delta-idf weighing
    :param classes: List of all classes
    :param universal_set: Set of all indices to consider
    :param linked_nodes: Set of all nodes linked by the midpoint
    :param n: Number of elements of universal set
    :return: List of weights of the midpoint for each label in class
    """
    predicted_pos = universal_set.intersection(linked_nodes)
    predicted_pos_num = len(predicted_pos)
    predicted_neg_num = n - predicted_pos_num
    return_list = []
    for label in classes:
        if label is None:
            continue
        actual_pos_num = label.not_test_members_num
        actual_neg_num = n - actual_pos_num
        diff = actual_pos_num * 1.0 / (predicted_pos_num + 1
            ) - actual_neg_num * 1.0 / (predicted_neg_num + 1)
        return_list.append(abs(diff))
    return return_list


def none_to_list(value):
    """a helper so that function args can be None, and updated to a list.
    """
    if not value:
        value = []
    return value


def v200_defaults_broker(defaults, runtime, harmonization, dry_run):
    """
    Inserting `*_pipeline_broker` and deleting broker into/from defaults configuration
    """
    changed = None
    values = {'destination_pipeline_broker': defaults.get('broker', 'redis'
        ), 'source_pipeline_broker': defaults.get('broker', 'redis')}
    for key, value in values.items():
        if key not in defaults:
            defaults[key] = value
            changed = True
    if 'broker' in defaults:
        del defaults['broker']
        changed = True
    return changed, defaults, runtime, harmonization


def resolve_ncase(path):
    """Resolve a case insensitive path on a case sensitive system, returning a string with the path if found else return the original path.

    """
    pass


def triangle_area(pt1, pt2, pt3):
    """Return the area of a triangle.

    Parameters
    ----------
    pt1: (X,Y) ndarray
        Starting vertex of a triangle
    pt2: (X,Y) ndarray
        Second vertex of a triangle
    pt3: (X,Y) ndarray
        Ending vertex of a triangle

    Returns
    -------
    area: float
        Area of the given triangle.

    """
    a = 0.0
    a += pt1[0] * pt2[1] - pt2[0] * pt1[1]
    a += pt2[0] * pt3[1] - pt3[0] * pt2[1]
    a += pt3[0] * pt1[1] - pt1[0] * pt3[1]
    return abs(a) / 2


def season_to_range(season):
    """Convert season string to month range (eg, 'DJF' -> (12, 2))

    Parameters
    ----------
    season : str
        Season string abbreviated by capital letters of each month (eg DJF)

    Returns
    -------
    ms, me
        Start and end month numbers.
    """
    months = 'JFMAMJJASOND'
    idx = list(range(len(months)))
    perms = {}
    for i in idx:
        perm = months[i:] + months[:i]
        if season in perm:
            start = perm.index(season)
            i_perm = idx[i:] + idx[:i]
            ms, me = i_perm[start] + 1, i_perm[start + len(season) - 1] + 1
            return ms, me
    raise ValueError(f'Invalid season: {season}')


@classmethod
def from_gdal_dataset(cls, gdal_dataset, **kwargs):
    """Create VRT from GDAL Dataset with the same size/georeference but wihout bands.

        Parameters
        ----------
        gdal_dataset : gdal.Dataset
            input GDAL dataset
        **kwargs : dict
            arguments for VRT()

        Returns
        -------
        vrt : VRT

        """
    vrt = cls.__new__(cls)
    vrt._init_from_gdal_dataset(gdal_dataset, **kwargs)
    return vrt


def p_simple_expr_identifier(p):
    """simple_expr : identifier"""
    p[0] = 'IDENTIFIER', p[1]


@classmethod
def for_type(cls, tp, hookfn, referencer=None, mode='set'):
    """
        For an object of a given type, apply the hookfn and use the
        specified mode to aggregate the data.

        To allow pickling (or any other defered access) of the target
        object, a referencer (a Reference subclass) may be specified
        to wrap the object as required.

        If mode is 'merge', merge the Layout output by the hook,
        otherwise if 'set', add the output to the path specified by
        the ViewRef.
        """
    cls.type_hooks[tp] = hookfn, mode, referencer


def _ctypes_out(parameter):
    """Returns a parameter variable declaration for an output variable for the specified
    parameter.
    """
    if (parameter.dimension is not None and ':' in parameter.dimension and
        'out' in parameter.direction and ('allocatable' in parameter.
        modifiers or 'pointer' in parameter.modifiers)):
        if parameter.direction == '(inout)':
            return 'type(C_PTR), intent(inout) :: {}_o'.format(parameter.name
                ), True
        else:
            return 'type(C_PTR), intent(inout) :: {}_c'.format(parameter.name
                ), True


def compose_dot_fields_by_fields(genedoc, fields):
    """
    reverse funtion of parse_dot_fields
    """
    res = None
    to_del = set()
    for k in fields:
        if k.find('.') != -1:
            if not res:
                import copy
                res = copy.deepcopy(genedoc)
            ks = k.split('.')
            broke = False
            if ks[0] in genedoc:
                t = genedoc[ks[0]]
                for e in ks[1:]:
                    if e in t:
                        t = t[e]
                    else:
                        broke = True
                        break
                if broke:
                    continue
                to_del.add(ks[0])
                res[k] = t
    for k in to_del:
        del res[k]
    return res if res else genedoc


def type_object_attrgetter(obj, attr, *defargs):
    """
    This implements an improved attrgetter for type objects (i.e. classes)
    that can handle class attributes that are implemented as properties on
    a metaclass.

    Normally `getattr` on a class with a `property` (say, "foo"), would return
    the `property` object itself.  However, if the class has a metaclass which
    *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find
    the "foo" property on the metaclass and resolve it.  For the purposes of
    autodoc we just want to document the "foo" property defined on the class,
    not on the metaclass.

    For example::

        >>> class Meta(type):
        ...     @property
        ...     def foo(cls):
        ...         return 'foo'
        ...
        >>> class MyClass(metaclass=Meta):
        ...     @property
        ...     def foo(self):
        ...         ""\"Docstring for MyClass.foo property.""\"
        ...         return 'myfoo'
        ...
        >>> getattr(MyClass, 'foo')
        'foo'
        >>> type_object_attrgetter(MyClass, 'foo')
        <property at 0x...>
        >>> type_object_attrgetter(MyClass, 'foo').__doc__
        'Docstring for MyClass.foo property.'

    The last line of the example shows the desired behavior for the purposes
    of autodoc.
    """
    for base in obj.__mro__:
        if attr in base.__dict__:
            if isinstance(base.__dict__[attr], property):
                return base.__dict__[attr]
            break
    return getattr(obj, attr, *defargs)


def change_owner_to(conn, schema, table, role):
    """Changes table's ownership to role

    Parameters
    ----------
    conn : sqlalchemy connection object
        A valid connection to a database
    schema : str
        The database schema
    table : str
        The database table
    role : str
        database role that access is granted to

    """
    sql_str = ("""ALTER TABLE {schema}.{table}
        OWNER TO {role};""".
        format(schema=schema, table=table, role=role))
    conn.execute(sql_str)


def scale_down(src_size, size):
    """Scales down crop size if it's larger than image size.

    If width/height of the crop is larger than the width/height of the image,
    sets the width/height to the width/height of the image.

    Parameters
    ----------
    src_size : tuple of int
        Size of the image in (width, height) format.
    size : tuple of int
        Size of the crop in (width, height) format.

    Returns
    -------
    tuple of int
        A tuple containing the scaled crop size in (width, height) format.

    Example
    --------
    >>> src_size = (640,480)
    >>> size = (720,120)
    >>> new_size = mx.img.scale_down(src_size, size)
    >>> new_size
    (640,106)
    """
    w, h = size
    sw, sh = src_size
    if sh < h:
        w, h = float(w * sh) / h, sh
    if sw < w:
        w, h = sw, float(h * sw) / w
    return int(w), int(h)


def is_command(attribute: str) ->bool:
    """Test if a method is an command."""
    return attribute.startswith('do_')


def _keep_alive(x, memo):
    """Keeps a reference to the object x in the memo.

    Because we remember objects by their id, we have
    to assure that possibly temporary objects are kept
    alive by referencing them.
    We store a reference at the id of the memo, which should
    normally not be used unless someone tries to deepcopy
    the memo itself...
    """
    try:
        memo[id(memo)].append(x)
    except KeyError:
        memo[id(memo)] = [x]


def _draw_heatmap(*args, **kwargs):
    """Wraps seaborn.heatmap to work with long, tidy format dataframes.
    """
    import seaborn as sb
    data = kwargs.pop('data')
    d = data.pivot(index=args[1], columns=args[0], values=args[2])
    return sb.heatmap(d, **kwargs)


@classmethod
def generate_single_tstamp_secs_eq(cls, column_name, filter_value):
    """Return tuple with sql and replacement.

        This function wraps other functions to build the sql partial
        and replacement dict for an equivalency match for a timestamp
        against a single column in the database.

        Args:
            column_name (str): Name of column in DB.
            filter_value (str or int or datetime.datetime): This is what
                 we look for in the column. Sanitized to Unix epoch for DB
                 compatibility.

        Returns:
            tuple: Item 0 contains the SQL partial string. Item 1 contains
                the replacement dictionary.

        """
    mod_filter_value = cls.timestamp_to_dbtime(filter_value)[0]
    return cls.generate_single_int_sql_eq(column_name, mod_filter_value)


@classmethod
def add_to_active_filters(cls, filter, key=None):
    """
        Add a new clause to the active filters. A filter may be either
        a Q object to be applied to the content class or a callable taking
        a queryset and spitting out a new one.

        If a filter with the given `key` already exists, the new filter
        replaces the old.
        """
    if cls.active_filters is None:
        cls.active_filters = {}
    if key is None:
        key = filter
    cls.active_filters[key] = filter


def _paddr(ins):
    """ Returns code sequence which points to
    local variable or parameter (HL)
    """
    output = []
    oper = ins.quad[1]
    indirect = oper[0] == '*'
    if indirect:
        oper = oper[1:]
    I = int(oper)
    if I >= 0:
        I += 4
    output.append('push ix')
    output.append('pop hl')
    output.append('ld de, %i' % I)
    output.append('add hl, de')
    if indirect:
        output.append('ld e, (hl)')
        output.append('inc hl')
        output.append('ld h, (hl)')
        output.append('ld l, e')
    output.append('push hl')
    return output


def t_IDENTIFIER(t):
    """[a-zA-Z_][a-zA-Z0-9_]*"""
    t.value = t.value.upper()
    return t


def get_test_spots_list():
    """
    returns a list of possible spot IDs from the spots repository.

    Parameters
    ----------s

    Returns
    -------
    list :: (list)

    Examples
    --------
    >>> lst = get_test_spots_list()
    """
    from os.path import exists
    print(exists('./lcp_video/test_data/spots'))


def lookup_template(widget, name):
    """ return a template path or return None
        """


@staticmethod
def _keypart(keymod: 'str') ->str:
    """Return first part of the internal keymod string +keymod+.

        Examples:
        >>> PhyscialInteractiveSprite._keypart(97) -> '97'
        >>> PhyscialInteractiveSprite._keypart(97 18) -> '97'
        """
    return keymod.split(' ')[0]


def parse_sorting(model, query, key, order=1, expression=None):
    """
    Sorting parser that works with embedded resources and sql expressions
    Moved out from the query (find) method.
    """
    if '.' in key:
        rel, sort_attr = key.split('.')
        rel_class = getattr(model, rel).property.mapper.class_
        query = query.outerjoin(rel_class)
        base_sort = getattr(rel_class, sort_attr)
    else:
        base_sort = getattr(model, key)
    if order == -1:
        base_sort = base_sort.desc()
    if expression:
        expression = getattr(base_sort, expression)
        base_sort = expression()
    return base_sort


@classmethod
def age(cls, daystart, s, isAfter):
    """Return a new MTimeFilter selecting before/after the given age."""
    epoch = daystart - int(s) * 60 * 60 * 24
    if isAfter:
        return cls(after=epoch)
    else:
        return cls(before=epoch)


def select_more():
    """Select those bones connected to the initial selection

    """
    pass


@classmethod
def random(cls, collection):
    """
            Returns a random document from a collection.

            :param collection Collection instance

            :returns document
        """
    return cls._construct_query(name='any', collection=collection)


def sin(data=None, out=None, name=None, **kwargs):
    """Computes the element-wise sine of the input array.

    The input should be in radians (:math:`2\\pi` rad equals 360 degrees).

    .. math::
       sin([0, \\pi/4, \\pi/2]) = [0, 0.707, 1]

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

       - sin(default) = default
       - sin(row_sparse) = row_sparse
       - sin(csr) = csr

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

    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 decode_chunked_transfer(chunked_body):
    """Parsed body received with chunked transfer encoding, and return the
    decoded body.

    For more info see:
    http://en.wikipedia.org/wiki/Chunked_transfer_encoding

    """
    body, h, t = '', '', chunked_body
    while t:
        h, t = t.split('\r\n', 1)
        if h == '0':
            break
        size = int(h, 16)
        body += t[:size]
        t = t[size + 2:]
    return body


def ver_str(version):
    """version tuple as string"""
    return '.'.join(map(str, version))


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

        :param bool val:
        :rtype: FileLockingValue
        """
    return cls('enabled', val)


def convert_param_representation_to_cfn(param_dict):
    """
    Convert params from {"ParamName: "ParamVal", ...} format to the format expected by the CloudFormation API
    [{"ParameterKey": "ParamName", "ParameterValue": "ParamVal}, ...] correctly handling bools and optional params.
    """
    param_list = []
    for k, v in param_dict.items():
        if v is None:
            v = ''
        if isinstance(v, bool):
            v = str(v).lower()
        param_list.append({'ParameterKey': k, 'ParameterValue': v})
    return param_list


@classmethod
def builder(cls):
    """
        return instance of this class
        """
    return cls()


def filter_match(filename, recip, sender=None):
    """Check if the give e-mail addresses match lines in filename."""
    from . import Defaults
    from . import FilterParser
    filter = FilterParser.FilterParser(Defaults.DB_CONNECTION)
    filter.read(filename)
    actions, matchline = filter.firstmatch(recip, [sender])
    checking_msg = 'Checking ' + filename
    print(checking_msg)
    print('-' * len(checking_msg))
    if recip:
        print('To:', recip)
    if sender:
        print('From:', sender)
    print('-' * len(checking_msg))
    if actions:
        print('MATCH:', matchline)
    else:
        print('Sorry, no matching lines.')


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


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by this acitoolkit class.

        :returns: list of strings containing APIC class names
        """
    resp = []
    return resp


def vel_avg_vv(g: float, ve_before1: float, ve_after1: float, ve_before2:
    float, ve_after2: float, mass: float) ->float:
    """Returns the arithmetic mean of the relative velocity of particles before and after
    a VV transition (using the energy conservation law) **M1(i1) + M2(k1) -> M1(i2) + M2(k2)**

    Parameters
    ----------
    g : float
        the relative dimensional velocity of the particles before the collision
    ve_before1 : float
        the vibrational energy of the molecule M1 before the transition
    ve_after1 : float
        the vibrational energy of the molecule M1 after the transition
    ve_before2 : float
        the vibrational energy of the molecule M2 before the transition
    ve_after2 : float
        the vibrational energy of the molecule M2 after the transition
    mass : float
        the collision-reduced mass :math:`m_{cd}`

    Returns
    -------
    float
        Arithmetic mean of before- and after- velocities for a VT transition

    Notes
    -----
    If the squared after-collision velocity is < 0, then the collision is impossible for such parameters and
    the function returns -1
    """
    gn_sq = (ve_before1 - ve_after1 + ve_before2 - ve_after2) * (2.0 / mass
        ) + g ** 2
    if gn_sq < 0:
        return -1
    else:
        return 0.5 * (g + gn_sq ** 0.5)


def no_match_load(key):
    """ If no match is made when loading, need to raise an exception
    """
    raise RuntimeError('Cannot load %s data type' % key)


@staticmethod
def write_sorting(sorting, save_path):
    """This function writes out the spike sorted data file of a given sorting
        extractor to the file format of this current sorting extractor. Allows
        for easy conversion between spike sorting file formats. It is a static
        method so it can be used without instantiating this sorting extractor.

        Parameters
        ----------
        sorting: SortingExtractor
            A SortingExtractor that can extract information from the sorted data
            file to be converted to the new format

        save_path: string
            A path to where the converted sorted data will be saved, which may
            either be a file or a folder, depending on the format
        """
    raise NotImplementedError(
        'The write_sorting function is not                                   implemented for this extractor'
        )


def add_to_specified_database(item, database):
    """ add an item to a database"""
    database['items'][database['name'], item['code']] = item


def tznow():
    """
    Return an aware or naive datetime.datetime, depending on settings.USE_TZ.
    """
    from django.utils.timezone import now
    return now()


def import_assignment(interface, node):
    """Set the properties on the given assignment, based on the given
        portlet type interface. The node is the <assignment /> root node.
        Settings are expected to be found in children of the node.
        """


@classmethod
def get(cls, credential_id):
    """
        Gets the Credential.

        Parameters
        ----------
        credential_id : str
            the identifier of the credential.

        Returns
        -------
        credential : Credential
            the requested credential.

        Examples
        --------
        .. code-block:: python

            >>> import datarobot as dr
            >>> cred = dr.Credential.get('5a8ac9ab07a57a0001be501f')
            >>> cred
            Credential('5e429d6ecf8a5f36c5693e03', 'my_s3_cred', 's3'),
        """
    return cls.from_location('{}{}/'.format(cls._path, credential_id))


def get(object):
    """Get the value of the field for the given object."""


def read(data=None):
    """
Read ``ps -eo pid,user,rss,%cpu,command``.

:options:

  **data** (``<str>``)
    For debugging: specify the output of ``ps -eo pid,user,rss,%cpu,command`` as string.

:returns:

  **lines** ``<list<dict>>``
    A list of dictionaries, that contain the different fields. All data are strings.
  """
    import subprocess
    if data is None:
        data = subprocess.check_output('ps -eo pid,user,rss,%cpu,command',
            shell=True).decode('utf-8')
    header, data = data.split('\n', 1)
    data = list(filter(None, data.split('\n')))
    header = list(filter(None, header.split(' ')))
    lines = []
    for line in data:
        d = ['' for i in header]
        line = line.strip()
        d[0], line = line.split(' ', 1)
        line = line.strip()
        d[1], line = line.split(' ', 1)
        line = line.strip()
        d[2], line = line.split(' ', 1)
        line = line.strip()
        d[3], line = line.split(' ', 1)
        d[4] = line.strip()
        info = {}
        for key, val in zip(header, d):
            info[key] = val
        lines += [info]
    return lines


def check_raw(raw):
    """ Check if raw data can be converted into an unstructured grid """
    try:
        raw['elem'][0, 0]
        raw['enum'][0]
    except Exception:
        raise Exception('Invalid file or missing key data.  ' +
            'Cannot parse into unstructured grid')


@classmethod
def validate_bool_field(cls, value, null=True):
    """
        Validate bool field value

        :type value: bool
        :param value:

        :type null: bool
        :param null: is allow None value

        :rtype: dict
        :return: {'is_valid':bool, 'error_msg':str}
        """
    is_valid = True
    error_msg = None
    if null is False and value is None:
        is_valid = False
        error_msg = 'Data should not be None'
    if value is not None and isinstance(value, bool) is False:
        is_valid = False
        error_msg = 'Data type should be <bool>'
    return {'is_valid': is_valid, 'error_msg': error_msg}


@classmethod
def css(class_, url):
    """Produces a chunk of XHTML for including CSS file with this p_url"""
    return '<link rel="stylesheet" type="text/css" href="%s"/>' % url


def is_tensor(obj):
    """Returns true if the given object is a framework-specific tensor."""
    pass


@classmethod
def load(cls, sc, path):
    """
        Load a model from the given path. The model should have been
        saved using py:meth:`Saveable.save`.

        :param sc: Spark context used for loading model files.
        :param path: Path specifying the directory to which the model
                     was saved.
        :return: model instance
        """
    raise NotImplemented


@staticmethod
def _get_messages_upload_server(session, peer_id):
    """
        https://vk.com/dev/photos.getMessagesUploadServer
        """
    response = session.fetch('photos.getMessagesUploadServer', peer_id=peer_id)
    return response['upload_url']


@classmethod
def pre_apply(cls, instance, **kwargs):
    """ Perform synchronous actions before signature apply """
    pass


def factorial(num):
    """Returns the factorial of a nonnegative integer.

    This function is provided in math module starting with Python 2.6,
    but implement anyway for compatibility with older systems."""
    result = 1
    for i in range(2, num + 1):
        result = result * i
    return result


def parseAddressRange(text):
    """parse a single address or an address range and return a tuple."""
    if '-' in text:
        adr1, adr2 = text.split('-', 1)
        try:
            adr1 = int(adr1, 0)
        except ValueError:
            raise ValueError(
                'Address range start address must be a valid number in dec, hex or octal'
                )
        try:
            adr2 = int(adr2, 0)
        except ValueError:
            raise ValueError(
                'Address range end address must be a valid number in dec, hex or octal'
                )
        return adr1, adr2
    elif '/' in text:
        adr1, size = text.split('/', 1)
        try:
            adr1 = int(adr1, 0)
        except ValueError:
            raise ValueError(
                'Address range start address must be a valid number in dec, hex or octal'
                )
        multiplier = 1
        if size.endswith('k'):
            size = size[:-1]
            multiplier = 1024
        try:
            size = int(size, 0) * multiplier
        except ValueError:
            raise ValueError(
                'Address range size must be a valid number in dec, hex or octal'
                )
        return adr1, adr1 + size - 1
    else:
        try:
            adr = int(text, 0)
            return adr, None
        except ValueError:
            raise ValueError(
                'Address must be a valid number in dec, hex or octal or a range adr1-adr2'
                )


def c2k(c):
    """Converts Celsius to Kelvin."""
    return c + 273.15


def extrude_move(ARMATURE_OT_extrude=None, TRANSFORM_OT_translate=None):
    """Create new bones from the selected joints and move them

    :param ARMATURE_OT_extrude: Extrude, Create new bones from the selected joints
    :param TRANSFORM_OT_translate: Move, Move selected items
    """
    pass


def checker_trailing_whitespace(physical_line):
    """Trailing whitespace is superfluous.

    Okay: echo Test#
    W201: echo Test #
    Okay: #
    W202:  #
    """
    physical_line = physical_line.rstrip('\n')
    physical_line = physical_line.rstrip('\r')
    physical_line = physical_line.rstrip('\x0c')
    stripped = physical_line.rstrip(' \t\x0b')
    if physical_line != stripped:
        if stripped:
            return len(stripped), 'W201 Trailing whitespace'
        else:
            return 0, 'W202 Blank line contains whitespace'


def ebs(dic, data):
    """
    EBS Reconstruction
    """
    raise NotImplementedError


def get_option_value(opt_name, default_value, *confs):
    """ assume that opts[0].priority > opts[1].priority > ... """
    for opts in confs:
        if opt_name in opts and opts[opt_name] is not None:
            return opts[opt_name]
    return default_value


def get_item(container, indeces):
    """Get item from recursive list."""
    while len(indeces) > 1:
        container = container[indeces[0]]
        indeces = indeces[1:]
    return container[indeces[0]]


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


def getReactionPropertyFromCode(value):
    """
    The input value must be one of: 0, 10, 11, 941, 942, 943, 944
    according to the integer EPDL97 code of the reaction property:
                     0 <-> integrated cross section
                    10 <-> avg. energy of secondary particle Yo
                    11 <-> avg. energy to the residual atom
                   941 <-> form factor
                   942 <-> scattering function
                   943 <-> imaginary anomalous scatt. factor
                   944 <-> real anomalous scatt. factor
    """
    if value == 0:
        return 'cross_section'
    if value == 10:
        return 'secondary_particle_energy'
    if value == 11:
        return 'atom_energy_transfer'
    if value == 941:
        return 'form_factor'
    if value == 942:
        return 'scattering_function'
    if value == 943:
        return 'imaginary_anomalous_scattering_factor'
    if value == 944:
        return 'real_anomalous_scattering_factor'
    raise ValueError('Invalid reaction property descriptor code')


@staticmethod
def get_rule_id_by_template_tag(root, rule_name):
    """Get the rule ID based on template_tag."""
    schema_ids = []
    rules = root.findall('rule')
    for rule in rules:
        if rule.find('template').attrib['tag'] == rule_name:
            schema_ids.append(rule.attrib['id'])
    if schema_ids == []:
        return None
    return schema_ids


@classmethod
def get_robot_mapfile(cls, site, mapfile):
    """ Download robot mapfile.

        :params site: Map info for site
        :params mapfile: select type in ('mapconfig', 'mapimage', 'dockconfig')
        :returns: Image content or json loaded structure
        """
    assert mapfile in ('map/config', 'map/image', 'dock/config')
    raw = mapfile in ('map/image',)
    api = cls(None, None)
    url = 'robots/%s/%s' % (site, mapfile)
    return api.method(url, raw=raw)


def state(obj):
    """Gets the UnitOfWork state of a mapped object"""
    return obj.__ming__.state


def opengl(animation: bool=False, sequencer: bool=False, write_still: bool=
    False, view_context: bool=True):
    """OpenGL render active viewport

    :param animation: Animation, Render files from the animation range of this scene
    :type animation: bool
    :param sequencer: Sequencer, Render using the sequencer’s OpenGL display
    :type sequencer: bool
    :param write_still: Write Image, Save rendered the image to the output path (used only when animation is disabled)
    :type write_still: bool
    :param view_context: View Context, Use the current 3D view for rendering, else use scene settings
    :type view_context: bool
    """
    pass


def _get_point_on_line(x1, y1, x2, y2, n):
    """Returns the (x, y) tuple of the point that has progressed a proportion
    n along the line defined by the two x, y coordinates.
    """
    x = (x2 - x1) * n + x1
    y = (y2 - y1) * n + y1
    return x, y


def get_status_old(code):
    """Get the torrent status using old status codes"""
    mapping = {(1 << 0): 'check pending', (1 << 1): 'checking', (1 << 2):
        'downloading', (1 << 3): 'seeding', (1 << 4): 'stopped'}
    return mapping[code]


@classmethod
def create_trunk(cls, port=None, subports=None, client=None, **kwargs):
    """Create network trunk

        :param port: dictionary containing parent port ID (port['id'])
        :param client: client to be used for connecting to networking service
        :param **kwargs: extra parameters to be forwarded to network service

        :returns: dictionary containing created trunk details
        """
    client = client or cls.client
    if port:
        kwargs['port_id'] = port['id']
    trunk = client.create_trunk(subports=subports, **kwargs)['trunk']
    trunk['client'] = client
    cls.trunks.append(trunk)
    return trunk


def setResponseHeaders(mapping):
    """Sets headers.  The headers must be Correctly-Cased.
        """


def set_api_key(config, key):
    """Configure a new API key."""
    if not key and 'X-Api-Key' in config.api_key:
        del config.api_key['X-Api-Key']
    else:
        config.api_key['X-Api-Key'] = key


def is_email_simple(value):
    """Return True if value looks like an email address."""
    if '@' not in value or value.startswith('@') or value.endswith('@'):
        return False
    try:
        p1, p2 = value.split('@')
    except ValueError:
        return False
    if '.' not in p2 or p2.startswith('.'):
        return False
    return True


def copy_dict(source, dest):
    """
    Populates a destination dictionary with the values from the source

    :param source: source dict to read from
    :param dest: destination dict to write to

    :returns: dest
    :rtype: dict

    """
    for name, value in source.items():
        dest[name] = value
    return dest


def get_service_context(**args):
    """An abstraction layer for getting service context.

    There could be multiple cloud backends for kingbird to use. This
    abstraction layer provides an indirection for kingbird to get the
    credentials of 'kingbird' user on the specific cloud. By default,
    this credential refers to the credentials built for keystone middleware
    in an OpenStack cloud.
    """
    pass


@staticmethod
def _strip_glob(value):
    """Remove the trailing * from a value."""
    assert value[-1] == '*'
    return value[:-1]


def _sort_set_none_first(set_):
    """Sort a set, sorting ``None`` before other elements, if present.
    """
    if None in set_:
        set_.remove(None)
        out = [None]
        out.extend(sorted(set_))
        set_.add(None)
        return out
    else:
        return sorted(set_)


def optimize_picklist_for_tecan_evo_dispensing(picklist):
    """Return a EVO-optimized version of the picklist.

    In that new version of the Picklist the liquid transfers are sorted, first
    by source plate, then by column of the source well, then by column of the
    destination well.
    """
    return picklist.sorted_by(lambda transfer: (transfer.source_well.plate.
        name, transfer.source_well.column, transfer.destination_well.column))


def getargnames(argspecs, with_unbox=False):
    """Resembles list of arg-names as would be seen in a function signature, including
    var-args, var-keywords and keyword-only args.
    """
    args = argspecs.args
    vargs = argspecs.varargs
    try:
        kw = argspecs.keywords
    except AttributeError:
        kw = argspecs.varkw
    try:
        kwonly = argspecs.kwonlyargs
    except AttributeError:
        kwonly = None
    res = []
    if not args is None:
        res.extend(args)
    if not vargs is None:
        res.append('*' + vargs if with_unbox else vargs)
    if not kwonly is None:
        res.extend(kwonly)
    if not kw is None:
        res.append('**' + kw if with_unbox else kw)
    return res


def splitarg(line):
    """
    Returns: a list with arguments and a list their starting locations
             in orginal line

    Break up a line in separate arguments, where:
    - comma is one separator
    - multiple commas are more separators
    - several spaces is one separator
    - one comma with leading/trailing space(s) is also one separator
    """
    args = []
    icolarg = []
    templine = line.rstrip()
    idx = len(templine)
    while idx > 0:
        idx = max(templine.rfind(','), templine.rfind(' '))
        args.append(templine[idx + 1:].strip())
        icolarg.append(idx + 1)
        templine = templine[:max(0, idx + 1)].rstrip()
        if idx > 0 and templine[-1] == ',':
            templine = templine[:-1].rstrip()
    return args[::-1], icolarg[::-1]


def get_days(diff):
    """
    Returns floating point number for days
    :param diff: timedelta
    :return: floating number
    """
    return diff.total_seconds() / (24 * 60 * 60)


def resolve_relative_path(base, path):
    """
    Resolve a path relative to a given base
    :param base: the base path. if it is an existing file, only the directory part will be used.
    :param path: the path to resolve.
    :return: the resolved path, or the input path if it was absolute.
    """
    from os.path import normpath, join, dirname, isabs, isfile
    if isabs(path):
        return path
    else:
        if isfile(base):
            base = dirname(base)
        return normpath(join(base, path))


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'org.apache.spark.ml.PipelineModel'


@staticmethod
def delist(val):
    """Return list item if list contains only one element."""
    if type(val) == list and len(val) == 1:
        return val[0]
    else:
        return val


def normals_make_consistent(calc_length: bool=False):
    """Recalculate the direction of selected handles

    :param calc_length: Length, Recalculate handle length
    :type calc_length: bool
    """
    pass


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 _is_exported(ident_name):
    """
    Returns `True` if `ident_name` matches the export criteria for an
    identifier name.

    This should not be used by clients. Instead, use
    `pdoc.Module.is_public`.
    """
    return not ident_name.startswith('_')


def dict_clean_others(d: dict, use: tuple):
    """
    Use values from `d` when the key exists in `d` and transfer them to a new dict.
    Only keys listed in `use` will be in the new dict which will be returned by this function.
    If a key listed in `use` is not included in `d`, it will be skipped and is not included in the new dict.

    :param d: dict: Dictionary to clean
    :param use: tuple: List of keys that will be transfered to the new dict.
                Alternatively if the key should be changed in the new returned dict,
                a tuple containing ('oldkey', 'newkey') can be passed.

    Example:
    d = {
        'firstkey': 'firstvalue',
        'second': 2,
        'third': None,
        'otherkey': 'hackyvalue',
    }

    dict_clean_others(d, ('firstkey', 'second', 'third', 'otherkey'))
    => {
        'firstkey': 'firstvalue',
        'second': 2,
        'third': None,
    }
    """
    values = {}
    for key in use:
        try:
            if isinstance(key, tuple):
                o_key, v_key = key
            else:
                v_key = o_key = key
            values[v_key] = d[o_key]
        except KeyError:
            pass
    return values


def p_program(p):
    """
    program : lines statement
    """
    p[1].children.append(p[2])
    p[0] = p[1]


def provides_facts():
    """
    Returns a dictionary keyed on the facts provided by this module. The value
    of each key is the doc string describing the fact.
    """
    return {'srx_cluster':
        'A boolean indicating if the device is part of an SRX cluster.',
        'srx_cluster_id': 'A string containing the configured cluster id',
        'srx_cluster_redundancy_group':
        "A multi-level dictionary of information about the SRX cluster redundancy groups on the device. The first-level key is the redundancy group id. The second-level keys are: cluster_id, failover_count, node0, and node1. The node0 and node1 keys have third-level keys of priority, preempt, status, and failover_mode. The values for this fact correspond to the values of the 'show chassis cluster status' CLI command."
        }


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 inter_event_time_distribution(G, u=None, v=None):
    """Return the distribution of inter event time.
     If u and v are None the dynamic graph intere event distribution is returned.
     If u is specified the inter event time distribution of interactions involving u is returned.
     If u and v are specified the inter event time distribution of (u, v) interactions is returned

     Parameters
     ----------
     G : graph
            A DyNetx graph.
     u : node id
     v : node id

     Returns
     -------

     nd : dictionary
         A dictionary from inter event time to number of occurrences
    """
    return G.inter_event_time_distribution(u, v)


def get_response(**kw):
    """ Return a WebOb-compatible response object which uses the blob
        content as the stream data and the mimetype of the file as the
        content type.  The ``**kw`` arguments will be passed to the
        :class:`pyramid.response.FileResponse` constructor as its keyword
        arguments."""


def fix_segment_table(segment_table):
    """Given a list of dictionaries in the form [{"start":start_frequency,
    "stop":stop_frequency,"number_points":number_points,"step":frequency_step}...] returns a table that is ordered by start
    frequency and has no overlapping points"""
    segment_table = sorted(segment_table, key=lambda x: x['start'])
    i = 0
    while i + 1 < len(segment_table):
        if segment_table[i]['stop'] == segment_table[i + 1]['start']:
            segment_table[i + 1]['start'] = segment_table[i + 1]['start'
                ] + segment_table[i + 1]['step']
            segment_table[i + 1]['number_points'] -= 1
        i += 1
    return segment_table


@staticmethod
def convert2d(feature, proj2d):
    """Convert the 3D volumetric feature to a 2D planar data set.

        proj2d specifies the dimension that we want to consider as channel
        for example for proj2d = 0 the 2D images are in the yz plane and
        the stack along the x dimension is considered as extra channels
        Args:
            feature (np.array): raw features
            proj2d (int): projection
        Returns:
            np.array: projected features
        """
    nc, nx, ny, nz = feature.shape
    if proj2d == 0:
        feature = feature.reshape(-1, 1, ny, nz).squeeze()
    elif proj2d == 1:
        feature = feature.reshape(-1, nx, 1, nz).squeeze()
    elif proj2d == 2:
        feature = feature.reshape(-1, nx, ny, 1).squeeze()
    return feature


@staticmethod
def release_start():
    """
        Releases are automatically started when they are created
        """
    pass


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))


@staticmethod
def _get_region_from_ancestors(element):
    """Try to get the region ID from the nearest ancestor that has it
        """
    region_id = None
    parent = element.parent
    while parent:
        region_id = parent.get(u'region')
        if region_id:
            break
        parent = parent.parent
    return region_id


def pretty_xml(xml):
    """Given a string with XML, return a string with the XML formatted pretty"""
    from xml.dom import minidom
    dom = minidom.parseString(xml)
    return dom.toprettyxml()


def credentialsChanged(user, name, pw, request):
    """
        Updates cookie credentials if user details are changed.
        """


def _get_next_line(lines, linenumber):
    """
    Returns the next line but skips over any empty lines.
    An empty line is returned if read past the last line.
    """
    inc = linenumber + 1
    num_lines = len(lines)
    while True:
        if inc == num_lines:
            return ''
        if lines[inc]:
            return lines[inc]
        inc += 1


@staticmethod
def _get_metric_rate_name(metric_name):
    """Change the metric name to a rate, i.e. "net.rx_bytes"
        gets converted to "net.rx_bytes_sec"
        """
    return '{0}_sec'.format(metric_name)


def find_tag(vobject_item):
    """Find component name from ``vobject_item``."""
    if vobject_item.name == 'VCALENDAR':
        for component in vobject_item.components():
            if component.name != 'VTIMEZONE':
                return component.name
    return None


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

        :param WebSessionsChangeFixedLengthPolicyType val:
        :rtype: EventType
        """
    return cls('web_sessions_change_fixed_length_policy', val)


def subdivide(number_cuts: int=1):
    """Subdivide selected segments

    :param number_cuts: Number of cuts
    :type number_cuts: int
    """
    pass


def mutating(func):
    """
    Decorator that marks functions for suitable only for mutable objects
    """
    func.__mutating__ = True
    return func


def new():
    """Create a new text data-block

    """
    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 '+'


@staticmethod
def read_file(file: str) ->str:
    """ Given a file path, we read it and print it out """
    file = str(file)
    with open(file) as f:
        text = f.read()
    return text


@staticmethod
def replace_path(path: str):
    """Linux path escaping"""
    symbol = ' !$^&*()=|[]{}?,<>"\':`;'
    for s in symbol:
        if s in path:
            path = path.replace(s, f'\\{s}')
    return path


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['type']
    if type == 'volume':
        return 'VolumeSourceFromVolumeDetails'
    if type == 'volumeBackup':
        return 'VolumeSourceFromVolumeBackupDetails'
    else:
        return 'VolumeSourceDetails'


def isrange(a, b):
    """
    Return True if the passed tuple `(a,b)` is a valid range
    (that is, `a` may not be greater than `b`).
    """
    if a is None or b is None:
        return True
    if a <= b:
        return True
    return False


def seek_line(f, pattern):
    """ find the next line starting with a specific string """
    line = next(f)
    while not line.startswith(pattern):
        line = next(f)
    return line


def _convert_qemu_node(node, old_node):
    """
    Convert qemu node from 1.X to 2.0
    """
    if old_node.get('properties', {}).get('hda_disk_image_md5sum'
        ) == '8ebc5a6ec53a1c05b7aa101b5ceefe31':
        node['console'] = None
        node['console_type'] = None
        node['node_type'] = 'nat'
        del old_node['properties']
        node['properties'] = {'ports': [{'interface': 'eth1', 'name':
            'nat0', 'port_number': 0, 'type': 'ethernet'}]}
        if node['symbol'] is None:
            node['symbol'] = ':/symbols/cloud.svg'
        return node
    node['node_type'] = 'qemu'
    if node['symbol'] is None:
        node['symbol'] = ':/symbols/qemu_guest.svg'
    return node


@staticmethod
def _read_file_block(file_handle, block_size=8192):
    """yield chunk_size blocks of file

        :param file_handle: handle to file
        :param chunk_size: block size of file to be read
        :return: block of file
        """
    while True:
        data = file_handle.read(block_size)
        if not data:
            break
        else:
            yield data


def onAfterAttributes(e):
    """Called after the attributes of a view field are changed.

    :param result: result of the attribute operation, 0 on success.
    :type result: int
    :rtype: None
    """
    if e.field == 'AMTCRLIMT':
        e.isEditable = False
        return


@classmethod
def log(cls, message):
    """ Display info message if verbose level allows it. """
    if cls.verbose > 0:
        msg = '[INFO] %s' % message
        cls.echo(msg)


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 _get_mro(cls):
    """Get an mro for a type or classic class"""
    if not isinstance(cls, type):

        class cls(cls, object):
            pass
        return cls.__mro__[1:]
    return cls.__mro__


def read_string(fd, loc=None):
    """
    Read a null-terminated string.
    The file descriptor is set to one past the null.

    :param fd: file handle opened in binary mode
    :return: the decoded string
    """
    if loc is not None:
        fd.seek(loc)
    b = b''
    while True:
        bb = fd.read(1)
        if bb == b'\x00':
            break
        b += bb
    return b.decode('utf-8')


@classmethod
def create_missing_types(cls, schema, type_dict, type_builder=None):
    """
        Creates missing types for fields with a CardinalityField part.
        It is assumed that the primary type converter for cardinality=1
        is registered in the type dictionary.

        :param schema:  Parse schema (or format) for parser (as string).
        :param type_dict:  Type dictionary with type converters.
        :param type_builder: Type builder to use for missing types.
        :return: Type dictionary with missing types. Empty, if none.
        :raises: MissingTypeError,
                if a primary type converter with cardinality=1 is missing.
        """
    if not type_builder:
        type_builder = cls.type_builder
    missing = cls.extract_missing_special_type_names(schema, type_dict)
    return type_builder.create_type_variants(missing, type_dict)


def size_slider_callback():
    """JS callback to select size of glyphs

    Returns
    -------
    code : :obj:`str`
    """
    code = """
            let n_rs = ax.length;
            for (let i=0; i<n_rs; i++){
                ax[i].size = cb_obj.value;
            }
           """
    return code


def charCodeAt(src: str, pos: int):
    """
    Returns the Unicode value of the character at the specified location.

    @param - index The zero-based index of the desired character.
    If there is no character at the specified index, NaN is returned.

    This was added for compatibility with python
    """
    try:
        return ord(src[pos])
    except IndexError:
        return None


def set_tracking_uri(uri):
    """
    Set the tracking server URI. This does not affect the
    currently active run (if one exists), but takes effect for successive runs.

    :param uri:

                - An empty string, or a local file path, prefixed with ``file:/``. Data is stored
                  locally at the provided file (or ``./mlruns`` if empty).
                - An HTTP URI like ``https://my-tracking-server:5000``.
                - A Databricks workspace, provided as the string "databricks" or, to use a
                  Databricks CLI
                  `profile <https://github.com/databricks/databricks-cli#installation>`_,
                  "databricks://<profileName>".
    """
    global _tracking_uri
    _tracking_uri = uri


def example_handler(name_list: list):
    """Example of a callback handler for when a window change occurs.

    This one just prints the list of strings that were found in handle_xevent.
    """
    print(name_list)


@staticmethod
def calc_faces(size_x, size_z):
    """Return the faces for a horizontal grid of ``size_x`` by ``size_z``
		cells.

		Faces are triangular, so each is composed by 3 vertices. Consequently,
		each returned face is a length-3 sequence of the vertex indices.

		:param size_x: number of cells along the X axis
		:type size_x: positive int
		:param size_z: number of cells along the Z axis
		:type size_z: positive int
		:return: faces for a heightfield trimesh based in a horizontal grid of
			``size_x`` by ``size_z`` cells
		:rtype: list of 3-tuple of ints

		>>> HeightfieldTrimesh.calc_faces(2, 4)
		[(0, 1, 4), (1, 5, 4), (1, 6, 5), (1, 2, 6), (2, 3, 6), (3, 7, 6)]

		"""
    indices = []
    for x in range(size_x):
        indices_x = []
        for z in range(size_z):
            indices_x.insert(z, size_z * x + z)
        indices.insert(x, indices_x)
    faces = []
    for x in range(size_x - 1):
        for z in range(size_z - 1):
            zero = indices[x][z]
            one = indices[x][z + 1]
            two = indices[x + 1][z]
            three = indices[x + 1][z + 1]
            face_type = zero
            if size_z % 2 == 0:
                face_type += 1
            if face_type % 2 == 0:
                face1 = zero, three, two
                face2 = zero, one, three
            else:
                face1 = zero, one, two
                face2 = one, three, two
            faces.append(face1)
            faces.append(face2)
    return faces


@classmethod
def bayes_llk_small(cls, z):
    """used to calculate the log-likelihood of small positive values: fitted with spline"""
    return cls.spline(z)


def resource_types():
    """Returns a list of the QAL-supported resource types"""
    return ['CUSTOM', 'FLATFILE', 'MATRIX', 'XPATH', 'RDBMS', 'SPREADSHEET']


def get_base_path_mappings(domainName=None, position=None, limit=None):
    """
    Represents a collection of  BasePathMapping resources.
    See also: AWS API Documentation

    :example: response = client.get_base_path_mappings(
        domainName='string',
        position='string',
        limit=123
    )

    :type domainName: string
    :param domainName: [REQUIRED]
            The domain name of a BasePathMapping resource.

    :type position: string
    :param position: The current pagination position in the paged result set.

    :type limit: integer
    :param limit: The maximum number of returned results per page. The value is 25 by default and could be between 1 - 500.

    :rtype: dict
    :return: {
        'position': 'string',
        'items': [
            {
                'basePath': 'string',
                'restApiId': 'string',
                'stage': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def get_point_in_block(cls, x, y, block_idx, block_size):
    """Get point coordinates in next block.

        Parameters
        ----------
        x : `int`
            X coordinate in current block.
        y : `int`
            Y coordinate in current block.
        block_index : `int`
            Current block index in next block.
        block_size : `int`
            Current block size.

        Raises
        ------
        IndexError
            If block index is out of range.

        Returns
        -------
        (`int`, `int`)
            Point coordinates.
        """
    if block_idx == 0:
        return y, x
    if block_idx == 1:
        return x, y + block_size
    if block_idx == 2:
        return x + block_size, y + block_size
    if block_idx == 3:
        x, y = block_size - 1 - y, block_size - 1 - x
        return x + block_size, y
    raise IndexError('block index out of range: %d' % block_idx)


def _all_delimiters_str():
    """delimiter = %x09 / %x20-2F / %x3B-40 / %x5B-60 / %x7B-7E"""
    delimiters = '\t'
    for i in range(32, 48):
        delimiters = delimiters + chr(i)
    for i in range(59, 65):
        delimiters = delimiters + chr(i)
    for i in range(91, 97):
        delimiters = delimiters + chr(i)
    for i in range(123, 127):
        delimiters = delimiters + chr(i)
    return delimiters


def kill_proc(proc, cmd, started_at):
    """kill proc if started
    returns True if proc is killed actually
    """
    if proc.returncode is None:
        proc.kill()


@classmethod
def _get_all(cls, parent_id=None, grandparent_id=None):
    """Retrives all the required resources."""
    client = cls._get_client()
    endpoint = cls._endpoint.format(resource_id='', parent_id=parent_id or
        '', grandparent_id=grandparent_id or '')
    resources = []
    while True:
        response = client.get_resource(endpoint)
        for raw_data in response.get('value', []):
            raw_data['parentResourceID'] = parent_id
            raw_data['grandParentResourceID'] = grandparent_id
            resources.append(cls.from_raw_data(raw_data))
        endpoint = response.get('nextLink')
        if not endpoint:
            break
    return resources


def PNT2Tidal_Pv12(XA):
    """ TaylorT2 1PN Quadrupolar Tidal Coefficient, v^12 Phasing Term.

   XA = mass fraction of object """
    XATo2nd = XA * XA
    XATo3rd = XATo2nd * XA
    return (15895 / 56 - 4595 * XA / 56 - 5715 * XATo2nd / 28 + 325 *
        XATo3rd / 14)


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 sudo_wrap_command(command):
    """adds a 'sudo' prefix to command to run as root.
    no support for sudo'ing to configurable users/groups"""
    sudo_prefix = 'sudo --non-interactive'
    return '%s %s' % (sudo_prefix, command)


def check_console_width(val):
    """ Show ruler to check console width. """
    valid = True
    message = '-' * val + '\n'
    message += (
        'console_width set to %s, try a lower value if above line overlaps' %
        val)
    return dict(valid=valid, message=message)


def o_to_matsubara_idx_f(o):
    """
    Convert index in "o" convension to fermionic Matsubara index

    Parameters
    ----------
    o 2*n+1

    Returns n
    -------

    """
    assert o % 2 == 1
    return int((o - 1) / 2)


@classmethod
def compensate(cls, amount):
    """ Increases the amount in such a way that the stripe fee is included
        in the effective charge (that is, the user paying the charge is paying
        the fee as well).

        """
    return round((float(amount) + cls.fixed) / (1 - cls.percentage), 2)


def true_positives(y_true, y_pred):
    """calculate the number of true positives using bitwise operations,
    emulating the way sklearn evaluation metric functions work"""
    return (y_true & y_pred).sum()


def print_valid(prefix: str, item: str):
    """
    Used to return a string if not null, with optional prefix
    :param prefix: str optional item to place before the item if it is not null
    :param item: item to return if not null
    :return: str
    """
    if item:
        return f'{prefix}{item}'
    else:
        return ''


def evaluate_filepath_conditions(file_destination: str, run_configurations:
    dict) ->(str, bool):
    """
    File paths passed will be checked for partial Mustache syntax for sections. If a section tag is provided ({{#section}},
    then the run configuration is checked for the tag.

    If the condition is met, then the destination path will be cleaned
    of the section tags and a true value will be returned.

    If the condition is not met, then the string as it is currently
    being processed at the time of failure is returned, and a false value is returned with it.

    :param file_destination:
    :param run_configurations:
    :return:
    """
    conditional_tag = '{{#'
    tag_close = '}}'
    conditional_tag_len = len(conditional_tag)
    tag_close_len = len(tag_close)
    conditional_tag_index = file_destination.find(conditional_tag)
    while conditional_tag_index >= 0:
        tag_close_index = file_destination.find(tag_close,
            conditional_tag_index)
        tag_start_index = conditional_tag_index + conditional_tag_len
        tag_key = file_destination[tag_start_index:tag_close_index]
        if tag_key not in run_configurations or not run_configurations[tag_key
            ]:
            return file_destination, False
        file_destination = file_destination[:conditional_tag_index
            ] + file_destination[tag_close_index + tag_close_len:]
        conditional_tag_index = file_destination.find(conditional_tag,
            tag_close_index + tag_close_len)
    return file_destination, True


def select_similar_region():
    """Select similar face regions to the current selection

    """
    pass


def _py_interpreter_range(py_version):
    """
    Yield Python versions in descending order.

    After the latest version, the major-only version will be yielded, and then
    all following versions up to 'end'.
    """
    yield 'py{major}{minor}'.format(major=py_version[0], minor=py_version[1])
    yield 'py{major}'.format(major=py_version[0])
    for minor in range(py_version[1] - 1, -1, -1):
        yield 'py{major}{minor}'.format(major=py_version[0], minor=minor)


def migrate(ml):
    """perform the migration from an old list version to a new list version"""


@staticmethod
def _convert_string_to_list(string):
    """ Converts various strings to a list """
    string = string.replace(',', ' ')
    string = string.replace('[', '')
    string = string.replace(']', '')
    string = string.replace('"', '')
    string = string.replace("'", '')
    string_list = string.split()
    return string_list


def ip_str_to_bin(ip_str):
    """
    转化ip格式，从str转为bin
    :param ip_str:
    :return:
    """
    import socket
    return socket.inet_aton(ip_str)


def _clean_path(path):
    """Removes trailing slash if present, unless it's the root path."""
    if len(path) > 1 and path.endswith('/'):
        return path[:-1]
    return path


def escape_markdown(raw_string):
    """Returns a new string which escapes all markdown metacharacters.

    Args
    ----
    raw_string : str
        A string, possibly with markdown metacharacters, e.g. "1 * 2"

    Returns
    -------
    A string with all metacharacters escaped.

    Examples
    --------
    ::
        escape_markdown("1 * 2") -> "1 \\* 2"
    """
    metacharacters = ['\\', '*', '-', '=', '`', '!', '#', '|']
    result = raw_string
    for character in metacharacters:
        result = result.replace(character, '\\' + character)
    return result


def initialelemdict():
    """Create an inital empty orbital elements dictionary for use by read_neocp_orbit."""
    keys = 'name H G epoch mean_anomaly long_node arg_perihelion inclination '
    keys += 'eccentricity MDM semi_axis n_obs n_nights type'
    return {}.fromkeys(keys.split())


def default_mount(hdd=None):
    """
    Content of Mount tab.

    Arguments:
    hdd - Content is related to HDD

    Return:
    Content items as list
    """
    if hdd is not None:
        name = 'HDD'
    else:
        name = ''
    items = [['Mount name', name, str, '', 'PLAIN', '', ''], ['Protocol', [
        'smbfs', 'cifs', 'nfs'], str, '', 'COMBO', '', ''], [
        'Protocol version', '2.0', float, '', 'PLAIN', '', ''], ['sec', [
        'ntlmssp', 'krb5', 'krb5i', 'ntlm', 'ntlmi', 'ntlmv2', 'ntlmv2i',
        'ntlmsspi', 'none'], str, '', 'COMBO', '', ''], ['gid', '', str, '',
        'PLAIN', '', ''], ['Domain', '', str, '', 'PLAIN', '', ''], ['IP',
        '', str, '', 'PLAIN', '', ''], ['Folder', '', str, '', 'PLAIN', '',
        ''], ['Need folder extension?', ['False', 'True'], bool, '',
        'COMBO', '', ''], ['Default user', '', str, '', 'PLAIN', '', ''], [
        'Is df giving the right quota?', ['True', 'False'], bool, '',
        'COMBO', '', ''], ['Target UID exists here and on target?', ['True',
        'False'], bool, '', 'COMBO', '', ''], ['Need sudo for mount?', [
        'False', 'True'], bool, '', 'COMBO', '', ''], [
        'Need sudo for copy?', ['False', 'True'], bool, '', 'COMBO', '', ''
        ], ['SSH address', '', str, '', 'PLAIN', '', ''], ['Quota command',
        '', str, '', 'PLAIN', '', ''], ['Quota / TB', '', float, '',
        'PLAIN', '', ''], ['Typ', ['Import', 'Copy_work', 'Copy_backup'],
        str, '', 'COMBO', '', '']]
    return items


def mp_ab_vs_cd(a, b, c, d):
    """Tests rigorously if ab is greater than, equal to, or less than cd, given
    integers (a, b, c, d). In most cases a quick decision is reached. The
    result is +1, 0, or -1 in the three respective cases.
    See mpmath.pdf (item 33)."""
    if a * b == c * d:
        return 0
    if a * b > c * d:
        return 1
    return -1


def _MPSERIES(x):
    """Macro like function which makes clear that one is retrieving the actual
    underlying series, sliced starting at the MINPERIOD of the series"""
    return x._series[x._minperiod - 1:]


@staticmethod
def get_path(num):
    """Get a path from the workitem number.

        For example: 31942 will return 30000-39999/31000-31999/31900-31999
        """
    num = int(num)
    dig_len = len(str(num))
    paths = []
    for i in range(dig_len - 2):
        divisor = 10 ** (dig_len - i - 1)
        paths.append('{}-{}'.format(num // divisor * divisor, (num //
            divisor + 1) * divisor - 1))
    return '/'.join(paths)


@classmethod
def from_label(cls, xml_header):
    """ Create a Meta_HeaderStructure from the XML portion describing it in the label.

        Parameters
        ----------
        xml_header : Label or ElementTree Element
            Portion of label that defines the Header data structure.

        Returns
        -------
        Meta_HeaderStructure
            Instance containing meta data about the header structure, as taken from the XML label.

        Raises
        ------
        PDS4StandardsException
            Raised if required meta data is absent.
        """
    obj = cls()
    obj._load_keys_from_xml(xml_header)
    keys_must_exist = ['object_length', 'offset', 'parsing_standard_id']
    obj._check_keys_exist(keys_must_exist)
    return obj


def pprint_dist_dict(int_dict, indent=4, descending=False):
    """Prints the given dict, representing a normalized distribution, nicely.

    Parameters
    ----------
    int_dict : list
        A dict object mapping each key to an int value between 0 and 1, and all
        values sum to 1.
    """
    sorted_tup = sorted(int_dict.items(), key=lambda x: x[1])
    if descending:
        sorted_tup.reverse()
    print('{')
    for tup in sorted_tup:
        print('{}{}: {:.2f} %'.format(' ' * indent, tup[0], tup[1] * 100))
    print('}')


def get_shared_content_cache_key_ptr(site_id, slug, language_code):
    """
    Get the rendering cache key for a sharedcontent block.

    This key is an indirection for the actual cache key,
    which is based on the object ID and parent ID.
    """
    return 'sharedcontent_key.{0}.{1}.{2}'.format(site_id, slug, language_code)


def evaluate_expression(expression, vars):
    """evaluation an expression"""
    try:
        v = eval(expression, globals(), vars)
    except NameError:
        return None
    except ZeroDivisionError:
        return None
    except IndexError:
        return None
    return v


def set_metrics(metrics):
    """
    Set properly metrics that we want to load
    @metrics: list
    """
    result = []
    for i in metrics:
        d = {'expression': i}
        result.append(d)
    return result


@classmethod
def modifier_bit(cls, keycode):
    """Return the modifer bit to be set in an HID keycode report if this is a
        modifier key; otherwise return 0."""
    return (1 << keycode - 224 if cls.LEFT_CONTROL <= keycode <= cls.
        RIGHT_GUI else 0)


def compute_s_inf(arg1, arg2):
    """Signed comparison operator"""
    return (arg1 - arg2 ^ (arg1 ^ arg2) & (arg1 - arg2 ^ arg1)).msb()


def pop_smallest():
    """Return and remove the (item, score) pair with lowest score.

        If len(self) is 0, raise IndexError.

        To be cleaer, this is the lowest score among the N best-scoring
        seen so far.  This is most useful if the capacity of the NBest
        object is never exceeded, in which case  pop_smallest() allows
        using the object as an ordinary smallest-in-first-out priority
        queue.
        """


@classmethod
def loadf(cls, file_handle):
    """create a Model object from a file_handle pointing to a JSON file"""
    return cls.loads(file_handle.read())


@staticmethod
def _vlan_tag_check(literal):
    """
        Check if the VLAN tag literal is a range or not and returns start and end tag number.

        :param literal: (str) VLAN tag literal
        :return: start_vlan (str), end_vlan (str)
        """
    if '-' in literal:
        vlans = literal.strip('-')
        return vlans[0], vlans[1]
    else:
        return literal, literal


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


def zeta_H3PO4_Na_Cl_MP98(T, P):
    """phosphoric-acid sodium chloride [MP98]."""
    zeta = 0
    valid = T == 298.15
    return zeta, valid


def scan(stream, Loader=Loader):
    """
    Scan a YAML stream and produce scanning tokens.
    """
    loader = Loader(stream)
    try:
        while loader.scanner.check_token():
            yield loader.scanner.get_token()
    finally:
        loader._parser.dispose()


def bfs(start):
    """
    Breadth first search

    Yields all nodes found from the starting point

    :param start: start node
    """
    to_visit = [start]
    visited = set([start])
    while to_visit:
        node = to_visit.pop(0)
        yield node
        if node.exception_analysis:
            for _, _, exception in node.exception_analysis.exceptions:
                if exception not in visited:
                    to_visit.append(exception)
                    visited.add(exception)
        for _, _, child in node.childs:
            if child not in visited:
                to_visit.append(child)
                visited.add(child)


def convertToRowAndColumn(x, y, shape, xScale=None, yScale=None, safe=True):
    """
    Convert from plot coordinates to image row and column.
    """
    if xScale is None:
        c = x
    else:
        if x < xScale[0]:
            x = xScale[0]
        c = (x - xScale[0]) / xScale[1]
    if yScale is None:
        r = y
    else:
        if y < yScale[0]:
            y = yScale[0]
        r = (y - yScale[0]) / yScale[1]
    if safe:
        c = min(int(c), shape[1] - 1)
        r = min(int(r), shape[0] - 1)
    else:
        c = int(c)
        r = int(r)
    return r, c


@classmethod
def setup_instance(cls, remote):
    """Prepares an instance to mount this type of share."""
    pass


def vo_raise(exception_class, args=(), config=None, pos=None):
    """
    Raise an exception, with proper position information if available.
    """
    if config is None:
        config = {}
    raise exception_class(args, config, pos)


def row_indices(n, square_length):
    """ Returns the one-dimensional indices of all the cells belonging to the
		same row as index `n`.
	"""
    j = n // square_length
    return range(j * square_length, (j + 1) * square_length)


@classmethod
def from_dict(cls, dict_in):
    """Create an instance of this object from given dict.

        """
    name = list(dict_in.keys()).pop()
    values = dict_in[name]
    help_text = values.pop('text', None)
    return cls(name=name, help_text=help_text, **values)


def select(extend: bool=False, deselect: bool=False, toggle: bool=False,
    entire_strokes: bool=False, location: int=(0, 0)):
    """Select Grease Pencil strokes and/or stroke 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 entire_strokes: Entire Strokes, Select entire strokes instead of just the nearest stroke vertex
    :type entire_strokes: bool
    :param location: Location, Mouse location
    :type location: int
    """
    pass


def _convert_split(builder, node, graph, err):
    """
    convert to CoreML Squeeze Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#5003
    """
    axis = node.attrs.get('axis', 0)
    split = node.attrs.get('split', None)
    num_splits = len(node.outputs) if split is None else 2
    builder.add_split_nd(name=node.name, input_name=node.inputs[0],
        output_names=node.outputs, axis=axis, num_splits=num_splits,
        split_sizes=split)


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

        :param DomainInvitesSetInviteNewUserPrefToNoType val:
        :rtype: EventType
        """
    return cls('domain_invites_set_invite_new_user_pref_to_no', val)


def derive_aggregation(dim_cols, agg_col, agg):
    """Produces consistent aggregation spec from optional column specification.

    This utility provides some consistency to the flexible inputs that can be provided
    to charts, such as not specifying dimensions to aggregate on, not specifying an
    aggregation, and/or not specifying a column to aggregate on.
    """
    if dim_cols == 'index' or agg_col == 'index' or dim_cols is None:
        agg = None
        agg_col = None
    elif agg_col is None:
        if isinstance(dim_cols, list):
            agg_col = dim_cols[0]
        else:
            agg_col = dim_cols
        agg = 'count'
    return agg_col, agg


def delete():
    """Delete active scene

    """
    pass


def delete_duplicate_br(doc, maxnum=2):
    """Continuous ``
`` tags to maximum ``
``, to save display space.

    >>> el = fromstring('
aaa

bbb

')
    >>> delete_duplicate_br(el)
    >>> tostring(el)
    '
aaa

  bbb

'
    """
    num = 0
    _remove = []
    for el in doc.iter():
        if el.tag == 'br':
            num += 1
            if num > maxnum:
                _remove.append(el)
            if el.tail is None or el.tail.strip() == '':
                num = min(num, maxnum)
            else:
                num = 0
        else:
            num = 0
    for el in list(_remove):
        el.drop_tag()


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

        :param FileLockingValue val:
        :rtype: UserFeatureValue
        """
    return cls('file_locking', val)


def lookupModel():
    """Return the IModel specified in either the model_source or
        model_file (the former takes precedence). See plone.supermodel for
        more information about this type.

        If neither a model_source or a model_file is given, but a schema is
        given, return a faux model that contains just this schema.

        Note that model.schema is not necessarily going to be the same as
        the schema returned by lookupSchema().
        """


@classmethod
def generate(cls, size, callback, channels=3, target_mode=None):
    """Generates new LUT using provided callback.

        :param size: Size of the table. Passed to the constructor.
        :param callback: Function with three parameters which correspond
                         three color channels. Will be called ``size**3``
                         times with values from 0.0 to 1.0 and should return
                         a tuple with ``channels`` elements.
        :param channels: The number of channels which should return callback.
        :param target_mode: Passed to the constructor of the resulting
                            lookup table.
        """
    size1D, size2D, size3D = cls._check_size(size)
    if channels not in (3, 4):
        raise ValueError('Only 3 or 4 output channels are supported')
    table = [0] * (size1D * size2D * size3D * channels)
    idx_out = 0
    for b in range(size3D):
        for g in range(size2D):
            for r in range(size1D):
                table[idx_out:idx_out + channels] = callback(r / (size1D -
                    1), g / (size2D - 1), b / (size3D - 1))
                idx_out += channels
    return cls((size1D, size2D, size3D), table, channels=channels,
        target_mode=target_mode, _copy_table=False)


def string_to_num(s):
    """Converts a string to an int/float

    Returns ``None`` if it can't be converted

    >>> string_to_num('5')
    5
    >>> string_to_num('5.2')
    5.2
    >>> string_to_num(10)
    10
    >>> string_to_num(10.1)
    10.1
    >>> string_to_num('this is not a string') is None
    True
    """
    if isinstance(s, (int, float)):
        return s
    if s.isdigit():
        return int(s)
    try:
        return float(s)
    except ValueError:
        return None


def bodyfinder(text):
    """ Return body or unchanged text if no body tags found.

    Always use html_headcheck() first.
    """
    lowertext = text.lower()
    bodystart = lowertext.find('<body')
    if bodystart == -1:
        return text
    bodystart = lowertext.find('>', bodystart) + 1
    if bodystart == 0:
        return text
    bodyend = lowertext.rfind('</body>', bodystart)
    if bodyend == -1:
        return text
    return text[bodystart:bodyend]


def combine():
    """
    @api {post} /music/search/combine 综合搜索
    @apiVersion 1.0.0
    @apiGroup Search
    @apiDescription 综合搜索

    @apiParam (Headers) {string} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳

    @apiParam (Body) {String} searchvalue 搜索词
    @apiParam (Body) {String} pageSize 请求的每页所含条目数目。注意：允许最大为100，否则都按100返回

    @apiSuccess (Success) {Object} music 音乐
    @apiSuccess (Success) {String} music.AlbumCoverL 大尺寸专辑封面
    @apiSuccess (Success) {String} music.AlbumCoverM 中等尺寸专辑封面
    @apiSuccess (Success) {String} music.AlbumCoverS 小尺寸专辑封面
    @apiSuccess (Success) {String} music.AlbumID 专辑编号
    @apiSuccess (Success) {String} music.AlbumName 专辑名称
    @apiSuccess (Success) {String} music.ArtistID 歌手编号
    @apiSuccess (Success) {String} music.ArtistName 歌手名称
    @apiSuccess (Success) {String} music.ContentProviderID 内版权唱片公司ID
    @apiSuccess (Success) {String} music.Gender 性别
    @apiSuccess (Success) {String} music.Genre 流派类型
    @apiSuccess (Success) {String} music.ItemCode 单曲代码
    @apiSuccess (Success) {String} music.ItemID 单曲编号
    @apiSuccess (Success) {String} music.ItemType 单曲类型
    @apiSuccess (Success) {String} music.LanguageType 语言类型
    @apiSuccess (Success) {String} music.Name 名称
    @apiSuccess (Success) {String} music.ProductID 产品编号
    @apiSuccess (Success) {String} music.Rating 收听总数
    @apiSuccess (Success) {String} music.RegionCode 区域代码
    @apiSuccess (Success) {String} music.ReleaseDate 发布日期
    @apiSuccess (Success) {String} music.StartDate 开始日期
    @apiSuccess (Success) {String} music.TranslateName 翻译名称
    @apiSuccess (Success) {String} music.version 版本

    @apiSuccess (Success) {Object} Album 专辑列表
    @apiSuccess (Success) {String} Album.AlbumID 专辑编号
    @apiSuccess (Success) {String} Album.ArtistID 专辑歌手编号
    @apiSuccess (Success) {String} Album.ArtistName 专辑歌手名称
    @apiSuccess (Success) {String} Album.ContentProviderID 专辑版权唱片公司ID
    @apiSuccess (Success) {String} Album.Genre 专辑流派类型
    @apiSuccess (Success) {String} Album.LanguageType 专辑语言类型
    @apiSuccess (Success) {String} Album.Name 专辑名称
    @apiSuccess (Success) {String} Album.Price 专辑价格
    @apiSuccess (Success) {String} Album.Rating 专辑收听总数
    @apiSuccess (Success) {String} Album.ReleaseDate 专辑发布日期
    @apiSuccess (Success) {String} Album.TranslateName 专辑翻译名称
    @apiSuccess (Success) {String} Album.version 专辑版本
    @apiSuccess (Success) {String} Album.JPG-1000X1000-ALBUM 专辑专辑图片（1000X1000）
    @apiSuccess (Success) {String} Album.JPG-240X240-ALBUM 专辑专辑图片（240X240）
    @apiSuccess (Success) {String} Album.JPG-320X320-ALBUM 专辑专辑图片（320X320）
    @apiSuccess (Success) {String} Album.JPG-600X600-ALBUM 专辑专辑图片（600X600）
    @apiSuccess (Success) {String} Album.NoOfTracks 专辑声音编号

    @apiSuccess (Success) {Object} Artist 歌手列表
    @apiSuccess (Success) {String} Artist.ArtistID 歌手编号
    @apiSuccess (Success) {String} Artist.Gender 歌手流派类型
    @apiSuccess (Success) {String} Artist.Name 歌手名
    @apiSuccess (Success) {String} Artist.Rating 歌手收听总数
    @apiSuccess (Success) {String} Artist.RegionCode 歌手区域代码
    @apiSuccess (Success) {String} Artist.TranslateName 歌手翻译名称
    @apiSuccess (Success) {String} Artist.AlbumCount 歌手专辑数量
    @apiSuccess (Success) {String} Artist.Birthday 歌手生日
    @apiSuccess (Success) {String} Artist.Blood 歌手血型
    @apiSuccess (Success) {String} Artist.Country 歌手国家
    @apiSuccess (Success) {String} Artist.Height 歌手身高
    @apiSuccess (Success) {String} Artist.Horoscope 歌手星座
    @apiSuccess (Success) {String} Artist.ItemCount 歌手单曲数量
    @apiSuccess (Success) {String} Artist.JPG-1000X1000-Artist 歌手图片（1000X1000）
    @apiSuccess (Success) {String} Artist.JPG-240X240-Artist 歌手图片（240X240）
    @apiSuccess (Success) {String} Artist.JPG-320X320-Artist 歌手图片（320X320）
    @apiSuccess (Success) {String} Artist.JPG-600X600-Artist 歌手图片（600X600）
    @apiSuccess (Success) {String} Artist.Weight 体重

    @apiSuccessExample {json} Success-Response:
    {
        "music": [
            {
                "AlbumCoverL": "/album/011/116872-JPG-1000X1000-ALBUM.jpg",
                "AlbumCoverM": "/album/011/116872-JPG-600X600-ALBUM.jpg",
                "AlbumCoverS": "/album/011/116872-JPG-320X320-ALBUM.jpg",
                "AlbumID": [
                    "116872"
                ],
                "AlbumName": [
                    "下课后"
                ],
                "ArtistID": [
                    "88399"
                ],
                "ArtistName": [
                    "经典老歌"
                ],
                "ContentProviderID": 4461,
                "Gender": [
                    "group"
                ],
                "Genre": "children",
                "ItemCode": "00000000",
                "ItemID": "1209670",
                "ItemType": "ftd",
                "LanguageType": "man",
                "Name": "三字经",
                "ProductID": 1209670,
                "Rating": 2289382,
                "RegionCode": [
                    "CN"
                ],
                "ReleaseDate": "1992-01-26",
                "StartDate": "1992-01-26",
                "TranslateName": "三字经",
                "version": ""
            }
        ],
        "album": [
            {
                "AlbumID": "116872",
                "ArtistID": "88399",
                "ArtistName": "经典老歌",
                "ContentProviderID": "4461",
                "Genre": "Children",
                "LanguageType": "MAN",
                "Name": "下课后",
                "Price": "0",
                "Rating": "1848966",
                "ReleaseDate": "1992-01-26T00:00:00Z",
                "TranslateName": "下课后",
                "version": "",
                "JPG-1000X1000-ALBUM": "/album/011/116872-JPG-1000X1000-ALBUM.jpg",
                "JPG-240X240-ALBUM": "/album/011/116872-JPG-240X240-ALBUM.jpg",
                "JPG-320X320-ALBUM": "/album/011/116872-JPG-320X320-ALBUM.jpg",
                "JPG-600X600-ALBUM": "/album/011/116872-JPG-600X600-ALBUM.jpg",
                "NoOfTracks": "1"
            }
        ],
        "artist": [
            {
                "ArtistID": "88399",
                "Gender": "Group",
                "Name": "经典老歌",
                "Rating": 1952167,
                "RegionCode": "CN",
                "TranslateName": "经典老歌",
                "AlbumCount": 1,
                "Birthday": "0000-00-00",
                "Blood": "N/A",
                "Country": "中国",
                "Height": 0,
                "Horoscope": "",
                "ItemCount": 1,
                "JPG-1000X1000-ARTIST": "/artist/008/88399-JPG-1000X1000-ARTIST.jpg",
                "JPG-240X240-ARTIST": "/artist/008/88399-JPG-240X240-ARTIST.jpg",
                "JPG-320X320-ARTIST": "/artist/008/88399-JPG-320X320-ARTIST.jpg",
                "JPG-600X600-ARTIST": "/artist/008/88399-JPG-600X600-ARTIST.jpg",
                "Weight": 0
            }
        ]
    }

    @apiError (Error) 31003 No keyword in the request params!

    @apiErrorExample {json} Error-Response:
    {
        "data": "No keyword in the request params!"
    }
    """


@staticmethod
def rmsd(df1, df2, heavy_only=True):
    """Compute the Root Mean Square Deviation between molecules

        Parameters
        ----------
        df1 : pandas.DataFrame
            DataFrame with HETATM, ATOM, and/or ANISOU entries
        df2 : pandas.DataFrame
            Second DataFrame for RMSD computation against df1. Must have the
            same number of entries as df1
        heavy_only : bool (default: True)
            Which atoms to compare to compute the RMSD. If `True` (default),
            computes the RMSD between non-hydrogen atoms only.

        Returns
        ---------
        rmsd : float
            Root Mean Square Deviation between df1 and df2

        """
    if df1.shape[0] != df2.shape[0]:
        raise AttributeError('DataFrames have unequal lengths')
    if heavy_only:
        d1 = df1[df1['atom_type'] != 'H']
        d2 = df2[df2['atom_type'] != 'H']
    else:
        d1, d2 = df1, df2
    total = (d1['x'].values - d2['x'].values) ** 2 + (d1['y'].values - d2[
        'y'].values) ** 2 + (d1['z'].values - d2['z'].values) ** 2
    rmsd = round((total.sum() / df1.shape[0]) ** 0.5, 4)
    return rmsd


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 custom_latex_processing(latex):
    """
    Processes a :epkg:`latex` file and returned the modified version.

    @param      latex       string
    @return                 string
    """
    if latex is None:
        raise ValueError('Latex is null')
    return latex


def complete_nro(val, character='0', n=3):
    """
    Complete with 0 a number until n chars
    """
    s_val = str(val).upper()
    ln = len(s_val)
    delta = n - ln
    s_out = ''
    for k in range(delta):
        s_out += character
    s_out += s_val
    return s_out


def flattened():
    """Return an iterator of all included and extended interfaces

        An iterator is returned for all interfaces either included in
        or extended by interfaces included in the specifications
        without duplicates. The interfaces are in "interface
        resolution order". The interface resolution order is such that
        base interfaces are listed after interfaces that extend them
        and, otherwise, interfaces are included in the order that they
        were defined in the specification.
        """


def html5_collapsible(summary, details) ->str:
    """Return nestable, collapsible <detail> tag for check grouping and sub-
    results."""
    return (
        f'{summary}
{details}
')


def _ADD_immediate(cpu, res_op, reg_op, imm_op):
    """
        ADD (immediate).

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


def gravity_aug(acceleration, friction_coefficient):
    """Usage: Find gravitational constant using acceleration and friction coefficient"""
    return acceleration / friction_coefficient


def init_state_collection(state, dict_, key):
    """Initialize a collection attribute and return the collection adapter."""
    attr = state.manager[key].impl
    user_data = attr.initialize(state, dict_)
    return attr.get_collection(state, dict_, user_data)


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


def parse_boolean(val):
    """String to boolean type."""
    return True if val and val.lower() == 'true' else False


def integer_to_binary_string(n) ->str:
    """
    Changes positive integer ``n`` to binary string.

    ..  container:: example

        >>> for n in range(1, 16 + 1):
        ...     print('{}\\t{}'.format(n, abjad.mathtools.integer_to_binary_string(n)))
        ...
        1  1
        2  10
        3  11
        4  100
        5  101
        6  110
        7  111
        8  1000
        9  1001
        10 1010
        11 1011
        12 1100
        13 1101
        14 1110
        15 1111
        16 10000

    """
    if n == 0:
        return '0'
    result = bin(abs(n)).lstrip('-0b')
    if n < 0:
        result = '-' + result
    return result


@classmethod
def from_response(cls, response):
    """ Create Throughput from returned Dynamo data """
    return cls(response['ReadCapacityUnits'], response['WriteCapacityUnits'])


def contract_tuple(chunks, factor):
    """ Return simple chunks tuple such that factor divides all elements

    Examples
    --------

    >>> contract_tuple((2, 2, 8, 4), 4)
    (4, 8, 4)
    """
    assert sum(chunks) % factor == 0
    out = []
    residual = 0
    for chunk in chunks:
        chunk += residual
        div = chunk // factor
        residual = chunk % factor
        good = factor * div
        if good:
            out.append(good)
    return tuple(out)


def get_contigs_splits_dict(split_ids, splits_basic_info):
    """
    For a given list of split ids, create a dictionary of contig names
    that represents all parents as keys, and ordered splits as items.

    split_ids is a set of split IDs, splits_basic_info comes from the contigs database:

     >>> contigs_db = dbops.ContigsDatabase(contigs_db_path)
     >>> splits_basic_info = contigs_db.db.get_table_as_dict(t.splits_info_table_name)
     >>> znnotation_db.disconnect()
     >>> x = get_contigs_splits_dict(set([contig_A_split_00001, contig_A_split_00002, contig_A_split_00004,
                                         contig_C_split_00003, contig_C_split_00004, contig_C_split_00005]),
                                    splits_basic_info)
     >>> print x
         {
             'contig_A': {
                             0: 'contig_A_split_00001',
                             1: 'contig_A_split_00002',
                             4: 'contig_A_split_00004'
                         },
             'contig_C': {
                             3: 'contig_C_split_00003',
                             4: 'contig_C_split_00004',
                             5: 'contig_C_split_00005'
                         }
         }
    """
    contigs_splits_dict = {}
    for split_id in split_ids:
        s = splits_basic_info[split_id]
        if s['parent'] in contigs_splits_dict:
            contigs_splits_dict[s['parent']][s['order_in_parent']] = split_id
        else:
            contigs_splits_dict[s['parent']] = {s['order_in_parent']: split_id}
    return contigs_splits_dict


def admm_wavelets_cone_beam_reconstruction_filter(*args, **kwargs):
    """Procedural interface for ADMMWaveletsConeBeamReconstructionFilter"""
    import itk
    instance = itk.ADMMWaveletsConeBeamReconstructionFilter.New(*args, **kwargs
        )
    return instance.__internal_call__()


def div(numer, denom):
    """PFA division behavior: inf and -inf for a finite number divided by zero and nan for 0/0.

    Also ensures that return type of any two numbers (including integers) is floating point.

    :type numer: number
    :param numer: the numerator
    :type denom: number
    :param denom: the denominator
    :rtype: float
    :return: fraction, including non-numeric possibilities
    """
    try:
        return numer / float(denom)
    except ZeroDivisionError:
        if numer > 0.0:
            return float('inf')
        elif numer < 0.0:
            return float('-inf')
        else:
            return float('nan')