def p_postfix_expression(p):
    """postfix_expression : postfix_expression_call
                          | postfix_expression_fact
                          | postfix_expression_binary
                          | postfix_expression_unary
                          | primary_expression
                          """
    p[0] = p[1]


def has_payment_id(extra_nonce):
    """
    Returns true if payment id is present
    :param extra_nonce:
    :return:
    """
    return len(extra_nonce) == 33 and extra_nonce[0] == 0


def average_precision_compute_fn(y_pred, y_true):
    """Attached function to the custom ignite metric AveragePrecisionMultiLabel

    Args:
        y_pred (:obj:`torch.Tensor`): model predictions
        y_true (:obj:`torch.Tensor`): ground truths

    Raises:
        RuntimeError: Indicates that sklearn should be installed by the user.

    Returns:
        :obj:`numpy.array`: average precision vector.
                            Of the same length as the number of labels present in the data
    """
    try:
        from sklearn.metrics import average_precision_score
    except ImportError:
        raise RuntimeError('This metric requires sklearn to be installed.')
    ap = average_precision_score(y_true.numpy(), y_pred.numpy(), None)
    return ap


def get_dataset(*args):
    """
	.. warning:: Deprecated

		**get_dataset** is deprecated and will be removed from future versions of **spm1d**.  Please access datasets using the "spm1d.data" interface.
	"""
    raise IOError(
        '"get_dataset" is deprecated.  Please access datasets using "spm1d.data".'
        )


@staticmethod
def _get_row_col_inds(sc_point_gids, row_length):
    """
        Convert supply curve point gids to row and col indices given row length

        Parameters
        ----------
        sc_point_gids : int | list | ndarray
            Supply curve point gid or list/array of gids
        row_length : int
            row length (shape[1])

        Returns
        -------
        row : int | list | ndarray
            row indices
        col : int | list | ndarray
            row indices
        """
    rows = sc_point_gids // row_length
    cols = sc_point_gids % row_length
    return rows, cols


def parse_regex_string(string):
    """
    Parse header string according to wappalizer DB format

    strings follow the below format:
    <string>[\\;version:\\\\d][\\;confidence:\\d]

    "string" is a mandatory regex string followed by 0 or more parameters (key:value), can be empty
    parameters are divided by a \\; sequence (a backslash followed by a semicolon)

    examples of parameters are:
    "version": indicate wich regex group store the version information
    "confidence": indicate a rate of confidence
    """
    parts = string.split('\\;')
    if len(parts) == 1:
        return parts[0], None
    else:
        extra = {}
        for p in parts[1:]:
            p = p.split(':')
            extra[p[0]] = p[1]
        return parts[0], extra


@classmethod
def _dynamo_to_python_attr(cls, dynamo_key):
    """
        Convert a DynamoDB attribute name to the internal Python name.

        This covers cases where an attribute name has been overridden via "attr_name".
        """
    return cls._dynamo_to_python_attrs.get(dynamo_key, dynamo_key)


@staticmethod
def free_dum_from_indices(*indices):
    """
        Convert ``indices`` into ``free``, ``dum`` for single component tensor

        ``free``     list of tuples ``(index, pos, 0)``,
                     where ``pos`` is the position of index in
                     the list of indices formed by the component tensors

        ``dum``      list of tuples ``(pos_contr, pos_cov, 0, 0)``

        Examples
        ========

        >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
        >>> m0, m1, m2, m3 = tensor_indices('m0 m1 m2 m3', Lorentz)
        >>> TIDS.free_dum_from_indices(m0, m1, -m1, m3)
        ([(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])

        """
    n = len(indices)
    if n == 1:
        return [(indices[0], 0, 0)], []
    free = [True] * len(indices)
    index_dict = {}
    dum = []
    for i, index in enumerate(indices):
        name = index._name
        typ = index._tensortype
        contr = index._is_up
        if (name, typ) in index_dict:
            is_contr, pos = index_dict[name, typ]
            if is_contr:
                if contr:
                    raise ValueError(
                        f'two equal contravariant indices in slots {pos:d} and {i:d}'
                        )
                else:
                    free[pos] = False
                    free[i] = False
            elif contr:
                free[pos] = False
                free[i] = False
            else:
                raise ValueError(
                    f'two equal covariant indices in slots {pos:d} and {i:d}')
            if contr:
                dum.append((i, pos, 0, 0))
            else:
                dum.append((pos, i, 0, 0))
        else:
            index_dict[name, typ] = index._is_up, i
    free = [(index, i, 0) for i, index in enumerate(indices) if free[i]]
    free.sort()
    return free, dum


def _output(result):
    """Common User interface"""
    print('=' * 34)
    print('WELCOME, Your search results are : ')
    print('=' * 34)
    for i, data in enumerate(result):
        num = i + 1
        print('{index}. {data_name}'.format(index=num, data_name=data.get(
            'name')))
    return


def hex2rgb(clr):
    """Convert hex to rgb values.
    - (r,g,b) where each value is 0..255
    - RRGGBB where each value is 00..FF"""
    return tuple(map(ord, clr[1:].decode('hex')))


def _get_conf(textequiv, default=1.0):
    """get float value of conf attribute with default"""
    return float(textequiv.conf or str(default))


def rvdw_change(rotamer_library, radius_vdw_info, start_index, end_index):
    """
    Change all radius vanderwals 0 to 0.5
    from the rotamer's library file
  """
    with open(rotamer_library, 'r') as f:
        lines = f.readlines()
        for i, new_line in enumerate(radius_vdw_info):
            lines[start_index + i] = (
                '{0:>5} {1:>8} {2:>8} {3:>10} {4:>8} {5:>8} {6:>13} {7:>13}\n'
                .format(*new_line))
    with open(rotamer_library, 'w') as f:
        f.write(''.join(lines))


def helical_transition_Re_Kubair_Kuloor(Di, Dc):
    """Calculates the transition Reynolds number for flow inside a curved or
    helical coil between laminar and turbulent flow, using the method of [1]_,
    as shown in [2]_.

    .. math::
        Re_{crit} = 12730 \\left(\\frac{D_i}{D_c}\\right)^{0.2}

    Parameters
    ----------
    Di : float
        Inner diameter of the coil, [m]
    Dc : float
        Diameter of the helix/coil measured from the center of the tube on one
        side to the center of the tube on the other side, [m]

    Returns
    -------
    Re_crit : float
        Transition Reynolds number between laminar and turbulent [-]

    Notes
    -----
    At very low curvatures, converges to Re = 0.
    Recommended for :math:`0.0005 < d_i/D_c < 0.103`

    Examples
    --------
    >>> helical_transition_Re_Kubair_Kuloor(1, 7.)
    8625.986927588123

    References
    ----------
    .. [1] Kubair, Venugopala, and N. R. Kuloor. "Heat Transfer to Newtonian
       Fluids in Coiled Pipes in Laminar Flow." International Journal of Heat
       and Mass Transfer 9, no. 1 (January 1, 1966): 63-75.
       doi:10.1016/0017-9310(66)90057-3.
    .. [2] El-Genk, Mohamed S., and Timothy M. Schriener. "A Review and
       Correlations for Convection Heat Transfer and Pressure Losses in
       Toroidal and Helically Coiled Tubes." Heat Transfer Engineering 0, no. 0
       (June 7, 2016): 1-28. doi:10.1080/01457632.2016.1194693.
    """
    return 12730.0 * (Di / Dc) ** 0.2


def update_field(pc, field, pc_data):
    """ Updates field in-place.
    """
    pc.pc_data[field] = pc_data
    return pc


def solve(fzn):
    """Call FlatZinc solver (Gecode) and process output."""
    import subprocess
    from problog.util import mktempfile
    fznfile = mktempfile('.fzn')
    with open(fznfile, 'w') as f:
        f.write(fzn)
    cmd = ['fzn-gecode', '-a', fznfile]
    result = subprocess.check_output(cmd).decode()
    current = {}
    for line in result.split('\n'):
        if line.startswith('----'):
            yield current
            current = {}
        elif line.startswith('===='):
            return
        else:
            vr, vl = line.strip(';').split(' = ')
            vr = int(vr[1:])
            vl = 1 if vl == 'true' else 0
            current[vr] = vl


def ensure_exists(path, is_dir=False):
    """
    Ensures a path exists.

    :param path: the path to ensure
    :type path: pathlib.Path
    :param is_dir: whether the path is a directory.
    :type is_dir: bool
    """
    path.parent.mkdir(parents=True, exist_ok=True)
    if is_dir:
        path.mkdir(exist_ok=True)
    else:
        path.touch()


def count_ones_iter(n):
    """Using Brian Kernighan’s Algorithm. (Iterative Approach)"""
    count = 0
    while n:
        n &= n - 1
        count += 1
    return count


def add():
    """Add a new time marker

    """
    pass


def _split_line(line, id_offset):
    """
    First 10 chars must be blank or contain id info
    """
    if not line or not line.strip():
        return None, None
    curr_id = line[0:id_offset].strip()
    curr_seq = line[id_offset:].strip().replace(' ', '')
    return curr_id, curr_seq


@classmethod
def init_silent(cls, numbering=None):
    """Create and return a silent Numbering."""
    num = cls(numbering)
    num.silent = True
    return num


def closeChildFD(descriptor):
    """
        Close a file descriptor which is connected to the child process, identified
        by its FD in the child process.
        """


@classmethod
def from_line(cls, line, user=None, cron=None):
    """
        Generate CronItem from a cron-line and parse out command and comment
        """
    obj = cls(user=user, cron=cron)
    obj.parse(line.strip())
    return obj


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 addTemplate(id, template):
    """ add the given ttw view template to the container
            and return it acquisition wrapped in the container """


def to_string(s):
    """desperate attempt to convert a string regardless of what garbage we get"""
    try:
        return s.decode('utf-8')
    except Exception as e:
        pass
    try:
        s2 = s.encode('utf-8', 'ignore')
        x = u'%s' % s2
        return s2
    except Exception:
        pass
    r = ''
    while s != '':
        try:
            r2 = r + s[0]
            s = s[1:]
            r2 = r2.encode('ascii', 'ignore')
            x = u'%s' % r2
            r = r2
        except Exception:
            break
    return r + '_XXX'


def get_fs_undf_name(function_space):
    """ Returns a undf name for this FunctionSpace object. """
    return 'undf_' + function_space.mangled_name


def evaluate(data_conf, model_conf, **kwargs):
    """Python evaluate method called by AOA framework

    Parameters:
    data_conf (dict): The dataset metadata
    model_conf (dict): The model configuration to use

    Returns:
    None:No return

    """
    print('Evaluation complete...')


