def escape_like(query: str, escape_character: str) ->str:
    """
    Escape special characters that are used in SQL's LIKE and ILIKE.

    Chosen escape character is prepended to each occurrence of a special character.
    Escape character is considered a special character too.

    WARNING: Do not forget to specify escape character to SQLAlchemy when actually
    performing `like`s and `ilike`s:
    >>> escape_character = "~"
    >>> search_query = "99.5%"
    >>> search_query = escape_like(search_query, escape_character)
    >>> Record.query.like(search_query, escape=escape_character) # do not forget `escape`
    """
    assert len(escape_character) == 1
    cases = [escape_character, '%', '_']
    for case in cases:
        query = query.replace(case, escape_character + case)
    return query


def adjust_frequency(frequency):
    """
    把frequency为1m这样的分钟, 调整为秒
    """
    frequency = frequency.strip().lower()
    return '{}s'.format(int(frequency[0:-1] * 60)) if frequency.endswith('m'
        ) else frequency


def is_file(obj):
    """
    Check to see if the presented object could represent a file
    """
    return hasattr(obj, 'fileno')


def writeConnectionLost(reason):
    """
        Indicates write connection was lost.
        """


def validate_timestamp(timestamp, label, required=False):
    """Validates the given timestamp value. Timestamps must be positive integers."""
    if timestamp is None and not required:
        return None
    if isinstance(timestamp, bool):
        raise ValueError('Boolean value specified as timestamp.')
    try:
        timestamp_int = int(timestamp)
    except TypeError:
        raise ValueError('Invalid type for timestamp value: {0}.'.format(
            timestamp))
    else:
        if timestamp_int != timestamp:
            raise ValueError('{0} must be a numeric value and a whole number.'
                .format(label))
        if timestamp_int <= 0:
            raise ValueError('{0} timestamp must be a positive interger.'.
                format(label))
        return timestamp_int


def check_timestamp_by_rule(rulearray, tstamp):
    """ check if given time-stamp is comply to the given rule array

	Parameter:
		rulearray - rule array generated by parse_cronstring
		tstamp - time-stamp to be check
	Return:
		True if given time-stamp complied, False otherwise
	"""
    complied = 0
    for rset in rulearray:
        is_complied = False
        if rset is None:
            is_complied = True
        else:
            for robj in rset:
                if robj.is_accept(tstamp):
                    is_complied = True
                    break
        if is_complied:
            complied = complied + 1
    if 5 == complied:
        return True
    return False


def remove_duplicates(df, cols=None):
    """
	Remove duplicate values from specified columns.

	Parameters
	----------
	cols  : List of columns to make the comparison, this only  will consider this subset of columns,
	for dropping duplicates. The default behavior will only drop the identical rows.

	return: Return a new DataFrame with duplicate rows removed
	"""
    assert isinstance(cols, list
        ), 'Error, cols argument provided must be a list.'
    return df.drop_duplicates(cols)


def face_map_remove_from():
    """Remove faces from a face map

    """
    pass


def slot_paste():
    """Copy the texture settings and nodes

    """
    pass


def _tile_exists(raster_bounds, tile_bounds):
    """Check if a tile is inside a given bounds."""
    return tile_bounds[0] < raster_bounds[2] and tile_bounds[2
        ] > raster_bounds[0] and tile_bounds[3] > raster_bounds[1
        ] and tile_bounds[1] < raster_bounds[3]


def multiply(image1, image2):
    """
    Superimposes two images on top of each other.

    If you multiply an image with a solid black image, the result is black. If
    you multiply with a solid white image, the image is unaffected.

    .. code-block:: python

        out = image1 * image2 / MAX

    :rtype: :py:class:`~PIL.Image.Image`
    """
    image1.load()
    image2.load()
    return image1._new(image1.im.chop_multiply(image2.im))


def connect(name, pattern, factory=None, predicates=(), pregenerator=None,
    static=True):
    """ Add a new route. """


def to_dimacs(cnf):
    """
    An alternative to `pynusmv.bmc.ltlspec:dump_dimacs_filename` which generates
    less verbose dimacs files and permits to have them all loaded in memory.

    :param cnf: a `BeCnf` expression to encode in dimacs format
    :return: a string representation of the `cnf` formula in DIMACS CNF format
    """
    heading = 'p cnf {} {}'.format(cnf.vars_number, cnf.clauses_number)
    d_clauses = [heading]
    for clause in cnf.clauses_list:
        text_form = ' '.join(map(str, clause)) + ' 0'
        d_clauses.append(text_form)
    return '\n'.join(d_clauses)


def _int_to_bit_tuple(value, bits):
    """
    Format value as a tuple of 1s and 0s.

    :param value:
        A non-negative integer to format

    :param bits:
        Number of bits in the output

    :return:
        A tuple of 1s and 0s with bits members.
    """
    if not value and not bits:
        return ()
    result = tuple(map(int, format(value, '0{0}b'.format(bits))))
    if len(result) != bits:
        raise ValueError('Result too large: {0} > {1}'.format(len(result),
            bits))
    return result


def lookahead(iterable):
    """Pass through all values from the given iterable, augmented by the
    information if there are more values to come after the current one
    (True), or if it is the last value (False).
    """
    it = iter(iterable)
    last = next(it)
    for val in it:
        yield last, True
        last = val
    yield last, False


def test_1arg(x):
    """
  test_1arg(x) = x

  Must be called with exactly one argument "x".
  """
    return x


def set_workflow(transition, path=''):
    """
        set_workflow sets the workflow state of an object.
        """


def getFisxMatName(materialName):
    """Small hack to make sure the given material name is not existing yet on
    fisx"""
    return '_' + materialName


def unquote_etag(etag):
    """Unquote a single etag:

    >>> unquote_etag('W/"bar"')
    ('bar', True)
    >>> unquote_etag('"bar"')
    ('bar', False)

    :param etag: the etag identifier to unquote.
    :return: a ``(etag, weak)`` tuple.
    """
    if not etag:
        return None, None
    etag = etag.strip()
    weak = False
    if etag.startswith(('W/', 'w/')):
        weak = True
        etag = etag[2:]
    if etag[:1] == etag[-1:] == '"':
        etag = etag[1:-1]
    return etag, weak


@classmethod
def available(cls):
    """returns True if PulseAudio is available and running on the system"""
    try:
        from audiotools.output import PulseAudio
        return True
    except ImportError:
        return False


def _interpolate(val, vmin, vmax):
    """Interpolate a color component between to values as provided
    by matplotlib colormaps
    """
    interp = (val - vmin[0]) / (vmax[0] - vmin[0])
    return (1 - interp) * vmin[1] + interp * vmax[2]


@classmethod
def include(cls, name, hash_key, range_key=None, includes=None, throughput=None
    ):
    """ Create an index that projects key attributes plus some others """
    return cls(cls.INCLUDE, name, hash_key, range_key, includes, throughput
        =throughput)


def current_version(repo):
    """Return the current version."""
    with open(repo + '/current_version', 'r') as f:
        return f.readline().strip()


def listify(thing):
    """Convert thing to a list.

    If thing is a string, then returns a list of thing. Otherwise
    returns thing.

    :arg thing: string or list of things

    :returns: list

    """
    if thing is None:
        return []
    if isinstance(thing, str):
        return [thing]
    return thing


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

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


def combine(hi, lo):
    """Combine the hi and lo bytes into the final ip address."""
    return (hi << 64) + lo


def saturation(L):
    """
    Return saturation density of a flux tube as a function of L-shell in units
    of :math:`#/cm^3`. Formula is from Carpenter and Anderson, JGR, 1992.
    """
    return 10 ** (-0.3145 * L + 3.9043)


def distance_between(s0, s1):
    """
    Return distance (real number) between two shapes.
    """
    raise NotImplementedError
    return 0.0


def AfterTransitionEventHandler(instance, event):
    """This will run the workflow_script_* on any
    content type that has one.
    """
    if not event.transition:
        return
    key = 'workflow_script_' + event.transition.id
    method = getattr(instance, key, False)
    if method:
        method()


def iteritems():
    """
        Get the iterator for this storage, should yield tuple of (key, value)
        """


@staticmethod
def p_a2ml_struct_type_name(p):
    """a2ml_struct_type_name : struct a2ml_identifier_optional CURLY_OPEN a2ml_struct_member_list_optional CURLY_CLOSE
                                 | struct a2ml_identifier"""
    p[0] = p[1]


def lookup_id_from_name(name, cfg):
    """
        Return ID key from an name in an config dict.
        :param str name: The string to lookup in an key 'name'.
        :param list cfg: The list of dicts to lookup 'id' from an 'name'.
        :return: The ID match with the 'name' string, or 0 if not found.
        :rtype : Integer
    """
    try:
        cfg_id = filter(lambda c: c['name'] == name, cfg)[0]['id']
    except:
        cfg_id = 0
    return cfg_id


def _split_sections(lines):
    """Split `lines` into sections of lines that have the same amount of parts"""
    sections = []
    while lines:
        line = lines.pop(0)
        partnum = len(line)
        section = [line]
        while lines and len(lines[0]) == partnum:
            line = lines.pop(0)
            section.append(line)
        sections.append(section)
    return sections


def splitBaseline(baseline, shift=16):
    """
    Given a baseline, split it into it consistent stand ID numbers.
    """
    part = 2 ** shift - 1
    return baseline >> shift & part, baseline & part


def count_all(seq, reverse=None):
    """
    Return a list of (value, count) pairs for each unique value in L.

    The result can be sorted from the least frequent to the most frequent if
    `reverse=False` or otherwise if reverse=True`.

    Examples:
        >>> count_all([10, 20, 10, 20, 30, 20], reverse=True)
        [(20, 3), (10, 2), (30, 1)]
    """
    countD = {}
    for idx, x in enumerate(seq):
        try:
            countD[x] = countD.get(x, 0) + 1
        except TypeError:
            break
    else:
        idx = None
    out = list(countD.items())
    if idx is not None:
        countL = list(countD.items())
        for i in range(idx, len(seq)):
            x = seq[i]
            for i, (y, c) in enumerate(countL):
                if y == x:
                    out[i] = x, c + 1
                    break
            else:
                out.append((x, 1))
    if reverse is not None:
        out.sort(key=lambda x: x[1], reverse=reverse)
    return out


def renderHeadCell():
    """Render the column header label."""


@classmethod
def isEnabled(cls):
    """
        Class method to check, if safe browsing is enabled.

        @return flag indicating the enabled state
        @rtype bool
        """
    return cls.enabled


def to_neutral_name(name):
    """ Convert a name to the neutral name with no capitals, underscores or dots.
    Used primarily to match function names of IDL and .h specs.
    """
    name = name.lower()
    if name.startswith('gpu'):
        name = name[3:]
    if name.startswith('wgpu'):
        name = name[4:]
    for c in ' -_.':
        name = name.replace(c, '')
    return name


