@staticmethod
def _from_string(msg: str='', del_spaces: bool=False, delimiter: str='\n'):
    """
        Takes a manual string input from the user, and then splits it using a comma delimiter into a list of values.         Called when an FeatureSet instance is created without input,         or when FeatureSet.enrich_randomization is called without input.

        :param msg: a promprt to be printed to the user
        :param del_spaces: if True, will delete all spaces in each delimited value.
        :param delimiter: the delimiter used to separate the values. Default is '
'
        :return:
        A list of the comma-seperated values the user inserted.
        """
    string = input(msg)
    split = string.split(sep=delimiter)
    if del_spaces:
        for i in range(len(split)):
            split[i] = split[i].replace(' ', '')
    if split[-1] == '':
        split = split[:-1]
    return split


def get_plural_string(word: str, amount: int) ->str:
    """Returns singular or plural of the word depending on the amount.
	Example:
		word = 'piece', amount = 0 -> '0 pieces'
		word = 'piece', amount = 1 -> '1 piece'
		word = 'piece', amount = 5 -> '5 pieces'"""
    if amount == 1:
        return f'1 {word}'
    else:
        return f'{amount} {word}s'


def reorder_dims(darray, dim1, dim2):
    """Interchange two dimensions of a DataArray in a similar way as numpy's swap_axes

    Parameters
    ---------
    darray: Xarray.DataArray/TimeSeriesX
    dim1: str, the first dim we want to swap
    dim2: str, the second dim we want to swap

    Returns
    ---------
    transposed darray

    Example Usage
    -------------
    # Swap the timeseries object's first dim and time dim
    check_first_dim = timeseries.dims[0]
    timeseries_swapped_time_dim = reorder_dims(timeseries, dim1=check_first_dim, dim2='time')

    See
    -------
    https://github.com/pydata/xarray/issues/1081, rafa-guedes comment on Aug 21, 2017
    """
    dims = list(darray.dims)
    assert set([dim1, dim2]).issubset(dims
        ), 'dim1 and dim2 must be existing dimensions in darray'
    ind1, ind2 = dims.index(dim1), dims.index(dim2)
    dims[ind2], dims[ind1] = dims[ind1], dims[ind2]
    return darray.transpose(*dims)


def calculate_excess(adsorbant, slab_cations, area, bulk, nspecies=1, check
    =False):
    """Calculates the excess of a given species at the surface.
    Depending on the nature of the species, there are two ways to do this.
    If the species is a constituent part of the surface, e.g.
    Oxygen in :math:`TiO_2` then the calculation must account for
    the stoichiometry of that material. Using the :math:`TiO_2` example

    .. math::
        \\Gamma_O = \\frac{1}{2A} \\Bigg( nO_{Slab} - \\frac{nO_{Bulk}}
        {nTi_{Bulk}}nTi_{Slab}  \\Bigg)

    where :math:`nO_{Slab}` is the number of oxygen in the slab,
    :math:`nO_{Bulk}` is the number of oxygen in the bulk,
    A is the surface area, :math:`nTi_{Bulk}` is the number of Ti in
    the bulk and :math:`nTi_{Slab}` is the number of Ti in the slab.
    If the species is just an external adsorbant, e.g. water or carbon dioxide
    then one does not need to consider the state of the surface,
    as there was none there to begin with.

    .. math::
        \\Gamma_{H_2O} = \\frac{nH_2O}{2A}

    where :math:`nH_2O` is the number of water molecules and A is the
    surface area.

    Parameters
    ----------
    adsorbant : int
        Number of species
    slab_cations : int
        Number of cations
    area : float
        Area of surface
    bulk : dic
        Dictonary of bulk properties
    nspecies : int (optional)
        number of external species
    check : bool (optional)
        Check if this is an external or constituent species.

    Returns
    -------
    float:
        Surface excess of given species.
    """
    if check is True and nspecies == 1:
        return (adsorbant - bulk['Anion'] / bulk['Cation'] * slab_cations) / (
            2 * area)
    else:
        return adsorbant / (area * 2)


def checkBoundsExplicit(solution, lb, ub):
    """ check if flux distribution 'solution' violates any of the given lower
        and upper flux bounds

    Keyword arguments:

    solution -- flux distribution (MetabolicFlux object)
    lb, ub   -- dicts {reaction : bound} of lower and upper bounds

    Returns:  lbViolations, ubViolations - {reaction : flux, bound} dicts
    """
    lbViolations, ubViolations = {}, {}
    for rea in solution:
        flux = solution[rea]
        if rea in lb:
            if flux < lb[rea]:
                lbViolations[rea] = flux, lb[rea]
        if rea in ub:
            if flux > ub[rea]:
                ubViolations[rea] = flux, ub[rea]
    return lbViolations, ubViolations


def sortByName(requestContext, seriesList):
    """
    Takes one metric or a wildcard seriesList.

    Sorts the list of metrics by the metric name.
    """
    return list(sorted(seriesList, key=lambda x: x.name))


def normalize_delays(delays):
    """
    Normalizes a dictionary of channel delays. Postive delays shift right, negative delays shift left.
    Since we cannot delay by a negative amount in hardware, shift all delays until they are positive.
    Takes in a dict of channel:delay pairs and returns a normalized copy of the same.
    """
    out = dict(delays)
    if not out or len(out) == 0:
        import logging
        logging.error('normalize_delays() had no delays?')
        return out
    min_delay = min(delays.values())
    if min_delay < 0:
        for chan in delays.keys():
            out[chan] += -min_delay
    return out


def calibrate(energy, shift):
    """Calibrate energy scale."""
    return energy + shift


@classmethod
def filename_with_attempt_prefix(cls, name, attempt):
    """
        Return the equivalent filename for `name` depending
        whether an attempt prefix must be used, if `attempt` isn't None.
        """
    if attempt is None:
        return name
    else:
        return '%d.%s' % (attempt, name)


def validate_member_type(key, member_value, property_schema, value_errors):
    """Validate a member of a collection is of a given type.

    :param key: The name of the collection property to validate.
    :type key: str
    :param member_value: The member value of the collection property to
        validate.
    :type member_value: object
    :param property_schema: The property schema to utilize for validation.
    :type property_schema: :class:`PropertySchema`
    :param value_errors: A list of errors found for a given value. If the
        validation fails, then an error message is added to the
        value_errors list.
    :type value_errors: list<str>
    :rtype: None
    """
    if not isinstance(member_value, property_schema.member_type):
        value_errors.append('The value "%s" for "%s" is not of type "%s".' %
            (str(member_value), key, property_schema.member_type))


def short_timestamp(time):
    """
    Generate a (short) human-readable timestamp
    (e.g. `"Jun 05, 2013; 02:58 PM"`)

    **Parameters:**

    * `time`: an instance of `datetime.datetime`

    **Returns:** a string containing a human-readable representation of the
    given time
    """
    return time.strftime('%b %d, %Y; %I:%M %p')


def isWeekend(datetime):
    """Determines whether a the argument lies in a weekend."""


def to_list(obj):
    """Convert an object to a list if it is not already one"""
    if not isinstance(obj, (list, tuple)):
        obj = [obj]
    return obj


def reset_queue(q):
    """clear all contents of queue by dummy reading contents"""
    for _ in range(q.qsize()):
        _ = q.get()


@classmethod
def init_from_molecule(cls, molecule, functional_groups=(), placer_ids=None):
    """
        Initialize from a :class:`.Molecule`.

        Parameters
        ----------
        molecule : :class:`.Molecule`
            The molecule to initialize from.

        functional_groups : :class:`iterable`, optional
            An :class:`iterable` of :class:`.FunctionalGroup` or
            :class:`.FunctionalGroupFactory` or both.
            :class:`.FunctionalGroup` instances are added to the
            building block and :class:`.FunctionalGroupFactory`
            instances are used to create :class:`.FunctionalGroup`
            instances the building block should hold.
            :class:`.FunctionalGroup` instances are used to identify
            which atoms are modified during
            :class:`.ConstructedMolecule` construction.

        placer_ids : :class:`tuple` of :class:`int`, optional
            The ids of *placer* atoms. These are the atoms which should
            be used for calculating the position of the building block.
            Depending on the values passed to `placer_ids`,
            and the functional groups in the building block, different
            *placer* ids will be used by the building block.

            #. `placer_ids` is passed to the initializer: the passed
               *placer* ids will be used by the building block.

            #. `placer_ids` is ``None`` and the building block has
               functional groups: The *placer* ids of the functional
               groups will be used as the *placer* ids of the building
               block.

            #. `placer_ids` is ``None`` and `functional_groups` is
               empty. All atoms of the molecule will be used for
               *placer* ids.

        Returns
        -------
        :class:`.BuildingBlock`
             The building block. It will have the same atoms, bonds and
             atomic positions as `molecule`.

        """
    return cls.init(atoms=tuple(molecule.get_atoms()), bonds=tuple(molecule
        .get_bonds()), position_matrix=molecule.get_position_matrix(),
        functional_groups=functional_groups, placer_ids=placer_ids)


def associate_vpc_with_hosted_zone(HostedZoneId=None, VPC=None, Comment=None):
    """
    Associates an Amazon VPC with a private hosted zone.
    See also: AWS API Documentation

    :example: response = client.associate_vpc_with_hosted_zone(
        HostedZoneId='string',
        VPC={
            'VPCRegion': 'us-east-1'|'us-east-2'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-west-2'|'eu-central-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-south-1'|'ap-northeast-1'|'ap-northeast-2'|'sa-east-1'|'ca-central-1'|'cn-north-1',
            'VPCId': 'string'
        },
        Comment='string'
    )

    :type HostedZoneId: string
    :param HostedZoneId: [REQUIRED]
            The ID of the private hosted zone that you want to associate an Amazon VPC with.
            Note that you can't associate a VPC with a hosted zone that doesn't have an existing VPC association.

    :type VPC: dict
    :param VPC: [REQUIRED]
            A complex type that contains information about the VPC that you want to associate with a private hosted zone.
            VPCRegion (string) --(Private hosted zones only) The region in which you created an Amazon VPC.
            VPCId (string) --(Private hosted zones only) The ID of an Amazon VPC.

    :type Comment: string
    :param Comment: Optional: A comment about the association request.

    :rtype: dict
    :return: {
        'ChangeInfo': {
            'Id': 'string',
            'Status': 'PENDING'|'INSYNC',
            'SubmittedAt': datetime(2015, 1, 1),
            'Comment': 'string'
        }
    }

    """
    pass


def order_structs(result):
    """
    order structure so that the structure whit highetst MFE(most negative)
    will be placed first and so on to the lowest MFE structure.

    """
    for i in result:
        i.reverse()
    result.sort()
    for i in result:
        i.reverse()
    return result


