def align_left(text, length, left_edge='|', right_edge='|', text_length=
    None, left_padding=2):
    """Left align text."""
    if text_length is None:
        text_length = len(text)
    computed_length = text_length + left_padding + len(left_edge) + len(
        right_edge)
    if length - computed_length >= 0:
        padding = left_padding
    else:
        padding = 0
    output = []
    length_so_far = 0
    output.append(left_edge)
    length_so_far += len(left_edge)
    output.append(' ' * padding)
    length_so_far += padding
    output.append(text)
    length_so_far += text_length
    output.append(' ' * (length - length_so_far - len(right_edge)))
    output.append(right_edge)
    return ''.join(output)


def list_tags_for_resource(ResourceArn=None):
    """
    Lists all tags for an AWS DMS resource.
    See also: AWS API Documentation

    :example: response = client.list_tags_for_resource(
        ResourceArn='string'
    )

    :type ResourceArn: string
    :param ResourceArn: [REQUIRED]
            The Amazon Resource Name (ARN) string that uniquely identifies the AWS DMS resource.

    :rtype: dict
    :return: {
        'TagList': [
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def from_existing(cls, keystone_session, id):
    """
        Attach to an existing lease by ID. When using in conjunction with the
        context manager, it will *not* delete the lease at the end.
        """
    return cls(keystone_session, _preexisting=True, _id=id)


@classmethod
def from_columns(cls, columns, column_names=None, wrapped=True):
    """
        Build a new object of the type corresponding to the wrapper from the supplied `columns` (a list of columns; only length-1 lists is supported).

        `column_names` parameter is ignored.
        If ``wrapped==True``, return a new wrapper contating the column; otherwise, just return the column.
        """
    if len(columns) != 1:
        raise ValueError(
            'Array1DWrapper only supports single columns, got {} columns'.
            format(len(columns)))
    return cls.from_array(columns[0])


def argv2line(argv):
    """Put together the given argument vector into a command line.

        "argv" is the argument vector to process.

    >>> from listcmd import argv2line
    >>> argv2line(['foo'])
    'foo'
    >>> argv2line(['foo', 'bar'])
    'foo bar'
    >>> argv2line(['foo', 'bar baz'])
    'foo "bar baz"'
    >>> argv2line(['foo"bar'])
    'foo"bar'
    >>> print argv2line(['foo" bar'])
    'foo" bar'
    >>> print argv2line(["foo' bar"])
    "foo' bar"
    >>> argv2line(["foo'bar"])
    "foo'bar"
    """
    escapedArgs = []
    for arg in argv:
        if ' ' in arg and '"' not in arg:
            arg = '"' + arg + '"'
        elif ' ' in arg and "'" not in arg:
            arg = "'" + arg + "'"
        elif ' ' in arg:
            arg = arg.replace('"', '\\"')
            arg = '"' + arg + '"'
        escapedArgs.append(arg)
    return ' '.join(escapedArgs)


def theta_Cl_HAsO4_M83(T, P):
    """a-a': chloride hydrogen-arsenate [M83]."""
    theta = 0.122
    valid = T == 298.15
    return theta, valid


def gizmo_tweak():
    """Tweak the active gizmo

    """
    pass


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

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

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


def check_tag_list(tag_list):
    """ Makes a list of any tags entered on the command line. """
    tags = []
    if len(tag_list) != 0:
        tags = tag_list[0].split(',')
    return tags


@staticmethod
def sort_key(term):
    """ Get a key to sort an ontology term

        Args:
            term (:obj:`OntologyTerm`): term

        Returns:
            :obj:`tuple`
        """
    return term.ontology, term.id, term.name, term.description, term.iri


def jaccard_index(str1, str2, n_gram=2):
    """
	Computes the Jaccard Index between two strings
	`str1` and `str2`.
	#TODO : Write details about Jaccard Index
	"""
    if str1 == str2:
        return 1
    len1, len2 = len(str1), len(str2)
    if len1 == 0 or len2 == 0:
        return 0
    first_set = set()
    second_set = set()
    for i in range(len1 - 1):
        if ' ' not in str1[i:i + n_gram] and len(str1[i:i + n_gram]) == n_gram:
            first_set.add(str1[i:i + n_gram])
    for i in range(len2 - 1):
        if ' ' not in str2[i:i + n_gram] and len(str2[i:i + n_gram]) == n_gram:
            second_set.add(str2[i:i + n_gram])
    if first_set and second_set:
        intersection_cardinality = len(first_set.intersection(second_set))
        union_cardinality = len(first_set.union(second_set))
        return intersection_cardinality / float(union_cardinality)
    else:
        raise Exception('No n-grams found. Choose a lower value of n_gram')


def remove_ami(ec2resource, image):
    """Remove an AMI and its underlying snapshots."""
    snapshots = []
    for device in image.block_device_mappings:
        if 'Ebs' in device:
            snapshots.append(ec2resource.Snapshot(device['Ebs']['SnapshotId']))
    print('deregistering %s' % image.id)
    image.deregister()
    for snapshot in snapshots:
        print('deleting snapshot %s' % snapshot.id)
        snapshot.delete()


def serialize(r):
    """
      Returns the dictionary represenation serialized back to plain text
    """
    d = ''
    if 'PROPERTY' in r:
        keys = sorted(r['PROPERTY'].keys())
        for key in keys:
            for index, val in enumerate(r['PROPERTY'][key]):
                d += '\r\nPROPERTY[{0}][{1}]={2}'.format(key, index, val)
    for prop in ['CODE', 'DESCRIPTION', 'QUEUETIME', 'RUNTIME']:
        if prop in r:
            d += '\r\n{0}={1}'.format(prop, r[prop])
    return '[RESPONSE]{0}\r\nEOF\r\n'.format(d)


def preallocate(dim1, dim2=None):
    """
    Preallocate a list by creating either [None] * dim1
    or [[None] * dim2] * dim1. I use for loop to break reference

    Parameters:
    ----------
    dim1 : length of list
    dim2 : if not None, each element is also a list of None

    Returns:
    ----------
    allocated_list : pre-allocated placeholders
    """
    allocated_list = None
    if dim1 > 0:
        if dim2 is None:
            allocated_list = [None for _ in range(dim1)]
        else:
            allocated_list = [[None for _1 in range(dim2)] for _2 in range(
                dim1)]
    return allocated_list


def _Mul(lhs=None, rhs=None, out=None, name=None, **kwargs):
    """Multiplies arguments element-wise.

    The storage type of ``elemwise_mul`` output depends on storage types of inputs

       - elemwise_mul(default, default) = default
       - elemwise_mul(row_sparse, row_sparse) = row_sparse
       - elemwise_mul(default, row_sparse) = row_sparse
       - elemwise_mul(row_sparse, default) = row_sparse
       - elemwise_mul(csr, csr) = csr
       - otherwise, ``elemwise_mul`` generates output with default storage

    Parameters
    ----------
    lhs : NDArray
        first input
    rhs : NDArray
        second input

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

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


def _set_np_ndarray_class(cls):
    """Set the symbolic class to be cls"""
    global _np_ndarray_cls
    _np_ndarray_cls = cls


def step(exp):
    """ The step function

        Increments dynamic['value'] as needed, using the appropriate value from dynamic['steps']

        You can create your own custom step function in your gustav experiment
        script by creating the function, then specifying it:

        def step(exp):
            exp.var.dynamic['value'] += exp.var.dynamic['cur_step'] * exp.var.dynamic['steps'][exp.var.dynamic['n_reversals']]
            exp.var.dynamic['value'] = max(exp.var.dynamic['value'], exp.var.dynamic['val_floor'])
            exp.var.dynamic['value'] = min(exp.var.dynamic['value'], exp.var.dynamic['val_ceil'])
        exp.var.dynamic['step'] = step
    """
    exp.var.dynamic['value'] += exp.var.dynamic['cur_step'] * exp.var.dynamic[
        'steps'][exp.var.dynamic['n_reversals']]
    exp.var.dynamic['value'] = max(exp.var.dynamic['value'], exp.var.
        dynamic['val_floor'])
    exp.var.dynamic['value'] = min(exp.var.dynamic['value'], exp.var.
        dynamic['val_ceil'])


@staticmethod
def to_phenotype(genotype):
    """
        Converts LCS representation of a state to environment
        representation.
        """
    return genotype[0]


def _get_user(request, user_incoming, email_incoming):
    """Pull out and return the user's ID and email from a given request,
    or (None, '') if the request is None.
    """
    if request:
        user_id = user_incoming if user_incoming else request.user.id
        user_email = email_incoming if email_incoming else request.user.email
    else:
        user_id = user_incoming
        user_email = email_incoming
    return user_id, user_email


@classmethod
def set_secgroup(cls, value):
    """
        sets the default group
        :param value: the group name
        :return:
        """
    cls.set('secgroup', value)


@classmethod
def prepare_json(cls, data_class, json_dict):
    """Prepares json for the data class."""
    attribute_dict = data_class.attribute_guide
    output = {}
    for key in attribute_dict:
        actual_dict = key.split(',')
        try:
            out = json_dict
            for level in actual_dict:
                out = out[level]
        except KeyError:
            output[attribute_dict[key][0]] = None
        else:
            output[attribute_dict[key][0]] = attribute_dict[key][1](out)
    return output


def get_new_filename(filename: str) ->str:
    """get_new_filename is system agnostic (3A, 3B1, 3B2).
    Gets an alyx compatible filename from any spikeglx ephys file.

    :param filename: Name of an ephys file
    :type filename: str
    :return: New name for ephys file
    :rtype: str
    """
    root = '_spikeglx_ephysData'
    gt = None
    for g in range(10):
        for t in range(10):
            if f'_g{g}_t{t}' in filename:
                gt = f'_g{g}_t{t}'
    else:
        if gt is None:
            raise NotImplementedError
    if '.bin' in filename:
        ext = 'bin'
    elif '.meta' in filename:
        ext = 'meta'
    if '.nidq.' in filename:
        return '.'.join([root + gt, 'nidq', ext])
    if '.imec0.' in filename:
        probe = 'imec0'
    elif '.imec1.' in filename:
        probe = 'imec1'
    elif '.imec.' in filename:
        probe = 'imec'
    if '.ap.' in filename:
        freq = 'ap'
    elif '.lf.' in filename:
        freq = 'lf'
    return '.'.join([root + gt, probe, freq, ext])


def resels2nnodes(resels, fwhm):
    """
	Get the number of field nodes from resel counts based on the FWHM

	:Parameters:

		*resels* --- resel counts

		*fwhm* --- actual or estimated FWHM*element_based* --- element-based sampling (default: node-based sampling)

	:Returns:

		*nNodes* --- number of field nodes

	:Example:

		>>> resels = (1, 10.0)
		>>> nNodes = rft1d.geom.resels2nnodes(resels, 10.0) #yields 101
		>>> resels = (2, 6.9)
		>>> nNodes = rft1d.geom.resels2nnodes(resels, 10.0) #yields 71

	:Note:

		See **rft1d.geom.resel_counts** for details regarding node-based vs. element-based sampling.
	"""
    return int(resels[0] + fwhm * resels[1])


def _decode_action_type(routes, topic):
    """
    Decode an inbound MQTT topic into an action type.

    :param routes: The routing dict
    :type routes: dict

    :param topic: The MQTT topic
    :type topic: str

    :returns: The action type
    """
    for handle, route in routes.items():
        if topic.startswith(route):
            return '@' + topic.replace(route, handle)
    return topic


def list_texts(texts):
    """
    Compile (Oxford) comma-delimited list of texts.

    :param texts: [list] non-empty sequence of texts
    :return: compiled text
    """
    all_texts_but_last = texts[:-1]
    if all_texts_but_last:
        last_delimiter = (',' if len(all_texts_but_last) > 1 else '') + ' and '
        return last_delimiter.join([', '.join(all_texts_but_last), texts[-1]])
    else:
        return texts[-1]


def get_tree_size(cur):
    """
    Return the total amount of tree nodes.
    """
    sql = """
      SELECT
        COUNT(*)
      FROM
        nodes;
    """
    cur.execute(sql)
    result = cur.fetchone()
    return result['count']


def keyval_list_to_dict(l):
    """
    Converts a list of key=value strings to a dictionary.
    :param l: the list
    :return: the dictionary
    """
    d = {}
    for e in l:
        keyval = e.split('=', 2)
        if len(keyval) != 2:
            return None
        d[keyval[0]] = keyval[1]
    return d


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 format_label_value(*values):
    """
    Construct a label value.

    If multiple value components are provided, they are joined by underscores.
    """
    return '_'.join(values)


def build_ieee_block(data):
    """Build IEEE block"""
    return str('#8%08d' % len(data)).encode('utf-8') + data


def write_widget(obj):
    """ Write a mesh object as a python script for widget use.
    """
    script = ''
    script += (
        'def create_thing_widget(rig, bone_name, size=1.0, bone_transform_name=None):\n'
        )
    script += '    obj = create_widget(rig, bone_name, bone_transform_name)\n'
    script += '    if obj != None:\n'
    if len(obj.data.vertices) > 0:
        script += '        verts = ['
        for v in obj.data.vertices:
            script += '(' + str(v.co[0]) + '*size, ' + str(v.co[1]
                ) + '*size, ' + str(v.co[2]) + '*size), '
        script += ']\n'
    if len(obj.data.edges) > 0:
        script += '        edges = ['
        for e in obj.data.edges:
            script += '(' + str(e.vertices[0]) + ', ' + str(e.vertices[1]
                ) + '), '
        script += ']\n'
    if len(obj.data.polygons) > 0:
        script += '        faces = ['
        for f in obj.data.polygons:
            script += '('
            for v in f.vertices:
                script += str(v) + ', '
            script += '), '
        script += ']\n'
    script += """
        mesh = obj.data