@classmethod
def from_isovar_result(cls, isovar_result):
    """
        Create a MutantProteinFragment from an isovar.IsovarResult object

        Parameters
        ----------
        isovar_result : isovar.IsovarResult

        Returns
        -------
        MutantProteinFragment
        """
    protein_sequence = isovar_result.top_protein_sequence
    if protein_sequence is None:
        return None
    return cls(variant=isovar_result.variant, gene_name=protein_sequence.
        gene_name, amino_acids=protein_sequence.amino_acids,
        mutant_amino_acid_start_offset=protein_sequence.mutation_start_idx,
        mutant_amino_acid_end_offset=protein_sequence.mutation_end_idx,
        n_overlapping_reads=isovar_result.num_total_fragments, n_alt_reads=
        isovar_result.num_alt_fragments, n_ref_reads=isovar_result.
        num_ref_fragments, n_alt_reads_supporting_protein_sequence=
        protein_sequence.num_supporting_fragments,
        supporting_reference_transcripts=protein_sequence.transcripts)


def viz_td(body, port=None, align='CENTER'):
    """Create HTML td for graphviz"""
    port_text = '' if port is None else 'PORT="{}"'.format(port)
    return '<TD {port_text} ALIGN="{align}">{body}</TD>'.format(**locals())


def method_return_unpacked():
    """This method has a single element returns, and when called will return
    this single element unpacked rather than in a single element map

    E.g.
       hello.greet("me") -> "Hello me" not {"return": "Hello me"}
    """
    tag = 'method:return:unpacked'
    return tag


def shorten_hash(original_hash: int) ->int:
    """
    This function removes final bytes from a hash to get a hash that can be parsed in java as an int
    :param original_hash: the original hash of an object. This should have 36 bytes.
    :return: A in int parsed from the first 32 bytes of the original hash
    """
    max_signed_int_32_bit = 2 ** 31 - 1
    return original_hash % max_signed_int_32_bit


@classmethod
def _pre_validate(cls, **kwargs):
    """ Pre execute logic. This method is executed before the main logic in the 'execute' method """
    pass


def get_job_manifest(JobId=None):
    """
    Returns a link to an Amazon S3 presigned URL for the manifest file associated with the specified JobId value. You can access the manifest file for up to 60 minutes after this request has been made. To access the manifest file after 60 minutes have passed, you'll have to make another call to the GetJobManifest action.
    The manifest is an encrypted file that you can download after your job enters the WithCustomer status. The manifest is decrypted by using the UnlockCode code value, when you pass both values to the Snowball through the Snowball client when the client is started for the first time.
    As a best practice, we recommend that you don't save a copy of an UnlockCode value in the same location as the manifest file for that job. Saving these separately helps prevent unauthorized parties from gaining access to the Snowball associated with that job.
    The credentials of a given job, including its manifest file and unlock code, expire 90 days after the job is created.
    See also: AWS API Documentation

    Examples
    Returns a link to an Amazon S3 presigned URL for the manifest file associated with the specified JobId value. You can access the manifest file for up to 60 minutes after this request has been made. To access the manifest file after 60 minutes have passed, you'll have to make another call to the GetJobManifest action.

    :example: response = client.get_job_manifest(
        JobId='string'
    )

    :type JobId: string
    :param JobId: [REQUIRED]
            The ID for a job that you want to get the manifest file for, for example JID123e4567-e89b-12d3-a456-426655440000 .

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

    """
    pass


def _is_instance(obj):
    """is custom class instance"""
    return hasattr(obj, '__dict__') or hasattr(obj, '__slots__')


def get_subjects():
    """Returns the list of subjects."""


def key_to_note(key, octaves=True):
    """Returns a string representing a note which is (key) keys from A0"""
    notes = ['a', 'a#', 'b', 'c', 'c#', 'd', 'd#', 'e', 'f', 'f#', 'g', 'g#']
    octave = (key + 8) // 12
    note = notes[(key - 1) % 12]
    if octaves:
        return note.upper() + str(octave)
    else:
        return note.upper()


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


def number2string(i):
    """Convert a number to a string

    Input: long or integer
    Output: string (big-endian)
    """
    s = hex(i)[2:].rstrip('L')
    if len(s) % 2:
        s = '0' + s
    return s.decode('hex')


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

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

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


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

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    :param deselect: Deselect, Remove from selection
    :type deselect: bool
    :param toggle: Toggle Selection, Toggle the selection
    :type toggle: bool
    :param deselect_all: Deselect On Nothing, Deselect all when nothing under the cursor
    :type deselect_all: bool
    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


def is_solved(cands_of):
    """A puzzle is solved if its candidate
        dict has only one candidate for each cell"""
    for vals in cands_of.values():
        if len(vals) > 1:
            return False
    return True


def sum_2_dictionaries(dicta, dictb):
    """Given two dictionaries of totals, where each total refers to a key
       in the dictionary, add the totals.
       E.g.:  dicta = { 'a' : 3, 'b' : 1 }
              dictb = { 'a' : 1, 'c' : 5 }
              dicta + dictb = { 'a' : 4, 'b' : 1, 'c' : 5 }
       @param dicta: (dictionary)
       @param dictb: (dictionary)
       @return: (dictionary) - the sum of the 2 dictionaries
    """
    dict_out = dicta.copy()
    for key in dictb.keys():
        if 'key' in dict_out:
            dict_out[key] += dictb[key]
        else:
            dict_out[key] = dictb[key]
    return dict_out


def copy_to(input, ctx):
    """Copy the given tensor to the context.

    Parameters
    ----------
    input : Tensor
        The input tensor
    ctx :
        A framework-specific context object.

    Returns
    -------
    Tensor
        The tensor on the given context.
    """
    pass


def cols_to_normalize(df, columns):
    """Convert data points to values between 0 and 1 and return new columns of prefixed data.

    Args:
        df: Pandas dataframe.
        columns: List of columns to transform.

    Returns:
        Original dataframe with additional prefixed columns.
    """
    for col in columns:
        df['norm_' + col] = (df[col] - df[col].min()) / (df[col].max() - df
            [col].min())
    return df


@staticmethod
def time_converter(resp):
    """
        Parses request.elapsed into milliseconds

        :param resp: response object
        :returns: integer that represents milliseconds

        """
    return int(resp.total_seconds() * 1000)


def xtype_from_derivation(derivation):
    """Returns the script type to be used for this derivation."""
    if derivation.startswith("m/84'"):
        return 'p2wpkh'
    elif derivation.startswith("m/49'"):
        return 'p2wpkh-p2sh'
    else:
        return 'p2pkh'


def convert_by_vocab(vocab, items):
    """Converts a sequence of [tokens|ids] using the vocab."""
    output = []
    for item in items:
        output.append(vocab[item])
    return output


def read(data=None):
    """
Read ``sinfo -o "%all"``.

:options:

  **data** (``<str>``)
    For debugging: specify the output of ``sinfo -o "%all"`` as string.

:returns:

  **lines** ``<list<dict>>``
    A list of dictionaries, that contain the different fields. All data are strings.
  """
    import subprocess
    if data is None:
        data = subprocess.check_output('sinfo -o "%all"', shell=True).decode(
            'utf-8')
    head, data = data.split('\n', 1)
    data = list(filter(None, data.split('\n')))
    head = head.split('|')
    lines = []
    for line in data:
        info = {}
        for key, val in zip(head, line.split('|')):
            if len(key.strip()) > 0:
                info[key.strip()] = val.strip()
        lines += [info]
    return lines


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


def shortest_path_pick():
    """Select shortest path between two selections

    """
    pass


def _validate_dict_or_string(s):
    """
	A validation method to convert input s to string or dictionary and raise error if it is not convertable
	"""
    if isinstance(s, str) or isinstance(s, dict):
        return s
    try:
        return str(s)
    except ValueError:
        raise ValueError('Could not convert input to dict or string')


def deltafmt(delta, decimals=None):
    """
Returns a human readable representation of a time with the format:

	[[[Ih]Jm]K[.L]s

For example: 6h5m23s

If "decimals" is specified, the seconds will be output with that many decimal places.
If not, there will be two places for times less than 1 minute, one place for times
less than 10 minutes, and zero places otherwise
"""
    try:
        delta = float(delta)
    except:
        return '(bad delta: %s)' % (str(delta),)
    if delta < 60:
        if decimals is None:
            decimals = 2
        return ('{0:.' + str(decimals) + 'f}s').format(delta)
    mins = int(delta / 60)
    secs = delta - mins * 60
    if delta < 600:
        if decimals is None:
            decimals = 1
        return ('{0:d}m{1:.' + str(decimals) + 'f}s').format(mins, secs)
    if decimals is None:
        decimals = 0
    hours = int(mins / 60)
    mins -= hours * 60
    if delta < 3600:
        return '{0:d}m{1:.0f}s'.format(mins, secs)
    else:
        return ('{0:d}h{1:d}m{2:.' + str(decimals) + 'f}s').format(hours,
            mins, secs)


@classmethod
def use(cls, server_url, timestamp, salt):
    """Create a Nonce instance"""
    raise NotImplementedError('Implement in subclass')


def tie_weight(to_layer, from_layer):
    """Assigns a weight object to the layer weights.

    This method exists to duplicate baseline functionality across packages.

    :param to_layer: the pytorch layer to assign weights to
    :param from_layer: pytorch layer to retrieve weights from
    """
    to_layer.weight = from_layer.weight


def ready():
    """Returns :const:`True` if the task has been executed."""


def maybe_evaluate(obj):
    """Attempt to evaluate promise, even if obj is not a promise."""
    try:
        return obj.__maybe_evaluate__()
    except AttributeError:
        return obj