def api_endpoint_to_host(api_endpoint):
    """
    Returns a likely workable host from just the endpoint.

    This would most likely come up if building from a host directly, without
    any API nodes.

    Input should look like http://foo.bar or https://foo.bar. We just return
    foo.bar.
    """
    return api_endpoint.split('/')[2]


@classmethod
def parse(cls, name, data_size, reader, parsers):
    """given a 4 byte name, data_size int, BitstreamReader
        and dict of {"atom":handler} sub-parsers,
        returns an atom of this class"""
    assert name == b'stco'
    version, flags, offset_count = reader.parse('8u 24u 32u')
    return cls(version, flags, [reader.read(32) for i in range(offset_count)])


def get_itemsize(context, list_type):
    """
    Return the item size for the given list type.
    """
    llty = context.get_data_type(list_type.dtype)
    return context.get_abi_sizeof(llty)


@classmethod
def visible_to(klass, user):
    """
        Predicate function to determine whether this list is meaningfully
        visible to this USER
        """
    if len(list(klass.get_member_lists_for_user(user))) > 1:
        return True
    return False


def apache_conf_insert(conf, line):
    """ Crudely add apache directives near other similar directives. """
    sections = conf.split('\n\n')
    directive, value = line.split(' ', 1)
    added = False
    for scount in range(len(sections)):
        if sections[scount].find(directive) >= 0:
            if sections[scount].find(line) < 0:
                sections[scount] += '\n' + line
            added = True
            break
    if not added:
        sections.append(line)
    return '\n\n'.join(sections)


def surface_multiprocessing(args):
    """ A single surface calculation designed to be run in parallel

    Args:
      args: a tuple containing:
        spheres (Spheres): a Spheres object containing all surface producing objects
        probe_radius (float): radius to use for probe calculations
        kwargs (dict): all remaining arguments accepted by the surface calculation algorithm

    Returns:
      surface (Spheres): the input Spheres object but with calculated surface parameters

    """
    spheres, probe_radius, kwargs = args
    return spheres.calculate_surface(probe_radius=probe_radius, **kwargs)


def _np_moveaxis(a, source, destination):
    """Move axes of an array to new positions.
    Other axes remain in their original order.

    Parameters
    ----------
    a : ndarray
        The array whose axes should be reordered.
        source : int or sequence of int
        Original positions of the axes to move. These must be unique.
        destination : int or sequence of int
        Destination positions for each of the original axes. These must also be
        unique.

    Returns
    -------
    result : ndarray
        Array with moved axes. This array is a view of the input array.

    See Also
    --------
        transpose: Permute the dimensions of an array.
        swapaxes: Interchange two axes of an array.

    Examples
    --------
    >>> x = np.zeros((3, 4, 5))
    >>> np.moveaxis(x, 0, -1).shape
    (4, 5, 3)
    >>> np.moveaxis(x, -1, 0).shape
    (5, 3, 4)
    These all achieve the same result:
    >>> np.transpose(x).shape
    (5, 4, 3)
    >>> np.swapaxes(x, 0, -1).shape
    (5, 4, 3)
    >>> np.moveaxis(x, [0, 1], [-1, -2]).shape
    (5, 4, 3)
    >>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape
    (5, 4, 3)
    """
    pass


def _transcode(s, encoding):
    """Common implementation for interpret_text and interpret_simpletext."""
    u = s.decode(encoding)
    if encoding == 'UTF-8':
        return s
    else:
        return u.encode('utf-8')


def mergedicts(*a):
    """ Merge a list of dictionaries. """
    result = {}
    for d in a:
        result.update(d)
    return result


@classmethod
def fromCSV(cls, filepath):
    """Constructor: creates a Stock instance by loading the stock data
           from a CSV file.

        The file should contain no headers and have 3 columns.
        The 1st column should have date stamps in the format YYYYMMDD (year,
        month and  day). The 2nd column should have time stamps in the format
        HHMM (hour and minute). The 3rd column should have stock price values.

        Examples of valid lines:
        20070805,0935,12.34
        20121231,1404,0.35

        The first two columns are imported as integers, and the last column is
        imported as floats.

        Args:
            filepath (string): Path to the CSV file to be imported.

        Returns:
            (Stock): An instance of the Stock class where prices and date/time
                     stamps were loaded from the supplied CSV file.
        """
    data = cls.stockFromCSV(filepath)
    stock = cls(prices=data['price'], dates=data['date'], timestamps=data[
        'time'])
    stock.filepath = filepath
    return stock


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 __setitem__(key, value):
    """Set the value associated with the given key."""


def _unloadlib():
    """Unload rabit library."""
    global _LIB
    del _LIB
    _LIB = None


@staticmethod
def write_with_pandas(data=None, save_path=None, header=False, sep='\t',
    encoding='cp1252'):
    """
        Writes dataframe or series
        :param data: pd.DataFrame, pd.Series
        :param save_path: complete path to file
        :param header: Include header in file
        :param sep: Row separator
        :param encoding: Encoding of out file
        :return: Text file
        """
    data.to_csv(save_path, sep=sep, encoding=encoding, index=False, header=
        header)


def unique_by_index(sequence):
    """ unique elements in `sequence` in the order in which they occur

    Parameters
    ----------
    sequence : iterable

    Returns
    -------
    uniques : list
        unique elements of sequence, ordered by the order in which the element
        occurs in `sequence`
    """
    uniques = []
    for element in sequence:
        if element not in uniques:
            uniques.append(element)
    return uniques


@classmethod
def bgblack(cls, string, auto=False):
    """Color-code entire string.

        :param str string: String to colorize.
        :param bool auto: Enable auto-color (dark/light terminal).

        :return: Class instance for colorized string.
        :rtype: Color
        """
    return cls.colorize('bgblack', string, auto=auto)


def delete_paragraph(paragraph):
    """Delete a paragraph."""
    p = paragraph._p
    parent_element = p.getparent()
    parent_element.remove(p)


def CheckSDSSString(theString):
    """Simple function to vet strings containing SDSS field specifications:
	"run rerun camcol field" or "run,rerun,camcol,field" for DR7;
	"run camcol field" or "run,camcol,field" for DR12. Also, camcol must
	be between 1 and 6.

	Returns 1 for valid DR7 field specification, 2 for valid DR12 specification,
	or 0 for bad field specification.
	"""
    pps = theString.split()
    ppc = theString.split(',')
    if len(pps) in [3, 4]:
        pp = pps
    elif len(ppc) in [3, 4]:
        pp = ppc
    else:
        return 0
    try:
        for p in pp:
            testv = int(p)
            if testv < 0:
                return 0
    except ValueError:
        return 0
    if len(pp) == 3:
        camcol = int(pp[1])
        fieldType = 2
    else:
        camcol = int(pp[2])
        fieldType = 1
    if camcol > 6 or camcol < 1:
        return 0
    return fieldType


def cmd_default(scope, samba, args):
    """Sets VARIABLE to VALUE but only if VARIABLE isn't defined already.

    """
    varname = args[0]
    val = args[1]
    if varname in scope:
        return
    scope[varname] = val


@classmethod
def check_token(cls, db, token):
    """Check if a token is acceptable"""
    if len(token) < cls.min_length:
        raise ValueError('Tokens must be at least %i characters, got %r' %
            (cls.min_length, token))
    found = cls.find(db, token)
    if found:
        raise ValueError('Collision on token: %s...' % token[:cls.
            prefix_length])


def find_keywords_in_section(hdr, title):
    """ Return a list of keyword names from hdr identified in the section
        with the specified section title.
    """
    sect_start = None
    sect_end = None
    for i, kw in enumerate(hdr.cards):
        if sect_start is None:
            if title in str(hdr[i]):
                sect_start = i
        elif '/' in str(hdr[i]) and hdr[i] not in ['N/A', ' ', '']:
            sect_end = i
            break
    if sect_end is None:
        sect_end = len(hdr)
    if sect_start is None:
        return None
    section_keys = list(hdr[sect_start + 1:sect_end - 1].keys())
    while section_keys.count('') > 0:
        section_keys.remove('')
    return section_keys


