def valid_tabulated_shape(width, height):
    """Return if the tabulated shape is valid.

    Validating that the strings `width` and `height` contain positive floats
    was previously done using a regex. However, experiments showed that
    trying to split the string and reading in the floats is much faster.

    :param width: string of widths
    :param height: string of heights
    :return: True if the shape if valid
    """
    if width is None or height is None:
        return False
    height_string_list = height.split(' ')
    width_string_list = width.split(' ')
    if len(height_string_list) != len(width_string_list):
        return False
    try:
        first_height = float(height_string_list[0])
        if first_height != 0:
            return False
    except ValueError:
        return False
    previous_height = -1
    for h_string, w_string in zip(height_string_list, width_string_list):
        try:
            h = float(h_string)
            w = float(w_string)
        except ValueError:
            return False
        if h < 0:
            return False
        if w < 0:
            return False
        if h < previous_height:
            return False
        previous_height = h
    return True


def make_tree(game_tree, root, node_builder, node_adder):
    """Construct a node tree from a Coarse_game_tree.

    game_tree    -- Coarse_game_tree
    root         -- node
    node_builder -- function taking parameters (parent node, property map)
                    returning a node
    node_adder   -- function taking a pair (parent node, child node)

    Builds a tree of nodes corresponding to this GameTree, calling
    node_builder() to make new nodes and node_adder() to add child nodes to
    their parent.

    Makes no further assumptions about the node type.

    """
    to_build = [(root, game_tree, 0)]
    while to_build:
        node, game_tree, index = to_build.pop()
        if index < len(game_tree.sequence) - 1:
            child = node_builder(node, game_tree.sequence[index + 1])
            node_adder(node, child)
            to_build.append((child, game_tree, index + 1))
        else:
            node._children = []
            for child_tree in game_tree.children:
                child = node_builder(node, child_tree.sequence[0])
                node_adder(node, child)
                to_build.append((child, child_tree, 0))


def iter_to_str(i):
    """Convert an iterable to a string contained single quoted elements.

    :type i: list
    :rtype: str
    """
    return ' '.join(map(lambda n: "'{}'".format(n), i))


def _bool_segments(array, start=0, delta=1, minlen=1):
    """Yield segments of consecutive `True` values in a boolean array

    Parameters
    ----------
    array : `iterable`
        An iterable of boolean-castable values.

    start : `float`
        The value of the first sample on the indexed axis
        (e.g.the GPS start time of the array).

    delta : `float`
        The step size on the indexed axis (e.g. sample duration).

    minlen : `int`, optional
        The minimum number of consecutive `True` values for a segment.

    Yields
    ------
    segment : `tuple`
        ``(start + i * delta, start + (i + n) * delta)`` for a sequence
        of ``n`` consecutive True values starting at position ``i``.

    Notes
    -----
    This method is adapted from original code written by Kipp Cannon and
    distributed under GPLv3.

    The datatype of the values returned will be the larger of the types
    of ``start`` and ``delta``.

    Examples
    --------
    >>> print(list(_bool_segments([0, 1, 0, 0, 0, 1, 1, 1, 0, 1]))
    [(1, 2), (5, 8), (9, 10)]
    >>> print(list(_bool_segments([0, 1, 0, 0, 0, 1, 1, 1, 0, 1]
    ...                           start=100., delta=0.1))
    [(100.1, 100.2), (100.5, 100.8), (100.9, 101.0)]
    """
    array = iter(array)
    i = 0
    while True:
        try:
            val = next(array)
        except StopIteration:
            return
        if val:
            n = 1
            try:
                while next(array):
                    n += 1
            except StopIteration:
                return
            finally:
                if n >= minlen:
                    yield start + i * delta, start + (i + n) * delta
            i += n
        i += 1


def load_map(file_name: str, map_name: str, num_levels: int=4, sigma: float=1.0
    ):
    """Loads an image map for further reading.

    :param file_name: The name of the image file.
    :type file_name: str
    :param map_name: The name that will be used to access this image.
    :type map_name: str
    :param num_levels: The number of levels in the map pyramid (default = 4). If num_levels == 0, the complete pyramid is built.
    :type num_levels: int
    :param sigma: The sigma value of the gaussian function.
    :type sigma: float
    """
    pass


def datetime_to_str(date=None, format='%Y-%m-%d %H:%M:%S'):
    """
    this method will convert the datetime into string with the format YYYY-mm-dd HH:MM:SS

    @Args:
    * [date] datetime.datetime, without any input the returning will be the current timestamp
    * [format] str, the format of output string

    @Returns:
    * [str] formatted string of timestamp
    """
    from datetime import datetime
    if date is None:
        date = datetime.now()
    if type(date) is not datetime:
        return '1970-01-01 00:00:00'
    return date.strftime(format)


@staticmethod
def calculate_hex(hex_string):
    """Credit for conversion to itsnotlupus/vesync_wsproxy."""
    hex_conv = hex_string.split(':')
    converted_hex = (int(hex_conv[0], 16) + int(hex_conv[1], 16)) / 8192
    return converted_hex


def check_arg(arg_name, arg_val, required_type, allow_none=True, min=None,
    max=None, choices=[]):
    """Check argument values and type"""
    if allow_none and arg_val is None:
        return arg_val
    if not isinstance(arg_val, required_type):
        try:
            arg_val = required_type(arg_val)
        except:
            raise Exception(
                'Argument `{}` value `{}` is not in correct type: `{}` and cannot be coerced'
                .format(arg_name, arg_val, required_type.__name__))
    if required_type in [float, int]:
        if min and arg_val < min:
            raise Exception(
                'Argument `{}` value `{}` is too low. Minimal value: {}'.
                format(arg_name, arg_val, min))
        if max and arg_val > max:
            raise Exception(
                'Argument `{}` value `{}` is too high. Maximal value: {}'.
                format(arg_name, arg_val, max))
    if choices and arg_val not in choices:
        raise Exception(
            'Argument `{}` value `{}` is not in the list of possible choices. Choices: {}'
            .format(arg_name, arg_val, ', '.join(choices)))
    return arg_val


def tup_multiply(tuple):
    """
    definition: func(tuple) {...}
    objective : multiplies every element in the given tuple
    """
    result = 1
    for element in tuple:
        result *= element
    return result


def _cal_constants(x, y):
    """Calcula as constantes '𝛂', 'β' e 'k'."""
    h = x[-1] / (x.size - 1)
    k = y[-1] / (y.size - 1)
    α = k / h ** 2
    β = k / (2 * h)
    return α, β, k


@staticmethod
def authenticate_ldap_user(ldap_user, password):
    """
        Returns an authenticated Django user or None.
        """
    return ldap_user.authenticate(password)


def dateformat(dt):
    """Formats a :class:`datetime.datetime` object as dd.mm.yyyy

    :param datetime.datetime dt: The :class:`datetime.datetime` object to
        format
    :return: A formatted string
    :rtype: str

    """
    return dt.strftime('%d.%m.%Y')


def takewhile_peek(predicate, iterable):
    """
    Like takewhile, but takes a peekable iterable and doesn't
    consume the non-matching item.

    >>> items = Peekable(range(10))
    >>> is_small = lambda n: n < 4

    >>> small_items = takewhile_peek(is_small, items)

    >>> list(small_items)
    [0, 1, 2, 3]

    >>> list(items)
    [4, 5, 6, 7, 8, 9]

    >>> empty = takewhile_peek(is_small, Peekable([]))
    >>> list(empty)
    []

    >>> items = Peekable([3])
    >>> small_items = takewhile_peek(is_small, items)
    >>> list(small_items)
    [3]
    >>> list(items)
    []

    >>> items = Peekable([4])
    >>> small_items = takewhile_peek(is_small, items)
    >>> list(small_items)
    []
    >>> list(items)
    [4]
    """
    while True:
        try:
            if not predicate(iterable.peek()):
                break
            yield next(iterable)
        except StopIteration:
            break


@classmethod
def from_csl_item(cls, csl_item):
    """
        Create an Unpaywall object for `csl_item`.
        """
    from .csl_item import CSL_Item
    csl_item = CSL_Item(csl_item)
    doi = csl_item.get('DOI')
    if doi:
        return cls.from_citekey(f'doi:{doi}', csl_item=csl_item)
    csl_item.infer_id()
    return cls.from_citekey(csl_item['id'], csl_item=csl_item)


def rename_elements(elements, rename_dict):
    """ Rename elements. """
    for k in range(elements.getSize()):
        e = elements.get(k)
        for id_old, id_new in rename_dict.items():
            e.renameSIdRefs(id_old, id_new)


def format_filesize(size):
    """Formats the file size into a human readable format."""
    for suffix in ('bytes', 'KB', 'MB', 'GB', 'TB'):
        if size < 1024.0:
            if suffix in ('GB', 'TB'):
                return '{0:3.2f} {1}'.format(size, suffix)
            else:
                return '{0:3.1f} {1}'.format(size, suffix)
        size /= 1024.0


def get_last_author_info():
    """Return the member object corresponding to the last author
        who modified this content object.
        """


def psi_H_Na_Cl_PK74(T, P):
    """c-c'-a: hydrogen sodium chloride [PK74]."""
    psi = -0.004
    valid = T == 298.15
    return psi, valid


def normalize_deps(dep_map):
    """Returns a copy of *dep_map* with no duplicate dependencies for a
    given target, and all dependencies properly represented as targets.
    """
    ret = type(dep_map)()
    for k, _deps in dep_map.items():
        cur_seen = set()
        ret[k] = []
        for d in _deps:
            if d not in ret:
                ret[d] = []
            if d in cur_seen:
                continue
            ret[k].append(d)
            cur_seen.add(d)
    return ret


@staticmethod
def AllInventoriesInt():
    """
        Get all inventory types as ints.

        Returns:
            list: of int formatted inventory types.
        """
    return [1, 2, 224]


def comment_stripper(jdx_line):
    """-> header.strip(), comment.strip()

    header=="" indicates a full comment line.
    """
    split_line = jdx_line.split('$$', 1)
    if len(split_line) > 1:
        header, comment = split_line
        return header.strip(), comment.strip()
    else:
        return split_line[0].strip(), ''


def filter_artifact_file_name(attribute, _value):
    """Used by attr.asdict to remove the src_name attr when serializing"""
    if attribute.name == 'src_name':
        return False
    return True


def add(anchor, title):
    """Add an new index.
        """


