def _get_sub_types_of_compositional_types(compositional_type: str) ->tuple:
    """
    Extract the sub-types of compositional types.

    This method handles both specification types (e.g. pt:set[], pt:dict[]) as well as python types (e.g. FrozenSet[], Union[]).

    :param compositional_type: the compositional type string whose sub-types are to be extracted.
    :return: tuple containing all extracted sub-types.
    """
    sub_types_list = list()
    if compositional_type.startswith('Optional'
        ) or compositional_type.startswith('pt:optional'):
        sub_type1 = compositional_type[compositional_type.index('[') + 1:
            compositional_type.rindex(']')].strip()
        sub_types_list.append(sub_type1)
    if compositional_type.startswith('FrozenSet'
        ) or compositional_type.startswith('pt:set'
        ) or compositional_type.startswith('pt:list'):
        sub_type1 = compositional_type[compositional_type.index('[') + 1:
            compositional_type.rindex(']')].strip()
        sub_types_list.append(sub_type1)
    if compositional_type.startswith('Tuple'):
        sub_type1 = compositional_type[compositional_type.index('[') + 1:
            compositional_type.rindex(']')].strip()
        sub_type1 = sub_type1[:-5]
        sub_types_list.append(sub_type1)
    if compositional_type.startswith('Dict') or compositional_type.startswith(
        'pt:dict'):
        sub_type1 = compositional_type[compositional_type.index('[') + 1:
            compositional_type.index(',')].strip()
        sub_type2 = compositional_type[compositional_type.index(',') + 1:
            compositional_type.rindex(']')].strip()
        sub_types_list.extend([sub_type1, sub_type2])
    if compositional_type.startswith('Union') or compositional_type.startswith(
        'pt:union'):
        inside_union = compositional_type[compositional_type.index('[') + 1
            :compositional_type.rindex(']')].strip()
        while inside_union != '':
            if inside_union.startswith('Dict') or inside_union.startswith(
                'pt:dict'):
                sub_type = inside_union[:inside_union.index(']') + 1].strip()
                rest_of_inside_union = inside_union[inside_union.index(']') +
                    1:].strip()
                if rest_of_inside_union.find(',') == -1:
                    inside_union = rest_of_inside_union.strip()
                else:
                    inside_union = rest_of_inside_union[
                        rest_of_inside_union.index(',') + 1:].strip()
            elif inside_union.startswith('Tuple'):
                sub_type = inside_union[:inside_union.index(']') + 1].strip()
                rest_of_inside_union = inside_union[inside_union.index(']') +
                    1:].strip()
                if rest_of_inside_union.find(',') == -1:
                    inside_union = rest_of_inside_union.strip()
                else:
                    inside_union = rest_of_inside_union[
                        rest_of_inside_union.index(',') + 1:].strip()
            elif inside_union.find(',') == -1:
                sub_type = inside_union.strip()
                inside_union = ''
            else:
                sub_type = inside_union[:inside_union.index(',')].strip()
                inside_union = inside_union[inside_union.index(',') + 1:
                    ].strip()
            sub_types_list.append(sub_type)
    return tuple(sub_types_list)


def _build_decrypt_parser(subparsers):
    """Build the decryption subparser."""
    decrypt_parser = subparsers.add_parser('decrypt', description=
        'Decrypts a file')
    decrypt_parser.add_argument('filename', action='store', help=
        'The file or directory to decrypt. Use "-" to read from stdin')


def is_real(e) ->bool:
    """ Returns ``True`` if `e` is a ``float``. """
    return type(e) is float


@classmethod
def type_descriptor(cls, typeobj):
    """Transform a generic type to a dialect-specific type.

        Dialect classes will usually use the
        :func:`_types.adapt_type` function in the types module to
        accomplish this.

        The returned result is cached *per dialect class* so can
        contain no dialect-instance state.

        """
    raise NotImplementedError()


def with_later(value):
    """
        Add the ``(state, tid)`` (another ICachedValue) to the list of
        cached entries. Return the new value to place in the cache.
        """


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

        :param ShowcaseViewDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_view_details', val)


def _count_of_prev(rule):
    """Count previous tokens to be present before a match in a rule."""
    return len(rule.prev_classes or []) + len(rule.prev_tokens or [])


def update_with_dict(obj, fields):
    """Update and save a model from the values of a :class:`dict`."""
    set_value = lambda name, val: setattr(obj, name, val)
    map(set_value, fields.items())
    obj.save()
    return obj


def get_pending_time(user_email):
    """
        returns a time indicating a user's pending status
        """


def extract_yyyy_mm_dd_hh_mm_ss_from_datetime64(dt64):
    """

    Extract separate fields for year, monday, day, hour, min, sec from
    a datetime64 object

    Parameters
    ----------
    dt64 : numpy.datetime64
        a datetime64 object

    Returns
    -------
    year, mon, day, hh, mm, ss : int

    """
    s = str(dt64)
    year = int(s[0:4])
    mon = int(s[5:7])
    day = int(s[8:10])
    hh = int(s[11:13])
    mm = int(s[14:16])
    ss = int(s[17:18])
    return year, mon, day, hh, mm, ss


def is_fp_closed(obj):
    """
    Checks whether a given file-like object is closed.

    :param obj:
        The file-like object to check.
    """
    try:
        return obj.isclosed()
    except AttributeError:
        pass
    try:
        return obj.closed
    except AttributeError:
        pass
    try:
        return obj.fp is None
    except AttributeError:
        pass
    raise ValueError('Unable to determine whether fp is closed.')


def flatten_list(lst):
    """
    Flattens a list of lists

    :param lst: list

    """
    flatten = []
    for item in lst:
        if isinstance(item, list):
            flatten.extend(item)
        else:
            flatten.append(item)
    return flatten


@classmethod
def _get_style_sources(cls, styling_section, element):
    """Returns a list, containing  tags, in the order they should be
        evaluated, for determining layout information.

        This method should be extended if the styles provided by it are not
        enough (like for the captions created with CaptionMaker 6, which are
        not compatible with the specs)

        Check the URL for detailed description of how styles should be resolved
        http://www.w3.org/TR/ttaf1-dfxp/#semantics-style-association

        Returns:
          1. All child styles of the element, each with its reference chain
          2. The style referenced by the element, via the attrib. style="asdf"
            together with its reference chain
        Note: the specs are unclear about the priority of styles that are
        referenced by nested styles. I've assumed it's higher than referential
        styling
        """
    if not hasattr(element, u'findAll'):
        return ()
    nested_styles = []
    if element.name not in (u'div', u'body', u'tt'):
        for style in element.contents:
            if getattr(style, u'name', None) == u'style':
                nested_styles.extend(cls._get_style_reference_chain(style,
                    styling_section))
    referenced_style_id = element.get(u'style')
    referenced_styles = []
    if referenced_style_id and styling_section:
        referenced_style = styling_section.findChild(u'style', {u'xml:id':
            referenced_style_id})
        referenced_styles = cls._get_style_reference_chain(referenced_style,
            styling_section)
    return nested_styles + referenced_styles


def AMPMMinutes():
    """Return the time string for an object not showing seconds."""


def guess_angles(bonds):
    """Given a list of Bonds, find all angles that exist between atoms.

    Works by assuming that if atoms 1 & 2 are bonded, and 2 & 3 are bonded,
    then (1,2,3) must be an angle.

    Returns
    -------
    list of tuples
        List of tuples defining the angles.
        Suitable for use in u._topology

    See Also
    --------
    :meth:`guess_bonds`

    .. versionadded 0.9.0
    """
    angles_found = set()
    for b in bonds:
        for atom in b:
            other_a = b.partner(atom)
            for other_b in atom.bonds:
                if other_b != b:
                    third_a = other_b.partner(atom)
                    desc = tuple([other_a.index, atom.index, third_a.index])
                    if desc[0] > desc[-1]:
                        desc = desc[::-1]
                    angles_found.add(desc)
    return tuple(angles_found)


def increment_period(value, periods, frequency):
    """Incrementa una fecha en X períodos, según su frecuencia."""
    actions = {'A': lambda : value.replace(years=+periods), '6M': lambda :
        value.replace(months=+(6 * periods)), 'Q': lambda : value.replace(
        months=+(3 * periods)), 'M': lambda : value.replace(months=+periods
        ), 'D': lambda : value.replace(days=+periods)}
    try:
        return actions[frequency]()
    except KeyError:
        raise ValueError('No se reconoce la frecuencia {}'.format(frequency))


def trip2str(trip):
    """ Pretty-printing. """
    header = '{} {} {} - {}:'.format(trip['departureTime'], trip[
        'departureDate'], trip['origin'], trip['destination'])
    output = [header]
    for subtrip in trip['trip']:
        originstr = u'{}....{}'.format(subtrip['departureTime'], subtrip[
            'origin'])
        output.append(originstr)
        for subsubtrip in subtrip['trip']:
            t = subsubtrip['arrivalTime']
            d = subsubtrip['stop']
            intermediatestr = t + u'.' * 8 + d
            output.append(intermediatestr)
        destinationstr = u'{}....{}'.format(subtrip['arrivalTime'], subtrip
            ['destination'])
        output.append(destinationstr)
    return '\n'.join(output)


def node_to_col(node, num_rows):
    """Returns column ID of a node in the intance's graph representation that represents a column.

    Args:
        node (int): The node ID of the column in the graph representation.
        num_rows (int): The number of rows in the instance.

    Returns:
        int: Column ID of the node. If negative, the node is not a column but a row.
    """
    return node - num_rows


@classmethod
def greaseMonkeyManager(cls):
    """
        Class method to get a reference to the GreaseMonkey manager.

        @return reference to the GreaseMonkey manager (GreaseMonkeyManager)
        """
    if cls._greaseMonkeyManager is None:
        from .GreaseMonkey.GreaseMonkeyManager import GreaseMonkeyManager
        cls._greaseMonkeyManager = GreaseMonkeyManager()
    return cls._greaseMonkeyManager


def get_edges(source_label, target_label, edge_label):
    """Generate query for getting all the edges of the graph.

    Parameters
    ----------
    source_label : optional
        Label of the source nodes to match
    target_label : optional
        Label of the target nodes to match
    edge_label : iterable, optional
        Label of the edges to match
    """
    query = 'MATCH (n:{})-[r:{}]->(m:{})\nRETURN n.id, m.id\n'.format(
        source_label, edge_label, target_label)
    return query