def gpib_control_atn(library, session, mode):
    """Specifies the state of the ATN line and the local active controller state.

    Corresponds to viGpibControlATN function of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param mode: Specifies the state of the ATN line and optionally the local active controller state.
                 (Constants.GPIB_ATN*)
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    return library.viGpibControlATN(session, mode)


def detectEolString(text):
    """Detects the eol string using the first split. It cannot detect a mix"""
    if len(text.split('\r\n', 1)) == 2:
        return '\r\n'
    if len(text.split('\r', 1)) == 2:
        return '\r'
    return '\n'


def marginal_word_distrib(topic_word_distrib, p_t):
    """
    Return the marginal word distribution ``p(w)`` (term proportions derived from topic model) given the
    topic-word distribution (phi) `topic_word_distrib` and the marginal topic distribution ``p(T)`` `p_t`.
    The latter can be calculated with :func:`~tmtoolkit.topicmod.model_stats.marginal_topic_distrib`.

    :param topic_word_distrib: topic-word distribution; shape KxM, where K is number of topics, M is vocabulary size
    :param p_t: marginal topic distribution; array of size K
    :return: array of size M (vocabulary size) with marginal word distribution
    """
    return (topic_word_distrib.T * p_t).sum(axis=1)


@classmethod
def get_active_clients(cls, store):
    """Return a list of active clients.
        An active client is a person who are authorized to make new sales
        """
    return store.find(cls, cls.status != cls.STATUS_INACTIVE)


def ModifyNodeStorageUnits(r, node, storage_type, name, allocatable=None):
    """
    Modifies parameters of storage units on the node.

    @type node: str
    @param node: node whose storage units to modify
    @type storage_type: str
    @param storage_type: storage type whose units to modify
    @type name: str
    @param name: name of the storage unit
    @type allocatable: bool or None
    @param allocatable: Whether to set the "allocatable" flag on the storage
                                            unit (None=no modification, True=set, False=unset)

    @rtype: int
    @return: job id
    """
    query = {'storage_type': storage_type, 'name': name}
    if allocatable is not None:
        query['allocatable'] = allocatable
    return r.request('put', '/2/nodes/%s/storage/modify' % node, query=query)


def format_index_array_attrs(series):
    """Format metadata attributes for and indexed array

    This function is used to provide the necessary metadata to meet
    the (proposed) LIGO Common Data Format specification for series data
    in HDF5.
    """
    attrs = {}
    for i, axis in zip(range(series.ndim), ('x', 'y')):
        unit = '{}unit'.format(axis)
        origin = '{}0'.format(axis)
        delta = 'd{}'.format(axis)
        aunit = getattr(series, unit)
        attrs.update({unit: str(aunit), origin: getattr(series, origin).to(
            aunit).value, delta: getattr(series, delta).to(aunit).value})
    return attrs


def pFloat(number='0.0'):
    """
	portable float converter
	"""
    from django.conf import settings
    if settings.DATABASE_ENGINE == 'sqlite3':
        number = float(number)
    else:
        from decimal import Decimal
        number = Decimal(str(number))
    return number


def ceil_div(a, b):
    """Return ceil(a / b) without performing any floating-point operations."""
    if not isinstance(a, int) or not isinstance(b, int):
        raise TypeError('unsupported operand type(s): %r and %r' % (type(a)
            .__name__, type(b).__name__))
    q, r = divmod(a, b)
    if r:
        return q + 1
    else:
        return q


def sequence(context, data):
    """Generate a sequence of numbers.

    It is the memorious equivalent of the xrange function, accepting the
    ``start``, ``stop`` and ``step`` parameters.

    This can run in two ways:
    * As a single function generating all numbers in the given range.
    * Recursively, generating numbers one by one with an optional ``delay``.

    The latter mode is useful in order to generate very large sequences
    without completely clogging up the user queue.

    If an optional ``tag`` is given, each number will be emitted only once
    across multiple runs of the crawler.
    """
    number = data.get('number', context.params.get('start', 1))
    stop = context.params.get('stop')
    step = context.params.get('step', 1)
    delay = context.params.get('delay')
    prefix = context.params.get('tag')
    while True:
        tag = None if prefix is None else '%s:%s' % (prefix, number)
        if tag is None or not context.check_tag(tag):
            data['number'] = number
            context.emit(data=data)
        if tag is not None:
            context.set_tag(tag, True)
        number = number + step
        if step > 0 and number >= stop:
            break
        if step < 0 and number <= stop:
            break
        if delay is not None:
            data['number'] = number
            context.recurse(data=data, delay=delay)
            break


def valuesname(name):
    """ 'NValues' -> 'n' """
    assert name.startswith('System`'), name
    if name == 'System`Messages':
        return 'messages'
    else:
        return name[7:-6].lower()


def readtab(fi, ty):
    """Reads a line from file with a space separated list
       of items of type ty

    :param file: input stream, for example sys.stdin
    :param ty: a type, for example int
    :returns: a tuple with elements of type ty
    """
    return tuple(map(ty, fi.readline().split()))


def test_zoo(archive, compression, cmd, verbosity, interactive):
    """Test a ZOO archive."""
    return [cmd, '-test', archive]


@classmethod
def from_lmax_linear(NmtBin, lmax, nlb, is_Dell=False):
    """
        Convenience constructor for generic linear binning.

        :param int lmax: integer value corresponding to the maximum             multipole used by these bandpowers.
        :param int nlb: integer value corresponding to a constant             bandpower width. I.e. the bandpowers will be defined as             consecutive sets of nlb multipoles from l=2 to l=lmax             with equal weights.
        :param boolean is_Dell: if True, the output of all pseudo-Cl             computations carried out using this bandpower scheme (e.g.             from :py:meth:`pymaster.workspaces.NmtWorkspace.decouple_cell`)             will be multiplied by `ell * (ell + 1) / 2 * PI`, where `ell`             is the multipole order (no prefactor otherwise).
        """
    return NmtBin(lmax=lmax, nlb=nlb, is_Dell=is_Dell)


def psi_K_Cl_HCO3_HMW84(T, P):
    """c-a-a': potassium chloride bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


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

        :param RevokeDesktopClientArg val:
        :rtype: RevokeDeviceSessionArg
        """
    return cls('desktop_client', val)


@classmethod
def overlapping(cls, spanA, spanB):
    """ Return whether two spans overlap. """
    return spanB.start <= spanA.start and spanB.end >= spanA.end


@staticmethod
def forward(ctx, *inputs):
    """ We manually put max_norm to the end of tensor inputs in order to please Function.apply """
    ctx._max_norm = inputs[-1].item()
    return inputs[:-1]


def p_list(p):
    """list : identifier type
			| list "," identifier type"""
    if len(p) == 3:
        p[0] = [{'name': p[1], 'type': p[2]}]
    elif isinstance(p[1], list):
        p[1].append({'name': p[3], 'type': p[4]})
        p[0] = p[1]
    else:
        p[0] = None


def flush_and_delete_basket(basket, using=None):
    """Delete basket and all lines"""
    basket.flush()
    basket.delete(using)


@classmethod
def _decode(cls, packet, key_handler):
    """Decode a version 01 SSH certificate"""
    _ = packet.get_string()
    key_params = key_handler.decode_ssh_public(packet)
    serial = packet.get_uint64()
    cert_type = packet.get_uint32()
    key_id = packet.get_string()
    principals = packet.get_string()
    valid_after = packet.get_uint64()
    valid_before = packet.get_uint64()
    options = packet.get_string()
    extensions = packet.get_string()
    _ = packet.get_string()
    return (key_params, serial, cert_type, key_id, principals, valid_after,
        valid_before, options, extensions)


def GetSlotGlobal(*args, **kwargs):
    """ Stub Anduin function."""
    print('GetSlotGlobal', args, kwargs)


def remove_position(p, name):
    """Remove a position from a portfolio by name.

    Parameters
    ----------
    p : alphapy.Portfolio
        Portfolio with the current position.
    name : int
        Unique identifier for the position, e.g., a stock symbol.

    Returns
    -------
    p : alphapy.Portfolio
        Portfolio with the deleted position.

    """
    del p.positions[name]
    return p


def intervalOverlapCheck(interval, cmprInterval, percentThreshold=0,
    timeThreshold=0, boundaryInclusive=False):
    """
    Checks whether two intervals overlap

    If percentThreshold is greater than 0, then if the intervals overlap, they
        must overlap by at least this threshold

    If timeThreshold is greater than 0, then if the intervals overlap, they
        must overlap by at least this threshold

    If boundaryInclusive is true, then two intervals are considered to overlap
        if they share a boundary
    """
    startTime, endTime = interval[:2]
    cmprStartTime, cmprEndTime = cmprInterval[:2]
    overlapTime = max(0, min(endTime, cmprEndTime) - max(startTime,
        cmprStartTime))
    overlapFlag = overlapTime > 0
    boundaryOverlapFlag = False
    if boundaryInclusive:
        boundaryOverlapFlag = (startTime == cmprEndTime or endTime ==
            cmprStartTime)
    percentOverlapFlag = False
    if percentThreshold > 0 and overlapFlag:
        totalTime = max(endTime, cmprEndTime) - min(startTime, cmprStartTime)
        percentOverlap = overlapTime / float(totalTime)
        percentOverlapFlag = percentOverlap >= percentThreshold
    timeOverlapFlag = False
    if timeThreshold > 0 and overlapFlag:
        timeOverlapFlag = overlapTime > timeThreshold
    overlapFlag = (overlapFlag or boundaryOverlapFlag or percentOverlapFlag or
        timeOverlapFlag)
    return overlapFlag


def zip_aligned(*args):
    """
    Similar to the zip built-in, but raises an ValueError if one sequence
    terminates before the others.
    """
    args = map(iter, args)
    yield from zip(*args)
    for idx, it in enumerate(args):
        try:
            next(it)
        except StopIteration:
            pass
        else:
            raise ValueError('the %s-th iterator is still running' % idx)


@classmethod
def _changes_are_easy(cls, event, series_data, date_data):
    """Returns True if the changes we want to make to event are easy to
        perform.

        Hard changes include changes to how the recurrence behaves and in start
        and end dates.

        :param event: The event we want to update.
        :type event: :class:`Event`.
        :param dict series_data: The desired recurrence behavior.
        :param dict date_data: The desired date for the event.
        """
    for k, v in series_data.iteritems():
        if getattr(event.parent_series, k) != v:
            return False
    for k, v in date_data.iteritems():
        if getattr(event, k) != v:
            return False
    return True


def quadratic_interpolate_peak(left, middle, right):
    """ Interpolate the peak and offset using a quadratic approximation

    Parameters
    ----------
    left : numpy array
        Values at a relative bin value of [-1]
    middle : numpy array
        Values at a relative bin value of [0]
    right : numpy array
        Values at a relative bin value of [1]

    Returns
    -------
    bin_offset : numpy array
        Array of bins offsets, each in the range [-1/2, 1/2]
    peak_values : numpy array
        Array of the estimated peak values at the interpolated offset
    """
    bin_offset = 1.0 / 2.0 * (left - right) / (left - 2 * middle + right)
    peak_value = middle + 0.25 * (left - right) * bin_offset
    return bin_offset, peak_value


def ndof_orbit():
    """Orbit the view using the 3D mouse

    """
    pass


def reindex_df_so_selected_cols_are_first(df, selected_cols, raise_error=True):
    """ Reindex DataFrame so that selected columns are displayed first (on the left)

    Parameters
    ----------
    df : pandas DataFrame
        Pandas 2D DataFrame with unique columns
    selected_cols : list
        List of strings representing the column names to place first

    Returns
    -------
    df : pandas DataFrame
        Original DataFrame with altered column order
    """
    col_list_orig = list(df.columns)
    for col in selected_cols:
        if col in col_list_orig:
            col_list_orig.remove(col)
        elif raise_error == True:
            raise ValueError(
                """