def collections_to_string(iterable, threshold=-1):
    """

    >>> collections_to_string([])
    ''
    >>> collections_to_string([1])
    '1'
    >>> collections_to_string([1, 2])
    '1 and 2'
    >>> collections_to_string([1, 2, 3, 4])
    '1, 2, 3, and 4'
    >>> collections_to_string([1, 2, 3, 4], threshold=4)
    '1, 2, 3, and 4'
    >>> collections_to_string([1, 2, 3, 4, 5, 6], threshold=4)
    '1, 2, 3, 4, and 2 items'
    >>> collections_to_string([1, 2, 3, 4, 5], threshold=4)
    '1, 2, 3, 4, and 5'
    >>> collections_to_string([1, 2, 3, 4], threshold=20)
    '1, 2, 3, and 4'

    """
    if len(iterable) == 0:
        return ''
    elif len(iterable) < 2:
        return str(iterable[0])
    if threshold == -1 or threshold >= len(iterable):
        threshold = len(iterable) - 1
    comman_list = []
    and_item = None
    for idx, item in enumerate(iterable):
        if and_item is not None:
            break
        elif len(comman_list) < threshold:
            comman_list.append(item)
        elif idx == len(iterable) - 1:
            and_item = item
        else:
            remainder_length = len(iterable) - idx
            and_item = '{} items'.format(remainder_length)
    return ', '.join(map(str, comman_list)) + (',' if len(comman_list) > 2 else
        '') + ' and ' + str(and_item)


def read_uic3tag(fh, byteorder, dtype, planecount, offsetsize):
    """Read MetaMorph STK UIC3Tag from file and return as dict."""
    if dtype != '2I' or byteorder != '<':
        raise ValueError('invalid UIC3Tag')
    values = fh.read_array('<u4', 2 * planecount).reshape(planecount, 2)
    return {'Wavelengths': values[:, (0)] / values[:, (1)]}


def __instancecheck__(cls, inst, live=True):
    """Does the given instance support this interface?"""
    return cls.implements(inst)


def parse_cstring_from_stream(stream, stream_pos=None):
    " Parse a C-string from the given stream. The string is returned without\n        the terminating \x00 byte. If the terminating byte wasn't found, None\n        is returned (the stream is exhausted).\n        If stream_pos is provided, the stream is seeked to this position before\n        the parsing is done. Otherwise, the current position of the stream is\n        used.\n        Note: a bytes object is returned here, because this is what's read from\n        the binary file.\n    "
    if stream_pos is not None:
        stream.seek(stream_pos)
    CHUNKSIZE = 64
    chunks = []
    found = False
    while True:
        chunk = stream.read(CHUNKSIZE)
        end_index = chunk.find(b'\x00')
        if end_index >= 0:
            chunks.append(chunk[:end_index])
            found = True
            break
        else:
            chunks.append(chunk)
        if len(chunk) < CHUNKSIZE:
            break
    return b''.join(chunks) if found else None


def synonyms(word2nums, num2words, word):
    """Uses the word2nums and num2words dicts to look up synonyms
    for the given word. Returns a list of synonym strings.
    """
    keys = word2nums[word]
    syns = set()
    for key in keys:
        syns = syns.union(num2words[key])
    if word in syns:
        syns.remove(word)
    return sorted(syns)


def bC_Mg_HSO4_HMW84(T, P):
    """c-a: magnesium bisulfate [HMW84]."""
    b0 = 0.4746
    b1 = 1.729
    b2 = 0.0
    C0 = 0
    C1 = 0
    alph1 = 2
    alph2 = -9
    omega = -9
    valid = T == 298.15
    return b0, b1, b2, C0, C1, alph1, alph2, omega, valid


def find_max_occurence(profile, max_count=2):
    """
    Return profile with base corresponding to max scores[CHECK!]
    """
    sorted_profile = []
    for p in profile:
        sorted_profile.append(sorted(list(p.items()), key=lambda x: x[1]))
    for i, p in enumerate(sorted_profile):
        sorted_profile[i] = p[-max_count:]
    return sorted_profile


def count_blanks(column):
    """
    Counts the blank cells in a column in a pandas dataframe.
    This is DIFFERENT than counting the null values.
    However, this WILL count cells that contain None.

    Parameters
    ----------
    column: a dataframe column or any iterable object
        column on which you want to count the blanks

    Returns
    -------
    int
        number of cells in the column that contain blanks

    Examples
    --------
    >>> my_df = create_dataframe(6, 4, include_empties=True, include_nulls=True)
    >>> my_df
          col1    col2    col3    col4
    row1  10      is      12      f
    row2  9       time            the
    row3  h       the     Nan     2
    row4  4       is      7       for
    row5  the     4               6
    row6  12      6       None    9

    >>> count_blanks(my_df['col3'])
    3
    """
    count = 0
    for thing in column:
        if not thing:
            count += 1
    return count


def _update_spcs(model, starting_id_dict, spc_id, spc_map):
    """updates the spcs"""
    if 'spc_id' in starting_id_dict and spc_id is not None:
        for spc_idi, spc_group in sorted(model.spcadds.items()):
            for unused_i, spc in enumerate(spc_group):
                assert hasattr(spc, 'conid')
                spc.conid = spc_id
            spc_map[spc_idi] = spc_id
            spc_id += 1
        for spc_idi, spc_group in sorted(model.spcs.items()):
            for unused_i, spc in enumerate(spc_group):
                assert hasattr(spc, 'conid')
                spc.conid = spc_id
            spc_map[spc_idi] = spc_id
            spc_id += 1
    else:
        for spc_id in model.spcadds:
            spc_map[spc_id] = spc_id
        for spc_id in model.spcs:
            spc_map[spc_id] = spc_id


def to_marshallable_type(obj):
    """Helper for converting an object to a dictionary only if it is not
    dictionary already or an indexable object nor a simple type"""
    if obj is None:
        return None
    if hasattr(obj, '__marshallable__'):
        return obj.__marshallable__()
    if hasattr(obj, '__getitem__'):
        return obj
    return dict(obj.__dict__)


@staticmethod
def _format2int(phasor_polar=False, phasor_float=False, analogs_float=False,
    freq_float=False):
    """
        ### format2int() ###

        Convert ``boolean`` representation of data format to integer.

        **Params:**

        * ``phasor_polar`` **(bool)** - If ``True`` phasor represented using magnitude and angle (polar)
        else rectangular.
        * ``phasor_float`` **(bool)** - If ``True`` phasor represented using floating point format else
        represented as 16 bit integer.
        * ``analogs_float`` **(bool)** - If ``True`` analog values represented using floating point notation
        else represented as 16 bit integer.
        * ``freq_float`` **(bool)** - If ``True`` FREQ/DFREQ represented using floating point notation
        else represented as 16 bit integer.

        **Returns:**

        * ``int`` representation of data format.

        """
    data_format = 1 << 1
    if freq_float:
        data_format |= 1
    data_format <<= 1
    if analogs_float:
        data_format |= 1
    data_format <<= 1
    if phasor_float:
        data_format |= 1
    data_format <<= 1
    if phasor_polar:
        data_format |= 1
    mask = 1 << 4
    data_format ^= mask
    return data_format


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

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


def copy_to_selected_button(all: bool=True):
    """Copy property from this object to selected objects or bones

    :param all: All, Copy to selected all elements of the array
    :type all: bool
    """
    pass


def blocksourcerequirements(repo):
    """Obtain requirements that will prevent an upgrade from occurring.

    An upgrade cannot be performed if the source repository contains a
    requirements in the returned set.
    """
    return {b'treemanifest', b'parentdelta', b'shared'}


def deliver_config_snapshot(deliveryChannelName=None):
    """
    Schedules delivery of a configuration snapshot to the Amazon S3 bucket in the specified delivery channel. After the delivery has started, AWS Config sends following notifications using an Amazon SNS topic that you have specified.
    See also: AWS API Documentation

    :example: response = client.deliver_config_snapshot(
        deliveryChannelName='string'
    )

    :type deliveryChannelName: string
    :param deliveryChannelName: [REQUIRED]
            The name of the delivery channel through which the snapshot is delivered.

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

    """
    pass


def taylor(energy, gradient, hessian, step):
    """Taylor series expansion of the energy to second order."""
    return energy + step @ gradient + 0.5 * step @ hessian @ step


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

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


def get_unlensed_total_flux(kwargs_src_light_list, src_light_model,
    kwargs_ps_list=None, ps_model=None):
    """Computes the total flux of unlensed objects

    Parameter
    ---------
    kwargs_src_light_list : list
        list of kwargs dictionaries for the unlensed source galaxy, each with an 'amp' key
    kwargs_ps_list : list
        list of kwargs dictionaries for the unlensed point source (if any), each with an 'amp' key

    Returns
    -------
    float
        the total unlensed flux
    """
    total_flux = 0.0
    for i, kwargs_src in enumerate(kwargs_src_light_list):
        total_flux += src_light_model.total_flux(kwargs_src_light_list,
            norm=True, k=i)[0]
    if kwargs_ps_list is not None:
        assert ps_model is not None
        for i, kwargs_ps in enumerate(kwargs_ps_list):
            total_flux += kwargs_ps['point_amp']
    return total_flux


def insert_derived_spline(spline_dictionary, spline_keys, derived_quantity,
    log=print):
    """Inserts a spline into a dictionary of horizon splines

    Derived from Horizons.h5.  Note: spline_keys is a vector of key
    names (should be length 1 for scalars, length 3 for vectors), where
    each key is the name of a group that will be written in the LVC
    file, such as Omega-vs-time or LNhatx-vs-time; and derived_quantity
    is the quantity to be splined.  The derived_quantity should be
    computed using derived_horizon_quantities_from_sxs().

    """
    from . import LVCDataset
    log('Computing ' + str(spline_keys))
    times_AH = derived_quantity[:, (0)]
    quantity_AH = derived_quantity[:, 1:]
    for i, spline_key in enumerate(spline_keys):
        spline_dictionary[spline_key] = LVCDataset.from_data(times_AH,
            quantity_AH[:, (i)], tol=1e-06)


def pack(as_png: bool=False):
    """Pack an image as embedded data into the .blend file

    :param as_png: Pack As PNG, Pack image as lossless PNG
    :type as_png: bool
    """
    pass


def NumbersToWords(number):
    """
    little function that converts numbers to words. This could be more efficient,
    and won't work if the number is bigger than 999 but it's for stave names,
    and I doubt any part would have more than 10 staves let alone 999.
    """
    units = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
        'nine']
    tens = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy',
        'eighty', 'ninety']
    output = ''
    if number != 0:
        str_val = str(number)
        if 4 > len(str_val) > 2:
            output += units[int(str_val[0]) - 1]
            output += 'hundred'
            if str_val[1] != 0:
                output += 'and' + tens[int(str_val[1]) - 1]
                if str_val[2] != 0:
                    output += units[int(str_val[2]) - 1]
        if 3 > len(str_val) > 1:
            output += tens[int(str_val[0]) - 1]
            if str_val[1] != 0:
                output += units[int(str_val[1]) - 1]
        if 2 > len(str_val) == 1:
            output += units[int(str_val[0]) - 1]
    else:
        output = 'zero'
    return output