"""
    script += '        mesh.from_pydata(verts, edges, faces)\n'
    script += '        mesh.update()\n'
    script += '        mesh.update()\n'
    script += '        return obj\n'
    script += '    else:\n'
    script += '        return None\n'
    return script


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 add_configure_spark_arguments(argparser):
    """Adds a set of arguments that are needed for spark session configuration.

    >>> from pyspark.sql import SparkSession
    >>>
    >>> arg_parser = argparse.ArgumentParser()
    >>> add_configure_spark_arguments(arg_parser)
    >>> # ... more argparse arguments

    >>> args = arg_parser.parse_args()
    >>> spark = configure_spark(SparkSession.builder.appName('petastorm-copy'), args).getOrCreate()

    :param argparser: An instance of ``argparse.ArgumentParser`` object
    :return: None
    """
    argparser.add_argument('--master', type=str, help=
        'Spark master. Default if not specified. To run on a local machine, specify "local[W]" (where W is the number of local spark workers, e.g. local[10])'
        )
    argparser.add_argument('--spark-session-config', type=str, nargs='+',
        help=
        'A list of "=" separated key-value pairs used to configure SparkSession object. For example: --spark-session-config spark.executor.cores=2 spark.executor.memory=10g'
        )


def email_to_fas(email):
    """Try to get a FAS username from an email address. For now, this
    is a dumb version which just does the 'easy' part of what the full
    fat fedmsg_meta email2fas did - for fedoraproject.org addresses,
    we can just do this easily. For all other addresses, we really
    need that full feature added to fedora-messaging.
    """
    if email.endswith('@fedoraproject.org'):
        return email.rsplit('@', 1)[0], True
    return email, False


def get(isamAppliance, check_mode=False, force=False):
    """
    Get management ssl certificate information
    """
    return isamAppliance.invoke_get(
        'Get management ssl certificate information',
        '/isam/management_ssl_certificate/')


@staticmethod
def get_friendly_name():
    """Gets the user friendly display name for this condition

        This typically reflects the text found in the Jenkins UI for the
        condition

        :rtype: :class:`str`
        """
    return 'not'


def userpwd(arg):
    """ If arg is of the form username:password, returns them as a tuple. Otherwise None. """
    ret = arg.split(':')
    return tuple(ret) if len(ret) == 2 else None


def getDirName(filepath):
    """e:/test/file.txt --> e:/test/"""
    filepath = filepath.replace('\\', '/')
    index = filepath.rfind('/')
    if index == -1:
        return './'
    return filepath[0:index + 1]


def flatten_to_polygons(geometry):
    """
    Return a list of all polygons of this (multi)`geometry`.
    """
    if geometry.type == 'Polygon':
        return [geometry]
    if geometry.type == 'MultiPolygon':
        return list(geometry)
    if hasattr(geometry, 'geoms'):
        geoms = []
        for part in geometry.geoms:
            if part.type == 'Polygon':
                geoms.append(part)
        if geoms:
            return geoms
    return []


def readJPEGInfo(image):
    """Read width, height and number of components from open JPEG file."""
    import struct
    from reportlab.pdfbase.pdfdoc import PDFError
    validMarkers = [192, 193, 194]
    noParamMarkers = [208, 209, 210, 211, 212, 213, 214, 215, 216, 1]
    unsupportedMarkers = [195, 197, 198, 199, 200, 201, 202, 203, 205, 206, 207
        ]
    done = 0
    while not done:
        x = struct.unpack('B', image.read(1))
        if x[0] == 255:
            x = struct.unpack('B', image.read(1))
            if x[0] in validMarkers:
                image.seek(2, 1)
                x = struct.unpack('B', image.read(1))
                if x[0] != 8:
                    raise PDFError('JPEG must have 8 bits per component')
                y = struct.unpack('BB', image.read(2))
                height = (y[0] << 8) + y[1]
                y = struct.unpack('BB', image.read(2))
                width = (y[0] << 8) + y[1]
                y = struct.unpack('B', image.read(1))
                color = y[0]
                return width, height, color
            elif x[0] in unsupportedMarkers:
                raise PDFError('JPEG Unsupported JPEG marker: %0.2x' % x[0])
            elif x[0] not in noParamMarkers:
                x = struct.unpack('BB', image.read(2))
                image.seek((x[0] << 8) + x[1] - 2, 1)


@classmethod
def add_hook(cls, hook_type, hook_func):
    """Add a new hook of specified type.

        :param cls: class that registers hooks
        :param hook_type: hook type, e.g., '__pre_parse_args__'
        :param hook_func: hook function
        """
    if hook_type not in cls._hooks_map:
        cls._hooks_map[hook_type] = []
    cls._hooks_map[hook_type].append(hook_func)


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

        :param GroupAddExternalIdType val:
        :rtype: EventType
        """
    return cls('group_add_external_id', val)


def _(x):
    """Identity function for string extraction."""
    return x


def write_xlsx(data, file_name, worksheet_names=None):
    """
    Writes out to new excel format.

    Args:
        data: 2D list of tables/worksheets.
        file_name: Name of the output file.
        worksheet_names: A list of worksheet names (optional).
    """
    raise NotImplementedError('Xlsx writing not implemented')


@classmethod
def has_deconstructor(cls, obj):
    """
        Test whether obj was assigned a deconstructor by assign_deconstructor().
        """
    try:
        return obj.__class__.__del__.__func__.func_defaults[1
            ] is cls.id_to_weakref_callback_pair
    except:
        return False


def apply_cli_args(application, args):
    """
    Set Flask app instance configuration from arguments

    :param application: Flask app instance
    :type application: :py:class:`Flask.app`
    :param args: arguments
    :type args: :py:class:`argparse.Namespace`
    :return: None
    """
    args_dict = vars(args)
    for argument, value in args_dict.items():
        if value is not None:
            application.config[argument.upper()] = value


def edit(text=None, editor=None, env=None, require_save=True, extension=
    '.txt', filename=None):
    """Edits the given text in the defined editor.  If an editor is given
    (should be the full path to the executable but the regular operating
    system search path is used for finding the executable) it overrides
    the detected editor.  Optionally, some environment variables can be
    used.  If the editor is closed without changes, `None` is returned.  In
    case a file is edited directly the return value is always `None` and
    `require_save` and `extension` are ignored.

    If the editor cannot be opened a :exc:`UsageError` is raised.

    Note for Windows: to simplify cross-platform usage, the newlines are
    automatically converted from POSIX to Windows and vice versa.  As such,
    the message here will have ``\\n`` as newline markers.

    :param text: the text to edit.
    :param editor: optionally the editor to use.  Defaults to automatic
                   detection.
    :param env: environment variables to forward to the editor.
    :param require_save: if this is true, then not saving in the editor
                         will make the return value become `None`.
    :param extension: the extension to tell the editor about.  This defaults
                      to `.txt` but changing this might change syntax
                      highlighting.
    :param filename: if provided it will edit this file instead of the
                     provided text contents.  It will not use a temporary
                     file as an indirection in that case.
    """
    from ._termui_impl import Editor
    editor = Editor(editor=editor, env=env, require_save=require_save,
        extension=extension)
    if filename is None:
        return editor.edit(text)
    editor.edit_file(filename)


def _get_subexon_seq(exon_row, interval):
    """Return the interval sequence of the subexon."""
    seq = exon_row['ExonSequence']
    if exon_row['Strand'] == 1:
        exon_start = exon_row['ExonRegionStart']
        interval_start = interval.start - exon_start
        interval_end = interval.end - exon_start + 1
    else:
        exon_start = exon_row['ExonRegionEnd']
        interval_start = exon_start - interval.end
        interval_end = exon_start - interval.start + 1
    assert interval_start < interval_end, 'Interval end should not be lower than its start'
    return seq[interval_start:interval_end]


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

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

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


def check_tls_mode(tls_mode):
    """Check that provided tls mode is valid and convert to canonical form.

    Args:
        tls_mode (string): One of 'on', 'off', 'starttls', or 'starttls-force'.
            If 'on', we use TLS for the initial session establishment.
            If 'off', no TLS is used (for connecting to a legacy manager that
            does not support TLS). If 'starttls', the connection is initially
            unencrypted and will then be upgraded to a TLS connection after the
            initial handshake when connecting to a remote manager.
            If 'starttls-force', the client will behave like starttls mode but
            the connection will be upgraded to TLS even when connecting to the
            manager on localhost.

    Returns (string): tls mode in canonical (lowercase) form.

    Raises:
        ValueError: an invalid tls mode was specified
    """
    tls_mode = tls_mode.lower()
    if tls_mode not in ['on', 'off', 'starttls', 'starttls-force']:
        raise ValueError(
            "tls mode must be one of 'on', 'off', 'starttls', or 'starttls-force'. got: '{}'"
            .format(tls_mode))
    return tls_mode


