@classmethod
def get_namespace(cls):
    """
        Return the pkg-resources entry point namespace name from which
        sub-commands will be loaded.
        """
    return cls.namespace


def _should_allow_unhandled(class_reference, key_name):
    """Check if a property is allowed to be unhandled."""
    if not hasattr(class_reference, '__deserialize_allow_unhandled_map__'):
        return False
    return class_reference.__deserialize_allow_unhandled_map__.get(key_name,
        False)


def get_request_query_params(request):
    """
    `request.QUERY_PARAMS` has been deprecated in favor of `request.query_params`
    since version 3.0, and has been fully removed as of version 3.2.
    """
    try:
        return request.QUERY_PARAMS
    except NotImplementedError:
        return request.query_params


def eratosthenes(firstCandidate=2):
    """
    Yields the sequence of prime numbers via the Sieve of Eratosthenes.
    rather than creating a fixed list of a range (z) and crossing out
    multiples of sequential candidates, this algorithm stores primes under
    their next possible candidate, thus allowing the generation of primes
    in sequence without storing a complete range (z).

    create a dictionary. each entry in the dictionary is a key:item pair of
    the largest (key) largest multiple of this prime so far found : (item)
    the prime. the dictionary only has as many entries as found primes.

    if a candidate is not a key in the dictionary, it is not a multiple of
    any already-found prime; it is thus a prime. a new entry is added to the
    dictionary, with the square of the prime as the key. the square of the prime
    is the next possible multiple to be found.

    to use this generator, create an instance and then call the .next() method
    on the instance

    >>> a = sieve.eratosthenes()
    >>> next(a)
    2
    >>> next(a)
    3

    We can also specify a starting value for the sequence, skipping over
    initial primes smaller than this number:

    >>> a = sieve.eratosthenes(95)
    >>> next(a)
    97
    >>> next(a)
    101
    """
    D = {}
    q = 2
    while True:
        p = D.pop(q, None)
        if p is not None:
            nextMult = p + q
            while nextMult in D:
                nextMult = nextMult + p
            D[nextMult] = p
        else:
            nextMult = q * q
            D[nextMult] = q
            if q >= firstCandidate:
                yield q
        q = q + 1


def not_empty(value):
    """Check that the string is not all blanks"""
    if value is None or value.strip() == '':
        raise ValueError('Got an empty string')
    return value


def previewrange_set(xmin: int=0, xmax: int=0, ymin: int=0, ymax: int=0,
    wait_for_input: bool=True):
    """Interactively define frame range used for playback

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


def is_callable(objdoc):
    """
    Returns true if the object is callable or wraps a callable.
    """
    return objdoc.get('callable') or objdoc.get('func', {}).get('callable')


def select_more():
    """Select vertex directly linked to already selected ones

    """
    pass


def select_all_toggle(invert: bool=False):
    """Toggle selection of all keyframes

    :param invert: Invert
    :type invert: bool
    """
    pass


def job_arguments_parser(arguments):
    """Parse Jobs argument into a dict like"""
    job_args = {}
    for arg in arguments:
        try:
            key, value = tuple(arg.split('='))
            job_args[key] = value
        except ValueError:
            print('Unknown argument. Should be argument_name=value arg2=value')
            return None
    return job_args


def int2bin(i, length=8):
    """Returns the bit representation of the given integer with a minimum
    length of ``length``. E.g. ``int2bin(109, 7) == '1101101'`` and
    ``int2bin(109, 8) == '01101101'``.

    :param int i: The integer to format
    :param int length: The minimum length of the output string. The string is
        zero-padded on the left.
    :return: The bit representation of the given int
    :rtype: string

    """
    if not isinstance(length, int):
        raise ValueError('expected int for length')
    return ('{:0>' + str(length) + 'b}').format(i)


def compile_wrfnnrp_bc_Salathe2014_locations(maptable):
    """
    Compile a list of file URLs for the Salathe et al., 2014 bias corrected WRF NNRP data

    maptable: (dataframe) a dataframe that contains the FID, LAT, LONG_, and ELEV for each interpolated data file
    """
    locations = []
    for ind, row in maptable.iterrows():
        basename = '_'.join(['data', str(row['LAT']), str(row['LONG_'])])
        url = [
            'http://cses.washington.edu/rocinante/WRF/NNRP/vic_16d/WWA_1950_2010/bc/forcings_ascii/'
            , basename]
        locations.append(''.join(url))
    return locations


def show_template():
    """Prints a template for `show`. See :func:`show <henchman.plotting.show>` for details.

    Example:
        >>> import henchman.plotting as hplot
        >>> hplot.show_template()
    """
    print(
        """show(plot,
     static=False,
     png=False,
     hover=False,
     colors=None,
     width=None,
     height=None,
     title='Temporary title',
     x_axis='my xaxis name',
     y_axis='my yaxis name',
     x_range=(0, 10) or None,
     y_range=(0, 10) or None)
"""
        )
    return None


def handle_message(sender, message):
    """
    Handles message events from the AlarmDecoder.
    """
    print(sender, message.raw)


@classmethod
def format_last_name(cls, last_name, locale):
    """
        Format the last name according to the locale.

        French, English, and Vietnamese personal names are converted to upper
        case.  However, Korean personal names are not upper cased.

        :param last_name: Surname (also known as *family name*) of the person.
            The last name can be used to alphabetically sort a list of users.

        :param locale: An object `Locale` that supposedly refers to the name
            of this person.

        :return: The formatted last name of the person.
        """
    last_name_ = cls.normalize_name(last_name)
    return last_name_.upper()


@staticmethod
def insert_column_into_data_for_csv(data_for_csv, columns_dict_value, index):
    """
        Insert a column of data into the data returned from data_for_csv
        :param data_for_csv: rows of csv data
        :type data_for_csv: list
        :param columns_dict_value: title and data information. see extra_column_information in get_csv
        :type columns_dict_value: dict
        :param index: index of column to be inserted
        :type index: int
        """
    columns_dict_value['data'].insert(0, columns_dict_value['title'])
    for i, row in enumerate(data_for_csv):
        row.insert(index, str(columns_dict_value['data'][i]).replace(',', ';'))


def get_payment_id_from_tx_extra_nonce(extra_nonce):
    """
    Extracts encrypted payment id from extra
    :param extra_nonce:
    :return:
    """
    if 33 != len(extra_nonce):
        raise ValueError('Nonce size mismatch')
    if 0 != extra_nonce[0]:
        raise ValueError('Nonce payment type invalid')
    return extra_nonce[1:]


def _get_k8s_model_attribute(model_type, field_name):
    """
    Takes a model type and a Kubernetes API resource field name (such as
    "serviceAccount") and returns a related attribute name (such as
    "service_account") to be used with  kubernetes.client.models objects. It is
    impossible to prove a negative but it seems like it is always a question of
    making camelCase to snake_case but by using the provided 'attribute_map' we
    also ensure that the fields actually exist.

    Example of V1PodSpec's attribute_map:
    {
        'active_deadline_seconds': 'activeDeadlineSeconds',
        'affinity': 'affinity',
        'automount_service_account_token': 'automountServiceAccountToken',
        'containers': 'containers',
        'dns_policy': 'dnsPolicy',
        'host_aliases': 'hostAliases',
        'host_ipc': 'hostIPC',
        'host_network': 'hostNetwork',
        'host_pid': 'hostPID',
        'hostname': 'hostname',
        'image_pull_secrets': 'imagePullSecrets',
        'init_containers': 'initContainers',
        'node_name': 'nodeName',
        'node_selector': 'nodeSelector',
        'priority': 'priority',
        'priority_class_name': 'priorityClassName',
        'restart_policy': 'restartPolicy',
        'scheduler_name': 'schedulerName',
        'security_context': 'securityContext',
        'service_account': 'serviceAccount',
        'service_account_name': 'serviceAccountName',
        'subdomain': 'subdomain',
        'termination_grace_period_seconds': 'terminationGracePeriodSeconds',
        'tolerations': 'tolerations',
        'volumes': 'volumes'
    }
    """
    if field_name in model_type.attribute_map:
        return field_name
    for key, value in model_type.attribute_map.items():
        if value == field_name:
            return key
    else:
        raise ValueError("'{}' did not have an attribute matching '{}'".
            format(model_type.__name__, field_name))


def _random_sequences(precursor, start=None, end=None):
    """
    randomly get sequences around some nucleotides.
    It could be enriched in some positions
    """
    return 0


def boolean(input):
    """Convert the given input to a boolean value.

    Intelligently handles boolean and non-string values, returning
    as-is and passing to the bool builtin respectively.

    This process is case-insensitive.

    Acceptable values:

    True
        * yes
        * y
        * on
        * true
        * t
        * 1

    False
        * no
        * n
        * off
        * false
        * f
        * 0

    :param input: the value to convert to a boolean
    :type input: any

    :returns: converted boolean value
    :rtype: bool
    """
    try:
        input = input.strip().lower()
    except AttributeError:
        return bool(input)
    if input in ('yes', 'y', 'on', 'true', 't', '1'):
        return True
    if input in ('no', 'n', 'off', 'false', 'f', '0'):
        return False
    raise ValueError('Unable to convert {0!r} to a boolean value.'.format(
        input))


@classmethod
def hosts(cls, parsed_args):
    """ Returns a list of hosts to connect to.

        Can return a host as '