def player_salary_values(html_text):
    """ player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by SpotRac
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = '<span'
    player_salaries = {}
    url_val = html_text.find('<a')
    total_val = html_text.find('Active Roster Cap	')
    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2:end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">')]
        player_key = play_key.split('/')[-2]
        for col_count in range(0, 9):
            if col_count < 6:
                start_ind = html_text.find(value_str) + len(value_str)
                html_text = html_text[start_ind:]
                start_ind = html_text.find('">') + 2
                end_ind = html_text.find('')
                end_len = 7
            elif col_count == 6:
                start_ind = html_text.find('') + 2
                if 'option-' in html_text[:start_ind]:
                    option_start = html_text.find('option-') + 7
                    option_end = html_text.find(' "')
                    option_list.append(html_text[option_start:option_end])
                end_ind = html_text.find('<input')
                end_len = 6
            elif col_count == 7:
                start_ind = html_text.find(value_str) + len(value_str)
                html_text = html_text[start_ind:]
                start_ind = html_text.find('" >') + 3
                end_ind = html_text.find(' ')
                end_len = 8
            else:
                start_ind = html_text.find('') + 3
                end_ind = html_text.find('	')
                end_len = 5
            try:
                salary_value = html_text[start_ind:end_ind]
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + end_len:]
        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list
        total_val = html_text.find('Active Roster Cap	')
        url_val = html_text.find('<a')
    return player_salaries


def getEofZ2TotalKeeton(EofZ2, EofZ2Final, EofZZFinal):
    """
	get total from NS loop and final contributions
	"""
    return EofZ2 + EofZ2Final + 2.0 * EofZZFinal


def p_simple_command(p):
    """simple_command : simple_command_element
                      | simple_command simple_command_element"""
    p[0] = p[1]
    if len(p) == 3:
        p[0].extend(p[2])


def matches_any(name, alternates):
    """Return a named group pattern matching list of alternates."""
    return '(?P<%s>' % name + '|'.join(alternates) + ')'


@classmethod
def from_cartesian(cls, cart):
    """
        Converts 3D rectangular cartesian coordinates to radial coordinate.
        """
    return cls(distance=cart.norm(), copy=False)


@staticmethod
def _deserialize_date(value):
    """
        Deserialise a date
        :param value: The date vlue
        :return: The deserialised date
        """
    import datetime
    import pytz
    if value is None:
        return value
    if value['timezone'] is None:
        return datetime.datetime.strptime(value['date'], '%Y-%m-%dT%H:%M:%S.%f'
            )
    if value['timezone'] == 'UTC':
        return datetime.datetime.strptime(value['date'], '%Y-%m-%dT%H:%M:%S.%f'
            ).replace(tzinfo=pytz.utc)
    return datetime.datetime.strptime(value['date'], '%Y-%m-%dT%H:%M:%S.%f'
        ).replace(tzinfo=pytz.timezone(value['timezone']))


def _describe_type(arg):
    """Describe given argument, including length if it's a tuple.

    The purpose is to prevent nonsensical exception messages such as::

        expected a tuple of length 2, got tuple
        expected a tuple, got tuple

    by turning them into::

        expected a tuple of length 3, got tuple of length 2
    """
    if isinstance(arg, tuple):
        return 'tuple of length %s' % len(arg)
    else:
        return type(arg).__name__


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

        :param SharedContentRestoreMemberDetails val:
        :rtype: EventDetails
        """
    return cls('shared_content_restore_member_details', val)


@classmethod
def drop_collection(cls):
    """Drops the entire collection associated with this
        :class:`SanicMongo.Document` type from the database.
        """
    cls._collection = None
    db = cls._get_db()
    return db.drop_collection(cls._get_collection_name())


def get_raster_from_json(scenario, raster_code):
    """return raster json object from scenario"""
    for result in scenario['result_set']:
        if result['result_type']['code'] == raster_code:
            return result['raster']


def camel_to_underscore(name):
    """Convert camel case style naming to underscore style naming

    If there are existing underscores they will be collapsed with the
    to-be-added underscores. Multiple consecutive capital letters will not be
    split except for the last one.

    >>> camel_to_underscore('SpamEggsAndBacon')
    'spam_eggs_and_bacon'
    >>> camel_to_underscore('Spam_and_bacon')
    'spam_and_bacon'
    >>> camel_to_underscore('Spam_And_Bacon')
    'spam_and_bacon'
    >>> camel_to_underscore('__SpamAndBacon__')
    '__spam_and_bacon__'
    >>> camel_to_underscore('__SpamANDBacon__')
    '__spam_and_bacon__'
    """
    output = []
    for i, c in enumerate(name):
        if i > 0:
            pc = name[i - 1]
            if c.isupper() and not pc.isupper() and pc != '_':
                output.append('_')
            elif i > 3 and not c.isupper():
                previous = name[i - 3:i]
                if previous.isalpha() and previous.isupper():
                    output.insert(len(output) - 1, '_')
        output.append(c.lower())
    return ''.join(output)


def ndim2spatial_axes(ndim):
    """
    >>> ndim2spatial_axes(3)
    (-3, -2, -1)

    >>> ndim2spatial_axes(1)
    (-1,)
    """
    return tuple(range(-ndim, 0))


def mmcif_lines_to_mmcif_blocks(lines):
    """A .cif file is ultimately a list of tables. This function takes a list of
    .cif file lines and splits them into these table blocks. Each block will be
    a ``dict`` containing a category name and a list of lines.

    :param deque lines: the .cif file lines.
    :rtype: ``list``"""
    category = None
    block, blocks = [], []
    while lines:
        line = lines.popleft()
        if line.startswith('data_'):
            continue
        if line.startswith('_'):
            line_category = line.split('.')[0]
            if line_category != category:
                if category:
                    blocks.append({'category': category[1:], 'lines': block})
                category = line_category
                block = []
        if line.startswith('loop_'):
            if category:
                blocks.append({'category': category[1:], 'lines': block})
            category = lines[0].split('.')[0]
            block = []
        block.append(line)
    if block:
        blocks.append({'category': category[1:], 'lines': block})
    return blocks


def ms_type_from_header(h: str) ->str:
    """
    Extract the ms type from header or filter string

    :param h: header or filter string
    :return: ms type (e.g. FTMS and ITMS)
    """
    return h.split(' ')[0]


def get_comments(github_object):
    """Get a list of comments, whater the object is a PR, a commit or an issue.
    """
    try:
        return github_object.get_issue_comments()
    except AttributeError:
        return github_object.get_comments()


@classmethod
def put_key(cls, key, value):
    """
        Wrapper for KVSClient put
        """
    return cls.client.put(key, value)


def info(client, user_id, group_id):
    """Get QoS info of specified user"""
    qos = client.qos.limits(method='GET', userId=user_id, groupId=group_id)
    return qos


def tile(input, size, dim):
    """
    >>> x = torch.tensor([[1,2], [3, 4], [5,6]])
    >>> x
    tensor([[1, 2],
            [3, 4],
            [5, 6]])
    >>> tile(x, 3, dim=1)
    tensor([[1, 1, 1, 2, 2, 2],
            [3, 3, 3, 4, 4, 4],
            [5, 5, 5, 6, 6, 6]])
    :param self:
    :param input:
    :param size:
    :param dim:
    :return:
    """
    assert input.dim() == 2
    assert dim == 1
    batch_size = input.size(0)
    return input.view(-1, 1).repeat(1, size).view(batch_size, -1)


def ndarray2GSLIB(array, data_file, col_name):
    """Convert 1D or 2D numpy ndarray to a GSLIB Geo-EAS file for use with
    GSLIB methods.

    :param array: input array
    :param data_file: file name
    :param col_name: column name
    :return: None
    """
    if array.ndim not in [1, 2]:
        raise ValueError('must use a 2D array')
    with open(data_file, 'w') as f:
        f.write(data_file + '\n')
        f.write('1 \n')
        f.write(col_name + '\n')
        if array.ndim == 2:
            ny, nx = array.shape
            for iy in range(ny):
                for ix in range(nx):
                    f.write(str(array[ny - 1 - iy, ix]) + '\n')
        elif array.ndim == 1:
            nx = len(array)
            for ix in range(0, nx):
                f.write(str(array[ix]) + '\n')


def register_deployable_on_tier(ts, deployable, attributes):
    """
    Deployable registration callback for tier.
    'deployable' is from table 'deployables'.
    """
    pass


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

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

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


def select_nearest_point(target, points, threshold):
    """Select data point nearest to a given point in time.

    :param datetime.datetime target: the target timestamp for the point.
    :param points: an iterator of :class:`Point`s to search.
    :param float threshold: the maximum number of seconds the selected
        point can be away from the target timestamp.

    :raises ValueError: if the selected data point exceeds the threshold.

    :returns: the :class:`Point` nearest to ``target``.
    """
    sorted_points = sorted(points, key=lambda p: abs(target - p.timestamp))
    if not sorted_points:
        raise ValueError('No points given')
    if abs(target - sorted_points[0].timestamp).total_seconds() > threshold:
        raise ValueError('No metric point within {} seconds'.format(threshold))
    return sorted_points[0]


def atse_isSchemaRegistered(schema_id):
    """ returns True if schema exists """


@staticmethod
def _ishex(value):
    """Returns true if value is hex.

        Parameters
        ----------
        value: :obj:`str`
            A string that can be or not hex.

        """
    try:
        int(value, 16)
        return True
    except ValueError:
        return False


@classmethod
def _quick_search_es(cls, search_phrase, autocomplete=False):
    """
        Searches on elasticsearch server for given search phrase.

        TODO:

            * Add support for sorting
            * Migrate to aggregates from facets

        This method passes a query, alongwith term facets, to the search method
        for processing. For example, if one has a `~pyes.query.BoolQuery`
        object, and the product has attributes 'color' and 'size', one may pass
        them as terms as follows -:

        >>> query.facet.add_term_facet('color')
        >>> query.facet.add_term_facet('size')

        The resultset is then obtained and relevant data can be retrieved.

        >>> result_set = conn.search(query, **kwargs)
        >>> print result_set.facets['color']['terms']
        [
            {'count': 1, 'term': 'blue'},
            {'count': 2, 'term': 'black'},
            ...
        ]

        :param search_phrase: Searches for this particular phrase
        :param limit: The number of records to be returned
        :param autocomplete: A boolean which is set to True if the request
        comes from the autocomplete web handler
        :returns: `~pyes.es.ResultSet` object which contains each product's
        attributes
        """
    filterable_attributes = cls.get_filterable_attributes()
    es_filter = cls._build_es_filter(filterable_attributes=
        filterable_attributes)
    query = cls._build_es_query(search_phrase)
    search_obj = query.search(filter=es_filter)
    if not autocomplete:
        cls._update_es_facets(search_obj, facet_filter=es_filter,
            filterable_attributes=filterable_attributes)
    return search_obj


@staticmethod
def split(cmd):
    """ Split a command line string into a list of arguments """
    raise NotImplementedError


@staticmethod
def add_git(meta, git_info):
    """Enrich the result meta information with commit data."""
    meta['hexsha'] = git_info.hexsha
    meta['author'] = git_info.author
    meta['email'] = git_info.email
    meta['authored_on'] = git_info.authored_on.isoformat(' ')


def test_values_eq(val1, val2) ->bool:
    """Test if val1 eq val2 for template management."""
    if val1 is None or val2 is None:
        return True
    if val1 == val2:
        return True
    return False


def delete_domain(DomainName=None):
    """
    The DeleteDomain operation deletes a domain. Any items (and their attributes) in the domain are deleted as well. The DeleteDomain operation might take 10 or more seconds to complete.
    See also: AWS API Documentation

    :example: response = client.delete_domain(
        DomainName='string'
    )

    :type DomainName: string
    :param DomainName: [REQUIRED] The name of the domain to delete.

    """
    pass


def get_import_context(node):
    """
    Go backs up the graph to the import that started this possible cycle,
    and gets the import line number
    :param node:
    :return: int
    """
    name = node.name
    seen = set()
    while node.parent and node.parent.parent:
        node = node.parent
        if node in seen or node.parent and node.parent.name == name:
            break
        seen.add(node)
    return node.is_imported_from[node.parent.full_path][0]