def format_var_info(tok, _dict, _global=''):
    """Formats the variable information so that it fits on a single line
       for each variable.

       The format we want is something like the following:

       [global] name: repr(name)

       However, if repr(name) exceeds a certain value, it is truncated.
       When that is the case, if len(name) is defined, as is the case for
       lists, tuples, dicts, etc., then len(name) is shown on a separate line.
       This can be useful information in case of IndexError and possibly
       others.
    """
    MAX_LENGTH = 50
    length_info = ''
    if _global:
        _global = 'global '
    name = tok.string
    obj = _dict[name]
    try:
        value = repr(obj)
    except Exception:
        return ''
    if value.startswith('<') and value.endswith('>') and ' at ' in value:
        value = value.split(' at ')[0] + '>'
    if len(value) > MAX_LENGTH:
        value = value[0:MAX_LENGTH - 5] + '...' + value[-1]
        try:
            length_info = len(obj)
        except TypeError:
            pass
    result = f'    {_global}{name}: {value}'
    if length_info:
        result += f'  | len({name}): {length_info}'
    return result


def attach(container, columns):
    """
        This is called after we've been attached to a search container

        :param SearchContainer container: the search container
        :param columns: list of objectlist columns
        """


@classmethod
def flush_event_listeners(cls):
    """
        Remove all of the event listeners for the model.
        """
    if not cls.__dispatcher__:
        return
    for event in cls.get_observable_events():
        cls.__dispatcher__.forget('%s: %s' % (event, cls.__name__))


def normallookup(f):
    """Mark a file normal, but possibly dirty."""


def filetypes():
    """Get supported archive filetypes for model export."""
    return {'npz': 'Numpy Zipped Archive'}


