def find_index(x, xs):
    """Find the index corresponding to a given value in an array."""
    n = len(xs)
    start = xs[0]
    end = xs[-1]
    i = round((n - 1) * (x - start) / (end - start))
    return int(i)


@classmethod
def value_fragment(cls, matches):
    """
        Remove OSB `[` and CSB `]` from map, but save their line/column
        information.
        """
    return cls.path_fragment(matches)


def GrossPremTable():
    """Gross premium table"""
    return None


def FXR_calc(item):
    """
    Calculate FNR,FPR,FDR,FOR.

    :param item: item In expression
    :type item:float
    :return: result as float
    """
    try:
        result = 1 - item
        return result
    except TypeError:
        return 'None'


def convert_table(shell_output, delimiter='\t|\\s{2,}', output='dict'):
    """
        a method to convert a STDOUT shell table into a python data structure

    :param shell_output: string from STDOUT with headers
    :param delimiter: string with regex pattern delimiting headers
    :param output: string with type of structure to output (dict, list or csv)
    :return: list of dictionaries or list of lists or string with csv format
    """
    import re
    gap_pattern = re.compile(delimiter)
    output_lines = shell_output.splitlines()
    column_headers = gap_pattern.split(output_lines[0])
    blank_index = column_headers.index('')
    if blank_index > -1:
        column_headers.pop(blank_index)
    indices = []
    for i in range(len(column_headers)):
        if i + 1 < len(column_headers):
            indices.append((output_lines[0].find(column_headers[i]),
                output_lines[0].find(column_headers[i + 1])))
        else:
            indices.append((output_lines[0].find(column_headers[i]), -1))
    python_list = []
    csv_string = ''
    if output == 'dict':
        pass
    elif output == 'list':
        python_list.append(column_headers)
    elif output == 'csv':
        for i in range(len(column_headers)):
            if i:
                csv_string += ','
            csv_string += column_headers[i]
    else:
        raise ValueError(
            'output argument must be one of dict, list or csv values.')
    for i in range(1, len(output_lines)):
        if output == 'dict':
            row_details = {}
            for j in range(len(column_headers)):
                row_details[column_headers[j]] = output_lines[i][indices[j]
                    [0]:indices[j][1]].rstrip()
            python_list.append(row_details)
        elif output == 'list':
            row_list = []
            for j in range(len(column_headers)):
                row_list.append(output_lines[i][indices[j][0]:indices[j][1]]
                    ).rstrip()
            python_list.append(row_list)
        elif output == 'csv':
            csv_string += '\n'
            for j in range(len(column_headers)):
                if j:
                    csv_string += ','
                csv_string += output_lines[i][indices[j][0]:indices[j][1]
                    ].rstrip()
    if csv_string:
        return csv_string
    return python_list


def makeInNotNullConditions(columns):
    """ Make the WHERE clause conditions of IS NOT NULL for columns"""
    clause = ''
    for col in columns:
        clause += str(f' {col} IS NOT NULL AND ')
    ret = clause[0:-4]
    return ret


def sample_detail_size(location: int=(0, 0)):
    """Sample the mesh detail on clicked point

    :param location: Location, Screen Coordinates of sampling
    :type location: int
    """
    pass


def get_child_ids(cur, node):
    """
    Return an iterator that yields the ID of every immediate child.

    :param node:
    :type node: Node or uuid4
    """
    sql = """
        SELECT
          id
        FROM
          nodes
        WHERE
          parent=%s
        ORDER BY
          position;
    """
    cur.execute(sql, (str(node),))
    for result in cur:
        yield str(result['id'])


def convertToTree(tree):
    """Override this function to convert a set of values to a tree."""
    return None


@staticmethod
def _walk_generic_dominator(node, gen_dominators, succ_cb):
    """Generic algorithm to return an iterator of the ordered list of
        @node's dominators/post_dominator.

        The function doesn't return the self reference in dominators.
        @node: The start node
        @gen_dominators: The dictionary containing at least node's
        dominators/post_dominators
        @succ_cb: return predecessors/successors of a node

        """
    done = set()
    if node not in gen_dominators:
        return
    node_gen_dominators = set(gen_dominators[node])
    todo = set([node])
    node_gen_dominators.remove(node)
    while node_gen_dominators:
        new_node = None
        while todo:
            node = todo.pop()
            if node in done:
                continue
            if node in node_gen_dominators:
                new_node = node
                break
            done.add(node)
            for pred in succ_cb(node):
                todo.add(pred)
        assert new_node is not None
        yield new_node
        node_gen_dominators.remove(new_node)
        todo = set([new_node])


def find_object(name, blacklist=None, whitelist=None):
    """Imports and returns an object given a fully qualified name.

    >>> find_object("whoosh.analysis.StopFilter")
    <class 'whoosh.analysis.StopFilter'>
    """
    if blacklist:
        for pre in blacklist:
            if name.startswith(pre):
                raise TypeError(
                    "%r: can't instantiate names starting with %r" % (name,
                    pre))
    if whitelist:
        passes = False
        for pre in whitelist:
            if name.startswith(pre):
                passes = True
                break
        if not passes:
            raise TypeError("Can't instantiate %r" % name)
    lastdot = name.rfind('.')
    assert lastdot > -1, 'Name %r must be fully qualified' % name
    modname = name[:lastdot]
    clsname = name[lastdot + 1:]
    mod = __import__(modname, fromlist=[clsname])
    cls = getattr(mod, clsname)
    return cls


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

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


def int_shape(x):
    """Returns the shape tensor or variable as a tuple of int or None entries.

    # Arguments
        x: Tensor or variable.

    # Returns
        A tuple of integers (or None entries).

    # Examples
    ```python
        >>> from keras import backend as K
        >>> inputs = K.placeholder(shape=(2, 4, 5))
        >>> K.int_shape(inputs)
        (2, 4, 5)
        >>> val = np.array([[1, 2], [3, 4]])
        >>> kvar = K.variable(value=val)
        >>> K.int_shape(kvar)
        (2, 2)
    ```
    """
    if hasattr(x, '_keras_shape'):
        return x._keras_shape
    try:
        if type(x.shape) is tuple:
            return x.shape
        else:
            return tuple(x.shape.as_list())
    except ValueError:
        return None


@staticmethod
def _at_block_start(tc, line):
    """
        Improve QTextCursor.atBlockStart to ignore spaces
        """
    if tc.atBlockStart():
        return True
    column = tc.columnNumber()
    indentation = len(line) - len(line.lstrip())
    return column <= indentation


def hide_dup_line_prefix(last_line: str, current_line: str) ->str:
    """ replace duplicate characters at the begin of two strings with spaces.

    :param last_line:       last line string (e.g. the last line of text/log file).
    :param current_line:    current line string.
    :return:                current line string but duplicate characters at the begin are replaced by space characters.
    """
    idx = 0
    min_len = min(len(last_line), len(current_line))
    while idx < min_len and last_line[idx] == current_line[idx]:
        idx += 1
    return ' ' * idx + current_line[idx:]


def _escape_for_regex(text):
    """Escape ``text`` to allow literal matching using egrep"""
    re_specials = '\\^$|(){}[]*+?.'
    sh_specials = '\\$`"'
    re_chars = []
    sh_chars = []
    for c in text:
        if c in re_specials:
            re_chars.append('\\')
        re_chars.append(c)
    for c in re_chars:
        if c in sh_specials:
            sh_chars.append('\\')
        sh_chars.append(c)
    return ''.join(sh_chars)


def get_exe():
    """ Wrapper for imageio_ffmpeg.get_ffmpeg_exe()
    """
    import imageio_ffmpeg
    return imageio_ffmpeg.get_ffmpeg_exe()


def pacstr(idpac):
    """Return correspond methods string."""
    if idpac[0] == 1:
        method = 'Mean Vector Length (MVL, Canolty et al. 2006)'
    elif idpac[0] == 2:
        method = 'Kullback-Leiber Distance (KLD, Tort et al. 2010)'
    elif idpac[0] == 3:
        method = 'Heights ratio (HR, Lakatos et al. 2005)'
    elif idpac[0] == 4:
        method = 'ndPac (Ozkurt et al. 2012)'
    elif idpac[0] == 5:
        method = 'Phase-Synchrony (Cohen et al. 2008; Penny et al. 2008)'
    elif idpac[0] == 6:
        method = 'Gaussian Copula PAC (Ince et al. 2017)'
    else:
        raise ValueError('No corresponding pac method.')
    if idpac[1] == 0:
        suro = 'No surrogates'
    elif idpac[1] == 1:
        suro = 'Permute phase across trials (Tort et al. 2010)'
    elif idpac[1] == 2:
        suro = 'Swap amplitude time blocks (Bahramisharif et al. 2013)'
    elif idpac[1] == 3:
        suro = 'Time lag (Canolty et al. 2006)'
    else:
        raise ValueError('No corresponding surrogate method.')
    if idpac[2] == 0:
        norm = 'No normalization'
    elif idpac[2] == 1:
        norm = 'Substract the mean of surrogates'
    elif idpac[2] == 2:
        norm = 'Divide by the mean of surrogates'
    elif idpac[2] == 3:
        norm = 'Substract then divide by the mean of surrogates'
    elif idpac[2] == 4:
        norm = ('Substract the mean and divide by the deviation of the ' +
            'surrogates')
    else:
        raise ValueError('No corresponding normalization method.')
    return method, suro, norm


def get_resourcetypes(url):
    """ Extract the resource type from a url in form /resource/{type} or just {type}/ """
    pos = url.find('/resource/')
    if pos < 0:
        return ''
    stem = url[pos + len('/resource/'):]
    slash = stem.find('/')
    if slash >= 0:
        return stem[:slash]
    return stem


def sanitize_value(value, type):
    """
    Ensure a given value is of the correct type, if the value is in a list or tuple, the first element will be coerced

    Parameters
    ----------
    value : object
        Value to be coerced
    type : Type
        One of ``int``, ``float``, ``str``, ``bool``

    Returns
    -------
    object
        Value coerced to specified type
    """
    if not isinstance(value, type):
        if isinstance(value, (list, tuple)):
            value = value[0]
        try:
            value = type(value)
        except (ValueError, TypeError):
            value = None
    return value


def validate():
    """The request is validated. It is finshed.
        """


def is_broadcast(mac):
    """Whether or not a mac is broadcast MAC address.

    Args:
        mac (str): MAC address in string format (``xx:xx:xx:xx:xx:xx``). Case
          insensitive.
    Returns:
        bool.
    """
    return mac.lower() == 'ff:ff:ff:ff:ff:ff'