def log1p(img):
    """
        Element-wise log of 1 + an `Image`.

        If the `Image` is empty, returns the empty `Image`.

        Example
        -------
        >>> import descarteslabs.workflows as wf
        >>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1").pick_bands("red")
        >>> img.log1p().compute(geoctx) # doctest: +SKIP
        ImageResult:
        ...
        """
    from ..math import arithmetic
    return arithmetic.log1p(img)


def append_dict(dict_obj, measure_key, measure_value):
    """appends data to keyed dict.

    Function that appends key to continuous dict, creates if doesn't exist. EAFP

    Parameters
    ----------
    dict_obj : dict
        dictionary object that contains continuous output measures

    measure_key : str
        key for the measure to be stored in continuous_dict

    measure_value : any data container
        value to be appended to dictionary

    Returns
    -------
    dict_obj : dict
        dictionary object passed to function, with specified data container appended

    Examples
    --------
    Given a dict object 'example' with some data in it:

    >>> example = {}
    >>> example['call'] = ['hello']

    We can use the function to append it:

    >>> example = append_dict(example, 'call', 'world')
    >>> example['call']
    ['hello', 'world']

    A new key will be created if it doesn't exist:

    >>> example = append_dict(example, 'different_key', 'hello there!')
    >>> sorted(example.keys())
    ['call', 'different_key']
    """
    try:
        dict_obj[measure_key].append(measure_value)
    except KeyError:
        dict_obj[measure_key] = [measure_value]
    return dict_obj


@classmethod
def _coerce_type(cls, value):
    """Convert value to int, float, or bool, if possible."""
    try:
        val = int(value)
    except ValueError:
        try:
            val = float(value)
        except ValueError:
            if value == 'False':
                val = False
            elif value == 'True':
                val = True
            else:
                val = cls.strip_and_unquote([], value)
    return val


def _xhaust(mapfunc, call, iterable, exception=StopIteration, n=next):
    """Call function `call` on an `iterable` until it's exhausted."""
    iterable = mapfunc(call, iterable)
    try:
        while 1:
            n(iterable)
    except exception:
        pass


def read_uic2tag(fh, byteorder, dtype, plane_count):
    """Read MetaMorph STK UIC2Tag from file and return as dictionary."""
    assert dtype == '2I' and byteorder == '<'
    values = fh.read_array('<u4', 6 * plane_count).reshape(plane_count, 6)
    return {'z_distance': values[:, (0)] / values[:, (1)], 'date_created':
        values[:, (2)], 'time_created': values[:, (3)], 'date_modified':
        values[:, (4)], 'time_modified': values[:, (5)]}


@staticmethod
def _is_first_multiline(line_stripped):
    """Check if the current line is a first line of multiline string."""
    is_first_multiline = line_stripped[-1] == '>'
    is_first_multiline = is_first_multiline and len(line_stripped.split(' ')
        ) <= 2
    return is_first_multiline


def _hyphenate(input, add_prefix=False):
    """Change underscores to hyphens so that object attributes can be easily
    tranlated to GPG option names.

    :param str input: The attribute to hyphenate.
    :param bool add_prefix: If True, add leading hyphens to the input.
    :rtype: str
    :return: The ``input`` with underscores changed to hyphens.
    """
    ret = '--' if add_prefix else ''
    ret += input.replace('_', '-')
    return ret


def namesAndDescriptions(dotted_name, all=0):
    """ Returns a list of pairs (name, description) for a given
        interface"""


def p_constant(t):
    """constant : CONST10
                | CONST8
                | CONST16"""
    if len(t[1]) > 9:
        t[0] = t[1] + 'L'
    else:
        t[0] = t[1]


def parse_set(string):
    """Parse set from comma separated string."""
    string = string.strip()
    if string:
        return set(string.split(','))
    else:
        return set()


def is_number(obj):
    """
    Checks if the given object is a number.

    Parameters
    ----------
    obj : Any
        The input argument.

    Returns
    -------
    test result : bool
        The test result of whether obj can be converted to a number or not.

    >>> is_number(3)
    True

    >>> is_number(1.34)
    True

    >>> is_number('3')
    True

    >>> is_number(np.array(3))
    True

    >>> is_number('a')
    False

    >>> is_number([1, 2, 3])
    False

    >>> is_number(None)
    False
    """
    try:
        float(obj)
        return True
    except (ValueError, TypeError):
        return False


def encode_sortable_key(encoder, value):
    """Takes a key and calculates the length of its optimal byte representation"""
    encoded = encoder.encode_to_bytes(value)
    return len(encoded), encoded


def t_handout_end(t):
    """\\s{3}</раздатка>\\n"""
    t.lexer.text += '\n]'
    t.lexer.begin('question')


def group_edit(exit: bool=False):
    """Edit node group

    :param exit: Exit
    :type exit: bool
    """
    pass


def pseudocode(algorithm):
    """Print the pseudocode for the given algorithm."""
    from urllib.request import urlopen
    from IPython.display import Markdown
    algorithm = algorithm.replace(' ', '-')
    url = (
        'https://raw.githubusercontent.com/aimacode/aima-pseudocode/master/md/{}.md'
        .format(algorithm))
    f = urlopen(url)
    md = f.read().decode('utf-8')
    md = md.split('\n', 1)[-1].strip()
    md = '#' + md
    return Markdown(md)


def _http_request(session, path, method='GET', options=None, params=None,
    headers=None):
    """Raw HTTP request helper function.

    Keyword arguments:
    :param session: The requests Session object to call a request with.
    :param path: the URL path.
    :param method: the HTTP method.
    :param options: a dictionary of data and parameters to pass on to the request.
    :param params: URL query parameters.
    :param headers: Dictionary of HTTP headers to include in the request.
    :return: requests response object.

    """
    path = path.strip('/')
    path = path.strip()
    url = '{}/{}'.format(session.hostname, path)
    allow_redirects = True
    if method in ['POST', 'PUT']:
        allow_redirects = False
    if options and 'allow_redirects' in options:
        allow_redirects = options['allow_redirects']
    data = None
    if options and 'data' in options:
        data = options['data']
    json = None
    if options and 'json' in options:
        json = options['json']
    if headers is None:
        headers = {}
    response = session.request(method, url, headers=headers,
        allow_redirects=allow_redirects, data=data, json=json, params=params)
    redirect_codes = [300, 301, 302, 303, 304, 305, 306, 307, 308]
    if method in ['POST', 'PUT'] and response.status_code in redirect_codes:
        if response.headers['Location']:
            response = session.request(method, response.headers['Location'],
                headers=headers, allow_redirects=True, data=data, json=json,
                params=params)
    return response


def __setattr__(zelf, name, value):
    """ Implement dotted dict access. """
    return zelf.__setitem__(name, value)


def set_bit(v, index, x):
    """Set the index:th bit of v to 1 if x is trur, else to 0, and return the new value."""
    mask = 1 << index
    v &= ~mask
    if x:
        v |= mask
    return v


@staticmethod
def storeDB(conn, ipv6addrs):
    """Overwrite the addresses in the table with the specified addresses (string) in the database."""
    connection = conn.cursor()
    vals = []
    for ipv6addr in ipv6addrs:
        vals.append((ipv6addr,))
    connection.execute('delete from ipv6addr')
    connection.executemany('insert into ipv6addr(addr) values (?)', iter(vals))
    connection.close()


def detach():
    """Detach selected nodes from parents

    """
    pass


@staticmethod
def writeString(data):
    """ Write a string as null-terminated c string (bytes). """
    if data is None:
        return chr(0)
    return data.encode('utf-8') + chr(0)


def zoom_border(xmin: int=0, xmax: int=0, ymin: int=0, ymax: int=0,
    wait_for_input: bool=True, zoom_out: bool=False):
    """Zoom in the view to the nearest item contained in the border

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


def default_violin_plot():
    """Retrn the default violin plots
    """
    violin_plots = ['chi_eff', 'chi_p', 'mass_ratio', 'luminosity_distance']
    return violin_plots


def preview_agents(previewAgentsArn=None, nextToken=None, maxResults=None):
    """
    Previews the agents installed on the EC2 instances that are part of the specified assessment target.
    See also: AWS API Documentation

    Examples
    Previews the agents installed on the EC2 instances that are part of the specified assessment target.
    Expected Output:

    :example: response = client.preview_agents(
        previewAgentsArn='string',
        nextToken='string',
        maxResults=123
    )

    :type previewAgentsArn: string
    :param previewAgentsArn: [REQUIRED]
            The ARN of the assessment target whose agents you want to preview.

    :type nextToken: string
    :param nextToken: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the PreviewAgents action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.

    :type maxResults: integer
    :param maxResults: You can use this parameter to indicate the maximum number of items you want in the response. The default value is 10. The maximum value is 500.

    :rtype: dict
    :return: {
        'agentPreviews': [
            {
                'agentId': 'string',
                'autoScalingGroup': 'string'
            },
        ],
        'nextToken': 'string'
    }

    """
    pass


def get_P_matrix(bravais_lattice):
    """
    Return a tuple of length 2 with the P matrix and its inverse::

      (P, invP)

    with :math:`invP = P^{-1}`.

    These :math:`P` matrices are obtained from Table 3 of the HPKOT
    paper.

    The P matrix is a :math:`3\\times 3` matrix is the matrix that converts
    the lattice vectors from crystallographic conventional
    :math:`(a,b,c)` to crystallographic primitive :math:`(a_P, b_P, c_P)`
    as follows: :math:`(a_P, b_P, c_P) = (a,b,c) P`

    The change of (real space) coordinate triples follows instead:
    :math:`(x_P, y_P, z_P)^T = (P^{-1}) (x,y,z)^T`

    .. note:: the :math:`invP = P^{-1}` matrix is always integer (with values
        only :math:`-1, 0, 1`) while :math:`P` is rational (non-integer values can be
        :math:`\\pm \\frac 1 2` and :math:`\\pm \\frac 1 3`).
    """
    import numpy as np
    if bravais_lattice in ['cP', 'tP', 'hP', 'oP', 'mP']:
        P = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        invP = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    elif bravais_lattice in ['cF', 'oF']:
        P = 1.0 / 2.0 * np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
        invP = np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
    elif bravais_lattice in ['cI', 'tI', 'oI']:
        P = 1.0 / 2.0 * np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
        invP = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
    elif bravais_lattice == 'hR':
        P = 1.0 / 3.0 * np.array([[2, -1, -1], [1, 1, -2], [1, 1, 1]])
        invP = np.array([[1, 0, 1], [-1, 1, 1], [0, -1, 1]])
    elif bravais_lattice == 'oC':
        P = 1.0 / 2.0 * np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 2]])
        invP = np.array([[1, -1, 0], [1, 1, 0], [0, 0, 1]])
    elif bravais_lattice == 'oA':
        P = 1.0 / 2.0 * np.array([[0, 0, 2], [1, 1, 0], [-1, 1, 0]])
        invP = np.array([[0, 1, -1], [0, 1, 1], [1, 0, 0]])
    elif bravais_lattice == 'mC':
        P = 1.0 / 2.0 * np.array([[1, -1, 0], [1, 1, 0], [0, 0, 2]])
        invP = np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 1]])
    elif bravais_lattice == 'aP':
        P = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        invP = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    else:
        raise ValueError('Invalid bravais_lattice {}'.format(bravais_lattice))
    return P, invP


def _altitude_factor(alt_units_in, alt_units_out):
    """helper method for convert_altitude"""
    factor = 1.0
    if alt_units_in == 'm':
        factor /= 0.3048
    elif alt_units_in == 'ft':
        pass
    elif alt_units_in == 'kft':
        factor *= 1000.0
    else:
        raise RuntimeError('alt_units_in=%r is not valid; use [ft, m, kft]' %
            alt_units_in)
    if alt_units_out == 'm':
        factor *= 0.3048
    elif alt_units_out == 'ft':
        pass
    elif alt_units_out == 'kft':
        factor /= 1000.0
    else:
        raise RuntimeError(
            'alt_units_out=%r is not valid; use [ft, m, kft]' % alt_units_out)
    return factor


def _write_qt_qmake_config(qt_qmake_config, pro):
    """ Write the qmake configuration values to a .pro file. """
    for name in ('QT', 'CONFIG', 'DEFINES', 'INCLUDEPATH', 'LIBS'):
        value = qt_qmake_config.get(name)
        if value:
            pro.write('    %s += %s\n' % (name, value))


def pairwise(iterable):
    """For a list ``s``, return pairs for consecutive entries. For example,
    a list ``s0``, ``s1``, etc. will produce ``(s0,s1), (s1,s2), ...`` and so
    on.

    See: https://docs.python.org/3/library/itertools.html#recipes."""
    import itertools
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)