' to force tmux to make a new window.
        """
    raise NotImplementedError()


def get_image(tag):
    """ Finds a specific image in ECR. """
    raise NotImplementedError


def create_html_template(ext_name, path_destination):
    """
    Create the display.template file
    :param ext_name: string
    :param path_destination: string
    :return: void
    """
    with open(path_destination + '/widget/' + ext_name + '/templates/' +
        'display.template', 'w') as outfile:
        outfile.write('<!-- Your HTML code -->')


def _ipv6_host(host):
    """
    Process IPv6 address literals
    """
    if host.startswith('[') and host.endswith(']'):
        host = host.replace('%25', '%').strip('[]')
    return host


def yearInfo2yearDay(yearInfo):
    """calculate the days in a lunar year from the lunar year's info

    >>> yearInfo2yearDay(0) # no leap month, and every month has 29 days.
    348
    >>> yearInfo2yearDay(1) # 1 leap month, and every month has 29 days.
    377
    >>> yearInfo2yearDay((2**12-1)*16) # no leap month, and every month has 30 days.
    360
    >>> yearInfo2yearDay((2**13-1)*16+1) # 1 leap month, and every month has 30 days.
    390
    >>> # 1 leap month, and every normal month has 30 days, and leap month has 29 days.
    >>> yearInfo2yearDay((2**12-1)*16+1)
    389
    """
    yearInfo = int(yearInfo)
    res = 29 * 12
    leap = False
    if yearInfo % 16 != 0:
        leap = True
        res += 29
    yearInfo //= 16
    for i in range(12 + leap):
        if yearInfo % 2 == 1:
            res += 1
        yearInfo //= 2
    return res


def turbulent_Dittus_Boelter(Re, Pr, heating=True, revised=True):
    """Calculates internal convection Nusselt number for turbulent flows
    in pipe according to [1]_, and [2]_, a reprint of [3]_.

    .. math::
        Nu = m*Re_D^{4/5}Pr^n

    Parameters
    ----------
    Re : float
        Reynolds number, [-]
    Pr : float
        Prandtl number, [-]
    heating : bool
        Indicates if the process is heating or cooling, optional
    revised : bool
        Indicates if revised coefficients should be used or not

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

    Notes
    -----
    The revised coefficient is m = 0.023.
    The original form of Dittus-Boelter has a linear coefficient of 0.0243
    for heating and 0.0265 for cooling. These are sometimes rounded to 0.024
    and 0.026 respectively.
    The default, heating, provides n = 0.4. Cooling makes n 0.3.

    0.6 ≤ Pr ≤  160
    Re_{D} ≥ 10000
    L/D ≥ 10

    Examples
    --------
    >>> turbulent_Dittus_Boelter(Re=1E5, Pr=1.2)
    247.40036409449127
    >>> turbulent_Dittus_Boelter(Re=1E5, Pr=1.2, heating=False)
    242.9305927410295

    References
    ----------
    .. [1] Rohsenow, Warren and James Hartnett and Young Cho. Handbook of Heat
       Transfer, 3E. New York: McGraw-Hill, 1998.
    .. [2] Dittus, F. W., and L. M. K. Boelter. "Heat Transfer in Automobile
       Radiators of the Tubular Type." International Communications in Heat
       and Mass Transfer 12, no. 1 (January 1985): 3-22.
       doi:10.1016/0735-1933(85)90003-X
    .. [3] Dittus, F. W., and L. M. K. Boelter, University of California
       Publications in Engineering, Vol. 2, No. 13, pp. 443-461, October 17,
       1930.
    """
    m = 0.023
    if heating:
        power = 0.4
    else:
        power = 0.3
    if heating and not revised:
        m = 0.0243
    elif not heating and not revised:
        m = 0.0265
    else:
        m = 0.023
    return m * Re ** 0.8 * Pr ** power


def filter_string(s, where):
    """Returns a string."""
    return u''.join(filter(where, s))


def twos_comp(val, bits):
    """
    Compute the 2's complement of int value val.

    :param val: Bytes to complement
    :param bits:
    :return: 2's complement of int value val
    """
    if val & 1 << bits - 1 != 0:
        val = val - (1 << bits)
    return val


def assign_tf_variable(variable, value):
    """Assign value to a TF variable"""
    variable.assign(value)


def isIterable(object):
    """
    Check whether an object is iterable or not.
    """
    try:
        iter(object)
        return True
    except TypeError:
        return False


def upper(f):
    """Return the input projection of an FST"""
    res = f.copy()
    res.input_project()
    res.minimize()
    return res


def limit(vmin, vmax, npeaks):
    """
    Fixed limits, vmin to vmax for all peaks.
    """
    return [(vmin, vmax)] * npeaks


def listChainOverrides():
    """ List portal type specific chain overrides.

        o Permission:  Private (Python only)
        """


@classmethod
def filter_stream_header(cls, s):
    """Remove bogus stream headers from socket output"""
    new_string, repl_count = cls.StreamTypeHeader.subn(b'', s)
    return new_string, repl_count


def copy(a):
    """
    Return a copy of the input tensor.
    """
    return a.copy()


def flip(array):
    """
    Reverses direction of array
    """
    return array[::-1]


def lorentzian(x, sigma, amp=1, x0=0, const=0):
    """Lorentzian distribution.
    x = independent variable
    sigma = width parameter
    x0 = centre position
    amp = amplitude
    const = y-offset
    """
    return amp * (sigma ** 2 / ((x - x0) ** 2 + sigma ** 2)) + const


@classmethod
def add_common_opts(cls, parser):
    """Add options that are common for several plugins.
        """
    for opt in cls.common_opt_names:
        cls._parser_add_opt(parser, opt)


def get_empty_notebook():
    """Default notbook with the minimum metadata."""
    return {'metadata': {'kernelspec': {'display_name': 'Python 3',
        'language': 'python', 'name': 'python3'}, 'language_info': {
        'codemirror_mode': {'name': 'ipython', 'version': 3},
        'file_extension': '.py', 'mimetype': 'text/x-python', 'name':
        'python', 'nbconvert_exporter': 'python', 'pygments_lexer':
        'ipython3', 'version': '3.6.6'}}, 'nbformat': 4, 'nbformat_minor': 2}


def _convert2int(value, map, low, high, name, cmd):
    """private converter tries map(value) low<=int(value)<=high or finally an error"""
    try:
        return map[value]
    except KeyError:
        try:
            ivalue = int(value)
            if low <= ivalue <= high:
                return ivalue
        except:
            pass
    raise ValueError('Bad %s value %s in %s' % (name, value, ascii(cmd)))


def check_type(*args) ->None:
    """Check type of arguments

    :param args: tuple list of argument/type
    :return:

    :Example:
        >>> check_type(args[0], str, args[2], float)

        * May use tuple for checking against a list of valid types
        >>> check_type(args[0], (str, float, int))
    """
    if len(args) % 2 == 0:
        for item in range(0, len(args), 2):
            if not isinstance(args[item], args[item + 1]):
                raise TypeError("Type of argument {} is '{}' but must be '{}'"
                    .format(item // 2 + 1, type(args[item]).__name__, args[
                    item + 1].__name__))


@staticmethod
def _readMeta(fd):
    """Read meta array from the top of a file. Read lines until a blank line is reached.
        This function should ideally work for ALL versions of MetaArray.
        """
    meta = ''
    while True:
        line = fd.readline().strip()
        if line == '':
            break
        meta += line
    ret = eval(meta)
    return ret


@classmethod
def _allowed_kwargs(cls):
    """ Define kwargs which are allowed in the constructor."""
    return (cls.MP_PRIORITY, cls.MP_HIERARCHY, cls.MP_DEFINITION_ORDER, cls
        .MP_DOC, cls.MP_VIEW)


def identity(x):
    """Temporarily copied from htools.

    Returns the input argument. Sometimes it is convenient to have this if
    we sometimes apply a function to an item: rather than defining a None
    variable, sometimes setting it to a function, then checking if it's None
    every time we're about to call it, we can set the default as identity and
    safely call it without checking.
    Parameters
    ----------
    x: any
    Returns
    -------
    x: Unchanged input.
    """
    return x


def makename(package, module):
    """Join package and module with a dot."""
    if package:
        name = package
        if module:
            name += '.' + module
    else:
        name = module
    return name


def display_bloch_sphere(**kwargs):
    """
    Prints an error message.
    """
    print('display_bloch_sphere not available on this version.')


@classmethod
def get_text_size(cls, text):
    """
            calculates the height and width of the input text string.

            return: (width, height)

        :param text: str - input text
        """
    return cls.font_metrics.width(text), cls.font_metrics.height()


@classmethod
def GetFormattedSuffixFormat(cls):
    """
        Returns the formatted suffix for the unit.

        :rtype: str
        :returns:
            The formatted suffix
        """
    return cls.FORMATTED_SUFFIX_FORMAT


def check_picard_for_errors(picard_stderr):
    """
        Checks the picard stderr for errors

        Parameters
        ----------
        picard_stderr : str
            picard stderr

        Raises
        ------
        IOError
            If picard stderr returns an error
    """
    if 'Elapsed time:' in picard_stderr:
        pass
    elif 'Exception' in picard_stderr:
        for picard_stderr_line in picard_stderr.splitlines():
            if 'Exception' in picard_stderr_line:
                raise Exception(picard_stderr_line)
    elif picard_stderr:
        raise Exception(picard_stderr)


def position(fontid: int, x: float, y: float, z: float):
    """Set the position for drawing text.

    :param fontid: The id of the typeface as returned by blf.load(), for default font use 0.
    :type fontid: int
    :param x: X axis position to draw the text.
    :type x: float
    :param y: Y axis position to draw the text.
    :type y: float
    :param z: Z axis position to draw the text.
    :type z: float
    """
    pass


def calculate_response_time_percentile(response_times, num_requests, percent):
    """
    Get the response time that a certain number of percent of the requests
    finished within. Arguments:

    response_times: A StatsEntry.response_times dict
    num_requests: Number of request made (could be derived from response_times,
                  but we save some CPU cycles by using the value which we already store)
    percent: The percentile we want to calculate. Specified in range: 0.0 - 1.0
    """
    num_of_request = int(num_requests * percent)
    processed_count = 0
    for response_time in sorted(response_times.keys(), reverse=True):
        processed_count += response_times[response_time]
        if num_requests - processed_count <= num_of_request:
            return response_time
    return 0


def name_to_agent_class(name):
    """Convert agent name to class.

    This adds "Agent" to the end of the name and uppercases the first letter
    and the first letter appearing after each underscore (underscores are
    removed).

    :param name: name of agent, e.g. local_human

    Returns class of agent, e.g. LocalHumanAgent.
    """
    words = name.split('_')
    class_name = ''
    for w in words:
        class_name += w[0].upper() + w[1:]
    class_name += 'Agent'
    return class_name


def _is_section_key(key):
    """Is a Config key a section name (does it start with a capital)?"""
    if key and key[0].upper() == key[0] and not key.startswith('_'):
        return True
    else:
        return False


def manage_permission(permission_to_manage, roles=[], acquire=0):
    """Change the settings for the given permission.

        If optional arg acquire is true, then the roles for the permission
        are acquired, in addition to the ones specified, otherwise the
        permissions are restricted to only the designated roles.
        """


def get_typestrings(struct):
    """
    Return the valid schema types as a set.
    """
    type_strings = struct.get('type', [])
    if isinstance(type_strings, str):
        type_strings = {type_strings}
    else:
        type_strings = set(type_strings)
    if not type_strings:
        type_strings = {'null', 'boolean', 'object', 'array', 'number',
            'string'}
    if 'integer' in type_strings and 'number' in type_strings:
        type_strings.remove('integer')
    return type_strings


def _get_percent(text):
    """If text is formatted like '33.2%', remove the percent and convert
    to a float.  Otherwise, just convert to a float.

    """
    if not text:
        return None
    if text.endswith('%'):
        text = text[:-1]
    return float(text.strip())


def manual_setup(conf: dict):
    """
    If configuration is meant to happen from scripts &c
    conf is supposed to be dictionary to override defaults
    """
    from django.conf import settings
    if conf.get('ROOT_URLCONF') and not isinstance(conf.get('ROOT_URLCONF'),
        tuple):
        conf['ROOT_URLCONF'] = tuple(conf.get('ROOT_URLCONF'))
    settings.configure(**conf)
    import django
    django.setup()


def group_pairs(phenotype_pairs):
    """group unique keys and combine their values"""
    unique_pairs = {}
    for k1, k2, value in phenotype_pairs:
        sorted_pair = tuple(sorted([k1, k2]))
        if sorted_pair not in unique_pairs:
            unique_pairs[sorted_pair] = [value]
        elif value not in unique_pairs[sorted_pair]:
            unique_pairs[sorted_pair].append(value)
    return unique_pairs


@classmethod
def process(inferred, results):
    """Process results and return a loaded instance.

        :param object inferred: Instance of the class itself
        :param dict record: Record to use for loading
        :return: Instance of the loaded class
        """
    return inferred(results)


def set(isamAppliance, client_id, options, endpoints, discovery_mechanisms,
    check_mode=False, force=False):
    """
    Set MMFA endpoint configuration
    """
    json_data = {'client_id': client_id, 'options': options, 'endpoints':
        endpoints, 'discovery_mechanisms': discovery_mechanisms}
    if check_mode is True:
        return isamAppliance.create_return_object(changed=True)
    else:
        return isamAppliance.invoke_post('Set MMFA endpoint configuration',
            '/iam/access/v8/mmfa-config/', json_data)


@classmethod
def get_HDX_code_from_location(cls, location, locations=None, configuration
    =None):
    """Get HDX code for location

        Args:
            location (str): Location for which to get HDX code
            locations (Optional[List[Dict]]): Valid locations list. Defaults to list downloaded from HDX.
            configuration (Optional[Configuration]): HDX configuration. Defaults to global configuration.

        Returns:
            Optional[str]: HDX code or None
        """
    if locations is None:
        locations = cls.validlocations(configuration)
    locationupper = location.upper()
    for locdict in locations:
        locationcode = locdict['name'].upper()
        if locationupper == locationcode:
            return locationcode
    for locdict in locations:
        if locationupper == locdict['title'].upper():
            return locdict['name'].upper()
    return None


def _mark_selected(path, byurl):
    """process the tree (flattened and sorted by url) to mark the entries
    selected which appear on the path, as well as their parent entries.
    """
    clear = []
    check = path.startswith
    for url, val in byurl:
        pt = val['path_type']
        if pt == 'N':
            continue
        elif pt != 'A' and path != url:
            continue
        elif check(url):
            while val:
                if val['selected']:
                    break
                if val['path_type'] == 'N' or val['path_type'
                    ] == 'E' and path != val['url']:
                    clear.append(val)
                val['selected'] = True
                val = val['parent']
    for ent in clear:
        ent['selected'] = False


def is_rds_db_snapshot_encrypted(rds_db_snapshot):
    """
    Checks the RDS snapshot 'Encrypted' value.

    >>> is_rds_db_snapshot_encrypted({'Encrypted': True})
    True
    >>> is_rds_db_snapshot_encrypted({'Encrypted': False})
    False
    >>> is_rds_db_snapshot_encrypted({})
    Traceback (most recent call last):
    ...
    KeyError: 'Encrypted'
    >>> is_rds_db_snapshot_encrypted(0)
    Traceback (most recent call last):
    ...
    TypeError: 'int' object is not subscriptable
    >>> is_rds_db_snapshot_encrypted(None)
    Traceback (most recent call last):
    ...
    TypeError: 'NoneType' object is not subscriptable
    """
    return bool(rds_db_snapshot['Encrypted'])


def two_pass_covariance(data1, data2):
    """Two pass algorithm computes the sample means
    and then the covariance"""
    n = len(data1)
    mean1 = sum(data1) / n
    mean2 = sum(data2) / n
    covariance = 0
    for i1, i2 in zip(data1, data2):
        a = i1 - mean1
        b = i2 - mean2
        covariance += a * b / n
    return covariance


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


def detect_outlier(magnitude, outlier_threshold):
    """
    Convenience function to check if any of the magnitudes surpass the
    threshold to mark this date as being an outlier

    This is used to mask out values from current or future processing

    Args:
        magnitude: float, magnitude of change at a given moment in time
        outlier_threshold: threshold value

    Returns:
        bool: True if these spectral values should be omitted
    """
    return magnitude > outlier_threshold


def line_peeker(file) ->str:
    """
    Creates a generator that reads lines from the file,
    but leaves the read position at the beginning of the
    last line read.

    :param file:    The file to read from.
    :return:        The line generator.
    """
    while True:
        pre = file.tell()
        line = file.readline()[:-1]
        post = file.tell()
        file.seek(pre)
        yield line
        file.seek(post)


def glPolygonOffset(factor: float, units: float):
    """Set the scale and units used to calculate depth values

    :param factor: Specifies a scale factor that is used to create a variable depth offset for each polygon. The initial value is 0.
    :type factor: float
    :param units: Is multiplied by an implementation-specific value to create a constant depth offset. The initial value is 0.
    :type units: float
    """
    pass


def _is_attribute(attr):
    """Return True if attr is an attribute."""
    return True


def p_Definitions(p):
    """Definitions : Definitions ExtendedAttributeList Definition"""
    p[3].extended_attributes = p[2]
    p[0] = p[1] + [p[3]]


@staticmethod
def robocopy_args(src, dest, delete=False, exclude_files=None, exclude_dirs
    =None, dry_run=False):
    """Robocopy for sheldon

        Args:
          dest: path to local tdir
          src: path to remote (raid) tdir

        Returns:
          subprocess return code from robocopy

          Robocopy return codes:

          0. No files were copied. No failure was encountered. No files were
          mismatched. The files already exist in the destination directory;
          therefore, the copy operation was skipped.
          1. All files were copied successfully.
          2. There are some additional files in the destination directory that are not
          present in the source directory. No files were copied.
          3. Some files were copied. Additional files were present. No failure
          was encountered.
          5. Some files were copied. Some files were mismatched. No failure was
          encountered.
          6. Additional files and mismatched files exist. No files were copied
          and no failures were encountered. This means that the files already
          exist in the destination directory.
          7. Files were copied, a file mismatch was present, and additional files
          were present.
          8. Several files did not copy.
          :param src:
          :param dest:
          :param delete:
          :param exclude_files:
          :param exclude_dirs:
          :param dry_run:

        """
    if exclude_files is None:
        exclude_files = []
    if exclude_dirs is None:
        exclude_dirs = []
    _args = ['robocopy', src, dest, '/MIR' if delete else '/E', '/mt',
        '/W:1', '/R:1']
    if exclude_dirs:
        _args.extend(['/XD', *exclude_dirs])
    if exclude_files:
        _args.extend(['/XF', *exclude_files])
    if dry_run:
        _args.append('/L')
    return list(filter(None, _args))


def lighter(image1, image2):
    """
    Compares the two images, pixel by pixel, and returns a new image containing
    the lighter values. At least one of the images must have mode "1".

    .. code-block:: python

        out = max(image1, image2)

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