def host(s):
    """Try to get a host out of something like username@ipaddress."""
    return s.split('@')[-1]


def validipport(port):
    """
    Returns True if `port` is a valid IPv4 port.

        >>> validipport('9000')
        True
        >>> validipport('foo')
        False
        >>> validipport('1000000')
        False
    """
    try:
        if not 0 <= int(port) <= 65535:
            return False
    except ValueError:
        return False
    return True


@staticmethod
def from_b58check(private_key):
    """ Decodes a Base58Check encoded private-key.

        Args:
            private_key (str): A Base58Check encoded private key.

        Returns:
            PrivateKey: A PrivateKey object
        """
    raise NotImplementedError


def view_zoom(factor: float=0.0):
    """Zoom in/out the image

    :param factor: Factor, Zoom factor, values higher than 1.0 zoom in, lower values zoom out
    :type factor: float
    """
    pass


@classmethod
def wrap_content(cls, container, wrapper):
    """wrap the content of container element with wrapper element"""
    wrapper.text = (container.text or '') + (wrapper.text or '')
    container.text = ''
    for ch in container:
        wrapper.append(ch)
    container.insert(0, wrapper)
    return container


def state_to_pixel(state):
    """Convert generator state to pixel value.

    Parameters
    ----------
    state : `str`

    Returns
    -------
    `int`
    """
    return ord(state[-1])


@staticmethod
def concat_url(endpoint, url):
    """Concatenate endpoint and final URL.

        E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to
        "http://keystone/v2.0/tokens".

        :param endpoint: the base URL
        :param url: the final URL
        """
    return '%s/%s' % (endpoint.rstrip('/'), url.strip('/'))


def p_suite_plus_1(p):
    """suite_plus : stmt"""
    p[0] = p[1]


def herm_conj(value):
    """
    Calculate the hermitian conjugate of a python object.

    If the object is neither a complex number nor a matrix, the original value
    is returned.  In the context of this module, this is the correct behavior
    for functions.
    """
    if hasattr(value, 'conjugate'):
        value = value.conjugate()
        if hasattr(value, 'transpose'):
            value = value.transpose()
    return value


def callcommand(name, args):
    """Request that a named command be executed.

        Receives the command name and a dictionary of command arguments.

        Returns a ``concurrent.futures.Future`` that will resolve to the
        result of that command request. That exact value is left up to
        the implementation and possibly varies by command.

        Not all commands can coexist with other commands in an executor
        instance: it depends on the underlying wire protocol transport being
        used and the command itself.

        Implementations MAY call ``sendcommands()`` automatically if the
        requested command can not coexist with other commands in this executor.

        Implementations MAY call ``sendcommands()`` automatically when the
        future's ``result()`` is called. So, consumers using multiple
        commands with an executor MUST ensure that ``result()`` is not called
        until all command requests have been issued.
        """


def calc_unique_bls(n_ants=None):
    """Calculate number of unique baselines
    Parameters
    ----------
    n_ants : :obj:`int`
        Available antennas
    Returns
    -------
    Number of unique baselines

    """
    return int(0.5 * n_ants * (n_ants - 1))


def log10(data=None, out=None, name=None, **kwargs):
    """Returns element-wise Base-10 logarithmic value of the input.

    ``10**log10(x) = x``

    The storage type of ``log10`` output is always dense

    Defined in src/operator/tensor/elemwise_unary_op_logexp.cc:L93

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

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

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


def sanit_is_jid(string):
    """
        Returns true if the string is a JID.
    """
    if string.count('@') != 1 or string.count('/') > 1:
        return False
    splitted = string.split('@')
    username = splitted[0]
    host = splitted[1]
    if host.count('.') > 1:
        return False
    host = host.replace('.', '')
    if '/' in host:
        host_resource = host.split('/')
        host = host_resource[0]
        resource = host_resource[1]
        if not resource.isalnum():
            return False
    return username.isalnum() and host.isalnum()


@staticmethod
def GetTotalBytesSent():
    """Returns (NewTotalBytesSent)"""
    raise NotImplementedError()


def get_note_category(note):
    """get a note category"""
    if 'category' in note:
        category = note['category'] if note['category'] is not None else ''
    else:
        category = ''
    return category


def filenamefrompath(filepath):
    """
        #根据文件路径取出文件名,文件名大写
        """
    fname = filepath.split('.', 1)[0]
    fname = fname.split('/')[len(fname.split('/')) - 1].upper()
    return fname


def model_key(model):
    """For a given model, return 'appname.modelname'."""
    return '%s.%s' % (model._meta.app_label, model._meta.object_name.lower())


def prediction_gears_gsm(correct_gear, gear_filter, gsm, times, velocities,
    accelerations, motive_powers, cycle_type=None, velocity_speed_ratios=
    None, engine_coolant_temperatures=None):
    """
    Predicts gears with a gear shifting model (cmv or gspv or dtgs or mgs) [-].

    :param correct_gear:
        A function to correct the gear predicted.
    :type correct_gear: callable

    :param gear_filter:
        Gear filter function.
    :type gear_filter: callable

    :param cycle_type:
        Cycle type (WLTP or NEDC).
    :type cycle_type: str

    :param velocity_speed_ratios:
        Constant velocity speed ratios of the gear box [km/(h*RPM)].
    :type velocity_speed_ratios: dict[int | float]

    :param gsm:
        A gear shifting model (cmv or gspv or dtgs).
    :type gsm: GSPV | CMV | DTGS

    :param velocities:
        Vehicle velocity [km/h].
    :type velocities: numpy.array

    :param accelerations:
        Vehicle acceleration [m/s2].
    :type accelerations: numpy.array

    :param times:
        Time vector [s].
    :type times: numpy.array, optional

    :param motive_powers:
        Motive power [kW].
    :type motive_powers: numpy.array

    :param engine_coolant_temperatures:
        Engine coolant temperature vector [°C].
    :type engine_coolant_temperatures: numpy.array

    :return:
        Predicted gears.
    :rtype: numpy.array
    """
    if velocity_speed_ratios is not None and cycle_type is not None:
        from . import _upgrade_gsm
        gsm = _upgrade_gsm(gsm, velocity_speed_ratios, cycle_type)
    gears = gsm.predict(times, velocities, accelerations, motive_powers,
        engine_coolant_temperatures, correct_gear=correct_gear, gear_filter
        =gear_filter)
    return gears


@staticmethod
def _effective_fee_rate(amt_sat, base, rate):
    """
        Calculates the effective fee rate: (base_fee + fee_rate * amt) / amt

        :param amt_sat: amount in sat
        :type amt_sat: int

        :param base: base fee in sat
        :type base: float

        :param rate: fee rate
        :type rate: float

        :return: effective fee rate
        :rtype: float
        """
    amt_msat = amt_sat * 1000
    assert not amt_msat == 0
    rate = (base + rate * amt_msat / 1000000) / amt_msat
    return rate


def write_projection_file(filename, sample_labels, projections):
    """
    Outputs the coordinates for each projection to a file.

    Parameters
    ----------
    filename : String
        File to write
    sample_labels : list(String) len=Num_Samples
        Labels for each sample
    projections : dict(string, (2 x Num_Samples) numpy.ndarray)
        dictionary mapping the projection type (e.g. "tSNE") to an array containing
        the two-dimensional coordinates for each sample in the projection.

    """
    ff = open(filename, 'w')
    for proj in projections:
        coordinates = projections[proj]
        for i in range(coordinates.shape[1]):
            ff.write(proj + '\t')
            ff.write(sample_labels[i] + '\t')
            ff.write('{:.5f}'.format(coordinates[0, i]) + '\t')
            ff.write('{:.5f}'.format(coordinates[1, i]))
            ff.write('\n')
    ff.close()


def testplot(yt, pred):
    """
    Author: Aru Raghuvanshi

    This function plots Predictions against Truth Values
    of the Algorithm. Best used for Regression Models.

    Arguments: truth, pred
    Returns: Plot

    """
    import matplotlib.pyplot as plt
    plt.style.use('seaborn')
    xaxis = range(1, yt.shape[0] + 1)
    plt.figure(figsize=(15, 6))
    plt.scatter(xaxis, yt, color='green', label='Truth Data', marker='o')
    plt.plot(xaxis, pred, color='limegreen', label='Prediction')
    plt.xlabel('Test Observations', fontsize=14)
    plt.ylabel('Predictions', fontsize=14)
    plt.title('Truth Vs Predicted', fontsize=16)
    plt.legend(fontsize=15, loc=4)
    plt.show()


def cbf_end_loop(array, apointer, inputdata, output, source, spointer):
    """
    End loop. However, it is possible to have an end loop operator
    ("]") without a preceding start loop operator ("["). In this case,
    the end loop operator ("]") will be ignored and execution continues.
    Note that unclosed or unopened loops may result in non-deterministic
    behaviour.
    """
    temp = spointer
    if array[apointer] < 1:
        return array, apointer, inputdata, output, source, spointer + 1
    else:
        count = 1
        try:
            while count > 0:
                spointer = spointer - 1
                if source[spointer] == ']':
                    count = count + 1
                if source[spointer] == '[':
                    count = count - 1
        except IndexError:
            spointer = temp
    return array, apointer, inputdata, output, source, spointer


def area_tri(v1: 'mathutils.Vector', v2: 'mathutils.Vector', v3:
    'mathutils.Vector') ->float:
    """Returns the area size of the 2D or 3D triangle defined.

    :param v1: Point1
    :type v1: 'mathutils.Vector'
    :param v2: Point2
    :type v2: 'mathutils.Vector'
    :param v3: Point3
    :type v3: 'mathutils.Vector'
    """
    pass


@classmethod
def new_from_raw(cls, raw):
    """Return a new instance of this model from a raw (dict) of data that is loaded by our Schema

        :param dict raw: The attributes to use when creating the instance
        """
    if raw is None:
        return None
    return cls(**raw)


def provider_parser(subparser):
    """Configure provider parser for DNSPod"""
    subparser.add_argument('--auth-username', help=
        'specify api id for authentication')
    subparser.add_argument('--auth-token', help=
        'specify token for authentication')


def ep2string(EP, area=1.0):
    """Format energy efficiency indicators as string from primary energy data

    In the context of the CTE regulations, this refers to primary energy values.
    """
    areafactor = 1.0 / area
    eparen = areafactor * EP['EPpasoA']['ren']
    epanren = areafactor * EP['EPpasoA']['nren']
    epatotal = eparen + epanren
    eparer = eparen / epatotal if epatotal else 0.0
    epren = areafactor * EP['EP']['ren']
    epnren = areafactor * EP['EP']['nren']
    eptotal = epren + epnren
    eprer = epren / eptotal if eptotal else 0.0
    txt = (
        """EP(step A)  , ren ={:>8.1f}, nren={:>8.1f}, tot ={:>8.1f}, RER ={:>8.2f}