def check_and_repair(monitor, verify=False, add_lease=False):
    """Like check(), but if the file/directory is not healthy, attempt to
        repair the damage.

        Any non-healthy result will cause an immediate repair operation, to
        generate and upload new shares. After repair, the file will be as
        healthy as we can make it. Details about what sort of repair is done
        will be put in the check-and-repair results. The Deferred will not
        fire until the repair is complete.

        This returns a Deferred that fires with an instance of
        ICheckAndRepairResults."""


def _validated_param(obj, name, base_class, default, base_class_name=None):
    """Validates a parameter passed to __init__. Makes sure that obj is
    the correct class. Return obj if it's not None or falls back to default

    :param obj: The object passed in.
    :param name: The name of the parameter.
    :param base_class: The class that obj must inherit from.
    :param default: The default object to fall back upon if obj is None.
    """
    base_class_name = (base_class_name if base_class_name else base_class.
        __name__)
    if obj is not None and not isinstance(obj, base_class):
        raise ValueError('{name} must be an instance of {cls}'.format(name=
            name, cls=base_class_name))
    return obj or default


def validate_float(s):
    """Convert s to float or raise a ValueError."""
    try:
        return float(s)
    except TypeError:
        raise ValueError('Could not convert "%s" to float' % s)


def memory_usage(job):
    """
    Perform memory usage verification.

    :param job: job object
    :return: exit code (int), diagnostics (string).
    """
    exit_code = 0
    diagnostics = ''
    return exit_code, diagnostics


def overbar(string):
    """
    Returns string preceeded by an overbar of the same length:
    >>> print(overbar('blee'))
    ____
    blee
    """
    return '%s\n%s' % ('_' * len(string), string)


def current_object_tids(cursor, oids):
    """
        Returns the current {oid_int: tid_int} for specified object ids.

        Note that this may be a BTree mapping, not a dictionary.
        """


@staticmethod
def check_sections(config):
    """Create a empty config file."""
    default_sections = ['global', 'auth', 'napps', 'kytos']
    for section in default_sections:
        if not config.has_section(section):
            config.add_section(section)


def is_hashable(obj) ->bool:
    """Tries whether the given object is hashable."""
    try:
        hash(obj)
    except:
        return False
    return True


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

    Eexceptions:
    1: no tags. 0.postDISTANCE[.dev0]
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance'] or pieces['dirty']:
            rendered += '.post%d' % pieces['distance']
            if pieces['dirty']:
                rendered += '.dev0'
    else:
        rendered = '0.post%d' % pieces['distance']
        if pieces['dirty']:
            rendered += '.dev0'
    return rendered


def f5(x):
    """Hyperbola with a pole at x=1, but pole replaced with 0.  Not continuous at root."""
    if x != 1:
        return 1.0 / (1.0 - x)
    return 0


def handleCollision_or_getZeroReward(player, arm, lower=0):
    """ If the player has a method handleCollision, it is called, otherwise a reward of lower is given to the player for that arm.
    """
    if hasattr(player, 'handleCollision'):
        player.handleCollision(arm, lower)
    else:
        player.getReward(arm, lower)


def is_hetatm(res):
    """
    Shortcut to check for HETATM residues
    """
    return res.id[0].startswith('H_') or res.id[0].startswith('W')


def firstval(*values, default=None, sentinel=None):
    """
    Get the first value in values which is not sentinel

    For delayed execution (similar to a if b else c) a value can be a
    callable which should return the value in question

    Example:

    default = firstval(a, config['a'], lambda: lengthycomputation())
    """
    for value in values:
        if callable(value):
            value2 = value()
            if value2 is not sentinel:
                return value2
        elif value is not sentinel:
            return value
    return default


def update_entry_attributes(sender, instance, **kwargs):
    """
    Updates attributes for Entry instance corresponding to
    specified instance.

    :param sender: the sending class.
    :param instance: the instance being saved.
    """
    from ..models import Entry
    entry = Entry.objects.get_for_model(instance)[0]
    default_url = getattr(instance, 'get_absolute_url', '')
    entry.title = getattr(instance, 'title', str(instance))
    entry.url = getattr(instance, 'url', default_url)
    entry.live = bool(getattr(instance, 'live', True))
    entry.save()


def get_tile_index(letter, mapping):
    """
    lookups up the letter in the tileset definition
    and returns the grid index (single value for TMX)
    """
    if letter in mapping:
        return mapping[letter]
    else:
        return 0


def generate_slices(sliceable_set, batch_len=1, length=None, start_batch=0):
    """Iterate through a sequence (or generator) in batches of length `batch_len`

    See Also:
      pug.dj.db.generate_queryset_batches

    References:
      http://stackoverflow.com/a/761125/623735

    Examples:
      >>  [batch for batch in generate_slices(range(7), 3)]
      [(0, 1, 2), (3, 4, 5), (6,)]
      >>  from django.contrib.auth.models import User, Permission
      >>  len(list(generate_slices(User.objects.all(), 2)))       == max(math.ceil(User.objects.count() / 2.), 1)
      True
      >>  len(list(generate_slices(Permission.objects.all(), 2))) == max(math.ceil(Permission.objects.count() / 2.), 1)
      True
    """
    if length is None:
        try:
            length = sliceable_set.count()
        except (IndexError, ValueError, AttributeError, TypeError):
            length = len(sliceable_set)
    length = int(length)
    for i in range(int(length / batch_len + 1)):
        if i < start_batch:
            continue
        start = i * batch_len
        end = min((i + 1) * batch_len, length)
        if start != end:
            yield tuple(sliceable_set[start:end])
    raise StopIteration


def psi_MgOH_CO3_SO4_HMW84(T, P):
    """c-a-a': magnesium-hydroxide carbonate sulfate [HMW84]."""
    psi = 0
    valid = T == 298.15
    return psi, valid


def hello_world():
    """Hello world function."""
    print('Hello world')


def _is_state_changed(record, deposit):
    """Return True if the celery tasks state changed."""
    state_r = record['_cds'].get('state', {})
    state_d = deposit['_cds'].get('state', {})
    return state_r != state_d


def describe_portfolio(AcceptLanguage=None, Id=None):
    """
    Retrieves detailed information and any tags associated with the specified portfolio.
    See also: AWS API Documentation

    :example: response = client.describe_portfolio(
        AcceptLanguage='string',
        Id='string'
    )

    :type AcceptLanguage: string
    :param AcceptLanguage: The language code to use for this operation. Supported language codes are as follows:
            'en' (English)
            'jp' (Japanese)
            'zh' (Chinese)
            If no code is specified, 'en' is used as the default.

    :type Id: string
    :param Id: [REQUIRED]
            The identifier of the portfolio for which to retrieve information.

    :rtype: dict
    :return: {
        'PortfolioDetail': {
            'Id': 'string',
            'ARN': 'string',
            'DisplayName': 'string',
            'Description': 'string',
            'CreatedTime': datetime(2015, 1, 1),
            'ProviderName': 'string'
        },
        'Tags': [
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    }

    """
    pass


def _parse_content_text(text):
    """ <content type="text">
          symbol:FANCA
          id:0000116087
          position_mRNA:c.1626+1_1627-1
          position_genomic:chr16:?
          Variant/DNA:c.(1626+1_1627-1)_(2151+1_2152-1)del
          Variant/DBID:FANCA_000723
          Times_reported:1
        </content>
    """
    out = {}
    for part in text.split('\n'):
        part = part.strip()
        try:
            key, val = part.split(':', 1)
        except IndexError:
            continue
        if part.startswith('symbol'):
            out['gene_name'] = val
        if part.startswith('id'):
            out['id'] = val
        if part.startswith('Variant/DBID'):
            out['DBID'] = val
        if part.startswith('Variant/DNA'):
            out['cDNA'] = val
        if part.startswith('position_mRNA'):
            out['mRNA'] = val
        if part.startswith('position_genomic'):
            out['gDNA'] = val
        if part.startswith('Times_reported'):
            out['times_reported'] = val
    return out


@staticmethod
def _get_task_requirement(task, reqname, default):
    """
        Return attribute `reqname` of `task`.

        If the attribute is not set or is ``None``, then return `default`
        instead.
        """
    return getattr(task, reqname, default)


def get_firmware_version(device_key: str) ->str:
    """
    Return device's current firmware version.

    :param device_key: Device identifier
    :type device_key: str
    :returns: version
    :rtype: str
    """
    pass


@classmethod
def enable(cls):
    """Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been
enabled until the result of this command is received.
        """
    return cls.build_send_payload('enable', {}), None


def restore__ast(_ast):
    """Attempt to restore the required classes to the _ast module if it
    appears to be missing them
    """
    if hasattr(_ast, 'AST'):
        return
    _ast.PyCF_ONLY_AST = 2 << 9
    m = compile(
        """def foo(): pass
class Bar(object): pass
if False: pass
baz = 'mako'
1 + 2 - 3 * 4 / 5
6 // 7 % 8 << 9 >> 10
11 & 12 ^ 13 | 14
15 and 16 or 17
-baz + (not +18) - ~17
baz and 'foo' or 'bar'
(mako is baz == baz) is not baz != mako
mako > baz < mako >= baz <= mako
mako in baz not in mako"""
        , '<unknown>', 'exec', _ast.PyCF_ONLY_AST)
    _ast.Module = type(m)
    for cls in _ast.Module.__mro__:
        if cls.__name__ == 'mod':
            _ast.mod = cls
        elif cls.__name__ == 'AST':
            _ast.AST = cls
    _ast.FunctionDef = type(m.body[0])
    _ast.ClassDef = type(m.body[1])
    _ast.If = type(m.body[2])
    _ast.Name = type(m.body[3].targets[0])
    _ast.Store = type(m.body[3].targets[0].ctx)
    _ast.Str = type(m.body[3].value)
    _ast.Sub = type(m.body[4].value.op)
    _ast.Add = type(m.body[4].value.left.op)
    _ast.Div = type(m.body[4].value.right.op)
    _ast.Mult = type(m.body[4].value.right.left.op)
    _ast.RShift = type(m.body[5].value.op)
    _ast.LShift = type(m.body[5].value.left.op)
    _ast.Mod = type(m.body[5].value.left.left.op)
    _ast.FloorDiv = type(m.body[5].value.left.left.left.op)
    _ast.BitOr = type(m.body[6].value.op)
    _ast.BitXor = type(m.body[6].value.left.op)
    _ast.BitAnd = type(m.body[6].value.left.left.op)
    _ast.Or = type(m.body[7].value.op)
    _ast.And = type(m.body[7].value.values[0].op)
    _ast.Invert = type(m.body[8].value.right.op)
    _ast.Not = type(m.body[8].value.left.right.op)
    _ast.UAdd = type(m.body[8].value.left.right.operand.op)
    _ast.USub = type(m.body[8].value.left.left.op)
    _ast.Or = type(m.body[9].value.op)
    _ast.And = type(m.body[9].value.values[0].op)
    _ast.IsNot = type(m.body[10].value.ops[0])
    _ast.NotEq = type(m.body[10].value.ops[1])
    _ast.Is = type(m.body[10].value.left.ops[0])
    _ast.Eq = type(m.body[10].value.left.ops[1])
    _ast.Gt = type(m.body[11].value.ops[0])
    _ast.Lt = type(m.body[11].value.ops[1])
    _ast.GtE = type(m.body[11].value.ops[2])
    _ast.LtE = type(m.body[11].value.ops[3])
    _ast.In = type(m.body[12].value.ops[0])
    _ast.NotIn = type(m.body[12].value.ops[1])