def find(ellipsname, crstype, strict=False):
    """
    Search for a ellipsoid name located in this module.

    Arguments:

    - **ellipsname**: The ellipsoid name to search for.
    - **crstype**: Which CRS naming convention to search (different
        CRS formats have different names for the same ellipsoid).
    - **strict** (optional): If False, ignores minor name mismatches
        such as underscore or character casing, otherwise must be exact
        match (defaults to False).
    """
    if not strict:
        ellipsname = ellipsname.lower().replace(' ', '_')
    for itemname, item in globals().items():
        if itemname.startswith('_') or itemname == 'Ellipsoid':
            continue
        try:
            if hasattr(item.name, crstype):
                itemname = getattr(item.name, crstype)
                if not strict:
                    itemname = itemname.lower().replace(' ', '_')
                if ellipsname == itemname:
                    return item
        except:
            pass
    else:
        return None


@classmethod
def add(cls, name, provider_cls, *provider_args, **provider_kwargs):
    """Adds provider to the registry."""
    if name in cls._REGISTRY:
        raise ValueError('Attempting to register duplicate provider: %s' % name
            )
    provider = provider_cls(*provider_args, **provider_kwargs)
    if not isinstance(provider, cls._PROVIDER_TYPE):
        raise ValueError(
            'Attempting to register a class not of an invalid type. Expecting instance of %s, got %s'
             % (cls._PROVIDER_TYPE, provider_cls))
    cls._REGISTRY[name] = provider


def sensor_remove(sensor: str='', object: str=''):
    """Remove a sensor from the active object

    :param sensor: Sensor, Name of the sensor to edit
    :type sensor: str
    :param object: Object, Name of the object the sensor belongs to
    :type object: str
    """
    pass


def get_temp(start_to_end: str, end_to_start: str, end_to_end: str) ->(str, str
    ):
    """ Gets a temp values in the computation of the simple automaton regex """
    temp = 'epsilon'
    if (start_to_end != 'epsilon' or end_to_end != 'epsilon' or
        end_to_start != 'epsilon'):
        temp = ''
    if start_to_end != 'epsilon':
        temp = start_to_end
    if end_to_end != 'epsilon':
        if temp:
            temp += '.' + end_to_end + '*'
        else:
            temp = end_to_end + '*'
    part1 = temp
    if not part1:
        part1 = 'epsilon'
    if end_to_start != 'epsilon':
        if temp:
            temp += '.' + end_to_start
        else:
            temp = end_to_start
    if not end_to_start:
        temp = ''
    return temp, part1


@classmethod
def build_close_payload(cls, status, reason=''):
    """Build a close frame."""
    if not isinstance(reason, bytes):
        reason = reason.encode('utf-8', errors='replace')
    if status is None:
        return b''
    payload_bytes = cls._pack_close_code(status) + reason
    return payload_bytes


def load_model(fname):
    """Read model from file. The model must be stored using gzip and pickle

    :param fname: filename
    :type fname: str (path)
    """
    import gzip
    import pickle
    with gzip.open(fname, 'r') as fpt:
        _ = pickle.load(fpt)
    return _


def center_vector(vec, newlen):
    """Returns the center ``newlen`` portion of a vector.

    Adapted from ``scipy.signal.signaltools._centered``:
    github.com/scipy/scipy/blob/v0.18.0/scipy/signal/signaltools.py#L236-L243

    """
    currlen = vec.shape[-1]
    startind = (currlen - newlen) // 2
    endind = startind + newlen
    return vec[startind:endind]


def __init__(A):
    """TransactionIndividualStatusCode - a model defined in Swagger"""
    A.discriminator = None


def time_func(func, *args, **kw):
    """ Run the supplied function and arguments.
      Return a the elapsed time in seconds and the function's own return value.
  """
    from cs.logutils import LogTime
    with LogTime(repr(func)) as L:
        ret = func(*args, **kw)
    return L.elapsed, ret


@staticmethod
def get_opt(opt_name, args):
    """Return option name and value.

        :param opt_name: name of the option, e.g., "username"
        :param args: parsed arguments
        """
    return opt_name, getattr(args, 'os_%s' % opt_name, None)


def get_category(category_name, default=None, sort_key=None):
    """ Get a sequence of dictionaries in the form
        ``[{'introspectable':IIntrospectable, 'related':[sequence of related
        IIntrospectables]}, ...]`` where each introspectable is part of the
        category associated with ``category_name`` .

        If the category named ``category_name`` does not exist in the
        introspector the value passed as ``default`` will be returned.

        If ``sort_key`` is ``None``, the sequence will be returned in the
        order the introspectables were added to the introspector.  Otherwise,
        sort_key should be a function that accepts an IIntrospectable and
        returns a value from it (ala the ``key`` function of Python's
        ``sorted`` callable)."""


def _compute_fans_stacked(shape):
    """Computes the number of input and output units for a weight shape.

    Args:
        shape: Integer shape tuple or TF tensor shape.

    Returns:
        A tuple of scalars (fan_in, fan_out).
    """
    if len(shape) < 1:
        fan_in = fan_out = 1
    elif len(shape) == 1:
        fan_in = fan_out = shape[0]
    elif len(shape) == 2:
        fan_in = shape[1]
        fan_out = 1
    else:
        fan_in = shape[-2]
        fan_out = shape[-1]
    return fan_in, fan_out


@classmethod
def is_available(cls, store):
    """Checks if Stoqlib database is properly installed
        :param store: a store
        """
    if not store.table_exists(u'system_table'):
        return False
    return bool(store.find(cls))


def get_traceback(db, job_id):
    """
    Return the traceback of the given calculation as a list of lines.
    The list is empty if the calculation was successful.

    :param db:
        a :class:`openquake.server.dbapi.Db` instance
    :param job_id:
        a job ID
    """
    log = db("SELECT * FROM log WHERE job_id=?x AND level='CRITICAL'", job_id)
    if not log:
        return []
    response_data = log[-1].message.splitlines()
    return response_data


def splitLongFileName(fn, limit=40):
    """Return fn, split into lines at slash characters."""
    aList = fn.replace('\\', '/').split('/')
    n, result = 0, []
    for i, s in enumerate(aList):
        n += len(s)
        result.append(s)
        if i + 1 < len(aList):
            result.append('/')
            n += 1
        if n > limit:
            result.append('\n')
            n = 0
    return ''.join(result)


@classmethod
def register_impl(cls, name, impl):
    """Register a web service implementation

        :param str name:
            The implementation's name.

        :param impl:
            The implementation.
        :type impl: :class:`WebServiceImpl`

        """
    cls._impls[name] = impl


def _add_to_metadata(metadata, name, value):
    """
    Add the name value pair to the metadata dict

    Args:
        metadata (dict): a dictionary containing the metadata
        name (string): the dictionary key
        value: the value to add

    Returns:
        dict: the new metadata dictionary

    """
    if name not in metadata.keys():
        metadata[name] = value
    else:
        if not isinstance(metadata[name], list):
            metadata[name] = [metadata[name]]
        metadata[name].append(value)
    return metadata


def parse_contact(contact, configparser):
    """
    Parse data from an abook file and return a usable dictionary
    """
    return {'name': configparser[contact].get('name'), 'email': set(
        configparser[contact].get('email').split(',')), 'notes':
        configparser[contact].get('notes'), 'custom1': configparser[contact
        ].get('custom1')}


def CP(df1, df2, price1='Close', price2='Close'):
    """
    Comparative Performance
    Returns: list of floats = jhta.CP(df1, df2, price1='Close', price2='Close')
    Source: https://www.fmlabs.com/reference/default.htm?url=CompPerformance.htm
    """
    cp_list = []
    for i in range(len(df1[price1])):
        cp = 1 + (df1[price1][i] / df2[price2][i] - df1[price1][0] / df2[
            price2][0]) / (df1[price1][0] / df2[price2][0])
        cp_list.append(cp)
    return cp_list


@classmethod
def get(cls, name):
    """Returns provider from the registry."""
    if name not in cls._REGISTRY:
        raise ValueError('Provider name not registered: %s' % name)
    return cls._REGISTRY[name]


@classmethod
def set_session_factory(cls, session_factory):
    """
        Classmethod to set the session factory
        :class:`~sqlalchemy_unchained.SessionManager` should use.

        :param session_factory: The session factory callable.
        """
    cls._session_factory = session_factory


def setlocalepath(dirname):
    """
    Set directory containing message catalogs.

    Message catalogs will be expected at the filename
    dirname/locale/category, where locale is a locale
    name and category is a locale facet such as
    LC_NUMERIC.
    """
    global _locale_path
    _locale_path = dirname


@classmethod
def _create(cls, model_class, *args, **kwargs):
    """Actually create an instance of the model_class.

        Customization point, will be called once the full set of args and kwargs
        has been computed.

        Args:
            model_class (type): the class for which an instance should be
                created
            args (tuple): arguments to use when creating the class
            kwargs (dict): keyword arguments to use when creating the class
        """
    return model_class(*args, **kwargs)


def _coerce_field_name(field_name, field_index):
    """
    Coerce a field_name (which may be a callable) to a string.
    """
    if callable(field_name):
        if field_name.__name__ == '<lambda>':
            return 'lambda' + str(field_index)
        else:
            return field_name.__name__
    return field_name


def bgr_to_rgb(bgr):
    """ Values in ndarrays are stored as BGR. """
    return bgr[2], bgr[1], bgr[0]