def unproxy(obj):
    """Return the Python interface from a proxy object"""
    if hasattr(obj, '__moyapy__'):
        return obj.__moyapy__()
    return obj


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


def __im_after_update__(clone):
    """Hook called at the end of `__im_update__()`.

        This method is called while exiting the context manager but before
        finalizing the clone.
        Thus, the clone object is still in transient state.
        """


@classmethod
def validate(cls, value):
    """Validate that the specified value is a valid enum.

        This method will raise a ValueError if the value is
        not a valid enum.

        :param value: the string value to verify
        """
    if value not in cls.VALUES:
        raise ValueError(
            "Invalid ParameterSource value: '{}'. Valid values are: {}".
            format(value, ','.join(cls.VALUES)))


def get_unique_repository():
    """ Retrieve all the repository names from the index. """
    query_unique_repository = """
    {
        "size": 0,
        "aggs": {
            "unique_repos": {
                "terms": {
                    "field": "origin",
                    "size": 5000
                }
            }
        }
    }
    """
    return query_unique_repository


def unfold_values(values):
    """Unfolds list of observation-frequency mappings.

    Args:
        values (tuple[number, int]): Observation-frequency mapping.

    Returns:
        List of values.

    Example:
        >>> from effectus.helpers import unfold_values
        >>> unfold_values([(1, 3), (2, 1), (3, 1)])
        [1, 1, 1, 2, 3]
    """
    result = []
    for observation, frequency in values:
        result += [observation] * frequency
    return result


def is_cjk_punctuation(char):
    """Returns true if char is a punctuation mark in a CJK language."""
    if len(char) != 1:
        return False
    lower = int('0x3000', 16)
    higher = int('0x300F', 16)
    return ord(char) >= lower and ord(char) <= higher


def _get_exon_cds(exon_cdna_seq, cdna_coding_start, cdna_coding_end,
    first_exon, last_exon):
    """
    Return the CDS of the exon.

    This function takes the cDNA sequence of the exon and the
    coding start and end coordinates to cut the sequence and
    return the coding sequence (CDS) of the exon.
    """
    cdna_len = len(exon_cdna_seq)
    cds_len = cdna_coding_end - cdna_coding_start + 1
    if cds_len == cdna_len:
        return exon_cdna_seq
    if first_exon:
        return exon_cdna_seq[-cds_len:]
    if last_exon:
        return exon_cdna_seq[:cds_len]
    raise ValueError('exon has {} bases instead of {}'.format(cdna_len,
        cds_len))


@staticmethod
def resort_couplings(J, sortIx):
    """Reorder given couplings into a desired order.

        Params:
        -------
        J (ndarray)
            vector of length n*(n-1)/2
        sortIx (ndarray)
        """
    return


def get_ports(host):
    """
    This function generates a list of open ports. Each entry is a tuple which contains the port, protocol, servicename,
    state and a banner string.

    :param host: The NmapHost object
    :type host libnmap.objects.host.NmapHost

    :return: list of tuples
    """
    ports = []
    for port, proto in host.get_ports():
        if host.get_service(port, proto) is not None:
            service = host.get_service(port, proto)
            servicename = service.service
            state = service.state
            banner = service.banner
            ports.append((port, proto, servicename, state, banner))
    return ports


def add_feather_vertex_slide(MASK_OT_add_feather_vertex=None,
    MASK_OT_slide_point=None):
    """Add new vertex to feather and slide it

    :param MASK_OT_add_feather_vertex: Add Feather Vertex, Add vertex to feather
    :param MASK_OT_slide_point: Slide Point, Slide control points
    """
    pass


@classmethod
def reset_next_id(cls):
    """
		If the current value of the next_id class attribute is not
		None then set it to 0, otherwise it is left unmodified.

		Example:

		>>> from ligo.lw import lsctables
		>>> for cls in lsctables.TableByName.values(): cls.reset_next_id()
		"""
    if cls.next_id is not None:
        cls.set_next_id(0)


def decompose_to_twos_and_threes(n):
    """
    Split an integer into a list of 2's and possible one 3 that add up to it

    :param n: the int
    :return: a list of 2's and possible one three
    """
    if not isinstance(n, int) and n >= 2:
        raise ValueError('n must be an integer greater than or equal to 2.')
    out = []
    if n % 2 == 1:
        n -= 3
        out.append(3)
    while n > 0:
        n -= 2
        out.append(2)
    out.reverse()
    return out


def delete_project(name=None):
    """
    Deletes a build project.
    See also: AWS API Documentation

    :example: response = client.delete_project(
        name='string'
    )

    :type name: string
    :param name: [REQUIRED]
            The name of the build project.

    :rtype: dict
    :return: {}

    """
    pass


def calc_csr(sigma_veff, sigma_v, pga, rd, gwl, depth):
    """
    Cyclic stress ratio from CPT, Eq 2.2,
    """
    return 0.65 * (sigma_v / sigma_veff) * rd * pga


def distance_to_buffer(distance):
    """
    Convert great circle distance (in small range < 1000km) to
    Euclidean form of point buffer used by shapely.
    :param distance: great circle distance in kilometers
    :return: point shift in Euclidean coordinates.
    """
    magic_num = 1078.599717114
    return distance / magic_num


def _columns_from_frevent(frevent):
    """Get list of column names from frevent
    """
    params = dict(frevent.GetParam())
    return ['time', 'amplitude', 'probability', 'timeBefore', 'timeAfter',
        'comment'] + list(params.keys())


def tidy_progress_range(apps, schema_editor):
    """
    Tidies progress ranges because a bug had caused them to go out of range
    """
    ContentSessionLog = apps.get_model('logger', 'ContentSessionLog')
    ContentSummaryLog = apps.get_model('logger', 'ContentSummaryLog')
    ContentSessionLog.objects.filter(progress__lt=0).update(progress=0.0)
    ContentSummaryLog.objects.filter(progress__lt=0).update(progress=0.0)
    ContentSummaryLog.objects.filter(progress__gt=1).update(progress=1.0)