def get_result_string(object, attr_list):
    """Construct string of values from several object attributes.

    :param object: A object from which to retrieve values.
    :type object: misc
    :param attr_list:
        List of strings indicating attributes to retrieve from the object.
    :type attr_list: list
    :returns: A concatenated string representing values from all attributes.
    :rtype: str
    """
    strings = []
    for attr in attr_list:
        attr_value = getattr(object, attr)
        strings.append(attr + ': ' + str(attr_value))
    string = ', '.join(strings)
    return string


def render_border(xmin: int=0, xmax: int=0, ymin: int=0, ymax: int=0,
    wait_for_input: bool=True):
    """Set the boundaries of the border render and enable border render

    :param xmin: X Min
    :type xmin: int
    :param xmax: X Max
    :type xmax: int
    :param ymin: Y Min
    :type ymin: int
    :param ymax: Y Max
    :type ymax: int
    :param wait_for_input: Wait for Input
    :type wait_for_input: bool
    """
    pass


def logout(request):
    """Possibly logout.

        If a logout was performed, return True, otherwise return False.
        """


def start_activity_with_command(command: str, toolkit=None):
    """
    更灵活的 start_activity，实际上是运行 adb shell am start <command>

    :param command: adb shell am start <command>
    :param toolkit:
    :return:
    """
    return toolkit.adb.run(['shell', 'am', 'start', command.split(' ')])


def table_to_dict(path, columns, sep=None, skip=None):
    """Convert tabled data to a dictionary

    :param path: path to the file to read
    :param columns: field names
    :param sep: fields separator
    :param skip: number of lines to skip on the source
    :return: dictionary
    """
    data_set = []
    with open(path) as source:
        if skip:
            source = list(source)[skip:]
        for line in source:
            values = line.split(sep, len(columns))
            data_set.append(dict(zip(columns, values)))
    return data_set


def _serialize_names(row, values_fields_mapping):
    """Replace name from ORM side to the serialization side as expected"""
    new_serialized_data = {}
    if not values_fields_mapping:
        new_serialized_data.update(row)
        return new_serialized_data
    for orm_name, serialize_info in values_fields_mapping.items():
        serialize_name, conv_func = serialize_info
        value = conv_func(row[orm_name])
        new_serialized_data[serialize_name] = value
    return new_serialized_data


def string_to_dict(s):
    """
    Convert a string to a dictionary, with extra processing for some
    matplotlib keyword arguments which are expected to have integer or
    floating point values.

    This function is in ``utils.py``.
    """
    arr = s.split(',')
    dct = {}
    skip = 0
    if len(s) == 0:
        return dct
    for i in range(0, len(arr)):
        if skip > 0:
            skip = skip - 1
        else:
            arr2 = arr[i].split('=')
            if arr2[1][0] == "'" and arr2[1][len(arr2[1]) - 1] == "'":
                arr2[1] = arr2[1][1:len(arr2[1]) - 1]
            if arr2[1][0] == '"' and arr2[1][len(arr2[1]) - 1] == '"':
                arr2[1] = arr2[1][1:len(arr2[1]) - 1]
            if arr2[0] == 'arrowstyle':
                for j in range(0, len(arr)):
                    if arr[j].split('=')[0] == 'head_width':
                        arr2[1] = arr2[1] + ',head_width=' + arr[j].split('=')[
                            1]
                    if arr[j].split('=')[0] == 'head_length':
                        arr2[1] = arr2[1] + ',head_length=' + arr[j].split('='
                            )[1]
                    if arr[j].split('=')[0] == 'tail_width':
                        arr2[1] = arr2[1] + ',tail_width=' + arr[j].split('=')[
                            1]
                    if arr[j].split('=')[0] == 'shrink_factor':
                        arr2[1] = arr2[1] + ',shrink_factor=' + arr[j].split(
                            '=')[1]
                    if arr[j].split('=')[0] == 'widthA':
                        arr2[1] = arr2[1] + ',widthA=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'widthB':
                        arr2[1] = arr2[1] + ',widthB=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'lengthB':
                        arr2[1] = arr2[1] + ',lengthB=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'as_angleB':
                        arr2[1] = arr2[1] + ',angleB=' + arr[j].split('=')[1]
                print('Found arrowstyle option, reprocessed:', arr2[1])
            if arr2[0] == 'connectionstyle':
                for j in range(0, len(arr)):
                    if arr[j].split('=')[0] == 'angleA':
                        arr2[1] = arr2[1] + ',angleA=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'cs_angleB':
                        arr2[1] = arr2[1] + ',angleB=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'armA':
                        arr2[1] = arr2[1] + ',armA=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'armB':
                        arr2[1] = arr2[1] + ',armB=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'rad':
                        arr2[1] = arr2[1] + ',rad=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'fraction':
                        arr2[1] = arr2[1] + ',fraction=' + arr[j].split('=')[1]
                    if arr[j].split('=')[0] == 'angle':
                        arr2[1] = arr2[1] + ',angle=' + arr[j].split('=')[1]
                print('Found connectionstyle option, reprocessed:', arr2[1])
            if arr2[0] == 'zorder':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'lw':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'alpha':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'shrinkA':
                arr2[1] = int(arr2[1])
            if arr2[0] == 'shrinkB':
                arr2[1] = int(arr2[1])
            if arr2[0] == 'bins':
                arr2[1] = int(arr2[1])
            if arr2[0] == 'fig_size_x':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'fig_size_y':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'left_margin':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'right_margin':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'top_margin':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'bottom_margin':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'left':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'right':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'top':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'bottom':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'wspace':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'hspace':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'fontsize':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'font':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'scale':
                arr2[1] = float(arr2[1])
            if arr2[0] == 'sharex':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'reorient':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'sharey':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'squeeze':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'fill':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'ticks_in':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'rt_ticks':
                if arr2[1] == 'True':
                    arr2[1] = True
                else:
                    arr2[1] = False
            if arr2[0] == 'color' and arr[i][5] == '=' and arr[i][6] == '(':
                arr2[1] = arr2[1] + ',' + arr[i + 1] + ',' + arr[i + 2]
                print(arr2[1])
                skip = 2
                arr2[1] = arr2[1][1:len(arr2[1]) - 1]
                arr3 = arr2[1].split(',')
                arr2[1] = float(arr3[0]), float(arr3[1]), float(arr3[2])
            elif arr2[0] == 'color' and arr[i][5] == '=' and arr[i][6] == '[':
                arr2[1] = arr2[1] + ',' + arr[i + 1] + ',' + arr[i + 2
                    ] + ',' + arr[i + 3]
                print(arr2[1])
                skip = 3
                arr2[1] = arr2[1][1:len(arr2[1]) - 1]
                arr3 = arr2[1].split(',')
                arr2[1] = [float(arr3[0]), float(arr3[1]), float(arr3[2]),
                    float(arr3[3])]
            if arr2[0] != 'head_width' and arr2[0] != 'head_length' and arr2[0
                ] != 'tail_width' and arr2[0] != 'rad' and arr2[0
                ] != 'angleA' and arr2[0] != 'as_angleB' and arr2[0
                ] != 'armA' and arr2[0] != 'armB' and arr2[0
                ] != 'angle' and arr2[0] != 'fraction' and arr2[0
                ] != 'shrink_factor' and arr2[0] != 'widthA' and arr2[0
                ] != 'lengthB' and arr2[0] != 'widthB' and arr2[0
                ] != 'cs_angleB':
                dct[arr2[0]] = arr2[1]
    return dct


@classmethod
def check(cls, message) ->bool:
    """
        Compare pattern with message

        :param message: always must be in lowercase
        :return: bool
        """
    return cls.match.lower() in message


@classmethod
def num_graphs(cls):
    """ Returns the number of alive instances. """
    return cls.__num_graphs


@classmethod
def bug_id_from_url(cls, url):
    """
            Strips the last '/' and returns the PK
        """
    return super().bug_id_from_url(url.strip('/'))


def list_tags(Resource=None):
    """
    Returns a list of tags assigned to a function when supplied the function ARN (Amazon Resource Name).
    See also: AWS API Documentation

    :example: response = client.list_tags(
        Resource='string'
    )

    :type Resource: string
    :param Resource: [REQUIRED]
            The ARN (Amazon Resource Name) of the function.

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

    """
    pass


def get_model_instance(model_class, instance_or_id, raise_on_error=True):
    """
    Get model's instance by id.
    :param model_class:
    :param instance_or_id:
    :param raise_on_error: if False, return None instead of raise.
    :return:
    """
    if isinstance(instance_or_id, model_class):
        return instance_or_id
    else:
        try:
            return model_class.objects.get(pk=instance_or_id)
        except Exception as e:
            if raise_on_error:
                raise
            else:
                return None


def match(a, b):
    """return true if all items of 'a' are matched in 'b', else return false.
    examples:
    match((0,1,2), (0,1,2)) will return True
    match((0,1,2), (0,1,3)) will return False
    """
    if str(a) == str(b):
        return True
    else:
        return False