@classmethod
def from_extended_slug(cls, slug):
    """Return an Target from an build or job slug."""
    parts = slug.split('/')
    assert len(parts) in [2, 3]
    user = parts[0]
    logical_id = None
    build_id = job_id = None
    if len(parts) == 3:
        project, logical_id = parts[1:]
    elif '#' in parts[1]:
        project, logical_id = parts[1].split('#', 1)
    elif '@' in parts[1]:
        project, build_id = parts[1].split('@', 1)
        build_id = int(build_id)
    elif ':' in parts[1]:
        project, job_id = parts[1].split(':', 1)
        job_id = int(job_id)
    else:
        project = parts[1]
    if logical_id:
        build_number, sep, job_number = logical_id.partition('.')
        assert build_number
        build_number = int(build_number)
        if job_number:
            job_number = int(job_number)
        else:
            job_number = None
        return cls(user, project, build_number=build_number, job_number=
            job_number)
    return cls(user, project, build_id, job_id)


@classmethod
def sql(cls):
    """
        Produces the SQL of the current query.
        """
    return cls.__query__.sql()


@classmethod
def bash(cls, *args):
    """
        executes bash with the given arguments
        :param args:
        :return:
        """
    return cls.execute('bash', args)


def a_error(plugin_ctx, ctx):
    """Display the error message."""
    message = ctx.ctrl.after.strip().splitlines()[-1]
    plugin_ctx.error(message)
    return False


def join_root(root, path):
    """Prepends `root` to the absolute path `path`.
    """
    p_root, p_loc = path.split_root()
    assert p_root == b'/'
    return root / p_loc


def _regrid_spline(x, y, newx, allow_extrapolation=False):
    """
    Implement regrid() function using spline fit and interpolation.
    """
    from scipy import interpolate
    if not allow_extrapolation:
        if newx.min() < x.min():
            raise ValueError('x.min(%f) must be smaller than newx.min(%f)' %
                (x.min(), newx.min()))
        if newx.max() > x.max():
            raise ValueError('x.max(%f) must be larger than newx.max(%f)' %
                (x.max(), newx.max()))
    spl = interpolate.splrep(x, y)
    newy = interpolate.splev(newx, spl)
    return newy


def untagged_corpus(filename):
    """Reads and yield token lists a `filename` string."""
    with open(filename, 'r') as source:
        for line in source:
            line = line.strip()
            if not line:
                continue
            yield line.split()


def add_translate_to(vstruct, centre=(0.0, 0.0, 0.0)):
    """translate all elements to new centre coordinate
    centre : (x,y,z)
    """
    vstruct['transforms'].append({'type': 'translate_to', 'centre': centre})


def check_auth(username, password, expected_user, expected_pw):
    """This function is called to check if a username /
            password combination is valid.
        """
    return username == expected_user and password == expected_pw


@classmethod
def count(cls, **kwargs):
    """
        Count the number of records that exist on firestore
        up until 5000 then return 5k+ if records
        exceed that number. The implmentation of this
        method might (will!) change
        """
    pass


def gwrap(some_string):
    """Returns green text."""
    return '\x1b[92m%s\x1b[0m' % some_string


def clean_picard_style_key(key: str) ->str:
    """Clean a Picard parameter key."""
    return key.upper()


def lookup_robots_rules(rules_map, user_agent):
    """Looks up a user agent in a rules mapping.

    Parameters:

    rules_map
        Rules mapping as produced by `parse_robots_txt`.
    user_agent
        Name of the user agent to look up in the rules.

    Returns:

    rules: (allowed, url_prefix)*
        The rules that apply to the given user agent.
    """
    user_agent = user_agent.casefold()
    for name, rules in rules_map.items():
        if name.startswith(user_agent):
            return rules
    return rules_map.get('*', [])


def checkPassword(encoded_password, password):
    """Does the encoded password match the given password?

        Return True if they match, else False.
        """


def name(obj):
    """Try to find some reasonable name for the object."""
    return getattr(obj, 'name', 0) or getattr(obj, '__name__', 0) or getattr(
        getattr(obj, '__class__', 0), '__name__', 0) or str(obj)


def df_name_multiindex(df, name):
    """
    Rename columns of a DataFrame by using new column names that
    are tuples of (name, column_name) to ensure unique column names
    that can also be split again. This transforms the columns to a MultiIndex.
    """
    d = {}
    for c in df.columns:
        d[c] = name, c
    return df.rename(columns=d)


def _format_local(local_path, local_is_path):
    """Format a path for log output"""
    if local_is_path:
        return local_path
    else:
        return getattr(local_path, 'name', '<file obj>')


def non_negative_int(argument):
    """
    Converts the argument into an integer.
    Raises ValueError for negative or non-integer values.
    """
    value = int(argument)
    if value >= 0:
        return value
    else:
        raise ValueError('negative value defined; must be non-negative')


def check_between(v_min, v_max, **params):
    """Checks parameters are in a specified range

    Parameters
    ----------

    v_min : float, minimum allowed value (inclusive)

    v_max : float, maximum allowed value (inclusive)

    params : object
        Named arguments, parameters to be checked

    Raises
    ------
    ValueError : unacceptable choice of parameters
    """
    for p in params:
        if params[p] < v_min or params[p] > v_max:
            raise ValueError('Expected {} between {} and {}, got {}'.format
                (p, v_min, v_max, params[p]))


def _serialize_list(embl_wrapper, data, sep='\n'):
    """Serialize a list of obj using a textwrap.TextWrapper instance. Returns
    one string of wrapped embl objects"""
    output = []
    for line in data:
        output += embl_wrapper.wrap(line)
    output = sep.join(output) + '\n'
    return output


@conf
def find_gfortran(conf):
    """Find the gfortran program (will look in the environment variable 'FC')"""
    fc = conf.find_program(['gfortran', 'g77'], var='FC')
    conf.get_gfortran_version(fc)
    conf.env.FC_NAME = 'GFORTRAN'


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

        :param PaperDocChangeSharingPolicyType val:
        :rtype: EventType
        """
    return cls('paper_doc_change_sharing_policy', val)


def getBitWidth(registerMap):
    """
        Return the bit width (32 or 64 bit) given the registers

        @type registerMap: map
        @param registerMap: Map of register names to value

        @rtype: int
        @return: The bit width
    """
    if 'rax' in registerMap or 'x0' in registerMap:
        return 64
    return 32


def append_file(fpath, data):
    """ Add new line to file"""
    with open(fpath, 'a+', encoding='utf8') as f:
        f.write(data + '\n')


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

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

    For example::

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

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


def _lookup_module(modmap, name, obj, main_module):
    """lookup name if module is imported"""
    for modobj, modname in modmap[name]:
        if modobj is obj and modname != main_module.__name__:
            return modname


def is_ordered():
    """ Return ``True`` if the folder has a manual ordering (e.g. its
        ``order`` attribute has been set), ``False`` otherwise."""


def human_readable_stat(c):
    """
    Transform a timedelta expressed in seconds into a human readable string

    Parameters
    ----------
    c
        Timedelta expressed in seconds

    Returns
    ----------
    string
        Human readable string
    """
    c = int(float(c))
    years = c // 31104000
    months = c // 2592000
    days = c // 86400
    hours = c // 3600 % 24
    minutes = c // 60 % 60
    seconds = c % 60
    if years > 0:
        return str(years) + 'Y'
    if months > 0:
        return str(months) + 'MO'
    if days > 0:
        return str(days) + 'D'
    if hours > 0:
        return str(hours) + 'h'
    if minutes > 0:
        return str(minutes) + 'm'
    return str(seconds) + 's'


def _r_long(int_bytes):
    """Convert 4 bytes in little-endian to an integer."""
    return int.from_bytes(int_bytes, 'little')


def identifier_to_label(identifier):
    """Tries to convert an identifier to a more human readable text label.
    Replaces underscores by spaces and may do other tweaks.
    """
    txt = identifier.replace('_', ' ')
    txt = txt.replace(' id', 'ID')
    txt = dict(url='URL').get(txt, txt)
    txt = txt[0].upper() + txt[1:]
    return txt


def hide(unselected: bool=False):
    """Hide (un)selected control points

    :param unselected: Unselected, Hide unselected rather than selected
    :type unselected: bool
    """
    pass


def _is_enabled():
    """
    Reason for returning true is explained in widi facade.
    /plyer/facades/wifi.py
    """
    return True


def subnet_provides_public_ip_mapping(subnet):
    """True iff subnet will map public ips on launch"""
    return subnet['MapPublicIpOnLaunch']


def _need_snippet_displayed(overall_messages_dets, block_messages_dets, *,
    in_notebook=False, multi_block=False):
    """
    Don't need to see the code snippet displayed when it is already visible
    right next to it:
    * because in notebook (it is already in the cell straight above)
    * because there is only one block in snippet and there is a block message
      for it (which will display the block i.e. the entire snippet) UNLESS there
      is an overall message separating them
    Otherwise we need it displayed.
    """
    if in_notebook:
        return False
    mono_block_snippet = not multi_block
    if (mono_block_snippet and block_messages_dets and not
        overall_messages_dets):
        return False
    return True


def concat_imports(values, sep='.'):
    """Combine import statements

    Parameters
    ----------
    values : list-like
        The values to be concatenated
    sep : string
        The value between the statements

    Returns
    -------
    str
        The concatenated string
    """
    if len(values) >= 1:
        store = []
        for v in values:
            if isinstance(v, (list, tuple)):
                store.extend(v)
            else:
                store.append(v)
        return sep.join(store)
    else:
        return ''


def start():
    """
        Start the process.
        """


def create_zoo(archive, compression, cmd, verbosity, interactive, filenames):
    """Create a ZOO archive."""
    cmdlist = [cmd, '-add', archive]
    cmdlist.extend(filenames)
    return cmdlist


@classmethod
def is_alias(cls, state):
    """Create a function that can be used as a alias for a in query.

            >>> class MyTracker(Tracker):
            ...     is_activated = Tracker.is_alias('active')
            ...
        """
    return lambda self, obj: self.in_state(state, obj)


@classmethod
def docker(klass, container_id, shell, script, interval, deregister=None):
    """
        Invoke *script* packaged within a running docker container with
        *container_id* at a specified *interval* on the configured
        *shell* using the Docker Exec API.  Optional *register* after which a
        failing service will be automatically deregistered.
        """
    ret = {'docker_container_id': container_id, 'shell': shell, 'script':
        script, 'interval': interval}
    if deregister:
        ret['DeregisterCriticalServiceAfter'] = deregister
    return ret


def strip_suffix(filename):
    """Returns a filename minus it's extension."""
    dotidx = filename.rfind('.')
    return filename[:dotidx] if dotidx != -1 else filename