@staticmethod
def _idgen_samples(source_name, cell_name, sample_number, sample_type):
    """
        Identifiers generator
        :param source_name: subject ID
        :param sample_number: sample Number
        :param sample_type: sample Term
        :return:
        """
    idarr = []
    if source_name != '':
        idarr.append('{}'.format(source_name))
    if cell_name != '':
        idarr.append('CEL-{}'.format(cell_name))
    idarr.append('SMP-')
    if sample_type != '':
        idarr.append(sample_type)
    if sample_number != '':
        idarr.append('{}'.format(sample_number))
    return '.'.join(idarr).replace(' ', '_')


def colored_info(outLn: str, lnType: str='e', debug: bool=False) ->None:
    """Output a color line based on the type of information."""
    if debug:
        print('colored_info :: START')
        print('Input string:\t{:s}'.format(outLn))
        print('String type:\t{:s}'.format(lnType.strip().lower()[0]))
    lnType = lnType.strip().lower()[0]
    validTypes = ['s', 'e', 'w', 'i']
    if not lnType in validTypes:
        print(
            '\x1b[5;30;41mError:\x1b[0m {:s} is not a valid type of output line.'
            .format(lnType))
        print('Please use one of the following:\n{:s}'.format(str(validTypes)))
    if lnType == 's':
        print('\x1b[5;30;42mSuccess:\x1b[0m {:s}'.format(outLn))
    elif lnType == 'e':
        print('\x1b[5;30;41mError:\x1b[0m {:s}'.format(outLn))
    elif lnType == 'w':
        print('\x1b[5;30;43mWarning:\x1b[0m {:s}'.format(outLn))
    elif lnType == 'i':
        print('\x1b[5;30;44mInfo:\x1b[0m {:s}'.format(outLn))


def format_attributes(callable, *args):
    """
    Format the results of *callable* in the format expected
    by Graphviz.
    """
    value = callable(*args)
    if not value:
        return ''
    else:
        parts = []
        for k in sorted(value):
            parts.append(f'{k}={value[k]}')
        return f" [{', '.join(parts)}]"


@classmethod
def has_resuming(cls):
    """Returns whether it supports to resume the fetch process.

        :returns: this backend does not support items resuming
        """
    return False


def _pointsFromList(L):
    """
    given a list of coordinates [x0, y0, x1, y1....]
    produce a list of points [(x0,y0), (y1,y0),....]
    """
    P = []
    for i in range(0, len(L), 2):
        P.append((L[i], L[i + 1]))
    return P


def is_ascii(s):
    u"""
    >>> is_ascii(u'The quick brown fox jumps over the lazy dog.')
    True
    >>> is_ascii(u'Liberté, égalité, fraternité!')
    False
    """
    try:
        s.encode('ascii')
        return True
    except UnicodeError:
        return False


@classmethod
def pixmap(cls, *args, **kwargs):
    """
        Returns QPixmap for the given resource name
        :param name: str, name of the pixmap
        :param category: str, category of the pixmap
        :param extension: str, extension of the pixmap
        :param color: QColor, color of the pixmap
        :return: QPixmap
        """
    if 'dirname' in kwargs:
        return cls(kwargs.pop('dirname'))._pixmap(*args, **kwargs)
    else:
        return cls()._pixmap(*args, **kwargs)


def tell():
    """Return the current position of this file"""


@classmethod
def topic(cls, **kwargs) ->str:
    """Get MQTT topic for this message type."""
    site_id = kwargs.get('site_id', '+')
    session_id = kwargs.get('site_id', '+')
    return f'rhasspy/asr/{site_id}/{session_id}/audioCaptured'


def __modularity(status):
    """
    Fast compute the modularity of the partition of the graph using
    status precomputed
    """
    links = float(status.total_weight)
    result = 0.0
    for community in set(status.node2com.values()):
        in_degree = status.internals.get(community, 0.0)
        degree = status.degrees.get(community, 0.0)
        if links > 0:
            result += in_degree / links - (degree / (2.0 * links)) ** 2
    return result


def open(transaction_manager=None, serial=''):
    """Return an IConnection object for use by application code.

        transaction_manager: transaction manager to use.  None means
            use the default transaction manager.
        serial: the serial (transaction id) of the database to open.
            An empty string (the default) means to open it to the newest
            serial. Specifying a serial results in a read-only historical
            connection.

        Note that the connection pool is managed as a stack, to
        increase the likelihood that the connection's stack will
        include useful objects.
        """


def rand_shuffle(arr):
    """Random shuffle the data in the first dimension of the array.

    The shuffled data is stored in a new array.

    Parameters
    ----------
    arr : Tensor
        The data tensor

    Returns
    -------
    Tensor
        The result tensor
    """
    pass


def grace(data, xlab='', ylab='', title=''):
    """
	Input data is of the form, [ [x1,y1], [x2,y2],....] where x and y are vectors
	"""
    try:
        import pygrace
        pg = pygrace.grace()
        for xy in data:
            pg.plot(xy[0], xy[1])
            pg.hold(1)
        pg.xlabel(xlab)
        pg.ylabel(ylab)
        pg.title(title)
        return True
    except:
        return False


def get_bytes(s):
    """Returns the byte representation of a hex- or byte-string."""
    if isinstance(s, bytes):
        b = s
    elif isinstance(s, str):
        b = bytes.fromhex(s)
    else:
        raise TypeError("s must be either 'bytes' or 'str'!")
    return b


def on_disconnect():
    """ Called when the client connection lost."""
    print('connect lost')


@classmethod
def new(cls, *args, **kwargs):
    """
        Should override in subclass
        :param args:
        :param kwargs:
        :return:
        """
    return super().new(*args, **kwargs)


@classmethod
def get_graph(cls, response):
    """ Given a Flask response, find the rdflib Graph """
    if cls.is_graph(response):
        return response
    if hasattr(response, '__getitem__'):
        if len(response) > 0 and cls.is_graph(response[0]):
            return response[0]


def makeopendir(fs, directory):
    """ Creates and opens the given directory in the given PyFilesystem. """
    if not fs.isdir(directory):
        fs.makedir(directory)
    return fs.opendir(directory)


def psi_Cs_Li_Cl_PK74(T, P):
    """c-c'-a: caesium lithium chloride [PK74]."""
    psi = -0.0094
    valid = T == 298.15
    return psi, valid


def _hex2dec(s):
    """
    returns the int represented by hex string s

    :param s: string
    :return: int
    """
    if not len(s) == 2:
        raise ValueError('s(' + str(s) + ') did not fit for _hex2dec')
    else:
        return int(s, base=16)


def ruby_strip(chars):
    """Strip whitespace and any quotes."""
    return chars.strip(' "\'')


def set_scale(distance: float=0.0):
    """Set scale of scene by scaling camera (or its parent if present)

    :param distance: Distance, Distance between selected tracks
    :type distance: float
    """
    pass


def zset_example():
    """ Example sorted set pagination.
    """
    from uuid import uuid4
    from redis import StrictRedis
    from zato.redis_paginator import ZSetPaginator
    conn = StrictRedis()
    key = 'paginator:{}'.format(uuid4().hex)
    for x in range(1, 18):
        conn.zadd(key, x, chr(96 + x))
    p = ZSetPaginator(conn, key, 6)
    print(p.count)
    print(p.num_pages)
    print(p.page_range)
    page = p.page(3)
    print(page)
    print(page.object_list)
    conn.delete(key)


def multiply(data, params=None):
    """
    Multiply function aggregation.

    Example config:

    .. code-block:: python

        config = {
            ...
            'fields': ['timestamp', 'x'],
            'aggregations': [
                {
                    'func': 'multiply',
                    'field': 'x',
                    'params': {
                        'by': 10
                    }
                }
            ],
            ...
        }
    """
    kwargs = params or {}
    factor = kwargs.get('by', 1.0)
    return data * factor


def validate_placeholder_uid(layout, placeholder_uid):
    """Validate the placeholder.

    :param string layout:
    :param string placeholder_uid:
    :return bool:
    """
    return placeholder_uid in layout.placeholder_uids


def previous():
    """Move to previous folder

    """
    pass


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

    The ".dev0" means dirty.

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


def iter_except(func, exception, first=None):
    """
    Call a function repeatedly until an exception is raised.

    Converts a call-until-exception interface to an iterator interface.
    Like builtins.iter(func, sentinel) but uses an exception instead
    of a sentinel to end the loop.

    Examples:
        iter_except(functools.partial(heappop, h), IndexError)   # priority queue iterator
        iter_except(d.popitem, KeyError)                         # non-blocking dict iterator
        iter_except(d.popleft, IndexError)                       # non-blocking deque iterator
        iter_except(q.get_nowait, Queue.Empty)                   # loop over a producer Queue
        iter_except(s.pop, KeyError)                             # non-blocking set iterator

    """
    try:
        if first is not None:
            yield first()
        while 1:
            yield func()
    except exception:
        pass


def getCurrentStep():
    """Return a dictionary object representing the currently
        active step."""


def net(f, c='close', o=1):
    """Calculate the net change of a given column.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe containing the column ``c``.
    c : str
        Name of the column in the dataframe ``f``.
    o : int, optional
        Offset value for shifting the series.

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

    References
    ----------
    *Net change is the difference between the closing price of a security
    on the day's trading and the previous day's closing price. Net change
    can be positive or negative and is quoted in terms of dollars* [IP_NET]_.

    .. [IP_NET] http://www.investopedia.com/terms/n/netchange.asp

    """
    new_column = f[c] - f[c].shift(o)
    return new_column


@classmethod
def render(cls, context, request):
    """Render the sitemap.

        TODO: I don't like that Sitemap.render is little bit different from this one.

        :return: dict of information for the templates {urlset: SitemapItem iterator}
        """
    reflective_builder = cls(request)
    reflective_builder.build()
    map = reflective_builder.get_sitemap()
    return map.render(context, request)


def qry_helper(flag_id, qry_string, param_str, flag_filt=False, filt_st=''):
    """Dynamically add syntaxtical elements to query.

    This functions adds syntactical elements to the query string, and
    report title, based on the types and number of items added thus far.

    Args:
        flag_filt (bool): at least one filter item specified.
        qry_string (str): portion of the query constructed thus far.
        param_str (str): the title to display before the list.
        flag_id (bool): optional - instance-id was specified.
        filt_st (str): optional - syntax to add on end if filter specified.
    Returns:
        qry_string (str): the portion of the query that was passed in with
                          the appropriate syntactical elements added.
        param_str (str): the title to display before the list.

    """
    if flag_id or flag_filt:
        qry_string += ', '
        param_str += ', '
    if not flag_filt:
        qry_string += filt_st
    return qry_string, param_str


def convert_to_inches(s):
    """
    Convert an SVG unit string like '42.5mm' or '12in' to inches as a float. If
    the unit string does not include physical units, return None.
    """
    assert s
    s = s.strip()
    for unit in ('in', 'mm', 'cm', 'px', 'pt'):
        if s[-2:] == unit:
            v = s[:-2]
            break
    else:
        return None
    v = float(v)
    if unit == 'in':
        return v
    elif unit == 'mm':
        return v / 25.4
    elif unit == 'cm':
        return v / 2.54
    elif unit == 'px':
        return v / 96.0
    elif unit == 'pt':
        return v / 72.0


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


def checking_new_account_name_action_d(user):
    """Destroy the new account because the user asked to disconnect."""
    return user.account.destroy()