def get_feature_names():
    """
	feature names for the fixed peptide length feature vectors
	"""
    aminos = ['A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'M', 'N', 'P',
        'Q', 'R', 'S', 'T', 'V', 'W', 'Y']
    names = []
    for a in aminos:
        names.append('Ib_' + a)
    names.append('sumIbaG')
    names.append('meanIbwikiG')
    names.append('sumIywaG')
    names.append('meanIywikiG')
    names += ['pmz', 'peplen', 'ionnumber', 'ionnumber_rel']
    for c in ['aG', 'wikiG', 'mz', 'bas', 'heli', 'hydro', 'pI']:
        names.append('sum_' + c)
    for c in ['mz', 'bas', 'heli', 'hydro', 'pI']:
        names.append('mean_' + c)
    for c in ['max_{}', 'min_{}', 'max{}_b', 'min{}_b', 'max{}_y', 'min{}_y']:
        for b in ['bas', 'heli', 'hydro', 'pI']:
            names.append(c.format(b))
    names.append('mz_ion')
    names.append('mz_ion_other')
    names.append('mean_mz_ion')
    names.append('mean_mz_ion_other')
    for c in ['bas', 'heli', 'hydro', 'pI']:
        names.append('{}_ion'.format(c))
        names.append('{}_ion_other'.format(c))
        names.append('{}_ion_minus_ion_other'.format(c))
    for c in ['plus_cleave{}', 'times_cleave{}', 'minus1_cleave{}',
        'minus2_cleave{}', 'bsum{}', 'ysum{}']:
        for b in ['bas', 'heli', 'hydro', 'pI']:
            names.append(c.format(b))
    for pos in ['0', '1', '-2', '-1']:
        for c in ['mz', 'bas', 'heli', 'hydro', 'pI', 'wikiG', 'P', 'D',
            'E', 'K', 'R']:
            names.append('loc_' + pos + '_' + c)
    for pos in ['i', 'i+1']:
        for c in ['wikiG', 'P', 'D', 'E', 'K', 'R']:
            names.append('loc_' + pos + '_' + c)
    for c in ['bas', 'heli', 'hydro', 'pI', 'mz']:
        for pos in ['i', 'i-1', 'i+1', 'i+2']:
            names.append('loc_' + pos + '_' + c)
    names.append('charge')
    return names


def get_bundles(includeInactive=None, pageToken=None):
    """
    Returns the list of bundles that are available for purchase. A bundle describes the specs for your virtual private server (or instance ).
    See also: AWS API Documentation

    :example: response = client.get_bundles(
        includeInactive=True|False,
        pageToken='string'
    )

    :type includeInactive: boolean
    :param includeInactive: A Boolean value that indicates whether to include inactive bundle results in your request.

    :type pageToken: string
    :param pageToken: A token used for advancing to the next page of results from your get bundles request.

    :rtype: dict
    :return: {
        'bundles': [
            {
                'price': ...,
                'cpuCount': 123,
                'diskSizeInGb': 123,
                'bundleId': 'string',
                'instanceType': 'string',
                'isActive': True|False,
                'name': 'string',
                'power': 123,
                'ramSizeInGb': ...,
                'transferPerMonthInGb': 123
            },
        ],
        'nextPageToken': 'string'
    }

    """
    pass