def parse_defaults(defaults_string):
    """Yields default values for a function, given the string provided by
    pg_get_expr(pg_catalog.pg_proc.proargdefaults, 0)"""
    if not defaults_string:
        return
    current = ''
    in_quote = None
    for char in defaults_string:
        if current == '' and char == ' ':
            continue
        if char == '"' or char == "'":
            if in_quote and char == in_quote:
                in_quote = None
            elif not in_quote:
                in_quote = char
        elif char == ',' and not in_quote:
            yield current
            current = ''
            continue
        current += char
    yield current


@staticmethod
def interfaces_roles_dont_change_and_router_transition_to_it_or_ot(interface:
    'TreeInterfaceUpstream') ->None:
    """
        Interfaces roles dont change (this interface remains Root) AND
        BestUpstreamNeighbor does not change AND
        router changes its interest in receiving data packets (becomes interested or not interested)
        """
    interface.logger.debug(
        'interfaces_roles_dont_change_and_router_transition_to_it_or_ot')
    interface.send_my_interest()


def __new__(cls, obj, *args, **kwargs):
    """Create an proxy instance referencing `obj`.

        (obj, *args, **kwargs) are passed to this class' __init__, so deriving classes can define an
        __init__ method of their own.

        _class_proxy_cache is unique per deriving class (each deriving class must hold its own cache).

        Args:
            obj (object): Instance of the class in which we want to use the proxy.
            *args: Variable length argument list.
            **kwargs: Arbitrary keyword arguments.

        Returns:
            object: New proxy instance referencing `obj`.
        """
    try:
        cache = cls.__dict__['_class_proxy_cache']
    except KeyError:
        cls._class_proxy_cache = cache = {}
    try:
        the_class = cache[obj.__class__]
    except KeyError:
        cache[obj.__class__] = the_class = cls._create_class_proxy(obj.
            __class__)
    instance = object.__new__(the_class)
    the_class.__init__(instance, obj, *args, **kwargs)
    return instance


def replace_parts_animal_movement(data_groups, animal_id, time_array,
    replacement_value_x, replacement_value_y):
    """
    Replace subsets (segments) of animal movement based on some indices e.g. time
    This function can be used to remove outliers

    Input:
    1.) First argument is a Python 3 dictionary whose key is 'animal_id'and value is
    Pandas DataFrame for that 'animal_id'
    2.) Second argument is 'animal_id' whose movements have to replaced
    3.) Third argument is an array of time indices whose movements have to replaced
    4.) Fourth argument is the value which will be replaced for all values contained
    in 'time_array' for 'x' attribute
    5.) Fifth argument is the value which will be replaced for all values contained
    in 'time_array' for 'y' attribute

    Returns:
    Modified Python 3 dictionary which was passed as first argument to it

    An example usage-

    data = csv_to_pandas(path)

    data_groups = group_animals(data)

    arr_index = np.array([10, 20, 200, 20000, 40000, 43200])

    replaced_data_groups = replace_parts_animal_movement(data_groups, 811, arr_index, 100, 90)
    """
    data_groups[animal_id].loc[time_array, 'x'] = replacement_value_x
    data_groups[animal_id].loc[time_array, 'y'] = replacement_value_y
    return data_groups


def check_tile_id(tile_id):
    """
    Raise a ``ValueError`` if the given SRTM tile ID (string)
    is improperly formatted.
    Otherwise, return nothing.
    """
    t = tile_id
    msg = '{!s} is not a valid STRM tile ID'.format(t)
    try:
        lat = int(t[1:3])
        lon = int(t[4:])
    except:
        raise ValueError(msg)
    if not (t[0] in ['N', 'S'] and t[3] in ['E', 'W'] and 0 <= lat <= 90 and
        0 <= lon <= 180):
        raise ValueError(msg)


@staticmethod
def get_jenkins_plugin_name():
    """Gets the name of the Jenkins plugin associated with this PyJen plugin

        This static method is used by the PyJen plugin API to associate this
        class with a specific Jenkins plugin, as it is encoded in the config.xml

        :rtype: :class:`str`
        """
    return 'org.jenkinsci.plugins.workflow.job.WorkflowJob'


def get_canonical_encoding_name(name):
    """
    Given an encoding name, get the canonical name from a codec lookup.

    :param str name: The name of the codec to lookup
    :return: The canonical version of the codec name
    :rtype: str
    """
    import codecs
    try:
        codec = codecs.lookup(name)
    except LookupError:
        return name
    else:
        return codec.name


def get_api(name):
    """Look up skin api by name."""


@classmethod
def _get_test_callable(cls, test):
    """
        Get the test callable, from the test.

        :param test:
            The test that has raised an error or succeeded
        :type test:
            :class:`nose.case.Test` or :class:`pytest.Item`
        :return:
            The test declaration, callable and name that is being run
        :rtype:
            `callable`
        """
    raise NotImplementedError


def countdown_iter(start_at, decr=1):
    """Generator that decrements after each generation until <= zero.

    NOTE(harlowja): we can likely remove this when we can use an
    ``itertools.count`` that takes a step (on py2.6 which we still support
    that step parameter does **not** exist and therefore can't be used).
    """
    if decr <= 0:
        raise ValueError(
            'Decrement value must be greater than zero and not %s' % decr)
    while start_at > 0:
        yield start_at
        start_at -= decr


def add_resource(stack_definition, resource_definition):
    """Insert the given resource definition into the stack definition.

    Add the resource to the template and store any temporary data.
    """
    resource_name = resource_definition.name
    stack_definition._resources.pop(resource_name, None)
    stack_definition._resource_data.pop(resource_name, None)
    stack_definition.t.add_resource(resource_definition)
    if stack_definition._resource_defns is not None:
        stack_definition._resource_defns[resource_name] = resource_definition


def print_bold(msg, end='\n'):
    """Convenience function to print a message in bold style

    Optionally you can also specify how the bold text should end. By default
    it ends with a new line character.

    :arg msg: Message to be converted to bold style
    :arg end: Tell how the printed string should end (newline, space etc)
    """
    print('\x1b[1m' + msg + '\x1b[0m', end=end)


def filter_colony_properties(colony_df, cluster_params, colony_props):
    """Assign -1 label to clusters not meeting these criteria."""
    if not cluster_params['min_density'] < colony_props['density'
        ] < cluster_params['max_density']:
        colony_df['Colony'] = -1
    if not cluster_params['min_roundness'] < colony_props['roundness'
        ] < cluster_params['max_roundness']:
        colony_df['Colony'] = -1
    return colony_df


@staticmethod
def remove_svc_acknowledgement(service):
    """Remove an acknowledgment on a service
        Format of the line that triggers function call::

        REMOVE_SVC_ACKNOWLEDGEMENT;<host_name>;<service_description>

        :param service: service to edit
        :type service: alignak.objects.service.Service
        :return: None
        """
    service.unacknowledge_problem()


def google_fixed_width_font(style):
    """check if the css of the current element defines a fixed width font"""
    font_family = ''
    if 'font-family' in style:
        font_family = style['font-family']
    if 'Courier New' == font_family or 'Consolas' == font_family:
        return True
    return False


def signal(num, remote=''):
    """Sends the signal to master or remote.

    :param num: Signal number.

    :param str|unicode remote: Remote address.

    :rtype: None

    :raises ValueError: If remote rejected the signal.

    :raises IOError: If unable to deliver to remote.
    """


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

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

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


def theme_install(overwrite: bool=True, filepath: str='', filter_folder:
    bool=True, filter_glob: str='*.xml'):
    """Load and apply a Blender XML theme file

    :param overwrite: Overwrite, Remove existing theme file if exists
    :type overwrite: bool
    :param filepath: filepath
    :type filepath: str
    :param filter_folder: Filter folders
    :type filter_folder: bool
    :param filter_glob: filter_glob
    :type filter_glob: str
    """
    pass


def CSV_Save(OutputParamsKeys, OutputDict, i, file):
    """
    Save parameters in CSV file.

    :param OutputParamsKeys : output parameters keys
    :type OutputParamsKeys : list
    :param OutputDict: analysis result dictionary
    :type OutputDict:dict
    :param i: cell load current [A]
    :type i : float
    :param file : file object
    :return: None
    """
    file.write(str(i) + ',')
    for key in OutputParamsKeys:
        file.write(str(OutputDict[key]))
        if key != OutputParamsKeys[-1]:
            file.write(',')
    file.write('\n')


def get(isamAppliance):
    """
    Get Set up complete status
    """
    return isamAppliance.invoke_get('Get Setup Complete Settings',
        '/setup_complete')