Error, reindex_df_so_selected_cols_are_first, '%s' not in columns"""
                 % col)
        else:
            print(
                "\n\nError, reindex_df_so_selected_cols_are_first, '%s' not in columns"
                 % col)
    col_list_final = selected_cols + col_list_orig
    return df.reindex(columns=col_list_final)


def copy_node(node):
    """Makes a copy of a node with the same attributes and text, but no children."""
    element = node.makeelement(node.tag)
    element.text = node.text
    element.tail = node.tail
    for key, value in node.items():
        element.set(key, value)
    return element


@classmethod
def compare(cls, old, updated):
    """
        Initiates a Diffbuilder instance and returns a cleaned up diff.

        Args:
            old(str): Original string.
            updated(str): Updated string.

        Returns:
            str: Cleaned up representation of a diff.
        """
    return cls(old, updated).diff


def CDL3WHITESOLDIERS(df):
    """
    Three Advancing White Soldiers
    """


def link_viewer():
    """Link to viewer node

    """
    pass


def events2person(df, agg):
    """
    make person level data based on event data

    icd: cat [icdmain, icdbi]
    age: min age
    ibd: k50 or k51 in icd
    """
    pass


def countArrayElements(array):
    """
        Simple method to count the repetitions of elements in an array

        @param array: An array of elements
        @return: A tuple (elements,counters), where elements is a list with the distinct elements and counters is the list with the number of times they appear in the array
    """
    elements = []
    counters = []
    for element in array:
        if element in elements:
            indx = elements.index(element)
            counters[indx] += 1
        else:
            elements.append(element)
            counters.append(1)
    return elements, counters


def get_share_hashes():
    """
        @return: ListOf(TupleOf(int, Hash))
        """


def div_ceil(n, d):
    """returns the ceiling of n divided by d as an int"""
    return n // d + (1 if n % d != 0 else 0)


def to_json(object):
    """
    Return a JSON serialization of an object.
    Standard types (None, bool, int, float, str, etc.) are using
    json.dumps whereas other type of object must define a to_json
    method returning the serialization.
    """
    serializer = getattr(object, 'to_json', None)
    if serializer is None:
        if object is None:
            return None
        raise ValueError('Cannot serialize in JSON object of type {0}'.
            format(type(object)))
    else:
        return serializer()


def get_examiner_users_in_group(group):
    """
    Fetches all Examiner-users in group.

    Args:
        group: ``AssignmentGroup``.

    Returns:
        QuerySet: QuerySet of ``User``-objects.
    """
    from django.contrib.auth import get_user_model
    user_queryset = get_user_model().objects.filter(id__in=group.examiners.
        values_list('relatedexaminer__user', flat=True))
    return user_queryset


def parse_list_attr(tree, name):
    """
    Parse a list attribute
    Return an empty list if the attribute is not found
    """
    res = tree.get(name, '')
    return res.split()


def _get_endian_str(endian):
    """
    DM4 header encodes little endian as byte value 1 in the header
    :return: 'big' or 'little' for use with python's int.frombytes function
    """
    if isinstance(endian, str):
        return endian
    assert isinstance(endian, int)
    if endian == 1:
        return 'little'
    return 'big'


def unscale_action(action_space, scaled_action):
    """
    Rescale the action from [-1, 1] to [low, high]
    (no need for symmetric action space)

    :param action_space: (gym.spaces.box.Box)
    :param action: (np.ndarray)
    :return: (np.ndarray)
    """
    low, high = action_space.low, action_space.high
    return low + 0.5 * (scaled_action + 1.0) * (high - low)


def reduce_func(nodes):
    """Collect messages and update node representations.

    Parameters
    ----------
    nodes : NodeBatch
        A batch of nodes.

    Returns
    -------
    dict mapping 'hv_new' to Float32 tensor of shape (V, K * T)
        Updated node representations. V for the number of nodes, K for the number of
        radial filters and T for the number of features to use
        (types of atomic number in the paper).
    """
    return {'hv_new': nodes.mailbox['m'].sum(1)}


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


@staticmethod
def serialize(data):
    """
        Let's prepare the data to writing it in NoSQL store. By default it returns data
        without any changes.

        :param data: input data
        :returns: data ready to be written in NoSQL store.
        """
    return data


def nodes(G):
    """Return a copy of the graph nodes in a list."""
    return G.nodes()


def make_file(data, file_name=None):
    """
    Stores config data into the file
    :param data: config data to store
    :param file_name: config file name
    """
    file_name = file_name or 'conf.ini'
    if len(file_name.split('.')) < 2:
        file_name = '{file_name}.ini'.format(file_name=file_name)
    with open(file_name, mode='w+') as f:
        for section, section_val in data.items():
            f.write('[{section_name}]\n'.format(section_name=section))
            for key, val in section_val.items():
                f.write('{key} = {val}\n'.format(key=key, val=val))
            f.write('\n')


def read_google_sheet_values(spreadsheets_resource, spreadsheet_id,
    sheet_name, sheet_range):
    """
    Return the values of the ranges of the sheet of a Google Sheets document.

    :param spreadsheets_resource: An object `googleapiclient.discovery.Resource`
        returned by the Google API client library.

    :param spreadsheet_id: Identification of a Google Sheet document.

    :param sheet_name: Name of a sheet in this Google Sheet document.

    :param sheet_range: String representation of the range to return
        values.

    :return: A list of a arrays (lists) of values.
    """
    sheet_range_values = spreadsheets_resource.values().get(spreadsheetId=
        spreadsheet_id, range=f'{sheet_name}!{sheet_range}').execute()
    range_values = sheet_range_values.get('values', [])
    return range_values


def lzf_length(raw_data):
    """ Get length of uncompressed data from a header of Compress::LZF
    output. Check Compress::LZF sources for the definition of this bit magic
        (namely, LZF.xs, decompress_sv)

    Args:
        raw_data (bytes): data compressed with Perl Compress::LZF

    Returns:
         Tuple[int, int]: (header_size, uncompressed_content_length) in bytes

    >>> lzf_length('\\xc4\\x9b')
    (2, 283)
    >>> lzf_length('\\xc3\\xa4')
    (2, 228)
    >>> lzf_length('\\xc3\\x8a')
    (2, 202)
    >>> lzf_length('\\xca\\x87')
    (2, 647)
    >>> lzf_length('\\xe1\\xaf\\xa9')
    (3, 7145)
    >>> lzf_length('\\xe0\\xa7\\x9c')
    (3, 2524)
    """
    if not raw_data:
        raise ValueError('LZF compressed data are missing header')
    lower = ord(raw_data[0])
    csize = len(raw_data)
    start = 1
    mask = 128
    while mask and csize > start and lower & mask:
        mask >>= 1 + (mask == 128)
        start += 1
    if not mask or csize < start:
        raise ValueError('LZF compressed data header is corrupted')
    usize = lower & mask - 1
    for i in range(1, start):
        usize = (usize << 6) + (ord(raw_data[i]) & 63)
    if not usize:
        raise ValueError('LZF compressed data header is corrupted')
    return start, usize


def atse_fieldMoveLeft(schema_id, schema_template, name, RESPONSE=None):
    """ move a field of a schemata to the left"""


def contains(iterable, value, from_index=None):
    """
    Returns true if the value is present in the iterable. Use from_index to start your search at a given index.

    Params: iterable, value
        iterable -> list, sequenece, set, dictionary, generator etc
        value -> Any element that is to be searched in the iterable

    IMP: This method is not lazy

    Examples:
    >>> _.contains([1, 2, 3], 3);
    >>> True
    """
    if from_index:
        for index, item in enumerate(iterable):
            if index > from_index and item == value:
                return True
        return False
    return value in iterable


def vector_from_points_xy(a, b):
    """
    Create a vector based on a start point a and end point b in the XY-plane.

    Parameters
    ----------
    a : sequence of float
        XY(Z) coordinates of a 2D or 3D point (Z will be ignored).
    b : sequence of float
        XY(Z) coordinates of a 2D or 3D point (Z will be ignored).

    Returns
    -------
    ab : tuple
        Resulting 3D vector in the XY-plane (Z = 0.0).

    Notes
    -----
    The result of this function is equal to ``subtract_vectors(b, a)``

    """
    return b[0] - a[0], b[1] - a[1], 0.0


@staticmethod
def _normalize_key(key):
    """If `key` is str, make lowercase and replace underscores with hyphens
        """
    if isinstance(key, str):
        return key.lower().replace('_', '-')


def timetz64_pack(timetup_tz, ql_pack=ql_pack, mktime64=mktime64):
    """
	Pack a time; offset from beginning of the day and timezone offset.

	Given a pair, ((seconds, microseconds), timezone_offset), pack it into its
	serialized form using a long long: "!ql".
	"""
    timetup, tz_offset = timetup_tz
    return ql_pack((mktime64(timetup), tz_offset))


def euler_characteristic_check(sphere, chi=2):
    """Checks the euler characteristic of a sphere

    If $f$ = number of faces, $e$ = number_of_edges and $v$ = number of
    vertices, the Euler formula says $f-e+v = 2$ for a mesh on a sphere. More
    generally, whether $f -e + v == \\chi$ where $\\chi$ is the Euler
    characteristic of the mesh.

    - Open chain (track) has $\\chi=1$
    - Closed chain (loop) has $\\chi=0$
    - Disk has $\\chi=1$
    - Sphere has $\\chi=2$
    - HemiSphere has $\\chi=1$

    Parameters
    ----------
    sphere : Sphere
        A Sphere instance with vertices, edges and faces attributes.
    chi : int, optional
       The Euler characteristic of the mesh to be checked

    Returns
    -------
    check : bool
       True if the mesh has Euler characteristic $\\chi$

    Examples
    --------
    >>> euler_characteristic_check(unit_octahedron)
    True
    >>> hemisphere = HemiSphere.from_sphere(unit_icosahedron)
    >>> euler_characteristic_check(hemisphere, chi=1)
    True

    """
    v = sphere.vertices.shape[0]
    e = sphere.edges.shape[0]
    f = sphere.faces.shape[0]
    return f - e + v == chi


def set_signal_handler(signum, handler, restart_syscall=True):
    """A wrapper for signal.signal that also calls siginterrupt(signum, False)
    on platforms that support that.

    :param restart_syscall: if set, allow syscalls interrupted by a signal to
        automatically restart (by calling `signal.siginterrupt(signum,
        False)`).  May be ignored if the feature is not available on this
        platform or Python version.
    """
    try:
        import signal
        siginterrupt = signal.siginterrupt
    except ImportError:
        return None
    except AttributeError:

        def siginterrupt(signum, flag):
            return None
    if restart_syscall:

        def sig_handler(*args):
            siginterrupt(signum, False)
            handler(*args)
    else:
        sig_handler = handler
    old_handler = signal.signal(signum, sig_handler)
    if restart_syscall:
        siginterrupt(signum, False)
    return old_handler


@classmethod
def from_module_dict(cls, environment, module_dict, globals):
    """Creates a template object from a module.  This is used by the
        module loader to create a template object.

        .. versionadded:: 2.4
        """
    return cls._from_namespace(environment, module_dict, globals)


@classmethod
def from_norm_at_gamma_1(cls, norm, p, gamma_min, gamma_max):
    """sets :math:`k_e` such that `norm` = :math:`n_e(\\gamma=1)`."""
    return cls(norm.to('cm-3'), p, gamma_min, gamma_max)


def is_image_visible(context, image, image_member_find, status=None):
    """Return True if the image is visible in this context."""
    if context.is_admin:
        return True
    if image['owner'] is None:
        return True
    if image['visibility'] in ['public', 'community']:
        return True
    if context.owner is not None:
        if context.owner == image['owner']:
            return True
        if 'shared' == image['visibility']:
            members = image_member_find(context, image_id=image['id'],
                member=context.owner, status=status)
            if members:
                return True
    return False


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


@classmethod
def from_buffer(cls, bfr, **kw):
    """ Factory to return a `PacketField` instance from a `CornuCopyBuffer`.

        This default implementation instantiates the instance from
        the value returned by `cls.value_from_buffer(bfr, **kw)`.
    """
    value = cls.value_from_buffer(bfr, **kw)
    return cls(value, **kw)


def delete_point():
    """Remove Paint Curve Point

    """
    pass


def _find_start(score_matrix, align_globally):
    """Return a list of starting points (score, (row, col)) (PRIVATE).

    Indicating every possible place to start the tracebacks.
    """
    nrows, ncols = len(score_matrix), len(score_matrix[0])
    if align_globally:
        starts = [(score_matrix[-1][-1], (nrows - 1, ncols - 1))]
    else:
        starts = []
        for row in range(nrows):
            for col in range(ncols):
                score = score_matrix[row][col]
                starts.append((score, (row, col)))
    return starts


def generateColumnName(variable, visit, instance):
    """Generate a column name for the given variable, visit and instance.

    :arg variable: Integer variable ID
    :arg visit:    Visit number
    :arg instance: Instance number
    """
    return '{}-{}.{}'.format(variable, visit, instance)


def extract_autoscaling_capacity(configuration, elastigroup_config):
    """
    This function will set the Spotinst capacity from the Senza AutoScaling settings.
    It will add a default capacity of 1 if none is present.
    The target capacity will be adjusted to be within the minimum and maximum boundaries
    If there's already a capacity section it will be left untouched
    """
    if 'capacity' in elastigroup_config:
        return
    auto_scaling = configuration.get('AutoScaling', None)
    target = 1
    minimum = 1
    maximum = 1
    if auto_scaling:
        minimum = int(auto_scaling.get('Minimum', minimum))
        maximum = int(auto_scaling.get('Maximum', maximum))
        target = min(max(minimum, int(auto_scaling.get('DesiredCapacity', 1
            ))), maximum)
    elastigroup_config['capacity'] = {'target': target, 'minimum': minimum,
        'maximum': maximum}


def compound_fwd_query(query, rel):
    """
    Create a compound forwards query that selects the
    destination nodes, which have source nodes within
    the subquery.

    :param query: The subquery.
    :param rel: The relation.
    """
    smt = 'SELECT dst FROM %s WHERE src IN (%s)'
    return smt % (rel, query), ()


@classmethod
def get_kinetic_energy_cutoff_wavefunctions(cls, calc, **kwargs):
    """Return kinetic energy cutoff for wavefunctions in eV."""
    from qe_tools.constants import ry_to_ev
    parameters = calc.inputs.parameters
    ecutwfc = None
    try:
        ecutwfc = parameters.get_dict()['SYSTEM']['ecutwfc']
    except KeyError:
        pass
    if ecutwfc is None:
        return None
    return ecutwfc * ry_to_ev


def _print_parsed_dependency(parsed_sents):
    """Prints one token per line and its head"""
    for sent in parsed_sents:
        print(sent.to_conll().encode('utf-8'))
        print()


def author_name():
    """
    Utility to compute logged in user name

    :returns: name of current user, ``str``
    """
    import getpass
    name = getpass.getuser()
    try:
        import pwd
        login = name
        name = pwd.getpwnam(login)[4]
        name = ''.join(name.split(','))
        if not name:
            name = login
    except:
        pass
    if type(name) == str:
        name = name.decode('utf-8')
    return name


def __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


@staticmethod
def get_attr_value(obj, attribute):
    """Return the value of the attribute if defined."""
    if hasattr(obj, attribute):
        return getattr(obj, attribute).value
    return None


def unquote_header_value(value, is_filename=False):
    """Unquotes a header value.  (Reversal of :func:`quote_header_value`).
    This does not use the real unquoting but what browsers are actually
    using for quoting.

    :param value: the header value to unquote.
    """
    if value and value[0] == value[-1] == '"':
        value = value[1:-1]
        if not is_filename or value[:2] != '\\\\':
            return value.replace('\\\\', '\\').replace('\\"', '"')
    return value


def header_toolbox():
    """Display header region toolbox

    """
    pass


@classmethod
def validate(cls, change_type):
    """Validate change type and raise ValueError if invalid"""
    if change_type not in cls.types:
        raise ValueError(
            "Invalid cli change type '%s'. Should be one of %s" % (
            change_type, str(cls.types)))


@staticmethod
def to_landscape(diagram):
    """ Convert a diagram to a landscape
            (b,d) -> (b, d-b)
        """
    diagram[:, (1)] -= diagram[:, (0)]
    return diagram


def rnd_char_del(string, configs):
    """
    Elimina un caracter de la palabra.

    :return: Arreglo con todas las posibles eliminaciones de letras para
    la palabra.
    """
    string_length = len(string)
    new_string_arr = []
    for i in range(0, string_length):
        string_as_list = list(string)
        del string_as_list[i]
        new_string = ''.join(string_as_list)
        new_string_arr.append(new_string)
    return new_string_arr


def read_hdr_file(path):
    """
    reads the hdr hyperpsectral image file
    Parameter:
    -----------------
    str: path of hdr file
    return:
    ---------------
    numpy array : hyperspectral; cube
    """
    import spectral.io.envi as envi
    img = envi.open(path)
    return img


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 remove_durations_in_chords(music_expr):
    """Remove the absolute durations within chord signs: < and >

    Args:
        music_expr (str): the music expression

    Returns:
        str: the same music expression but with the durations removed from within chords.
    """
    cleaned = ''
    in_chord = False
    in_timing = False
    for char in music_expr:
        if char == '<':
            in_chord = True
            cleaned += char
        elif char == '>':
            in_chord = False
            in_timing = False
            cleaned += char
        elif not in_chord:
            cleaned += char
        elif in_timing:
            if char.isalpha() or char == ' ':
                in_timing = False
                cleaned += char
        elif char.isdigit():
            in_timing = True
        else:
            cleaned += char
    return cleaned


@classmethod
def getInitialDisplayRange(cls):
    """This class method returns a tuple containing ``(low, high)``
        percentile values which are used to set the initial values for the
        :attr:`.ColourMapOpts.displayRange` and
        :attr:`.ColourMapOpts.clippingRange` properties. If the initial
        display range has not yet been set (via the
        :meth:`setInitialDisplayRange` method), ``None`` is returned.
        """
    try:
        return cls.__initialDisplayRange
    except AttributeError:
        return None


@classmethod
def copy(cls, pop):
    """ Copy an existing NeuralPop """
    new_pop = cls(parent=pop.parent, with_models=pop.has_models,
        meta_groups=pop.meta_groups)
    for name, group in pop.items():
        new_pop.create_group(group.ids, name, group.model, group.neuron_param)
        new_pop._syn_spec = pop.syn_spec
    return new_pop


def indent(s, size=4):
    """Indent a string with @size spaces"""
    return ' ' * size + ('\n' + ' ' * size).join(s.split('\n'))


def dash_number(number):
    """add dashes to a US phone number string without dashes"""
    if len(number) == 10:
        return '%s-%s-%s' % (number[:3], number[3:6], number[6:])
    elif len(number) == 11:
        return '%s-%s-%s-%s' % (number[0], number[1:4], number[4:7], number[7:]
            )
    else:
        raise Exception('invalid phone number, wrong length %d' % len(number))


@staticmethod
def get_main_window():
    """
        Returns Qt object that references to the main DCC window
        :return:
        """
    return None


def psi_Ca_Cl_SO4_HMW84(T, P):
    """c-a-a': calcium chloride sulfate [HMW84]."""
    psi = -0.018
    valid = T == 298.15
    return psi, valid