@classmethod
def on_before_tests(cls):
    """
        Run before run the tests for the element
        """
    pass


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

        :param ResellerSupportChangePolicyDetails val:
        :rtype: EventDetails
        """
    return cls('reseller_support_change_policy_details', val)


def static_resource_uri(src: str, prefix: str=None) ->str:
    """Build static path of resource."""
    local_prefix = '_static' if prefix is None else prefix
    if src.startswith('http://') or src.startswith('https://'):
        return src
    return f'{local_prefix}/{src}'


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


def CellAbsorption(ElList, Volume):
    """Compute unit cell absorption

    :param dict ElList: dictionary of element contents including mu and
      number of atoms be cell
    :param float Volume: unit cell volume
    :returns: mu-total/Volume
    """
    muT = 0
    for El in ElList:
        muT += ElList[El]['mu'] * ElList[El]['FormulaNo']
    return muT / Volume


def recall_metric(y_true, y_pred):
    """Calculate the Recall from a keras batch"""
    from keras import backend as K
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall


@classmethod
def is_date_func(cls, arg_val):
    """
        To check if argument match the date pattern
        The default pattern matches 4/1/2001 | 12/12/2001 | 55/5/3434
        """
    return cls.match_pattern(arg_val, cls.date_regex_pattern)


@staticmethod
def dispute_fee(amount):
    """
        Return processing fee associated to a chargeback (i.e. $15).
        """
    return 1500


@staticmethod
def is_hello(x) ->bool:
    """Return if packet is a hello packet."""
    if 'length' in x:
        val = x['length']
    else:
        val = x.header.value['length']
    return bool(val == 32)


def _dict_extends(d1, d2):
    """
    Helper function to create a new dictionary with the contents of the two
    given dictionaries. Does not modify either dictionary, and the values are
    copied shallowly. If there are repeates, the second dictionary wins ties.

    The function is written to ensure Skulpt compatibility.

    Args:
        d1 (dict): The first dictionary
        d2 (dict): The second dictionary
    """
    d3 = {}
    for key, value in d1.items():
        d3[key] = value
    for key, value in d2.items():
        d3[key] = value
    return d3


def parse_scen_file(scen_file, n_agents):
    """Return the agent start locations and the goal locations.

    Args:
        scen_file (str): path to the scenario file.
        n_agents (int): number of agents to read from the scenario (might contain a lot of agents - the more the harder)

    Returns:
        tuple. two lists - one of start locations and one of goal locations (each locations is a tuple of x,y).
    """
    starts = []
    goals = []
    with open(scen_file, 'r') as f:
        lines = iter(f)
        next(lines)
        for i, line in enumerate(lines):
            _, _, _, _, x_start, y_start, x_goal, y_goal, _ = line.split('\t')
            starts.append((int(x_start), int(y_start)))
            goals.append((int(x_goal), int(y_goal)))
            if i == n_agents - 1:
                break
    return tuple(starts), tuple(goals)


def group_make():
    """Make group from selected nodes

    """
    pass


def get_data_loader(dataset, batch_size, num_workers):
    """
    generate the data_loader from the given dataset
    :param dataset: dataset for training (Should be a PyTorch dataset)
                    Make sure every item is an Image
    :param batch_size: batch size of the data
    :param num_workers: num of parallel readers
    :return: dl => dataloader for the dataset
    """
    from torch.utils.data import DataLoader
    dl = DataLoader(dataset, batch_size=batch_size, shuffle=True,
        num_workers=num_workers)
    return dl


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 list_rar(archive, compression, cmd, verbosity, interactive):
    """List a RAR archive."""
    cmdlist = [cmd]
    if verbosity > 1:
        cmdlist.append('v')
    else:
        cmdlist.append('l')
    if not interactive:
        cmdlist.extend(['-p-', '-y'])
    cmdlist.extend(['--', archive])
    return cmdlist


def __add__(other):
    """Used for merge two managers."""


@classmethod
def get_inverted_operation_type(cls, operation_type):
    """ Get the inverted operation_type (IN->OUT / OUT->IN)

        :param operation_type: the type of transaction
        :returns: the inverted transaction type
        """
    if operation_type == cls.TYPE_IN:
        return cls.TYPE_OUT
    return cls.TYPE_IN


def invert_txid(txid: bytes) ->str:
    """invert txid string from bytes

    :param txid: txid byte string from wallet
    :type txid: bytes
    :return: inverted txid string
    :rtype: str
    """
    tx = txid.hex()
    if len(tx) != 64:
        raise ValueError('txid %r length != 64' % tx)
    new_txid = ''
    for i in range(32):
        new_txid += tx[62 - 2 * i]
        new_txid += tx[62 - 2 * i + 1]
    return new_txid


def setup_mvrm_share(parser):
    """Setup options which ls does not use."""
    parser.add_argument('-d', '--directories', action='store_true', help=
        'delete and rename directories')
    parser.add_argument('-i', '--confirm', action='store_true', help=
        'prompt for confirmation before renaming or deleting any files')
    parser.add_argument('-f', '--force', action='store_true', help=
        'never prompt for confirmation')


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 extra_supported_chars():
    """ Returns extra supported chars besides phonetics """
    return ['.', ',', ' ', ';', ':', '?', '-']


def _np_copy(a, out=None):
    """
    Return an array copy of the given object.

    Parameters
    ----------
    a : ndarray
        Input data.
    out : ndarray or None, optional
        Alternative output array in which to place the result. It must have
        the same shape and dtype as the expected output.

    Returns
    -------
    arr : ndarray
        Array interpretation of `a`.

    Notes
    -------
    This function differs from the original `numpy.copy
    <https://docs.scipy.org/doc/numpy/reference/generated/numpy.copy.html>`_ in
    the following aspects:

    - Input type does not support Python native iterables(list, tuple, ...).
    - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output.
    - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output.
    - Does not support "order" parameter.

    Examples
    --------
    Create an array x, with a reference y and a copy z:

    >>> x = np.array([1, 2, 3])
    >>> y = x
    >>> z = np.copy(x)

    Note that, when ``x`` is modified, ``y`` is also modified, but not ``z``:

    >>> x[0] = 10
    >>> x[0] == y[0]
    array([1.])
    >>> x[0] == z[0]
    array([0.])
    """
    pass


def wrapper_commands() ->dict:
    """Lists the available 'wrapper' sub-commands of the 'chado' command with corresponding descriptions"""
    return {'extract':
        'run a pre-compiled query against the CHADO database', 'insert':
        'insert a new entity of a specified type into the CHADO database',
        'delete':
        'delete an entity of a specified type from the CHADO database',
        'import': 'import data from file into the CHADO database', 'export':
        'export data from the CHADO database to file', 'execute':
        'execute a function defined in a CHADO database', 'admin':
        'perform administrative tasks, such as creating or dumping a CHADO database'
        }


@classmethod
def get_exchange_name(cls):
    """
        Get exchange name
        :return: Exchange name string
        """
    return 'Cryptopia'


def clear_matplotlib_ticks(ax=None, axis='both'):
    """
    Clears the default matplotlib axes, or the one specified by the axis
    argument.

    Parameters
    ----------
    ax: Matplotlib AxesSubplot, None
        The subplot to draw on.
    axis: string, "both"
        The axis to clear: "x" or "horizontal", "y" or "vertical", or "both"
    """
    if not ax:
        return
    if axis.lower() in ['both', 'x', 'horizontal']:
        ax.set_xticks([], [])
    if axis.lower() in ['both', 'y', 'vertical']:
        ax.set_yticks([], [])


def evaluations(ty, pv):
    """
    evaluations(ty, pv) -> (ACC, MSE, SCC)

    Calculate accuracy, mean squared error and squared correlation coefficient
    using the true values (ty) and predicted values (pv).
    """
    if len(ty) != len(pv):
        raise ValueError('len(ty) must equal to len(pv)')
    total_correct = total_error = 0
    sumv = sumy = sumvv = sumyy = sumvy = 0
    for v, y in zip(pv, ty):
        if y == v:
            total_correct += 1
        total_error += (v - y) * (v - y)
        sumv += v
        sumy += y
        sumvv += v * v
        sumyy += y * y
        sumvy += v * y
    l = len(ty)
    ACC = 100.0 * total_correct / l
    MSE = total_error / l
    try:
        SCC = (l * sumvy - sumv * sumy) * (l * sumvy - sumv * sumy) / ((l *
            sumvv - sumv * sumv) * (l * sumyy - sumy * sumy))
    except:
        SCC = float('nan')
    return ACC, MSE, SCC


def function_with_types_in_docstring(param1, param2):
    """Example function with types documented in the docstring.

    `PEP 484`_ type annotations are supported. If attribute, parameter, and
    return types are annotated according to `PEP 484`_, they do not need to be
    included in the docstring:

    Args:
        param1 (int): The first parameter.
        param2 (str): The second parameter.

    Returns:
        bool: The return value. True for success, False otherwise.

    .. _PEP 484:
        https://www.python.org/dev/peps/pep-0484/

    """


@classmethod
def __get_real_class(mcs, unknown_class):
    """Provide a real class for a proxy *or* real class"""
    try:
        return mcs.__real_class_store__[unknown_class]
    except KeyError:
        return unknown_class


def send_message(message):
    """
    This will eventually handle the message passing from the api layer
    Right now it is just a dummy function that prints
    """
    print(message)
    return


@staticmethod
def _relation_to_symbol(relation):
    """
        Change a numeric relation to a string symbol.

        :param Rational relation: the relation

        :returns: a symbol with the right relation to ``relation`` or None
        :rtype: str or NoneType
        """
    if relation == 0:
        return None
    elif relation < 0:
        return '>'
    elif relation > 0:
        return '<'
    else:
        assert False


@classmethod
def from_definition(cls, definition_fp):
    """
        Return a PatternManager ojbect from give pattern difinition file
        """
    pm = cls()
    with open(definition_fp) as f:
        pattern_lines = filter(lambda x: any([len(x) == 0, x[0] != '#']), f
            .read().strip().split('\n'))
    for line in pattern_lines:
        lemma, sep, tail = line.partition(':')
        snippets = tail.split(';')
        pm.add_snippets(snippets, lemma)
    return pm


def _plot_vels(vels, labels, title=None):
    """Plot trial velocities as a stem plot"""
    trace = dict(y=vels, x=labels, mode='markers')
    layout = dict(title=title, xaxis=dict(title='Trial', automargin=True),
        yaxis=dict(title='Speed (m/s)'))
    return dict(data=[trace], layout=layout)


def islast(iterable):
    """
    An iterator similar to the builtin :py:func:`enumerate`, except that
    instead of the index, it returns a boolean flag indicating if the
    current element is the last one.

    Based on the recipe at http://stackoverflow.com/a/2429118/2988730.
    Saw http://stackoverflow.com/a/2429260/2988730 after writing this.
    """
    iterable = iter(iterable)
    item = next(iterable)
    for peek in iterable:
        yield False, item
        item = peek
    yield True, item


def hourminsec(n_seconds):
    """Generate a string of hours and minutes from total number of seconds

    Args
    ----
    n_seconds: int
        Total number of seconds to calculate hours, minutes, and seconds from

    Returns
    -------
    hours: int
        Number of hours in `n_seconds`
    minutes: int
        Remaining minutes in `n_seconds` after number of hours
    seconds: int
        Remaining seconds in `n_seconds` after number of minutes
    """
    hours, remainder = divmod(n_seconds, 3600)
    minutes, seconds = divmod(remainder, 60)
    return abs(hours), abs(minutes), abs(seconds)


def pulse(time, start, duration):
    """ Implements vensim's PULSE function

    In range [-inf, start) returns 0
    In range [start, start + duration) returns 1
    In range [start + duration, +inf] returns 0
    """
    t = time()
    return 1 if start <= t < start + duration else 0


def register_deployable(ts, deployablename, attributes):
    """
    Deployable registration callback.
    'deployablename' is from table 'deployable-names'.
    """
    pass


def b32_normalize(key: str) ->str:
    """
    Web sites often gives the secret with spaces between 4-char words. This method normalizes
    the received key into one parseable by base64, and handles padding.

    :param key: the original key.
    :return: a normalized b32 string.
    """
    key = key.upper().replace(' ', '')
    key += '=' * (-len(key) % 8)
    return key


@classmethod
def disconnect(cls, entry):
    """Disconnect the pixelpin_auth account for the given user"""
    raise NotImplementedError('Implement in subclass')


@classmethod
def parse_date_string(cls, date_str):
    """
        Classmethod that takes a date from Metron's REST API and splits it into it's components
        """
    day = None
    month = None
    year = None
    if date_str is not None:
        parts = date_str.split('-')
        year = parts[0]
        if len(parts) > 1:
            month = parts[1]
            if len(parts) > 2:
                day = parts[2]
    return day, month, year


def render(counts, **kwargs):
    """Generate and return HTML pluggdapps footer.

        ``counts``,
            A dictionary of, number of interfaces and number plugin count.

        Optional keyword arguments,

        ``id``,
            If specified will be used as **id** attribute for the widget node.
        """


def shared_options(parser):
    """parser is an OptionParser object add the following options to it """
    parser.add_option('-c', '--config', dest='config', help=
        'config module to use standard is osdcquery.config.Tcga', default=
        'osdcquery.config.Tcga')
    parser.add_option('-v', '--verbose', action='store_true', dest=
        'verbose', help='display messages to standard out', default=False)
    parser.add_option('-d', '--log', dest='loglevel', help=
        'python log level DEBUG, INFO ...', default='ERROR')


def get_in_units(value, units):
    """get a value in the required units """
    try:
        from pint import UnitRegistry
        ureg = UnitRegistry()
    except ImportError:
        raise ImportError('please install pint to use this module')
    return ureg.Quantity(value, units)


def _roman(n):
    """
    :param n: the input integer
    :return the roman numeral
    :raise ValueError: if the input integer is not a positive
        integer less than five
    """
    if n not in range(1, 5):
        raise ValueError(
            'The roman numeral converter is not supported for the value %d' % n
            )
    if n == 4:
        return 'IV'
    else:
        return 'I' * n


@classmethod
def register_serializer(cls, name, method):
    """Add `method` as `name` to the set of serializers to pick from
        in :meth:`serialize`

        Parameters
        ----------
        name : str
            The name of the serializer
        method : Callable
            A callable object that when called with a :class:`Glycan` returns a :class:`str`
        """
    cls._serializers[name] = method


def _a_decode_list(stream, offset, count, mapping):
    """
    'a1l3i123',3,1 --> 8,[123]
    'a2l1i41i2',3,1 --> 8,[4,2]
    """
    container = []
    for _ in range(count):
        index = offset
        while 48 <= ord(stream[index:index + 1]) <= 57:
            index += 1
        offset, value = mapping[stream[index:index + 1]](stream, index + 1,
            int(stream[offset:index]), mapping)
        container.append(value)
    return offset, container


def _replace_special_characters(str_special_chars):
    """
    Replaces special characters in a string with their percent-encoded counterparts
        ':' -> '%3A'
        '/' -> '%2F'
        ',' -> '%2C'
    (e.g. "1/1/9" -> "1%2F1%2F9")

    :param str_special_chars: string in which to substitute characters
    :return: new string with characters replaced by their percent-encoded counterparts
    """
    str_percents = str_special_chars.replace(':', '%3A').replace('/', '%2F'
        ).replace(',', '%2C')
    return str_percents


def export_cli(f):
    """a decorator that marks a function as exported for CLI

    intended to be used by plugins
    the HandlerRegistry will export the function under its own name
    """
    setattr(f, 'exported_cli', True)
    return f


def load_mod(zelf, modname, force=True):
    """ load a module and if force is sset to True, put in in the cache, """
    mod = zelf.direct(modname)
    if mod and force:
        zelf._table[modname] = mod
    return mod


def _get_text_positions(text):
    """
    For each character in the text object, return a list pixel values for
    the start of each character.

    Note, this returns a list that is len(text) + 1, so that the end of the
    last character can be determined.
    """
    orig = text.get_text()
    text.set_text('##')
    bb = text.get_window_extent()
    width0 = bb.width
    text.set_text('# #')
    bb = text.get_window_extent()
    width1 = bb.width
    space_width = width1 - width0
    s = str(orig)
    N = len(s)
    x_positions = [bb.x0]
    for i in range(1, N + 1):
        txt = s[0:i]
        text.set_text(txt)
        bb = text.get_window_extent()
        x = bb.x0 + bb.width
        if txt[0] == ' ':
            x += space_width
        if i > 0 and txt[-1] == ' ':
            x += space_width
        x_positions.append(x)
    text.set_text(orig)
    return x_positions


def append_value(dictionary, key, item):
    """Append those items to the values for that key"""
    items = dictionary.get(key, [])
    items.append(item)
    dictionary[key] = items


def _inv_impl(expr, op, **kw):
    """See :meth:`.ColumnOperators.__inv__`."""
    if hasattr(expr, 'negation_clause'):
        return expr.negation_clause
    else:
        return expr._negate()


def splitter(option):
    """
    Splits participant id's by ','
    :param participant_id: args parsed from user
    :return: list containing participants
    """
    if not option:
        return None
    else:
        return option.split(',')


def _is_key_file_encrypted(key_file):
    """Detects if a key file is encrypted or not."""
    with open(key_file, 'r') as f:
        for line in f:
            if 'ENCRYPTED' in line:
                return True
    return False


def get_progress():
    """Returns a tuple of floats, (chk, ciphertext, encode_and_push),
        each from 0.0 to 1.0 . 'chk' describes how much progress has been
        made towards hashing the file to determine a CHK encryption key: if
        non-convergent encryption is in use, this will be trivial, otherwise
        the whole file must be hashed. 'ciphertext' describes how much of the
        ciphertext has been pushed to the helper, and is '1.0' for non-helper
        uploads. 'encode_and_push' describes how much of the encode-and-push
        process has finished: for helper uploads this is dependent upon the
        helper providing progress reports. It might be reasonable to add all
        three numbers and report the sum to the user."""


def process(proc_data):
    """
    Final processing to conform to the schema.

    Parameters:

        proc_data:   (dictionary) raw structured data to process

    Returns:

        List of dictionaries. Structured data with the following schema:

        [
          {
            "id":             integer,
            "opcode":         string,
            "status":         string,
            "flags": [
                              string
            ],
            "query_num":      integer,
            "answer_num":     integer,
            "authority_num":  integer,
            "additional_num": integer,
            "axfr": [
              {
                "name":       string,
                "class":      string,
                "type":       string,
                "ttl":        integer,
                "data":       string
              }
            ],
            "question": {
              "name":         string,
              "class":        string,
              "type":         string
            },
            "answer": [
              {
                "name":       string,
                "class":      string,
                "type":       string,
                "ttl":        integer,
                "data":       string
              }
            ],
            "authority": [
              {
                "name":       string,
                "class":      string,
                "type":       string,
                "ttl":        integer,
                "data":       string
              }
            ],
            "query_time":     integer,   # in msec
            "server":         string,
            "when":           string,
            "rcvd":           integer
            "size":           string
          }
        ]
    """
    for entry in proc_data:
        int_list = ['id', 'query_num', 'answer_num', 'authority_num',
            'additional_num', 'rcvd']
        for key in int_list:
            if key in entry:
                try:
                    key_int = int(entry[key])
                    entry[key] = key_int
                except ValueError:
                    entry[key] = None
        if 'axfr' in entry:
            for ax in entry['axfr']:
                try:
                    ttl_int = int(ax['ttl'])
                    ax['ttl'] = ttl_int
                except ValueError:
                    ax['ttl'] = None
        if 'answer' in entry:
            for ans in entry['answer']:
                try:
                    ttl_int = int(ans['ttl'])
                    ans['ttl'] = ttl_int
                except ValueError:
                    ans['ttl'] = None
        if 'authority' in entry:
            for auth in entry['authority']:
                try:
                    ttl_int = int(auth['ttl'])
                    auth['ttl'] = ttl_int
                except ValueError:
                    auth['ttl'] = None
        if 'query_time' in entry:
            try:
                qt_int = int(entry['query_time'].split()[0])
                entry['query_time'] = qt_int
            except ValueError:
                entry['query_time'] = None
    return proc_data


def find(item, vec):
    """return the index of the first occurence of item in vec"""
    for i in range(len(vec)):
        if item == vec[i]:
            return i
    return -1


@classmethod
def field_data(cls, data):
    """The content data of the field."""
    return cls(cls.FIELD_DATA, data)


def data_class_from_pvspec(group, pvspec):
    """Return the data class for a given PVSpec in a group"""
    if pvspec.read_only:
        return group.type_map_read_only[pvspec.dtype]
    return group.type_map[pvspec.dtype]


def slices_overlap(slice_a, slice_b):
    """Test if the ranges covered by a pair of slices overlap."""
    assert slice_a.step is None
    assert slice_b.step is None
    return max(slice_a.start, slice_b.start) < min(slice_a.stop, slice_b.stop)


def render(context, mimetype, content, filename=None, url=None):
    """Render an XHTML preview of the raw ``content`` in a
        `RenderingContext`.

        The `content` might be:
         * a `str` object
         * an `unicode` string
         * any object with a `read` method, returning one of the above

        It is assumed that the content will correspond to the given `mimetype`.

        Besides the `content` value, the same content may eventually
        be available through the `filename` or `url` parameters.
        This is useful for renderers that embed objects, using <object> or
        <img> instead of including the content inline.

        Can return the generated XHTML text as a single string or as an
        iterable that yields strings. In the latter case, the list will
        be considered to correspond to lines of text in the original content.

        """


def anim_transforms_to_deltas():
    """Convert object animation for normal transforms to delta transforms

    """
    pass


def _get200Response(link):
    """获取当http response code为200时的返回模板

    :link: Link对象
    :returns: {'$ref': '', 'schema': ''}

    """
    serializer = getattr(link, '__serializer__', None)
    tpl = dict(description='Success')
    if not serializer:
        return tpl
    obj_name = serializer.name
    ref = {'$ref': '#/definitions/{}'.format(obj_name)}
    if link.action == 'get' and '{' not in link.url:
        tpl['schema'] = dict(items=ref, type='array')
    else:
        tpl['schema'] = ref
    return tpl


def create_new_conversation(cursor, title, message, user_id, bot_id):
    """
    Creates new conversation in Humhub.

    :param cursor: MySQL Cursor for database processes
    :param str title: Title of conversation
    :param str message: First message of created conversation
    :param int user_id: Humhub User ID to create conversation with
    :param int bot_id: User ID to use for the bot
    """
    query = (
        'INSERT INTO message (title, created_by, updated_by) VALUES ({}, {}, {})'
        .format(title, bot_id, bot_id))
    cursor.execute(query)
    message_id = cursor.lastrowid
    query = (
        'INSERT INTO user_message (message_id, user_id, created_by, updated_by) VALUES ({}, {}, {}, {})'
        .format(message_id, user_id, bot_id, bot_id))
    cursor.execute(query)
    query = (
        'INSERT INTO message_entry (message_id, user_id, content, created_by, updated_by) VALUES ({}, {}, {}, {})'
        .format(message_id, user_id, message, bot_id, bot_id))
    cursor.execute(query)


def context_modal_mouse(data_path_iter: str='', data_path_item: str='',
    header_text: str='', input_scale: float=0.01, invert: bool=False,
    initial_x: int=0):
    """Adjust arbitrary values with mouse input

    :param data_path_iter: data_path_iter, The data path relative to the context, must point to an iterable
    :type data_path_iter: str
    :param data_path_item: data_path_item, The data path from each iterable to the value (int or float)
    :type data_path_item: str
    :param header_text: Header Text, Text to display in header during scale
    :type header_text: str
    :param input_scale: input_scale, Scale the mouse movement by this value before applying the delta
    :type input_scale: float
    :param invert: invert, Invert the mouse input
    :type invert: bool
    :param initial_x: initial_x
    :type initial_x: int
    """
    pass


@classmethod
def UTM(cls, zone, north=True):
    """Create UTM projection of given ``zone``."""
    assert zone >= 1 and zone <= 60
    if north:
        return cls.fromEPSG(epsg=32600 + zone)
    else:
        return cls.fromEPSG(epsg=32700 + zone)


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


def verification_run(base_verification_url: str, verification_run_id: str=None
    ) ->str:
    """
    Build the URL to communicate with the verification run API.
    """
    if not verification_run_id:
        return '/'.join([base_verification_url, 'runs'])
    return '/'.join([base_verification_url, 'runs', verification_run_id])


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

    If x is already in a, insert it to the right of the rightmost x.

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


def insensitive(string):
    """Given a string, returns its lower/upper case insensitive string"""
    if getattr(str, 'casefold', None) is not None:
        insen = lambda str_name: str_name.casefold()
    else:
        insen = lambda str_name: str_name.upper().lower()
    return insen(string)


def _clip(n: float) ->float:
    """
    Helper function to emulate numpy.clip for the specific
    use case of preventing math domain errors on the
    acos function by "clipping" values that are > abs(1).
    e.g. _clip(1.001) == 1
         _clip(-1.5) == -1
         _clip(0.80) == 0.80
    """
    sign = n / abs(n)
    if abs(n) > 1:
        return 1 * sign
    else:
        return n


def walk_seqstep(seqstep):
    """Compare two sequences by calling `advance_step` until it returns the result."""
    while not seqstep.result:
        seqstep.advance_step()


def eccentricity_anomaly(E, e, M):
    """Eccentric anomaly function"""
    import numpy as np
    return E - e * np.sin(E) - M


@staticmethod
def parse_data_string(data_string):
    """ Parses a string assumed to contain gene order data, retrieving information about fragment type, gene order, blocks names and their orientation

        First checks if gene order termination signs are present.
        Selects the earliest one.
        Checks that information preceding is not empty and contains gene order.
        Generates results structure by retrieving information about fragment type, blocks names and orientations.

        **NOTE:** comment signs do not work in data strings. Rather use the fact that after first gene order termination sign everything is ignored for processing

        :param data_string: a string to retrieve gene order information from
        :type data_string: ``str``
        :return: (``$`` | ``@``, [(``+`` | ``-``, block_name),...]) formatted structure corresponding to gene order in supplied data string and containing fragments type
        :rtype: ``tuple(str, list((str, str), ...))``
        """
    data_string = data_string.strip()
    linear_terminator_index = data_string.index('$'
        ) if '$' in data_string else -1
    circular_terminator_index = data_string.index('@'
        ) if '@' in data_string else -1
    if linear_terminator_index < 0 and circular_terminator_index < 0:
        raise ValueError(
            'Invalid data string. No chromosome termination sign ($|@) found.')
    if linear_terminator_index == 0 or circular_terminator_index == 0:
        raise ValueError(
            'Invalid data string. No data found before chromosome was terminated.'
            )
    if (linear_terminator_index < 0 or 0 < circular_terminator_index <
        linear_terminator_index):
        chr_type = '@'
        terminator_index = circular_terminator_index
    else:
        chr_type = '$'
        terminator_index = linear_terminator_index
    data = data_string[:terminator_index].strip()
    split_data = data.split()
    blocks = []
    for block in split_data:
        cut_index = 1 if block.startswith('-') or block.startswith('+') else 0
        if cut_index == 1 and len(block) == 1:
            raise ValueError('Empty block name definition')
        blocks.append(('-' if block.startswith('-') else '+', block[
            cut_index:]))
    return chr_type, blocks


@classmethod
def smart_variables(cls, options=None):
    """List all smart variables

        Usage::

            hammer hostgroup smart-variables [OPTIONS]

        Options::

            --hostgroup HOSTGROUP_NAME        Hostgroup name
            --hostgroup-id HOSTGROUP_ID
            --hostgroup-title HOSTGROUP_TITLE Hostgroup title
            --order ORDER                     sort results
            --page PAGE                       paginate results
            --per-page PER_PAGE               number of entries per request
            --search SEARCH                   filter results
        """
    cls.command_sub = 'smart-variables'
    return cls.execute(cls._construct_command(options), output_format='csv')


def port_int(p):
    """Pass through a port number (as a number or a string) provided it is valid and in range, otherwise raise an exception"""
    try:
        port = int(p)
    except:
        raise ValueError('Invalid port number')
    if port >= 0 and port <= 65535:
        return port
    else:
        raise ValueError('Port number out of range')


def get_user_id(handler_input):
    """Return the userId in the request.

    The method retrieves the ``userId`` from the input request.
    This value uniquely identifies the user and is generally used as input for
    some Alexa-specific API calls.
    More information about this can be found here:
    https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#system-object
    :param handler_input: The handler input instance that is generally
        passed in the sdk's request and exception components
    :type handler_input: ask_sdk_core.handler_input.HandlerInput
    :return: Users userId or None if not available
    :rtype: Optional[str]
    """
    user = handler_input.request_envelope.context.system.user
    return user.user_id if user else None


def decode(val):
    """Try to decode a string, and don't stop code execution if it fails.

    Args:
        val (str): Should be a string.

    Returns:
        str: Should also be a string.
    """
    if val is None or str(val) == str(''):
        return None
    if str(str(val).strip()) == str('NULL'):
        return None
    try:
        return val.decode('utf-8')
    except Exception:
        try:
            return val.decode('latin-1')
        except Exception:
            try:
                return val.decode('ascii')
            except Exception:
                pass
    return val


@classmethod
def AddArguments(cls, argument_group):
    """Adds command line arguments to an argument group.

    This function takes an argument parser or an argument group object and adds
    to it all the command line arguments this helper supports.

    Args:
      argument_group (argparse._ArgumentGroup|argparse.ArgumentParser):
          argparse group.
    """
    argument_group.add_argument('--temporary_directory',
        '--temporary-directory', dest='temporary_directory', type=str,
        action='store', metavar='DIRECTORY', help=
        'Path to the directory that should be used to store temporary files created during processing.'
        )


def get_trend(timeseries):
    """
    Using the values returned by get_timeseries(), compare the current
    Metric value with it's previous period's value

    :param timeseries: data returned from the get_timeseries() method
    :returns: the last period value and relative change
    """
    last = timeseries['value'][len(timeseries['value']) - 1]
    prev = timeseries['value'][len(timeseries['value']) - 2]
    trend = last - prev
    trend_percentage = None
    if last == 0:
        if prev > 0:
            trend_percentage = -100
        else:
            trend_percentage = 0
    else:
        trend_percentage = int(trend / last * 100)
    return last, trend_percentage


def clean_ns(tag):
    """Return a tag and its namespace separately."""
    if '}' in tag:
        split = tag.split('}')
        return split[0].strip('{'), split[-1]
    return '', tag


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

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


def usePython():
    """
    Force the use of the Python implementation of the kernels
    """
    global kernels_imp
    from . import _kernels_py
    kernels_imp = _kernels_py


@classmethod
def row2data(cls, row):
    """Convertit une ligne lue depuis le cache CSV en flottant."""
    return float(row[0])


@classmethod
def close(cls):
    """Close file stats file"""
    assert cls._fileobj, cls._fileobj
    if cls.line_buffer:
        cls.write_buffer()
    assert not cls._fileobj.close()
    cls._fileobj = cls._rp = None


def launch(url, wait=False, locate=False):
    """This function launches the given URL (or filename) in the default
    viewer application for this file type.  If this is an executable, it
    might launch the executable in a new session.  The return value is
    the exit code of the launched application.  Usually, ``0`` indicates
    success.

    Examples::

        click.launch('http://click.pocoo.org/')
        click.launch('/my/downloaded/file', locate=True)

    .. versionadded:: 2.0

    :param url: URL or filename of the thing to launch.
    :param wait: waits for the program to stop.
    :param locate: if this is set to `True` then instead of launching the
                   application associated with the URL it will attempt to
                   launch a file manager with the file located.  This
                   might have weird effects if the URL does not point to
                   the filesystem.
    """
    from ._termui_impl import open_url
    return open_url(url, wait=wait, locate=locate)


def inductionName(ext: str, sensor: str, serial: int, chopper: bool) ->str:
    """Get internal format induction coil calibration file name

    Parameters
    ----------
    ext : str
        Calibration file extension
    sensor : str
        Sensor name
    serial : int
        The sensor serial number
    chopper : bool
        Boolean flag for chopper on or off

    Returns
    -------
    out : str
        Name of calibration file
    """
    return 'IC_{}.{}'.format(serial, ext)


def getSpectroscopicParmLabel(expt_type):
    """
    Returns the label for the spectroscopic parameter in the plot group.

    Parameters
    ----------
    expt_type : str
        Type of the experiment - found in the parms.txt file

    Returns
    -------
    str
        label for the spectroscopic parameter axis in the plot
    """
    if expt_type in ['DC modulation mode', 'current mode']:
        return 'DC Bias'
    elif expt_type == 'AC modulation mode with time reversal':
        return 'AC amplitude'
    return 'User Defined'


@classmethod
def from_string(cls, rgb_hex_str):
    """
        Return a new instance from an RGB color hex string like ``'3C2F80'``.
        """
    r = int(rgb_hex_str[:2], 16)
    g = int(rgb_hex_str[2:4], 16)
    b = int(rgb_hex_str[4:], 16)
    return cls(r, g, b)


def web_ui_names():
    """Return dict of web UI JSON naming conventions"""
    maps = {'TimePerEvent': 'TimePerEvent (seconds)', 'OpenRunningTimeout':
        'OpenRunningTimeout (deprecated)', 'SizePerEvent':
        'SizePerEvent (KBytes)', 'Memory': 'Memory (MBytes)',
        'BlockCloseMaxSize': 'BlockCloseMaxSize (Bytes)', 'SoftTimeout':
        'SoftTimeout (seconds)'}
    return maps


def distribute_evenly(items, num_buckets):
    """
    Distribute items as evenly as possible into N buckets.
    """
    out = [[] for _ in range(num_buckets)]
    for index, item in enumerate(items):
        out[index % num_buckets].append(item)
    return out


def to_filename(name):
    """Convert a project or version name to its filename-escaped form

    Any '-' characters are currently replaced with '_'.
    """
    return name.replace('-', '_')


@classmethod
def get_extend_raw_conf(cls, raw_conf, language):
    """ Take a raw conf that might not have all the parameters and
            add the missing with default value into a new returned raw conf
        """
    def_conf = cls._get_default_raw_conf(language)
    res = cls._get_update_left_with_right_raw_conf(def_conf, raw_conf,
        same_key=False)
    return res


def stream_response(response, chunk_size=8 * 1024):
    """Read the response in chunks."""
    while True:
        buf = response.read(chunk_size)
        if not buf:
            break
        yield buf


def post_process_request(req, template, data, content_type):
    """Do any post-processing the request might need; typically adding
        values to the template `data` dictionary, or changing template or
        mime type."""
    return template, data, content_type


def UniqueSet(aset):
    """