def radians(data=None, out=None, name=None, **kwargs):
    """Converts each element of the input array from degrees to radians.

    .. math::
       radians([0, 90, 180, 270, 360]) = [0, \\pi/2, \\pi, 3\\pi/2, 2\\pi]

    The storage type of ``radians`` output depends upon the input storage type:

       - radians(default) = default
       - radians(row_sparse) = row_sparse
       - radians(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L293

    Parameters
    ----------
    data : NDArray
        The input array.

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

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


def local():
    """Returns a local repository instance.

        If the peer represents a local repository, returns an object that
        can be used to interface with it. Otherwise returns ``None``.
        """


def loggingchoices():
    """
    utility for AdminServerForm
    """
    for index, choice in enumerate(['debug', 'info', 'warning', 'error',
        'critical']):
        yield index, choice


def constant(rsq, epsilon, *args, **kwargs):
    """Constant potential."""
    return epsilon, 0.0, 0.0


@classmethod
def errata_info(cls, options):
    """Retrieve a single errata for a system"""
    cls.command_sub = 'errata info'
    return cls.execute(cls._construct_command(options), output_format='csv')


def force_fma(mass, acceleration):
    """Usage: force_fma(mass of object, acceleration)"""
    return mass * acceleration


def strtonum(value):
    """
    For numbers 0 to 9, return the number spelled out. Otherwise, return the
    number. This follows Associated Press style.  This always returns a string
    unless the value was not int-able, unlike the Django filter.
    Taken from: https://github.com/jmoiron/humanize/blob/master/humanize/number.py#L81
    """
    try:
        value = int(value)
    except (TypeError, ValueError):
        return value
    if not 0 <= value < 10:
        return str(value)
    return ('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven',
        'eight', 'nine')[value]


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 cookie_change(cls, cookie):
    """Called to log a change in Syncrepl cookie.

        :param str cookie: The new Syncrepl cookie.

        :return None - any returned value is ignored.

        This callback happens any time the LDAP server sends us a new Syncrepl
        cookie.

        The Syncrepl cookie is an opaque string, which we send to the LDAP
        server at the start of a Syncrepl search.  If we do not have one, then
        the LDAP server knows to send us everything.  If we *do* have one, then
        the LDAP server can use that to know how far behind we are, and to send
        us just the changes.

        This callback can happen in all modes, and in all phases, as it is
        up to the LDAP server to give us a new Syncrepl cookie, when it is
        appropriate to do so.
        """
    pass


def configure_logging(quiet):
    """Set the logging level."""
    global __QUIET__
    __QUIET__ = quiet


def save(client, name, file_=None):
    """Save a model's current orientation as a new view.

    Args:
        client (obj):
            creopyson Client.
        name (str):
            View name.
        `file_` (str, optional):
            Model name. Defaults is current active model.

    Returns:
        None

    """
    data = {'name': name}
    if file_ is not None:
        data['file'] = file_
    else:
        active_file = client.file_get_active()
        if active_file is not None:
            data['file'] = active_file['file']
    return client._creoson_post('view', 'save', data)


def decode(input, errors='strict'):
    """Decodes the input and returns a tuple (output, length consumed).
        """


def condtopy(cond):
    """
        >>> condtopy('line 2 is more than line 1')
        'line2>line1'
        """
    delim = ' is more than '
    if delim in cond:
        lh, rh = cond.split(delim, 1)
        lh = lh.replace(' ', '')
        rh = rh.replace(' ', '')
        return '%s>%s' % (lh, rh)
    raise Exception('dunno condition [%s]' % (cond,))


def lightcurveChopImport(glueApp, dataCollection, parentData, obsWindows):
    """
    Receives list of obs windows, breaks dataseries accordingly, imports data object to collection

    :param glueApp: Current instantiation of the Glue Application to spawn canvas into
    :type glueApp: glue.app.qt.application.GlueApplication

    :param dataCollection: Library of imported data objects to current Glue interface
    :type dataCollection: glue.core.data.DataCollection

    :param parentData: Glue (Pandas) Data Object containing CSV lightcurve data
    :type parentData: glue.core.data.Data

    :param obsWindows: List of observation windows with indices upon which to chop
    :type obsWindows: list
    """
    from glue.core import Data
    indxStart = 0
    extensionList = parentData.component_ids()
    for window in obsWindows:
        indxEnd = window[0]
        newChop = Data(label='AutoChop ' + str(indxStart))
        for extension in extensionList:
            newChop[str(extension)] = parentData[extension][indxStart:indxEnd]
        dataCollection.append(newChop)
        indxStart = indxEnd + 1


def __new__(cls, name, description=None):
    """Keep a dict of PermissionSetting instances, indexed by
        name. If the name already exists in the dict, return that
        instance rather than creating a new one.
        """
    instances = cls.__dict__.get('_z_instances')
    if instances is None:
        cls._z_instances = instances = {}
    it = instances.get(name)
    if it is None:
        instances[name] = it = object.__new__(cls)
        it._init(name, description)
    return it


def normalize_cov_type(cov_type):
    """
    Normalize the cov_type string to a canonical version

    Parameters
    ----------
    cov_type : str

    Returns
    -------
    normalized_cov_type : str
    """
    if cov_type == 'nw-panel':
        cov_type = 'hac-panel'
    if cov_type == 'nw-groupsum':
        cov_type = 'hac-groupsum'
    return cov_type


@staticmethod
def get_url_params(end_point):
    """
        Gets route parameters as dictionary
        :param end_point str target route
        :rtype: dict
        """
    var_params = end_point.split('/')
    if len(var_params) == 1 and var_params[0] == '':
        return []
    elif len(var_params) == 1 and var_params[0] != '':
        return [var_params[0]]
    else:
        params = list()
        for param in var_params:
            if len(param) > 0:
                params.append(param)
        return params


def theta_Cl_SO4_HMW84(T, P):
    """a-a': chloride sulfate [HMW84]."""
    theta = 0.02
    valid = T == 298.15
    return theta, valid


def stripnull(string):
    """Return string truncated at first null character.

    Clean NULL terminated C strings.

    >>> stripnull(b'string\\x00')
    b'string'

    """
    i = string.find(b'\x00')
    return string if i < 0 else string[:i]


@staticmethod
def from_affine():
    """ Converts from an Affine representation to a Jacobian.
        """
    raise NotImplementedError()


def GetNeighbors(ID, model=None, neighbors=None, mag_range=None, cdpp_range
    =None, aperture_name=None, cadence='lc', **kwargs):
    """
  Return `neighbors` random bright stars on the same module as `EPIC`.

  :param int ID: The target ID number
  :param str model: The :py:obj:`everest` model name. Only used when imposing CDPP bounds. Default :py:obj:`None`
  :param int neighbors: Number of neighbors to return. Default None
  :param str aperture_name: The name of the aperture to use. Select `custom` to call          :py:func:`GetCustomAperture`. Default :py:obj:`None`
  :param str cadence: The light curve cadence. Default `lc`
  :param tuple mag_range: (`low`, `high`) values for the Kepler magnitude. Default :py:obj:`None`
  :param tuple cdpp_range: (`low`, `high`) values for the de-trended CDPP. Default :py:obj:`None`

  """
    raise NotImplementedError('This mission is not yet supported.')


def params(f):
    """
	Read header parameters like ## key=value into a dictionary
	:param f: file handler
	:return: {key: value}
	"""
    params = {}
    pos = f.tell()
    line = f.readline()
    while line.startswith('#') or line == '\n':
        if line.startswith('##'):
            line = line[2:].rstrip('\n')
            try:
                idx = line.index('=')
                key = line[0:idx].lstrip()
                value = line[idx + 1:]
                params[key] = value
            except:
                pass
        pos = f.tell()
        line = f.readline()
    f.seek(pos)
    return params


def has_pdf(obj):
    """ NOT IMPLEMENTED. Once we do pdf generation for text content, this will work

    :param obj: The Plone content object to get preview URLs for
    :type obj: A Plone content object
    :return: True if there is a pdf available
    :rtype: boolean
    """
    return False


def find_mixed_type_cols(df, fix=True):
    """For a given dataframe, find the columns that are of mixed type.

    Tool to help with the performance warning when trying to save a pandas DataFrame as a HDF.
    When a column changes datatype somewhere, pickling occurs, slowing down the reading process of the HDF file.

    Parameters
    ----------
    df : pandas.DataFrame
        Dataframe to be searched for mixed data-types
    fix : bool
        Switch to control if NaN values in these problem columns should be replaced by the string 'UNKNOWN'
    Returns
    -------
    List of column names that have data type changes within themselves.
    """
    result = []
    for col in df.columns:
        weird = (df[[col]].applymap(type) != df[[col]].iloc[0].apply(type)
            ).any(axis=1)
        if len(df[weird]) > 0:
            print(col)
            result.append(col)
    if fix is True:
        for col in result:
            df[col].fillna('UNKNOWN', inplace=True)
    return result


def from_like_context(ctx, param, value):
    """Return the value for an option from the context if the option
    or `--all` is given, else return None."""
    if ctx.obj and ctx.obj.get('like') and (value == 'like' or ctx.obj.get(
        'all_like')):
        return ctx.obj['like'][param.name]
    else:
        return None


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

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

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


def unsubscribe(nodeIdentifier, subscriber, requestor):
    """ Cancel the subscription of an entity to a pubsub node.

        The subscription of C{subscriber} is removed from the list of
        subscriptions of the node with id C{nodeIdentifier}. If the
        C{requestor} is not allowed to unsubscribe C{subscriber}, an an
        exception should be raised.

        @return: a deferred that fires when unsubscription is complete.
        """


def update(options):
    """
    Updates the global settings for this configuration file from the inputed config options.
    """
    globals().update(options)


def binary_accuracy(y_true, y_pred):
    """Accuracy for binary data

    :param y_true: Real values on which to compare.
    :type y_true: numpy.array
    :param y_pred: Predicted values
    :type y_pred: numpy.array

    :return: Binary accuracy (in percent)
    :rtype: float
    """
    return (y_true == y_pred).mean()


def highestMax(requestContext, seriesList, n=1):
    """
    Takes one metric or a wildcard seriesList followed by an integer N.

    Out of all metrics passed, draws only the N metrics with the highest
    maximum value in the time period specified.

    Example::

        &target=highestMax(server*.instance*.threads.busy,5)

    Draws the top 5 servers who have had the most busy threads during the time
    period specified.

    """
    result_list = sorted(seriesList, key=lambda s: max(s))[-n:]
    return sorted(result_list, key=lambda s: max(s), reverse=True)


@classmethod
def start(cls):
    """Starts the watchdog and hooks function for various events."""
    if cls.running is False:
        cls.running = True
        cls.event_handler.on_deleted = cls.on_file_system_event
        cls.event_handler.on_moved = cls.on_file_system_event
        cls.event_handler.on_created = cls.on_file_system_event
        cls.event_handler.on_modified = cls.on_file_system_event
        cls.observer.start()


def run_length_decode(in_array):
    """A function to run length decode an int array.
    :param in_array: the input array of integers
    :return the decoded array"""
    switch = False
    out_array = []
    for item in in_array:
        if switch == False:
            this_item = item
            switch = True
        else:
            switch = False
            out_array.extend([this_item] * int(item))
    return out_array


def color_isolate(affect_visibility: bool=False):
    """Toggle whether the active color is the only one that is editable and/or visible

    :param affect_visibility: Affect Visibility, In addition to toggling the editability, also affect the visibility
    :type affect_visibility: bool
    """
    pass


def commit():
    """ called after processing of the queue has ended """


def timedelta_to_seconds(td):
    """Equivalent to ``td.total_seconds()`` (introduced in Python 2.7)."""
    return td.total_seconds()


def get_pixel_error(zz_gt):
    """calculate error in stereo distance due to 1 pixel mismatch (function of depth)"""
    disp = 0.54 * 721 / zz_gt
    error = abs(zz_gt - 0.54 * 721 / (disp - 1))
    return error


def armature_apply(selected: bool=False):
    """Apply the current pose as the new rest pose

    :param selected: Selected Only, Only apply the selected bones (with propagation to children)
    :type selected: bool
    """
    pass


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