@classmethod
def construct_limit(cls, count):
    """
        Create a condition that will limit the results to a count

        Parameters
        ----------
        count : int

        Returns
        -------
        condition : :class:`.Condition`

        """
    c = cls()
    c.limit = count
    return c


def mail_password_subject():
    """ returns encoded version of mail password template subject line """


def p_expr_string(p):
    """ bexpr : string %prec ID
    """
    p[0] = p[1]


def validate_pmid(pmid):
    """Validate PMID to annotate"""
    if not pmid or not isinstance(pmid, int) or pmid <= 0:
        raise ValueError('Invalid ``pmid`` parameter')


def theta_Mg_MgOH_HMW84(T, P):
    """c-c': magnesium magnesium-hydroxide [HMW84]."""
    theta = 0.0
    valid = T == 298.15
    return theta, valid


def get_pid(osi):
    """Get the processor ID of the calling processor."""
    return osi.to_process('getPID', [])


@classmethod
def pkey_get_withref(clas, pool_or_cursor, *vals):
    """get the thing and the stuff from REFKEYS in a single roundtrip"""
    raise NotImplementedError('todo')


def mem(dic, data):
    """
    Maximum Entropy Reconstruction
    """
    raise NotImplementedError


@classmethod
def load(cls, path):
    """Reads an ML instance from the input path, a shortcut of `read().load(path)`."""
    return cls.read().load(path)


@classmethod
def worldXY(cls):
    """Construct the world XY frame.

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

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


def join_host_port(host, port):
    """Joins a hostname and port together.

    This is a minimal implementation intended to cope with IPv6 literals. For
    example, _join_host_port('::1', 80) == '[::1]:80'.

    :Args:
        - host - A hostname.
        - port - An integer port.

    """
    if ':' in host and not host.startswith('['):
        return '[%s]:%d' % (host, port)
    return '%s:%d' % (host, port)


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

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    :param deselect: Deselect, Remove from selection
    :type deselect: bool
    :param toggle: Toggle Selection, Toggle the selection
    :type toggle: bool
    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


def parse_db_project(new_project):
    """Parse Project from database to JSON."""
    project_data = {'name': new_project.name, 'customer': new_project.
        customer.customer_id, 'families': []}
    for family in new_project.families:
        family_data = {'name': family.name, 'panels': family.panels,
            'priority': family.priority, 'delivery_type': family.
            delivery_type, 'require_qcok': family.require_qcok, 'samples':
            [], 'existing_family': True if family.existing_family else False}
        for sample in family.samples:
            sample_data = {'name': sample.name, 'sex': sample.sex, 'status':
                sample.status, 'application_tag': sample.application_tag.
                name if sample.application_tag else None, 'capture_kit':
                sample.capture_kit, 'source': sample.source, 'container':
                sample.container, 'container_name': sample.container_name,
                'well_position': sample.well_position, 'quantity': sample.
                quantity, 'existing_sample': True if sample.existing_sample
                 else False}
            for parent_id in ('father', 'mother'):
                parent_sample = getattr(sample, parent_id)
                if parent_sample:
                    sample_data[parent_id] = parent_sample.name
            family_data['samples'].append(sample_data)
            for key in list(sample_data.keys()):
                if sample_data[key] is None:
                    del sample_data[key]
        project_data['families'].append(family_data)
    return project_data


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


@staticmethod
def __calltipDisplayable(calltip):
    """True if calltip is displayable"""
    if calltip is None:
        return False
    if calltip.strip() == '':
        return False
    return True


def make_label_safe_for_cypher(label):
    """
    Make a given subset name safe for use in Cypher

    Parameters
    ----------
    label : str
        Subset name

    Returns
    -------
    str
        Cypher-safe name
    """
    if not label.startswith('`'):
        label = '`' + label
    if not label.endswith('`'):
        label += '`'
    return label


def strip_transient(nb):
    """Strip transient values that shouldn't be stored in files.

    This should be called in *both* read and write.
    """
    nb.metadata.pop('orig_nbformat', None)
    nb.metadata.pop('orig_nbformat_minor', None)
    nb.metadata.pop('signature', None)
    for cell in nb.cells:
        cell.metadata.pop('trusted', None)
    return nb


@staticmethod
def _word_too_long(encoded_word, environment):
    """ Is a given encoded word too long for the LMDB environment?

        :param bytes encoded_word:
        :return bool:
        """
    return len(encoded_word) > environment.max_key_size()


def list_functions(Marker=None, MaxItems=None):
    """
    Returns a list of your Lambda functions. For each function, the response includes the function configuration information. You must use  GetFunction to retrieve the code for your function.
    This operation requires permission for the lambda:ListFunctions action.
    If you are using versioning feature, the response returns list of $LATEST versions of your functions. For information about the versioning feature, see AWS Lambda Function Versioning and Aliases .
    See also: AWS API Documentation

    Examples
    This operation retrieves a Lambda functions
    Expected Output:

    :example: response = client.list_functions(
        Marker='string',
        MaxItems=123
    )

    :type Marker: string
    :param Marker: Optional string. An opaque pagination token returned from a previous ListFunctions operation. If present, indicates where to continue the listing.

    :type MaxItems: integer
    :param MaxItems: Optional integer. Specifies the maximum number of AWS Lambda functions to return in response. This parameter value must be greater than 0.

    :rtype: dict
    :return: {
        'NextMarker': 'string',
        'Functions': [
            {
                'FunctionName': 'string',
                'FunctionArn': 'string',
                'Runtime': 'nodejs'|'nodejs4.3'|'nodejs6.10'|'java8'|'python2.7'|'python3.6'|'dotnetcore1.0'|'nodejs4.3-edge',
                'Role': 'string',
                'Handler': 'string',
                'CodeSize': 123,
                'Description': 'string',
                'Timeout': 123,
                'MemorySize': 123,
                'LastModified': 'string',
                'CodeSha256': 'string',
                'Version': 'string',
                'VpcConfig': {
                    'SubnetIds': [
                        'string',
                    ],
                    'SecurityGroupIds': [
                        'string',
                    ],
                    'VpcId': 'string'
                },
                'DeadLetterConfig': {
                    'TargetArn': 'string'
                },
                'Environment': {
                    'Variables': {
                        'string': 'string'
                    },
                    'Error': {
                        'ErrorCode': 'string',
                        'Message': 'string'
                    }
                },
                'KMSKeyArn': 'string',
                'TracingConfig': {
                    'Mode': 'Active'|'PassThrough'
                }
            },
        ]
    }

    :returns:
    (string) --

    """
    pass


def to_list(obj):
    """
    Transforms a non iterable object into a singleton list, or an iterable
    into a list.
    """
    if isinstance(obj, list) or isinstance(obj, tuple):
        return list(obj)
    return [obj]


@classmethod
def begin(cls):
    """
        begin() and commit() let you explicitly specify an SQL transaction.
        Be sure to call commit() after you call begin().
        """
    db = cls.db
    db.b_commit = False


def parse_js(file_path, function_name, replace_vars=None):
    """
    | helper function to get a js function string from a file containing js functions
    | useful if we want to call js functions from python as in mongoDB map reduce.
    | Function must be named starting in first column and end with '}' in first column
      (see relevant functions in js directory)

    :Parameters:
        - file_path: (str) full path_name
        - function name: (str) name of function
        - replace_vars: (optional) a tuple to replace %s variables in functions
    :Returns: a js function as string
    """
    rt = ''
    start = 'function {}'.format(function_name)
    with open(file_path, 'r') as fin:
        ln = fin.readline()
        while ln:
            if ln.startswith(start) or rt:
                rt += ln
            if rt and ln.startswith('}'):
                break
            ln = fin.readline()
    if rt and replace_vars:
        return rt % replace_vars
    else:
        return rt


def keep_phase_in_dataset(saved_game_proto):
    """ Filter function that decides if we should put a phase in the dataset
        :param saved_game_proto: A `.proto.game.SavedGame` object from the dataset.
        :return: A boolean that indicates if we should keep this phase or not.
    """
    if saved_game_proto.map.startswith('standard'):
        return True
    return False


def unparse_netloc(user, password, hostname, port):
    """
    We expect the arguments to be strings, empty if not present.
    """
    netloc = ''
    up = user + ':' + password + '@'
    if len(up) > 2:
        netloc = up
    netloc += hostname
    if len(port) > 0:
        netloc += ':' + port
    return netloc


def accuracy_efficiency(rk1, parallel=False, mode='float', tol=1e-14, p=None):
    """
    Compute the accuracy efficiency of method rk1.

    The accuracy efficiency is

    `\\eta = \\frac{1}{s_1} \\left(\\frac{1}{A_1}\\right)^{1/p+1}`

    where `s_1` are the number of stages of the the method and
    `A_1` is its principal error norms.

    **Examples**::

        Accuracy efficiency of Dormand-Prince
        >>> from nodepy import rk
        >>> dp5 = rk.loadRKM('DP5')
        >>> rk.accuracy_efficiency(dp5) # doctest: +ELLIPSIS
        0.5264921944121...
    """
    if p is None:
        p = rk1.order(mode=mode, tol=tol)
    A1 = rk1.principal_error_norm(mode=mode, tol=tol)
    if parallel:
        return 1.0 / rk1.num_seq_dep_stages() * (1.0 / A1) ** (1.0 / (p + 1))
    else:
        return 1.0 / len(rk1) * (1.0 / A1) ** (1.0 / (p + 1))


def extract_from_url(url):
    """ Extracts information from a URL  and fills the passed kwargs dict
    with the key values extracted.

    Reference: http://docs.sqlalchemy.org/en/latest/core/engines.html

    :param str url:
    :return: key/value pairs for:
        'db_engine', 'db_host', 'db_port', 'db_usr', 'db_pwd'
    :rtype: dict
    """
    kwargs = {}
    protocol, rest = url.split('://', 1)
    kwargs['db_engine'] = protocol
    if '/' in rest:
        rest, kwargs['db_name'] = rest.split('/', 1)
    if '@' in rest:
        uid_pwd, host = rest.split('@')
        kwargs['db_usr'], kwargs['db_pwd'] = uid_pwd.split(':')
    else:
        host = rest
    if ':' in host:
        kwargs['db_host'], kwargs['db_port'] = host.split(':', 1)
    elif host:
        kwargs['db_host'], kwargs['db_port'] = host, '0'
    return kwargs


def broadcast_add(lhs=None, rhs=None, name=None, attr=None, out=None, **kwargs
    ):
    """Returns element-wise sum of the input arrays with broadcasting.

    `broadcast_plus` is an alias to the function `broadcast_add`.

    Example::

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

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

       broadcast_add(x, y) = [[ 1.,  1.,  1.],
                              [ 2.,  2.,  2.]]

       broadcast_plus(x, y) = [[ 1.,  1.,  1.],
                               [ 2.,  2.,  2.]]

    Supported sparse operations:

       broadcast_add(csr, dense(1D)) = dense
       broadcast_add(dense(1D), csr) = dense

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_basic.cc:L58

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

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

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


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

        :param SharedLinkViewType val:
        :rtype: EventType
        """
    return cls('shared_link_view', val)


@classmethod
def from_date(cls, d):
    """
        Create a ``RepublicanDate`` from the given ``datetime.date`` object.
        """
    return cls.from_gregorian(d.year, d.month, d.day)


@staticmethod
def send_socket(sock, data):
    """Send data to the connection."""
    sock.send(data)


def make_args(*args, **kwargs):
    """
    Useful for setting table args and mapper args on models and other things
    """
    return tuple(args) + (kwargs,)


@classmethod
def get_by_id(cls, context, db_id):
    """Find a volume connector based on its integer ID.

        :param cls: the :class:`VolumeConnector`
        :param context: Security context.
        :param db_id: The integer (database primary key) ID of a
                      volume connector.
        :returns: A :class:`VolumeConnector` object.
        :raises: VolumeConnectorNotFound if no volume connector exists with
                 the specified ID.
        """
    db_connector = cls.dbapi.get_volume_connector_by_id(db_id)
    connector = cls._from_db_object(context, cls(), db_connector)
    return connector


@staticmethod
def metadata_id(item):
    """Extracts the identifier from a Confluence item.

        This identifier will be the mix of two fields because a
        historical content does not have any unique identifier.
        In this case, 'id' and 'version' values are combined because
        it should not be possible to have two equal version numbers
        for the same content. The value to return will follow the
        pattern: <content>#v<version> (i.e 28979#v10).
        """
    cid = item['id']
    cversion = item['version']['number']
    return str(cid) + '#v' + str(cversion)


def suspend(storeID):
    """
        @type storeID: C{int}
        @param storeID: The storeID of the listener to suspend.

        @rtype: L{twisted.internet.defer.Deferred}
        @return: A Deferred which fires when the listener has been suspended.
        """


@staticmethod
def moveaxis(tensor, source, destination):
    """Move axes of a tensor to new positions.

        Parameters
        ----------
        tensor : tl.tensor
        source : int or sequence of int
            Original positions of the axes to move. These must be unique.
        destination : int or sequence of int
            Destination positions for each of the original axes. These must also be
            unique.

        Returns
        -------
        tensor
        """
    raise NotImplementedError


def get_user_meta_prefix(server_type):
    """
    Returns the prefix for user metadata headers for given server type.

    This prefix defines the namespace for headers that will be persisted
    by backend servers.

    :param server_type: type of backend server i.e. [account|container|object]
    :returns: prefix string for server type's user metadata headers
    """
    return 'x-%s-%s-' % (server_type.lower(), 'meta')


def get_attribute(obj, attr_name):
    """
    Retrieve the attribute of a specific object
    :param obj: object from which get the value
    :param attr_name: name of the attribute
    :return: value of the attribute
    """
    return getattr(obj, attr_name)


def get_logger(name):
    """Returns a general purpose logger instance."""


@classmethod
def mongod(cls, *args):
    """
        executes mongod with the given arguments
        :param args:
        :return:
        """
    return cls.execute('mongod', args)


def chr_set_null(chr_value):
    """sql util function"""
    return 'null' if chr_value is None or not chr_value else ''.join(("'",
        chr_value, "'"))


def _get_content_type(response):
    """Parse response and return content-type"""
    try:
        content_type = response.headers['Content-Type']
        content_type = content_type.split(';', 1)[0]
    except KeyError:
        content_type = None
    return content_type


def getFieldSamples(field_name):
    """Get an iterable of up to three sample values for a field.

        The values are unicode strings.
        Date values are represented as ISO-date resp. empty string.

        """


def note_hash(channel, pitch):
    """Generate a note hash."""
    return channel * 128 + pitch


@classmethod
def construct_from_name(cls, name, *args, **kwds):
    """Constructs a curve from a short name used in command line arguments
        across the whole ``yard`` package.

        `name` is matched against the ``identifier`` class-level properties of
        all the subclasses of `Curve` to find the subclass to be constructed.
        All the remaining arguments are passed on intact to the constructor of
        the subclass. Returns a new instance of the found subclass, or raises
        ``ValueError`` if an invalid name was given.
        """
    return cls.find_class_by_name(name)(*args, **kwds)


@staticmethod
def set_args(arg_list):
    """! @brief Set arguments to configure behavior"""
    raise NotImplementedError()


def straceback(color=None):
    """
    Returns a string with the traceback.

    Use ANSII color formatting for output in terminal if color is not None.
    """
    import traceback
    s = traceback.format_exc()
    if color is not None:
        try:
            from termcolor import colored
            return colored(s, color)
        except ImportError:
            return s
    else:
        return s


def read_dicom_dir_as_volume(dirname):
    """
    https://pyscience.wordpress.com/2014/10/19/image-segmentation-with-python-and-simpleitk/
    """
    import SimpleITK
    reader = SimpleITK.ImageSeriesReader()
    filenamesDICOM = reader.GetGDCMSeriesFileNames(dirname)
    reader.SetFileNames(filenamesDICOM)
    imgOriginal = reader.Execute()
    img = SimpleITK.GetArrayFromImage(imgOriginal).swapaxes(0, 2)
    return img


@staticmethod
def lineGenerator(key, value, colIds):
    """Generates a PSI line from a single event

        key -- id of the event.
        value -- the dictionary containning all column names and psi values calculated.
        colIds -- list containing the column names
        """
    line = []
    line.append(key)
    for x in colIds:
        line.append(str(value[x]))
    return line


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

        :param FileSaveCopyReferenceType val:
        :rtype: EventType
        """
    return cls('file_save_copy_reference', val)