remove repeated item in set
    """
    return set(aset)


def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
    """Remove matching input prompts from a block of input.

    Parameters
    ----------
    prompt_re : regular expression
        A regular expression matching any input prompt (including continuation)
    initial_re : regular expression, optional
        A regular expression matching only the initial prompt, but not continuation.
        If no initial expression is given, prompt_re will be used everywhere.
        Used mainly for plain Python prompts, where the continuation prompt
        ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.

    If initial_re and prompt_re differ,
    only initial_re will be tested against the first line.
    If any prompt is found on the first two lines,
    prompts will be stripped from the rest of the block.
    """
    if initial_re is None:
        initial_re = prompt_re
    line = ''
    while True:
        line = yield line
        if line is None:
            continue
        out, n1 = initial_re.subn('', line, count=1)
        if turnoff_re and not n1:
            if turnoff_re.match(line):
                while line is not None:
                    line = yield line
                continue
        line = yield out
        if line is None:
            continue
        out, n2 = prompt_re.subn('', line, count=1)
        line = yield out
        if n1 or n2:
            while line is not None:
                line = yield prompt_re.sub('', line, count=1)
        else:
            while line is not None:
                line = yield line


def render_latex_mpl(text, path, color=(0, 0, 0), dpi=600, output='png'):
    """
    Render a LaTeX-formula into an image with matplotlib.

    Parameters
    ----------
    text : string
        String containing the latex-code.
    path : string
        Path to the file to be saved.
    color : tuple, optional
        color of the text given as rgb tuple. Default: ``(0, 0, 0)``
    dpi : int, optional
        Used dpi. Default: 1200
    output : string, optional
        Output format. Default: ``"png"``

    Notes
    -----
    If you get the following error:

        ``RuntimeError: libpng signaled error``

    Try to set the dpi higher. (1200 recomended)

    If big symbols like ``\\int`` or ``\\sum`` don't show up properly,
    try setting a

        ``\\displaystyle``

    infront of them.
    """
    from matplotlib.mathtext import MathTextParser
    from matplotlib.font_manager import FontProperties
    from matplotlib import figure, rc
    from matplotlib.backends import backend_agg
    rc('text', usetex=False)
    prop = FontProperties()
    parser = MathTextParser('path')
    width, height, depth, _, _ = parser.parse(text, dpi=72, prop=prop)
    fig = figure.Figure(figsize=(width / 72.0, height / 72.0))
    fig.text(0, depth / height, text, fontproperties=prop, color=color)
    backend_agg.FigureCanvasAgg(fig)
    fig.savefig(path, dpi=dpi, format=output, transparent=True)


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 write_weight_file(weights, outputFile):
    """ output the RSCUs or weights """
    with open(outputFile, 'w') as f:
        f.write('%s\t%s\n' % ('codons', 'weights'))
        for k, v in weights.items():
            f.write('%s\t%s\n' % (str(k), str(v)))


def isolate_type_render():
    """Hide unselected render objects of same type as active by setting the hide render flag

    """
    pass


def GetHTMLColor(color):
    """Convert single-channeled colors or (R, G, B) tuples to #RRGGBB.

    If the color has only one channel (grayscale, typically), it is converted
    to a (R, G, B) tuple first.

    Parameters
    ----------
    color : int or list
        Grayscale value or list of red, green, blue pixel values

    Returns
    -------
    str
        HTML-version of color
    """
    rgb_tuple = (color, color, color) if type(color) == int else color
    return '#%02x%02x%02x' % tuple(rgb_tuple)


def read_pcd_file(path):
    """
    Reads a *.pcd pointcloud file
    :param path: path to the *.pcd pointcloud file
    :return: list of points
    """
    with open(path) as f:
        data = f.readline().split()
        num_points = 0
        while data[0] != 'DATA':
            if data[0] == 'POINTS':
                num_points = int(data[1])
            data = f.readline().split()
            continue
        return [tuple(map(float, f.readline().split())) for _ in range(
            num_points)]


def hasClosingPunctuation(text: str) ->bool:
    """
    Return True if the text ends with a period or question mark or exclamation mark, or something like '.)'

    Note that the colon, etc. is not included here because it's a special case.
    """
    if not text:
        return False
    for period in '.።?!':
        if text[-1] == period:
            return True
        for closingPunctuation in ')]"\'”’»›':
            if text.endswith(period + closingPunctuation):
                return True
    return False


def is_valid_smb_hidden_files(smb_hidden_files):
    """
    Validates smbhiddenfiles NAS volume parameter.  String should be forward
    slash (/) delimited.

    :type smb_hidden_files: str
    :param smb_hidden_files: The smbhiddenfiles parameter to be validated.

    :rtype: bool
    :return: True or False depending on whether smb_hidden_files passes
        validation.
    """
    if smb_hidden_files is None:
        return False
    if not smb_hidden_files.startswith('/') or not smb_hidden_files.endswith(
        '/'):
        return False
    return True


def format_to_str(value, empty_value='--', format_string='%0.2f'):
    """
    Format value with format_string when evaluated as True
    else return the empty value
    """
    if not value:
        return empty_value
    return format_string % value


def getBrowserIdManager():
    """Return the nearest acquirable browser id manager.

        o Raise SessionDataManagerErr if no browser id manager can be found.

        o Permission required: Access session data
        """


def installGSDependencies(context):
    """Install dependend profiles."""
    return


@classmethod
def create_or_update(cls, fixed_kwargs: dict, new_additional_kwargs: dict):
    """
        Create object if doesnt exists. Else update it
        :param fixed_kwargs: key values to find object in db
        :param new_additional_kwargs: new changing kwargs
        :return: found/created object and True if created, False if found
        """
    try:
        found = cls.objects.get(**fixed_kwargs)
        for key, value in new_additional_kwargs.items():
            found.__setattr__(key, value)
        found.save()
        return found, False
    except cls.DoesNotExist:
        return cls.objects.create(**{**fixed_kwargs, **new_additional_kwargs}
            ), True


@staticmethod
def get_name():
    """
        Get the name of the extractor.
        :return: the name of the extractor
        """
    return 'FASTQ'


def srfqe(wavelength, QE):
    """'converts a QE in units to spectral response
    given the wavelength (nm)"""
    spectral_response = QE * wavelength / 1239.8
    return spectral_response


def igrf_print(igrf_array):
    """
    Print out Declination, Inclination, Intensity from an array returned from
    the igrf function.

    Parameters
    ----------
    igrf_array : array that is output from ipmag.igrf function

    Examples
    --------
    An array generated by the ``ipmag.igrf`` function is passed to ``ipmag.igrf_print``

    >>> local_field = ipmag.igrf([2013.6544, .052, 37.87, -122.27])
    >>> ipmag.igrf_print(local_field)
    Declination: 13.950
    Inclination: 61.352
    Intensity: 48744.848 nT
    """
    print('Declination: %0.3f' % igrf_array[0])
    print('Inclination: %0.3f' % igrf_array[1])
    print('Intensity: %0.3f nT' % igrf_array[2])


@classmethod
def build(cls, path: str) ->object:
    """
        Identify and instantiate a module.

        :param path: Path to module
        :return: Newly instantiated module
        """
    label = cls.identify(path)
    if label:
        mod = cls.instantiate(label)
        if mod:
            return mod
        else:
            raise cls.Exception('Error loading module: %s' % label)
    else:
        raise cls.Exception('Module not found: %s' % path)
    return None


def get_server_certificate(ServerCertificateName=None):
    """
    Retrieves information about the specified server certificate stored in IAM.
    For more information about working with server certificates, including a list of AWS services that can use the server certificates that you manage with IAM, go to Working with Server Certificates in the IAM User Guide .
    See also: AWS API Documentation

    :example: response = client.get_server_certificate(
        ServerCertificateName='string'
    )

    :type ServerCertificateName: string
    :param ServerCertificateName: [REQUIRED]
            The name of the server certificate you want to retrieve information about.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: =,.@-

    :rtype: dict
    :return: {
        'ServerCertificate': {
            'ServerCertificateMetadata': {
                'Path': 'string',
                'ServerCertificateName': 'string',
                'ServerCertificateId': 'string',
                'Arn': 'string',
                'UploadDate': datetime(2015, 1, 1),
                'Expiration': datetime(2015, 1, 1)
            },
            'CertificateBody': 'string',
            'CertificateChain': 'string'
        }
    }

    """
    pass


def remove_text_if_not_tick(tick_values, text_values):
    """
    removes text so that no text is in place where not ticks
    """
    for text_value in text_values:
        if tick_values.count(text_value) == 0:
            text_values.remove(text_value)


def get_routes():
    """ Return a sequence of Route objects registered in the mapper.
        Static routes will not be returned in this sequence."""


def unique(df, columns=None):
    """Asserts that columns in `df` only have unique values.

    Args:
        df (pd.DataFrame): Any pd.DataFrame.
        columns (list): A subset of columns to check for uniqueness of row values.

    Returns:
        Original `df`.

    """
    if columns is None:
        columns = df.columns
    for col in columns:
        if not df[col].is_unique:
            raise AssertionError('Column {!r} contains non-unique values'.
                format(col))
    return df


@staticmethod
def convert_nb(text):
    """Tries to convert the given the given text as a number.

        Also work with scientific notation like 1e+50.

        Arguments
        ---------
        text : string
            The text to convert.

        Result
        ------
        int or float

        Example
        -------

        >>> BaseParser('').convert_nb('1')
        1
        >>> BaseParser('').convert_nb('-3')
        -3
        >>> BaseParser('').convert_nb('0')
        0
        >>> BaseParser('').convert_nb('0.0')
        0.0
        >>> BaseParser('').convert_nb('1.0')
        1.0
        >>> BaseParser('').convert_nb('9999999999')
        9999999999
        >>> BaseParser('').convert_nb('1e+50')
        1e+50
        >>> BaseParser('').convert_nb('-2.5e33')
        -2.5e+33

        """
    try:
        return int(text)
    except ValueError:
        return float(text)


def nt_escape(node_string):
    """Properly escape strings for n-triples and n-quads serialization."""
    output_string = ''
    for char in node_string:
        if char == u'\t':
            output_string += '\\t'
        elif char == u'\n':
            output_string += '\\n'
        elif char == u'\r':
            output_string += '\\r'
        elif char == u'"':
            output_string += '\\"'
        elif char == u'\\':
            output_string += '\\\\'
        elif char >= u' ' and char <= u'!' or char >= u'#' and char <= u'[' or char >= u']' and char <= u'~':
            output_string += char
        elif char >= u'\x7f' and char <= u'\uffff':
            output_string += '\\u%04X' % ord(char)
        elif char >= u'𐀀' and char <= u'\U0010ffff':
            output_string += '\\U%08X' % ord(char)
    return output_string


def buiild_canonicalized_headers(headers, prefix):
    """
    aliyun的header里的canonicalized属性排序和计算
    :param headers:
    :param prefix:
    :return:
    """
    canonicalized_headers = ''
    if len(headers) > 0:
        x_header_list = headers.keys()
        sorted(x_header_list)
        for k in x_header_list:
            if k.startswith(prefix):
                canonicalized_headers += k + ':' + headers[k] + '\n'
    return canonicalized_headers


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 normalize_name(string):
    """convert to lowercase, remove spaces and underscores"""
    return string.replace(' ', '').replace('_', '').lower()


@classmethod
def reconstruct_common(cls, t, x, y, z=None, initial=None):
    """Reconstruct angles from 3 or more detections

        This function converts the arguments to be suitable for the
        algorithm.

        :param t: arrival times of the detectors in ns.
        :param x,y,z: positions of the detectors in m. The height
                      for all detectors will be set to 0 if not given.
        :param initial: dictionary containing values from previous
                        reconstructions is ignored.

        """
    if z is None:
        z = [0] * len(x)
    return cls.reconstruct(t, x, y, z)


def rules_stats(rules, itemsets, n_examples):
    """
    Generate additional stats for rules generated by :obj:`association_rules()`.

    Parameters
    ----------
    rules: iterable
        Rules as output by `association_rules()`.
    itemsets: dict
        The itemsets as obtained by `dict(frequent_itemsets(...))`.
    n_examples: int
        The total number of instances (for calculating coverage, lift,
        and leverage).

    Yields
    ------
    atecedent: frozenset
        The LHS of the association rule.
    consequent: frozenset
        The RHS of the association rule.
    support: int
        Support as an absolute number of instances.
    confidence: float
        The confidence percent, calculated as: ``total_support / lhs_rupport``.
    coverage: float
        Calculated as: ``lhs_support / n_examples``
    strength: float
        Calculated as: ``rhs_support / lhs_examples``
    lift: float
        Calculated as: ``n_examples * total_support / lhs_support / rhs_support``
    leverage: float
        Calculated as: ``(total_support * n_examples - lhs_support * rhs_support) / n_examples**2``

    Examples
    --------
    >>> N = 30
    >>> X = np.random.random((N, 50)) > .9
    >>> itemsets = dict(frequent_itemsets(X, .1))
    >>> rules = association_rules(itemsets, .6)
    >>> list(rules_stats(rules, itemsets, N))
    [(frozenset({15}), frozenset({0}), 3, 0.75, 0.13..., 1.5, 3.75, 0.073...),
     (frozenset({47}), frozenset({22}), 3, 0.6, 0.16..., 1.4, 2.57..., 0.061...),
     (frozenset({27}), frozenset({22}), 4, 0.66..., 0.2, 1.16..., 2.85..., 0.086...),
     (frozenset({19}), frozenset({22}), 3, 0.6, 0.16..., 1.4, 2.57..., 0.061...)]

    """
    assert isinstance(itemsets, dict) and isinstance(next(iter(itemsets),
        frozenset()), frozenset)
    assert n_examples > 0
    for left, right, support, confidence in rules:
        l_support, r_support = itemsets[left], itemsets[right]
        coverage = l_support / n_examples
        strength = r_support / l_support
        lift = n_examples * confidence / r_support
        leverage = (support * n_examples - l_support * r_support
            ) / n_examples ** 2
        yield left, right, support, confidence, coverage, strength, lift, leverage


def _discard_firestore_client() ->None:
    """Only to be used by the test suite.
    """
    global _firestore_client
    _firestore_client = None


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


@classmethod
def create(cls, consumer, userid, session=None, **kwargs):
    """Create an access token instance and assign it to the consumer and
        user
        """
    return cls._create_token(consumer.access_tokens, userid=userid, session
        =session, **kwargs)


def round_up(integer, multiple):
    """Round up to the nearest multiple"""
    if multiple <= 0:
        raise ValueError('Can not round up to non-positive multiple {}'.
            format(multiple))
    return (integer if integer % multiple == 0 else integer + multiple -
        integer % multiple)


def dirs():
    """Returns an object implementing the ``idirs`` interface."""


def _update_hparams(hparams, is_training):
    """Update hparams for given is_training option."""
    if not is_training:
        hparams.set_hparam('drop_path_keep_prob', 1.0)