@staticmethod
def max_argmax(s0, sL, offset=0, n_memory=1, limit=1):
    """ Return Score and TraceBack Pointer Simultaneously
        @params s0,sL    : score of S^0_n and S^L_n.
        @params n        : index.
        @params limit    : minimum length of segment sets.
        @params n_memory : The length of memory.
        """
    if s0 >= sL:
        return s0, offset + 1 - limit
    else:
        return sL, offset + n_memory


def ls(client):
    """List the user's devices."""
    for device in client.devices:
        print('{0.id}: {0.name} ({0.type.name} {0.model_id})'.format(device))


def html_progress_bar(value, total, label, interrupted=False):
    """Html code for a progress bar `value`/`total` with `label`"""
    bar_style = 'progress-bar-interrupted' if interrupted else ''
    return f"""
    <div>
        <style>
            /* Turns off some styling */
            progress {{
                /* gets rid of default border in Firefox and Opera. */
                border: none;
                /* Needs to be in here for Safari polyfill so background images work as expected. */
                background-size: auto;
            }}
            .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {{
                background: #F44336;
            }}
        </style>
      <progress value='{value}' class='{bar_style}' max='{total}' style='width:300px; height:20px; vertical-align: middle;'></progress>
      {label}
    </div>
    """


def _get_lock_name(obj):
    """
    Gets a lock name for the object.

    :param django.db.models.Model obj: the object for which we want the lock

    :returns: a name for this object
    :rtype: :class:`str`
    """
    return '%s.%s__%d' % (obj.__module__, obj.__class__.__name__, obj.id)


def unbox(data, c_type=None, ffi=ffi):
    """
    Try to return something to pass to low-level ffi calls.
    For a cffi type, return data.
    For a Struct, return the wrapper's cdata.
    Else try to use data as a ffi initializer for c_type.
    """
    if not isinstance(data, ffi.CData):
        try:
            return data.cdata
        except AttributeError:
            if c_type:
                return ffi.new(c_type, data)
    return data


def subtract_params(p1, p2):
    """
    Subtract two lists of parameters
    """
    res = []
    for x, y in zip(p1, p2):
        res.append(x - y)
    return res


def callRemote(name, *args, **kwargs):
    """Invoke a method on the remote object with which I am associated.

        I always return a Deferred. This will fire with the results of the
        method when and if the remote end finishes. It will errback if any of
        the following things occur::

         the arguments do not match the schema I believe is in use by the
         far end (causes a Violation exception)

         the connection to the far end has been lost (DeadReferenceError)

         the arguments are not accepted by the schema in use by the far end
         (Violation)

         the method executed by the far end raises an exception (arbitrary)

         the return value of the remote method is not accepted by the schema
         in use by the far end (Violation)

         the connection is lost before the response is returned
         (ConnectionLost)

         the return value is not accepted by the schema I believe is in use
         by the far end (Violation)
        """


def natural_wavelength(gamma_factor, E, I, delta_f, W_sub):
    """Return the factored natural wavelength [m] i.e. the distance from prop to
    touchdown - JIP.

    :param float E: Young's Modulus [Pa]
    :param float I: Second moment of area [m^4]
    :param float delta_f: Imperfection height [m]
    :param W_sub float: Submerged pipe weight [kg/m^3]
    """
    return gamma_factor * (72 * E * I * delta_f / W_sub) ** (1 / 4)


def readbytes(path):
    """Read binary from file.
    """
    with open(path, 'rb') as f:
        return f.read()


def validate_type(data_dict: dict, type_name: str) ->dict:
    """Ensure that dict has field 'type' with given value."""
    data_dict_copy = data_dict.copy()
    if 'type' in data_dict_copy:
        if data_dict_copy['type'] != type_name:
            raise Exception('Object type must be {}, but was instead {}.'.
                format(type_name, data_dict['type']))
    else:
        data_dict_copy['type'] = type_name
    return data_dict_copy


def estimate_coef(clear_x, clear_y):
    """
    Linear regression function.

    :param clear_x: cleared_x
    :type clear_x : list
    :param clear_y: cleared_y
    :type clear_y : list
    :return: [slope,intercept]
    """
    try:
        n = len(clear_x)
        mean_x = sum(clear_x) / n
        mean_y = sum(clear_y) / n
        SS_xy = 0
        SS_xx = 0
        for index, item in enumerate(clear_x):
            SS_xx += item ** 2
            SS_xy += item * clear_y[index]
        SS_xx -= n * mean_x ** 2
        SS_xy -= n * mean_x * mean_y
        B1 = SS_xy / SS_xx
        B0 = mean_y - B1 * mean_x
        return [B1, B0]
    except (TypeError, ZeroDivisionError, OverflowError, ValueError):
        return [0, 0]


def get_preferred_sparse_format():
    """Get the preferred sparse matrix format supported by the backend.

    Different backends have their preferred backend. This info is useful when
    constructing a sparse matrix.
    """
    return 'coo'


def blackwhite(image):
    """Convert color images to black and white."""
    return image.convert('L')


def _set_sql_mode(sql_mode, dbapi_con, connection_rec):
    """Set the sql_mode session variable.

    MySQL supports several server modes. The default is None, but sessions
    may choose to enable server modes like TRADITIONAL, ANSI,
    several STRICT_* modes and others.

    Note: passing in '' (empty string) for sql_mode clears
    the SQL mode for the session, overriding a potentially set
    server default.
    """
    cursor = dbapi_con.cursor()
    cursor.execute('SET SESSION sql_mode = %s', [sql_mode])


def prettyPrintDictionary(d):
    """Pretty print a dictionary as simple keys and values"""
    maxKeyLength = 0
    maxValueLength = 0
    for key, value in list(d.items()):
        maxKeyLength = max(maxKeyLength, len(key))
        maxValueLength = max(maxValueLength, len(key))
    for key in sorted(d.keys()):
        print(('%' + str(maxKeyLength) + 's : %-' + str(maxValueLength) +
            's') % (key, d[key]))


def get_basic_number_rows():
    """Returns two lists, one of the 'top' row and one of the 'bottom' row of numbers.

    'The tiles are arranged into two groups: four "large numbers" (25, 50, 75 and 100)
    (12, 37, 62, 87 in some special episodes) and the remainder "small numbers",
    which comprise two each of the numbers 1 to 10.'
    https://en.wikipedia.org/wiki/Countdown_(game_show)#Numbers_round
    """
    top_row = [25, 50, 75, 100]
    bottom_row = []
    for i in range(1, 11):
        bottom_row.append(i)
        bottom_row.append(i)
    return top_row, bottom_row


def _get_out_object(ctx):
    """Returns out object from context

    :param om: out_message
    :return: out_object
    """
    om = ctx.descriptor.out_message
    oo = None
    if ctx.descriptor.is_out_bare():
        oo = next(iter(ctx.out_object))
    elif len(om._type_info) == 0:
        oo, = ctx.out_object
    elif len(om._type_info) == 1:
        om, = om._type_info.values()
        oo, = ctx.out_object
    else:
        oo = om.get_serialization_instance(ctx.out_object)
    return oo


def approve_version():
    """Approve the current unapproved version.
        """


def stub_false():
    """Returns ``False``.

    Returns:
        bool: False

    Example:

        >>> stub_false()
        False

    .. versionadded:: 4.0.0
    """
    return False


def del_eta_del_x(U, f, g, balance='geostrophic', R=None):
    """
    Calculate :mat: `\\frac{\\partial \\eta} {\\partial x}` for different
    force balances

    Parameters
    ----------
    U : array_like
        velocity magnitude [m/s]
    f : float
        Coriolis parameter
    d : float
        Acceleration of gravity
    balance : str, optional
              geostrophic [default], gradient or max_gradient
    R : float, optional
        Radius

    """
    if balance == 'geostrophic':
        detadx = f * U / g
    elif balance == 'gradient':
        detadx = (U ** 2 / R + f * U) / g
    elif balance == 'max_gradient':
        detadx = R * f ** 2 / (4 * g)
    return detadx


def mafft(pre, multifasta):
    """ performs default mafft alignment
    """
    msa = pre + '.mafft'
    cmd = 'mafft --retree 2 --reorder {multifasta} > {msa}'.format(**locals())
    return msa, cmd


@classmethod
def has_feature(cls, feature: int) ->bool:
    """Flash device feature"""
    try:
        features = cls.FEATURES
    except AttributeError:
        raise NotImplementedError('No FEATURES defined')
    return bool(features & feature)


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

        :param FileAddDetails val:
        :rtype: EventDetails
        """
    return cls('file_add_details', val)


def int_or_none(val):
    """Attempt to parse an integer value, or None."""
    if val is None:
        return val
    else:
        return int(val)


def int_to_bytes_str(value: int) ->bytes:
    """
    Converts a int value to a bytes array containing the numeric character.
    Ex: 123 -> b'123'
    :param value: int value to convert
    :return: bytes array
    """
    return str(value).encode('utf-8')


def find(iterable, conditional):
    """
    Looks through each value in the list, returning the first one that passes a truth test
    The function yields as soon as it finds an acceptable element, and doesn't traverse the entire iterable

    params: iterable, conditional
        iterable -> list, sequenece, set, dictionary, generator etc
        conditional -> a lambda or function that takes one or two inputs, first is element from iterable, second is index (optional)

    Examples:

    >>> list(_.find([1, 2, 3, 4, 5, 6], lambda x: x % 2 == 0))
    >>> [2]

    Since this returns a generator with a single value "next" can also be used to extract that value
    >>> next(_.find([1, 2, 3, 4, 5, 6], lambda x: x % 2 == 0))
    >>> 2

    TODO: What happens if nothing is matched, generator would raise an exception on next
    """
    for element in iterable:
        if conditional(element):
            yield element
            break


def build_option_parser(parser):
    """Hook to add global options"""
    return parser


@staticmethod
def iter_params():
    """return (ROL bits)"""
    for rol_bits in range(1, 8):
        yield rol_bits


def add_labels(raw_txt, labels):
    """
    给识别出来的标签增加表示，利于在UI上展示.

    比如标签“法院名称”，会被拓展成：北京市人民法院
    """
    if len(labels) == 0:
        return raw_txt
    label_format = '%s' % (' '.join(labels), raw_txt)
    return label_format


def write_file(path, content):
    """ Open a new file with the given path and write the content into it.
    """
    with open(path, 'w', encoding='utf-8') as f:
        f.write(content)


@classmethod
def FillUnitDatabaseWithPosc(cls, unit_database, fill_categories=True):
    """
        Fills a unit database with the posc values.

        :param UnitDatabase unit_database:
            The unit database to be filled.

        :param bool fill_categories:
            Indicates whether for each quantity type a category with the same name should be created.

        :rtype: UnitDatabase
        :returns:
            The unit database passed as a parameter.
        """
    from .posc import FillUnitDatabaseWithPosc
    unit_database.Clear()
    FillUnitDatabaseWithPosc(unit_database, fill_categories=fill_categories,
        override_categories=True)
    if fill_categories:
        for quantity_alias, quantity_type in cls._ADDITIONAL_CATEGORY_ALIASES.items(
            ):
            unit_database.AddCategory(quantity_alias, quantity_type)
    return unit_database


def unsubscribe():
    """Cancel a subscription. Once this method has been completed (and
        its Deferred has fired), no further messages will be received by the
        observer (i.e. the response to unsubscribe() will wait until all
        pending messages have been queued).

        This method is idempotent: calling it multiple times has the same
        effect as calling it just once."""
    return None


def Preparer(value):
    """
    A preparer is called after deserialization of a value but before
    that value is validated.

    Any modifications to ``value`` required should be made by
    returning the modified value rather than modifying in-place.

    If no modification is required, then ``value`` should be returned
    as-is.
    """


def is_sec_compressed(sec):
    """Return a boolean indicating if the sec represents a compressed public key."""
    return sec[:1] in (b'\x02', b'\x03')


def model_sed_abs(x, r):
    """ interpolate with r(Regli) at position x """
    test_tgm = x[:2]
    return r(test_tgm)[:-1]


def theta_Cl_H2AsO4_M83(T, P):
    """a-a': chloride dihydrogen-arsenate [M83]."""
    theta = 0.228
    valid = T == 298.15
    return theta, valid