def _STRH_register(cpu, reg_op, mem_op):
    """
        STRH (register).

        :param reg_op: source register.
        :param mem_op: memory.
        """
    cpu._ldr_str_register(reg_op, mem_op, ldr=False, size=16)


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

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


@classmethod
def configure(cls, **kwargs):
    """ This function gets called with the per-provider configuration
        defined in onegov.yml. Authentication providers may optionally
        access these values.

        The return value is either a provider instance, or none if the
        provider is not available.

        """
    return cls()


def error_check_stats(predicted, reference, field=''):
    """
    Checks the arguments provided to the statistics functions for the
    target and Taylor diagrams. THe data is provided in the predicted
    field (PREDICTED) and the reference field (REFERENCE).

    If a dictionary is provided for PREDICTED or REFERENCE, then
    the name of the field must be supplied in FIELD.

    The function currently supports dictionaries, lists, and np.ndarray,
    types for the PREDICTED and REFERENCE variables.

    Input:
    PREDICTED : predicted field
    REFERENCE : reference field
    FIELD     : name of field to use in PREDICTED and REFERENCE dictionaries
                (optional)

    Output:
    None.

    Author: Peter A. Rochford
        Symplectic, LLC
        www.thesymplectic.com
        prochford@thesymplectic.com

    Created on June 12, 2018

    """
    from array import array
    import numbers
    import numpy as np
    import pandas as pd
    if isinstance(predicted, dict):
        if field == '':
            raise ValueError('FIELD argument not supplied.')
        if field in predicted:
            p = np.array(predicted[field], dtype=float)
        else:
            raise ValueError('Field is not in PREDICTED dictionary: ' + field)
    elif isinstance(predicted, list):
        p = np.array(predicted, dtype=float)
    elif isinstance(predicted, np.ndarray):
        p = predicted
    elif isinstance(predicted, pd.Series):
        p = predicted.values
    else:
        raise ValueError('PREDICTED argument must be a dictionary.')
    if isinstance(reference, dict):
        if field == '':
            raise ValueError('FIELD argument not supplied.')
        if field in reference:
            r = np.array(reference[field], dtype=float)
        else:
            raise ValueError('Field is not in REFERENCE dictionary: ' + field)
    elif isinstance(reference, list):
        r = np.array(reference, dtype=float)
    elif isinstance(reference, np.ndarray):
        r = reference
    elif isinstance(reference, pd.Series):
        r = reference.values
    else:
        raise ValueError('REFERENCE argument must be a dictionary.')
    if isinstance(p, array):
        p = np.array(p)
    if isinstance(p, numbers.Number):
        p = np.array(p, ndmin=1)
    if not isinstance(p, np.ndarray):
        raise ValueError('Argument PREDICTED does not contain a numeric array')
    if isinstance(r, array):
        r = np.array(p)
    if isinstance(r, numbers.Number):
        r = np.array(r, ndmin=1)
    if not isinstance(r, np.ndarray):
        raise ValueError('Argument REFERENCE does not contain a numeric array')
    pshape = np.shape(p)
    rshape = np.shape(r)
    if not np.array_equal(pshape, rshape):
        raise ValueError(
            'PREDICTED and REFERENCE fields have different shapes:\n' +
            'shape(predicted) = ' + str(pshape) + '\n' +
            'shape(reference) = ' + str(rshape))
    if not np.isfinite(p).all():
        raise ValueError('PREDICTED field has non-finite values')
    if not np.isfinite(r).all():
        raise ValueError('REFERENCE field has non-finite values')
    return p, r


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 native_type(cls):
    """ Return the native SqlAlchemy type """
    return cls.sqlalchemy_type


def n_m_to_ansi_j(n, m):
    """Convert (n,m) two term index to ANSI single term index."""
    return int((n * (n + 2) + m) / 2)