def type_object_attrgetter(obj, attr, *defargs):
    """
    This implements an improved attrgetter for type objects (i.e. classes)
    that can handle class attributes that are implemented as properties on
    a metaclass.

    Normally `getattr` on a class with a `property` (say, "foo"), would return
    the `property` object itself.  However, if the class has a metaclass which
    *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find
    the "foo" property on the metaclass and resolve it.  For the purposes of
    autodoc we just want to document the "foo" property defined on the class,
    not on the metaclass.

    For example::

        >>> class Meta(type):
        ...     @property
        ...     def foo(cls):
        ...         return 'foo'
        ...
        >>> class MyClass(metaclass=Meta):
        ...     @property
        ...     def foo(self):
        ...         ""\"Docstring for MyClass.foo property.""\"
        ...         return 'myfoo'
        ...
        >>> getattr(MyClass, 'foo')
        'foo'
        >>> type_object_attrgetter(MyClass, 'foo')
        <property at 0x...>
        >>> type_object_attrgetter(MyClass, 'foo').__doc__
        'Docstring for MyClass.foo property.'

    The last line of the example shows the desired behavior for the purposes
    of autodoc.
    """
    for base in obj.__mro__:
        if attr in base.__dict__:
            if isinstance(base.__dict__[attr], property):
                return base.__dict__[attr]
            break
    return getattr(obj, attr, *defargs)


def decode_signed_varint(i):
    """Zig-zag decodes an integer value.
    """
    if not i & 1:
        return i >> 1
    return i >> 1 ^ ~0


def parse_bdist_wininst(name):
    """Return (base,pyversion) or (None,None) for possible .exe name"""
    lower = name.lower()
    base, py_ver, plat = None, None, None
    if lower.endswith('.exe'):
        if lower.endswith('.win32.exe'):
            base = name[:-10]
            plat = 'win32'
        elif lower.startswith('.win32-py', -16):
            py_ver = name[-7:-4]
            base = name[:-16]
            plat = 'win32'
        elif lower.endswith('.win-amd64.exe'):
            base = name[:-14]
            plat = 'win-amd64'
        elif lower.startswith('.win-amd64-py', -20):
            py_ver = name[-7:-4]
            base = name[:-20]
            plat = 'win-amd64'
    return base, py_ver, plat


def is_timezone_aware(value):
    """Check if a datetime is time zone aware.

    `is_timezone_aware()` is the inverse of `is_timezone_naive()`.

    :param value: A valid datetime object.
    :type value: datetime.datetime, datetime.time
    :returns: bool -- if the object is time zone aware.

    .. versionadded:: 0.3.0
    """
    assert hasattr(value, 'tzinfo')
    return value.tzinfo is not None and value.tzinfo.utcoffset(value
        ) is not None


def normalize_tuple(value, n, name):
    """Transforms a single int or iterable of ints into an int tuple.

    # Arguments
        value: The value to validate and convert. Could be an int, or any iterable
          of ints.
        n: The size of the tuple to be returned.
        name: The name of the argument being validated, e.g. `strides` or
          `kernel_size`. This is only used to format error messages.

    # Returns
        A tuple of n integers.

    # Raises
        ValueError: If something else than an int/long or iterable thereof was
        passed.
    """
    if isinstance(value, int):
        return (value,) * n
    else:
        try:
            value_tuple = tuple(value)
        except TypeError:
            raise ValueError('The `' + name +
                '` argument must be a tuple of ' + str(n) +
                ' integers. Received: ' + str(value))
        if len(value_tuple) != n:
            raise ValueError('The `' + name +
                '` argument must be a tuple of ' + str(n) +
                ' integers. Received: ' + str(value))
        for single_value in value_tuple:
            try:
                int(single_value)
            except ValueError:
                raise ValueError('The `' + name +
                    '` argument must be a tuple of ' + str(n) +
                    ' integers. Received: ' + str(value) +
                    ' including element ' + str(single_value) + ' of type ' +
                    str(type(single_value)))
    return value_tuple


def cmp(x, y):
    """
    Replacement for built-in function cmp that was removed in Python 3

    Compare the two objects x and y and return an integer according to
    the outcome. The return value is negative if x < y, zero if x == y
    and strictly positive if x > y.
    """
    return (x > y) - (x < y)


def get_return_data_type(func_name):
    """Return a somewhat-helpful data type given a function name"""
    if func_name.startswith('get_'):
        if func_name.endswith('_list'):
            return 'List'
        elif func_name.endswith('_count'):
            return 'Integer'
    return ''


def add_marker_at_click():
    """Place new marker at the desired (clicked) position

    """
    pass


def connection_refused_handler(spawn):
    """ handles connection refused scenarios
    """
    raise Exception('Connection refused to device %s' % (str(spawn),))


def _axes_all_finite_sized(fig):
    """Return whether all axes in the figure have a finite width and height."""
    for ax in fig.axes:
        if ax._layoutbox is not None:
            newpos = ax._poslayoutbox.get_rect()
            if newpos[2] <= 0 or newpos[3] <= 0:
                return False
    return True


@classmethod
def select(cls, selector, _candidate_generator=None, limit=None):
    """Perform a CSS selection operation on the current element."""
    cls.__soup()
    return cls.__params['soup'].select(selector, _candidate_generator, limit)


@staticmethod
def supportedViews():
    """Overrides :meth:`.ControlMixin.supportedViews`. The
        ``HistogramToolBar`` is only intended to be added to
        :class:`.HistogramPanel` views.
        """
    from fsleyes.views.histogrampanel import HistogramPanel
    return [HistogramPanel]


def _remove_intercept_patsy(terms):
    """
    Remove intercept from Patsy terms.
    """
    from patsy.desc import INTERCEPT
    if INTERCEPT in terms:
        terms.remove(INTERCEPT)
    return terms


def calculate_G2(neighborsymbols, neighborpositions, center_symbol, eta,
    cutoff, cutofffxn, Ri, normalized=True, backend=None):
    """Calculate G2 symmetry function.

    Parameters
    ----------
    neighborsymbols : list of str
        List of symbols of all neighbor atoms.
    neighborpositions : list of list of floats
        List of Cartesian atomic positions.
    center_symbol : str
        Chemical symbol of the center atom.
    eta : float
        Parameter of Gaussian symmetry functions.
    cutoff : float
        Cutoff radius.
    cutofffxn : object
        Cutoff function.
    Ri : list
        Position of the center atom. Should be fed as a list of three floats.
    normalized : bool
        Whether or not the symmetry function is normalized.
    backed : object
        A backend.

    Returns
    -------
    feature : float
        Radial feature.
    """
    feature = 0.0
    num_neighbors = len(neighborpositions)
    Rc = cutoff
    feature = 0.0
    num_neighbors = len(neighborpositions)
    if normalized:
        Rc = cutoff
    else:
        Rc = 1.0
    for count in range(num_neighbors):
        symbol = neighborsymbols[count]
        Rj = neighborpositions[count]
        if backend.name == 'torch':
            Ri = backend.from_numpy(Ri)
            Rc = backend.from_numpy(Rc)
        if symbol == center_symbol:
            Rij = backend.norm(Rj - Ri)
            feature += backend.exp(-eta * Rij ** 2.0 / Rc ** 2.0) * cutofffxn(
                Rij)
    return feature


def dict_from_file(filename, key_type=str):
    """Load a text file and parse the content as a dict.

    Each line of the text file will be two or more columns splited by
    whitespaces or tabs. The first column will be parsed as dict keys, and
    the following columns will be parsed as dict values.

    Args:
        filename(str): Filename.
        key_type(type): Type of the dict's keys. str is user by default and
            type conversion will be performed if specified.

    Returns:
        dict: The parsed contents.
    """
    mapping = {}
    with open(filename, 'r') as f:
        for line in f:
            items = line.rstrip('\n').split()
            assert len(items) >= 2
            key = key_type(items[0])
            val = items[1:] if len(items) > 2 else items[1]
            mapping[key] = val
    return mapping


def wtime_to_minutes(time_string):
    """ wtime_to_minutes

    Convert standard wallclock time string to minutes.

    Args:
        - Time_string in HH:MM:SS format

    Returns:
        (int) minutes

    """
    hours, mins, seconds = time_string.split(':')
    return int(hours) * 60 + int(mins) + 1


@staticmethod
def all(log):
    """Keep every token in the log."""
    return log


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

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

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


def add_file(mod_file, rev, files):
    """Add the modified file to the list"""
    if mod_file in files:
        files[mod_file].append(rev)
    else:
        files[mod_file] = [rev]


@classmethod
def _convert_to_number_format(cls, number_format_dict):
    """
        Convert ``number_format_dict`` to an openpyxl v2.1.0 number format
        initializer.
        Parameters
        ----------
        number_format_dict : dict
            A dict with zero or more of the following keys.
                'format_code' : str
        Returns
        -------
        number_format : str
        """
    return number_format_dict['format_code']


def switch_direction():
    """Change the direction that a chain of bones points in (head <-> tail swap)

    """
    pass


@staticmethod
def is_collapsed(node):
    """A "collapsed" paragraph is one which has no text, immediately
        starting a subparagraph. For example:
        (a)(1) Some text    <- (a) is collapsed
        (a) Some text - (1) Other text   <- (a) is not collapsed
        """
    marker = '({})'.format(node['label'][-1])
    text_without_marker = node['text'].replace(marker, '')
    return node['text'].strip() and not text_without_marker.strip()


def face_split_edgenet(face: 'bmesh.types.BMFace', edgenet:
    'bmesh.types.BMEdge') ->'bmesh.types.BMFace':
    """Splits a face into any number of regions defined by an edgenet.

    :param face: The face to split.
    :type face: 'bmesh.types.BMFace'
    :param face: The face to split.
    :param edgenet: Sequence of edges.
    :type edgenet: 'bmesh.types.BMEdge'
    :return:  The newly created faces.
    """
    pass


def runge_kutta_ode_solver(ode, time_step, y, params):
    """4th order Runge-Kutta ODE solver.

    Carnahan, B., Luther, H. A., and Wilkes, J. O. (1969).
    Applied Numerical Methods. Wiley, New York.

    Parameters
    ----------
    ode : function
        Ordinary differential equation function. In the Lorenz model it is SDE.
    time_step : float
    y : np.ndarray of dimension (batch_size, n_obs)
        Current state of the time-series.
    params : list of parameters
        The parameters needed to evaluate the ode. In this case it is
        list of four elements - eta, theta1, theta2 and f.

    Returns
    -------
    np.ndarray
        Resulting state initiated at y and satisfying ode solved by this solver.

    """
    k1 = time_step * ode(y, params)
    k2 = time_step * ode(y + k1 / 2, params)
    k3 = time_step * ode(y + k2 / 2, params)
    k4 = time_step * ode(y + k3, params)
    y = y + (k1 + 2 * k2 + 2 * k3 + k4) / 6
    return y


def make_directory_entry(d):
    """
    Create a directory entry that conforms to the format of the Desktop Entry
    Specification by freedesktop.org.  See:
            http://freedesktop.org/Standards/desktop-entry-spec
    These should work for both KDE and Gnome2

    An entry is a .directory file that includes the display name, icon, etc.
    It will be placed in the location specified within the passed dict.  The
    filename can be explicitly specified, but if not provided, will default to
    an escaped version of the name.
    """
    assert d['path'].endswith('.directory')
    d.setdefault('comment', '')
    d.setdefault('icon', '')
    fo = open(d['path'], 'w')
    fo.write(
        """[Desktop Entry]
Type=Directory
Encoding=UTF-8
Name=%(name)s
Comment=%(comment)s
Icon=%(icon)s
"""
         % d)
    fo.close()