def shquote(arg):
    """Quote an argument for later parsing by shlex.split()"""
    for c in ('"', "'", '\\', '#'):
        if c in arg:
            return repr(arg)
    if arg.split() != [arg]:
        return repr(arg)
    return arg


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

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

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


def findImplicitInputFile():
    """
    Find what input file the user *probably* wants to use,
    by scanning the current folder.
    In preference order:
    1. index.bs
    2. Overview.bs
    3. the first file with a .bs extension
    4. the first file with a .src.html extension
    """
    import glob
    import os
    if os.path.isfile('index.bs'):
        return 'index.bs'
    if os.path.isfile('Overview.bs'):
        return 'Overview.bs'
    allBs = glob.glob('*.bs')
    if allBs:
        return allBs[0]
    allHtml = glob.glob('*.src.html')
    if allHtml:
        return allHtml[0]
    return None


@classmethod
def from_xml_node(cls, xml_node):
    """
        Initialize the object from a XML node.
        :param xml_node: The XML node from which all necessary parameters will be parsed.
        :type xml_node: xml.etree.Element
        """
    raise NotImplementedError(
        'from_xml_node must be implemented by derived classes.')


def psi_H_Na_OH_HMW84(T, P):
    """c-c'-a: hydrogen sodium hydroxide [HMW84]."""
    psi = 0
    valid = T == 298.15
    return psi, valid


def warn(msg, category=UserWarning, stacklevel=2):
    """Generate a a warning with stacktrace.

    Parameters
    ----------
    msg : str
        The message of the warning.

    category : class
        The class of the warning to produce.

    stacklevel : int, optional
        How many steps above this function to "jump" in the stacktrace when
        displaying file and line number of the error message.
        Usually ``2``.

    """
    import warnings
    warnings.warn(msg, category=category, stacklevel=stacklevel)


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


def get_licenser_classes():
    """
    Get all licenser classes

    @return Return a dict contained licenser classes with their tags as key.
    """
    import sys
    import inspect
    members = inspect.getmembers(sys.modules[__name__], lambda member:
        inspect.isclass(member) and member.__module__ == __name__)
    classes_dict = dict()
    for name, member in members:
        if not name.endswith('Licenser'):
            continue
        if name == 'Licenser':
            continue
        classes_dict[member.tag] = member
    return classes_dict


def remove(participation):
    """Remove a participation."""


def index_doc(docid, context):
    """Add an object's info to the index."""


def unquote(s):
    """
    Undo the effects of quote(). Based heavily on urllib.unquote().
    """
    mychr = chr
    myatoi = int
    list = s.split('_')
    res = [list[0]]
    myappend = res.append
    del list[0]
    for item in list:
        if item[1:2]:
            try:
                myappend(mychr(myatoi(item[:2], 16)) + item[2:])
            except ValueError:
                myappend('_' + item)
        else:
            myappend('_' + item)
    return ''.join(res)


@classmethod
def get_real_child_model(cls, data):
    """Returns the real base class specified by the discriminator"""
    discriminator_value = data[cls.json_discriminator_key]
    return cls.discriminator_value_class_map.get(discriminator_value)


def renderHead():
    """Render the thead."""


def xpath_soup(element):
    """
    Generate xpath from BeautifulSoup4 element
    :param element: BeautifulSoup4 element.
    :type element: bs4.element.Tag or bs4.element.NavigableString
    :return: xpath as string
    :rtype: str

    Usage:

    >>> import bs4
    >>> html = (
    ...     '<title>title</title>'
    ...     '
p 1

p 2
'
    ...     )
    >>> soup = bs4.BeautifulSoup(html, 'html.parser')
    >>> xpath_soup(soup.html.body.p.i)
    '/html/body/p[1]/i'
    """
    components = []
    child = element if element.name else element.parent
    for parent in child.parents:
        """
        @type parent: bs4.element.Tag
        """
        siblings = parent.find_all(child.name, recursive=False)
        components.append(child.name if siblings == [child] else '%s[%d]' %
            (child.name, 1 + siblings.index(child)))
        child = parent
    components.reverse()
    return '/%s' % '/'.join(components)


@classmethod
def has(cls, blok):
    """ Return True if the blok is loaded

        :param blok: blok name
        :rtype: bool
        """
    return blok and blok in cls.ordered_bloks or False


def wipe_deploy_internal_info(node):
    """Remove temporary deployment fields from driver_internal_info."""
    info = node.driver_internal_info
    info.pop('agent_secret_token', None)
    info.pop('agent_secret_token_pregenerated', None)
    info['deploy_steps'] = None
    info.pop('agent_cached_deploy_steps', None)
    info.pop('deploy_step_index', None)
    info.pop('deployment_reboot', None)
    info.pop('deployment_polling', None)
    info.pop('skip_current_deploy_step', None)
    info.pop('steps_validated', None)
    info.pop('agent_url', None)
    node.driver_internal_info = info


@staticmethod
def options():
    """
        Subclasses must override the base class implementation.

        The method returns an `ordered dictionary`_. Each key is the
        name of a piece of public data to be managed by the Expert
        class. The object mapped to that key configures how the data
        is to be published. See the
        :py:meth:`declare <turberfield.utils.expert.Expert.declare>`
        method for details.

        .. _ordered dictionary: https://docs.python.org/3/library/collections.html#collections.OrderedDict
        """
    raise NotImplementedError


@staticmethod
def _set_object_transform_matrix(obj, vtk_tm):
    """Set ``obj``'s pose according to the transform ``vtk_tm``.

		:param obj: object to be modified
		:type obj: :class:`vtk.vtkProp3D`
		:param vtk_tm: homogeneous transform
		:type vtk_tm: :class:`vtk.vtkMatrix4x4`

		"""
    obj.PokeMatrix(vtk_tm)


def read_bytes(fh, byteorder, dtype, count):
    """Read tag data from file and return as byte string."""
    dtype = 'b' if dtype[-1] == 's' else byteorder + dtype[-1]
    return fh.read_array(dtype, count).tostring()


def closest_in_list(value, items):
    """Get nearest item from a list of items to the value"""
    return min(items, key=lambda x: abs(x - value))


def texsafe(text):
    """Escape text such that it is tex-safe."""
    conv = {'&': '\\&', '%': '\\%', '$': '\\$', '#': '\\#', '_': '\\_', '{':
        '\\{', '}': '\\}', '~': '\\textasciitilde{}', '^': '\\^{}', '\\':
        '\\textbackslash{}', '<': '\\textless', '>': '\\textgreater'}
    escaped = []
    for char in text:
        if char in conv:
            char = conv[char]
        escaped.append(char)
    return ''.join(escaped)


@classmethod
def LINNEAN_RANKS(cls):
    """ All main Linnean ranks ordered. """
    return (cls.KINGDOM, cls.PHYLUM, cls.CLASS, cls.ORDER, cls.FAMILY, cls.
        GENUS, cls.SPECIES)


def findExtname(fimg, extname, extver=None):
    """
    Returns the list number of the extension corresponding to EXTNAME given.
    """
    i = 0
    extnum = None
    for chip in fimg:
        hdr = chip.header
        if 'EXTNAME' in hdr:
            if hdr['EXTNAME'].strip() == extname.upper():
                if extver is None or hdr['EXTVER'] == extver:
                    extnum = i
                    break
        i += 1
    return extnum


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value


def process(off, leadVar, leadDeg, deg, pos, result, todoList):
    """Computes an inplace not exactly tensorproduct of the given
    basis functions (only the simplex of the single variable bases,
    as we limit the multi variable polynomials by a given maximum degree).
    """
    for v in range(leadVar):
        l = deg - leadDeg
        k = 1 + deg * v
        for d in range(1, deg - leadDeg + 1):
            l = deg + 1 - leadDeg - d
            result[:, pos:pos + l] = result[:, 1 + off:1 + off + l] * result[:,
                k:k + 1]
            if l > 1 and leadVar > 0:
                todoList.append((pos - 1, v, leadDeg + d))
            pos += l
            k += 1
            l -= 1
    return pos


def time_category(dtObj):
    """Return a time category, bed, home, work, given a dtObj."""
    if 9 <= dtObj.hour <= 17:
        return 'daytime'
    elif 5 <= dtObj.hour < 9:
        return 'morning'
    elif 17 < dtObj.hour < 23:
        return 'evening'
    else:
        return 'night'


@classmethod
def init_from_dict(cls, dict_obj):
    """Construct a model instance from a dictionary.

        This serves as a 2nd constructor

        :param dict_obj: dictionary object
        :returns o
        """
    o = cls('unnamed')
    o.provider_service_id = dict_obj.get('id', 'unknown_id')
    o.access_urls = dict_obj.get('access_urls', [])
    o.status = dict_obj.get('status', u'deploy_in_progress')
    o.domains_certificate_status = dict_obj.get('domains_certificate_status',
        {})
    o.name = dict_obj.get('name', None)
    o.error_info = dict_obj.get('error_info', None)
    o.error_message = dict_obj.get('error_message', None)
    o.error_class = dict_obj.get('error_class', None)
    return o


def idx2letter(idx):
    """Convert a numerical index to a char."""
    if 0 <= idx < 20:
        return chr(97 + idx)
    else:
        raise ValueError('A wrong idx value supplied.')