@staticmethod
def encode(error_code_protobuf_object, error_code_object: 'ErrorCode') ->None:
    """
        Encode an instance of this class into the protocol buffer object.

        The protocol buffer object in the error_code_protobuf_object argument is matched with the instance of this class in the 'error_code_object' argument.

        :param error_code_protobuf_object: the protocol buffer object whose type corresponds with this class.
        :param error_code_object: an instance of this class to be encoded in the protocol buffer object.
        :return: None
        """
    error_code_protobuf_object.error_code = error_code_object.value


@classmethod
def get_lines(cls):
    """
        Reads all lines from the given glob path
        """
    lines = set()
    for file_name in cls.get_sysfs_files():
        with open(file_name, 'r', encoding='utf-8') as file:
            for line in file:
                line = line.strip()
                if line:
                    lines.add(line)
    return lines


@classmethod
def property_map(cls):
    """Return a mapping of query names and columns."""
    return {'name': 'name', 'description': 'description', 'service':
        'service', 'version': 'version'}


def write_version(name):
    """ Make the default modules version string """
    modules_version = '#%Module1.0\nset ModulesVersion {0}'.format(name)
    return modules_version


def docmd_css(klass, style='default'):
    """
        Prints out CSS for the specified style.
        """
    print(klass.generate_css(style))


def required_validator(ns, value):
    """
    Required value wizard validator. Raises ValueError on validation error.

    :param pypsi.namespace.Namespace ns: active namespace
    :param value: input value
    :returns: validated value
    """
    if value is None:
        raise ValueError('Value is required')
    if not isinstance(value, str):
        return value
    value = value.strip()
    if not value:
        raise ValueError('Value is required')
    return value


def load_numpy_linalg(finder, module):
    """the numpy.linalg module implicitly loads the lapack_lite module; make
       sure this happens"""
    finder.IncludeModule('numpy.linalg.lapack_lite')


def generate_presigned_url(ClientMethod=None, Params=None, ExpiresIn=None,
    HttpMethod=None):
    """
    Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
            ClientMethod.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
            default, the http method is whatever is used in the method's model.

    """
    pass


def bool_to_word(bool_value):
    """
    Converts a boolean to a "Yes" or "No"
    :param bool_value: a boolean
    :return: a string of the word representing the boolean
    """
    if bool_value is True:
        return 'Yes'
    else:
        return 'No'


def get_parent_name_by_child_name_for_tree(tree):
    """
    Return dictionary mapping child node names to parent node names
    """
    parents = {}
    for clade in tree.find_clades(order='level'):
        for child in clade:
            parents[child.name] = clade.name
    return parents


def edges(input_file, thresh=0.1):
    """Extracts the edges around an ultrasound

  Returns the distance in pixels in the form:
  left,right,top,bottom

  Args:
      input_file: Path to input video (must be mp4, mov, or avi)
      thresh (float, optional): Defaults to 0.1
  """
    import numpy as np
    import cv2
    from pathlib import Path
    from sonocrop import vid
    v, fps, f, height, width = vid.loadvideo(input_file)
    u = vid.countUniquePixelsAlongFrames(v)
    u_avg = u / f
    maxW = np.max(u_avg, axis=0)
    left, right = vid.findEdges(maxW, thresh=thresh)
    maxH = np.max(u_avg, axis=1)
    top, bottom = vid.findEdges(maxH, thresh=thresh)
    return f'{left},{right},{top},{bottom}'


def retrieve_properties_ex(vim, prop_coll, spec_set, max_count=500):
    """Retrieve properties.

    Retrieve properties using PropertyCollector.RetrievePropertiesEx
    and PropertyCollector.ContinueRetrievePropertiesEx
    args:
    :param vim: Vim object
    :param prop_coll: PropertyCollector MOR
    :param max_count: Max num of objects returned in a single call.
    """
    objcont = []
    client_factory = vim.client.factory
    opts = client_factory.create('ns0:RetrieveOptions')
    opts.maxObjects = max_count
    res = vim.RetrievePropertiesEx(prop_coll, specSet=spec_set, options=opts)
    while True:
        if res and res.objects:
            objcont.extend(res.objects)
        if hasattr(res, 'token') and res.token:
            res = vim.ContinueRetrievePropertiesEx(prop_coll, token=res.token)
        else:
            break
    return objcont


def mult_recall(el1, el2, cdict, ldict):
    """Computes the multiplicity recall for two elements."""
    return min(len(cdict[el1] & cdict[el2]), len(ldict[el1] & ldict[el2])
        ) / float(len(ldict[el1] & ldict[el2]))


@classmethod
def from_index(cls, index):
    """Return the Enum value at a given index."""
    return cls.ALL[index]


def filter_distorigin(subparticles, subpart, distorigin):
    """return True is particle must be kept"""
    xDim, yDim, _ = subpart.getDim()
    coordinate = subpart.getCoordinate()
    x = coordinate.getX()
    y = coordinate.getY()
    distance_sqr = (x - xDim / 2.0) ** 2 + (y - yDim / 2.0) ** 2
    return distance_sqr > distorigin ** 2


def point_to_tuple(point):
    """
    Convert a QPointF into a (x, y) tuple.
    """
    return point.x(), point.y()


def aggregate_clusters(G):
    """ Takes as input the labeled graph and outputs a dictionary with the keys
    being cluster IDs and the values being sets of cluster elements. """
    clusters = {}
    for node in G:
        label = G.nodes[node]['label']
        if label not in clusters:
            clusters[label] = {node}
        else:
            clusters[label].add(node)
    return clusters


def __le__(ref):
    """KeyReferences must be totally orderable."""


@staticmethod
def get_transaction_fee():
    """
        Returns transaction fee.

        :return: 10
        :rtype: int
        """
    return 10


def guessFont(fname):
    """Given a font name like "Tahoma-BoldOblique", "Bitstream Charter Italic"
    or "Perpetua Bold Italic" guess what it means.

    Returns (family, x) where x is
        0: regular
        1: bold
        2: italic
        3: bolditalic

    """
    italic = 0
    bold = 0
    if '-' not in fname:
        sfx = {'Bold': 1, 'Bold Italic': 3, 'Bold Oblique': 3, 'Italic': 2,
            'Oblique': 2}
        for key in sfx:
            if fname.endswith(' ' + key):
                return fname.rpartition(key)[0], sfx[key]
        return fname, 0
    else:
        family, mod = fname.rsplit('-', 1)
    mod = mod.lower()
    if 'oblique' in mod or 'italic' in mod:
        italic = 1
    if 'bold' in mod:
        bold = 1
    if bold + italic == 0:
        return fname, 0
    return family, bold + 2 * italic


def quote(s):
    """
    Ensure that primary key values do not confuse the admin URLs by escaping
    any '/', '_' and ':' characters. Similar to urllib.quote, except that the
    quoting is slightly different so that it doesn't get automatically
    unquoted by the Web browser.
    """
    if not isinstance(s, str):
        return s
    res = list(s)
    for i in range(len(res)):
        c = res[i]
        if c in ':/_#?;@&=+$,"<>%\\':
            res[i] = '_%02X' % ord(c)
    return ''.join(res)


def check_within_aristotle_notification_permission(recipient):
    """
    The purpose of this function is to check if the 'within aristotle' checkbox
    has been selected in Notification Permissions of the recipient argument.
    :param recipient: User object who we are going to check the notification permission.
    :return: True if the checkbox is selected. NoneType otherwise.
    """
    if recipient.profile.notificationPermissions['notification methods'][
        'within aristotle']:
        return True


def utctimetuple():
    """Return UTC time tuple compatilble with time.gmtimr()."""


def __new__(cls, prefix, seqno):
    """
        Construct a new "unique identifier" instance (a string).
        """
    instance = str.__new__(cls, '%s.%d' % (prefix, seqno))
    instance._seqno = seqno
    instance._prefix = prefix
    return instance


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 __combine(a, b):
    """
    Helper function to combine lists or a list and an object.
    """
    output = []
    if isinstance(a, list) and isinstance(b, list):
        output = a + b
    elif isinstance(a, list):
        output = a
        output.append(b)
    elif isinstance(b, list):
        output = b
        output.append(a)
    return output


def copy_as_script():
    """Copy the console contents for use in a script

    """
    pass


@staticmethod
def contains_wildcard(event):
    """
        Does the event string contain a wildcard.

        :param event: The event string
        :type event: str or unicode
        :return: True if it does, False otherwise
        """
    return event.find('*') != -1 or event.find('#') != -1


@classmethod
def triggers_by_table(cls, triggers):
    """Return dictionary from tables to triggers."""
    d = {}
    for trigger in triggers:
        table = trigger.tablename, trigger.policy, trigger.modal
        if table not in d:
            d[table] = [trigger]
        else:
            d[table].append(trigger)
    return d


@classmethod
def generic_model(cls, site_class, **kwds):
    """Use generic model parameters based on site class.

        Parameters
        ----------
        site_class: str
            Site classification. Possible options are:
             * Geomatrix AB
             * Geomatrix CD
             * USGS AB
             * USGS CD
             * USGS A
             * USGS B
             * USGS C
             * USGS D

            See the report for definitions of the Geomatrix site
            classication. USGS site classification is based on :math:`V_{s30}`:

            =========== =====================
            Site Class  :math:`V_{s30}` (m/s)
            =========== =====================
            A           >750 m/s
            B           360 to 750 m/s
            C           180 to 360 m/s
            D           <180 m/s
            =========== =====================

        Returns
        -------
        ToroVelocityVariation
            Initialized :class:`ToroVelocityVariation` with generic parameters.
        """
    p = dict(cls.PARAMS[site_class])
    p.update(kwds)
    return cls(**p)


def strand_ratio(number1, number2):
    """ Compute ratio between two number. Return result between [0:0.5].
    """
    try:
        division = float(number1) / (number1 + number2)
        if division > 0.5:
            division = 1 - division
    except ZeroDivisionError:
        return 0
    return division


def p_expr_access(p):
    """expr : expr LBRACKET expr RBRACKET"""
    p[0] = 'access', p[1], p[3]


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 set(notifier):
    """Service that are going to use profiler should set callable notifier.

       Callable notifier is instance of callable object, that accept exactly
       one argument "info". "info" - is dictionary of values that contains
       profiling information.
    """
    global __notifier
    __notifier = notifier


@staticmethod
def build_base_doc(**kwargs):
    """Build the API 'create user with base docs' payload from property values."""
    payload = {'email': kwargs.get('email'), 'phone_number': kwargs.get(
        'phone_number'), 'ip': kwargs.get('ip'), 'name': kwargs.get('name'),
        'alias': kwargs.get('alias'), 'entity_type': kwargs.get(
        'entity_type'), 'entity_scope': kwargs.get('entity_scope'),
        'birth_day': kwargs.get('birth_day'), 'birth_month': kwargs.get(
        'birth_month'), 'birth_year': kwargs.get('birth_year'),
        'address_street': kwargs.get('address_street'), 'address_city':
        kwargs.get('address_city'), 'address_subdivision': kwargs.get(
        'address_subdivision'), 'address_postal_code': kwargs.get(
        'address_postal_code'), 'address_country_code': kwargs.get(
        'address_country_code')}
    return payload