@classmethod
def _define_char(cls, prev: str, current: str) ->bool:
    """
        Helper method that'll tell us if a character has to be treated as a
        special one or it is part of the text that 's intended to be printed
        out.

        Takes the previous character and the current character, in case it is
        one of the special characters defined in the class and is prepended by
        a '' means that it has not to be treated as a special one

        Returns True if it's a special character
        """
    if current in cls.special_chars:
        if prev != '\\':
            return True
    return False


def _parse_osl(root, parser):
    """Assemble Python dictionaries of groups from XML document"""
    if root.findtext('Succeeded') == 'false':
        error_reason = root.findtext('Reason', default='unknown reason')
        raise Exception('Lookup failed: ' + error_reason)
    return parser(root)


@staticmethod
def get_opera_ua():
    """
        todo 随机生成opera UA
        :return:
        """
    from fake_useragent import FakeUserAgent
    ua = FakeUserAgent()
    return ua.opera


def get_geometries(type='HB'):
    """
    Function to return typical geometries for different aquicistions.

    Parameters
    ----------
    type : {'HB', 'HF', 'VB', 'VF'}
        Backscatter type:
            * HB: Horizontal Back Scattering (90.0, 90.0, 0.0, 180.0, 0.0, 0.0).
            * HF: Horizontal Forward Scattering (90.0, 90.0, 0.0, 0.0, 0.0, 0.0).
            * VB: Vertical Back Scattering (0.0, 180.0, 0.0, 0.0, 0.0, 0.0).
            * VF: Vertical Forward Scattering (180.0, 180.0, 0.0, 0.0, 0.0, 0.0).

    Returns
    -------
    geometry : tuple
        A tuple with (iza, vza, iaa, vaa, alpha, beta) parameters.

    """
    if type is 'HB':
        return 90.0, 90.0, 0.0, 180.0, 0.0, 0.0
    elif type is 'HF':
        return 90.0, 90.0, 0.0, 0.0, 0.0, 0.0
    elif type is 'VB':
        return 0.0, 180.0, 0.0, 0.0, 0.0, 0.0
    elif type is 'VF':
        return 180.0, 180.0, 0.0, 0.0, 0.0, 0.0
    else:
        raise ValueError(
            "The parameter type should be 'HB', 'HF', 'VB', 'VF'. The actual parameter is: {0}"
            .format(str(type)))


def plot(client, file_=None, dirname=None, driver=None):
    """Export a model plot.

    Args:
        client (obj):
            creopyson Client.
        `file_` (str, optional):
            Model name. Defaults is currently active model.
        dirname (str, optional):
            Destination directory.
            Defaults is Creo's current working directory.
        driver (str, optional):
            Driver export.
            Defaults is `POSTSCRIPT`.
            Valid values: POSTSCRIPT, JPEG, TIFF.

    Returns:
        dict:
            dirname (str): Directory of the output file
            filename (str): Name of the output file

    """
    data = {}
    if file_ is not None:
        data['file'] = file_
    else:
        active_file = client.file_get_active()
        if active_file is not None:
            data['file'] = active_file['file']
    if dirname:
        data['dirname'] = dirname
    if driver:
        data['driver'] = driver
    return client._creoson_post('interface', 'plot', data)


def optionsTableString(options, defaults=None):
    """Return a string containing a table of options set"""
    formatstring = '{:<50}|  {:<30}\n'
    result = '\nOptions\n=======\n' + formatstring.format('Name', 'Value'
        ) + '-' * 80 + '\n'
    for name, value in sorted(options.items()):
        valuestring = str(value)
        if defaults is not None and value == defaults[name]:
            valuestring += '\t(default)'
        result += formatstring.format(name, valuestring)
    return result


def openFile(path):
    """Returns the file or filelike object identified by the given path
        (relative to this directory).

        Raises IOError if the file cannot be opened.
        """


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

        :param GroupAddExternalIdDetails val:
        :rtype: EventDetails
        """
    return cls('group_add_external_id_details', val)


def parse_photo_link(photo_url):
    """
    Extracts the base URL (URL without query parameters) and the photo name from a Onedrive photo URL
    :param photo_url: photo URL
    :return: base URL and photo name
    """
    base_url = photo_url.split('?')[0]
    name = base_url.split('/')[-1]
    return base_url, name


def Clift_Gauvin(Re):
    """Calculates drag coefficient of a smooth sphere using the method in
    [1]_ as described in [2]_.

    .. math::
        C_D = \\frac{24}{Re}(1 + 0.152Re^{0.677}) + \\frac{0.417}
        {1 + 5070Re^{-0.94}}

    Parameters
    ----------
    Re : float
        Particle Reynolds number of the sphere using the surrounding fluid
        density and viscosity, [-]

    Returns
    -------
    Cd : float
        Drag coefficient [-]

    Notes
    -----
    Range is Re <= 2E5

    Examples
    --------
    >>> Clift_Gauvin(200.)
    0.7905400398000133

    References
    ----------
    .. [1] R. Clift, W.H. Gauvin, The motion of particles in turbulent gas
       streams, Proc. Chemeca, 70, 1970, pp. 14-28.
    .. [2] Barati, Reza, Seyed Ali Akbar Salehi Neyshabouri, and Goodarz
       Ahmadi. "Development of Empirical Models with High Accuracy for
       Estimation of Drag Coefficient of Flow around a Smooth Sphere: An
       Evolutionary Approach." Powder Technology 257 (May 2014): 11-19.
       doi:10.1016/j.powtec.2014.02.045.
    """
    return 24.0 / Re * (1 + 0.152 * Re ** 0.677) + 0.417 / (1 + 5070 * Re **
        -0.94)


def _remove_proper_feature(human_readable: str) ->str:
    """Removes proper feature from human-readable analysis."""
    human_readable = human_readable.replace('+[Proper=False]', '')
    human_readable = human_readable.replace('+[Proper=True]', '')
    return human_readable


def parse_string(clause_constructor, string, on_error='raise'):
    """ Creates a clause object from a string

        :param clause_constructor: The type of clause to build
        :param string: The string to use to build this clause
        :param on_error: The action to take when an error is encountered ('raise', 'warn', 'ignore')
        :return: The clause object
    """
    assert on_error in ('raise', 'warn', 'ignore'
        ), 'Valid values for error are "raise", "warn", "ignore"'
    clause = clause_constructor()
    clause.from_string(string, on_error=on_error)
    if not clause.is_valid:
        return None
    return clause


def check(rank, default=None):
    """Check whether `rank` is greater than `default`."""
    return rank > default.upper() if default is not None else False


def column_exists(df, col):
    """Check the column name exists in the DataFrame.

    Args:
        df (:obj:`DataFrame`): Pandas DataFrame.
        col (str): Column name.

    Returns:
        bool: True if exists, False if not exists.

    """
    if col and col not in df.columns:
        print('The specify column `{0!s}` not found in the input file'.
            format(col))
        return False
    else:
        return True


def list_items_in_collection(keys):
    """List just the items in the collection."""


@classmethod
def max(cls, item='uid', like={}, isin={}, orderby='', where='', limit='',
    **criteria):
    """return max of item (column) filtered by these criteria
    """
    what = 'max(%s)' % item
    return cls.list(asObjects=False, sql='', like=like, isin=isin, orderby=
        orderby, where=where, limit=limit, what=what, **criteria)[0][what]


def rule(port, action='ACCEPT', source='net', dest='$FW', proto='tcp'):
    """
    Helper to build a firewall rule.

    Examples::

        from fabtools.shorewall import rule

        # Rule to accept connections from example.com on port 1234
        r1 = rule(port=1234, source=hosts(['example.com']))

        # Rule to reject outgoing SMTP connections
        r2 = rule(port=25, action='REJECT', source='$FW', dest='net')

    """
    return {'action': action, 'source': source, 'dest': dest, 'proto':
        proto, 'dest_port': port}


def hide_code_str():
    """
    Print an HTML code to hide python code in Jupyter notebooks
    :return: String
    """
    return """

    The raw code for this IPython notebook is by default hidden for easier reading.
    To toggle on/off the raw code, click here.
    """


@staticmethod
def find_all_offsets(pattern, text, offset=0):
    """Don't use regular expressions as they are a tad slow"""
    matches = []
    pattern_len = len(pattern)
    next_match = text.find(pattern)
    while next_match != -1:
        matches.append((next_match + offset, next_match + pattern_len + offset)
            )
        next_match = text.find(pattern, next_match + 1)
    return matches


def instanceof(obj, classinfo):
    """Wrap isinstance to only return True/False"""
    try:
        return isinstance(obj, classinfo)
    except TypeError:
        return False


def aiida_version():
    """get the version of aiida in use

    :returns: packaging.version.Version
    """
    from aiida import __version__ as aiida_version_
    from packaging import version
    return version.parse(aiida_version_)


def utcnow():
    """Return the current UTC date and time, with tzinfo None.

        This is like now(), but returns the current UTC date and time, as a
        naive datetime object.

        See also now().
        """


def str_maxed(arg, maxlen):
    """ Returns a (possibly) truncated string representation of arg

    If maxlen is positive (or null), returns str(arg) up to maxlen chars.

    :param arg:
    :param maxlen:
    :return:
    """
    s = str(arg)
    if maxlen <= 0 or len(s) <= maxlen:
        return s
    else:
        return '%s..' % s[:maxlen]


@classmethod
def _decr_instances(cls, instance):
    """
        Remove from list and reposition other bars
        so that newer bars won't overlap previous bars
        """
    with cls._lock:
        try:
            cls._instances.remove(instance)
        except KeyError:
            pass
        if not instance.gui:
            for inst in cls._instances:
                if inst.pos > abs(instance.pos):
                    inst.pos -= 1
    if not cls._instances and cls.monitor:
        try:
            cls.monitor.exit()
            del cls.monitor
        except AttributeError:
            pass
        else:
            cls.monitor = None


def add(url, method, params, headers, payload):
    """Create task and queue it after successful transaction"""


@staticmethod
def get_output_codes():
    """Return a list of all possible output codes."""
    return ['interface-added', 'interface-removed', 'deprecated',
        'undeprecatedc-symbol-changed', 'reply-added', 'reply-removed',
        'ecs-changed-true-invalidates', 'ecs-changed-true-false',
        'ecs-changed-true-const', 'ecs-changed-invalidates-true',
        'ecs-changed-invalidates-false', 'ecs-changed-invalidates-const',
        'ecs-changed-false-invalidates', 'ecs-changed-false-true',
        'ecs-changed-false-const', 'ecs-changed-const-invalidates',
        'ecs-changed-const-true', 'ecs-changed-const-false', 'method-added',
        'method-removed', 'property-added', 'property-removed',
        'signal-added', 'signal-removed', 'argument-added',
        'argument-removed', 'property-type-changed',
        'property-access-changed-read-readwrite',
        'property-access-changed-read-write',
        'property-access-changed-write-read',
        'property-access-changed-write-readwrite',
        'property-access-changed-readwrite-read',
        'property-access-changed-readwrite-write', 'argument-name-changed',
        'argument-type-changed', 'argument-direction-changed-in-out',
        'argument-direction-changed-out-in']


def pytest_addoption(parser):
    """
    register argparse-style options and ini-style config values.
    """
    test_selection_group = parser.getgroup('Tests Selection')
    test_selection_group.addoption('--run-destructive', action='store_true',
        default=False, help=
        'Run destructive tests. These tests can include adding or removing users from your system for example. Default: False'
        )
    test_selection_group.addoption('--run-expensive', action='store_true',
        default=False, help=
        'Run expensive tests. These tests usually involve costs like for example bootstrapping a cloud VM. Default: False'
        )