EP(step A+B), ren ={:>8.1f}, nren={:>8.1f}, tot ={:>8.1f}, RER ={:>8.2f}
"""
        .format(eparen, epanren, epatotal, eparer, epren, epnren, eptotal,
        eprer))
    return txt


@staticmethod
def split_header(fp):
    """
        Read file pointer and return pair of lines lists:
        first - header, second - the rest.
        """
    body_start, header_ended = 0, False
    lines = []
    for line in fp:
        if line.startswith('#') and not header_ended:
            body_start += 1
        else:
            header_ended = True
        lines.append(line)
    return lines[:body_start], lines[body_start:]


def add_nocolour_argument(subparser):
    """
    Oft used argument for disabling colour.

    :param subparser: an argparse instance
    """
    add = subparser.add_argument
    add('--no-colour', action='store_true', help='disable colour output')


def add_entry_to_all_stats(results, project_id, episode_id, task_type_id,
    task_status_id, task_status_short_name, task_status_color, task_count,
    entity_nb_frames):
    """
    Add to aggregated entry of stats results, information of given count for
    given entity, task type and task satus.
    """
    task_type_id = str(task_type_id)
    task_status_id = str(task_status_id)
    results.setdefault('all', {'all': {}})
    results['all'].setdefault(task_type_id, {})
    results['all'][task_type_id].setdefault(task_status_id, {'name':
        task_status_short_name, 'color': task_status_color, 'count': 0,
        'frames': 0})
    results['all'][task_type_id][task_status_id]['count'] += task_count or 0
    results['all'][task_type_id][task_status_id]['frames'
        ] += entity_nb_frames or 0
    results['all']['all'].setdefault(task_status_id, {'name':
        task_status_short_name, 'color': task_status_color, 'count': 0,
        'frames': 0})
    results['all']['all'][task_status_id]['count'] += task_count or 0
    results['all']['all'][task_status_id]['frames'] += entity_nb_frames or 0


def to_lvm_size(number_of_bytes, fmt='%.1f'):
    """Inverse of lvm_size() using numeric string format @fmt."""
    size = float(number_of_bytes)
    if size >= 1024 ** 3:
        return (fmt + 'G') % (size / 1024 ** 3)
    elif size >= 1024 ** 2:
        return (fmt + 'M') % (size / 1024 ** 2)
    elif size >= 1024:
        return (fmt + 'K') % (size / 1024)
    return '%dB' % size


@classmethod
def should_include(cls, builder_context: 'PipelineBuilderContext'):
    """Include this wrap in adviser, once."""
    if not builder_context.is_included(cls
        ) and builder_context.is_adviser_pipeline():
        return {}
    return None


@classmethod
def _from_dict(cls, _dict):
    """Initialize a Behavior object from a json dictionary."""
    args = {}
    if 'trait_id' in _dict:
        args['trait_id'] = _dict.get('trait_id')
    else:
        raise ValueError(
            "Required property 'trait_id' not present in Behavior JSON")
    if 'name' in _dict:
        args['name'] = _dict.get('name')
    else:
        raise ValueError(
            "Required property 'name' not present in Behavior JSON")
    if 'category' in _dict:
        args['category'] = _dict.get('category')
    else:
        raise ValueError(
            "Required property 'category' not present in Behavior JSON")
    if 'percentage' in _dict:
        args['percentage'] = _dict.get('percentage')
    else:
        raise ValueError(
            "Required property 'percentage' not present in Behavior JSON")
    return cls(**args)


def execute(need_active: bool=False):
    """Execute selected file

    :param need_active: Need Active, Only execute if there’s an active selected file in the file list
    :type need_active: bool
    """
    pass


@staticmethod
def drop_hostname(email):
    """
        >>> Context.drop_hostname("foo")
        'foo'
        >>> Context.drop_hostname("foo@bar.com")
        'foo'
        >>> Context.drop_hostname("")
        ''
        >>> Context.drop_hostname("@")
        ''
        """
    try:
        n = email.index('@')
    except ValueError:
        return email
    else:
        return email[0:n]


def delete_qualification_type(QualificationTypeId=None):
    """
    The DeleteQualificationType deletes a Qualification type and deletes any HIT types that are associated with the Qualification type.
    This operation does not revoke Qualifications already assigned to Workers because the Qualifications might be needed for active HITs. If there are any pending requests for the Qualification type, Amazon Mechanical Turk rejects those requests. After you delete a Qualification type, you can no longer use it to create HITs or HIT types.
    See also: AWS API Documentation

    :example: response = client.delete_qualification_type(
        QualificationTypeId='string'
    )

    :type QualificationTypeId: string
    :param QualificationTypeId: [REQUIRED]
            The ID of the QualificationType to dispose.

    :rtype: dict
    :return: {}

    """
    pass


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

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

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


def give_user_correction_instructions():
    """Give the user instructions for supplying valid destination-correction
    information."""
    print(
        """	If you just want to update a package's destination right away,
first type the package ID, then comma and space, then either the landmark
or street address.
	If you are entering information about a destination correction that
will be known later, enter it in this format: first the package ID, and then
the time by which the true destination will be known.
	If you are updating an existing correction item, enter it in this
format: first the package ID, and then either the landmark or the street
address (yes, this is the same as in the first case).

	Here are some examples of input that will be accepted:
3, 09:30		<= this says that package with ID 3 has the wrong
			destination location, but it will be corrected
			by 9:30am today
5, 13:30		<= similarly, this says package 5 will
			have the correct destination by 1:30pm today
6, Sugar House Park	<= this says that package ID 6 needs to go to
			Sugar House Park instead of whatever the previous
			destination was

	A couple of things worth keeping in mind:
1. If you enter a time, it must be in this format
	h:mm or hh:mm
	Examples: 3:55, 12:30, 14:00