def pnt_version(ws, logger):
    """
    Function to check if PNT has the expected version
    PNT version is located at cell E2 on the excel input file
    """
    version = str(ws['E2'].value)
    if 'R-PNT-TEC-016-1/rev.3' not in version:
        logger.error(
            'La celda E2 del PNT no contiene la version R-PNT-TEC-016-1/rev.3')
        logger.error('La version del documento excel introducido es: ')
        logger.error(version)
        logger.error('Saliendo del programa...')
        exit(1)
    else:
        logger.info('Success reading version of registry')


@classmethod
def create_connection_manager(cls, store_host, store_port, credential, **kwargs
    ):
    """
        创建一个新的连接器，不同的 DriverImpl 会自动初始化各自的 ConnectionImpl

        NOTE: 由于设计的原因，connection的定义不够清析，如今 connection == connection_manager == connector
        :param store_host:
        :param store_port:
        :param credential:
        :type  credential: :class:`gddriver.models.Credential`
        :rtype: gddriver.base.Connection
        """
    return cls.connection_class(store_host, store_port, credential, **kwargs)


def compute_all_type_links(ltypes):
    """ Compute all links between the different data types.

    Args:
        ltypes: List of all types
    """
    nbtypes = len(ltypes)
    for i, tp in enumerate(ltypes):
        tp.id = i
    for tp1 in ltypes:
        tp1.kind_of_types = tuple(map(lambda tp2: tp2.base_type in tp1.
            higher_types, ltypes))
    for tp1 in ltypes:
        ctypes = [None] * nbtypes
        for tp2 in ltypes:
            ct = tp1._compute_common_type(tp2)
            if ct is not None:
                ctypes[tp2.id] = ct
        tp1.common_types = tuple(ctypes)


def psi_Ca_Na_Cl_HMW84(T, P):
    """c-c'-a: calcium sodium chloride [HMW84]."""
    psi = -0.007
    valid = T == 298.15
    return psi, valid


def hash_password(plaintext_password=''):
    """
    Create a password hash from a given string for protecting a worksheet
    only. This will not work for encrypting a workbook.

    This method is based on the algorithm provided by
    Daniel Rentz of OpenOffice and the PEAR package
    Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>.
    See also http://blogs.msdn.com/b/ericwhite/archive/2008/02/23/the-legacy-hashing-algorithm-in-open-xml.aspx
    """
    password = 0
    for idx, char in enumerate(plaintext_password, 1):
        value = ord(char) << idx
        rotated_bits = value >> 15
        value &= 32767
        password ^= value | rotated_bits
    password ^= len(plaintext_password)
    password ^= 52811
    return str(hex(password)).upper()[2:]


def id2z(pid):
    """
    Given a nucleus ID (2006 PDG standard), returns the charge number.

    :param pid: nucleus ID
    :return: charge number
    """
    return pid % 1000000000 // 10000


@classmethod
def extra_table_metadata(cls, database, table_name, schema_name):
    """Returns engine-specific table metadata"""
    return {}


def get_cache(namespace, **options):
    """Return a beaker cache for this namespace, constructed with
        the given options if it didn't exists.
        """


def find_delete_index(value=None, headers=None):
    """Find index of action value in a list"""
    for index, val in enumerate(headers):
        if val == value:
            yield index


def valid_str(x: str) ->bool:
    """
    Return ``True`` if ``x`` is a non-blank string;
    otherwise return ``False``.
    """
    if isinstance(x, str) and x.strip():
        return True
    else:
        return False


@classmethod
def get_meta_var_key_attribute(cls, nsmap):
    """Helper method to get the full name for meta:name attribute."""
    return '{{{}}}{}'.format(nsmap[cls.META_VAR_TAG_NS], cls.
        META_VAR_KEY_ATTRIBUTE)


def _grid(x):
    """Access the underlying ndarray of a Grid object or return the object itself"""
    try:
        return x.grid
    except AttributeError:
        return x


def list_state_machines(maxResults=None, nextToken=None):
    """
    Lists the existing state machines. The results may be split into multiple pages. To retrieve subsequent pages, make the call again using the nextToken returned by the previous call.
    See also: AWS API Documentation

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

    :type maxResults: integer
    :param maxResults: The maximum number of results that will be returned per call. nextToken can be used to obtain further pages of results. The default is 100 and the maximum allowed page size is 1000.
            This is an upper limit only; the actual number of results returned per call may be fewer than the specified maximum.

    :type nextToken: string
    :param nextToken: If a nextToken was returned by a previous call, there are more results available. To retrieve the next page of results, make the call again using the returned token in nextToken . Keep all other arguments unchanged.
            The configured maxResults determines how many results can be returned in a single call.

    :rtype: dict
    :return: {
        'stateMachines': [
            {
                'stateMachineArn': 'string',
                'name': 'string',
                'creationDate': datetime(2015, 1, 1)
            },
        ],
        'nextToken': 'string'
    }

    """
    pass


def isLimitExceed(NFA0Delta, NFA1Delta):
    """Decide if the size of NFA0 and NFA1 exceed the limit.

    Size of NFA0 is denoted as N, and size of NFA1 is denoted as M. If N*N*M exceeds 1000000, return False,
    else return True. If bothNFA is False, then NFA0 should be NFA, and NFA1 should be Transducer. If both NFA is
    True, then NFA0 and NFA1 are both NFAs.

    :param dict NFA0Delta: NFA0's transition Delta
    :param dict NFA1Delta: NFA1's transition Delta
    :rtype: bool"""
    N = 0
    for s in list(NFA0Delta.keys()):
        for s1 in NFA0Delta[s]:
            N += len(NFA0Delta[s][s1])
    M = 0
    for s in list(NFA1Delta.keys()):
        for s1 in NFA1Delta[s]:
            M += len(NFA1Delta[s][s1])
    if N * N * M > 1000000:
        return True
    else:
        return False


@classmethod
def from_dict(cls, view_dict):
    """Create a view from a dictionary in the following format.

        .. code-block:: python

            {
            'type': 'View',
            'identifier': str,  # View identifier
            "display_name": str,  # View display name
            'position': [],  # list with position value
            'direction': [],  # list with direction value
            'up_vector': [],  # list with up_vector value
            'h_size': number,  # h_size.value
            'v_size': number,  # v_size value
            'shift': number,  # shift value
            'lift': number,  # lift value
            'view_type': number,  # view_type value
            'fore_clip': number,  # fore_clip value
            'aft_clip': number  # aft_clip value
            }
        """
    assert view_dict['type'
        ] == 'View', 'Expected View dictionary. Got {}.'.format(view_dict[
        'type'])
    view = cls(identifier=view_dict['identifier'], position=view_dict[
        'position'], direction=view_dict['direction'], up_vector=view_dict[
        'up_vector'], h_size=view_dict['h_size'], v_size=view_dict['v_size'
        ], shift=view_dict['shift'], lift=view_dict['lift'])
    view.fore_clip = view_dict['fore_clip']
    view.aft_clip = view_dict['aft_clip']
    if 'display_name' in view_dict and view_dict['display_name'] is not None:
        view.display_name = view_dict['display_name']
    return view


def _replace_escaped_unicode(match: 'Match') ->str:
    """
    Replaces escaped unicode to their unicode character.
    :param match: matched escaped unicode
    :type match: Match
    :return: unicode character
    :rtype: str
    """
    return match.group(0).encode('utf-8').decode('unicode_escape')


def SET_INTERSECTION(*expressions):
    """
    Takes two or more arrays and returns an array that contains the elements that appear in every input array.
    https://docs.mongodb.com/manual/reference/operator/aggregation/setIntersection/
    for more details
    :param expressions: The arrays (expressions)
    :return: Aggregation operator
    """
    return {'$setIntersection': list(expressions)}


def list_types_sync(api, instance='', **params):
    """List all the groups types of an instance. If no instance is provided , fetch the platform types

    Args:
        api: the ApiClient instance to use for requests
        instance: the instance id
        ``**params``: optional  dictionary of search parameters as defined in https://api.lumapps.com/docs/feedtype/list

    Returns:
        list of Lumapps Feed resourcess
    """
    if not params:
        params = dict()
    if instance != '':
        params['instance'] = instance
    result = api.get_call('feedtype', 'list', **params)
    return result


def dict_has_all_keys(dct, *keys):
    """Determines if a dict contains all of the given keys.
    Returns True if all keys are contained in dict, False otherwise.
    """
    for key in keys:
        if key not in dct:
            return False
    return True


def linear(x):
    """Linear activation function :math:`\\varphi(x) = x`

    Parameters
    ----------
    x : float32
        The activation (the summed, weighted input of a neuron).

    Returns
    -------
    float32
        The output of the identity applied to the activation.
    """
    return x


def processExited(reason):
    """
        Called when the child process exits.

        @type reason: L{twisted.python.failure.Failure}
        @param reason: A failure giving the reason the child process
            terminated.  The type of exception for this failure is either
            L{twisted.internet.error.ProcessDone} or
            L{twisted.internet.error.ProcessTerminated}.

        @since: 8.2
        """


def get_meta(df):
    """
    Return the metadata from a single dataframe
    :param df: cudf.dataframe
    :return: Row data from the first row of the dataframe
    """
    ret = df.iloc[:0]
    return ret


def get_tl_num_size(val: int) ->int:
    """
    Calculate the length of a TL variable.

    :param val: an integer standing for Type or Length.
    :return: The length of var.
    """
    if val <= 252:
        return 1
    elif val <= 65535:
        return 3
    elif val <= 4294967295:
        return 5
    else:
        return 9


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


def provider_parser(subparser):
    """Configure a provider parser for Hetzner"""
    subparser.add_argument('--auth-token', help='Specify Hetzner DNS API token'
        )


def set_default_region(region: str):
    """
    Initializes all library clients based on the specified region.  The library clients
    are AWS API clients that give us access to AWS.  Note that if you set the region with
    **aws configure**, that will take precedence.

    :param region: The region that all library clients will be opened with.
    :return: No return value.
    """
    global _region
    _region = region


def create_temporary_directory(prefix_dir=None):
    """Creates a temporary directory and returns its location"""
    from tempfile import mkdtemp
    return mkdtemp(prefix='bloom_', dir=prefix_dir)


def _count_elements(mapping, iterable):
    """Tally elements from the iterable."""
    mapping_get = mapping.get
    for elem in iterable:
        mapping[elem] = mapping_get(elem, 0) + 1


def parse_requirements_fname(dep_name):
    """Parse requirements file path from dependency declaration (-r<filepath>).

    >>> parse_requirements_fname('pep8')
    >>> parse_requirements_fname('-rrequirements.txt')
    'requirements.txt'

    :param dep_name: Name of the dependency
    :return: Requirements file path specified in the dependency declaration
        if specified otherwise None
    :rtype: str or None
    """
    req_option = '-r'
    if dep_name.startswith(req_option):
        return dep_name[len(req_option):]