def select_less():
    """Shrink the current selection of adjacent selected strips

    """
    pass


def doc_view_manual_ui_context():
    """View a context based online manual in a web browser

    """
    pass


@classmethod
def load(cls, path: str):
    """
        Load model state.

        :param path: state file path
        :return: state
        """
    import torch
    map_location = None
    if not torch.cuda.is_available():
        map_location = 'cpu'
    return torch.load(path, map_location=map_location)


def highest(f, c, p=20):
    """Calculate the highest value on a rolling basis.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe containing the column ``c``.
    c : str
        Name of the column in the dataframe ``f``.
    p : int
        The period over which to calculate the rolling maximum.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    """
    new_column = f[c].rolling(p).max()
    return new_column


def _set_django_attributes(span, request):
    """Set the django related attributes."""
    django_user = getattr(request, 'user', None)
    if django_user is None:
        return
    user_id = django_user.pk
    user_name = django_user.get_username()
    if user_id is not None:
        span.add_attribute('django.user.id', str(user_id))
    if user_name is not None:
        span.add_attribute('django.user.name', user_name)


def symmetrize():
    """Symmetrize the topology modifications

    """
    pass


def sizeof_fmt(num):
    """Takes the a filesize in bytes and returns a nicely formatted string. """
    for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
        if num < 1024.0:
            return '%3.1f %s' % (num, x)
        num /= 1024.0


def abc_psd(nu, a, b, c):
    """Lorentzian model of a Power Spectral Density.

    Parameters
    ----------
    nu : `numpy.ndarray` or `float`
        spatial frequency
    a : `float`
        a coefficient
    b : `float`
        b coefficient
    c : `float`
        c coefficient

    Returns
    -------
    `numpy.ndarray`
        value of PSD model

    """
    return a / (1 + (nu / b) ** 2) ** (c / 2)


def split_by_lines(tokens: list):
    """
    Splits given value token by lines: returns array where each entry is a token list
    for a single line
    """
    result = []
    line = []
    for t in tokens:
        if isinstance(t, str):
            lines = t.splitlines()
            line.append(lines.pop(0) if lines else '')
            while lines:
                result.append(line)
                line = [lines.pop(0) or '']
        else:
            line.append(t)
    if line:
        result.append(line)
    return result


def bearer_auth(request, authn):
    """
    Pick out the access token, either in HTTP_Authorization header or
    in request body.

    :param request: The request
    :param authn: The value of the Authorization header
    :return: An access token
    """
    try:
        return request['access_token']
    except KeyError:
        if not authn.startswith('Bearer '):
            raise ValueError('Not a bearer token')
        return authn[7:]


@classmethod
def fromkeys(cls, iterable, value=None):
    """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        """
    d = cls()
    for key in iterable:
        d[key] = value
    return d


def allDonors():
    """ get all the  donors"""


@staticmethod
def _caldav_filter_domain_calendar(filter):
    """
        Return a domain for caldav filter on calendar
        """
    if not filter:
        return []
    if filter.localName == 'principal-property-search':
        return [('id', '=', 0)]
    return [('id', '=', 0)]


def get_table_from_time_spents(time_spents, detail_level='month'):
    """
    Buid a time spent table based on given time spents and given level
    of detail (week, day or month).
    """
    result = {}
    for time_spent in time_spents:
        if detail_level is 'week':
            unit = str(time_spent.date.isocalendar()[1])
        elif detail_level is 'day':
            unit = str(time_spent.date.day)
        elif detail_level is 'year':
            unit = str(time_spent.date.year)
        else:
            unit = str(time_spent.date.month)
        person_id = str(time_spent.person_id)
        if unit not in result:
            result[unit] = {}
        if person_id not in result[unit]:
            result[unit][person_id] = 0
        result[unit][person_id] += time_spent.duration
    return result