2. If you enter a time, it must be "military time".
3. That means "AM" and "PM" are ignored.
4. If you enter a location, then whether that is a landmark or street address,
it must match exactly what the package csv file had for that package.
The exception is that the (five-digit) zip code is optional.
"""
        )


def get(isamAppliance, check_mode=False, force=False):
    """
    Retrieve existing suffixes.
    """
    return isamAppliance.invoke_get('Retrieving suffixes from embedded ldap',
        '/isam/embedded_ldap/suffixes/v1')


def normalize_pep440(**kwd):
    """ Normalize the version.

        >>> normalize_pep440(**parse_pep440('1.2.3.4.rc5.post.dev'))
        '1.2.3.4rc5'
    """
    normalized = '.'.join(map(str, kwd['release']))
    if 'pre_release' in kwd:
        normalized += '%s%s' % kwd['pre_release']
    if 'post_release' in kwd:
        normalized += '.post' + str(kwd['post_release'])
    if 'dev_release' in kwd:
        normalized += '.dev' + str(kwd['dev_release'])
    if 'epoch' in kwd:
        normalized = '{}!{}'.format(kwd['epoch'], normalized)
    return normalized


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 _get_y_header(UPPER_PAGE_EDGE, box_parameters, Y1_MAX, verbose):
    """
    Note: in PDF the upper border of a column can easily be higher than the
    lower boarder of its header (anyway, I'm extrapolating these values).
    --> header text will eventually be in a column, and column text will be found
        inside the header's box ...
    "PDF is evil." (Yusuke Shinyama)
    """
    headers = list()
    cols = list()
    for params in box_parameters:
        if params.y1 == Y1_MAX:
            headers.append(params)
        else:
            cols.append(params)
    upper_cols_border = 0
    for params in cols:
        if params.y1 > upper_cols_border:
            if params.y1 > params.y0:
                upper_cols_border = params.y1
    y0 = 0
    for params in headers:
        if params.y0 < upper_cols_border:
            if params.y0 > y0:
                y0 = params.y0
        else:
            y0 = upper_cols_border
    Y_HEADER = y0
    return Y_HEADER


@staticmethod
def __protocolize(base_url):
    """Internal add-protocol-to-url helper"""
    if not base_url.startswith('http://') and not base_url.startswith(
        'https://'):
        base_url = 'https://' + base_url
    base_url = base_url.rstrip('/')
    return base_url


def astype(input, ty):
    """Convert the input tensor to the given data type.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    ty : data type
        It should be one of the values in the data type dict.

    Returns
    -------
    Tensor
        A framework-specific tensor.
    """
    pass


def inclear():
    """clear incoming things"""


def get_thresholds(keys):
    """Returns non-str thresholds of iterable.

    Args:
        keys (iterable): Iterable, that is the result of
          :func:`delay_segments.keys()`.
    """
    return sorted(list(filter(lambda x: not isinstance(x, str), keys)))


def get_function_name(s):
    """
    Get the function name from a C-style function declaration string.

    :param str s: A C-style function declaration string.
    :return:      The function name.
    :rtype:       str
    """
    s = s.strip()
    if s.startswith('__attribute__'):
        if '))' not in s:
            raise ValueError(
                '__attribute__ is present, but I cannot find double-right parenthesis in the function declaration string.'
                )
        s = s[s.index('))') + 2:].strip()
    if '(' not in s:
        raise ValueError(
            'Cannot find any left parenthesis in the function declaration string.'
            )
    func_name = s[:s.index('(')].strip()
    for i, ch in enumerate(reversed(func_name)):
        if ch == ' ':
            pos = len(func_name) - 1 - i
            break
    else:
        raise ValueError(
            'Cannot find any space in the function declaration string.')
    func_name = func_name[pos + 1:]
    return func_name


def shortify(s, length=50):
    """
    Returns a shortified version of s
    """
    return '…' + s[-(length - 1):] if len(s) > length else s


def sliding_window(x, window_size=10, step_size=1):
    """
    Generate substrings by the sliding window algorithm

    Parameters
    -----
    x : str
        input string
    window_size : int
        window size (default: 10)
    step_size : int
        step size (default: 1)
    """
    n_chunks = (len(x) - window_size) / step_size + 1
    for i in range(0, int(n_chunks * step_size), step_size):
        yield x[i:i + window_size]


def merge_with_quotechar(S, dialect):
    """Merge quoted blocks in the abstraction

    This function takes the abstract representation and merges quoted blocks
    (``QC...CQ``) to a single cell (``C``). The function takes nested quotes
    into account.

    Parameters
    ----------
    S : str
        The data of a file as a string

    dialect : SimpleDialect
        The dialect used to make the abstraction.

    Returns
    -------
    abstraction : str
        A simplified version of the abstraction with quoted blocks merged.

    """
    in_quotes = False
    i = 0
    quote_pairs = []
    while i < len(S):
        s = S[i]
        if not s == 'Q':
            i += 1
            continue
        if not in_quotes:
            in_quotes = True
            begin_quotes = i
        elif i + 1 < len(S) and S[i + 1] == 'Q':
            i += 1
        else:
            end_quotes = i
            quote_pairs.append((begin_quotes, end_quotes))
            in_quotes = False
        i += 1
    Sl = list(S)
    for begin, end in quote_pairs:
        for i in range(begin, end + 1):
            Sl[i] = 'C'
    S = ''.join(Sl)
    return S


def gram_schmidt(data):
    """
    Calculate Gram-Schmidt orthogonalization parameters.
    """
    C = (data.real * data.imag).sum()
    R = (data.real * data.real).sum()
    idata = data.imag - C / R * data.real
    S = (idata * idata).sum()
    return R / S, -C / S


@classmethod
def _get_origin(cls):
    """Return list of Model names for origin Reference"""
    return [cls.__name__]


def _add_volumes(bold_file, bold_cut_file, skip_vols):
    """Prepend skip_vols from bold_file onto bold_cut_file."""
    import nibabel as nb
    import numpy as np
    from nipype.utils.filemanip import fname_presuffix
    if skip_vols == 0:
        return bold_cut_file
    bold_img = nb.load(bold_file)
    bold_cut_img = nb.load(bold_cut_file)
    bold_data = np.concatenate((bold_img.dataobj[(...), :skip_vols],
        bold_cut_img.dataobj), axis=3)
    out = fname_presuffix(bold_cut_file, suffix='_addnonsteady')
    bold_img.__class__(bold_data, bold_img.affine, bold_img.header
        ).to_filename(out)
    return out


def dict_to_sequence(d):
    """Returns an internal sequence dictionary update."""
    if hasattr(d, 'items'):
        d = d.items()
    return d


def g_id_neighbor_in_grid_index(g_id, grid_index, nb_mesh=1):
    """
    Return g_id neigbhor if exists in given grid index at a distance of n mesh
    """
    x_g_id, y_g_id = g_id
    x_min = x_g_id - nb_mesh
    x_max = x_g_id + nb_mesh + 1
    y_min = y_g_id - nb_mesh
    y_max = y_g_id + nb_mesh + 1
    for x_g_id in range(x_min, x_max):
        for y_g_id in range(y_min, y_max):
            neighbor_g_id = x_g_id, y_g_id
            if neighbor_g_id in grid_index['index']:
                yield neighbor_g_id


def __is_driver_section_header(tag):
    """
    Returns true if the given tag is a driver version section header.

    Keyword Args:
    tag -- The HTML tag to inspect
    """
    for child in tag.children:
        if '.xx driver' in child:
            return True
    return False


def getQuestions():
    """Return the questions for this part of the survey"""


def compress_column(col):
    """takes a dense matrix column and puts it into OP4 format"""
    packs = []
    n = 0
    i = 0
    packi = []
    while i < len(col):
        if col[i] == n + 1:
            packi.append(i)
            n += 1
        else:
            if packi:
                packs.append(packi)
            packi = [i]
            n = col[i]
        i += 1
    if packi:
        packs.append(packi)
    return packs


def rax_argument_spec():
    """Return standard base dictionary used for the argument_spec
    argument in AnsibleModule

    """
    return dict(api_key=dict(type='str', aliases=['password'], no_log=True),
        auth_endpoint=dict(type='str'), credentials=dict(type='path',
        aliases=['creds_file']), env=dict(type='str'), identity_type=dict(
        type='str', default='rackspace'), region=dict(type='str'),
        tenant_id=dict(type='str'), tenant_name=dict(type='str'), username=
        dict(type='str'), validate_certs=dict(type='bool', aliases=[
        'verify_ssl']))


def zeros_like(data=None, out=None, name=None, **kwargs):
    """Return an array of zeros with the same shape, type and storage type
    as the input array.

    The storage type of ``zeros_like`` output depends on the storage type of the input

    - zeros_like(row_sparse) = row_sparse
    - zeros_like(csr) = csr
    - zeros_like(default) = default

    Examples::

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

      zeros_like(x) = [[ 0.,  0.,  0.],
                       [ 0.,  0.,  0.]]

    Parameters
    ----------
    data : NDArray
        The input

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

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


def linear_function(a):
    """
    Defines a typical linear encoding / decoding function, essentially a
    pass-through function.

    Parameters
    ----------
    a : numeric or array_like
        Array to encode / decode.

    Returns
    -------
    numeric or ndarray
        Encoded / decoded array.

    Examples
    --------
    >>> linear_function(0.18)
    0.18
    """
    return a


def base_10_to_n(val: int):
    """Change a  to a base-n number.
    Up to base-36 is supported without special notation."""
    num_rep = {(0): 'a', (1): 'b', (2): 'c', (3): 'd', (4): 'e', (5): 'f',
        (6): 'g', (7): 'h', (8): 'i', (9): 'j', (10): 'k', (11): 'l', (12):
        'm', (13): 'n', (14): 'o', (15): 'p', (16): 'q', (17): 'r', (18):
        's', (19): 't', (20): 'u', (21): 'v', (22): 'w', (23): 'x', (24):
        'y', (25): 'z'}
    new_num_string = ''
    current = val
    if current == 0:
        return num_rep[0]
    while current != 0:
        remainder = current % 26
        remainder_string = num_rep[remainder]
        new_num_string = remainder_string + new_num_string
        current = current // 26
    return new_num_string


def file_basename(fp, **kwargs):
    """
    Return the basename of a file without folder location and extension
    """
    return fp.rpartition('/')[2].partition('.')[0]


def intersection_over_union(y_true, y_pred):
    """
    Intersection over union

    Parameters
    ----------
    y_true: numpy.ndarray
        Ground truth
    y_pred: numpy.ndarray
        Prediction

    Returns
    -------
    iou_score: float
        Intersection over union score

    """
    intersection = y_true & y_pred
    union = y_true | y_pred
    return intersection.sum() / union.sum()


def reformat_strand(input_value, format, case=False):
    """Converts common strand orientation formats.

    :param input_value: Value that will be edited.
    :type input_value: str, int
    :param format:
        Indicates how the value should be edited.
        Valid format types include:
        'fr_long' ('forward', 'reverse')
        'fr_short' ('f', 'r')
        'fr_abbrev1' ('for', 'rev')
        'fr_abbrev2' ('fwd', 'rev')
        'tb_long' ('top', 'bottom')
        'tb_short' ('t', 'b')
        'wc_long' ('watson', 'crick')
        'wc_short' ('w','c')
        'operator' ('+', '-')
        'numeric' (1, -1).
    :type format: str
    :param case:
        Indicates whether the output value should be capitalized.
    :type case: bool
    :returns: The re-formatted value as indicated by 'format'.
    :rtype: str, int
    """
    format_dict = {'fr_long': ['forward', 'reverse'], 'fr_short': ['f', 'r'
        ], 'fr_abbrev1': ['for', 'rev'], 'fr_abbrev2': ['fwd', 'rev'],
        'tb_long': ['top', 'bottom'], 'tb_short': ['t', 'b'], 'wc_long': [
        'watson', 'crick'], 'wc_short': ['w', 'c'], 'operator': ['+', '-'],
        'numeric': [1, -1]}
    strand1_values = set()
    strand2_values = set()
    for values in format_dict.values():
        strand1_values.add(values[0])
        strand2_values.add(values[1])
    if format in format_dict.keys():
        if isinstance(input_value, str):
            new_value = input_value.lower()
        else:
            new_value = input_value
        if new_value in strand1_values:
            new_value = format_dict[format][0]
        elif new_value in strand2_values:
            new_value = format_dict[format][1]
        else:
            new_value = 'NA'
    else:
        new_value = 'NA'
    if isinstance(new_value, str):
        if case == True:
            new_value = new_value.capitalize()
    return new_value


@classmethod
def addnstr(cls, s, x=None, y=None, n=None, attr=None):
    """
        write at most n characters at specified position or cursor.

        :param s: string to write
        :param x: optional x value
        :param y: optional y value
        :param n: max number of characters
        :param attr: optional attributes
        """
    x, y = cls._fix_xy(x, y)
    attr = cls._fix_attr(attr)
    n = cls.WIDTH if n is None else n
    if attr is None:
        return cls.WINDOW.addnstr(y, x, s, n)
    else:
        return cls.WINDOW.addnstr(y, x, s, n, attr)


@staticmethod
def p_page_optional_parameter_list(p):
    """page_optional_parameter_list : page_optional_parameter
                                        | page_optional_parameter page_optional_parameter_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def to_bytes(seq):
    """convert a sequence to a bytes type"""
    if isinstance(seq, bytes):
        return seq
    elif isinstance(seq, bytearray):
        return bytes(seq)
    elif isinstance(seq, memoryview):
        return seq.tobytes()
    elif isinstance(seq, str):
        raise TypeError(
            'unicode strings are not supported, please encode to bytes: {!r}'
            .format(seq))
    else:
        return bytes(bytearray(seq))


def ensure_var_or_dot(formula_term):
    """
    Ensure that a non specified formula term is transformed into a dot.
    """
    return formula_term if formula_term else '.'


def get_role_name(account_id, role):
    """Shortcut to insert the `account_id` and `role` into the iam string."""
    return 'arn:aws:iam::{0}:role/{1}'.format(account_id, role)


def truncate_string(input_string, character_limit):
    """
    Used to truncate a string to ensure it may be imported into database
    :param input_string: string to be truncated
    :type input_string: str
    :param character_limit: the maximum number of allowed characters
    :type character_limit: int
    :return: truncated string (removing the trailing characters)
    :rtype: str
    """
    if len(input_string) > character_limit:
        return input_string[0:character_limit - 1]
    return input_string


def obtener_datos_junta(df, n_junta):
    """
    Obtener una fila según el número de junta
    :param df: Dataframe resultado de leer actas.csv
    :param n_junta: número de junta
    :return: lista con los datos de la junta
    """
    return [n_junta] + df.loc[n_junta].values.tolist()


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

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


def choose_positions_to_merge(main_list, position_shift):
    """
    >>> choose_positions_to_merge([0 ,1, 2, 5, 8, 9, 10, 11, 12, 20, 33, 34], 1)
    ([0, 2, 5, 8, 10, 12, 20, 33], [1, 9, 11, 34])

    >>> choose_positions_to_merge([0], 1)
    ([0], [])
    """
    result_main = []
    result_disappearing = []
    i = 0
    while i < len(main_list) - 1:
        result_main.append(main_list[i])
        if main_list[i] + position_shift == main_list[i + 1]:
            result_disappearing.append(main_list[i + 1])
            i += 1
        i += 1
    if i == len(main_list) - 1:
        result_main.append(main_list[i])
    return result_main, result_disappearing


def is_number(string):
    """String is a number."""
    try:
        float(string)
        return True
    except ValueError:
        return False


def Required(field, dictionary):
    """
    When added to a list of validations
    for a dictionary key indicates that
    the key must be present. This
    should not be called, just inserted
    into the list of validations.
    # Example:
        validations = {
            "field": [Required, Equals(2)]
        }
    By default, keys are considered
    optional and their validations
    will just be ignored if the field
    is not present in the dictionary
    in question.
    """
    return field in dictionary


def _get_reporoot():
    """Returns the absolute path to the repo root directory on the current
    system.
    """
    from os import path
    import aflow
    apath = path.abspath(aflow.__file__)
    return path.dirname(path.dirname(apath))


def objects(daterange=None):
    """ Returns a list of all contained time entries
        """


def has_children(tree):
    """Return true if this tree has any child.
    """
    return len(tree.children) > 0


def acceleration_to_dxl(value, model):
    """Converts from degrees/second^2 to ticks"""
    return int(round(value / 8.583, 0))


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

        :param DeviceDeleteOnUnlinkFailType val:
        :rtype: EventType
        """
    return cls('device_delete_on_unlink_fail', val)


def index_report(df, label='', time_fmt='%Y-%m-%d %T', return_index_dict=False
    ):
    """Sorts dataframe index, prints index's start and end points and its datetime frequency.
    if return_index_dict=True then it returns these values in a dictionary as well as printing them."""
    import pandas as pd
    df.sort_index(inplace=True)
    index_info = {'index_start': df.index[0].strftime(time_fmt),
        'index_end': df.index[-1].strftime(time_fmt), 'index_freq': df.
        index.freq}
    if df.index.freq is None:
        try:
            index_info['inferred_index_freq'] = pd.infer_freq(df.index)
        except:
            index_info['inferred_index_freq'] = 'error'
    dashes = '---' * 20
    print(dashes)
    print(f'\tINDEX REPORT:\t{label}')
    print(dashes)
    print(
        f"""* Index Endpoints:
	{df.index[0].strftime(time_fmt)} -- to -- {df.index[-1].strftime(time_fmt)}"""
        )
    print(f'* Index Freq:\n\t{df.index.freq}')
    if return_index_dict == True:
        return index_info
    else:
        return


def template_substitute(text, **kwargs):
    """
    Replace placeholders in text by using the data mapping.
    Other placeholders that is not represented by data is left untouched.

    :param text:   Text to search and replace placeholders.
    :param data:   Data mapping/dict for placeholder key and values.
    :return: Potentially modified text with replaced placeholders.
    """
    for name, value in kwargs.items():
        placeholder_pattern = '{%s}' % name
        if placeholder_pattern in text:
            text = text.replace(placeholder_pattern, value)
    return text


def defaultpagerenv():
    """return a dict of default environment variables and their values,
    intended to be set before starting a pager.
    """
    return {b'LESS': b'FRX', b'LV': b'-c'}


@staticmethod
def p_ref_measurement_optional_list(p):
    """ref_measurement_optional_list : ref_measurement_optional
                                         | ref_measurement_optional ref_measurement_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def _get_marker_param(params):
    """Extract marker id from request's dictionary (defaults to None)."""
    return params.pop('marker', None)


def full_name(func):
    """Return full name of `func` by adding the module and function name."""
    try:
        name = func.__qualname__
    except AttributeError:
        name = func.__name__
    return func.__module__ + '.' + name


def setup_forceview(ax):
    """Builds the total force visualisation pane.

    Parameters
    ----------
    ax: Axes object
        The axes position that the pane should be placed in.
    """
    ax.plot([0], color='#34a5daff')
    ax.set_ylabel('Force/N', fontsize=16)
    ax.set_xlabel('Time/s', fontsize=16)


def _database_to_isoformat(datetimeobj):
    """Return a xs:dateTime parsable string from datatime."""
    return datetimeobj.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'


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 get_par_box(domain, last=False):
    """ Returns the bounding box of the surface parametric domain in ccw direction.

    :param domain: parametric domain
    :type domain: list, tuple
    :param last: if True, adds the first vertex to the end of the return list
    :type last: bool
    :return: edges of the parametric domain
    :rtype: tuple
    """
    u_range = domain[0]
    v_range = domain[1]
    verts = [(u_range[0], v_range[0]), (u_range[1], v_range[0]), (u_range[1
        ], v_range[1]), (u_range[0], v_range[1])]
    if last:
        verts.append(verts[0])
    return tuple(verts)


def integerize(num, count):
    """Calculate and return integer value if result is integer"""
    calc = num * count
    calc = int(calc) if calc.is_integer() else calc
    return calc


@classmethod
def init_manual(cls, pawn_value, knight_value, bishop_value, rook_value,
    queen_value, king_value):
    """
        Manual init method for external piece values

        :type: PAWN_VALUE: int
        :type: KNIGHT_VALUE: int
        :type: BISHOP_VALUE: int
        :type: ROOK_VALUE: int
        :type: QUEEN_VALUE: int
        """
    piece_values = cls()
    piece_values.PAWN_VALUE = pawn_value
    piece_values.KNIGHT_VALUE = knight_value
    piece_values.BISHOP_VALUE = bishop_value
    piece_values.ROOK_VALUE = rook_value
    piece_values.QUEEN_VALUE = queen_value
    piece_values.KING_VALUE = king_value
    return piece_values


def tag(tag):
    """Select a single tag."""
    return {'tag': tag}


def dequote(s):
    """
    If a string has single or double quotes around it, remove them.
    Make sure the pair of quotes match.
    If a matching pair of quotes is not found, return the string unchanged.
    """
    if s[0] == s[-1] and s.startswith(("'", '"')):
        return s[1:-1]
    return s


def multi_split(s, seps):
    """Does a string split for multiple separators, and removes any blanks
    :param s: input string to parse
    :param seps: separators to use - the order of these matter
    """
    res = [s]
    for sep in seps:
        s, res = res, []
        for seq in s:
            res += seq.split(sep)
    for i in res:
        if not i:
            res.pop(res.index(i))
    return res


def isInitialMessage():
    """Returns a boolean indicating whether this is the first message in
           a thread"""


def default_func(*pargs, **_):
    """
    As a placeholder function, it works like lambda x: x.
    As a method of a class, it returns cls or self.
    :param pargs: positional arguments
    :param _: keyword arguments, ignored
    :return: 1st positional arguments
    """
    return pargs[0]


def dict_to_ordered_list(data):
    """Get extra as ordered list.

    Actually, I'm not sure whether I should or should not be using
    ``OrderedDict`` here.

    :param dict data:
    :return list:
    """
    items = list(data.items())
    items.sort()
    return items


@staticmethod
def format_request(method, url, *args, **kwargs):
    """
        Formats the payload from the module, into a payload the API handler can use.

        :param url: Connection URL to access
        :type url: string
        :param method: The preferred API Request method (GET, ADD, POST, etc....)
        :type method: basestring
        :param kwargs: The payload dictionary from the module to be converted.

        :return: Properly formatted dictionary payload for API Request via Connection Plugin.
        :rtype: dict
        """
    params = [{'url': url}]
    if args:
        for arg in args:
            params[0].update(arg)
    if kwargs:
        keylist = list(kwargs)
        for k in keylist:
            kwargs[k.replace('__', '-')] = kwargs.pop(k)
        if method == 'get' or method == 'clone':
            params[0].update(kwargs)
        elif kwargs.get('data', False):
            params[0]['data'] = kwargs['data']
        else:
            params[0]['data'] = kwargs
    return params


def extract_some_key_val(dct, keys):
    """
    Gets a sub-set of a :py:obj:`dict`.

    :param dct: Source dictionary.
    :type dct: :py:obj:`dict`

    :param keys: List of subset keys, which to extract from ``dct``.
    :type keys: :py:obj:`list` or any iterable.

    :rtype: :py:obj:`dict`
    """
    edct = {}
    for k in keys:
        v = dct.get(k, None)
        if v is not None:
            edct[k] = v
    return edct


def __init__(config, rrset_channel, metrics=None):
    """Initialize an Authority Plugin client."""


def usage():
    """ Print a help menu to the screen, if the user enters a bad command line flag.

    Returns: None
    """
    print(__doc__)
    exit()


def wrap(value):
    """Return *value* as a list.

    Reader._parse(elem, unwrap=True) returns single children of *elem* as bare
    objects. wrap() ensures they are a list.
    """
    return value if isinstance(value, list) else [value]


def upgradeObservations(context, logger):
    """ check if any observation has old country assignments
    """
    COUNTRIES = {'au': 'at', 'cr': 'hr', 'et': 'ee', 'sv': 'sk'}
    brains = context.portal_catalog.unrestrictedSearchResults(portal_type=
        'Observation', Country=COUNTRIES.keys())
    for brain in brains:
        observation = brain.getObject()
        old = observation.country
        new = COUNTRIES.get(old)
        observation.country = new
        logger.info('Country set for %s (%s -> %s)' % (observation.id, old,
            new))


def two_sum(a, b):
    """
    Add ``a`` and ``b`` exactly, returning the result as two float64s.
    The first is the approximate sum (with some floating point error)
    and the second is the error of the float64 sum.

    Using the procedure of Shewchuk, 1997,
    Discrete & Computational Geometry 18(3):305-363
    http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf

    Returns
    -------
    sum, err : float64
        Approximate sum of a + b and the exact floating point error
    """
    x = a + b
    eb = x - a
    ea = x - eb
    eb = b - eb
    ea = a - ea
    return x, ea + eb


@classmethod
def model_path(cls):
    """Get the path to fastai pretrained models in the config file."""
    return cls.get_path('model_path')


def is_ipxe_enabled(task):
    """Return true if ipxe is set.

    :param task: A TaskManager object
    :returns: boolean true if ``[pxe]ipxe_enabled`` is configured
              or if the task driver instance is the iPXE driver.
    """
    return 'ipxe_boot' in task.driver.boot.capabilities


@classmethod
def _get_version(cls):
    """Return VCS program version."""
    return cls._popen(['svn', '--version'], merge_err=False).split()[2]


def interleave(inter, f, seq):
    """Call f on each item in seq, calling inter() in between.
    """
    seq = iter(seq)
    try:
        f(next(seq))
    except StopIteration:
        pass
    else:
        for x in seq:
            inter()
            f(x)


def get_project_requests(gl, project_id, request_state):
    """ Get Project's Merge Requests
    :param gl: GitLab Object Instance
    :param project_id: Project Identifier (int)
    :param request_state: Optional Type Identifier (string)
    :return: Merge Requests (List)
    """
    return False


@classmethod
def geom_col_name(cls):
    """
        Return the name of the metadata column used to store the feature
        geometry column.
        """
    return 'f_geometry_column'


@classmethod
def generate(cls, group, seed=None, fact=None, *args):
    """Generate and return a new key"""
    key = group.generate_one_key(cls, seed, fact, *args)
    return key


@classmethod
def _norm_ident(cls, ident):
    """
        helper which normalizes & validates 'ident' value.
        """
    assert ident is not None
    if isinstance(ident, bytes):
        ident = ident.decode('ascii')
    iv = cls.ident_values
    if ident in iv:
        return ident
    ia = cls.ident_aliases
    if ia:
        try:
            value = ia[ident]
        except KeyError:
            pass
        else:
            if value in iv:
                return value
    raise ValueError('invalid ident: %r' % (ident,))


def is_classifier(estimator):
    """Returns True if the given estimator is (probably) a classifier.
    Parameters
    ----------
    estimator : object
        Estimator object to test.
    Returns
    -------
    out : bool
        True if estimator is a classifier and False otherwise.
    """
    return getattr(estimator, '_estimator_type', None) == 'classifier'


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


@classmethod
def parametrize(cls, **parameters):
    """Return a clone of this class with the given args in the common.

        Use this method (or its syntactic sugar 'params') to pass values to
        components under a flow.
        """
    new_common = cls.common.copy()
    new_common.update(**parameters)
    class_name = new_common.get('name', cls.__name__)
    return type(class_name, (cls,), {'common': new_common, '__doc__': cls.
        __doc__})


def shape(tensor, dim=None):
    """Get tensor shape/dimension as list/int"""
    if dim is None:
        return tensor.shape.as_list()
    else:
        return tensor.shape.as_list()[dim]


def linear_force(params, t, force):
    """
    Calculation of the residual to perform linear fit on a function forcing its intercept to be at the origin

    This auxiliary function returns the residual which is passed to the main wrap around fitting function: linear_fit_nob

    Parameters:
    ----------
    params :  numpy.ndarray
        parameters defined by the non-linear optimization wrap around function: nls_fit
    t : numpy.ndarray
        independent variable (generally time trace)
    force : numpy.ndarray
        dependent variable (generally force trace)

    Returns:
    ----------
    (model - force) : numpy.ndarray
        residual calculated to be passed to the optimization function: linear_fit_nob
    """
    p = params.valuesdict()
    A = p['A']
    model = A * t
    return model - force


def count_from_1(index, collection):
    """Numbering function: consecutive integers starting at 1."""
    return index + 1


def read_msa(path):
    """ read original msa

    Parameter
    =========
    path : string
        path to the MSA file

    Return
    ======
    result : dict
        the dictionary containing the protein sequence without characters linked
        to MSA
    """
    result = {}
    with open(path) as inf:
        for line in inf:
            if line[0] == '\n':
                continue
            if line[0] == '>':
                tmp = line[1:-1].split()
                name = tmp[0]
                result[name] = ''
            else:
                result[name] += line.rstrip().replace('-', '')
    return result


def from_base(base, num):
    """Decode a big-endian iterable of digits in the given base to a single
    positive integer.
    """
    out = 0
    for digit in num:
        if digit >= base or digit < 0:
            raise ValueError('invalid digit: %i' % digit)
        out *= base
        out += digit
    return out


def sliding_window(a, window=3, step=1, axis=0):
    """Sliding window across an array.

    :param a: input array.
    :param window: window length.
    :param step: step length between consecutive windows.
    :param axis: axis over which to apply window.

    :yields: windows of the input array.
    """
    slicee = [slice(None)] * a.ndim
    end = 0
    for start in range(0, a.shape[axis] - window + 1, step):
        end = start + window
        slicee[axis] = slice(start, end)
        yield a[tuple(slicee)]
    if a.shape[axis] > end:
        start = a.shape[axis] - window
        slicee[axis] = slice(start, a.shape[axis])
        yield a[tuple(slicee)]


@classmethod
def simplify_form(cls, form: str) ->str:
    """
        TODO: figure out what transformation is needed
        :param form:
        :return:
        """
    return form.lower()


def Mag2Counts(mag, mzero):
    """
    Convert magnitude to counts.

    Parameters
    ----------
    mag : magnitude [mag]

    mzero : magnitude zero point [counts]

    Returns
    -------
    counts : counts [counts]
    """
    exp = (mzero - mag) / 2.5
    counts = 10 ** exp
    return counts


def _get_derivation_order(fnc):
    """
    Returns derivation order of function according to place in integrator chain.
    """
    from .splines import Spline
    if fnc.__func__ == Spline.f:
        return 0
    elif fnc.__func__ == Spline.df:
        return 1
    elif fnc.__func__ == Spline.ddf:
        return 2
    elif fnc.__func__ == Spline.dddf:
        return 3
    else:
        raise ValueError()


def get_value_unit(value, unit, prefix):
    """
    Return a human-readable value with unit specification. Try to
    transform the unit prefix to the one passed as parameter. When
    transform to higher prefix apply nearest integer round.
    """
    prefixes = '', 'K', 'M', 'G', 'T'
    if len(unit):
        if unit[:1] in prefixes:
            valprefix = unit[0]
            unit = unit[1:]
        else:
            valprefix = ''
    else:
        valprefix = ''
    while valprefix != prefix:
        uidx = prefixes.index(valprefix)
        if uidx > prefixes.index(prefix):
            value *= 1024
            valprefix = prefixes[uidx - 1]
        else:
            if value < 10240:
                return value, '{0}{1}'.format(valprefix, unit)
            value = int(round(value / 1024.0))
            valprefix = prefixes[uidx + 1]
    return value, '{0}{1}'.format(valprefix, unit)


def write_shadow_surface(s, xx, yy, outFile='presurface.dat'):
    """
      write_shadowSurface: writes a mesh in the SHADOW/presurface format
      SYNTAX:
           out = write_shadowSurface(z,x,y,outFile=outFile)
      INPUTS:
           z - 2D array of heights
           x - 1D array of spatial coordinates along mirror width.
           y - 1D array of spatial coordinates along mirror length.

      OUTPUTS:
           out - 1=Success, 0=Failure
           outFile - output file in SHADOW format. If undefined, the
                     file is names "presurface.dat"

    """
    out = 1
    try:
        fs = open(outFile, 'w')
    except IOError:
        out = 0
        print("Error: can't open file: " + outFile)
        return
    else:
        fs.write(repr(xx.size) + ' ' + repr(yy.size) + ' \n')
        for i in range(yy.size):
            fs.write(' ' + repr(yy[i]))
        fs.write('\n')
        for i in range(xx.size):
            tmps = ''
            for j in range(yy.size):
                tmps = tmps + '  ' + repr(s[j, i])
            fs.write(' ' + repr(xx[i]) + ' ' + tmps)
            fs.write('\n')
        fs.close()
        print('write_shadow_surface: File for SHADOW ' + outFile +
            ' written to disk.')


def pytest_xdist_rsyncfinish(source, gateways):
    """ called after rsyncing a directory to remote gateways takes place. """


def bluetoothValidate(address):
    """ Returns True if the string argument appears to be a Bluetooth address (strictly speaking, a MAC address)

        arguments:
        address - string MAC address

        returns:
        boolean - True if it appears to be a bluetooth address, otherwise false
    """
    import re
    validMAC = re.compile('^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$')
    if validMAC.match(address):
        return True
    else:
        return False


def _compute_phi_ss(C, mag, c1_dists, log_phi_ss, mean_phi_ss):
    """
    Returns the embeded logic tree for single station sigma
    as defined to be used in the Swiss Hazard Model 2014:
    the single station sigma branching levels combines with equal
    weights: the phi_ss reported as function of magnitude
    as proposed by Rodriguez-Marek et al (2013) with the mean
    (mean_phi_ss) single station value;
    the resulted phi_ss is in natural logarithm units
    """
    phi_ss = 0
    if mag < C['Mc1']:
        phi_ss = c1_dists
    elif mag >= C['Mc1'] and mag <= C['Mc2']:
        phi_ss = c1_dists + (C['C2'] - c1_dists) * ((mag - C['Mc1']) / (C[
            'Mc2'] - C['Mc1']))
    elif mag > C['Mc2']:
        phi_ss = C['C2']
    return (phi_ss * 0.5 + mean_phi_ss * 0.5) / log_phi_ss


def get_pairs(word):
    """Return set of symbol pairs in a word.

    Word is represented as tuple of symbols (symbols being variable-length strings).
    """
    pairs = set()
    prev_char = word[0]
    for char in word[1:]:
        pairs.add((prev_char, char))
        prev_char = char
    return pairs


@classmethod
def debug(cls, message):
    """ Display debug message if verbose level allows it. """
    if cls.verbose > 1:
        msg = '[DEBUG] %s' % message
        cls.echo(msg)


def __len__():
    """
        Return the number of status conditions.
        """


def set_use_gpu(v: bool):
    """
        Set whether to use CUDA or not.
    """
    global use_gpu
    use_gpu = v


def bit_size(num):
    """
    Number of bits needed to represent a integer excluding any prefix
    0 bits.

    Usage::

        >>> bit_size(1023)
        10
        >>> bit_size(1024)
        11
        >>> bit_size(1025)
        11

    :param num:
        Integer value. If num is 0, returns 0. Only the absolute value of the
        number is considered. Therefore, signed integers will be abs(num)
        before the number's bit length is determined.
    :returns:
        Returns the number of bits in the integer.
    """
    try:
        return num.bit_length()
    except AttributeError:
        raise TypeError('bit_size(num) only supports integers, not %r' %
            type(num))


def t_OPEN_TAG(t):
    """<[?%](([Pp][Hh][Pp][ \\t\\r\\n]?)|=)?"""
    if '=' in t.value:
        t.type = 'OPEN_TAG_WITH_ECHO'
    t.lexer.lineno += t.value.count('\n')
    t.lexer.begin('php')
    return t


def _get_object_id(obj):
    """
    Gets the ID for an API object.

    :param obj:
        The API object
    :type obj:
        `dict`
    :return:
    """
    return obj.get('id', None)


def chunk_sequence(sequence, chunk_length):
    """Yield successive n-sized chunks from l."""
    for index in range(0, len(sequence), chunk_length):
        yield sequence[index:index + chunk_length]


def shift_series(s):
    """Produces a copy of the provided series shifted by one, starting with 0."""
    s0 = s.copy()
    s0 = s0.shift(1)
    s0.iloc[0] = 0.0
    return s0


def _outter_split(inpt, delim, openers, closers=None, opener_lookup=None):
    """Splits only at delims that are at outter-most level regarding
    openers/closers pairs.
    Unchecked requirements:
    Only supports length-1 delim, openers and closers.
    delim must not be member of openers or closers.
    len(openers) == len(closers) or closers == None
    """
    if closers is None:
        closers = openers
    if opener_lookup is None:
        opener_lookup = {}
        for i in range(len(openers)):
            opener_lookup[openers[i]] = i
    stack = []
    res = []
    splt = 0
    for i in range(len(inpt)):
        if inpt[i] == delim and len(stack) == 0:
            res.append(inpt[splt:i].strip())
            splt = i + 1
        elif inpt[i] in opener_lookup:
            stack.append(opener_lookup[inpt[i]])
        elif len(stack) > 0 and inpt[i] == closers[stack[-1]]:
            stack.pop()
    res.append(inpt[splt:].strip())
    return res


def vertical_spacing(spaces=1):
    """
        I could just overwrite the automatic newline builtin.
        But the code looks unclean so screw it.
    """
    for _ in range(0, spaces):
        print()


def PC_AC1_calc(P, TOP, POP):
    """
    Calculate percent chance agreement for Gwet's AC1.

    :param P: condition positive
    :type P : dict
    :param TOP: test outcome positive
    :type TOP : dict
    :param POP: population
    :type POP:dict
    :return: percent chance agreement as float
    """
    try:
        result = 0
        classes = list(P.keys())
        for i in classes:
            pi = (P[i] + TOP[i]) / (2 * POP[i])
            result += pi * (1 - pi)
        result = result / (len(classes) - 1)
        return result
    except Exception:
        return 'None'


def open(mode='r'):
    """
        Opens this file path with the given mode.

        @return: a file-like object.
        @raise Exception: if this file path cannot be opened.
        """


def parse_yr_filter(dt_df, years, label):
    """
    Parse string year filter and apply it to datetime-indexed
    DataFrame.

    Arguments:
        dt_df (:obj:`pandas.DataFrame`): datetime-indexed DataFrame
        years (str or int): years to select, e.g. 2015 or 2000-2010
        label (str): identifier to print warning message if ``years``
            filter partially overlaps with actual date index

    Returns:

        ret (tuple of (:obj:`pandas.DataFrame`, str)): first element is
            input DataFrame ``dt_df`` indexed to ``years`` filter,
            second element is string of year range, e.g. '2001_2011'

    Example:

        >>> df = pd.DataFrame(index=pd.date_range('2000', '2015'))
        >>> df, yr_str = parse_yr_filter(df, '1998-2002', 'station1')
        WARNING: data for station1 starts in 2000 but you gave 1998
        Years used will only include 2000 to 2002

        Now df will only contain indices with dates between 2000 and
        2002 and

        >>> yr_str
        '1998_2002'

    Raises:
        ValueError: if ``years`` is invalid or not found
            in time series index of DataFrame.

    """
    err_msg = '{} is not a valid years option,\n'.format(years
        ), 'use single or range e.g. 2015 or 2000-2010'
    if years == 'all':
        year_str = 'all_yrs'
    else:
        try:
            if years and isinstance(years, str) and '-' in years:
                start, end = years.strip().split('-')
                year_str = '{}_{}'.format(start, end)
                data_start = start
                data_end = end
                dt_df = dt_df.loc[start:end]
                if not start in dt_df.index:
                    data_start = dt_df.index.year.min()
                    print('WARNING: data for {l} starts in {d}'.format(l=
                        label, d=data_start) + ' but you gave {s}'.format(s
                        =start))
                if not end in dt_df.index:
                    data_end = dt_df.index.year.max()
                    print('WARNING: data for {l} ends in {d}'.format(l=
                        label, d=data_end) + ' but you gave {e}'.format(e=end))
                if data_start != start or data_end != end:
                    print('Years used will only include {} to {}'.format(
                        data_start, data_end))
            else:
                year_str = str(int(years))
                if not len(year_str) == 4:
                    raise ValueError(err_msg)
                if not years in dt_df.index:
                    print('WARNING:', label, 'is missing data', 'for year:',
                        years)
                    data_start = dt_df.index.year.min()
                    data_end = dt_df.index.year.max()
                    print('Years used will only include {} to {}'.format(
                        data_start, data_end))
                else:
                    dt_df = dt_df.loc[years]
        except:
            raise ValueError(err_msg)
    ret = dt_df, year_str
    return ret


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

        :param SsoRemoveLogoutUrlDetails val:
        :rtype: EventDetails
        """
    return cls('sso_remove_logout_url_details', val)


@conf
def find_xlc(conf):
    """
	Detects the Aix C compiler
	"""
    cc = conf.find_program(['xlc_r', 'xlc'], var='CC')
    conf.get_xlc_version(cc)
    conf.env.CC_NAME = 'xlc'


def find():
    """Find specified text

    """
    pass


def run_script(script_name, namespace):
    """Execute the named script in the supplied namespace dictionary"""


def module_to_str(obj):
    """
    Return the string representation of *obj*'s ``__module__`` attribute, or
    an empty string if there is no such attribute.
    """
    if hasattr(obj, '__module__'):
        return str(obj.__module__)
    else:
        return ''


def _on_message_simple(client, userdata, message):
    """Internal callback"""
    if userdata['msg_count'] == 0:
        return
    if message.retain and not userdata['retained']:
        return
    userdata['msg_count'] = userdata['msg_count'] - 1
    if userdata['messages'] is None and userdata['msg_count'] == 0:
        userdata['messages'] = message
        client.disconnect()
        return
    userdata['messages'].append(message)
    if userdata['msg_count'] == 0:
        client.disconnect()


@staticmethod
def p_formula_optional_list(p):
    """formula_optional_list : formula_optional
                                 | formula_optional formula_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def get_log_from_input():
    """
    If an application is invoked without any arguments,
    the data for a log is retrieved through an interactive session.
    """
    while True:
        minutes = input(
            'Enter the working time (in minutes, Ctrl-C for cancel): ').strip()
        if not minutes.isdigit():
            print('No minutes have been entered. Try once more...')
            continue
        comment = input('Comment on the entry: ') or None
        print('Data was successfully added: Minutes - {}, Comment - {}'.
            format(minutes, comment))
        return [minutes, comment]


def obsolete_validator(status):
    """Check if current entry is obsolete."""
    return not status.entry.obsolete


def get_pub_id(title, authors, year):
    """construct publication id"""
    if len(title.split(' ')) > 1 and title.split(' ')[0].lower() in ['the', 'a'
        ]:
        _first_word = title.split(' ')[1].split('_')[0]
    else:
        _first_word = title.split(' ')[0].split('_')[0]
    pub_id = authors[0].split(',')[0].split(' ')[0] + _first_word + str(year)
    return pub_id


def predicative(adjective):
    """ Returns the predicative adjective (lowercase): belles => beau.
    """
    w = adjective.lower()
    if w.endswith(('ais', 'ois')):
        return w
    if w.endswith(('és', 'ée', 'ées')):
        return w.rstrip('es')
    if w.endswith(('que', 'ques')):
        return w.rstrip('s')
    if w.endswith(('nts', 'nte', 'ntes')):
        return w.rstrip('es')
    if w.endswith('eaux'):
        return w.rstrip('x')
    if w.endswith(('aux', 'ale', 'ales')):
        return w.rstrip('uxles') + 'l'
    if w.endswith(('rteuse', 'rteuses', 'ailleuse')):
        return w.rstrip('es') + 'r'
    if w.endswith(('euse', 'euses')):
        return w.rstrip('es') + 'x'
    if w.endswith(('els', 'elle', 'elles')):
        return w.rstrip('les') + 'el'
    if w.endswith(('ifs', 'ive', 'ives')):
        return w.rstrip('es')[:-2] + 'if'
    if w.endswith(('is', 'ie', 'ies')):
        return w.rstrip('es')
    if w.endswith(('enne', 'ennes')):
        return w.rstrip('nes') + 'en'
    if w.endswith(('onne', 'onnes')):
        return w.rstrip('nes') + 'n'
    if w.endswith(('igne', 'ignes', 'ingue', 'ingues')):
        return w.rstrip('s')
    if w.endswith(('ène', 'ènes')):
        return w.rstrip('s')
    if w.endswith(('ns', 'ne', 'nes')):
        return w.rstrip('es')
    if w.endswith(('ite', 'ites')):
        return w.rstrip('es')
    if w.endswith(('is', 'ise', 'ises')):
        return w.rstrip('es') + 's'
    if w.endswith(('rice', 'rices')):
        return w.rstrip('rices') + 'eur'
    if w.endswith(('iers', 'ière', 'ières')):
        return w.rstrip('es')[:-3] + 'ier'
    if w.endswith(('ette', 'ettes')):
        return w.rstrip('tes') + 'et'
    if w.endswith(('rds', 'rde', 'rdes')):
        return w.rstrip('es')
    if w.endswith(('nds', 'nde', 'ndes')):
        return w.rstrip('es')
    if w.endswith(('us', 'ue', 'ues')):
        return w.rstrip('es')
    return w.rstrip('s')


@classmethod
def detect(cls, old_config, new_config):
    """Detect if commit hash in `new_config` differs from `old_config`"""
    old_hash_commit = old_config['metadata'].get('VCS', None)
    new_hash_commit = new_config['metadata'].get('VCS')
    if new_hash_commit and old_hash_commit != new_hash_commit:
        yield cls(old_config, new_config)


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

        :param TeamMergeRequestAcceptedShownToSecondaryTeamDetails val:
        :rtype: EventDetails
        """
    return cls('team_merge_request_accepted_shown_to_secondary_team_details',
        val)


def timedelta(old, new):
    """Get timedelta between timepoints.

    Parameters
    ----------
    old : pd.DataFrame
        This is the older dataframe.
    new : pd.DataFrame
        This is the newer dataframe.

    Returns
    -------
    pd.Series
        The content will be timedelta values. Look into numpy for more options.

    """
    old = old.reset_index()
    old = old.set_index('Subject ID')
    new = new.reset_index()
    new = new.set_index('Subject ID')
    timedeltas = old['SCANDATE'] - new['SCANDATE']
    return timedeltas


def vis_mat(img, ax=None):
    """Visualize a density map image.

    Args:
        img (~numpy.ndarray): An array of shape :math:`(height, width)`.
            This is a density map and the range of its value is :math:`[-inf, inf]`.
        ax: (matplotlib.axes.Axis): The vis_tools is displayed on this
            axis. If this is :obj:`None` (default), a new axis is created.

    Returns:
         ~matploblib.axes.Axes:
        Returns the Axes object with the plot for further tweaking.
    """
    from matplotlib import pyplot as plt
    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
    ax.matshow(img)
    return ax


def avroTypeToSchema(avroType):
    """Convert a titus.datatype.AvroType into an Avro schema.

    :type avroType: titus.datatype.AvroType
    :param avroType: AvroType object
    :rtype: avro.schema.Schema
    :return: schema object for the Avro library
    """
    return avroType.schema


@classmethod
def detect(cls, old_config, new_config):
    """Detect if algorithm definition in `new_config` differs from `old_config`"""
    if old_config['algorithms'] != new_config['algorithms']:
        yield cls(old_config, new_config)


@classmethod
def natural_key_fields(cls):
    """
        Digest is used as a natural key for PackageLangpacks.
        """
    return 'digest',


def recherche_dichotomique(li, c):
    """
    Effectue une recherche dichotomique.

    @param  li      tableau
    @param  c       élément à chercher
    @return         position

    .. exref::
        :tag: Base
        :title: recherche dichotomique

        La `recherche dichotomique <http://fr.wikipedia.org/wiki/Dichotomie>`_
        est plus rapide qu'une recherche classique mais elle
        suppose que celle-ci s'effectue dans un ensemble trié.
        L'idée est de couper en deux l'intervalle de recherche à chaque itération.
        Comme l'ensemble est trié, en comparant l'élément cherché à l'élément central,
        on peut éliminer une partie de l'ensemble : la moitié inférieure ou supérieure.

        .. runpython::
            :showcode:

            def recherche_dichotomique(li, c) :
                a, b = 0, len (li)-1
                while a <= b :
                    m = (a + b)//2
                    if   c == li[m]: return m
                    elif c <  li[m]: b = m-1
                    else           : a = m+1
                return -1

            print(recherche_dichotomique([0, 2, 5, 7, 8], 7))
    """
    a, b = 0, len(li) - 1
    while a <= b:
        m = (a + b) // 2
        if c == li[m]:
            return m
        elif c < li[m]:
            b = m - 1
        else:
            a = m + 1
    return -1


def bookmark_toggle():
    """Toggle bookmarks display

    """
    pass


def arccosh(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns the element-wise inverse hyperbolic cosine of the input array, \\
    computed element-wise.

    The storage type of ``arccosh`` output is always dense

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

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

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

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


def defaultExpireAuthCookie(resp, cookie_name):
    """Expire the cookie"""


def _set_daily_ward_vaccination_capacity(params, name: str, index: int,
    value: float):
    """Adjust the Parameters.daily_ward_vaccination_capacity
       parameter
    """
    if index is not None:
        raise IndexError(
            'You cannot index the daily_ward_vaccination parameter')
    params.daily_ward_vaccination_capacity = value