@classmethod
def write_str(cls, opc_sync: bool, total_size: int, context: str
    ) ->'IoTransferEventArgs':
    """Creates new IoTransferEventArgs of write string

		:param opc_sync: defines if the command is OPC-synchronised
		:param total_size: size of the data to write
		:param context: SCPI command write. It is truncated to maximum of 100 characters.
		:return: IoTransferEventArgs object of a write string operation."""
    obj = cls(False, opc_sync, total_size, context)
    obj.binary = False
    return obj


def extract_aaf(var):
    """
    Extract the AAF directly from the INFO field.
    """
    return var.INFO.get('AF')


def _convert_to_utf8(data_dict, binary=False):
    """
    Convert keys and values to unicode. If binary is flagged then only keys are
    converted.
    """
    item = {}
    for k, v in data_dict.items():
        k = str(k, 'utf8')
        if not binary:
            try:
                v = str(v, 'utf8', errors='ignore')
            except TypeError:
                v = str(v)
        item[k] = v
    return item


def process_soa(data, template):
    """
    Replace {SOA} in template with a set of serialized SOA records
    """
    record = template[:]
    if data is not None:
        assert len(data) == 1, 'Only support one SOA RR at this time'
        data = data[0]
        soadat = []
        domain_fields = ['mname', 'rname']
        param_fields = ['serial', 'refresh', 'retry', 'expire', 'minimum']
        for f in (domain_fields + param_fields):
            assert f in data.keys(), "Missing '%s' (%s)" % (f, data)
        data_name = str(data.get('name', '@'))
        soadat.append(data_name)
        if data.get('ttl') is not None:
            soadat.append(str(data['ttl']))
        soadat.append('IN')
        soadat.append('SOA')
        for key in domain_fields:
            value = str(data[key])
            soadat.append(value)
        soadat.append('(')
        for key in param_fields:
            value = str(data[key])
            soadat.append(value)
        soadat.append(')')
        soa_txt = ' '.join(soadat)
        record = record.replace('{soa}', soa_txt)
    else:
        record = record.replace('{soa}', '')
    return record


def pixel_scale_interpolation_grid_tag_from_pixel_scale_interpolation_grid(
    pixel_scale_interpolation_grid):
    """Generate an interpolation pixel scale tag, to customize phase names based on the resolution of the interpolation     grid that deflection angles are computed on before interpolating to the and sub aa.

    This changes the phase name 'phase_name' as follows:

    pixel_scale_interpolation_grid = 1 -> phase_name
    pixel_scale_interpolation_grid = 2 -> phase_name_pixel_scale_interpolation_grid_2
    pixel_scale_interpolation_grid = 2 -> phase_name_pixel_scale_interpolation_grid_2
    """
    if pixel_scale_interpolation_grid is None:
        return ''
    return '__interp_{0:.3f}'.format(pixel_scale_interpolation_grid)


@staticmethod
def id_to_telid(eventio_id):
    """See io_hess.c, l. 2519"""
    return eventio_id & 255 | (eventio_id & 1056964608) >> 16


def is_array_sequence(obj):
    """ Return True if `obj` is an array sequence. """
    try:
        return obj.is_array_sequence
    except AttributeError:
        return False


@staticmethod
def p_named_arg_list(p):
    """
        named_arglist : named_arg
                      | named_arglist ',' named_arg
        """
    if len(p) == 2:
        p[0] = [p[1]]
    else:
        p[0] = p[1] + [p[3]]


def properties():
    """ Iterator over the changed properties (name, value)
        """


def mag_to_object_dist(efl, mag):
    """Compute the object distance for a given focal length and magnification.

    Parameters
    ----------
    efl : `float`
        focal length of the lens
    mag : `float`
        signed magnification

    Returns
    -------
    `float`
        object distance

    """
    return efl * (1 / mag + 1)


@classmethod
def from_string(cls, time_str):
    """Populate time components from time string of the format HH[:MM[:SS[.microseconds]]]"""
    parts = time_str.split(':')
    obj = cls()
    if len(parts) > 0:
        obj.hour = int(parts[0])
    if len(parts) > 1:
        obj.minute = int(parts[1])
    if len(parts) > 2:
        if '.' in parts[2]:
            second_parts = parts[2].split('.')
            obj.second = int(second_parts[0])
            obj.microsecond = int(second_parts[1])
        else:
            obj.second = int(parts[2])
    return obj


def _get_bw_summary(coords, annotation):
    """Return summary of BigWig scores in an interval
    """
    chrom, start, end = coords
    try:
        return annotation.summarize(str(chrom), start, end, end - start
            ).min_val[0]
    except AttributeError:
        return None


def indexof(coll, item, start=0, default=None):
    """Return the index of the item in the collection

    :param coll: iterable
    :param item: scalar
    :param start: (optional) The start index
    :default: The default value of the index if the item is not in the collection

    :returns: idx -- The index of the item in the collection

    >>> monties = ['Eric', 'John', 'Terry', 'Terry', 'Graham', 'Mickael']
    >>> indexof(monties, 'Terry')
    2

    >>> indexof(monties, 'Terry', start=3)
    3

    >>> indexof(monties, 'Terry', start=4) is None
    True

    """
    if item in coll[start:]:
        return list(coll).index(item, start)
    else:
        return default


@staticmethod
def first_order_score(y, mean, scale, shape, skewness):
    """ GAS Poisson Update term using gradient only - native Python function

        Parameters
        ----------
        y : float
            datapoint for the time series

        mean : float
            location parameter for the Poisson distribution

        scale : float
            scale parameter for the Poisson distribution

        shape : float
            tail thickness parameter for the Poisson distribution

        skewness : float
            skewness parameter for the Poisson distribution

        Returns
        ----------
        - Score of the Poisson family
        """
    return y - mean


def wavedec2_keys(level):
    """Subband keys corresponding to a wavedec2 decomposition."""
    approx = ''
    coeffs = {}
    for lev in range(level):
        for k in ['a', 'h', 'v', 'd']:
            coeffs[approx + k] = None
        approx = 'a' * (lev + 1)
        if lev < level - 1:
            coeffs.pop(approx)
    return list(coeffs.keys())


def __call__(*args, **kw):
    """Compute a response body"""


def convert_array(array, type_):
    """Convert all elements in array to <typ>"""
    for i in range(len(array)):
        for j in range(len(array[i])):
            array[i][j] = type_(array[i][j])


def _cmp(a, b):
    """ Implementation of ``cmp`` for Python 3
    """
    return (a > b) - (a < b)


def getdims(x=(10000, 200)):
    """
    return the dims for network
    """
    assert len(x) == 2
    n_sample = x[0]
    if n_sample > 20000:
        dims = [x[-1], 128, 32]
    elif n_sample > 10000:
        dims = [x[-1], 64, 32]
    elif n_sample > 5000:
        dims = [x[-1], 32, 16]
    elif n_sample > 2000:
        dims = [x[-1], 128]
    elif n_sample > 500:
        dims = [x[-1], 64]
    else:
        dims = [x[-1], 16]
    return dims


def partial_cross_section_nm2(beam_energy: float, energy_loss_start_eV:
    float, energy_loss_end_eV: float, convergence_angle: float,
    collection_angle: float, atomic_number: int, shell_number: int,
    subshell_index: int) ->float:
    """Returns the partial cross section.

    Uses generalized oscillator strength function.

    beam_energy is in eV.
    energy_start, energy_end are in eV.
    convergence_angle is in radians.
    collection_angle is in radians.

    The return value units are nm * nm.
    """
    pass


def get_world_to_view_matrix(mlab_scene):
    """returns the 4x4 matrix that is a concatenation of the modelview transform and
    perspective transform. Takes as input an mlab scene object.

    Parameters
    ----------
    mlab_scene : MayaviScene instance

    Returns
    -------
    np_comb_trans_mat : array-like
        Combined 4x4 transformation matrix for modelview and perspective transforms
    """
    from mayavi.core.ui.mayavi_scene import MayaviScene
    if not isinstance(mlab_scene, MayaviScene):
        raise TypeError('argument must be an instance of MayaviScene')
    scene_size = tuple(mlab_scene.get_size())
    clip_range = mlab_scene.camera.clipping_range
    aspect_ratio = float(scene_size[0]) / float(scene_size[1])
    vtk_comb_trans_mat = (mlab_scene.camera.
        get_composite_projection_transform_matrix(aspect_ratio, clip_range[
        0], clip_range[1]))
    np_comb_trans_mat = vtk_comb_trans_mat.to_array()
    return np_comb_trans_mat


def group_deselect():
    """Deselect bones of active Bone Group

    """
    pass


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

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


@classmethod
def get_default_handler_map(cls):
    """
        A class method that returns the default handler map.
        """
    return cls._default_handler_map


@classmethod
def _emit_failed(cls):
    """Print FAILED on error."""
    cls._emit_message('FAILED\n')


def assign_node_ids(t, suffix=''):
    """
    makes sure that a tree, and all its terminal
    and nonterminal nodes, have a suitable xml_id
    attribute.
    """
    if hasattr(t, 'xml_id'):
        sent_id = t.xml_id
    elif hasattr(t, 'sent_no'):
        sent_id = 's%s' % (t.sent_no,)
        if sent_id[:2] == 'ss':
            sent_id = sent_id[1:]
        t.xml_id = sent_id
    elif hasattr(t, 'sent_id'):
        sent_id = str(t.sent_id)
        t.xml_id = sent_id
    for i, n in enumerate(t.terminals):
        if not hasattr(n, 'xml_id'):
            n.xml_id = '%s_%s' % (sent_id, i + 1)
    node_id = 500
    for n in t.bottomup_enumeration():
        if n.isTerminal():
            continue
        if hasattr(n, 'xml_id'):
            continue
        n.xml_id = '%s_n%s%s' % (sent_id, node_id, suffix)
        node_id += 1


def teff(cluster):
    """
    Calculate Teff for main sequence stars ranging from Teff 3500K - 8000K. Use
    [Fe/H] of the cluster, if available.

    Returns a list of Teff values.
    """
    b_vs, _ = cluster.stars()
    teffs = []
    for b_v in b_vs:
        teffs.append(8575 - 5222.27 * b_v + 1380.92 * b_v ** 2 + 701.7 *
            b_v * (cluster.fe_h - 0.15))
    return teffs


def underline(line, underline='~'):
    """Return an underline string for ``line``.

    Intended for use with level 3 and lower headings.

    Note that the default for ``underline`` assumes that the level
    1 and 2 underlines are the standard ``=`` and ``-``. You can
    pass a different underline character to this function if needed.
    """
    if line.endswith('\n'):
        line = line[:-1]
    return '{}\n'.format(underline * len(line))


def escape_null(s: str) ->str:
    """Replaces each null character (\\0) in the input with \\\\0"""
    return s.replace('\x00', '\\0')


@classmethod
def atomic(cls):
    """Do the DB atomic bits."""
    return cls._meta.database.atomic()