def insort_left(a, x, lo=0, hi=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.

    If x is already in a, insert it to the left of the leftmost x.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if a[mid] < x:
            lo = mid + 1
        else:
            hi = mid
    a.insert(lo, x)


def volmesh_vertex_lift(volmesh, vkey, target_xyz, hfkeys):
    """Duplicates and lifts a vertex, then creates cells using the vertex halffaces and the duplicated vertex.

    Parameters
    ----------
    volmesh : VolMesh
        A volmesh object representing a polyhedral force diagram.
    vkey : int
        The key of the vertex to lift.
    hfkeys : list
        List of halfface keys to create new cells from.
    xyz : tuple
        Target xyz coordinates of the lifted vertex.

    Notes
    -----
    The lifting vertex must be on the boundary of the volmesh.

    See Also
    --------
    * :func:`compas_3gs.operations.face_pinch`

    """
    if not volmesh.is_vertex_on_boundary(vkey):
        raise Exception('This vertex is interior.')
    x, y, z = target_xyz
    w = volmesh.add_vertex(x=x, y=y, z=z)
    for hfkey in hfkeys:
        halffaces = [volmesh.halfface_vertices(hfkey)[::-1]]
        for u, v in volmesh.halfface_halfedges(hfkey):
            halffaces.append([u, v, w])
        volmesh.add_cell(halffaces)
    return volmesh


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 get_htl(A):
    """ Return the half-top-left of the given array.
    """
    nx, _ = A.shape
    li = int(nx / 2)
    return A[:li, :li]


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

        :param FileEditCommentDetails val:
        :rtype: EventDetails
        """
    return cls('file_edit_comment_details', val)


def allowed(repo, remote_user, config_group, config_item):
    """Read from repo config list to check if given user is allowed.

    within Heptapod, ``remote_user`` being ``None`` means that `hg` is invoked
    from the command line, or directly by a server-side process, such as
    the Rails application performing a merge.

    In these cases, the permission
    checking responsibility is on the caller. Hence a ``None`` remote user
    is always allowed.
    """
    allowed = repo.ui.configlist(config_group, config_item)
    if remote_user is None or '*' in allowed or remote_user in allowed:
        repo.ui.debug('user %r is allowed by %s.%s=%r' % (remote_user,
            config_group, config_item, allowed))
        return True
    return False


def p_statement_assignment(p):
    """statement : assignment SEMICOLON"""
    p[0] = p[1]


def add_attachments_to_set(attachmentSetId=None, attachments=None):
    """
    Adds one or more attachments to an attachment set. If an attachmentSetId is not specified, a new attachment set is created, and the ID of the set is returned in the response. If an attachmentSetId is specified, the attachments are added to the specified set, if it exists.
    An attachment set is a temporary container for attachments that are to be added to a case or case communication. The set is available for one hour after it is created; the expiryTime returned in the response indicates when the set expires. The maximum number of attachments in a set is 3, and the maximum size of any attachment in the set is 5 MB.
    See also: AWS API Documentation

    :example: response = client.add_attachments_to_set(
        attachmentSetId='string',
        attachments=[
            {
                'fileName': 'string',
                'data': b'bytes'
            },
        ]
    )

    :type attachmentSetId: string
    :param attachmentSetId: The ID of the attachment set. If an attachmentSetId is not specified, a new attachment set is created, and the ID of the set is returned in the response. If an attachmentSetId is specified, the attachments are added to the specified set, if it exists.

    :type attachments: list
    :param attachments: [REQUIRED]
            One or more attachments to add to the set. The limit is 3 attachments per set, and the size limit is 5 MB per attachment.
            (dict) --An attachment to a case communication. The attachment consists of the file name and the content of the file.
            fileName (string) --The name of the attachment file.
            data (bytes) --The content of the attachment file.

    :rtype: dict
    :return: {
        'attachmentSetId': 'string',
        'expiryTime': 'string'
    }

    """
    pass


@classmethod
def _from_dict(cls, _dict):
    """Initialize a Feed object from a json dictionary."""
    args = {}
    if 'link' in _dict:
        args['link'] = _dict.get('link')
    return cls(**args)


def init(_definitionfile):
    """Loads the definition file and extracts settings"""
    pass


@classmethod
def define(cls, colnames, constraint_names=[], comment=None, annotations={}):
    """Build a key definition."""
    if not isinstance(colnames, list):
        raise TypeError('Colnames should be a list.')
    return {'unique_columns': list(colnames), 'names': constraint_names,
        'comment': comment, 'annotations': annotations}


def map_value_or(f, value, default):
    """Return Value or Default if Value is None."""
    return f(value) if value is not None else default


@staticmethod
def p_daq_list_optional(p):
    """daq_list_optional : daq_list_type
                             | max_odt
                             | max_odt_entries
                             | first_pid
                             | event_fixed
                             | predefined"""
    p[0] = p.slice[1].type, p[1]


def screen_full_area(use_hide_panels: bool=False):
    """Toggle display selected area as fullscreen/maximized

    :param use_hide_panels: Hide Panels, Hide all the panels
    :type use_hide_panels: bool
    """
    pass


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


def parse_git_url(git_url):
    """Parse the git url.

    Args:
        git_url (str): url of a git repository (https or ssh)

    Returns:
        (str, str, str): tupple of domain, user and project name parsed from url
    """
    import re
    regex = re.compile(
        '(?:git@|https:\\/\\/)([\\w\\-_\\.]+)[:\\/]([\\w\\-_\\.\\/]+)[\\/]([\\w\\-_]+)(?:.git)*$'
        )
    domain, user, project = regex.search(git_url).groups()
    return domain, user, project


def _trace_D(gj, p_i, Dxtrav):
    """
    Return the representative h satisfying h[gj] == p_i

    If there is not such a representative return None

    """
    for h in Dxtrav:
        if h[gj] == p_i:
            return h


def _dense_match(table, metadata):
    """ Match on dense pandas tables"""
    subtableids = set(table.index)
    submetadataids = set(metadata.index)
    if len(subtableids) != len(table.index):
        raise ValueError('`table` has duplicate sample ids.')
    if len(submetadataids) != len(metadata.index):
        raise ValueError('`metadata` has duplicate sample ids.')
    idx = subtableids & submetadataids
    if len(idx) == 0:
        raise ValueError(
            'No more samples left.  Check to make sure that the sample names between `metadata` and `table` are consistent'
            )
    subtable = table.loc[idx]
    submetadata = metadata.loc[idx]
    return subtable, submetadata


@staticmethod
def p_char_string(p):
    """char_string : STRING"""
    p[0] = p[1]


def make_empty_table(row_count, column_count):
    """
    Make an empty table

    Parameters
    ----------
    row_count : int
        The number of rows in the new table
    column_count : int
        The number of columns in the new table

    Returns
    -------
    table : list of lists of str
        Each cell will be an empty str ('')
    """
    table = []
    while row_count > 0:
        row = []
        for column in range(column_count):
            row.append('')
        table.append(row)
        row_count -= 1
    return table


def is_clusterer(estimator):
    """
    Returns True if the given estimator is a clusterer.

    Parameters
    ----------
    estimator : class or instance
        The object to test if it is a Scikit-Learn clusterer, especially a
        Scikit-Learn estimator or Yellowbrick visualizer
    """
    return getattr(estimator, '_estimator_type', None) == 'clusterer'


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


def get_image_media_type(img_ext):
    """Return media type for image based on extension.
  """
    if '.' in img_ext:
        img_ext = img_ext.split('.')[-1]
    img_ext = img_ext.lower()
    assert img_ext in ['bmp', 'tiff', 'tif', 'png', 'jpg', 'jpeg'
        ], 'image format must be one of png, jpg, jpeg, tif, tiff, bmp.'
    if img_ext in ['jpg', 'jpeg']:
        return 'image/jpeg'
    if img_ext == 'png':
        return 'image/png'
    if img_ext in ['bmp']:
        return 'image/bmp'
    if img_ext in ['tif', 'tiff']:
        return 'image/tiff'


def numeric_ranges(s):
    """
    Parse numeric ranges separated by comma.

    A numeric range can either be a single number, or a range separated by a
    dash.

    Overlaps are ignored since we are storing the result in a set.

    Example: 1,2,10-15,22 -> set([1,2,10,11,12,13,14,15,22])
    """
    numbers = set()
    parts = s.split(',')
    for p in parts:
        if '-' in p:
            left, right = p.split('-')
            numbers.update(range(int(left), int(right) + 1))
        else:
            numbers.add(int(p))
    return numbers


def CheckFormatString(pattern, *arguments):
    """
    Checks if the given format string (for instance, "%.g") is valid for the given arguments.
    :param pattern: a string in "%" format
    :param arguments: the arguments to check against
    :raises ValueError:
        if the format is invalid.
    """
    try:
        pattern % arguments
    except (TypeError, ValueError):
        raise ValueError('%r is not a valid format string.' % pattern)


def _excerpt_step(n_samples, n_excerpts=None, excerpt_size=None):
    """Compute the step of an excerpt set as a function of the number
    of excerpts or their sizes."""
    assert n_excerpts >= 2
    step = max((n_samples - excerpt_size) // (n_excerpts - 1), excerpt_size)
    return step


def decode_long(data):
    """Decode a long from a two's complement little-endian binary string.

    >>> decode_long(b'')
    0
    >>> decode_long(b"\\xff\\x00")
    255
    >>> decode_long(b"\\xff\\x7f")
    32767
    >>> decode_long(b"\\x00\\xff")
    -256
    >>> decode_long(b"\\x00\\x80")
    -32768
    >>> decode_long(b"\\x80")
    -128
    >>> decode_long(b"\\x7f")
    127
    """
    return int.from_bytes(data, byteorder='little', signed=True)


def identityfunc(arg, *args, **kwargs):
    """Single argument identity function.

    >>> identityfunc('arg')
    'arg'

    """
    return arg


def mutually_exclusive():
    """
    returns functional markers that the FM team came up with and we determined to be mostly mutually exclusive
    """
    MUTUALLY_EXCLUSIVE = ['agriculture, fishing, and forestry',
        'real estate', 'real estate construction',
        'real estate components and materials', 'real estate lessor',
        'public services', 'mining', 'extraction', 'media', 'tv and movies',
        'music', 'manufacturing', 'finished goods manufacturing',
        'components manufacturing', 'material manufacturing',
        'transportation', 'electricity', 'telecommunications', 'pipelines',
        'water and sewage systems', 'utility equipment and services',
        'gas utilities', 'healthcare', 'pharmaceuticals and biotech',
        'food processing and manufacturing', 'energy',
        'finance and banking', 'airplanes', 'trains', 'boats',
        'transportation of people', 'transportation of goods',
        'food services', 'entertainment establishments', 'tourism',
        'technology', 'hardware', 'software', 'retail',
        'wholesale and distribution', 'consumer services', 'business services']
    return MUTUALLY_EXCLUSIVE


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 to_tuple(d):
    """
	Expects dict with single key, returns tuple.
	>>> to_tuple({'a': 1})
	('a', 1)
	"""
    return next(iter(d.items()))


def runCrons():
    """run all active crons"""


def save(memory, filelike):
    """output binary to given file object"""
    for segment in sorted(memory.segments):
        filelike.write(bytes(segment.data))


def gpencil_brush_preset_add(name: str='', remove_name: bool=False,
    remove_active: bool=False):
    """Add or remove grease pencil brush preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_name: remove_name
    :type remove_name: bool
    :param remove_active: remove_active
    :type remove_active: bool
    """
    pass


def fill_headers(tree, table):
    """
    tree -- header_tree returned from set_headers
    table -- built Table
    return -- col_leaves
    """
    leaves = []
    depth = 0
    current_sweep = tree.children
    while current_sweep:
        cols_to_left = 0
        next_sweep = []
        for node in current_sweep:
            end_col = cols_to_left + node.descendants
            if depth < tree.depth - 1 - node.depth:
                next_sweep.append(node)
                cols_to_left = end_col
            else:
                txt = node.name
                table.set_header_cell(depth, cols_to_left, end_col, txt)
                cols_to_left = end_col
                for child in node.children:
                    next_sweep.append(child)
                if not node.children:
                    leaves.append(node)
        depth += 1
        current_sweep = next_sweep
    return leaves


def is_dunder(name):
    """Returns True if a __dunder__ name, False otherwise."""
    return name[:2] == name[-2:] == '__' and name[2:3] != '_' and name[-3:-2
        ] != '_' and len(name) > 4


def last_blank(src):
    """Determine if the input source ends in a blank.

    A blank is either a newline or a line consisting of whitespace.

    Parameters
    ----------
    src : string
      A single or multiline string.
    """
    if not src:
        return False
    ll = src.splitlines()[-1]
    return ll == '' or ll.isspace()


@staticmethod
def frange(start, stop, step, digits_to_round=3):
    """
        Works like range for doubles

        :param start: starting value
        :param stop: ending value
        :param step: the increment_value
        :param digits_to_round: the digits to which to round         (makes floating-point numbers much easier to work with)
        :return: generator
        """
    while start < stop:
        yield round(start, digits_to_round)
        start += step


def setAttributes(segments, attributes):
    """
        Set `attributes` for segment.

        `attributes` is a dictionary of:
         * size -> s.st_size
         * uid -> s.st_uid
         * gid -> s.st_gid
         * mode -> s.st_mode
         * atime -> int(s.st_atime)
         * mtime -> int(s.st_mtime)
        """


def copy_driver_button():
    """Copy the driver for the highlighted button

    """
    pass


def divider(name=None, start='# ', end=' #', char='-', len=60):
    """
    Creates a formatted section with given length padded with given chars

    Parameters
    ----------
    name : str or None
        name of the section
    start : str
    end : str
    char: str
    len: int

    Returns
    -------
    str
        formatted string

    """
    fmt = '%s{:%s^%ds}%s' % (start, char, len, end)
    if name:
        return fmt.format(' %s ' % name)
    return fmt.format('')


def neg_even(data):
    """
    Negate even points
    """
    data[(...), ::2] = -data[(...), ::2]
    return data


@classmethod
def read_from_file(cls, filename):
    """Reads a string file and returns a :class:`DrillString` object with `DrillString.parameters` based on data in the string file.

        Parameters
        ----------
        filename : str
            Filename of a string file.

        Returns
        -------
        DrillString
            :class:`DrillString` object with parameters from the passed string file.
        """
    drill_string = cls('', '', '')
    drill_string._get_params_from_TO_data(filename)
    drill_string._get_tools_from_TO_data(filename)
    return drill_string


def dummy_hash(x):
    """
    Supplies a constant dummy hash
    """
    return 'dummy_hash'.encode('utf-8')


def write_xgmml(G, filename, name='THAPBI PICT edit-graph'):
    """Save graph in XGMML format suitable for Cytoscape import."""
    with open(filename, 'w') as handle:
        handle.write(
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
        handle.write(
            """<graph directed="0"  xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.cs.rpi.edu/XGMML">
"""
            )
        for n in G:
            node = G.nodes[n]
            try:
                label = node['label'].replace('\n', ';')
            except KeyError:
                label = None
            if not label:
                label = '{%s}' % n[:6]
            handle.write(f'  <node id="{n}" label="{label}">\n')
            color = node['color']
            size = node['size'] * 0.45 + 5.0
            handle.write(
                """    <graphics type="CIRCLE" fill="%s" outline="#000000" h="%0.2f" w="%0.2f"/>
"""
                 % (color, size, size))
            handle.write(f'    <att type="string" name="MD5" value="{n}"/>\n')
            handle.write(
                '    <att type="integer" name="Total-abundance" value="%i"/>\n'
                 % node.get('total_abundance', 0))
            handle.write(
                '    <att type="integer" name="Max-sample-abundance" value="%i"/>\n'
                 % node.get('max_sample_abundance', 0))
            handle.write(
                '    <att type="integer" name="Sample-count" value="%i"/>\n' %
                node.get('sample_count', 0))
            if node['genus']:
                handle.write(
                    '    <att type="string" name="Genus" value="%s"/>\n' %
                    node['genus'])
            if node['taxonomy']:
                handle.write(
                    '    <att type="string" name="Taxonomy" value="%s"/>\n' %
                    node['taxonomy'])
            handle.write('  </node>\n')
        for n1, n2 in G.edges():
            edge = G.edges[n1, n2]
            handle.write(
                '  <edge source="%s" target="%s" weight="%0.2f">\n' % (n1,
                n2, edge['weight']))
            handle.write('    <graphics fill="%s" width="%0.1f"/>\n' % (
                edge['color'], edge['width']))
            if 'edit_dist' in edge:
                handle.write(
                    '    <att type="integer" name="Edit-distance" value="%i"/>\n'
                     % edge['edit_dist'])
            handle.write(
                '    <att type="integer" name="Edit-distance-weight" value="%i"/>\n'
                 % edge['weight'])
            handle.write('  </edge>\n')
        handle.write('</graph>\n')


def p_q_STRING(p):
    """q_STRING : "'" STRING "'" """
    p[0] = p[2]


def service_name_dne(service):
    """
    This error occurs when a service name is missing. Ex. There is no "datasys" entry in the list of biids in CA.
    :param service:
    :return:
    """
    return 'CA entry does not include {} id'.format(service)


def notifications_enabled(conf):
    """Check if oslo notifications are enabled."""
    notifications_driver = set(conf.oslo_messaging_notifications.driver)
    return notifications_driver and notifications_driver != {'noop'}


def _all_equal(seq, elem):
    """Raise an error if not all elements of a list are equal"""
    if not seq.count(seq[0]) == len(seq):
        raise ValueError(f'All {elem} must be the same, found: {set(seq)}')


def adapt_name_for_rest(name):
    """
    Modifies a user-provided name for use in API calls.
    Basically we want an alias like 'MDB:OPS Name/SIMULATOR_BatteryVoltage2'
    to be prepended with a slash.
    """
    if name.startswith('/'):
        return name
    elif '/' not in name:
        raise ValueError('Provided name is not a fully-qualified XTCE name.')
    return '/' + name


def grid_indices_gen(nx, ny):
    """A generator for grid vertex indices.
    """
    for x in range(nx - 1):
        for y in range(ny - 1):
            root = x + y * ny
            yield root, root + 1, root + nx
            yield root + nx, root + 1, root + nx + 1


@staticmethod
def make_full_name(login, reponame):
    """Create full name from owner login name and repository name

        :param login: Owner login
        :type login: str
        :param reponame: Name of repository (without owner login)
        :type reponame: str
        :return: Full name of repository
        :rtype: str
        """
    return '{}/{}'.format(login, reponame)


def load_np_dtype(arr):
    """ Load a numpy array """
    return arr.value


@staticmethod
def endDiagram(*args):
    """ Called last uring the render to finalise a diagram """
    pass


def Odds(p):
    """Computes odds for a given probability.

    Example: p=0.75 means 75 for and 25 against, or 3:1 odds in favor.

    Note: when p=1, the formula for odds divides by zero, which is
    normally undefined.  But I think it is reasonable to define Odds(1)
    to be infinity, so that's what this function does.

    p: float 0-1

    Returns: float odds
    """
    if p == 1:
        return float('inf')
    return p / (1 - p)


def attach_http_accept_default(event):
    """Accept: application/json"""
    env = event.request.environ
    accept = env.get('HTTP_ACCEPT')
    if accept is None or '*/*':
        env['HTTP_ACCEPT'] = 'application/json'


@classmethod
def add_operating_system(cls, options=None):
    """
        Adds OS to record.
        """
    cls.command_sub = 'add-operatingsystem'
    result = cls.execute(cls._construct_command(options))
    return result


def to_datetime_string(value):
    """
    gets the datetime string representation of input value with utc offset.

    for example: `2015-12-24T23:40:15+03:30`

    :param datetime value: input object to be converted.

    :rtype: str
    """
    return value.isoformat(timespec='seconds')


def send_to_spooler(message=None, **kwargs):
    """Send data to the The uWSGI Spooler. Also known as spool().

    .. warning:: Either `message` argument should contain a dictionary
        this message dictionary will be constructed from `kwargs`.

    :param dict[bytes, bytes] message: The message to spool. Keys and values are bytes.
    :param dict kwargs:

        Possible kwargs (these are also reserved `message` argument dictionary keys):

            * spooler: The spooler (id or directory) to use.
                Specify the ABSOLUTE path of the spooler that has to manage this task

            * priority: Number. The priority of the message. Larger - less important.

                .. warning:: This works only if you enable `order_tasks` option in `spooler.set_basic_params()`.

                This will be the subdirectory in the spooler directory in which the task will be placed,
                you can use that trick to give a good-enough prioritization to tasks.

                .. note:: This is for systems with few resources. For better approach use multiple spoolers.

            * at: Unix time at which the task must be executed.
                The task will not be run until the 'at' time is passed.

            * body: A binary body to add to the message,
                in addition to the message dictionary itself.
                Use this key for objects bigger than 64k, the blob will be appended
                to the serialized uwsgi packet and passed back t
                o the spooler function as the 'body' argument.

    :rtype: str|None
    """


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

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
               "message_analyzed": {
                    "type": "text",
                    "index": true
               }
           }
        }"""
    return {'items': mapping}


def _get_side_from_team(team):
    """Map integer reference to string"""
    return {(0): 'radiant', (1): 'dire', (2): 'broadcaster', (4): 'unassigned'
        }.get(team, 'unassigned')


def _is_parent_of(parent, child):
    """Check whether the first device is the parent of the second device."""
    if child.is_partition:
        return child.partition_slave == parent
    if child.is_toplevel:
        return child.drive == parent and child != parent
    return False


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

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


def get_r1_0(pdw_file, t1w_file, max_r1_0, mask=None):
    """
    Returns the R1_0 map NIfTI file from the given proton density
    and T1-weighted images. The R1_0 map is computed using the
    ``pdw_t1w_to_r1`` function. The ``pdw_t1w_to_r1`` module
    must be in the Python path.

    :param pdw_file: the proton density NIfTI image file path
    :param t1w_file: the T1-weighted image file path
    :param max_r1_0: the R1_0 range maximum
    :param mask: the optional mask image file path to use
    :return: the R1_0 map NIfTI image file path
    """
    import os
    import nibabel as nb
    import numpy as np
    from pdw_t1w_to_r1 import pdw_t1w_to_r1
    from dcmstack.dcmmeta import NiftiWrapper
    pdw_nii = nb.load(pdw_file)
    pdw_nw = NiftiWrapper(pdw_nii, make_empty=True)
    t1w_nw = NiftiWrapper(nb.load(t1w_file), make_empty=True)
    r1_space = np.arange(0.01, max_r1_0, 0.01)
    pdw_opts = {}
    if mask:
        pdw_opts['mask'] = nb.load(mask).get_data()
    r1_0_arr = pdw_t1w_to_r1(pdw_nw, t1w_nw, r1_space=r1_space, **pdw_opts)
    cwd = os.getcwd()
    r1_0_nii = nb.Nifti1Image(r1_0_arr, pdw_nii.affine)
    out_file = os.path.join(cwd, 'r1_0_map.nii.gz')
    nb.save(r1_0_nii, out_file)
    return out_file


def context(target_dict, specific_context, inc_target=False):
    """
    Returns a list of Strings based on the location of the target word in the
    text within the target dict (NOTE the target word can occur more than once
    hence why a list is returned as the context is returned for each occurence).
    specific_context can be one of the following:

    1. left - left of the target occurence.
    2. right - right of the target occurence.
    3. target - target word/words of each target occurence.
    4. full - whole text repeated for each occurence.

    The list will be length 1 if the target word only occurs once in the text.

    :param target_dict: Dictionary that contains text and the spans of the     target word in the text.
    :param specific_context: String specifying either the context e.g. left.
    :param inc_target: Whether to include the target word in the context text.     (Only applies for left and right context.)
    :type target_dict: dict
    :type specific_context: String
    :type inc_target: Boolean Default False
    :returns: A list of context strings
    :rtype: list
    """
    acceptable_contexts = {'left', 'right', 'target', 'full'}
    if specific_context not in acceptable_contexts:
        raise ValueError(
            'context parameter can only be one of the following {} not {}'.
            format(acceptable_contexts, specific_context))
    text = target_dict['text']
    spans = target_dict['spans']
    contexts = []
    for span in spans:
        start_char = span[0]
        end_char = span[1]
        if specific_context == 'left':
            if inc_target:
                contexts.append(text[:end_char])
            else:
                contexts.append(text[:start_char])
        elif specific_context == 'right':
            if inc_target:
                contexts.append(text[start_char:])
            else:
                contexts.append(text[end_char:])
        elif specific_context == 'target':
            contexts.append(text[start_char:end_char])
        elif specific_context == 'full':
            contexts.append(text)
        else:
            raise ValueError(
                'context parameter should only be `right` or `left` not {} there must be a logic error'
                .format(specific_context))
    return contexts


def average(old_avg, current_value, count):
    """
    Calculate the average. Count must start with 0

    >>> average(None, 3.23, 0)
    3.23
    >>> average(0, 1, 0)
    1.0
    >>> average(2.5, 5, 4)
    3.0
    """
    if old_avg is None:
        return current_value
    return (float(old_avg) * count + current_value) / (count + 1)


def get(isamAppliance, check_mode=False, force=False):
    """
    Retrieve current version.
    """
    return isamAppliance.invoke_get('Retrieving version', '/core/sys/versions')


def updated_with(orig_dict, *new_values):
    """Return a copy of orig_dict updated with new_values.

    New keys are added, and the values of existing keys will take the
    values in new_values.

    You can specify more than one update dictionary.
    They are applied in order, so the values of any keys in later dictionaries
    will overwrite the earlier ones.
    If any evaluate to falselike (i.e. are None, False or empty)
    then they are skipped.

    >>> updated_with({1: 2, 2: 4, 3: 2}, {1: 'two', 4: 'four'})
    {1: 'two', 2: 4, 3: 2, 4: 'four'}
    >>> updated_with({1: 2}, None, {1: 'two', 2: 4}, None, {2: 'four'}, None)
    {1: 'two', 2: 'four'}

    Example patterns:
       def something(self, overrides=None):
           return updated_with({'some': 'defaults'},
                self.one_dict,
                self.another_dict,
                overrides,
           )
    """
    newdict = dict(orig_dict)
    for vals in new_values:
        if vals:
            newdict.update(vals)
    return newdict


def find_members(search_string, location=None):
    """Return all members object corresponding to users which
        theirs fullname contains ``search_string``. Search is done at
        the given ``location`` if provided.

        :raises: :py:exc:`~silva.core.services.interfaces.MemberLookupError`
        :return: a list of :py:class:`~silva.core.interfaces.auth.IMember`
                 objects.
        """


def get_plate_data(plate):
    """
    returns the pole list for a given plate

    Parameters
    ----------
    plate : string (options: AF, ANT, AU, EU, GL, IN, NA, SA)

    Returns
    ---------
    apwp : string with format
        0.0        90.00    0.00
        1.0        88.38  182.20
        2.0        86.76  182.20
        ...

    """
    from . import poles
    apwp = poles.get_apwp(plate)
    return apwp


@classmethod
def _AddElement(cls, element):
    """Method used by generated code to associate the element binding with a use in this type.

        This is necessary because all complex type classes appear in the
        module prior to any of the element instances (which reference type
        classes), so the association must be formed after the element
        instances are available."""
    return cls._UseForTag(element.name())._setElementBinding(element)


def assert_list_data(value: list) ->None:
    """Asserts value is list type."""
    assert isinstance(value, list
        ), f'Input value type must be a list. Actual type: {type(value)}, value: {value}'


def get_logg_from_atm_table_filename(filename):
    """
    Get logg from filename / directory name.

    :param filename: str;
    :return: float;
    """
    filename = filename if not str(filename).endswith('.csv') else str(filename
        ).replace('.csv', '')
    g = str(filename).split('_')[2][1:]
    return int(g) / 10.0


def safeget(dct, *keys):
    """ Recursive function to safely access nested dicts or return None.
    param dict dct: dictionary to process
    param string keys: one or more keys"""
    for key in keys:
        try:
            dct = dct[key]
        except KeyError:
            return None
    return dct


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

        :param MemberRemoveExternalIdDetails val:
        :rtype: EventDetails
        """
    return cls('member_remove_external_id_details', val)


def select_nth(skip: int=1, nth: int=1, offset: int=0):
    """Deselect every Nth element starting from the active vertex, edge or face

    :param skip: Deselected, Number of deselected elements in the repetitive sequence
    :type skip: int
    :param nth: Selected, Number of selected elements in the repetitive sequence
    :type nth: int
    :param offset: Offset, Offset from the starting point
    :type offset: int
    """
    pass


def filter_blacklist(insertions, genes, field='gene_name'):
    """Filters insertions for blacklisted genes.

    Parameters
    ----------
    insertions : List[Insertion]
        Insertions to filter.
    genes : set[str]
        Symbols of the blacklisted genes.

    Yields
    ------
    Insertion
        Next filtered insertion.

    """
    for ins in insertions:
        if ins.metadata[field] not in genes:
            yield ins


def _check_for_unknown_fields(cls, data):
    """
    Checks for keys in a dictionary that don't exist as fields on a model.

    :param cls:
        The ``Model`` class to validate ``data`` against.

    :param data:
        A dict with keys to validate.

    :returns:
        Errors of the fields that were not present in ``cls``.
    """
    errors = {}
    fields = set(getattr(cls, '_initial', {})) | set(data)
    rogues_found = fields - set(cls._fields)
    if rogues_found:
        for field_name in rogues_found:
            errors[field_name] = [u'%s is an illegal field.' % field_name]
    return errors


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

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


def bin2hex(binstr):
    """Convert a binary string to hexdecimal string."""
    return '{0:X}'.format(int(binstr, 2))


def listObjectActions(info):
    """ Return a sequence of workflow action objects.

        o 'info' is an OAI (ObjectActionInformation ?) structure.

        o Returned actions are relevant to 'info.content' (this method is
          called only when this workflow is applicable to 'info.content').

        o Invoked by the portal_workflow tool.

        o Permission:  Private (Python only)
        """


@classmethod
def make_symmetric(cls, mat):
    """
        Make a matrix symmetric, by averaging with its transpose.

        Parameters
        ----------
        mat : array-like, shape=[n_samples, n, n]

        Returns
        -------
        sym : array-like, shape=[n_samples, n, n]
        """
    return 1 / 2 * (mat + cls.transpose(mat))


def setup_body_points(on_container, points):
    """
    Setup points for Star instance and spots based on input `points` Dict object.
    Such `points` map looks like following

    :param on_container: Union; instance to setup spot points and body points on
    :param points: Dict[str, numpy.array];

    ::

        {
            "object": [[point0_x, point0_y, point0_z], ..., [pointN_x, pointN_y, pointN_z]],
            "0": [<points>],
            "1": [<points>]...
        },

    where `object` contain numpy.array of object points and indices points for given spot.
    """
    on_container.points = points.pop('object')
    for spot_index, spot_points in points.items():
        on_container.spots[int(spot_index)].points = points[spot_index]


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

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
                "text_analyzed": {
                  "type": "text",
                  "fielddata": true,
                  "index": true
                }
           }
        } """
    return {'items': mapping}


def query(**kw):
    """
        return the specified children of the container
        """


def assign_role_to_principal(role_id, principal_id):
    """Assign the role to the principal."""


def create_python_dtype_dataset(py_obj, h_group, call_id=0, **kwargs):
    """ dumps a python dtype object to h5py file

    Args:
        py_obj: python object to dump; should be a python type (int, float, bool etc)
        h_group (h5.File.group): group to dump data into.
        call_id (int): index to identify object's relative location in the iterable.
    """
    d = h_group.create_dataset('data_%i' % call_id, data=py_obj, dtype=type
        (py_obj))
    d.attrs['type'] = [b'python_dtype']
    d.attrs['python_subdtype'] = bytes(str(type(py_obj)), 'ascii')


def _load_model(name):
    """Load a model class from the SDK in order to inspect for
    parameter names and whether they're required.
    :param str name: The model class name to load.
    :returns: Model class
    """
    if name.startswith('azure.'):
        namespace = name.split('.')
    else:
        namespace = ['azure', 'batch', 'models', name]
    model = __import__(namespace[0])
    for level in namespace[1:]:
        model = getattr(model, level)
    return model


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


def _split_on_first_equal(line, val='='):
    """Split a line based on first occurrence of " ="

    Parameters
    ----------
    line: str
        string to split
    split: str
        split based on this. Can be multiple characters.
    >>> _split_on_first_equal("this = abc = 1")
    ('this', 'abc = 1')
    """
    l = line.split(' {} '.format(val))
    if l[0].endswith(' {}'.format(val)):
        l[0] = l[0].replace(' {}'.format(val), '')
    return l[0], ' {} '.format(val).join(l[1:])


def star_output_mode(cluster, logdir, cmdline, *args):
    """Select output mode: [stream|ordered|off]"""
    modes = 'stream', 'ordered', 'off'
    if args[0] not in modes:
        raise ValueError('Output mode must be one of: %s' % repr(modes))
    cluster.output_mode = args[0]
    print('Output mode set to %s' % cluster.output_mode)


def is_grandcanonical(trajectory, tests=1):
    """
    Simple test to check if a trajectory is grandcanonical.
    i.e. if the number of particles fluctuates.

    We compare the first frame to an integer number `tests` of other
    frames starting from the end of `trajectory`.
    """
    is_variable = False
    if tests > 0:
        skip = max(1, int(len(trajectory) / float(tests)))
    else:
        skip = 1
    N0 = len(trajectory[0].particle)
    for sample in range(len(trajectory) - 1, 0, -skip):
        N1 = len(trajectory[sample].particle)
        is_variable = False
        if N0 != N1:
            is_variable = True
            break
    return is_variable


def find_cluster(dd, clusters):
    """Find the correct cluster. The first and the last one are not numeric"""
    for clst in clusters[4:-1]:
        if dd <= int(clst):
            return clst
    return clusters[-1]


def setPrefixLimit(limit):
    """
    Set the limit on the prefix length for all Banana connections
    established after this call.

    The prefix length limit determines how many bytes of prefix a banana
    decoder will allow before rejecting a potential object as too large.

    @type limit: L{int}
    @param limit: The number of bytes of prefix for banana to allow when
    decoding.
    """
    global _PREFIX_LIMIT
    _PREFIX_LIMIT = limit


def metadata_listdir(name):
    """List of metadata names in the directory (like ``os.listdir()``)"""


def apply_format(data_frame, column_names, format_method):
    """Apply a formatting function to a DataFrame column and return.

    Simplify applying format modifications to the data stored in columns
    of `data_frame`. Check if the parameters are of the right type, apply
    `format_method` to the columns of `data_frame` whose labels are passed
    in `column names`. Return the DataFrame with the applied changes.

    Parameters
    ----------
    data_frame : pandas.DataFrame
        DataFrame containing the data to be modified.
    column_names : list
        List of string labels of columns in `data_frame` to be modified.
    format_method : function
        Function to be applied to the columns of `data_frame`, whose labels
        are listed in `column_names`.

    Returns
    -------
    data_frame : pandas.DataFrame
        The passed in DataFrame with the formatting changes applied to
        its columns.

    See Also
    --------
    pandas.apply

    Examples
    --------
    >>> data = pd.read_csv("data.csv")
    >>> print(data[['Wage']][0:3]) #print first few lines
        Wage
    0  €565K
    1  €405K
    2  €290K
    >>> data = apply_format(data, ['Wage'], money_format)
    >>> print(data[['Wage']][0:3])
       Wage
    0   565
    1   405
    2   290
    """
    for column in column_names:
        if isinstance(column, str) and column in data_frame and callable(
            format_method):
            data_frame.loc[:, (column)] = data_frame[column].apply(
                format_method)
    return data_frame


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in list(other.keys()):
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in list(kwds.items()):
        self[key] = value


def user_key(scancode):
    """Return a key symbol for a key not supported by pyglet.

    This can be used to map virtual keys or scancodes from unsupported
    keyboard layouts into a machine-specific symbol.  The symbol will
    be meaningless on any other machine, or under a different keyboard layout.

    Applications should use user-keys only when user explicitly binds them
    (for example, mapping keys to actions in a game options screen).
    """
    assert scancode > 0
    return scancode << 32


def does_weak_dominate(g1, g2, delta1, delta2):
    """
    Returns true if 'g1' weakly dominates 'g2' with the given relaxation

    Parameters
    ----------
    g1 : tuple of float
        Objective values of a point
    g2 : tuple of float
        Objective values of a point
    delta1 : tuple of float
        Relaxation of 'g1'
    delta2 : tuple of float
        Relaxation of 'g2'

    Returns
    -------
    is_dom : bool
    """
    dim = len(g1)
    is_dom = True
    i = 0
    while i < dim and is_dom:
        if g2[i] + delta2[i] < g1[i] - delta1[i]:
            is_dom = False
        i = i + 1
    return is_dom


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

        :param GroupDeleteType val:
        :rtype: EventType
        """
    return cls('group_delete', val)


def calculate_model_ages():
    """Calculates the estimated age

    Calculate the estimated age which would be measured from the model
    fission track population.  Each time interval added in, and
    corrected by the amount of density reduction expected given the
    length reduction.
    """


def flip_normals():
    """Flip the direction of selected faces’ normals (and of their vertices)

    """
    pass


def lookup_developer_identity(IdentityPoolId=None, IdentityId=None,
    DeveloperUserIdentifier=None, MaxResults=None, NextToken=None):
    """
    Retrieves the IdentityID associated with a DeveloperUserIdentifier or the list of DeveloperUserIdentifier s associated with an IdentityId for an existing identity. Either IdentityID or DeveloperUserIdentifier must not be null. If you supply only one of these values, the other value will be searched in the database and returned as a part of the response. If you supply both, DeveloperUserIdentifier will be matched against IdentityID . If the values are verified against the database, the response returns both values and is the same as the request. Otherwise a ResourceConflictException is thrown.
    You must use AWS Developer credentials to call this API.
    See also: AWS API Documentation

    :example: response = client.lookup_developer_identity(
        IdentityPoolId='string',
        IdentityId='string',
        DeveloperUserIdentifier='string',
        MaxResults=123,
        NextToken='string'
    )

    :type IdentityPoolId: string
    :param IdentityPoolId: [REQUIRED]
            An identity pool ID in the format REGION:GUID.

    :type IdentityId: string
    :param IdentityId: A unique identifier in the format REGION:GUID.

    :type DeveloperUserIdentifier: string
    :param DeveloperUserIdentifier: A unique ID used by your backend authentication process to identify a user. Typically, a developer identity provider would issue many developer user identifiers, in keeping with the number of users.

    :type MaxResults: integer
    :param MaxResults: The maximum number of identities to return.

    :type NextToken: string
    :param NextToken: A pagination token. The first call you make will have NextToken set to null. After that the service will return NextToken values as needed. For example, let's say you make a request with MaxResults set to 10, and there are 20 matches in the database. The service will return a pagination token as a part of the response. This token can be used to call the API again and get results starting from the 11th match.

    :rtype: dict
    :return: {
        'IdentityId': 'string',
        'DeveloperUserIdentifierList': [
            'string',
        ],
        'NextToken': 'string'
    }

    :returns:
    (string) --

    """
    pass


def lag_to_suffix(lag: int) ->str:
    """
    Return the suffix for a column, given its lag.
    """
    if lag < 0:
        str_lag = 'f' + str(abs(lag))
    else:
        str_lag = 'l' + str(abs(lag))
    return str_lag


def farey(n):
    """
    Generates the Farey sequence of maximum denominator n.  Includes 0/1 & 1/1.
    Code shamelessly stolen from Wikipedia.
    Input: n -- a positive integer
    Output: Sequence of lists of the form [integer, integer]
    Examples:
    >>> list(farey(5))
    [(0, 1), (1, 5), (1, 4), (1, 3), (2, 5), (1, 2), (3, 5), (2, 3), (3, 4), (4, 5), (1, 1)]
    """
    a, b, c, d = 0, 1, 1, n
    yield a, b
    while c <= n:
        k = (n + b) // d
        a, b, c, d = c, d, k * c - a, k * d - b
        yield a, b


def get_runner(settings):
    """
    Return the appropriate VR runner command to use with the given settings.
    """
    return 'vrun' if settings.image_url is not None else 'vrun_precise'


@classmethod
def from_vertical_pattern(cls, pattern, size, **kwargs):
    """Create an image using a background pattern, scaled to the image width."""
    return cls.from_pattern(pattern, size, scale=(True, False),
        preserve_aspect=True, **kwargs)


def convert_int(*args, **kwargs):
    """
    Handle converter type "int"

    :param args:
    :param kwargs:
    :return: return schema dict
    """
    schema = {'type': 'integer', 'format': 'int32'}
    if 'max' in kwargs:
        schema['maximum'] = kwargs['max']
    if 'min' in kwargs:
        schema['minimum'] = kwargs['min']
    return schema


def OdfChk(SGLaue, L, M):
    """needs doc string"""
    if not L % 2 and abs(M) <= L:
        if SGLaue == '0':
            if M == 0:
                return True
        elif SGLaue == '-1':
            return True
        elif SGLaue == '2/m':
            if not abs(M) % 2:
                return True
        elif SGLaue == 'mmm':
            if not abs(M) % 2 and M >= 0:
                return True
        elif SGLaue == '4/m':
            if not abs(M) % 4:
                return True
        elif SGLaue == '4/mmm':
            if not abs(M) % 4 and M >= 0:
                return True
        elif SGLaue in ['3R', '3']:
            if not abs(M) % 3:
                return True
        elif SGLaue in ['3mR', '3m1', '31m']:
            if not abs(M) % 3 and M >= 0:
                return True
        elif SGLaue == '6/m':
            if not abs(M) % 6:
                return True
        elif SGLaue == '6/mmm':
            if not abs(M) % 6 and M >= 0:
                return True
        elif SGLaue == 'm3':
            if M > 0:
                if L % 12 == 2:
                    if M <= L // 12:
                        return True
                elif M <= L // 12 + 1:
                    return True
        elif SGLaue == 'm3m':
            if M > 0:
                if L % 12 == 2:
                    if M <= L // 12:
                        return True
                elif M <= L // 12 + 1:
                    return True
    return False


def _test():
    """perform internal tests."""
    import doctest
    doctest.testmod()


def query(userids=None, verbs=None, content_uids=None, sort_on=None,
    sort_order=None, ignore_completed=True):
    """
        Query the action storage for ContentActions matching the given query.
        Results are AND'd together

        :param userids: UserIDs to lookup
        :type userids: list or str or None
        :param verbs: Action verb to lookup
        :type verbs: list or str or None
        :param content_uids: Content UIDs to lookup
        :type content_uids: list or str or None
        :param sort_on: Field to sort on (created, completed, verb)
        :type sort_on: str
        :param sort_order: Whether to reverse the sort order ('reverse')
        :type sort_order: str or None
        :param ignore_completed: Whether to exclude completed actions from the
               results
        :type ignore_completed: bool
        :return: List of ContentActions
        :rtype: :class: `ContentAction`
        """


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

        :param PaperChangeMemberPolicyType val:
        :rtype: EventType
        """
    return cls('paper_change_member_policy', val)


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

        :param LegalHoldsReleaseAHoldDetails val:
        :rtype: EventDetails
        """
    return cls('legal_holds_release_a_hold_details', val)


def islast(generator):
    """ indicate whether the current item is the last one in a generator
    """
    next_x = None
    first = True
    for x in generator:
        if not first:
            yield next_x, False
        next_x = x
        first = False
    if not first:
        yield next_x, True


@classmethod
def after_delete(cls, info, instance):
    """Perform "after delete" operations.

        Override this to perform any operation on the instance
        after its `.delete()` method is called.
        """
    pass


@classmethod
def _get_all(cls, with_conformance=False, limit=None, minimal=True,
    page_size=100, page=1, values=None, language=None):
    """
        Query Wikidata to get all instances of this model.

        Notes:
            - Based on the way the query is optimized, the page_size and limit will provide UPPER bounds, but
              the response count can at times be less than the number provided due to post-query clean-up
              such as merging duplicates.

            - TODO: Consider use the .objects.all() style
        Args:
            with_conformance (Optional[Bool]): True if intending to use SheX validation, False otherwise
            limit (Optional[Int]): The maximum records to query Wikidata for
            minimal (Optional[Bool]): True if only need ID, label and description, False otherwise
            page_size (Optional[Int]): Maximum Number of records per API Request
            page (Optional[Int]): Page position, If None, get all pages
            values (Optional[List[str]]): List of QID values to use in the query.
            language (Optional[str]): Set the Primary language. If not set, will default to Meta Option.

        Returns (Generator[WikidataItemBase]): Generator of this model's instances

        """
    finished = False
    single_page = isinstance(page, int)
    unknown_depth = not values
    page = page or 1
    remaining_limit = limit
    value_total = len(values) if values else None
    if value_total:
        remaining_limit = min(remaining_limit, value_total
            ) if remaining_limit else value_total
    while not finished:
        offset = (page - 1) * page_size
        query_limit = min(remaining_limit, page_size) if limit else page_size
        if values:
            query_values = values[offset:offset + query_limit]
            query_offset = 0
        else:
            query_values = values
            query_offset = offset
        cls.logger.debug(
            'Querying for Page: %s  Limit: %s  Offset: %s  Minimal: %s',
            page, query_limit, offset, minimal)
        wikidata_response = cls._query_wikidata(limit=query_limit, minimal=
            minimal, offset=query_offset, values=query_values, language=
            language)
        for item in wikidata_response:
            yield cls._from_wikidata(item, with_conformance=with_conformance)
        api_count = len(wikidata_response)
        cls.logger.debug('... found %s item(s)', api_count)
        if remaining_limit:
            remaining_limit -= api_count
        finished = (single_page or unknown_depth and not api_count or
            isinstance(remaining_limit, int) and remaining_limit <= 0 or
            value_total and offset >= value_total)
        page += 1


def is_fp_closed(obj):
    """
    Checks whether a given file-like object is closed.

    :param obj:
        The file-like object to check.
    """
    if hasattr(obj, 'fp'):
        return obj.fp is None
    return obj.closed


def kick(roomJID, nick, reason=None, sender=None):
    """
        Kick a user from a MUC room.

        @param roomJID: The bare JID of the room.
        @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}

        @param nick: The occupant to be banned.
        @type nick: L{JID<twisted.words.protocols.jabber.jid.JID>} or
            C{unicode}

        @param reason: The reason given for the kick.
        @type reason: C{unicode}

        @param sender: The entity sending the request.
        @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
        """


def get_long_description(path):
    """
    Get long description from file.
    """
    if path:
        with open(path, 'rt') as fp:
            return fp.read()
    return None


def predict_co2_emissions(co2_emissions_model, params):
    """
    Predicts CO2 instantaneous emissions vector [CO2g/s].

    :param co2_emissions_model:
        CO2 emissions model (co2_emissions = models(params)).
    :type co2_emissions_model: callable

    :param params:
        CO2 emission model parameters (a2, b2, a, b, c, l, l2, t, trg).

        The missing parameters are set equal to zero.
    :type params: dict

    :return:
        CO2 instantaneous emissions vector [CO2g/s].
    :rtype: numpy.array
    """
    return co2_emissions_model(params)


@classmethod
def bernoulli(cls, k, p):
    """
        Visualization for a Bernoulli distribution
        Args:
            k, p (float): parameters to a Bernoulli distribution
        Returns:
            image (IPython.display.Image): The image that can be displayed inline in a Jupyter notebook
        """
    if k not in (0, 1):
        raise ValueError(
            'For a Bernoulli distribution, k should always be either 0 or 1.')
    if not 0 <= p <= 1:
        raise ValueError(
            'For a Bernoulli distribution, p should always be between 0 and 1.'
            )
    return cls._call_post(dist='bernoulli', k=k, p=p)


@staticmethod
def _compress(proxy):
    """
        compress transitive composite proxy dependencies (e.g. when a composite input is itself connected to a composite
        filter)
        """
    changed = True
    while changed:
        changed = False
        for compName, fromPort in proxy:
            for idx in range(len(proxy[compName, fromPort])):
                if proxy[compName, fromPort][idx] is None:
                    continue
                proxyNode, proxyPort = proxy[compName, fromPort][idx]
                if (proxyNode, proxyPort) in proxy:
                    changed = True
                    proxy[compName, fromPort][idx] = None
                    proxy[compName, fromPort].extend(proxy[proxyNode,
                        proxyPort])
    for compName, fromPort in proxy:
        toDel = set()
        for idx in range(len(proxy[compName, fromPort])):
            if proxy[compName, fromPort][idx] is None:
                toDel.add(idx)
        for idx in sorted(toDel)[::-1]:
            assert proxy[compName, fromPort][idx] is None
            proxy[compName, fromPort] = proxy[compName, fromPort][:idx
                ] + proxy[compName, fromPort][idx + 1:]
    return proxy


def Tsal_1989(Re, eD):
    """Calculates Darcy friction factor using the method in Tsal (1989)
    [2]_ as shown in [1]_.

    .. math::
        A = 0.11(\\frac{68}{Re} + \\frac{\\epsilon}{D})^{0.25}

    if :math:`A >= 0.018` then `fd = A`;

    if :math:`A < 0.018` then :math:`fd = 0.0028 + 0.85 A`.

    Parameters
    ----------
    Re : float
        Reynolds number, [-]
    eD : float
        Relative roughness, [-]

    Returns
    -------
    fd : float
        Darcy friction factor [-]

    Notes
    -----
    Range is 4E3 <= Re <= 1E8;  0 <= eD <= 5E-2

    Examples
    --------
    >>> Tsal_1989(1E5, 1E-4)
    0.018382997825686878

    References
    ----------
    .. [1] Winning, H. and T. Coole. "Explicit Friction Factor Accuracy and
       Computational Efficiency for Turbulent Flow in Pipes." Flow, Turbulence
       and Combustion 90, no. 1 (January 1, 2013): 1-27.
       doi:10.1007/s10494-012-9419-7
    .. [2] Tsal, R.J.: Altshul-Tsal friction factor equation.
       Heat-Piping-Air Cond. 8, 30-45 (1989)
    """
    A = 0.11 * (68 / Re + eD) ** 0.25
    if A >= 0.018:
        return A
    else:
        return 0.0028 + 0.85 * A


def getid(obj):
    """Return id if argument is a Resource.

    Abstracts the common pattern of allowing both an object or an object's ID
    (UUID) as a parameter when dealing with relationships.
    """
    if getattr(obj, 'uuid', None):
        return obj.uuid
    else:
        return getattr(obj, 'id', obj)