def display2classmethod(display):
    """Opposite of classmethod2display.
    """
    L = display.split(' -> ')
    return L[0], L[1]


def is_lambda_name(name):
    """
    Check if `name` is the name of lambda function.
    """
    return name.endswith('<lambda>')


def make_vector(dim, init_value):
    """
    Return a list of dim copies of init_value
    """
    return [init_value] * dim


def get_roles():
    """Return information about the available basis set roles available

    The returned data is a map of role to display name. The format
    can be passed as the role argument to fmt argument to :func:`lookup_basis_by_role`
    """
    return {'orbital': 'Orbital basis', 'jfit': 'J-fitting', 'jkfit':
        'JK-fitting', 'rifit': 'RI-fitting', 'optri':
        'Optimized RI-fitting', 'admmfit':
        'Auxiliary-Density Matrix Method Fitting', 'dftxfit':
        'DFT Exchange Fitting', 'dftjfit': 'DFT Correlation Fitting'}


def get_real_space_mask_from_fit(mask, fit):
    """Get the masks of the fit if the masks should be plotted on the fit.

    Parameters
    -----------
    fit : datas.fitting.fitting.AbstractLensHyperFit
        The fit to the datas, which includes a lisrt of every model image, residual_map, chi-squareds, etc.
    mask : bool
        If *True*, the masks is plotted on the fit's datas.
    """
    if mask:
        return fit.masked_dataset.mask
    else:
        return None


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 fisher_exact(fo, alpha=0.05):
    """fisher_exact 显著性检验函数
    此处采用的是调用R的解决方案，需要安装包 pyper
    python解决方案参见
    https://mrnoutahi.com/2016/01/03/Fisher-exac-test-for-mxn-table/
    但还有些问题，所以没用.
    """
    import pyper as pr
    r = pr.R(use_pandas=True, use_numpy=True)
    r.assign('fo', fo)
    r('b<-fisher.test(fo)')
    pdata = r['b']
    p_value = pdata['p.value']
    if p_value < alpha:
        result = 1
    else:
        result = 0
    return result, p_value


def get_stop_index(word, sliding_window_length):
    """ Stop index for two adjacent sliding windows.

    For blActgActgA it would be::

        blAct | gActg | A -> b | lActg | ActgA

    """
    return len(word) - sliding_window_length * 2 + 1


def make_c_header(name, front, body):
    """
    Build a C header from the front and body.
    """
    return (
        """
{0}

# ifndef _GU_ZHENGXIONG_{1}_H
# define _GU_ZHENGXIONG_{1}_H

{2}

# endif /* {3}.h */
    """
        .strip().format(front, name.upper(), body, name) + '\n')


@classmethod
def fetch(cls, channel, start, end, host=None, port=None, verbose=False,
    connection=None, verify=False, pad=None, allow_tape=None, scaled=None,
    type=None, dtype=None):
    """Fetch data from NDS

        Parameters
        ----------
        channel : `str`, `~gwpy.detector.Channel`
            the data channel for which to query

        start : `~gwpy.time.LIGOTimeGPS`, `float`, `str`
            GPS start time of required data,
            any input parseable by `~gwpy.time.to_gps` is fine

        end : `~gwpy.time.LIGOTimeGPS`, `float`, `str`
            GPS end time of required data,
            any input parseable by `~gwpy.time.to_gps` is fine

        host : `str`, optional
            URL of NDS server to use, if blank will try any server
            (in a relatively sensible order) to get the data

        port : `int`, optional
            port number for NDS server query, must be given with `host`

        verify : `bool`, optional, default: `False`
            check channels exist in database before asking for data

        scaled : `bool`, optional
            apply slope and bias calibration to ADC data, for non-ADC data
            this option has no effect

        connection : `nds2.connection`, optional
            open NDS connection to use

        verbose : `bool`, optional
            print verbose output about NDS progress, useful for debugging;
            if ``verbose`` is specified as a string, this defines the
            prefix for the progress meter

        type : `int`, optional
            NDS2 channel type integer

        dtype : `type`, `numpy.dtype`, `str`, optional
            identifier for desired output data type
        """
    return cls.DictClass.fetch([channel], start, end, host=host, port=port,
        verbose=verbose, connection=connection, verify=verify, pad=pad,
        scaled=scaled, allow_tape=allow_tape, type=type, dtype=dtype)[str(
        channel)]


def equity_capacity_demand_difference(slots, events, X, beta, **kwargs):
    """
    A function that returns the maximum difference between demand for an event
    and the slot capacity it is scheduled in.
    """
    return beta