def footer(preamble_toc, cfr_toc, full_id):
    """Generate "navigation" context which allows the user to move between
    sections in the footer"""
    items = preamble_toc + cfr_toc
    nav = {'previous': None, 'next': None, 'page_type': 'preamble-section'}
    for idx, item in enumerate(items):
        if item.markup_id == full_id:
            if idx > 0:
                nav['previous'] = items[idx - 1]
            if idx < len(items) - 1:
                nav['next'] = items[idx + 1]
    return nav


def set_ants_transform_parameters(transform, parameters):
    """
    Set parameters of an ANTsTransform

    ANTsR function: `setAntsrTransformParameters`
    """
    transform.set_parameters(parameters)


def __insert_click_param(f, param):
    """
    Much like :func:`click.decorators._param_memo`, this updates
    the params on a command, but instead of append, it prepends
    the parameter
    :param function f:
    :param click.Parameter param:
    """
    if not hasattr(f, '__click_params__'):
        f.__click_params__ = []
    f.__click_params__.insert(0, param)


@staticmethod
def get_status_txt(job):
    """ Return string corresponding to status code """
    return job.get_status_display()


def size_filter(polar, min_delta, max_delta):
    """
    Accept a list of polar vectors
    Return a list of polar vectors with length between min_delta and max_delta
    """
    select = (polar[:, (0)] >= min_delta) * (polar[:, (0)] <= max_delta)
    return polar[select]


def setup_msdview(ax):
    """Builds the simulation mean squared deviation visualisation pane.

    Parameters
    ----------
    ax: Axes object
        The axes position that the pane should be placed in.
    """
    ax.plot([0], color='#34a5daff')
    ax.set_ylabel('MSD/m$^2$', fontsize=16)
    ax.set_xlabel('Time/s', fontsize=16)


@staticmethod
def _wrap_method(wrapper_infodict, cls):
    """Return a wrapped version of func.

        :param wrapper_infodict: The infodict to be used for constructing the
            wrapper.
        :param cls: Class to which the wrapper method will be added, this is
            used for the super call.
        """
    src = (
        'lambda %(signature)s: super(_wrapper_class_, _wrapper_class_).%(name)s(%(signature)s)'
         % wrapper_infodict)
    wrapped_func = eval(src, {'_wrapper_class_': cls})
    wrapped_func.__name__ = wrapper_infodict['name']
    wrapped_func.__doc__ = wrapper_infodict['doc']
    wrapped_func.__module__ = wrapper_infodict['module']
    wrapped_func.__dict__.update(wrapper_infodict['dict'])
    wrapped_func.__defaults__ = wrapper_infodict['defaults']
    return wrapped_func


def monkeypatch_django():
    """
    Monkeypatches support for us into parts of Django.
    """
    from django.contrib.staticfiles.management.commands.runserver import Command as StaticRunserverCommand
    from .management.commands.runserver import Command as RunserverCommand
    StaticRunserverCommand.__bases__ = RunserverCommand,


def reset():
    """Reset the state."""
    global GENERATORS
    GENERATORS = {}


def rho_YY(rho_SL_k, rho_SL_k_comp, rho_SL_l, rho_SL_l_comp, rho_SS_kl,
    rho_LL_kl, rho_YL_kl, rho_YL_lk):
    """
    rho_SL_k, rho_SL_k_comp:  G2F parameters for asset k
    rho_SL_l, rho_SL_l_comp:  G2F parameters for asset l
    rho_SS_kl, rho_LL_kl, rho_YL_kl, rho_YL_lk:  cross terms k-l
    """
    den = rho_SL_k_comp * rho_SL_l_comp
    num = (rho_SS_kl - rho_SL_k * rho_SL_l * rho_LL_kl - rho_SL_k *
        rho_SL_l_comp * rho_YL_lk - rho_SL_l * rho_SL_k_comp * rho_YL_kl)
    return num / den


@staticmethod
def name(cls):
    """For a filter or action return its name."""
    return cls.schema['properties']['type']['enum'][0]


@classmethod
def branch_type(cls, branch):
    """
        Return the string representation for the type of a branch
        """
    typename = branch.GetClassName()
    if not typename:
        leaf = branch.GetListOfLeaves()[0]
        typename = leaf.GetTypeName()
        leaf_count = leaf.GetLeafCount()
        if leaf_count:
            length = leaf_count.GetMaximum()
        else:
            length = leaf.GetLen()
        if length > 1:
            typename = '{0}[{1:d}]'.format(typename, length)
    return typename


def _parse_common(xml, the_dict):
    """
    Parse things in common for both variables and functions. This should
    be run after a more specific function like _parse_func or
    _parse_variable because it needs a member dictionary as an input.

    Parameters
    ----------
    xml : etree.Element
        The xml representation for the member you would like to parse

    the_dict : dict
        The dictionary that has already been filled with more specific
        data. This dictionary is modified in-place and an updated
        version is returned.

    Returns
    -------
    the_dict : dict
        The member dictionary that has been updated with the
        briefdescription and definition keys.
    """
    mem_bd = xml.find('briefdescription')
    try:
        mem_bdstr = mem_bd.find('para').text
        mem_bdstr = mem_bdstr if mem_bdstr is not None else ''
    except AttributeError:
        mem_bdstr = ''
    the_dict['briefdescription'] = mem_bdstr
    the_dict['definition'] = xml.find('definition').text
    return the_dict


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value


def expand_as_pair(input_):
    """Return a pair of same element if the input is not a pair.
    """
    if isinstance(input_, tuple):
        return input_
    else:
        return input_, input_


def p_length_timestamp(t):
    """length : TIMESTAMP"""
    from fractions import Fraction
    t[0] = Fraction(t[1], 75)


def define(hub):
    """
    Define how the watch requisite should behave
    """
    return {'result': True, 'changes_post': 'mod_watch'}


def get_block_device_info(instance, block_device_mapping):
    """Converts block device mappings for an instance to driver format.

    Virt drivers expect block device mapping to be presented in the format
    of a dict containing the following keys:

    - root_device_name: device name of the root disk
    - ephemerals: a (potentially empty) list of DriverEphemeralBlockDevice
                  instances
    - swap: An instance of DriverSwapBlockDevice or None
    - block_device_mapping: a (potentially empty) list of
                            DriverVolumeBlockDevice or any of it's more
                            specialized subclasses.
    """
    from nova.virt import block_device as virt_block_device
    block_device_info = {'root_device_name': instance.root_device_name,
        'ephemerals': virt_block_device.convert_ephemerals(
        block_device_mapping), 'block_device_mapping': virt_block_device.
        convert_all_volumes(*block_device_mapping)}
    swap_list = virt_block_device.convert_swap(block_device_mapping)
    block_device_info['swap'] = virt_block_device.get_swap(swap_list)
    return block_device_info


def keyconfig_remove():
    """Remove key config

    """
    pass


def build_options(port, source):
    """Create a configuration dict suitable to be used when deploying the GUI.

    Return None if no customized options are present.
    """
    options = {}
    if port is not None:
        options['port'] = port
    if source is not None:
        user, branch = source
        value = 'https://github.com/{}/juju-gui.git {}'.format(user, branch)
        options['juju-gui-source'] = value
    return options or None


@classmethod
def list_files(cls, directory):
    """Return the list of all file objects in the directory."""
    return cls.list_directory_content(directory, element_type='file')


def axis_labels_from_ctype(ctype, unit):
    """
    Returns axis labels for the given coordinate type and unit.

    Parameters
    ----------
    ctype: `str`
        Coordinate type.
    unit: `str`
        Required unit.

    Returns
    -------
    `str`
        "Axis Label [Unit]"
    """
    ctype_short = ctype[:4]
    labels = {'HGLN': f'Heliographic Longitude [{unit}]', 'CRLN':
        f'Carrington Longitude [{unit}]', 'HPLN':
        f'Helioprojective Longitude (Solar-X) [{unit}]', 'SOLX':
        f'Heliocentric X [{unit}]', 'HGLT': f'Latitude [{unit}]', 'CRLT':
        f'Latitude [{unit}]', 'HPLT':
        f'Helioprojective Latitude (Solar-Y) [{unit}]', 'SOLY':
        f'Heliocentric Y [{unit}]'}
    return labels.get(ctype_short, f'{ctype} [{unit}]')


def resolve_ref(schema_dict, ref):
    """
    Resolves a local ref in the form of ``#/definitions/dog`` or
    ``#/parameters/cat``.

    :param dict schema_dict: A raw, json-decoded schema.
    """
    kind, name = ref.split('/')[1:]
    return schema_dict[kind][name]


def _set_config(c):
    """Set gl configuration for template"""
    raise NotImplementedError


def is_valid_field(field, allow_quote=False, minimum=None, maximum=None):
    """
    Validates a generic user inputted field, such as a "name" for an
    object.  For now, it basically only validates whether single quote
    characters should be allowed in the string.

    :type field: str
    :param field: The data to be validated.

    :type allow_quote: bool
    :param allow_quote: If True, a single quote character (') will be allowed
        to pass validation.

    :type minimum: int
    :param minimum: If defined, values with fewer characters than this value
        will be rejected.

    :type maximum: int
    :param maximum: If defined, values with more characters than this value
        will be rejected.

    :rtype: bool
    :return: True or False depending on whether field passes validation.
    """
    if field is None:
        return False
    if not allow_quote and "'" in field:
        return False
    if minimum:
        if len(field) < minimum:
            return False
    if maximum:
        if len(field) > maximum:
            return False
    return True


def get_func_name(func):
    """Return a name which includes the module name and function name."""
    func_name = getattr(func, '__name__', func.__class__.__name__)
    module_name = func.__module__
    if module_name is not None:
        module_name = func.__module__
        return '{}.{}'.format(module_name, func_name)
    return func_name


def space_solar_power(x):
    """Return the radiant power density (W/m²) where x is the distance from  the sun (m)"""
    return 2.8942e+25 / x ** 2


@classmethod
def _from_dict(cls, _dict):
    """Initialize a ToneChatScore object from a json dictionary."""
    args = {}
    if 'score' in _dict:
        args['score'] = _dict.get('score')
    else:
        raise ValueError(
            "Required property 'score' not present in ToneChatScore JSON")
    if 'tone_id' in _dict:
        args['tone_id'] = _dict.get('tone_id')
    else:
        raise ValueError(
            "Required property 'tone_id' not present in ToneChatScore JSON")
    if 'tone_name' in _dict:
        args['tone_name'] = _dict.get('tone_name')
    else:
        raise ValueError(
            "Required property 'tone_name' not present in ToneChatScore JSON")
    return cls(**args)