def opengl(animation: bool=False, sequencer: bool=False, write_still: bool=
    False, view_context: bool=True):
    """Take a snapshot of the active viewport

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


def set_col_kind(me, xid, kind):
    """set_col_kind with transparent index mapping."""
    xid = me._colmap.map(xid) if xid else xid
    if xid > 0:
        return me._set_col_kind(xid, kind)


def is_protein_or_chemical(agent):
    """Return True if the agent is a protein/protein family or chemical."""
    if agent is None:
        return True
    dbs = set(['UP', 'HGNC', 'CHEBI', 'PFAM-DEF', 'IP', 'INDRA', 'PUBCHEM',
        'CHEMBL'])
    agent_refs = set(agent.db_refs.keys())
    if agent_refs.intersection(dbs):
        return True
    return False


@staticmethod
def body(request_bounds, request_data, evalscript, request_output=None,
    other_args=None):
    """ Generate the body the Processing API request body

        :param request_bounds: A dictionary as generated by `SentinelHubRequest.bounds` helper method.
        :type request_bounds: dict
        :param request_data: A list of dictionaries as generated by `SentinelHubRequest.input_data` helper method.
        :type request_data: List[dict]
        :param evalscript: Evalscript (https://docs.sentinel-hub.com/api/latest/#/Evalscript/)
        :type evalscript: str
        :param request_output: A dictionary as generated by `SentinelHubRequest.output` helper method.
        :type request_output: dict
        :param other_args: Additional dictionary of arguments. If provided, the resulting dictionary will get updated
                           by it.
        :param other_args: dict
        """
    request_body = {'input': {'bounds': request_bounds, 'data':
        request_data}, 'evalscript': evalscript}
    if request_output is not None:
        request_body['output'] = request_output
    if other_args:
        request_body.update(other_args)
    return request_body


def DefaultExtension(schema_obj, form_obj, schemata=None):
    """Create a default field"""
    if schemata is None:
        schemata = ['systemconfig', 'profile', 'client']
    DefaultExtends = {'schema': {'properties/modules': [schema_obj]},
        'form': {'modules': {'items/': form_obj}}}
    output = {}
    for schema in schemata:
        output[schema] = DefaultExtends
    return output


def describe_account_limits():
    """
    Describes the current Auto Scaling resource limits for your AWS account.
    For information about requesting an increase in these limits, see AWS Service Limits in the Amazon Web Services General Reference .
    See also: AWS API Documentation

    Examples
    This example describes the Auto Scaling limits for your AWS account.
    Expected Output:

    :example: response = client.describe_account_limits()

    :rtype: dict
    :return: {
        'MaxNumberOfAutoScalingGroups': 123,
        'MaxNumberOfLaunchConfigurations': 123,
        'NumberOfAutoScalingGroups': 123,
        'NumberOfLaunchConfigurations': 123
    }

    """
    pass


def copy(brain):
    """Copy the figure to the clip board"""
    return brain.copy_screenshot()


def tuple_search(t, i, v):
    """
    Search tuple array by index and value
    :param t: tuple array
    :param i: index of the value in each tuple
    :param v: value
    :return: the first tuple in the array with the specific index / value
    """
    for e in t:
        if e[i] == v:
            return e
    return None


def getValues(context):
    """Return the values for the source in the given context."""


def class_props(cls):
    """
    ClassProps seems to have problems. While we're figuring out that,
    a simpler, less efficient, more direct solution.
    """
    classkeys = list(getattr(cls, '__dict__', {}).keys())
    slotkeys = list(getattr(cls, '__slots__', []))
    return classkeys + slotkeys


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

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

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


@classmethod
def _make_atom_key_from_parts(cls, atom_parts, all_parts=False):
    """ If all_parts is False, only key from the values that determine alternate locations """
    return cls.AtomLookupKey(name=atom_parts['name'], number=atom_parts[
        'number'] if all_parts else None, residue_name=atom_parts[
        'residue_name'], residue_number=atom_parts['residue_number'], chain
        =atom_parts['chain'], insertion_code=atom_parts['insertion_code'],
        segment_id=atom_parts.get('segment_id', ''), alternate_location=
        atom_parts['alternate_location'] if all_parts else None)


def get_int_from_str(txt):
    """
    converts txt to a integer number and returns this number
    return None if txt is not a number
    """
    try:
        number = int(txt)
        if number is not 0:
            return number
    except:
        return None


def pytest_runtest_teardown(item, nextitem):
    """ called after ``pytest_runtest_call``.

    :arg nextitem: the scheduled-to-be-next test item (None if no further
                   test item is scheduled).  This argument can be used to
                   perform exact teardowns, i.e. calling just enough finalizers
                   so that nextitem only needs to call setup-functions.
    """


def group2commdct(commdct, glist):
    """add group info tocomdct"""
    for (gname, objname), commitem in zip(glist, commdct):
        commitem[0]['group'] = gname
        commitem[0]['idfobj'] = objname
    return commdct


def copy_stack_trace(from_var, to_var):
    """
    Copies the stack trace from one or more tensor variables to
    one or more tensor variables and returns the destination variables.

    Parameters
    ----------
    from_var
        Tensor variable or list of tensor variables to copy stack traces from.
    to_var
        Tensor variable or list of tensor variables to copy stack traces to.

    Notes
    -----
    The stacktrace is assumed to be of the form of a list of lists
    of tuples. Each tuple contains the filename, line number, function name
    and so on. Each list of tuples contains the truples belonging to a
    particular variable.

    """
    tr = []
    if type(from_var) is list:
        for v in from_var:
            tr += getattr(v.tag, 'trace', [])
    else:
        tr = getattr(from_var.tag, 'trace', [])
    if tr and isinstance(tr[0], tuple):
        tr = [tr]
    if type(to_var) is list:
        for v in to_var:
            v.tag.trace = getattr(v.tag, 'trace', []) + tr
    else:
        to_var.tag.trace = getattr(to_var.tag, 'trace', []) + tr
    return to_var


def inch2mm(inches):
    """Convert inches to millimetres."""
    return inches * 25.4


def filter_type_one_fault_results(type_one_faults, relay_timeseries):
    """
       type_one_fault_check can return a lot of points.  All most people care about is the fault type and (probably) start and end time (if applicable).  This does the filtering to return such a list
    """
    from Hard_Fault import Hard_Fault
    res = []
    if not type_one_faults or len(type_one_faults) == 0:
        return []
    if len(type_one_faults) == 1:
        relay_status_pt, fault_text = type_one_faults[0]
        res.append(Hard_Fault(relay_status_pt.time, relay_status_pt.time,
            fault_text))
        return res
    cur_fault_points = [type_one_faults[0]]
    idx = 1
    while idx < len(type_one_faults):
        cur_fault_relay_pt, cur_fault_txt = type_one_faults[idx]
        last_fault_relay_pt, last_fault_txt = cur_fault_points[-1]
        cur_fault_relay_idx = relay_timeseries.index((cur_fault_relay_pt.
            time, cur_fault_relay_pt.value))
        last_fault_relay_idx = relay_timeseries.index((last_fault_relay_pt.
            time, last_fault_relay_pt.value))
        if (cur_fault_relay_idx != last_fault_relay_idx + 1 or
            cur_fault_txt != last_fault_txt):
            res.append(Hard_Fault(cur_fault_points[0][0].time,
                cur_fault_points[-1][0].time, last_fault_txt))
            cur_fault_points = [type_one_faults[idx]]
            idx += 1
        else:
            cur_fault_points.append((cur_fault_relay_pt, cur_fault_txt))
            idx += 1
    if len(cur_fault_points) > 0:
        res.append(Hard_Fault(cur_fault_points[0][0].time, cur_fault_points
            [-1][0].time, last_fault_txt))
    return res


def distribute_value(samples, spacing=1.0, range_start=0.0, range_end=1.0):
    """
    Returns a list of values distributed between a start and end range
    :param samples: int, number of values to sample across the value range
    :param spacing: float, incremental scale for each sample distance
    :param range_start: float, minimum value in the sample range
    :param range_end: float, maximum value in the sample range
    :return: list<float>
    """
    value_list = [range_start]
    value_dst = abs(range_end - range_start)
    unit = 1.0
    factor = 1.0
    for i in range(samples - 2):
        unit += factor * spacing
        factor *= spacing
    unit = value_dst / unit
    total_unit = unit
    for i in range(samples - 2):
        mult_factor = total_unit / value_dst
        value_list.append(range_start - (range_start - range_end) * mult_factor
            )
        unit *= spacing
        total_unit += unit
    value_list.append(range_end)
    return value_list


def endpointForURI(uri):
    """
        Construct and return an L{IStreamClientEndpoint} for the outgoing
        request's connection.

        @param uri: The URI of the request.
        @type uri: L{twisted.web.client.URI}

        @return: An endpoint which will have its C{connect} method called to
            issue the request.
        @rtype: an L{IStreamClientEndpoint} provider

        @raises twisted.internet.error.SchemeNotSupported: If the given
            URI's scheme cannot be handled by this factory.
        """


def generate_kml(tx, ty, tz, tileext, tilesize, tileswne, options, children
    =None, **args):
    """
    Template for the KML. Returns filled string.
    """
    if not children:
        children = []
    args['tx'], args['ty'], args['tz'] = tx, ty, tz
    args['tileformat'] = tileext
    if 'tilesize' not in args:
        args['tilesize'] = tilesize
    if 'minlodpixels' not in args:
        args['minlodpixels'] = int(args['tilesize'] / 2)
    if 'maxlodpixels' not in args:
        args['maxlodpixels'] = int(args['tilesize'] * 8)
    if children == []:
        args['maxlodpixels'] = -1
    if tx is None:
        tilekml = False
        args['title'] = options.title
    else:
        tilekml = True
        args['title'] = '%d/%d/%d.kml' % (tz, tx, ty)
        args['south'], args['west'], args['north'], args['east'] = tileswne(tx,
            ty, tz)
    if tx == 0:
        args['drawOrder'] = 2 * tz + 1
    elif tx is not None:
        args['drawOrder'] = 2 * tz
    else:
        args['drawOrder'] = 0
    url = options.url
    if not url:
        if tilekml:
            url = '../../'
        else:
            url = ''
    s = (
        """<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>%(title)s</name>
    <description></description>
    <Style>
      <ListStyle id="hideChildren">
        <listItemType>checkHideChildren</listItemType>
      </ListStyle>
    </Style>"""
         % args)
    if tilekml:
        s += (
            """
    <Region>
      <LatLonAltBox>
        <north>%(north).14f</north>
        <south>%(south).14f</south>
        <east>%(east).14f</east>
        <west>%(west).14f</west>
      </LatLonAltBox>
      <Lod>
        <minLodPixels>%(minlodpixels)d</minLodPixels>
        <maxLodPixels>%(maxlodpixels)d</maxLodPixels>
      </Lod>
    </Region>
    <GroundOverlay>
      <drawOrder>%(drawOrder)d</drawOrder>
      <Icon>
        <href>%(ty)d.%(tileformat)s</href>
      </Icon>
      <LatLonBox>
        <north>%(north).14f</north>
        <south>%(south).14f</south>
        <east>%(east).14f</east>
        <west>%(west).14f</west>
      </LatLonBox>
    </GroundOverlay>
"""
             % args)
    for cx, cy, cz in children:
        csouth, cwest, cnorth, ceast = tileswne(cx, cy, cz)
        s += (
            """
    <NetworkLink>
      <name>%d/%d/%d.%s</name>
      <Region>
        <LatLonAltBox>
          <north>%.14f</north>
          <south>%.14f</south>
          <east>%.14f</east>
          <west>%.14f</west>
        </LatLonAltBox>
        <Lod>
          <minLodPixels>%d</minLodPixels>
          <maxLodPixels>-1</maxLodPixels>
        </Lod>
      </Region>
      <Link>
        <href>%s%d/%d/%d.kml</href>
        <viewRefreshMode>onRegion</viewRefreshMode>
        <viewFormat/>
      </Link>
    </NetworkLink>
        """
             % (cz, cx, cy, args['tileformat'], cnorth, csouth, ceast,
            cwest, args['minlodpixels'], url, cz, cx, cy))
    s += '      </Document>\n</kml>\n    '
    return s


def best_archiver(random, population, archive, args):
    """Archive only the best individual(s).

    This function archives the best solutions and removes inferior ones.
    If the comparison operators have been overloaded to define Pareto
    preference (as in the ``Pareto`` class), then this archiver will form
    a Pareto archive.

    .. Arguments:
       random -- the random number generator object
       population -- the population of individuals
       archive -- the current archive of individuals
       args -- a dictionary of keyword arguments

    """
    new_archive = archive
    for ind in population:
        if len(new_archive) == 0:
            new_archive.append(ind)
        else:
            should_remove = []
            should_add = True
            for a in new_archive:
                if ind.candidate == a.candidate:
                    should_add = False
                    break
                elif ind < a:
                    should_add = False
                elif ind > a:
                    should_remove.append(a)
            for r in should_remove:
                new_archive.remove(r)
            if should_add:
                new_archive.append(ind)
    return new_archive


@classmethod
def from_bdms(cls, bdms):
    """Returns a list of BlockDevicePayload objects based on the passed
        BlockDeviceMappingList.
        """
    payloads = []
    for bdm in bdms:
        if bdm.volume_id is not None:
            payloads.append(cls(bdm))
    return payloads


@classmethod
def create(cls, title, url, **kwargs):
    """
        Create a new VO Service Catalog with user parameters.

        Parameters
        ----------
        title : str
            Title of the catalog.

        url : str
            Access URL of the service. This is used to build queries.

        kwargs : dict
            Additional metadata as keyword-value pairs describing the catalog,
            except 'title' and 'url'.

        Returns
        -------
        cat : `VOSCatalog`
            VO Service Catalog.

        Raises
        ------
        TypeError
            Multiple values given for keyword argument.

        """
    tree = {'title': title, 'url': url}
    tree.update(kwargs)
    return cls(tree)


def _get_data_dir():
    """Get the data directory based on the module location."""
    return '/usr/share/distro-info'


def vertex_group_invert():
    """Invert weights to the active vertex group

    """
    pass


def validate_key(key):
    """Check if an key is a valid dotted path

    :raises: ValueError if invalid.
    """
    if len(key) is 0:
        raise ValueError('Key or a part of it may not be empty')
    if key.startswith('.') or key.endswith('.'):
        raise ValueError('Key may not start or end with a single dot: {}'.
            format(key))
    if '..' in key:
        raise ValueError('Key may not contain successive double dots: {}'.
            format(key))


def HStrainNames(SGData):
    """Needs a doc string"""
    laue = SGData['SGLaue']
    uniq = SGData['SGUniq']
    if laue in ['m3', 'm3m']:
        return ['D11', 'eA']
    elif laue in ['6/m', '6/mmm', '3m1', '31m', '3']:
        return ['D11', 'D33']
    elif laue in ['3R', '3mR']:
        return ['D11', 'D12']
    elif laue in ['4/m', '4/mmm']:
        return ['D11', 'D33']
    elif laue in ['mmm']:
        return ['D11', 'D22', 'D33']
    elif laue in ['2/m']:
        Dij = ['D11', 'D22', 'D33']
        if uniq == 'a':
            Dij += ['D23']
        elif uniq == 'b':
            Dij += ['D13']
        elif uniq == 'c':
            Dij += ['D12']
        return Dij
    else:
        Dij = ['D11', 'D22', 'D33', 'D12', 'D13', 'D23']
        return Dij


def parse_id(id_value: str) ->dict:
    """
    Parse the id_value into its component parts.

    :param id_value:
        The id value to parse.
    :return:
        A dictionary containing the parts of the id including the prefix,
        uuid, and checksum.
    """
    if len(id_value.split('-')) != 8:
        template = '"{value}" is not a nuggan id.'
        raise ValueError(template.format(value=id_value))
    prefix, hex_time, remaining = id_value.split('-', maxsplit=2)
    base_id, checksum = remaining.rsplit('-', maxsplit=1)
    prefixed_id, _ = id_value.rsplit('-', maxsplit=1)
    return {'prefix': prefix, 'hex_time': hex_time, 'prefixed_id':
        prefixed_id, 'base_id': base_id, 'checksum': checksum}


def breadth_first_search_ci(root, criterion, up=True):
    """Perform a breadth-first search on a CI and its parents/children.

    :param root: The start of search
    :param criterion: A callable that takes a CI and returns a value that
        should evaluate to True if the search if succesful
    :param up: If true, the search will move to parents. Otherwise - to
        children.
    :return: A tuple (CI, criterion(CI)) on success or (None, None) on failure
    """
    queue = [root]
    enqueued = {root.id}
    while queue:
        current = queue.pop(0)
        result = criterion(current)
        if result:
            return current, result
        if up:
            to_search = current.get_parents()
        else:
            to_search = current.get_children()
        for ci in to_search:
            if ci.id not in enqueued:
                queue.append(ci)
                enqueued.add(ci.id)
    return None, None


def get_reverse_relation(model, related_name):
    """
        Helper function that returns a reverse relation instance for a
        given model and the related_name for the reverse relation.

        model: subclass of django.db.models.Model
        related_name: str
    """
    return model._meta.fields_map.get(related_name)


def _get_v2_error_from_json(_json_error):
    """This function extracts error details (if present) from a Community API v2 response.

    :param _json_error: The API response in JSON format
    :type _json_error: dict
    :returns: A Boolean stating if an error was found and a tuple with the error code and error/exception messages
    """
    _error_code, _error_msg, _exc_msg = 0, '', ''
    _error_found = True if _json_error['status'] == 'error' else False
    if _error_found:
        _error_code = _json_error['data']['code']
        _error_type = _json_error['data']['type']
        _error_msg = f"{_json_error['message']} (Error Type: {_error_type})"
        _exc_msg = (
            f"The Community API v2 call failed with the error code '{_error_code}' and the following "
             + f'message: {_error_msg}')
    return _error_found, (_error_code, _error_msg, _exc_msg)


def _activities_from_user_query(user_id):
    """Return an SQLAlchemy query for all activities from user_id."""
    import ckan.model as model
    q = model.Session.query(model.Activity)
    q = q.filter(model.Activity.user_id == user_id)
    return q


def separate():
    """Isolate selected bones into a separate armature

    """
    pass


def linalg_sumlogdiag(A=None, out=None, name=None, **kwargs):
    """Computes the sum of the logarithms of the diagonal elements of a square matrix.
    Input is a tensor *A* of dimension *n >= 2*.

    If *n=2*, *A* must be square with positive diagonal entries. We sum the natural
    logarithms of the diagonal elements, the result has shape (1,).

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

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

    Examples::

       Single matrix reduction
       A = [[1.0, 1.0], [1.0, 7.0]]
       sumlogdiag(A) = [1.9459]

       Batch matrix reduction
       A = [[[1.0, 1.0], [1.0, 7.0]], [[3.0, 0], [0, 17.0]]]
       sumlogdiag(A) = [1.9459, 3.9318]

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

    Parameters
    ----------
    A : NDArray
        Tensor of square matrices

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

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


def endcut(s, post):
    """ If string `s` ends with `post` cut it off and return the preceding string. """
    if s.endswith(post):
        return s[:-len(post)]
    else:
        return s


def decode_tx(txid):
    """
        return dict with important transaction information
        """
    return NotImplementedError


def np_fcn_nd_to_1d(fcn, data, axis=-1):
    """
    Take in an n-dimensional array and return a 1D version operated on by fcn.    Works with many numpy functions that can take an "axis" parameter
    """
    if data.ndim > 1:
        dims = list(range(data.ndim))
        dims.pop(axis)
        vec = fcn(data, axis=tuple(dims))
    else:
        vec = data
    return vec


@staticmethod
def get_susceptance(rs, x):
    """x : reactance (ohm)
rs : series resistance (ohm)
return susceptance B (S) if not infinite"""
    if rs == 0 and x == 0:
        return None
    return -x / (rs * rs + x * x)


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


@classmethod
def get_schema_obj(cls):
    """ Returns an instantiated object for Schema associated
                with the model class
        """
    if '_schema_obj' not in cls.__dict__:
        cls._schema_obj = cls.get_schema_cls()()
    return cls._schema_obj


def unsafe(f):
    """Marks a function or method as unsafe.

    ::

        @unsafe
        def delete(self):
            pass
    """
    f.unsafe_callable = True
    return f


def attribute_has_range_list(attr):
    """ Only some attributes can have range list values, if they have the
        required DW_FORM (rangelistptr "class" in DWARF spec v3)
    """
    if attr.name == 'DW_AT_ranges':
        if attr.form in ('DW_FORM_data4', 'DW_FORM_data8'):
            return True
    return False


def get_spd_dtype_list(endianess='<'):
    """
    Get the data type list for an SPD map.
    Further information about the file format is available `here
    <https://github.com/hyperspy/hyperspy/
    files/29505/SpcMap-spd.file.format.pdf>`__.

    Table of header tags:
     - tag: 16 byte char array;    *File ID tag ("MAPSPECTRA_DATA")*
     - version: 4 byte long;       *File version*
     - nSpectra: 4 byte long;      *Number of spectra in file*
     - nPoints: 4 byte long;       *Number of map pixels in X direction*
     - nLines: 4 byte long;        *Number of map pixels in Y direction*
     - nChannels: 4 byte long;     *Number of channels per spectrum*
     - countBytes: 4 byte long;    *Number of count bytes per channel*
     - dataOffset: 4 byte long;    *File offset in bytes for data start*
     - nFrames: 4 byte long;       *Number of frames in live spectrum mapping*
     - fName: 120 byte char array; *File name of electron image acquired during mapping*

    Parameters
    ----------
    endianess : byte-order used to read the data

    Returns
    -------
    dtype_list : list
        List of the data tags and data types that will be used by numpy to
        read an SPD file header.
    """
    end = endianess
    dtype_list = [('tag', '16i1'), ('version', end + 'i4'), ('nSpectra',
        end + 'i4'), ('nPoints', end + 'i4'), ('nLines', end + 'u4'), (
        'nChannels', end + 'u4'), ('countBytes', end + 'u4'), ('dataOffset',
        end + 'u4'), ('nFrames', end + 'u4'), ('fName', end + '120i1'), (
        'filler', end + 'V900')]
    return dtype_list


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


def clean_props(props):
    """Clean properties of dangerous values and wrong data types.

    Make sure the properties don't have IORs or similar in them, because
    they will confuse the notify_connect calls.

    Make sure that all keys are not unicode.

    """
    new_props = {}
    for p in props:
        if p == 'dataport.corba_cdr.inport_ior':
            continue
        if p == 'dataport.corba_cdr.inport_ref':
            continue
        if p == 'dataport.corba_cdr.outport_ior':
            continue
        if p == 'dataport.corba_cdr.outport_ref':
            continue
        new_props[str(p)] = str(props[p])
    return new_props


def param_matches_type(param_name, rig_type):
    """ Returns True if the parameter name is consistent with the rig type.
    """
    if param_name.rsplit('.', 1)[0] == rig_type:
        return True
    else:
        return False


def get_module_version_attr(module):
    """
    Simply return the __version__ attribute as recommended by PEP396
    See https://www.python.org/dev/peps/pep-0396/#specification

    Note that even if some packages use custom attribute names such as 'version' (without underscores) it does not
    seem a good idea to try them. Indeed we would have no guarantee that the semantic meaning is the same.
    See https://stackoverflow.com/questions/31146153/get-python-tornado-version/31146188.

    :param module:
    :return:
    """
    return module.__version__


@classmethod
def origin_index(cls, index):
    """Return the equivalent index when the supershape is at the origin."""
    row, col = index
    origin_row = row % 2
    origin_col = col % 3
    return origin_row, origin_col


def average(da, dim=None, weights=None):
    """
        Returns the weighted average
        Author: Dougie Squire
        Date: 06/08/2018

        Parameters
        ----------
        da : xarray DataArray
            Array to be averaged
        dim : str or sequence of str, optional
            Dimension(s) over which to compute weighted average. If None, average is computed over all
            dimensions
        weights : xarray DataArray, optional
            Weights to apply during averaging. Shape of weights must be broadcastable to shape of da.
            If None, unity weighting is applied

        Returns
        -------
        weighted : xarray DataArray
            Weighted average of input array along specified dimensions

        Examples
        --------
        >>> A = xr.DataArray(np.random.normal(size=(4,4)), coords=[('lat', np.arange(-90,90,45)),
        ...                                                        ('lon', np.arange(0,360,90))])
        >>> degtorad = doppyo.utils.constants().pi / 180
        >>> cos_lat = xr.ufuncs.cos(A['lat'] * degtorad)
        >>> doppyo.utils.average(A, dim='lat', weights=cos_lat)
        <xarray.DataArray (lon: 4)>
        array([-0.473632, -0.241208, -0.954826,  0.498559])
        Coordinates:
          * lon      (lon) int64 0 90 180 270
    """
    if weights is None:
        return da.mean(dim)
    else:
        weights = (0 * da + 1) * weights
        return (da * weights).sum(dim) / weights.sum(dim)


def get(project, version=None):
    """Return a tuple (version, file) with the the egg for the specified
        project and version. If version is None, the latest version is
        returned. If no egg is found for the given project/version (None, None)
        should be returned."""


def get_colmin(data):
    """
    Get rowwise column names with minimum values

    :param data: pandas dataframe
    """
    data = data.T
    colmins = []
    for col in data:
        colmins.append(data[col].idxmin())
    return colmins


@classmethod
def check_is_runnable(cls):
    """
        Check that the launcher can be created and can run on the system.

        :raises: :class:`LauncherNotRunnable`.
        """
    pass


def sort_versions(v):
    """ Return the versions sorted
    """
    v.sort(key=lambda x: x[0])
    return v


def cycles_integrator_preset_add(name: str='', remove_active: bool=False):
    """Add an Integrator Preset

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


def KK_RC2_fit(params, w, t_values):
    """
    Kramers-Kronig Function: -RC-

    Kristian B. Knudsen (kknu@berkeley.edu / kristianbknudsen@gmail.com)
    """
    Rs = params['Rs']
    R1 = params['R1']
    R2 = params['R2']
    return Rs + R1 / (1 + w * 1.0j * t_values[0]) + R2 / (1 + w * 1.0j *
        t_values[1])


def _join_translated(translated_parts, os_sep_class):
    """Join translated glob pattern parts.

    This is different from a simple join, as care need to be taken
    to allow ** to match ZERO or more directories.
    """
    res = ''
    for part in translated_parts[:-1]:
        if part == '.*':
            res += part
        else:
            res += part + os_sep_class
    if translated_parts[-1] == '.*':
        res += '.+'
        res += '({os_sep_class}?.*)?'.format(os_sep_class=os_sep_class)
    else:
        res += translated_parts[-1]
    return res


def __format_float(value):
    """Format float in scientific notation, 6 decimal places.

    :param value:
    :return:
    """
    return '{:.6e}'.format(float(value))


@staticmethod
def stuff_predictor_into_envelope(predictor: dict) ->dict:
    """Insert a serialized embedded predictor into a module envelope, to facilitate deser."""
    return dict(module_type='PREDICTOR', config=predictor, active=False,
        schema_id='43c61ad4-7e33-45d0-a3de-504acb4e0737')


def get_num_frames(dur, anal):
    """Given the duration of a track and a dictionary containing analysis
    info, return the number of frames."""
    total_samples = dur * anal['sample_rate']
    return int(total_samples / anal['hop_size'])


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


def read_process(process):
    """Get any stdout and stderr from the process"""
    try:
        next_chunk = process.stdout.read()
    except IOError:
        next_chunk = ''
    try:
        next_error = process.stderr.read()
    except IOError:
        next_error = ''
    return next_chunk, next_error


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def get_tag(record, name, default=None):
    """
    Loks in the XML tag 'record' for
    other tags named 'name', and returns the value of the first one.
    If none is found, it returns 'default'.
    """
    tag = record.getElementsByTagName(name)
    if len(tag) and len(tag[0].childNodes):
        return tag[0].childNodes[0].nodeValue
    else:
        return default


def pg_connect_bits(meta):
    """Turn the url into connection bits."""
    bits = []
    if meta['username']:
        bits.extend(['-U', meta['username']])
    if meta['hostname']:
        bits.extend(['-h', meta['hostname']])
    if meta['port']:
        bits.extend(['-p', str(meta['port'])])
    return bits


@classmethod
def get_factory(cls, format_string):
    """Get the file factory for this format"""
    format_string = cls.simplify_format(format_string)
    if format_string in cls._factories:
        return cls._factories[format_string]
    else:
        raise ValueError('Unknown file format: ' + format_string)


@classmethod
def get_importers(cls):
    """ Returns a tuple of currently active importers in use for the
        framework.

        """
    return tuple(cls.__importers)


def find_genusspecific_allele_list(profiles_file, target_genus):
    """
    A new way of making our specific databases: Make our profiles file have lists of every gene/allele present for
    each genus instead of just excluding a few genes for each. This way, should have much smaller databases
    while managing to make ConFindr a decent bit faster (maybe)
    :param profiles_file: Path to profiles file.
    :param target_genus: Genus you want to make a custom database for (STR)
    :return: List of gene/allele combinations that should be part of species-specific database.
    """
    alleles = list()
    with open(profiles_file) as f:
        lines = f.readlines()
    for line in lines:
        line = line.rstrip()
        genus = line.split(':')[0]
        if genus == target_genus:
            alleles = line.split(':')[1].split(',')[:-1]
    return alleles


@staticmethod
def __print_lineno(msg, fname=None):
    """Print line number and file name header for diff of msg pairs"""
    lineno = msg.meta['lineno'] if 'lineno' in msg.meta else 'N/A'
    return ('--- Line %d (%s) ' % (lineno, fname)).ljust(32, '-')


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


def form_shell_ratio(radius, thickness, length):
    """form:shell ratio"""
    return (radius + thickness) ** 2 / ((radius + thickness) ** 2 - radius ** 2
        )


@classmethod
def _get_BZ_integration_grid(cls, calc, **kwargs):
    """Return an array with Brillouin zone point counts along each vector of reciprocal lattice."""
    try:
        array, _ = calc.inputs.kpoints.get_kpoints_mesh()
        return array
    except AttributeError:
        return None
    except KeyError:
        return None


def IntVectorProperty(name: str='', description: str='', default: list=(0,
    0, 0), min: int=-2 ** 31, max: int=2 ** 31 - 1, soft_min: int=-2 ** 31,
    soft_max: int=2 ** 31 - 1, step: int=1, options: set={'ANIMATABLE'},
    subtype: str='NONE', size: int=3, update=None, get=None, set=None):
    """Returns a new vector int property definition.

    :param name: Name used in the user interface.
    :type name: str
    :param description: Text used for the tooltip and api documentation.
    :type description: str
    :param default: sequence of ints the length of size.
    :type default: list
    :param min: Hard minimum, trying to assign a value below will silently assign this minimum instead.
    :type min: int
    :param max: Hard maximum, trying to assign a value above will silently assign this maximum instead.
    :type max: int
    :param soft_min: Soft minimum (>= min), user won’t be able to drag the widget below this value in the UI.
    :type soft_min: int
    :param soft_max: Soft maximum (<= max), user won’t be able to drag the widget above this value in the UI.
    :type soft_max: int
    :param step: Step of increment/decrement in UI, in [1, 100], defaults to 1 (WARNING: unused currently!).
    :type step: int
    :param options: Enumerator in [‘HIDDEN’, ‘SKIP_SAVE’, ‘ANIMATABLE’, ‘LIBRARY_EDITABLE’, ‘PROPORTIONAL’,’TEXTEDIT_UPDATE’].
    :type options: set
    :param subtype: Enumerator in [‘COLOR’, ‘TRANSLATION’, ‘DIRECTION’, ‘VELOCITY’, ‘ACCELERATION’, ‘MATRIX’, ‘EULER’, ‘QUATERNION’, ‘AXISANGLE’, ‘XYZ’, ‘COLOR_GAMMA’, ‘LAYER’, ‘NONE’].
    :type subtype: str
    :param size: Vector dimensions in [1, 32].
    :type size: int
    :param update: Function to be called when this value is modified, This function must take 2 values (self, context) and return None. Warning there are no safety checks to avoid infinite recursion.
    :param get: Function to be called when this value is ‘read’, This function must take 1 value (self) and return the value of the property.
    :param set: Function to be called when this value is ‘written’, This function must take 2 values (self, value) and return None.
    """
    pass


def unique_filter(matches):
    """
    Iterate over matches and yield unique matches.
    """
    uniques = set()
    for key, match, line, lineno in matches:
        if (key, match) in uniques:
            continue
        uniques.add((key, match))
        yield key, match, line, lineno


def cyclic_direction(x, y, z):
    """
    Returns 1 or -1 depending on the cyclic ordering of (x,y,z)

    TESTS::

        sage: from surface_dynamics.flat_surfaces.separatrix_diagram import cyclic_direction
        sage: cyclic_direction(0,1,2)
        1
        sage: cyclic_direction(1,2,0)
        1
        sage: cyclic_direction(2,0,1)
        1
        sage: cyclic_direction(2,1,0)
        -1
        sage: cyclic_direction(1,0,2)
        -1
        sage: cyclic_direction(0,2,1)
        -1
    """
    if x < y < z or y < z < x or z < x < y:
        return 1
    else:
        return -1


@classmethod
def create(cls, server, option, value):
    """
        Based on the given option and value from the configuration
        file, creates the appropriate retention policy object
        for the given server
        """
    if option == 'wal_retention_policy':
        context = 'WAL'
    elif option == 'retention_policy':
        context = 'BASE'
    else:
        raise ValueError('Unknown option for retention policy: %s' % option)
    for policy_class in cls.policy_classes:
        policy = policy_class.create(server, context, value)
        if policy:
            return policy
    raise ValueError('Cannot parse option %s: %s' % (option, value))


def SGB_quality_level(row):
    """
    https://doi.org/10.1016/j.cell.2019.01.001
    """
    if row['Strain heterogeneity'] < 0.5 and row['Completeness'
        ] > 90.0 and row['Contamination'] < 5.0:
        return 'high_quality'
    elif row['Completeness'] > 50.0 and row['Contamination'] < 5.0:
        return 'medium_quality'
    else:
        return 'low_quality'


def alias(requestContext, seriesList, newName):
    """
    Takes one metric or a wildcard seriesList and a string in quotes.
    Prints the string instead of the metric name in the legend.

    Example::

        &target=alias(Sales.widgets.largeBlue,"Large Blue Widgets")

    """
    try:
        seriesList.name = newName
    except AttributeError:
        for series in seriesList:
            series.name = newName
    return seriesList


def parse_def(surface, node):
    """Parse the SVG definitions."""
    for def_type in ('marker', 'gradient', 'pattern', 'path', 'mask', 'filter'
        ):
        if def_type in node.tag.lower() and 'id' in node:
            getattr(surface, '{}s'.format(def_type))[node['id']] = node


def _margeff_cov_params_dummy(model, cov_margins, params, exog, dummy_ind,
    method, J):
    """
    Returns the Jacobian for discrete regressors for use in margeff_cov_params.

    For discrete regressors the marginal effect is

    \\Delta F = F(XB) | d = 1 - F(XB) | d = 0

    The row of the Jacobian for this variable is given by

    f(XB)*X | d = 1 - f(XB)*X | d = 0

    Where F is the default prediction of the model.
    """
    for i in dummy_ind:
        exog0 = exog.copy()
        exog1 = exog.copy()
        exog0[:, (i)] = 0
        exog1[:, (i)] = 1
        dfdb0 = model._derivative_predict(params, exog0, method)
        dfdb1 = model._derivative_predict(params, exog1, method)
        dfdb = dfdb1 - dfdb0
        if dfdb.ndim >= 2:
            dfdb = dfdb.mean(0)
        if J > 1:
            K = dfdb.shape[1] // (J - 1)
            cov_margins[i::K, :] = dfdb
        else:
            cov_margins[(i), :len(dfdb)] = dfdb
    return cov_margins


def Prepend(prefix, content, skip_first_line=True, skip_empty_lines=False):
    """Prepends the prefix to each line of the provided content."""
    lines = content.split('\n')
    if lines and len(lines) > 1 and not lines[-1]:
        trailing_newline = True
        lines.pop()
    else:
        trailing_newline = False
    content = []
    for line in lines:
        if skip_first_line:
            skip_first_line = False
        elif line or not skip_empty_lines:
            line = '{}{}'.format(prefix, line)
        content.append(line)
    content = '\n'.join(content)
    if trailing_newline:
        content += '\n'
    return content


def psi_Mg_CO3_HCO3_HMW84(T, P):
    """c-a-a': magnesium carbonate bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


@classmethod
def load(cls, datastore_version_id=None):
    """
        Generates a Capabilities object by looking up all capabilities from
        defaults and overrides and provides the one structure that should be
        used as the interface to controlling capabilities per datastore.

        :returns: Capabilities
        """
    self = cls(datastore_version_id)
    self._load()
    return self


@classmethod
def _test_scheme(cls, scheme):
    """
            Test if a scheme is valide or raise BadScheme

            :param bytes scheme: A scheme
            :raises BadScheme: if ``scheme`` is not a valid scheme
        """
    if scheme not in cls.schemes_salt and scheme not in cls.schemes_nosalt:
        cls._raise_bad_scheme(scheme, cls.schemes_salt | cls.schemes_nosalt,
            'The scheme %r is not valid. Valide schemes are %s.')


def ratio(qnty1, qnty2):
    """
        >>> q1=Qnty.fromstring('63.5 millimeter')
        >>> q2=Qnty.fromstring('792.0 point')
        >>> str(q1/q2)
        '0.0801767676768 millimeter / point'
        >>> str(q1.to_base_units()/q2.to_base_units())
        '0.227272727273 dimensionless'
        >>> str((q1.to_base_units()/q2.to_base_units()).magnitude)
        '0.227272727273'
        >>> str(ratio(q1,q2))
        '0.227272727273'
        """
    return (qnty1.to_base_units() / qnty2.to_base_units()).magnitude


def pkg2dir(package):
    """
    Return directory path from UML package class.
    """
    name = []
    while package:
        name.insert(0, package.name)
        package = package.package
    return '/'.join(name)


def is_string_like(obj):
    """Return true if obj behaves like a string"""
    try:
        obj + ''
    except:
        return False
    return True


def train(dataset_path, output_path, config_path=None, verbose=False,
    random_seed=None):
    """Train an NLU engine on the provided dataset"""
    import json
    import logging
    from pathlib import Path
    from snips_nlu import SnipsNLUEngine
    from snips_nlu.cli.utils import set_nlu_logger
    from snips_nlu.common.utils import check_random_state
    if verbose == 1:
        set_nlu_logger(logging.INFO)
    elif verbose >= 2:
        set_nlu_logger(logging.DEBUG)
    with Path(dataset_path).open('r', encoding='utf8') as f:
        dataset = json.load(f)
    config = None
    if config_path is not None:
        with Path(config_path).open('r', encoding='utf8') as f:
            config = json.load(f)
    random_state = check_random_state(random_seed)
    print('Create and train the engine...')
    engine = SnipsNLUEngine(config, random_state=random_state).fit(dataset)
    print('Persisting the engine...')
    engine.persist(output_path)
    print('Saved the trained engine to %s' % output_path)


def compare_hash_tables(cls):
    """ Return a list of nc files that have changed or are new """
    old_hashes = cls.get_old_hashes()
    changed = []
    if old_hashes:
        if len(cls.new_hashes) == 0:
            cls.load_hash_table()
        for key in cls.new_hashes:
            if key not in old_hashes.keys() or key in old_hashes.keys(
                ) and old_hashes[key] != cls.new_hashes[key]:
                changed.append(key)
    return changed


def create_custom_prior_for(model, par, transform, aftertransform=lambda x: x):
    """
	Pass your own prior weighting transformation
	"""
    print('  custom prior for %s' % par.name)
    return dict(model=model, index=par._Parameter__index, name=par.name,
        transform=transform, aftertransform=aftertransform)


def joins(*parts, sep=' '):
    """Join a sequence as a string with given separator.

    This is a shortcut function that saves you the effort of converting
    each element in a str.join(sequence) call to a str first.

    :param sequence parts: A sequence of items to join
    :param str sep: The separator to join them with
    :returns str: The newly joined string

    """
    if not parts or not any(parts):
        return ''
    return sep.join(map(str, parts))


def pole(sys):
    """
    Compute system poles.

    Parameters
    ----------
    sys: StateSpace or TransferFunction
        Linear system

    Returns
    -------
    poles: ndarray
        Array that contains the system's poles.

    Raises
    ------
    NotImplementedError
        when called on a TransferFunction object

    See Also
    --------
    zero
    TransferFunction.pole
    StateSpace.pole

    """
    return sys.pole()


def skl2onnx_installed():
    """
    Checks that *skl2onnx* converter is available.
    """
    try:
        import skl2onnx
        return True
    except ImportError:
        return False


def upgrade_geometry(geometry, geometry_type_filter=None):
    """
    Transform a given geometry to a GeometryCollection, all inside geometries are transformed to MULTI geometries.
    Optionally you can add a geometry_type_filter (if you'r geometry input is an GeometryCollection) in this case only
    filtred geometry type will be return
    """
    if isinstance(geometry, dict):
        if geometry['type'].upper() == 'GEOMETRYCOLLECTION':
            geometry_list = geometry['geometries']
        else:
            geometry_list = [geometry]
    if geometry_type_filter:
        if isinstance(geometry_type_filter, str):
            geometry_type_filter = {geometry_type_filter.upper()}
        elif isinstance(geometry_type_filter, (list, tuple, set)):
            geometry_type_filter = set(geometry_type_filter)
        else:
            print(
                'geometry_type_filter must be a geometry type or a list of geometry type'
                )
    else:
        geometry_type_filter = {'POINT', 'LINESTRING', 'POLYGON',
            'MULTIPOINT', 'MULTILINESTRING', 'MULTIPOLYGON', 'GEOMETRY',
            'GEOMETRYCOLLECTION'}
    result_geometry_list = []
    for geometry in geometry_list:
        if geometry['type'].upper() in geometry_type_filter:
            result_geometry = dict(geometry)
            if not 'MULTI' in result_geometry['type'].upper():
                result_geometry['coordinates'] = [result_geometry[
                    'coordinates']]
                result_geometry['type'] = 'Multi' + result_geometry['type']
            result_geometry_list.append(result_geometry)
    return {'type': 'GeometryCollection', 'geometries': result_geometry_list}


def __call__(cls, *args, **kwargs):
    """Creates a computed object, catching self-casts."""
    if len(args) == 1 and not kwargs and isinstance(args[0], cls):
        return args[0]
    else:
        return type.__call__(cls, *args, **kwargs)


def fit_exponential(X, y):
    """
    Fits an exponential curve to the data.
    """
    raise NotImplementedError('Exponential best fit lines are not implemented')


def brightness_to_percentage(byt):
    """Convert brightness from absolute 0..255 to percentage."""
    return round(byt * 100.0 / 255.0)


def net_radiation_grass(ra_24, l_net, r0_grass=0.23):
    """
    Computes the net radiation for reference grass

    .. math ::
        Q^{*} = \\left[\\left(1-\\alpha_{0, grass}\\right)S^{\\downarrow}-L^{*}-I\\right]

    Parameters
    ----------
    ra_24 : float
        daily solar radiation
        :math:`S^{\\downarrow}`
        [Wm-2]
    l_net : float
        daily net longwave radiation
        :math:`L^{*}`
        [wm-2]
    r0_grass : float
        albedo for reference grass
        :math:`alpha_{0}_grass`
        [-]

    Returns
    -------
    rn_24_grass : float
        daily net radiation for reference grass
        :math:`Q^{*}`
        [Wm-2]

    Examples
    --------
    >>> import ETLook.radiation as rad
    >>> rad.net_radiation_grass(ra_24=123., l_net=24.)
    70.7
    """
    return (1 - r0_grass) * ra_24 - l_net


@staticmethod
def _transform_session_persistence(persistence):
    """Transforms session persistence into an object that will

            be processed by the templating system
        """
    return {'type': persistence.type, 'persistence_timeout': persistence.
        persistence_timeout, 'persistence_granularity': persistence.
        persistence_granularity}


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 is_less_than(val_a, val_b):
    """Return True if val_a is less than val_b (evaluate as integer)"""
    size = len(val_a)
    if size != len(val_b):
        return False
    for i in reversed(range(size)):
        if val_a[i] < val_b[i]:
            return True
        elif val_a[i] > val_b[i]:
            return False
    return False


def ungroup_licenses(licenses):
    """
    Ungroup multiple licenses information
    """
    lic_key = []
    lic_name = []
    lic_file = []
    lic_url = []
    for lic in licenses:
        if 'key' in lic:
            lic_key.append(lic['key'])
        if 'name' in lic:
            lic_name.append(lic['name'])
        if 'file' in lic:
            lic_file.append(lic['file'])
        if 'url' in lic:
            lic_url.append(lic['url'])
    return lic_key, lic_name, lic_file, lic_url


def get_node_type_filter(classifiers, subclassing):
    """
    Return filter dictionaries given a set of classifiers.

    :param classifiers: a dictionary with classifiers (note: does *not* support lists)
    :param subclassing: if True, allow for subclasses of the ormclass

    :returns: dictionary in QueryBuilder filter language to pass into {"type": ... }
    :rtype: dict

    """
    from aiida.orm.utils.node import get_query_type_from_type_string
    from aiida.common.escaping import escape_for_sql_like
    value = classifiers['ormclass_type_string']
    if not subclassing:
        filters = {'==': value}
    else:
        filters = {'like': '{}%'.format(escape_for_sql_like(
            get_query_type_from_type_string(value)))}
    return filters


@staticmethod
def aggregate_by_functions(df, column_name, group_by, functions=['sum',
    'count']):
    """Aggregate by multiple functions

        Parameters
        ----------
        df : pandas.core.frame.DataFrame
            Two-dimensional size-mutable,
            potentially heterogeneous tabular data
        column_name : TYPE
        group_by : TYPE
            Description
        functions : list, optional
            Description

        Returns
        -------
        `pandas.core.frame.DataFrame`
            DataFrame

        Example
        -------
        # Lets say, you want the total price of each order as well as the
        # number of items in each order.
        >> Orders.head(5)
            order_id | quantity | item_name | choice_description | item_price
            1 | 1 | Chips and Fresh Tomato Salsa          | NaN          | 2.39
            1 | 1 | Izze                                  | [Clementine] | 3.39
            1 | 1 | Nantucket Nectar                      | [Apple]      | 3.39
            1 | 1 | Chips and Tomatillo-Green Chili Salsa | NaN          | 2.39
            2 | 2 | Chicken Bowl                          | NaN          | 16.98
        >> aggregate_by_functions(orders, 'item_price', 'order_id').head()
            order_id  | sum   | count
                    1 | 11.56 | 4
                    2 | 16.98 | 1
                    3 | 12.67 | 2
                    4 | 21.00 | 2
                    5 | 13.70 | 2
        """
    return df.groupby(group_by)[column_name].agg(functions)


def disable_cloud_admin_access(session, confirm, return_type=None, **kwargs):
    """
    Disables the ability of a storage cloud administrator to access the VPSA
    GUI of this VPSA to assist in troubleshooting.  This does not grant access
    to any volume data.  Enabled by default.

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type confirm: bool
    :param confirm: If True, cloud admin access will be disabled.  This is a
        safeguard for this function since it requires no other arguments.

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    if not confirm:
        raise ValueError(
            'The confirm parameter is not set to True - cloud admin access will not be disabled.'
            )
    path = '/api/users/admin_access/disable.json'
    return session.post_api(path=path, return_type=return_type, **kwargs)


def length_difference_check(orthologLen, inparalogLen, lenRatioThr, debug=False
    ):
    """
    Check the difference in length between a inparalong and its ortholog sequence (from the same species).

    Return a tuple of type (1, 0.4) where 1 means the inparalog should be kept, and 0.4 is
    the difference in length from the closest ortholog in the cluster.
    If the inparalog should be dropped then the first value is 0
    """
    if debug:
        print('\nlength_difference_check :: START')
        print('Ortholog length: %d' % orthologLen)
        print('Inparalogs length: %d' % inparalogLen)
        print('Length difference threshold: %s' % str(lenRatioThr))
    lenDiffRatio = 0
    if orthologLen == inparalogLen:
        return 1, 0.0, 1.0
    else:
        inparaVsOrthoLen = 1.0
        if inparalogLen < orthologLen:
            seqLenDiff = orthologLen - inparalogLen
            lenDiffRatio = round(float(seqLenDiff) / float(orthologLen), 2)
            inparaVsOrthoLen = -round(float(orthologLen) / float(
                inparalogLen), 2)
        else:
            seqLenDiff = inparalogLen - orthologLen
            lenDiffRatio = round(float(seqLenDiff) / float(inparalogLen), 2)
            inparaVsOrthoLen = round(float(inparalogLen) / float(
                orthologLen), 2)
        if lenDiffRatio <= lenRatioThr:
            return 1, lenDiffRatio, inparaVsOrthoLen
        else:
            return 0, lenDiffRatio, inparaVsOrthoLen


def str2bool(strvalue, default=None):
    """
	Converts string value to :class:`bool`. Can parse human-readable values,
	like ``'yes'`` and ``'off'``.

	If value is not recognized -- the value of the :paramref:`~str2bool.default`
	argument will be returned.

	.. note::

		:func:`str2bool` is not an extension of default :class:`bool`. For
		example, it doesn't recognize integer ``2`` (or any other number) as
		:data:`True` value.

	:param strvalue: Value to parse
	:type strvalue: str
	:param default:  Default value, defaults to :data:`None`
	:type default: *
	:returns: Parsed boolean value or :paramref:`~str2bool.default` 	(if defined). Not a bool value will be returned **only** if value was not 	recognized.
	:rtype: bool or *

	"""
    if strvalue is None:
        return default
    rl = str(strvalue).lower()
    if rl in ['true', '1', 't', 'y', 'yes', 'on']:
        return True
    if rl in ['false', '0', 'f', 'n', 'no', 'off']:
        return False
    return default


def t_type(text):
    """[A-Z][A-Za-z_-]*"""
    return text


def __add__(other):
    """A DateTime may be added to a number and a number may be
        added to a DateTime; two DateTimes cannot be added."""


def laminar_entry_thermal_Hausen(Re, Pr, L, Di):
    """Calculates average internal convection Nusselt number for laminar flows
    in pipe during the thermal entry region according to [1]_ as shown in
    [2]_ and cited by [3]_.

    .. math::
        Nu_D=3.66+\\frac{0.0668\\frac{D}{L}Re_{D}Pr}{1+0.04{(\\frac{D}{L}
        Re_{D}Pr)}^{2/3}}

    Parameters
    ----------
    Re : float
        Reynolds number, [-]
    Pr : float
        Prandtl number, [-]
    L : float
        Length of pipe [m]
    Di : float
        Diameter of pipe [m]

    Returns
    -------
    Nu : float
        Nusselt number, [-]

    Notes
    -----
    If Pr >> 1, (5 is a common requirement) this equation also applies to flows
    with developing velocity profile.
    As L gets larger, this equation  becomes the constant-temperature Nusselt
    number.

    Examples
    --------
    >>> laminar_entry_thermal_Hausen(Re=100000, Pr=1.1, L=5, Di=.5)
    39.01352358988535

    References
    ----------
    .. [1] Hausen, H. Darstellung des Warmeuberganges in Rohren durch
       verallgeminerte Potenzbeziehungen, Z. Ver deutsch. Ing Beih.
       Verfahrenstech., 4, 91-98, 1943
    .. [2] W. M. Kays. 1953. Numerical Solutions for Laminar Flow Heat Transfer
       in Circular Tubes.
    .. [3] Bergman, Theodore L., Adrienne S. Lavine, Frank P. Incropera, and
       David P. DeWitt. Introduction to Heat Transfer. 6E.
       Hoboken, NJ: Wiley, 2011.
    """
    Gz = Di / L * Re * Pr
    return 3.66 + 0.0668 * Gz / (1 + 0.04 * Gz ** (2 / 3.0))


def rectCenter(rect0):
    """Return the center of the rectangle as an (x, y) coordinate."""
    xMin, yMin, xMax, yMax = rect0
    return (xMin + xMax) / 2, (yMin + yMax) / 2


def savepoint(optimistic=False):
    """Create a savepoint.

        If the *optimistic* argument is true, then data managers that don't
        support savepoints can be used, but an error will be raised if the
        savepoint is rolled back.

        An `ISavepoint` object is returned.
        """


def get_user_login_info(login, users, user_login_rel):
    """
    Return a dict of data for each user; it's important
    that the users remain in the same order.
    """
    login_is_active = login.is_active and login.machine.is_active
    info = []
    for user in users:
        is_allowed = (user.pk, login.pk) in user_login_rel
        is_active = user.is_active and login_is_active
        verb = 'is' if is_active else 'would be'
        adjective = 'permitted to access' if is_allowed else 'forbidden from'
        explanations = []
        if not user.is_active:
            explanations.append('user were active')
        if not login.is_active:
            explanations.append('login were active')
        if not login.machine.is_active:
            explanations.append('machine were active')
        if_ = ' if ' if is_allowed else ' even if '
        explanation = if_ + ' and '.join(explanations) if explanations else ''
        tooltip = '%s %s %s %s@%s%s' % (user, verb, adjective, login.
            username, login.machine.hostname or login.machine.ip, explanation)
        info.append({'is_active': is_active, 'is_allowed': is_allowed,
            'action': 'deny' if is_allowed else 'permit', 'tooltip':
            tooltip, 'user': user})
    return info


def extend_substation(grid):
    """ Reinforce MV or LV substation by exchanging the existing trafo and installing a parallel one if necessary with according to dena

    Parameters
    ----------
        grid : :class:`~.ding0.core.GridDing0`
            Grid identifier.

    Returns
    -------
    type
        #TODO: Description of return. Change type in the previous line accordingly
    """
    pass


@classmethod
def from_file(cls, path, **kwargs):
    """
        Creates a new object from a specified Error Solver file.

        Parameters
        ----------
        path : str
            The file path.
        kwargs
            Additional arguments accepted by the default initializer.
        """
    data = cls._read_file(path)
    return cls(equations=data.get('equations', []), names=data.get('names',
        {}), combos=data.get('combos', {}), **kwargs)


def _aborttransaction(repo, tr):
    """Abort current transaction for shelve/unshelve, but keep dirstate
    """
    dirstatebackupname = b'dirstate.shelve'
    repo.dirstate.savebackup(tr, dirstatebackupname)
    tr.abort()
    repo.dirstate.restorebackup(None, dirstatebackupname)


def bC_Na_B4O5OH4_FW86(T, P):
    """c-a: sodium tetraborate [FW86]."""
    b0 = -0.11
    b1 = -0.4
    b2 = 0
    C0 = 0
    C1 = 0
    alph1 = 2
    alph2 = -9
    omega = -9
    valid = T == 298.15
    return b0, b1, b2, C0, C1, alph1, alph2, omega, valid


def get_params(cls, instance, ignore=None):
    """ Retrieve the initialization parameters corresponding to a class

    This helper function retrieves the parameters of function __init__ for
    class 'cls' and returns the value for these parameters in object
    'instance'. When using a composition pattern (e.g. with a NiftiMasker
    class), it is useful to forward parameters from one instance to another.

    Parameters
    ----------
    cls: class
        The class that gives us the list of parameters we are interested
        in

    instance: object, instance of BaseEstimator
        The object that gives us the values of the parameters

    ignore: None or list of strings
        Names of the parameters that are not returned.

    Returns
    -------
    params: dict
        The dict of parameters
    """
    _ignore = set(('memory', 'memory_level', 'verbose', 'copy', 'n_jobs'))
    if ignore is not None:
        _ignore.update(ignore)
    param_names = cls._get_param_names()
    params = dict()
    for param_name in param_names:
        if param_name in _ignore:
            continue
        if hasattr(instance, param_name):
            params[param_name] = getattr(instance, param_name)
    return params


def get_command(line, fmt_space):
    """
    Given a header line, get the possible command

    Parameters
    -----------
    line : string
        Line of the header

    fmt_space : boolean
        Yes = Novonix format with spaces in the commands

    Returns
    --------
    command : string
        Instruction in the header line

    Examples
    ---------
    >>> import preparenovonix.novonix_io as prep
    >>> command = prep.get_command('[Open circuit storage]',fmt_space=True)
    >>> print(command)
    Open circuit storage
    """
    command = ' '
    fw = line.strip()
    if fmt_space:
        command = fw[1:-1]
    elif ':' in fw:
        command = fw.split(':')[1].strip()
    else:
        command = fw[1:-1]
    return command


def token_stream(file, break_on_newline=True):
    """Word tokenizer. Also breaks on newlines."""
    while True:
        line = file.readline()
        for word in line.split(None):
            yield word
        if break_on_newline:
            yield '\n'


def _uniformly_named_arguments(captured_arguments):
    """Iterate the captured arguments as uniform name/value pairs."""
    args, kwargs = captured_arguments
    width = len(str(len(args)))
    for i, arg in enumerate(args, 1):
        name = str(i).zfill(width)
        yield name, arg
    yield from kwargs.items()


def select_less():
    """Deselect keyframes on ends of selection islands

    """
    pass


def altitude_from_radius(radius, body):
    """Return altitude for a given radius."""
    return radius - body.mean_radius


@classmethod
def __drop_table__(cls) ->str:
    """Constructs the needed sql statements to drop a mr_database table from a Table class"""
    return f'DROP TABLE IF EXISTS {cls.get_table_name()};'


def confirm_device(AccessToken=None, DeviceKey=None,
    DeviceSecretVerifierConfig=None, DeviceName=None):
    """
    Confirms tracking of the device. This API call is the call that begins device tracking.
    See also: AWS API Documentation

    :example: response = client.confirm_device(
        AccessToken='string',
        DeviceKey='string',
        DeviceSecretVerifierConfig={
            'PasswordVerifier': 'string',
            'Salt': 'string'
        },
        DeviceName='string'
    )

    :type AccessToken: string
    :param AccessToken: [REQUIRED]
            The access token.

    :type DeviceKey: string
    :param DeviceKey: [REQUIRED]
            The device key.

    :type DeviceSecretVerifierConfig: dict
    :param DeviceSecretVerifierConfig: The configuration of the device secret verifier.
            PasswordVerifier (string) --The password verifier.
            Salt (string) --The salt.

    :type DeviceName: string
    :param DeviceName: The device name.

    :rtype: dict
    :return: {
        'UserConfirmationNecessary': True|False
    }

    """
    pass


def include_package(config):
    """Pyramid package include"""
    config.add_translation_dirs('pyams_pagelet:locales')
    config.scan()


@classmethod
def warning(cls, value=None, message=None, **kwargs):
    """
        Provides a convenience constructor for Values instances with warnings.

        :param value: The value of the Value instance to be constructed.
        :param message: The message, if any.
        :param kwargs: Extra payload for the value.
        :return: A Value instance with warnings.
        """
    return cls(value=value, message=message, status=cls.Status.Warning, **
        kwargs)


@staticmethod
def parent_only_text(elem):
    """
        Returns the text for the current element without the text of child elements.

        :param elem:
        :return string:
        """
    parent_only_text = elem.lxml.findtext('./')
    return parent_only_text


def unicode_is_ascii(u_string):
    """Determine if unicode string only contains ASCII characters.

    :param str u_string: unicode string to check. Must be unicode
        and not Python 2 `str`.
    :rtype: bool
    """
    assert isinstance(u_string, str)
    try:
        u_string.encode('ascii')
        return True
    except UnicodeEncodeError:
        return False


def validate(data):
    """Validate a dictionary of data.

        This method is only responsible of validating relationships between
        the values in the data. It can be assumed that all values have been
        validated in isolation before.

        The return value of this method is a tuple of errors that occurred
        during the validation process.
        """


def list_sql_injection_match_sets(NextMarker=None, Limit=None):
    """
    Returns an array of  SqlInjectionMatchSet objects.
    See also: AWS API Documentation

    Examples
    The following example returns an array of up to 100 SQL injection match sets.
    Expected Output:

    :example: response = client.list_sql_injection_match_sets(
        NextMarker='string',
        Limit=123
    )

    :type NextMarker: string
    :param NextMarker: If you specify a value for Limit and you have more SqlInjectionMatchSet objects than the value of Limit , AWS WAF returns a NextMarker value in the response that allows you to list another group of SqlInjectionMatchSets . For the second and subsequent ListSqlInjectionMatchSets requests, specify the value of NextMarker from the previous response to get information about another batch of SqlInjectionMatchSets .

    :type Limit: integer
    :param Limit: Specifies the number of SqlInjectionMatchSet objects that you want AWS WAF to return for this request. If you have more SqlInjectionMatchSet objects than the number you specify for Limit , the response includes a NextMarker value that you can use to get another batch of Rules .

    :rtype: dict
    :return: {
        'NextMarker': 'string',
        'SqlInjectionMatchSets': [
            {
                'SqlInjectionMatchSetId': 'string',
                'Name': 'string'
            },
        ]
    }

    """
    pass


def is_valid_nickname(nick):
    """
    Return True if the given name is a valid nickname.
    """
    if len(nick) == 0 or len(nick) > 16:
        return False
    valid = (
        'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`^-_[]{}|\\'
        )
    invalid = set(nick) - set(valid)
    return not bool(invalid)


def sweep_log(start, stop, step=10):
    """Generator function to be used in sweeps.
Advantages towards the range python built-in functions_
    - Supports floating point arguments
    - Supports both up and down sweeps
    - Less memory footprint for large sweeps"""
    stp = abs(step)
    if start < stop:
        while start <= stop:
            yield start
            start *= stp
    elif start > stop:
        while start >= stop:
            yield start
            start /= stp


@classmethod
def export_to_hdf5(cls, h5_file, model, eids, encoding='ascii'):
    """exports the elements in a vectorized way"""
    pids = []
    nodes = []
    cid = []
    plane = []
    sptid = []
    for eid in eids:
        element = model.elements[eid]
        pids.append(element.pid)
        nodes.append(element.nodes)
        cid.append(element.cid)
        plane.append(element.plane.encode(encoding))
        sptidi = 0 if element.sptid is None else element.sptid
        sptid.append(sptidi)
    h5_file.create_dataset('eid', data=eids)
    h5_file.create_dataset('nodes', data=nodes)
    h5_file.create_dataset('pid', data=pids)
    h5_file.create_dataset('cid', data=cid)
    h5_file.create_dataset('plane', data=plane)
    h5_file.create_dataset('sptid', data=sptid)


def unicode_open(*args, **kwargs):
    """
        Opens files in UTF-8 encoding by default, unless an 'encoding'
        keyword argument is passed. Returns a file object.
    """
    if not 'encoding' in kwargs:
        kwargs['encoding'] = 'utf-8'
    return open(*args, **kwargs)


def vertex_group_copy_to_selected():
    """Replace vertex groups of selected objects by vertex groups of active object

    """
    pass


def __or__(i1, i2):
    """ Return the union of i1 and i2
        """
    return i1.__class__(i1._union(i1, i2))


def type_assert(exp, self):
    """
    exp 会做偏函数, 所以对象会被绑定在第二个参数上
    """
    actual = type(self._val)
    res = actual is exp
    msg_format = '{0} should be {1}'.format
    self._assert(res, msg_format(actual, exp))
    return self


def get_previous_versions():
    """Get a list of the ids of the most recent versions (that
        are not public anymore. Index 0 is oldest, up is more recent
        versions).
        """


@classmethod
def print(cls, text, col, indent=0, indent_step='   '):
    """
        Print color coded, indented text to standard out using Python print

        :param indent_step: String of spaces with the number of spaces per indent step (Default='    ')
        :param indent: Integer indicating the indentation level for the print (Default=0)
        :param text: The text to be printed
        :param col: One of PrintHelper.HEADER, OKBLUE etc.
        """
    indent_str = indent_step * indent
    print(col + indent_str + text + cls.ENDC)


@classmethod
def from_google(cls, google_x, google_y, zoom):
    """Creates a tile from Google format X Y and zoom"""
    max_tile = 2 ** zoom - 1
    assert 0 <= google_x <= max_tile, 'Google X needs to be a value between 0 and (2^zoom) -1.'
    assert 0 <= google_y <= max_tile, 'Google Y needs to be a value between 0 and (2^zoom) -1.'
    return cls(tms_x=google_x, tms_y=2 ** zoom - 1 - google_y, zoom=zoom)


@staticmethod
def is_https(request_data):
    """
        Checks if https or http.

        :param request_data: The request as a dict
        :type: dict

        :return: False if https is not active
        :rtype: boolean
        """
    is_https = 'https' in request_data and request_data['https'] != 'off'
    is_https = is_https or 'server_port' in request_data and str(request_data
        ['server_port']) == '443'
    return is_https


def build_ssh_command(config):
    """
    Prepare an ssh command according to the arguments passed on command line

    :param argparse.Namespace config: the configuration from command line
    :return list[str]: the ssh command as list of string
    """
    ssh_command = ['ssh', '%s@%s' % (config.user, config.barman_host), 'barman'
        ]
    if config.config:
        ssh_command.append("--config='%s'" % config.config)
    ssh_command.extend(['put-wal', config.server_name])
    if config.test:
        ssh_command.append('--test')
    return ssh_command


def dt_average(a, b):
    """ Average function that is friendly with datetime formats that only
    support substraction. """
    return a + (b - a) / 2


def _get_name_info(name_index, name_list):
    """Helper to get optional details about named references

       Returns the dereferenced name as both value and repr if the name
       list is defined.
       Otherwise returns the name index and its repr().
    """
    argval = name_index
    if name_list is not None and name_index < len(name_list):
        argval = name_list[name_index]
        argrepr = argval
    else:
        argrepr = repr(argval)
    return argval, argrepr


def get_verify_key(signing_key):
    """Get a verify key from a signing key"""
    verify_key = signing_key.verify_key
    verify_key.version = signing_key.version
    verify_key.alg = signing_key.alg
    return verify_key


def ndim(input):
    """Return the number of dimensions of the tensor.

    Parameters
    ----------
    input : Tensor
        The input tensor.

    Returns
    -------
    int
        The number of dimensions
    """
    pass


@classmethod
def error_handler(cls, sock, error):
    """Handle the error that occurred while trying to receive and handle the incoming command.

        Args:
            sock (multiprocessing.connection.Connection): Client socket in case you need to respond to the given command
            error (Exception): Error that occurred
        """
    pass


def services_to_strings(services, service_to_string):
    """Convert SUPPORT_* service bitmask to list of service strings."""
    strings = []
    for service in service_to_string:
        if service & services:
            strings.append(service_to_string[service])
    return strings


def unique_ancestors(node):
    """
    Returns the list of all nodes dominating the given node, where
    there is only a single path of descent.
    """
    results = []
    try:
        current = node.parent()
    except AttributeError:
        return results
    while current and len(current) == 1:
        results.append(current)
        current = current.parent()
    return results


def safe_no_dnn_workmem(workmem):
    """
    Make sure the user is not attempting to use dnn.conv.workmem`.
    """
    if workmem:
        raise RuntimeError(
            'The option `dnn.conv.workmem` has been removed and should not be used anymore. Please use the option `dnn.conv.algo_fwd` instead.'
            )
    return True


def is_outlier_detector(estimator):
    """Return True if the given estimator is (probably) an outlier detector.

    Parameters
    ----------
    estimator : object
        Estimator object to test.

    Returns
    -------
    out : bool
        True if estimator is an outlier detector and False otherwise.
    """
    return getattr(estimator, '_estimator_type', None) == 'outlier_detector'


def _first_fully_overlapping_windows(mzrs: list) ->list:
    """
    Select m/z windows that fall within another window and have a different mass ranges
    For example: [100-200] and [125-175] (Invalid)

    :param mzrs: Nested list of m/z ranges / windows
    :return: Nested list of m/z ranges / windows
    """
    assert type(mzrs) == list, 'List required'
    for i in range(0, len(mzrs) - 1):
        if mzrs[i][0] <= mzrs[i + 1][0] and mzrs[i][1] >= mzrs[i + 1][1]:
            return mzrs[i], mzrs[i + 1]
    return []


def draw_sprite_color(label_map, color_dict, background_color):
    """
    A function return label_map after draw color for each sprite

    @param:
        - label_map (a map after draw border for each sprite)
        - color_dict (a collection of color for each label)
        - background_color (the color to use as the background
                            of the image to create)

    @return:
        - label_map after draw color for each sprite
    """
    for row in range(len(label_map)):
        for col in range(len(label_map[row])):
            if label_map[row][col].label == 0:
                label_map[row][col] = background_color
            else:
                label_map[row][col] = color_dict[label_map[row][col].label]
    return label_map


@classmethod
def _split(cls, text, end='\n'):
    """Replace sentence boundaries with newlines and append a newline.

        :param text: string to line break at sentences
        :param end: appended to the end of the update text

        >>> Markdown._split("Hello, world!", end='')
        'Hello, world!'

        >>> Markdown._split("Hello, world! How are you? I'm fine. Good.")
        "Hello, world!\\nHow are you?\\nI'm fine.\\nGood.\\n"

        """
    stripped = text.strip()
    if stripped:
        return cls.REGEX_SENTENCE_BOUNDARIES.sub('\n', stripped) + end
    else:
        return ''


def _roman(data, scheme_map, **kw):
    """Transliterate `data` with the given `scheme_map`. This function is used
    when the source scheme is a Roman scheme.

    :param data: the data to transliterate
    :param scheme_map: a dict that maps between characters in the old scheme
                       and characters in the new scheme
    """
    vowels = scheme_map.vowels
    marks = scheme_map.marks
    virama = scheme_map.virama
    consonants = scheme_map.consonants
    other = scheme_map.other
    longest = scheme_map.longest
    to_roman = scheme_map.to_roman
    togglers = kw.pop('togglers', set())
    suspend_on = kw.pop('suspend_on', set())
    suspend_off = kw.pop('suspend_off', set())
    if kw:
        raise TypeError('Unexpected keyword argument %s' % list(kw.keys())[0])
    buf = []
    i = 0
    had_consonant = found = False
    len_data = len(data)
    append = buf.append
    toggled = False
    suspended = False
    while i <= len_data:
        token = data[i:i + longest]
        while token:
            if token in togglers:
                toggled = not toggled
                i += 2
                found = True
                break
            if token in suspend_on:
                suspended = True
            elif token in suspend_off:
                suspended = False
            if toggled or suspended:
                token = token[:-1]
                continue
            if had_consonant and token in vowels:
                mark = marks.get(token, '')
                if mark:
                    append(mark)
                elif to_roman:
                    append(vowels[token])
                found = True
            elif token in other:
                if had_consonant:
                    append(virama[''])
                append(other[token])
                found = True
            if found:
                had_consonant = token in consonants
                i += len(token)
                break
            else:
                token = token[:-1]
        if not found:
            if had_consonant:
                append(virama[''])
            if i < len_data:
                append(data[i])
                had_consonant = False
            i += 1
        found = False
    return ''.join(buf)


def _adjust_n_years(other, n, month, reference_day):
    """Adjust the number of times an annual offset is applied based on
    another date, and the reference day provided"""
    if n > 0:
        if (other.month < month or other.month == month and other.day <
            reference_day):
            n -= 1
    elif other.month > month or other.month == month and other.day > reference_day:
        n += 1
    return n


def default_narrative(end_yr, value_by, value_ey, diffusion_choice='linear',
    sig_midpoint=0, sig_steepness=1, base_yr=2015, regional_specific=True,
    fueltype_replace=0, fueltype_new=0):
    """Create a default single narrative with a single timestep

    E.g. from value 0.2 in 2015 to value 0.5 in 2050

    Arguments
    ----------
    end_yr : int
        End year of narrative
    value_by : float
        Value of start year of narrative
    value_ey : float
        Value at end year of narrative
    diffusion_choice : str, default='linear'
        Wheter linear or sigmoid
    sig_midpoint : float, default=0
        Sigmoid midpoint
    sig_steepness : float, default=1
        Sigmoid steepness
    base_yr : int
        Base year
    regional_specific : bool
        If regional specific or not

    Returns
    -------
    container : list
        List with narrative
    """
    return [{'base_yr': base_yr, 'end_yr': end_yr, 'value_by': value_by,
        'value_ey': value_ey, 'diffusion_choice': diffusion_choice,
        'sig_midpoint': sig_midpoint, 'sig_steepness': sig_steepness,
        'regional_specific': regional_specific, 'fueltype_replace': 0,
        'fueltype_new': 0}]


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

        :param FileLockingLockStatusChangedDetails val:
        :rtype: EventDetails
        """
    return cls('file_locking_lock_status_changed_details', val)


def gensim_corpus_to_dtm(corpus):
    """
    Convert a Gensim corpus object to a sparse DTM in COO format.

    .. seealso:: :func:`~tmtoolkit.bow.dtm.dtm_to_gensim_corpus` for the reverse function.

    :param corpus: Gensim corpus object
    :return: sparse DTM in COO format
    """
    import gensim
    from scipy.sparse import coo_matrix
    dtm_t = gensim.matutils.corpus2csc(corpus)
    return coo_matrix(dtm_t.transpose())


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 collection_holdout_clear():
    """Clear masking of collection in the active view layer

    """
    pass


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 zeta_BOH3_H_Cl_FW86(T, P):
    """n-c-a: boric-acid hydrogen chloride [FW86]."""
    zeta = -0.0102
    valid = T == 298.15
    return zeta, valid