def merging_from_list(list_var, merged_var, merged_id, merged_id_var,
    node_label, edge_label, merge_typing=False, carry_vars=None,
    ignore_naming=False, multiple_rows=False, multiple_var=None):
    """Generate query for merging the nodes of a neo4j list.

    Parameters
    ----------
    list_var : str
        Name of the variable corresponding to the list of nodes to clone
    merged_var : str
        Name of the variable corresponding to the new merged node
    merged_id : str
        Id to use for the new node that corresponds to the merged node
    merged_id_var : str
        Name of the variable for the id of the new merged node
    node_label
        Label of the nodes to merge, default is 'node'
    edge_label
        Label of the edges to merge, default is 'edge'
    merge_typing : boolean
        If true, typing edges are merged
    carry_vars : str
        Collection of variables to carry
    multiple_rows : boolean
        Must be True when the previous matching resulted in more than one
        record (for example when there is more than one group of nodes to
        merge). When True, a map linking the original ids of the nodes to
        the id of the merged one is created so that the edges between the
        merged nodes are always preserved
    multiple_var : str
        Variable which has a different value on each row. Used for controlling
        the merging on multiple rows

    Returns
    -------
    query : str
        Generated query
    carry_vars : set
        Updated collection of variables to carry
    """
    if carry_vars is None:
        carry_vars = set([list_var])
    carry_vars.remove(list_var)
    query = 'UNWIND {} as node_to_merge\n'.format(list_var)
    query += ('// accumulate all the attrs of the nodes to be merged\n' +
        'WITH [] as new_props, node_to_merge, ' + ', '.join(carry_vars) +
        '\n' +
        """WITH new_props + REDUCE(pairs = [], k in keys(node_to_merge) |
"""
         + '\tpairs + REDUCE(inner_pairs = [], v in node_to_merge[k] | \n' +
        '\t\tinner_pairs + {key: k, value: v})) as new_props, node_to_merge, '
         + ', '.join(carry_vars) + '\n')
    query += ('WITH collect(node_to_merge) as {}, '.format(list_var) +
        'collect(new_props) as new_props_col, ' + ', '.join(carry_vars) +
        """
WITH REDUCE(init=[], props in new_props_col | init + props) as new_props, """
         + '{}, '.format(list_var) + ', '.join(carry_vars) + '\n')
    carry_vars.add(list_var)
    query += ("WITH apoc.map.groupByMulti(new_props, 'key') as new_props, " +
        ', '.join(carry_vars) + '\n' +
        """WITH apoc.map.fromValues(REDUCE(pairs=[], k in keys(new_props) |
	pairs + [k, REDUCE(values=[], v in new_props[k] |
		values + CASE WHEN v.value IN values THEN [] ELSE v.value END)])) as new_props, """
         + ', '.join(carry_vars) + '\n' + 'WITH {}[0] as {}, new_props, '.
        format(list_var, merged_var) + ', '.join(carry_vars) +
        """
SET {} = new_props
""".format(merged_var))
    carry_vars.add(merged_var)
    if ignore_naming is True:
        query += (
            '// set appropriate node id\nSET {}.id = toString(id({}))\n'.
            format(merged_var, merged_var) + """SET {}.count = NULL
""".
            format(merged_var) + 'WITH toString(id({})) as {}, '.format(
            merged_var, merged_id_var) + ', '.join(carry_vars) + '\n')
    else:
        query += ('// search for a node with the same id as the clone id\n' +
            """OPTIONAL MATCH (same_id_node:{} {{ id : '{}'}})
""".format(
            node_label, merged_id) + 'WITH same_id_node,  ' +
            'CASE WHEN same_id_node IS NOT NULL THEN (coalesce(same_id_node.count, 0) + 1) '
             + 'ELSE 0 END AS same_id_node_new_count, ' + ', '.join(
            carry_vars) + '\n' +
            """// generate new id if the same id node was found
""" +
            '// and filter edges which will be removed \n' +
            'WITH same_id_node, same_id_node_new_count, ' +
            "'{}' + CASE WHEN same_id_node_new_count <> 0 ".format(
            merged_id) +
            "THEN toString(same_id_node_new_count) ELSE '' END as {}, ".
            format(merged_id_var) + ', '.join(carry_vars) +
            """
// set appropriate node id
SET {}.id = {}
""".format(
            merged_var, merged_id_var) + 'SET {}.count = NULL\n'.format(
            merged_var) + 'WITH {}, '.format(merged_id_var) + ', '.join(
            carry_vars) + '\n')
    carry_vars.add(merged_id_var)
    if multiple_rows:
        query += 'UNWIND {} AS node_to_merge\n'.format(list_var)
        carry_vars.remove(list_var)
        query += (
            '//create a map from node ids to the id of the merged_node\n' +
            'WITH {{old_node:node_to_merge.id,  new_node:{}}} as id_to_merged_id, '
            .format(merged_var) + 'node_to_merge, ' + ', '.join(carry_vars) +
            '\n' +
            'WITH collect(id_to_merged_id) as ids_to_merged_id, collect(node_to_merge) as {}, '
            .format(list_var) + ', '.join(carry_vars) + '\n')
        carry_vars.add(list_var)
        query += (
            "WITH apoc.map.groupByMulti(ids_to_merged_id, 'old_node') as ids_to_merged_id, "
             + ', '.join(carry_vars) + '\n' +
            """WITH apoc.map.fromValues(REDUCE(pairs=[], k in keys(ids_to_merged_id) |
	pairs + [k, REDUCE(values=[], v in ids_to_merged_id[k] |
		values + CASE WHEN v.new_node IN values THEN [] ELSE v.new_node END)])) as ids_to_merged_id, """
             + ', '.join(carry_vars) + '\n')
        carry_vars.difference_update([multiple_var, list_var, merged_var,
            merged_id_var])
        query += (
            'WITH collect({{n:{}, nodes_to_merge:{}, merged_node: {}, merged_id: {}}}) '
            .format(multiple_var, list_var, merged_var, merged_id_var) +
            'as all_n, collect(ids_to_merged_id) as ids_to_merged_id, ' +
            ', '.join(carry_vars) + '\n' +
            'WITH reduce(acc={}, x in ids_to_merged_id | apoc.map.merge(acc, x))'
             + ' as ids_to_merged_id, all_n, ' + ', '.join(carry_vars) +
            '\n' + """UNWIND all_n as n_maps
""" +
            'WITH n_maps.n as {}, n_maps.nodes_to_merge as {}, '.format(
            multiple_var, list_var) +
            'n_maps.merged_node as {}, n_maps.merged_id as {}, '.format(
            merged_var, merged_id_var) + 'ids_to_merged_id, ' + ', '.join(
            carry_vars) + '\n')
        carry_vars.update([multiple_var, list_var, merged_var,
            merged_id_var, 'ids_to_merged_id'])
    query += 'UNWIND {} AS node_to_merge\n'.format(list_var)
    carry_vars.remove(list_var)
    if multiple_rows:
        query += (
            """// accumulate all the attrs of the edges incident to the merged nodes
WITH node_to_merge, """
             + ', '.join(carry_vars) +
            """
OPTIONAL MATCH (node_to_merge)-[out_rel:{}]->(suc)
""".
            format(edge_label) +
            'WITH CASE WHEN suc.id IN keys(ids_to_merged_id)\n' +
            """		THEN {id: id(ids_to_merged_id[suc.id][0]), neighbor: ids_to_merged_id[suc.id][0], edge: out_rel}
"""
             +
            '\t\tELSE {id: id(suc), neighbor: suc, edge: out_rel} END AS suc_map, '
             + 'node_to_merge, ' + ', '.join(carry_vars) + '\n' +
            'WITH collect(suc_map) as suc_maps, ' + 'node_to_merge, ' +
            ', '.join(carry_vars) + '\n' +
            """OPTIONAL MATCH (pred)-[in_rel:{}]->(node_to_merge)
""".
            format(edge_label) +
            'WITH CASE WHEN pred.id IN keys(ids_to_merged_id)\n' +
            """		THEN {id: id(ids_to_merged_id[pred.id][0]), neighbor: ids_to_merged_id[pred.id][0], edge: in_rel}
"""
             +
            '\t\tELSE {id: id(pred), neighbor: pred, edge: in_rel} END AS pred_map, '
             + 'node_to_merge, suc_maps, ' + ', '.join(carry_vars) + '\n' +
            'WITH collect(pred_map) as pred_maps, ' +
            'suc_maps, node_to_merge, ' + ', '.join(carry_vars) + '\n')
    else:
        query += (
            """// accumulate all the attrs of the edges incident to the merged nodes
WITH [] as suc_maps, [] as pred_maps, node_to_merge, """
             + ', '.join(carry_vars) +
            """
OPTIONAL MATCH (node_to_merge)-[out_rel:{}]->(suc)
""".
            format(edge_label) +
            'WITH suc_maps + collect({id: id(suc), neighbor: suc, edge: out_rel}) as suc_maps, '
             + 'pred_maps, node_to_merge, ' + ', '.join(carry_vars) + '\n' +
            """OPTIONAL MATCH (pred)-[in_rel:{}]->(node_to_merge)
""".
            format(edge_label) +
            'WITH pred_maps + collect({id: id(pred), neighbor: pred, edge: in_rel}) as pred_maps, '
             + 'suc_maps, node_to_merge, ' + ', '.join(carry_vars) + '\n')
    query += ('WITH collect(node_to_merge) as {}, '.format(list_var) +
        'collect(node_to_merge.id) as list_ids, collect(suc_maps) as suc_maps_col, '
         + 'collect(pred_maps) as pred_maps_col, ' + ', '.join(carry_vars) +
        """
WITH REDUCE(init=[], maps in suc_maps_col | init + maps) as suc_maps, """
         +
        'REDUCE(init=[], maps in pred_maps_col | init + maps) as pred_maps, ' +
        'list_ids, {}, '.format(list_var) + ', '.join(carry_vars) + '\n')
    carry_vars.add(list_var)
    carry_vars.add('list_ids')
    query += ("WITH apoc.map.groupByMulti(suc_maps, 'id') as suc_props, " +
        """REDUCE(list=[], map in suc_maps |
	list + CASE WHEN NOT map['neighbor'] IS NULL THEN [map['neighbor']] ELSE [] END) as suc_nodes, apoc.map.groupByMulti(pred_maps, 'id') as pred_props, """
         +
        """REDUCE(list=[], map in pred_maps |
	list + CASE WHEN NOT map['neighbor'] IS NULL THEN [map['neighbor']] ELSE [] END) as pred_nodes, """
         + """	REDUCE(l=[], el in suc_maps + pred_maps|
""" +
        "\t\tl + CASE WHEN el['id'] IN list_ids THEN [toString(el['id'])] ELSE [] END)"
         + ' as self_loops, ' + ', '.join(carry_vars) + '\n')
    carry_vars.remove('list_ids')
    carry_vars.add('self_loops')
    query += (
        """WITH suc_nodes, pred_nodes, apoc.map.fromValues(REDUCE(edge_props=[], k in keys(suc_props) |
	edge_props + [k, apoc.map.groupByMulti(REDUCE(props=[], el in suc_props[k] |
		props + REDUCE(pairs=[], kk in keys(el['edge']) |
			pairs + REDUCE(values=[], v in el['edge'][kk] |
				values + {key: kk, value: v}))), 'key')])) as suc_props,
"""
         +
        """	apoc.map.fromValues(REDUCE(edge_props=[], k in keys(pred_props) |
	edge_props + [k, apoc.map.groupByMulti(REDUCE(props=[], el in pred_props[k] |
		props + REDUCE(pairs=[], kk in keys(el['edge']) |
			pairs + REDUCE(values=[], v in el['edge'][kk] |
				 values + {key: kk, value: v}))), 'key')])) as pred_props,
"""
         +
        """	REDUCE(edge_props=[], k IN filter(k IN keys(suc_props) WHERE k IN self_loops) |
		edge_props + suc_props[k]) +
	REDUCE(edge_props=[], k IN filter(k IN keys(pred_props) WHERE k IN self_loops) |
		edge_props + pred_props[k]) as self_loop_props, """
         + ', '.join(carry_vars) + '\n' +
        'WITH suc_nodes, suc_props, pred_nodes, pred_props, ' +
        """apoc.map.groupByMulti(REDUCE(pairs=[], el in self_loop_props |
	pairs + REDUCE(inner_pairs=[], k in keys(el['edge']) |
		inner_pairs + REDUCE(values=[], v in el['edge'][k] |
			values + {key: k, value: v}))), 'key') as self_loop_props, """
         + ', '.join(carry_vars) + '\n')
    query += """FOREACH(suc IN filter(suc IN suc_nodes WHERE NOT id(suc) in self_loops) |
	MERGE ({})-[new_rel:{}]->(suc)
""".format(merged_var, edge_label) + """	SET new_rel = apoc.map.fromValues(REDUCE(pairs=[], k in keys(suc_props[toString(id(suc))]) |
		 pairs + [k, REDUCE(values=[], v in suc_props[toString(id(suc))][k] |
			values + CASE WHEN v.value IN values THEN [] ELSE v.value END)])))
FOREACH(pred IN filter(pred IN pred_nodes WHERE NOT id(pred) in self_loops) |
	MERGE (pred)-[new_rel:{}]->({})
""".format(edge_label, merged_var) + """	SET new_rel = apoc.map.fromValues(REDUCE(pairs=[], k in keys(pred_props[toString(id(pred))]) |
		 pairs + [k, REDUCE(values=[], v in pred_props[toString(id(pred))][k] |
			values + CASE WHEN v.value IN values THEN [] ELSE v.value END)])))
"""
    query += """// add self loop
FOREACH(dummy in CASE WHEN length(self_loops) > 0 THEN [NULL] ELSE [] END |
	MERGE ({})-[new_rel:{}]->({})
""".format(merged_var, edge_label, merged_var) + """	SET new_rel = apoc.map.fromValues(REDUCE(pairs=[], k in keys(self_loop_props) |
		pairs + [k, REDUCE(values=[], v in self_loop_props[k] |
			values + CASE WHEN v.value IN values THEN [] ELSE v.value END)])))
"""
    carry_vars.remove('self_loops')
    if merge_typing:
        query += 'WITH ' + ', '.join(carry_vars) + '\n'
        query += 'UNWIND {} AS node_to_merge\n'.format(list_var)
        carry_vars.remove(list_var)
        query += (
            """// accumulate all the attrs of the edges incident to the merged nodes
WITH [] as suc_typings, [] as pred_typings, node_to_merge, """
             + ', '.join(carry_vars) + '\n')
        query += ('OPTIONAL MATCH (node_to_merge)-[:typing]->(suc)\n' +
            'WITH suc_typings + collect(suc) as suc_typings, node_to_merge, ' +
            'pred_typings, ' + ', '.join(carry_vars) + '\n' +
            """OPTIONAL MATCH (pred)-[:typing]->(node_to_merge)
""" +
            'WITH pred_typings + collect(pred) as pred_typings, node_to_merge, '
             + 'suc_typings, ' + ', '.join(carry_vars) + '\n')
        query += ('WITH collect(node_to_merge) as {}, '.format(list_var) +
            'collect(suc_typings) as suc_typings_col, ' +
            'collect(pred_typings) as pred_typings_col, ' + ', '.join(
            carry_vars) +
            """
WITH REDUCE(init=[], sucs in suc_typings_col | init + sucs) as suc_typings, """
             +
            'REDUCE(init=[], preds in pred_typings_col | init + preds) as pred_typings, '
             + '{}, '.format(list_var) + ', '.join(carry_vars) + '\n')
        carry_vars.add(list_var)
        query += ('FOREACH(suc in suc_typings |\n' +
            '\tMERGE ({})-[:typing]->(suc))\n'.format(merged_var) +
            """FOREACH(pred in pred_typings |
""" +
            '\tMERGE (pred)-[:typing]->({}))\n'.format(merged_var))
    query += 'WITH ' + ', '.join(carry_vars
        ) + '\n' + """FOREACH(node in filter(x IN {} WHERE x <> {}) |
""".format(
        list_var, merged_var) + '\tDETACH DELETE node)\n'
    carry_vars.remove(list_var)
    return query, carry_vars


def tick(price, tick_size=0.05):
    """
    Rounds a given price to the requested tick
    """
    return round(price / tick_size) * tick_size


def trim_image(img, white_bg=True, thresh=240):
    """
    Trim edges of image.

    Args:
        img (numpy.array): 2D rectangular grayscale image
    """
    if not white_bg:
        thresh = 255 - thresh
    top_found = False
    bot_found = False
    left_found = False
    right_found = False
    top_ind = img.shape[1]
    bot_ind = 0
    left_ind = img.shape[0]
    right_ind = 0
    for r, row in enumerate(img):
        for c, pix in enumerate(row):
            if pix <= thresh:
                top_ind = min(top_ind, r)
                bot_ind = max(bot_ind, r)
                left_ind = min(left_ind, c)
                right_ind = max(right_ind, c)
    return top_ind, bot_ind, left_ind, right_ind


@staticmethod
def delete_local_session(callback=None):
    """
        Deletes the local session.
        """
    if callback is not None:
        callback()


def create_friendship_instance(sender, instance, created, raw, **kwargs):
    """
    Create a |FriendshipRequest| for newly created |User|.

    .. seealso::
        :data:`~django.db.models.signals.post_save` built-in signal.
    """
    from friends.models import Friendship
    if created and not raw:
        Friendship.objects.create(user=instance)


def _has_converged(pi_star, pi):
    """Checks if the random walk has converged.

    :param pi_star: the new vector
    :param pi: the old vector
    :returns: bool-- True iff pi has converged.

    """
    node_count = pi.shape[0]
    EPS = 1e-05
    for i in range(node_count):
        if pi[i] - pi_star[i] > EPS:
            return False
    return True


def last(expr, defer=None):
    """
    returns the last item from the collection

    Parameters
    ----------
    expr : iterable
        the list
    defer : any type, optional
        what is returned when nothing is provided in the iterable. The default is None.

    Returns
    -------
    out : item
        last item in the array

    Examples
    --------
    >>> xt.last(['a','b'])
    'b'

    >>> xt.last([])
    None

    """
    iter(expr)
    try:
        return expr[-1]
    except IndexError:
        return defer