def view(df, row=10, col=5):
    """Abbreviated view like `.head()`, but limit both rows & columns."""
    return df.iloc[:row, :col]


def distance_based_on_molecular_formula(metabolite1, metabolite2, normalize
    =True):
    """Calculate the distance of two metabolites bases on the molecular formula

    Parameters
    ----------
    metabolite1 : Metabolite
        The first metabolite.
    metabolite2 : Metabolite
        The second metabolite.
    normalize : bool, optional
        If the distance should be normalized by the total number of elements in both metabolites (defaults to True).

    Returns
    -------
    float
        The distance between metabolite1 and metabolite2.

    """
    if len(metabolite1.elements) == 0 or len(metabolite2.elements) == 0:
        raise ValueError(
            'Cannot calculate distance between metabolites %s and %s' % (
            metabolite1, metabolite2))
    elements = set(list(metabolite1.elements.keys()) + list(metabolite2.
        elements.keys()))
    distance = 0.0
    for element in elements:
        distance += abs(metabolite1.elements.get(element, 0) - metabolite2.
            elements.get(element, 0))
    if normalize:
        return distance / sum(list(metabolite1.elements.values()) + list(
            metabolite2.elements.values()))
    else:
        return distance


def describe_execution(executionArn=None):
    """
    Describes an execution.
    See also: AWS API Documentation

    :example: response = client.describe_execution(
        executionArn='string'
    )

    :type executionArn: string
    :param executionArn: [REQUIRED]
            The Amazon Resource Name (ARN) of the execution to describe.

    :rtype: dict
    :return: {
        'executionArn': 'string',
        'stateMachineArn': 'string',
        'name': 'string',
        'status': 'RUNNING'|'SUCCEEDED'|'FAILED'|'TIMED_OUT'|'ABORTED',
        'startDate': datetime(2015, 1, 1),
        'stopDate': datetime(2015, 1, 1),
        'input': 'string',
        'output': 'string'
    }

    """
    pass


def copied(object, original):
    """Send an :class:`~.IObjectCopiedEvent` for ``object``.

        ``original`` is the object the copy was created from.

        """


def subscript(cube, index, value):
    """Filter cube1 using the index and the value. Return a new cube without the index1 dimension
        Ex.
            cp.subscript(nodo_ejemplo,index_para_ejemplo,"Item 1")
    """
    return cube[index == value]


def golf():
    """
    Full factorial experiments to maximize a golfer's driving distance.

    A full factorial experiment with four factors run by a golf enthusiast. The
    objective of the experiments was for the golfer to maximize her driving distance
    at a specific tee off location on her local golf course. The golfer considered
    the following factors:

    H = Tee height (cm)
    N = Holes: number of golf balls played for prior to experimental tee shot
    C = Club type
    T = Time of day (on the 24 hour clock)

    The data are in standard order, however the actual experiments were run in
    random order.

    Coded values for H, N, C and T should be used in the linear regression
    model analysis, with -1 representing the low value and +1 the high value.

    Dimensions
    ----------
    A data frame containing 16 observations of 4 variables (H, N, C, T) and a
    column y, as a response variable.

    Source
    ------
    A MOOC on Design of Experiments: ``Experimentation for Improvement'',
    https://learnche.org

    Example
    -------
    """
    pass


@classmethod
def commit(cls):
    """
        Send all pending stuff toward knockdaemon UDP listener
        :return bool
        :rtype bool
        """
    return cls._internal_commit()


def peso_cubagem(largura, altura, profundidade):
    """
    Função para calculo de peso de cubagem. Caso o peso de cubagem for maior
    que o peso real, este é utilizado para calculo do frete.

    Exemplo: um Equipamento que pesa 27 Kg e tem as seguintes dimensões:
    72cm x 44cm x 62cm ficaria com:
    32.74Kg na modalidade Expresso e
    58.93Kg na modalidade Rodoviário

    >>> peso_cubagem(72, 44, 62)
    {'Cubagem Expresso': 32.736, 'Cubagem Rodoviario': 58.93069306930693}
    >>> cubagens = peso_cubagem(72, 44, 62)
    >>> cubagem_expresso = cubagens['Cubagem Expresso']
    >>> cubagem_expresso
    32.736

    :param largura: em centímetros
    :param altura: em centímetros
    :param profundidade: em centímetros
    :return: Retorna um dicionário com os pesos de cubagem.
    """
    peso_cubagem_expresso = largura * altura * profundidade / 6000
    peso_cubagem_rodoviario = largura * altura * profundidade / 3333
    return {'Cubagem Expresso': peso_cubagem_expresso, 'Cubagem Rodoviario':
        peso_cubagem_rodoviario}


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


@classmethod
def load(cls, fname):
    """

        Return a Map with tmx fname loaded and ready to use.

        :param fname:
        :return:
        """
    tile_map = super().load(fname)
    tile_map.update_objects_definitions()
    return tile_map


def returnExactMatch(wavecal_info, rootname):
    """Return the shift dictionary for the specified wavecal rootname.

    The rootname of a wavecal exposure is used to extract one element of
    wavecal_info (there should always be exactly one matching element).
    The shift dictionary from that matchine element is then returned.

    None will be returned if wavecal_info is empty.

    Parameters
    ----------
    wavecal_info: list of dictionaries
        List of wavecal information dictionaries

    rootname: str
        Used to find the appropriate element of wavecal_info

    Returns
    -------
    dictionary or None
        The shift dictionary corresponding to rootname, or None
    """
    if len(wavecal_info) < 1:
        return None
    for wc_dict in wavecal_info:
        if wc_dict['rootname'] == rootname:
            return wc_dict['shift_dict']
    raise RuntimeError('There should have been a matching element.')


def clean_input_reads(records):
    """Add a cleaned_seq attribute to records that do not have one

    Use this to convert a stream of records that might not have a
    `cleaned_seq` attribute to one that does. Use this to extend
    Records loaded by `screed.open()`. It is a mistake to apply
    this to a `ReadParser` stream.
    """
    for record in records:
        record.cleaned_seq = record.sequence.upper().replace('N', 'A')
        yield record


def local_pose_to_global_pose(pose1, pose2):
    """
    Applies the transform from pose1 to pose2
    :param pose1: instance of ``util.Pose``
    :param pose2: instance of ``util.Pose``
    """
    return pose1.transform().apply_to_pose(pose2)


def find_indices(lst, element):
    """ Returns the indices for all occurrences of 'element' in 'lst'.

    Args:
        lst (list): List to search.
        element:  Element to find.

    Returns:
        list: List of indices or values
    """
    result = []
    offset = -1
    while True:
        try:
            offset = lst.index(element, offset + 1)
        except ValueError:
            return result
        result.append(offset)


def _getMacroDependencyTrees(theMacroAdjList, theMacro):
    """Returns the dependency trees (parent/child, child/parent) for the macro.
    Can be None."""
    if theMacroAdjList.hasParent(theMacro.identifier):
        pcTree = theMacroAdjList.treeParentChild(theMacro.identifier)
    else:
        pcTree = None
    if theMacroAdjList.hasChild(theMacro.identifier):
        cpTree = theMacroAdjList.treeChildParent(theMacro.identifier)
    else:
        cpTree = None
    return pcTree, cpTree


@staticmethod
def get_description(v, item):
    """
        Return description of parameter.

        :param v: VOEvent xml
        :param item: single dictionary item from mapping
        :type v: lxml.objectify.ObjectifiedElement
        :type item: dict
        :returns: Description on parameter is applicable, else None
        :rtype: str, NoneType
        """
    param_group = item.get('param_group')
    param_name = item.get('param_name')
    try:
        note = v.find(".//Group[@name='{}']".format(param_group)).find(
            ".//Param[@name='{}']".format(param_name)).Description
        if note:
            return '[{}] {}'.format(param_name, note)
        else:
            return None
    except AttributeError:
        return None


@staticmethod
def _to_list(data):
    """Converts certain data types (str, unicode) into list.

        Args:
          data: data to convert

        Returns:
          list with converted data
        """
    types = [str]
    for data_type in types:
        if isinstance(data, data_type):
            return [data]
    return data


@classmethod
def get_by_owner_contact(cls, owner, contact):
    """Возвращает записи фильтрованные по владельцу и контакту."""
    return cls.query().filter_by(owner=owner, contact=contact).first()


def spnToLatex(spname):
    """
  Utilitiy function to convert species names to proper latex math strings.

  The returned string can directly be embedded in a latex $ $ statement.
  """
    name = str(spname)
    if str(spname) == 'HN2+':
        name = 'N2H+'
    if str(spname) == 'C18O':
        return 'C^{18}O'
    if str(spname) == '13CO':
        return '^{13}CO'
    if str(spname) == 'H13CO+':
        return 'H^{13}CO^+'
    newname = ''
    previous_char = None
    for c in name:
        if c.isdigit():
            newname += '_' + c
        elif c == '-' and not (previous_char == 'o' or previous_char == 'p'):
            newname += '^-'
        elif c == '+':
            newname += '^+'
        elif c == '#':
            newname += '\\#'
        else:
            newname += c
        previous_char = c
    if '_H' in newname:
        newname = newname.replace('_H', '\\_H')
    if '^+^+' in newname:
        newname = newname.replace('^+^+', '^{++}')
    return newname


def _w2f(word):
    """converts string word if possible to float"""
    try:
        return float(word)
    except (ValueError, TypeError):
        return word


@classmethod
def all_commands(cls):
    """Yield all of the commands except for OK, SBDRING, and READY, because they are responses.

        Note:
            The command value is yielded so SESSION yields b'AT+SBDIX'.
        """
    for name in dir(cls):
        if not name.startswith(b'_'
            ) and name != 'OK' and name != 'RING' and name != 'READY':
            yield getattr(cls, name)


def p_atom_list(t):
    """
    atom_list : atom_list ATOM
              | ATOM
    """
    if len(t) == 3:
        t[0] = t[1] + [t[2]]
    elif len(t) == 2:
        t[0] = [t[1]]
    else:
        assert False


def coerce_options(options, converters):
    """Convert some configuration options to expected types.

    To replace given options with the converted values
    in a dictionary you might do::

        conf.update(coerce_options(conf, {
            'debug': asbool,
            'serve_static': asbool,
            'auto_reload_templates': asbool
        }))
    """
    converted_options = {}
    for option, converter in converters.items():
        if option in options:
            converted_options[option] = converter(options[option])
    return converted_options


@classmethod
def keys(cls):
    """
        Returns all the keys for the given enum.

        Returns:
            all EnumSymbol keys for the given enum
        """
    return cls._registered.keys()


def Option(cls):
    """Shorthand description for a type allowing NoneType"""
    return cls + (type(None),) if isinstance(cls, tuple) else (cls, type(None))


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

        :param str val:
        :rtype: AddSecondaryEmailResult
        """
    return cls('already_pending', val)