def get(isamAppliance, id, check_mode=False, force=False):
    """
    Retrieve a URL Mapping
    """
    return isamAppliance.invoke_get('Retrieve a URL Mapping',
        '/wga/dynurl_config/{0}'.format(id))


@classmethod
def get_type(cls):
    """
        This function is called when the unmounted type (InputObjectType instance)
        is mounted (as a Field, InputField or Argument)
        """
    return cls


def extract_matching_pattern(regex, group_name, unfiltered_list):
    """
        Return the desired group_name from a list of matching patterns

        @param regex : a regular expression with named groups
        @param group_name : the desired matching group name value
        @param unfiltered_list : a list of matches

        @rtype : the string value
    """
    result = ''
    filtered_list = list(filter(regex.search, unfiltered_list))
    if len(filtered_list) == 1:
        filtered_string = ''.join(filtered_list)
        result = regex.search(filtered_string).group(group_name)
    return result


def intersect_line_line(line1_start, line1_end, line2_start, line2_end):
    """
    Find the point where the lines (segments) defined by
    ``(line1_start, line1_end)`` and ``(line2_start, line2_end)``
    intersect.  If no intersection occurs, ``None`` is returned.

    >>> intersect_line_line((3, 0), (8, 10), (0, 0), (10, 10))
    (6, 6)
    >>> intersect_line_line((0, 0), (10, 10), (3, 0), (8, 10))
    (6, 6)
    >>> intersect_line_line((0, 0), (10, 10), (8, 10), (3, 0))
    (6, 6)
    >>> intersect_line_line((8, 10), (3, 0), (0, 0), (10, 10))
    (6, 6)
    >>> intersect_line_line((0, 0), (0, 10), (3, 0), (8, 10))
    >>> intersect_line_line((0, 0), (0, 10), (3, 0), (3, 10))

    Ticket #168:
    >>> intersect_line_line((478.0, 117.0), (478.0, 166.0), (527.5, 141.5), (336.5, 139.5))
    (478.5, 141.48167539267016)
    >>> intersect_line_line((527.5, 141.5), (336.5, 139.5), (478.0, 117.0), (478.0, 166.0))
    (478.5, 141.48167539267016)

    This is a Python translation of the ``lines_intersect``, C Code from
    Graphics Gems II, Academic Press, Inc. The original routine was written
    by Mukesh Prasad.

    EULA: The Graphics Gems code is copyright-protected. In other words, you
    cannot claim the text of the code as your own and resell it. Using the code
    is permitted in any program, product, or library, non-commercial or
    commercial. Giving credit is not required, though is a nice gesture. The
    code comes as-is, and if there are any flaws or problems with any Gems
    code, nobody involved with Gems - authors, editors, publishers, or
    webmasters - are to be held responsible. Basically, don't be a jerk, and
    remember that anything free comes with no guarantee.
    """
    x1, y1 = line1_start
    x2, y2 = line1_end
    x3, y3 = line2_start
    x4, y4 = line2_end
    a1 = y2 - y1
    b1 = x1 - x2
    c1 = x2 * y1 - x1 * y2
    r3 = a1 * x3 + b1 * y3 + c1
    r4 = a1 * x4 + b1 * y4 + c1
    if r3 and r4 and r3 * r4 >= 0:
        return None
    a2 = y4 - y3
    b2 = x3 - x4
    c2 = x4 * y3 - x3 * y4
    r1 = a2 * x1 + b2 * y1 + c2
    r2 = a2 * x2 + b2 * y2 + c2
    if r1 and r2 and r1 * r2 >= 0:
        return None
    denom = a1 * b2 - a2 * b1
    x_num = b1 * c2 - b2 * c1
    y_num = a2 * c1 - a1 * c2
    if not denom:
        return None
    elif isinstance(denom, float):
        offset = abs(denom) / 2
        x = (x_num < 0 and x_num - offset or x_num + offset) / denom
        y = (y_num < 0 and y_num - offset or y_num + offset) / denom
    else:
        offset = abs(denom) // 2
        x = (x_num < 0 and x_num - offset or x_num + offset) // denom
        y = (y_num < 0 and y_num - offset or y_num + offset) // denom
    return x, y


def opt_to_dict(options, chart_id='chart_id'):
    """
    returns dictionary of options for highcharts/highstocks object
    with field chart:renderTo set to arg chart_id
    """
    _options = dict(options)
    _options['chart']['renderTo'] = chart_id
    return _options


def _bold(text):
    """Colorize terminal output to bold."""
    return '\x1b[1m{text}\x1b[0m'.format(text=text)


def filter_builtin_packages(dependencies):
    """Return a list of dependencies with the builtin packages removed"""
    return filter(lambda dep: not dep.is_builtin, dependencies)


def timestring_from_time(time):
    """Converts datetime into a formatted string for .tcx file."""
    return time.strftime('%Y-%m-%dT%H:%M:%S.00-06:00')


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

    """
    pass


def _build_group_assignment_lookup(annos):
    """
    Builds a lookup as a dictionary of groupIds to formId lists
    """
    _assignments = {}
    if annos is not None:
        for anno in annos:
            _form_id = None
            _group_id = None
            kvs = anno.getMapValue()
            for kv in kvs:
                if kv.name == 'formId':
                    _form_id = kv.value
                elif kv.name == 'groupId':
                    _group_id = kv.value
            _assignments.setdefault(int(_group_id), set()).add(_form_id)
    return _assignments


def indentation(logical_line, previous_logical, indent_char, indent_level,
    previous_indent_level):
    """Use 4 spaces per indentation level.

    For really old code that you don't want to mess up, you can continue to
    use 8-space tabs.

    Okay: a = 1
    Okay: if a == 0:\\n    a = 1
    E111:   a = 1
    E114:   # a = 1

    Okay: for item in items:\\n    pass
    E112: for item in items:\\npass
    E115: for item in items:\\n# Hi\\n    pass

    Okay: a = 1\\nb = 2
    E113: a = 1\\n    b = 2
    E116: a = 1\\n    # b = 2
    """
    c = 0 if logical_line else 3
    tmpl = 'E11%d %s' if logical_line else 'E11%d %s (comment)'
    if indent_level % 4:
        yield 0, tmpl % (1 + c, 'indentation is not a multiple of four')
    indent_expect = previous_logical.endswith(':')
    if indent_expect and indent_level <= previous_indent_level:
        yield 0, tmpl % (2 + c, 'expected an indented block')
    elif not indent_expect and indent_level > previous_indent_level:
        yield 0, tmpl % (3 + c, 'unexpected indentation')


def define_orderers(orderer_names, orderer_hosts, domain=None):
    """Define orderers as connection objects.

        Args:
            orderer_names (Iterable): List of orderer names.
            orderer_hosts (Iterable): List of orderer hosts.
            domain (str): Domain used. Defaults to none.

        Returns:
            dict: A dictionary of Orderer Connections
    """
    orderer_connections = {}
    for name, host in zip(orderer_names, orderer_hosts):
        if domain:
            key = f'{name}.{domain}'
        else:
            key = name
        orderer_connections[key] = {'url': 'grpc://' + host + ':7050'}
    return orderer_connections


def __virtual__(hub):
    """
    Don't load on Windows, this is for *nix style platforms
    """
    return True


@classmethod
def parse(cls, reader, block_length):
    """returns this metadata block from a BitstreamReader"""
    return cls(application_id=reader.read_bytes(4), data=reader.read_bytes(
        block_length - 4))


def delete_role(keystone, role):
    """
    Deletes an OpenStack role
    :param keystone: the keystone client
    :param role: the SNAPS-OO Role domain object to delete
    :return:
    """
    keystone.roles.delete(role.id)


def getcapabilities():
    """Make a request to the SOS, returns an XML document wrapped in a
        Python file object."""


def seqs2bool(seqs):
    """
    convert orf and intron information to boolean
    # seqs[id] = [gene, model, [[i-gene_pos, i-model_pos, i-length, iseq, [orfs], [introns]], ...]]
    # seqs[id] = [gene, model, [[i-gene_pos, i-model_pos, i-length, iseq, [orfs], [introns], orfs?, introns?], ...]]
    """
    for seq in seqs:
        for i, ins in enumerate(seqs[seq][2]):
            if len(ins[4]) > 0:
                ins.append(True)
            else:
                ins.append(False)
            if len(ins[5]) > 0:
                ins.append(True)
            else:
                ins.append(False)
            seqs[seq][2][i] = ins
    return seqs


@staticmethod
def construct_condition_name(failure_node, idx):
    """Construct condition name that will be used in case of conditional fallbacks.

        :param failure_node: failure node for which the condition name should be constructed
        :param idx: index of condition that should be printed (could be multiple fallbacks with same source and dst)
        :return: string representation of constructed condition name as stated in the generated python code
        """
    return '_{flow}_{src}_f_{dest}_{idx}'.format(flow=failure_node.flow.
        name, src='_'.join(failure_node.traversed), dest='_'.join(
        failure_node.fallbacks[idx]), idx=idx)


def is_aware(dtime):
    """test if a datetime instance is timezone aware"""
    if dtime.tzinfo is not None and dtime.tzinfo.utcoffset(dtime) is not None:
        return True
    else:
        return False


def _onPutEvent(args, **kwds):
    """Put completion notification - run specified callback"""
    fcn = args.usr
    if callable(fcn):
        fcn()


def update_headers(response, headers):
    """
    Helper function to update headers in the response.

    :param response: swob.Response object
    :param headers: dictionary headers
    """
    if hasattr(headers, 'items'):
        headers = headers.items()
    for name, value in headers:
        if name.lower() == 'etag':
            response.headers[name] = value.replace('"', '')
        elif name.lower() not in ('date', 'content-length', 'content-type',
            'connection', 'x-put-timestamp', 'x-delete-after'):
            response.headers[name] = value


def timedelta_as_seconds(td):
    """
    Returns the value of the entire timedelta as
    integer seconds, rounded down

    """
    return td.days * 86400 + td.seconds


def _add_args(compiler, arg_list, arg_cat, arg_type, args_names):
    """Updates arguments list with API specific arguments

    Parameters
    ----------
    arg_list : list of str
        List of arguments to update.
    arg_cat : {'api', 'option'}
        Category of argument.
    arg_type : {'link', 'compile'}
        Type of argument.
    args_names : list of str
        Arguments names to use."""
    if args_names:
        for name in args_names:
            try:
                arg_list.append(compiler[arg_cat][name][arg_type])
            except KeyError:
                continue


def _check_comp(comp):
    """Check that conversion to named matrices is possible."""
    ref_sens = None
    kind = -1
    for k, c_k in enumerate(comp):
        if c_k['coeff_type'] != kind:
            c_ref = c_k
            ref_sens = c_ref['sensors']
            kind = c_k['coeff_type']
        elif not c_k['sensors'] == ref_sens:
            raise RuntimeError('Cannot use an uneven compensation matrix')


def lerp(a, b, x):
    """linear interpolation"""
    return a + x * (b - a)


def describe_lags(lagId=None):
    """
    Describes the link aggregation groups (LAGs) in your account.
    If a LAG ID is provided, only information about the specified LAG is returned.
    See also: AWS API Documentation

    :example: response = client.describe_lags(
        lagId='string'
    )

    :type lagId: string
    :param lagId: The ID of the LAG.
            Example: dxlag-abc123
            Default: None

    :rtype: dict
    :return: {
        'lags': [
            {
                'connectionsBandwidth': 'string',
                'numberOfConnections': 123,
                'lagId': 'string',
                'ownerAccount': 'string',
                'lagName': 'string',
                'lagState': 'requested'|'pending'|'available'|'down'|'deleting'|'deleted',
                'location': 'string',
                'region': 'string',
                'minimumLinks': 123,
                'awsDevice': 'string',
                'connections': [
                    {
                        'ownerAccount': 'string',
                        'connectionId': 'string',
                        'connectionName': 'string',
                        'connectionState': 'ordering'|'requested'|'pending'|'available'|'down'|'deleting'|'deleted'|'rejected',
                        'region': 'string',
                        'location': 'string',
                        'bandwidth': 'string',
                        'vlan': 123,
                        'partnerName': 'string',
                        'loaIssueTime': datetime(2015, 1, 1),
                        'lagId': 'string',
                        'awsDevice': 'string'
                    },
                ],
                'allowsHostedConnections': True|False
            },
        ]
    }

    :returns:
    Ordering : The initial state of a hosted connection provisioned on an interconnect. The connection stays in the ordering state until the owner of the hosted connection confirms or declines the connection order.
    Requested : The initial state of a standard connection. The connection stays in the requested state until the Letter of Authorization (LOA) is sent to the customer.
    Pending : The connection has been approved, and is being initialized.
    Available : The network link is up, and the connection is ready for use.
    Down : The network link is down.
    Deleting : The connection is in the process of being deleted.
    Deleted : The connection has been deleted.
    Rejected : A hosted connection in the 'Ordering' state will enter the 'Rejected' state if it is deleted by the end customer.

    """
    pass


def get_nested_dict_key(nested_dict):
    """Get all keys of nested dict

    Arguments
    ----------
    nested_dict : dict
        Nested dictionary

    Return
    ------
    all_nested_keys : list
        Key of nested dict
    """
    all_nested_keys = []
    for values in nested_dict.values():
        all_nested_keys += values.keys()
    return all_nested_keys


def target_move_up():
    """Move particle target up in the list

    """
    pass


def import_module(conf):
    """
    Imports the configuration as a module.

    :param conf: The string to the configuration.
    Automatically strips off ".py" file extensions.
    """
    if '.' in conf:
        parts = conf.split('.')
        name = '.'.join(parts[:-1])
        fromlist = parts[-1:]
        try:
            module = __import__(name, fromlist=fromlist)
            conf_mod = getattr(module, parts[-1])
        except AttributeError:
            raise ImportError('No module named %s' % conf)
    else:
        conf_mod = __import__(conf)
    return conf_mod


@staticmethod
def mul_inv(a, b):
    """
        Modular inversion a mod b
        :param a:
        :param b:
        :return:
        """
    b0 = b
    x0, x1 = 0, 1
    if b == 1:
        return 1
    while a > 1:
        q = a // b
        a, b = b, a % b
        x0, x1 = x1 - q * x0, x0
    if x1 < 0:
        x1 += b0
    return x1


def subscribe_to_dataset(IdentityPoolId=None, IdentityId=None, DatasetName=
    None, DeviceId=None):
    """
    Subscribes to receive notifications when a dataset is modified by another device.
    This API can only be called with temporary credentials provided by Cognito Identity. You cannot call this API with developer credentials.
    See also: AWS API Documentation

    :example: response = client.subscribe_to_dataset(
        IdentityPoolId='string',
        IdentityId='string',
        DatasetName='string',
        DeviceId='string'
    )

    :type IdentityPoolId: string
    :param IdentityPoolId: [REQUIRED]
            A name-spaced GUID (for example, us-east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon Cognito. The ID of the pool to which the identity belongs.

    :type IdentityId: string
    :param IdentityId: [REQUIRED]
            Unique ID for this identity.

    :type DatasetName: string
    :param DatasetName: [REQUIRED]
            The name of the dataset to subcribe to.

    :type DeviceId: string
    :param DeviceId: [REQUIRED]
            The unique ID generated for this device by Cognito.

    :rtype: dict
    :return: {}

    """
    pass


def read_stdout(proc, lines):
    """ Reads all remaining stdout """
    if proc and proc.stdout:
        while True:
            line = proc.stdout.readline()
            if not line and proc.poll() is not None:
                return
            lines.append(line)
    return None


def parse_header(line):
    """
    Parse the header into a name-value.
    """
    parts = line.split(b':', 1)
    if len(parts) == 2:
        return parts[0].lower().strip().decode('ascii'), parts[1].strip()
    else:
        raise ValueError('Invalid header: %r' % line)


def tmpFile(afileName):
    """
    True if the file is fileInfo.db
    """
    tak = afileName.split('/')[1]
    if afileName in ['tmp']:
        return True
    return False


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

        :param FileRenameType val:
        :rtype: EventType
        """
    return cls('file_rename', val)


def _pil_image_to_bytes(p_img):
    """
    Get the component bytes from the given PIL Image.
    In recent version of PIL, the tobytes function is the correct thing to
    call, but some older versions of PIL do not have this function.
    :param p_img: PIL Image to get the bytes from.
    :type p_img: PIL.Image.Image
    :returns: Byte string.
    :rtype: bytes
    """
    if hasattr(p_img, 'tobytes'):
        return p_img.tobytes()
    else:
        return p_img.tostring()


@staticmethod
def _identity(obj):
    """Return the given object.

        Args:
            obj: An object.

        Returns:
            The given object.
        """
    return obj


@staticmethod
def get_geom_str(osgeo_geom, str_type='wkt'):
    """
        Method to return a geometry string from an osgeo geometry object
        :param osgeo_geom: OSGEO geometry object
        :param str_type: 'wkt', 'json', or 'wkb
        :return: wkt, json or wkb
        """
    if str_type == 'wkt':
        try:
            return osgeo_geom.ExportToWkt()
        except:
            return
    elif str_type == 'json':
        try:
            return osgeo_geom.ExportToJson()
        except:
            return
    elif str_type == 'wkb':
        try:
            return osgeo_geom.ExportToWkb()
        except:
            return
    else:
        raise ValueError('Unsupported geometry type')


def substitute(line, charges, current_residuum):
    """
	Look up the charge for an atom, and write into a string.

	Args:
	line: String containing an atom name, residuum name, and original charge.
	charges: DataFrame containing atom name, residuum names, new charges.

	Returns:
	line: the original line, with the charge updated from the `charges` table.
	"""
    current_atom = line[0:7].strip()
    mask = (charges.atom == current_atom) & (charges.residue ==
        current_residuum)
    new_charge = charges[mask].q.values[0]
    charge_string = '{: 1.6f}'.format(new_charge) + '  '
    modified_line = line[:24] + charge_string + line[34:]
    return modified_line


def elapsed(seconds, short=True):
    """ return a string showing the elapsed days, hours, minutes, seconds. """
    txt = ''
    sub = str(seconds).split('.')[-1]
    nsec = float(seconds)
    year = 365 * 24 * 60 * 60
    week = 7 * 24 * 60 * 60
    day = 24 * 60 * 60
    hour = 60 * 60
    minute = 60
    years = int(nsec / year)
    nsec -= years * year
    weeks = int(nsec / week)
    nsec -= weeks * week
    days = int(nsec / day)
    nsec -= days * day
    hours = int(nsec / hour)
    nsec -= hours * hour
    minutes = int(nsec / minute)
    sec = nsec - minutes * minute
    if years:
        txt += '%sy' % years
    if weeks:
        days += weeks * 7
    if days:
        txt += '%sd' % days
    if years and short and txt:
        return txt
    if hours:
        txt += '%sh' % hours
    if days and short and txt:
        return txt
    if minutes:
        txt += '%sm' % minutes
    if hours and short and txt:
        return txt
    if sec == 0:
        txt += '0s'
    elif sec < 1 or not short:
        txt += '%.3fs' % sec
    else:
        txt += '%ss' % int(sec)
    txt = txt.strip()
    return txt


def questionnaire(args):
    """
    Clear up missing arguments.

    :param args: Arguments.
    :type args: argparse.Namespace
    """
    if args.curef is None:
        args.curef = input('CUREF: ')
    if args.fvver is None:
        args.fvver = input('STARTING OS: ')
    return args


def shift_index_column(panda_dataframe, columns_to_index):
    """Shift the index column of a pandas DataFrame

    Parameters
    ----------
    panda_dataframe: pandas.DataFrame
        A pandas dataframe.
    columns_to_index: list
        Column label or list of column labels / arrays

    Returns
    -------
    output: pandas.DataFrame
        A new pandas DataFrame with the shifted columns as index.
    """
    new_data = panda_dataframe.set_index(columns_to_index)
    return new_data


def longest_str(textes):
    """Returns longest text in a list"""
    if not textes:
        return -1
    else:
        maxlen = -1
        for text in textes:
            l = len(text)
            if l > maxlen:
                maxlen = l
                toReturn = text
        return toReturn


def element(point, p, q, n):
    """Test, whether the given point is on the curve (p, q, n)"""
    if point:
        x, y = point
        return (x * x * x - p * x - q) % n == y * y % n
    else:
        return True


def menu_clean(menu_config):
    """
    Make sure that only the menu item with the largest weight is active.
    If a child of a menu item is active, the parent should be active too.
    :param menu:
    :return:
    """
    max_weight = -1
    for _, value in list(menu_config.items()):
        if value['submenu']:
            for _, v in list(value['submenu'].items()):
                if v['active']:
                    value['active'] = True
                    value['active_weight'] = v['active_weight']
        if value['active']:
            max_weight = max(value['active_weight'], max_weight)
    if max_weight > 0:
        for _, value in list(menu_config.items()):
            if value['active'] and value['active_weight'] < max_weight:
                value['active'] = False
    return menu_config


def polygonReverse(polygon):
    """Reverses the vertices in the polygon.

    Keyword arguments:
    polygon -- The polygon

    """
    polygon.reverse()


@classmethod
def get_social_auth(cls, provider, uid):
    """Return UserSocialAuth for given provider and uid"""
    raise NotImplementedError('Implement in subclass')


def class_name(obj):
    """
    Get the name of an object, including the module name if available.
    """
    name = obj.__name__
    module = getattr(obj, '__module__')
    if module:
        name = f'{module}.{name}'
    return name