def prepare_deformation_field_cmd(args, reg_params):
    """
    Prepares the niftyreg command to generate the deformation field from the
    control point file (allready generated in registration).
    :param args:
    :param reg_params:
    :return:
    """
    cmd = '{} -def {} {} -ref {}'.format(reg_params.transform_program_path,
        args.paths.control_point_file_path, args.paths.
        tmp__deformation_field, args.paths.downsampled_background)
    return cmd


def symmetryDict(M):
    """
    erstellt ein dict, was aus einer beliebigen Matrix M
    mittels M.subs(..) eine symmetrische Matrix macht
    """
    n, m = M.shape
    res = {}
    for i in range(1, n):
        for j in range(i):
            res[M[i, j]] = M[j, i]
    return res


def parse_keys(client, keys):
    """parse_keys will take in a list of keys, either just single model key
    names, or lists with a model and specific identifier, and return
    client.key objects
    """
    for key in keys:
        if isinstance(key, list):
            keys.append(client.key(key[0], key[1]))
        else:
            keys.append(client.key(key))
        return keys


@classmethod
def clear(cls, traces=True, enabler=True, dispatcher=True, loggers=False):
    """
        Clear the current thread's context of the named attributes.
        This will reset them to their default values.
        """
    if traces:
        cls._context.traces = []
    if enabler:
        cls._context.enabler = False
    if dispatcher:
        cls._context.dispatcher = None
    if loggers:
        cls._context.loggers = {}


def intersect_line_line(v1: 'mathutils.Vector', v2: 'mathutils.Vector', v3:
    'mathutils.Vector', v4: 'mathutils.Vector'):
    """Returns a tuple with the points on each line respectively closest to the other.

    :param v1: First point of the first line
    :type v1: 'mathutils.Vector'
    :param v2: Second point of the first line
    :type v2: 'mathutils.Vector'
    :param v3: First point of the second line
    :type v3: 'mathutils.Vector'
    :param v4: Second point of the second line
    :type v4: 'mathutils.Vector'
    """
    pass


def get_center_of_rectangle(rectangle):
    """
    Returns center of rectangle in carthesian coordinate system
    """
    return int((rectangle[0] + rectangle[2]) / 2), int((rectangle[1] +
        rectangle[3]) / 2)


def make_social_name(txt):
    """from a link like http://foo.com/username returns username"""
    return txt.split('/')[-1]


@staticmethod
def _interp_spatial(a):
    """
        Helper function for spatial interpolation.
        """
    import scipy.interpolate as si
    t, d, points, msk, grid_lat, grid_lon, method = a
    new_data = si.griddata(points, d[~msk], (grid_lat, grid_lon), method=method
        )
    return t, new_data


def find_insert_marker(filenames):
    """Searches for the insert marker and returns (filename, lineno).
    Defaults to the first file and last line if not found.
    """
    marker = 'FAVA-INSERT-MARKER'
    for filename in filenames:
        with open(filename, 'r') as file:
            for lineno, linetext in enumerate(file):
                if marker in linetext:
                    return filename, lineno
    return filenames[0], len(open(filenames[0]).readlines()) + 1


@classmethod
def __format_document__(cls, document):
    """Formats a :obj:`geolink_formatter.entity.Document` instance as HTML list item.

        Args:
            document (geolink_formatter.entity.Document): The document to be formatted.

        Returns:
            str: The document formatted as HTML list item.

        """
    if document.enactment_date:
        enactment_date = u'({0})'.format(document.enactment_date.strftime(
            '%d.%m.%Y'))
    else:
        enactment_date = u''
    if document.abrogation_date:
        files = u''
        strike_start = u''
        strike_end = u''
        abrogation_date = u'({0})'.format(document.abrogation_date.strftime
            ('%d.%m.%Y'))
    else:
        files = cls.__format_files__(document.files)
        strike_start = u''
        strike_end = u''
        abrogation_date = u''
    subtype = u' ({0})'.format(document.subtype) if document.subtype else u''
    return (
        u'
{strike_start}{type}{title} {enactment_date}{strike_end} {abrogation_date}{files}
'
        .format(type=u'{0}{1}: '.format(document.type or u'', subtype) if
        document.type or document.subtype else u'', title=document.title,
        enactment_date=enactment_date, files=files, strike_start=
        strike_start, strike_end=strike_end, abrogation_date=abrogation_date))


@staticmethod
def _blend_color_opacity(color, opacity):
    """ Blend color with white to simulate opacity

        Args:
            color (:obj:`int`): color (0-0xffffff)
            opacity (:obj:`int`): opacity (0-0xff)

        Returns:
            :obj:`int`: blended color
        """
    r = color >> 16
    g = color - r * 2 ** 16 >> 8
    b = color - r * 2 ** 16 - g * 2 ** 8
    w = 255
    r_opaque = round((r * opacity + w * (255 - opacity)) / 255)
    g_opaque = round((g * opacity + w * (255 - opacity)) / 255)
    b_opaque = round((b * opacity + w * (255 - opacity)) / 255)
    return (r_opaque << 16) + (g_opaque << 8) + b_opaque


def save_dirty():
    """Save all modified textures

    """
    pass


def _get_expr_indices(expr_dag, expr_code):
    """
    Get indices of all read/write expression in the expression dag which is represented as a list.
    :param expr_dag: The expression dag to search for read/write expressions.
    :param expr_code: The expression code.
    :return: A list of indices with all expressions that match the expression code.
    """
    expr_indices = []
    for iExp, expr in enumerate(expr_dag.expressions):
        if expr.code == expr_code:
            expr_indices.append(iExp)
    return expr_indices


def get_file_fd():
    """Return a file descriptor to access the file data.
        """


@classmethod
def dump(cls, content):
    """
        Transforms a dictionary to a string

        :param content: the dictionary to transform
        :type content: ``dict``

        :return: the related string

        """
    return cls.dump_dict(content, spaces=0).strip() + '\n'


def texture_paint_toggle():
    """Toggle texture paint mode in 3D view

    """
    pass


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

    Like 'git describe --tags --dirty --always -long'.
    The distance/hash is unconditional.

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


@classmethod
def cid(cls):
    """Processor class ID
        """
    return repr(cls) if cls._cid is None else cls._cid


def calculate_temperature_change(degree: int=0) ->tuple:
    """
    Turns a degree in a range from -100 to 100 into a RGB color conversion.

    Negative degrees cool the image (increase blues)

    Positive degrees heat the image (increase reds)

    :param degree: Integer: The intended color temperature change
    """
    degree = min(100, degree) if degree >= 0 else max(-100, degree)
    red = 255 if degree > 1 else round(255 - abs(degree) / 100 * 255)
    green = 255 if degree == 0 else round(255 - abs(degree) / 100 * 255)
    blue = 255 if degree < 1 else round(255 - abs(degree) / 100 * 255)
    return red, green, blue


def vert_select_ungrouped(extend: bool=False):
    """Select vertices without a group

    :param extend: Extend, Extend the selection
    :type extend: bool
    """
    pass


@staticmethod
def text_from_element(element):
    """the text value of an xml element"""
    if element is not None:
        value = element.text
    else:
        value = ''
    return value


def __getattr__(name):
    """Promise to provide __getattr__.
        """


@staticmethod
def get_quality_symbols():
    """returns a list of all allowed quality symbols in asc order:
            lowest--->highest
            !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~]
        """
    all_string = (
        '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~]'
        )
    return list(all_string)


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

    The ".dev0" means dirty.

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


def wrap_valid_longitude(lon):
    """ wrap a longitude value around to always have a value in the range
      [-180, +180) i.e 0 => 0, 1 => 1, -1 => -1, 181 => -179, -181 => 179
  """
    return (lon + 180.0) % 360.0 - 180.0


def get_close_matches_Levenshtein(word, possibilities, n=3, cutoff=0.6,
    full=False):
    """Replaces difflib.get_close_matches with faster algortihm based on
       Levenshtein.ratio.
       HINT: Similarity increase significatively after lower() and unidecode()

       Refs: https://en.wikipedia.org/wiki/Levenshtein_distance
    """
    import pandas as pd
    import Levenshtein
    if isinstance(possibilities, str):
        possibilities = [possibilities]
    rs = pd.DataFrame()
    MATCH = False
    for p in possibilities:
        similarity = Levenshtein.ratio(word, p)
        if similarity >= cutoff:
            MATCH = True
            rs = rs.append({'similarity': similarity, 'match': p},
                ignore_index=True)
    if MATCH:
        rs = rs.sort_values('similarity', ascending=False).reset_index(drop
            =True)
        if full:
            return list(rs['match'][:n].values), list(rs['similarity'][:n].
                values)
        else:
            return list(rs['match'][:n].values)
    elif full:
        return [], 0
    else:
        return []


def apris_human_alias(x):
    """
    A predefined function for convenience
    It extracts transcript IDs from the full names of appris genomes.
    """
    return x.split('|')[4]


@classmethod
def butter(cls, filtertype, freq, samplerate, order=5, numid=None):
    """
        filtertype: one of 'low', 'high', 'band'
        freq      : cutoff freq -- (low, high) for bandpass filter
        samplerate: samplerate of the simulation
        order     : order of the filter

        Returns --> a Filter
        """
    assert filtertype in ('low', 'high', 'band')
    from sndfileio import dsp
    b, a = dsp.filter_butter_coeffs(filtertype, freq, samplerate=samplerate,
        order=order)
    return cls(b, a, numid=numid)


def apply_mask(matrix, mask_pattern, matrix_size, is_encoding_region):
    """    Applies the provided mask pattern on the `matrix`.

    ISO/IEC 18004:2015(E) -- 7.8.2 Data mask patterns (page 50)

    :param tuple matrix: A tuple of bytearrays
    :param mask_pattern: A mask pattern (a function)
    :param int matrix_size: width or height of the matrix
    :param is_encoding_region: A function which returns ``True`` iff the
            row index / col index belongs to the data region.
    """
    for i in range(matrix_size):
        for j in range(matrix_size):
            if is_encoding_region(i, j):
                matrix[i][j] ^= mask_pattern(i, j)


def get_facts(device):
    """
    Determines ifd_style fact based on the personality.
    """
    ifd_style = 'CLASSIC'
    if device.facts['personality'] == 'SWITCH':
        ifd_style = 'SWITCH'
    elif device.facts['personality'] == 'JDM':
        ifd_style = None
    return {'ifd_style': ifd_style}


def select_next_item():
    """Select the next element (using selection order)

    """
    pass


def handle_command(server, process, command):
    """
    Parse and handle a single command from a client.

    This is the main entry point for the commands module.

    :param server: The NuttsshServer object for the current connection.
    :param process: The SSHServerProcess object created by AsyncSSH for this
                    command channel.
    :param command: The command to execute. This is either the string passed by
                    the SSH client, or None when no command was passed (and a
                    shell was requested).
    """
    list(server, process)


def ChopHexStr(hexstr):
    """Takes a hex string and divides it into strings of length 2 (each
    representing a byte) and places them in a list. Returns the list.
    """
    tmp = hexstr
    bytes = []
    while tmp:
        bytes += [tmp[:2]]
        tmp = tmp[2:]
    return bytes


def get_tiddlers_from_bag(bag):
    """
    Yield the individual :py:class:`tiddlers <tiddlyweb.model.tiddler.Tiddler>`
    that are in a :py:class:`bag <tiddlyweb.model.bag.Bag>`.

    The tiddlers return are empty objects that have not been loaded from
    the :py:class:`store <tiddlyweb.store.Store>`.

    Rarely used, see :py:func:`tiddlyweb.store.Store.list_bag_tiddlers`.
    """
    for tiddler in bag.store.list_bag_tiddlers(bag):
        yield tiddler


@classmethod
def get_avaliable_property_certificates_from_council(cls, council_id,
    session=None):
    """
        Avaliable prop certs are those that aren't deprecated (deprecated = False)
        """
    return cls.get_session(session).query(cls).filter(cls.council_id ==
        council_id, cls.deprecated == False).order_by(cls.visual_order.asc())


def pack(tup):
    """
    Packs a tuple of 8-bit integers.

    :param tup: Tuple of 8-bit integers.
    :type tup: tuple
    :return: The packed n-bit value, where n is len(tup) * 8.
    :rtype: int
    """
    size = len(tup)
    result = 0
    for i in range(size):
        result = tup[i] << i * 8 | result
    return result


def swap_data():
    """Swap 2 sequencer strips

    """
    pass


@staticmethod
def short_name_type():
    """
        Returns the short name type for this port.

        :returns: string
        """
    return 'e'


def BLMdimList(sType='stacked'):
    """
    Return standard list of dimensions for calculated BLM.

    Parameters
    ----------
    sType : string, optional, default = 'stacked'
        Selected 'stacked' or 'unstacked' dimensions.
        Set 'sDict' to return a dictionary of unstacked <> stacked dims mappings for use with xr.stack({dim mapping}).

    Returns
    -------
    list : set of dimension labels.

    """
    if sType is 'stacked':
        return ['Euler', 'Eke', 'BLM']
    elif sType is 'sDict':
        return {'BLM': ['l', 'm'], 'Euler': ['P', 'T', 'C']}
    else:
        return ['Eke', 'l', 'm', 'P', 'T', 'C']


def to_list(x, allow_tuple=False):
    """Normalizes a list/tensor into a list.

    If a tensor is passed, we return
    a list of size 1 containing the tensor.

    # Arguments
        x: target object to be normalized.
        allow_tuple: If False and x is a tuple,
            it will be converted into a list
            with a single element (the tuple).
            Else converts the tuple to a list.

    # Returns
        A list.
    """
    if isinstance(x, list):
        return x
    if allow_tuple and isinstance(x, tuple):
        return list(x)
    return [x]


def find_duplicate_keys(data):
    """
    Find duplicate keys in a layer of ordered pairs. Intended as the object_pairs_hook callable
    for json.load or loads.

    :param data: ordered pairs
    :return: Dictionary with no duplicate keys
    :raises ValueError if duplicate keys are found
    """
    out_dict = {}
    for key, value in data:
        if key in out_dict:
            raise ValueError('Duplicate key: {}'.format(key))
        out_dict[key] = value
    return out_dict


@staticmethod
def patch(method, replacement, class_=None):
    """This method replaces m_method with a p_replacement method, but
           keeps p_method on its class under name
           "_base_<initial_method_name>_". In the patched method, one may use
           Hack.base to call the base method. If p_method is static, you must
           specify its class in p_class_."""
    isStatic = class_
    class_ = class_ or method.im_class
    name = isStatic and method.func_name or method.im_func.__name__
    baseName = '_base_%s_' % name
    if isStatic:
        method = staticmethod(method)
        replacement = staticmethod(replacement)
    setattr(class_, baseName, method)
    setattr(class_, name, replacement)


@staticmethod
def determine_dicom_zipname(filenames, series_label):
    """Return a filename for the dicom series that is unique to a container

        Args:
            filenames (dict): A map of series uids to filenames
            series_label (str): The base to use for the filename

        Returns:
            str: The filename for the zipped up series
        """
    filename = series_label + '.dicom.zip'
    duplicate = 1
    while filename in filenames.values():
        filename = series_label + f'_dup-{duplicate}.dicom.zip'
    return filename


@classmethod
def property(cls, icls):
    """replicate standard @property decorator"""
    obj = cls(icls)
    obj.is_property = True
    return obj


def gt(value, other):
    """Checks if `value` is greater than `other`.

    Args:
        value (number): Value to compare.
        other (number): Other value to compare.

    Returns:
        bool: Whether `value` is greater than `other`.

    Example:

        >>> gt(5, 3)
        True
        >>> gt(3, 5)
        False
        >>> gt(5, 5)
        False

    .. versionadded:: 3.3.0
    """
    return value > other


def ends_with_semi_colon(contents: str) ->bool:
    """
    Returns `True` if a given line ends with a semi-colon.
    """
    contents = contents.strip()
    return contents.endswith(';') and not contents == '};'


def yield_chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


@classmethod
def indentation(cls):
    """
        Return the number of spaces for the next indentation level.

        :returns: indentation
        :rtype: int
        """
    return len(cls._EDGE_STR)


@staticmethod
def all(n, k):
    """
        A generator that returns all of the compositions of n into k parts.
        :param n: integer to compose
        :type n: int
        :param k: number of parts to compose
        :type k: int
        :return: a list of k-elements which sum to n

        Compositions are an expression of n as a sum k parts, including zero
        terms, and order is important.  For example, the compositions of 2
        into 2 parts:

        >>> compositions(2,2) = [2,0],[1,1],[0,2].

        NOTE: There are C(n+k-1,n) partitions of n into k parts.  See:
        `Stars and Bars <https://en.wikipedia.org/wiki/Stars_and_bars_(combinatorics)>`_.
        """
    t = n
    h = 0
    a = [0] * k
    a[0] = n
    yield list(a)
    while a[k - 1] != n:
        if t != 1:
            h = 0
        t = a[h]
        a[h] = 0
        a[0] = t - 1
        a[h + 1] += 1
        h += 1
        yield list(a)


@classmethod
def filter_field(cls):
    """Return a field that can be used as a unique key for this Resource.

        :returns: A field that can be used as a unique key.
        :rtype: str
        """
    if cls._filter_field is None:
        with cls._filter_field_lock:
            if cls._filter_field is None:
                cls._filter_field = cls._schema().filterable_key()
    return cls._filter_field


def vertex_weight_delete(weight_group: int=-1):
    """Delete this weight from the vertex (disabled if vertex group is locked)

    :param weight_group: Weight Index, Index of source weight in active vertex group
    :type weight_group: int
    """
    pass


def quantized_concat(*data, **kwargs):
    """Joins input arrays along a given axis.

    The dimensions of the input arrays should be the same except the axis along
    which they will be concatenated.
    The dimension of the output array along the concatenated axis will be equal
    to the sum of the corresponding dimensions of the input arrays.
    All inputs with different min/max will be rescaled by using largest [min, max] pairs.
    If any input holds int8, then the output will be int8. Otherwise output will be uint8.

    Defined in src/operator/quantization/quantized_concat.cc:L108
    This function support variable length of positional input.

    Parameters
    ----------
    data : Symbol[]
        List of arrays to concatenate
    dim : int, optional, default='1'
        the dimension to be concated.

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


@classmethod
def maptag(cls, tag, fn):
    """
        Map (override) tag => I{class} mapping.
        @param tag: An xsd tag name.
        @type tag: str
        @param fn: A function or class.
        @type fn: fn|class.
        """
    cls.tags[tag] = fn


def read_file_str(file_path):
    """
    Read the target file string.

    Parameters
    ----------
    file_path : str
        Path of target file.

    Returns
    -------
    file_str : str
        The target string read.
    """
    with open(file_path, mode='r', encoding='utf-8') as f:
        file_str = f.read()
    return file_str


@staticmethod
def calc_depth_tor(mag: float, mechanism: str) ->float:
    """Calculate an estimate of the depth to top of rupture (km).

        Parameters
        ----------
        mag : float
            moment magnitude of the event (:math:`M_w`)
        mechanism : str
            fault mechanism. Valid options: "U", "SS", "NS",
            "RS".

        Returns
        -------
        depth_tor : float
            estimated depth to top of rupture (km)

        """
    if mechanism == 'RS':
        depth_tor = 2.704 - 1.226 * max(mag - 5.849, 0)
    else:
        depth_tor = 2.673 - 1.136 * max(mag - 4.97, 0)
    return max(depth_tor, 0) ** 2


def split_box(fraction, x, y, w, h):
    """Return set of two boxes where first is the fraction given"""
    if w >= h:
        new_w = int(w * fraction)
        if new_w:
            return (x, y, new_w, h), (x + new_w, y, w - new_w, h)
        else:
            return None, None
    else:
        new_h = int(h * fraction)
        if new_h:
            return (x, y, w, new_h), (x, y + new_h, w, h - new_h)
        else:
            return None, 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 _clean_query_string(q):
    """Clean up a query string for searching.

    Removes unmatched parentheses and joining operators.

    Arguments:
        q (str): Query string to be cleaned

    Returns:
        str: The clean query string.
    """
    q = q.replace('()', '').strip()
    if q.endswith('('):
        q = q[:-1].strip()
    if q[-3:] == 'AND' or q[-3:] == 'NOT':
        q = q[:-3]
    elif q[-2:] == 'OR':
        q = q[:-2]
    while q.count('(') > q.count(')'):
        q += ')'
    while q.count(')') > q.count('('):
        q = '(' + q
    return q.strip()


@staticmethod
def parse_next_word(gen):
    """Skip the newlines the parser provides."""
    word = next(gen)
    while word == '\n':
        word = next(gen)
    return word


@classmethod
def make(cls, path, data, stat):
    """Creates a new NodeData tuple.

        :returns: A :class:`~kazoo.recipe.cache.NodeData` instance.
        """
    return cls((path, data, stat))


def _format_servers_list_power_state(state):
    """Return a formatted string of a server's power state

    :param state: the power state number of a server
    :rtype: a string mapped to the power state number
    """
    power_states = ['NOSTATE', 'Running', '', 'Paused', 'Shutdown', '',
        'Crashed', 'Suspended']
    try:
        return power_states[state]
    except Exception:
        return 'N/A'


def createMainWidget(argv):
    """
    Function to create the main widget.

    @param argv list of commandline parameters (list of strings)
    @return reference to the main widget (QWidget)
    """
    from PluginManager.PluginUninstallDialog import PluginUninstallWindow
    return PluginUninstallWindow()


def analyze_results(results):
    """
    Check the results of the dependency analyses and report errors

    :type results: list[pordego_dependency.analysis_result.AnalysisResult]
    :raise: AssertionError
    """
    errors = []
    for result in results:
        if result.has_error:
            errors.extend(result.error_messages)
    if errors:
        raise AssertionError('\n\n'.join(errors))


def showInvLines(rh):
    """
    Produce help output related to command synopsis

    Input:
       Request Handle
    """
    if rh.subfunction != '':
        rh.printLn('N', 'Usage:')
    rh.printLn('N', '  python ' + rh.cmdName + ' DeleteVM <userid> directory')
    rh.printLn('N', '  python ' + rh.cmdName + ' DeleteVM help')
    rh.printLn('N', '  python ' + rh.cmdName + ' DeleteVM version')
    return


@classmethod
def create(cls, options=None):
    """Create new network interface for host"""
    cls.command_sub = 'create'
    cls.execute(cls._construct_command(options), output_format='csv')


def _is_descriptor(obj):
    """Returns True if obj is a descriptor, False otherwise."""
    return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj,
        '__delete__')


@classmethod
def from_degrees(cls, degrees):
    """Returns `degrees` converted to time instance.

           >>> Time.from_degrees (0)
           Time (0, 0, 0, 0)
           >>> Time.from_degrees (360)
           Time (0, 0, 0, 0)
           >>> Time.from_degrees (180)
           Time (12, 0, 0, 0)
           >>> Time.from_degrees (90)
           Time (6, 0, 0, 0)
           >>> Time.from_degrees (135)
           Time (9, 0, 0, 0)
        """
    return cls.from_decimal_hours(degrees % 360.0 / 15.0)


@staticmethod
def fileid(file_or_id):
    """Gets the ID of a given :class:`StoredFile`

        If the given parameter is already a StoredFile id it will
        directly return it.
        """
    return getattr(file_or_id, 'file_id', file_or_id)


def _is_dunder(name):
    """Returns True if a __dunder__ name, False otherwise."""
    return name[:2] == name[-2:] == '__' and name[2:3] != '_' and name[-3:-2
        ] != '_' and len(name) > 4


def str_replace(string, i, val):
    """Replace string[i] with val and return new string."""
    assert len(val) == 1
    return string[:i] + val + string[i + 1:]


def str_fsize(sz):
    """Format a size int/float to the most appropriate string."""
    if sz < 1024:
        return '%.1f bytes' % sz
    sz /= 1024.0
    if sz < 1024:
        return '%.1f Kb' % sz
    sz /= 1024.0
    if sz < 1024:
        return '%.1f Mb' % sz
    sz /= 1024.0
    return '%.1f Gb' % sz


def interpolate_value(x, y, t):
    """Find the value of x: y(x) = t."""
    if t > max(y) or t < min(y):
        raise RuntimeError('t outside of [%f, %f]' % (min(y), max(y)))
    for j in range(1, len(x)):
        x0 = x[j - 1]
        y0 = y[j - 1]
        x1 = x[j]
        y1 = y[j]
        if (y0 - t) * (y1 - t) < 0:
            return x0 + (t - y0) * (x1 - x0) / (y1 - y0)


def arctan(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise inverse tangent of the input array.

    The output is in the closed interval :math:`[-\\pi/2, \\pi/2]`

    .. math::
       arctan([-1, 0, 1]) = [-\\pi/4, 0, \\pi/4]

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

       - arctan(default) = default
       - arctan(row_sparse) = row_sparse
       - arctan(csr) = csr

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

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

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


def to_binary_seed(seed_phrase, passphrase='', language='english'):
    """Derive a 64-byte binary seed from a mnemonic seed phrase.

    Return a pair (binary_seed, seed_phrase_type), where seed_phrase_type
    is one of the following strings:
    - 'BIP-0039'
    - 'BIP-0039 and Electrum standard'
    - 'BIP-0039 and Electrum segwit'
    - 'BIP-0039 and Electrum 2FA'
    - 'Old (pre 2.0) Electrum'
    - 'Electrum standard'
    - 'Electrum segwit'
    - 'Electrum 2FA'
    - 'UNKNOWN'

    If seed_phrase is a BIP39-compliant phrase for the specfied language
    (this condition covers the first four cases listed above), generate
    the binary seed as recommended by BIP39. Otherwise, if seed_phrase
    is an Electrum seed phrase (this condition covers the next four cases
    listed above), generate the binary seed by using Electrum's algorithm.
    Otherwise (this is the last case listed above), generate the binary
    seed in a non-standard way.

    Keyword arguments:
    passphrase -- an optional extension of the seed phrase (default: '')
    language -- the language for a BIP-0039 seed phrase (default: 'english')
    """
    import hashlib
    import hmac
    from pbkdf2 import PBKDF2
    from mnemonic import Mnemonic
    from .electrum_mnemonic import normalize_text, is_new_electrum_seed_phrase, ELECTRUM_SEED_PREFIX_SW, ELECTRUM_SEED_PREFIX_2FA, electrum_seed_type
    seed_phrase = normalize_text(seed_phrase)
    passphrase = normalize_text(passphrase)
    m = Mnemonic(language)
    if m.check(seed_phrase):
        seed_phrase_type = 'BIP-0039'
        if is_new_electrum_seed_phrase(seed_phrase):
            seed_phrase_type += ' and Electrum standard'
        elif is_new_electrum_seed_phrase(seed_phrase, ELECTRUM_SEED_PREFIX_SW):
            seed_phrase_type += ' and Electrum segwit'
        elif is_new_electrum_seed_phrase(seed_phrase, ELECTRUM_SEED_PREFIX_2FA
            ):
            seed_phrase_type += ' and Electrum 2FA'
        salt = 'mnemonic' + passphrase
    else:
        seed_phrase_type = electrum_seed_type(seed_phrase)
        salt = ('electrum' if seed_phrase_type != 'UNKNOWN' else 'non-standard'
            ) + passphrase
    PBKDF2_ROUNDS = 2048
    binary_seed = PBKDF2(seed_phrase, salt, iterations=PBKDF2_ROUNDS,
        macmodule=hmac, digestmodule=hashlib.sha512).read(64)
    return binary_seed, seed_phrase_type


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

    The ".dev0" means dirty.

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


@staticmethod
def crc32_xfer(data):
    """
        Returns the 32 bit CRC (XFER algorithm) of the provided bytes

        Compatible with CRC-32/XFER from https://crccalc.com/?method=crc32
        If the returned crc is appended to the original data and run back through
        this function the result will be 0.
        :param bytes,bytearray data: bytes to calculate crc on
        :return int: crc of input data
        """
    data = data.encode() if isinstance(data, str) else data
    _poly = 175
    crc = 0
    highbit = 1 << 32 - 1
    mask = highbit - 1 << 1 | 1
    poly = _poly
    shift = 32 - 8
    diff8 = -shift
    if diff8 > 0:
        mask = 255
        crc <<= diff8
        shift = 0
        highbit = 128
        poly = _poly << diff8
    for byte in data:
        crc ^= byte << shift
        for i in range(8):
            if crc & highbit:
                crc = crc << 1 ^ poly
            else:
                crc = crc << 1
        crc &= mask
    if diff8 > 0:
        crc >>= diff8
    return crc


def hard_light(image1, image2):
    """
    Superimposes two images on top of each other using the Hard Light algorithm

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


def split_sequence_into_dict_and_nondicts(*args):
    """Separate dict and non-dict items. Merge dicts and merge non-dicts

    Elements are combined in the order that they appear.  i.e. non-dict items
    will be appended to a combined list as they are encounterd.  Repeated dict
    keys will be overridded by the latest value.

    Parameters
    ----------
    *args : one or more positional items
        Mixture of dict and non-dict.

    Returns
    -------
    merged_non_dict : list
        List of non dictionary items.
    merged_dict : dict
        Merged dictionary.

    """
    merged_non_dict = []
    merged_dict = dict()
    for v in args:
        if isinstance(v, dict):
            merged_dict.update(v)
        else:
            merged_non_dict.append(v)
    return merged_non_dict, merged_dict


def printarg(d):
    """
	Prints all the arguments from given arguments
	"""
    print(
        'Verbose switch is set to on. All functions would be printed\nArgs:\n')
    print('-' * 25)
    for i in d.items():
        print('{:12}|{}'.format(i[0], i[1]))
    print('-' * 25)
    return


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


def mirror_distance_object(focal_point, distance_image):
    """Usage: Find distance of object with focal point and distance of image"""
    numerator = focal_point * distance_image
    denominator = distance_image - focal_point
    return numerator / denominator


def enable_radius(DirectoryId=None, RadiusSettings=None):
    """
    Enables multi-factor authentication (MFA) with the Remote Authentication Dial In User Service (RADIUS) server for an AD Connector directory.
    See also: AWS API Documentation

    :example: response = client.enable_radius(
        DirectoryId='string',
        RadiusSettings={
            'RadiusServers': [
                'string',
            ],
            'RadiusPort': 123,
            'RadiusTimeout': 123,
            'RadiusRetries': 123,
            'SharedSecret': 'string',
            'AuthenticationProtocol': 'PAP'|'CHAP'|'MS-CHAPv1'|'MS-CHAPv2',
            'DisplayLabel': 'string',
            'UseSameUsername': True|False
        }
    )

    :type DirectoryId: string
    :param DirectoryId: [REQUIRED]
            The identifier of the directory for which to enable MFA.

    :type RadiusSettings: dict
    :param RadiusSettings: [REQUIRED]
            A RadiusSettings object that contains information about the RADIUS server.
            RadiusServers (list) --An array of strings that contains the IP addresses of the RADIUS server endpoints, or the IP addresses of your RADIUS server load balancer.
            (string) --
            RadiusPort (integer) --The port that your RADIUS server is using for communications. Your on-premises network must allow inbound traffic over this port from the AWS Directory Service servers.
            RadiusTimeout (integer) --The amount of time, in seconds, to wait for the RADIUS server to respond.
            RadiusRetries (integer) --The maximum number of times that communication with the RADIUS server is attempted.
            SharedSecret (string) --Not currently used.
            AuthenticationProtocol (string) --The protocol specified for your RADIUS endpoints.
            DisplayLabel (string) --Not currently used.
            UseSameUsername (boolean) --Not currently used.

    :rtype: dict
    :return: {}

    """
    pass


def longest_leg(all_amounts):
    """
    Find the longest leg between amounts.

    Args:
        all_amounts: list of amounts.
    Returns:
        index of logest leg.
    """
    firsts = []
    for amounts in all_amounts:
        if len(amounts) == 0:
            firsts.append(0)
        else:
            firsts.append(abs(amounts[0]))
    return firsts.index(max(firsts))


@classmethod
def from_rva(cls, rva, owner):
    """
        Loads address translator with RVA
        """
    return cls(rva, owner)


def stepTextChanged(build, step, text):
    """The text for a step has been updated.

        This is called when calling setText() on the step status, and
        hands in the text list."""


def computeLogSubTicks(ticks, lowBound, highBound):
    """Return the sub ticks for the log scale for all given ticks if subtick
    is in [lowBound, highBound]

    :param ticks: log10 of the ticks
    :param lowBound: the lower boundary of ticks
    :param highBound: the higher boundary of ticks
    :return: all the sub ticks contained in ticks (log10)
    """
    if len(ticks) < 1:
        return []
    res = []
    for logPos in ticks:
        dataOrigPos = logPos
        for index in range(2, 10):
            dataPos = dataOrigPos * index
            if lowBound <= dataPos <= highBound:
                res.append(dataPos)
    return res


def _adjustPixelSize(wldWidth, wldHeight, pixWidth, pixHeight):
    """Used by :func:`calcPixelWidth` and :func:`calcPixelHeight`.

    Potentially reduces the given pixel width/height such that the
    display space aspect ratio is maintained.
    """
    if any((pixWidth == 0, pixHeight == 0, wldWidth == 0, wldHeight == 0)):
        return 0, 0
    pixRatio = float(pixWidth) / pixHeight
    wldRatio = float(wldWidth) / wldHeight
    if pixRatio > wldRatio:
        pixWidth = wldWidth * (pixHeight / wldHeight)
    elif pixRatio < wldRatio:
        pixHeight = wldHeight * (pixWidth / wldWidth)
    return pixWidth, pixHeight


def python_3000_backticks(logical_line):
    """Backticks are removed in Python 3: use repr() instead.

    Okay: val = repr(1 + 2)
    W604: val = `1 + 2`
    """
    pos = logical_line.find('`')
    if pos > -1:
        yield pos, "W604 backticks are deprecated, use 'repr()'"


def adjust_key(key, shape):
    """Prepare a slicing tuple (key) for slicing an array of specific shape."""
    if type(key) is not tuple:
        key = key,
    if Ellipsis in key:
        if key.count(Ellipsis) > 1:
            raise IndexError("an index can only have a single ellipsis ('...')"
                )
        ellipsis_pos = key.index(Ellipsis)
        missing = (slice(None),) * (len(shape) - len(key) + 1)
        key = key[:ellipsis_pos] + missing + key[ellipsis_pos + 1:]
    if len(key) > len(shape):
        raise IndexError('too many indices for array')
    if len(key) < len(shape):
        missing = (slice(None),) * (len(shape) - len(key))
        key += missing
    return key


def change_endianness(b: bytes) ->bytes:
    """Reverse a bytestring"""
    return b[::-1]


def month_and_year(datetimes):
    """Return the month and year of given dates."""
    return datetimes.astype('datetime64[M]', copy=False)


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

        :param FilePreviewDetails val:
        :rtype: EventDetails
        """
    return cls('file_preview_details', val)


def verify_account_id(account_id):
    """
    Verify Account ID

    :type account_id: str|int
    :param account_id: Account ID

    :return: Fixed account ID
    :rtype: int
    """
    account_id = str(account_id)
    if len(account_id) != 32:
        raise ValueError('The Account ID should be of length 32. Given: {}.'
            .format(account_id))
    return account_id


def deregister_job_definition(jobDefinition=None):
    """
    Deregisters an AWS Batch job definition.
    See also: AWS API Documentation

    Examples
    This example deregisters a job definition called sleep10.
    Expected Output:

    :example: response = client.deregister_job_definition(
        jobDefinition='string'
    )

    :type jobDefinition: string
    :param jobDefinition: [REQUIRED]
            The name and revision (name:revision ) or full Amazon Resource Name (ARN) of the job definition to deregister.

    :rtype: dict
    :return: {}

    """
    pass


def getTransitionById(transition_id):
    """Get transition with transition_id.
        """


def normal2SD(x, y, z):
    """Converts a normal vector to a plane (given as x,y,z)
    to a strike and dip of the plane using the Right-Hand-Rule.
    Input:
        x: The x-component of the normal vector
        y: The y-component of the normal vector
        z: The z-component of the normal vector
    Output:
        strike: The strike of the plane, in degrees clockwise from north
        dip: The dip of the plane, in degrees downward from horizontal
    """
    from math import asin, atan2, sqrt, degrees
    z = -z
    r = sqrt(x * x + y * y + z * z)
    plunge = degrees(asin(z / r))
    bearing = degrees(atan2(y, x))
    bearing = 90 - bearing
    if bearing < 0:
        bearing += 360
    if plunge < 0:
        plunge = -plunge
        bearing -= 180
        if bearing < 0:
            bearing += 360
    strike = bearing + 90
    dip = 90 - plunge
    if strike > 360:
        strike -= 360
    return strike, dip


def _get_key_recursively(response, key, limit):
    """ Recursively search for a key in a response
    Not really sure if that's the most elegant solution."""
    if response is None:
        raise TypeError(
            'Either provide a response or a URL for the next_page and previous_page methods'
            )
    stack = [response]
    iters_performed = 0
    while iters_performed < limit and len(stack) > 0:
        for dct in stack:
            key_found = dct.get(key)
            if key_found is not None:
                return key_found
        new_stack = []
        for dct in stack:
            for k, v in dct.items():
                if type(v) == dict:
                    new_stack.append(v)
        stack = new_stack
        iters_performed += 1
    return None


def _simplifie_chaines(valeur):
    """
    Transforme les listes imbriquées d’un seul élément en scalaire, sauf si l’élément est un tuple.

    :param valeur:
        (list[str|tuple]) Valeur à simplifier.
    :returns:
        (list[str|tuple]|str|tuple) Valeur éventuellement simplifiée.
    """
    original = valeur
    while isinstance(valeur, list) and len(valeur) == 1:
        valeur = valeur[0]
    if isinstance(valeur, str) or isinstance(valeur, tuple) and isinstance(
        valeur[0], int):
        return valeur
    return original


@classmethod
def fromkeys(cls, iterable, value=None, callback=lambda : None):
    """ dict.fromkeys(S[,v]) -> New csvdict with keys from S and values
        equal to v. v defaults to None. """
    new_csvd = cls(callback)
    for key in iterable:
        new_csvd[key] = value
    return new_csvd


def addLanguage(language):
    """Add Language to Translation Domain"""


def popitem():
    """ Pop the item with key k from the dictionary and return it as a
        two-tuple (k, v).  If k doesn't exist, raise a KeyError."""


def p_maybe_nline(p):
    """ maybe_nline : newlines
                    | empty """
    pass


@classmethod
def from_dataframe(cls, dataframe, column, offset=0):
    """
        Creates and return a Series from a DataFrame and specific column

        :param dataframe: raccoon DataFrame
        :param column: column name
        :param offset: offset value must be provided as there is no equivalent for a DataFrame
        :return: Series
        """
    return cls(data=dataframe.get_entire_column(column, as_list=True),
        index=dataframe.index, data_name=column, index_name=dataframe.
        index_name, sort=dataframe.sort, offset=offset)


def onebp_inserts(seq):
    """Generate all variants of sequence with 1bp insert.

    Assumes unambiguous IUPAC codes A, C, G, T only.
    """
    seq = seq.upper()
    variants = set()
    for i in range(len(seq)):
        for s in 'ACGT':
            variants.add(seq[:i] + s + seq[i:])
    for s in 'ACGT':
        variants.add(seq + s)
    return variants


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

    The ".dev0" means dirty.

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


@classmethod
def all(cls):
    """Retrieve all instances"""
    return cls.builder()


def index_power(array, n):
    """
        Find Nth power of the element with index N.
    """
    if n >= len(array):
        return -1
    return array[n] ** n


def hex_byte(byte):
    """
    Return the hex string for this byte. 00-ff.
    """
    if byte not in range(0, 256):
        raise ValueError(byte)
    return hex(byte)[2:].rjust(2, '0')


@staticmethod
def _estimate_read_time(length):
    """"estimates the read time for a call to read_from_device without COM_BUS_RESET_TIME
        based on empirical measurements of one prt_hw_model and 5 prt_e_model"""
    return length * 0.002075 + 0.070727


def make_local_dict(params):
    """Convert the "local" field to a dictionary

    Args:
        params (dict): plotting parameters

    Returns:
        an updated params
    """
    new_local = dict()
    for p in params['local']:
        k = p['which_panel']
        new_local[k] = p
    params['local'] = new_local
    return params


def human_readable_size(size, precision=0):
    """ Convert size in bytes to a more readable form. """
    i, units = 0, ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    while size > 1024 and i < len(units):
        i += 1
        size /= 1024
    return '%.*f%s' % (precision, size, units[i])


def __init__(config, rrset_channel, changes_channel, metrics=None):
    """Initialize a Reconciler Plugin client."""


@classmethod
def header_hash(cls, header):
    """Given a header return the hash."""
    return cls.HEADER_HASH(header)


@staticmethod
def p_predefined(p):
    """predefined : generic_parameter_list"""
    p[0] = p[1]


def csv_append(csv_string, item):
    """
    Appends an item to a comma-separated string.

    If the comma-separated string is empty/None, just returns item.
    """
    if csv_string:
        return ','.join((csv_string, item))
    else:
        return item


@classmethod
def is_task(cls, obj):
    """
        Returns true is an object is a build task.
        """
    return isinstance(obj, cls)


def iterable_method_call(iterable, method, unpack, *args):
    """Call a method on each element of an iterable

    iterable[i].method(arg)

    Parameters
    ----------
    iterable : sequence etc.
        Iterable whos members will have thier attribute changed.
    method : string
        Method to call.
    unpack : bool
        If True then each member of `*args` will be unpacked before passing to
        method.
    *args : positional arguments
        If a single positional argument then all members of `iterable`
        will have their method called with the same single argument.
        If more that one positional argument then
        iterable[0].method will be called with args[0],
        iterable[1].method will be set to args[1] etc.
        Skip elements by having corresponding value of *args=None.

    """
    if len(args) == 0:
        for i in iterable:
            getattr(i, method)()
        return
    if len(args) == 1:
        if not args[0] is None:
            if unpack:
                for i in iterable:
                    getattr(i, method)(*args[0])
            else:
                for i in iterable:
                    getattr(i, method)(args[0])
        return
    if len(args) > 1:
        for i, a in enumerate(args):
            if unpack:
                if not a is None:
                    getattr(iterable[i], method)(*a)
            elif not a is None:
                getattr(iterable[i], method)(a)
        return


def _unitrange(x):
    """Scaling function for :class:`Scaler`. Performs ``(x - min(x)) / (max(x) - min(x))``.
    Consider using :func:`unitrange` instead."""
    scaling_center = x.min(axis=0)
    scaling_factor = x.max(axis=0) - scaling_center
    return scaling_center, scaling_factor


def supplements(parms, countrate=None):
    u"""Supplementary parameters:
        Effective number of freely diffusing particles in 3D solution:
        [11] n3D = n*F
        Effective number particles diffusing on 2D surface:
        [12] n2D = n*(1-F)
    """
    n = parms[0]
    F3d = parms[3]
    Info = list()
    Info.append([u'n3D', n * F3d])
    Info.append([u'n2D', n * (1.0 - F3d)])
    if countrate is not None:
        cpp = countrate / n
        Info.append([u'cpp [kHz]', cpp])
    return Info


@classmethod
def all(cls, client=None, **kwargs):
    """Retrieve all user records (limited by pagination) as Users.

        Args:
            client (Client): an instance of the API Client
            per_page (int, str): (opt) number of records to retrieve
            page (int, str): (opt) page number to retrieve
            query (str): (opt) substring to filter for in user names/emails

        Returns:
            list: containing 0 or more User instances
        """
    response = client.users.get(**kwargs)
    return cls.multiple_from_response(client, response['users'])


def iedges_to_geometry_results(iedges_all, geometry_array, results_array):
    """
    Takes the iedges and slices the geometry/results to isolate the rings
    or C shapes.
    """
    geometry = []
    results = []
    for iedges in iedges_all:
        geometryi = geometry_array[(iedges), :]
        resultsi = results_array[iedges]
        geometry.append(geometryi)
        results.append(resultsi)
    return geometry, results


def is_list(i):
    """Converts entered value into a list"""
    i = i.split(' ')
    return i


def write_file(filename, content, mode='w'):
    """write_file will open a file, "filename" and write content, "content"
    and properly close the file
    """
    with open(filename, mode) as filey:
        filey.writelines(content)
    return filename


@classmethod
def with_default_starting_params(cls, y, components):
    """Factory method for starting model parameters.

        Parameters
        ----------
        y: array-like of floats
            Time series
        components: Components
            Components used in the model

        Returns
        -------
        ModelParams
            Default starting params.
        """
    alpha = 0.09
    if components.seasonal_periods.sum() > 16:
        alpha = 1e-06
    beta = None
    phi = None
    if components.use_trend:
        beta = 0.05
        if components.seasonal_periods.sum() > 16:
            beta = 5e-07
        phi = 1
        if components.use_damped_trend:
            phi = 0.999
    gamma_params = None
    if len(components.seasonal_periods) > 0:
        gamma_params = [0.001] * components.gamma_params_amount()
    box_cox_lambda = cls.find_initial_box_cox_lambda(y, components)
    return cls(components=components, alpha=alpha, beta=beta, phi=phi,
        gamma_params=gamma_params, box_cox_lambda=box_cox_lambda)


def normal_curl_evar(curl_evar, unscaled_r, scaled_r):
    """ Normalise a variable proportional to the curl of the electric field

    Parameters
    -----------
    curl_evar : (float)
        Variable related to electric field (e.g. vorticity)
    unscaled_r : (float)
        Radius of polar cap in degrees
    scaled_r : (float)
        Radius of normalised OCB polar cap in degrees

    Returns
    --------
    nvar : (float)
        Normalised variable

    Notes
    -------
    Assumes that the cross polar cap potential is fixed across the polar cap
    regardless of the radius of the Open Closed field line Boundary.  This is
    commonly assumed when looking at statistical patterns that control the IMF
    (which accounts for dayside reconnection) and assume that the nightside
    reconnection influence is averaged out over the averaged period.

    References
    -----------
    Chisham, G. (2017), A new methodology for the development of high‐latitude
    ionospheric climatologies and empirical models, Journal of Geophysical
    Research: Space Physics, doi:10.1002/2016JA023235.
    """
    nvar = curl_evar * (unscaled_r / scaled_r) ** 2
    return nvar


def region_scale():
    """Scale selected area

    """
    pass


def _apply_text_method(text_data, transformer=None):
    """
    Applies a text based method to the given data, for example
    a Lemmatizer, Stemmer, etc.

    Parameters
    ----------
    text_data : str
        Text data to transform

    transformer : Transformation object, optional
        trasnformer applied on the data, for example
        lemmatizer, stemmer, etc. , by default None

    Returns
    -------
    str
        Transformed data
    """
    transformed_text_data = ''
    for word in text_data.split():
        transformed_text_data += f'{transformer(word)} '
    return transformed_text_data.strip()


def weights_from_file_weighted_samples(file_weighted_samples) ->[float]:
    """Open the file "multinest.txt" and extract the weight values of every accepted live point as a list."""
    weighted_samples = open(file_weighted_samples)
    total_samples = 0
    for line in weighted_samples:
        total_samples += 1
    weighted_samples.seek(0)
    log_likelihoods = []
    for line in range(total_samples):
        weighted_samples.read(4)
        log_likelihoods.append(float(weighted_samples.read(24)))
        weighted_samples.readline()
    weighted_samples.close()
    return log_likelihoods


def _generate_facet(config):
    """Make facet string for query from facet configurations.

    A facet configuration is a dictionary with specific fields.

    Facet can be of three types:

    1. field
    2. count
    3. pivot

    There are global configurations for all facet types. These are specified
    in the following fields:

    1. limit
    2. sort
    3. mincount

    For field type facet you must specify the following fields:

    1. field
        Field with which to bucketize documents. This field can be a list of
        fields.

    For range type facet you must specify the following fields:

    1. range
        Field with which to bucketize documents.
    2. start
    3. end
    4. step

    For pivot type facet you must specify the following fields:

    1. pivot
        List of fields with which to bucketize documents.

    For more information of faceting checkout the solr documentation:
    https://lucene.apache.org/solr/guide/6_6/faceting.html

    """
    if config is None:
        config = {}
    if len(config) == 0:
        return ''
    elements = ['facet=true']
    if 'field' in config:
        field = config['field']
        if not isinstance(field, (list, tuple)):
            field = [field]
        for field_ in field:
            elements.append('facet.field={}'.format(field_))
        if 'mincount' in config:
            mincount = config['mincount']
            elements.append('facet.mincount={}'.format(mincount))
    elif 'range' in config:
        field = config['range']
        elements.append('facet.range={}'.format(field))
        start = config['start']
        end = config['end']
        gap = config['gap']
        elements.extend(['facet.range.start={}'.format(start),
            'facet.range.end={}'.format(end), 'facet.range.gap={}'.format(gap)]
            )
        if 'mincount' in config:
            mincount = config['mincount']
            elements.append('facet.mincount={}'.format(mincount))
    elif 'pivot' in config:
        fields = config['pivot']
        elements.append('facet.pivot={}'.format(','.join(fields)))
        if 'mincount' in config:
            mincount = config['mincount']
            elements.append('facet.pivot.mincount={}'.format(mincount))
    if 'limit' in config:
        limit = config['limit']
        elements.append('facet.limit={}'.format(limit))
    if 'sort' in config:
        sortby = config['sort']
        elements.append('facet.sort={}'.format(sortby))
    return '&{}'.format('&'.join(elements))


def clear_dictionaries():
    """Delete all dictionaries"""
    global _inode_index
    _inode_index = None


@classmethod
def get_object(cls, api_token, domain, record_id):
    """
            Class method that will return a Record object by ID and the domain.
        """
    record = cls(token=api_token, domain=domain, id=record_id)
    record.load()
    return record


def getWarningHeader():
    """
    Returns the 'warning' part in output file
    """
    str = ''
    return str


def json_to_macro_listeners(ctx, data, macro_objects):
    """
    m = ctx._manager
    for i in data:
        cell = find_sl(ctx, i["cell"])
        macro_object = macro_objects["macro_target"])
        macro_arg = i["macro_arg"]
        m.add_macro_listener(cell, macro_object, macro_arg)
    """
    pass


def zerocopy_from_dgl_ndarray(input):
    """Zerocopy a dgl.ndarray.NDArray to framework-specific Tensor

    Parameters
    ----------
    input : dgl.ndarray.NDArray

    Returns
    -------
    Tensor
    """
    pass


def get_name(s_file):
    """Return sample name from file path."""
    return s_file.split('/')[-1].replace('.gz', '').replace('.bed', ''
        ).replace('.xl', '')


@classmethod
def is_plugin_enabled_by_default(cls):
    """
        Each plugin can overwrite the default value of whether a
        plugin should be enabled if the value is not explicitly
        set in the configuration

        """
    return True


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


def load_settings(file_path, module_name='', secret_key=''):
    """ a method to load data from json valid files

    :param file_path: string with path to settings file
    :param module_name: [optional] string with name of module containing file path
    :param secret_key: [optional] string with key to decrypt drep file
    :return: dictionary with settings data
    """
    title = 'load_settings'
    try:
        _path_arg = '%s(file_path=%s)' % (title, str(file_path))
    except:
        raise ValueError('%s(file_path=...) must be a string.' % title)
    from os import path
    if module_name:
        try:
            _path_arg = _path_arg.replace(')', ', module_name=%s)' % str(
                module_name))
        except:
            raise ValueError('%s(module_name=...) must be a string.' % title)
        from importlib.util import find_spec
        module_path = find_spec(module_name).submodule_search_locations[0]
        file_path = path.join(module_path, file_path)
    if not path.exists(file_path):
        raise ValueError('%s is not a valid file path.' % _path_arg)
    ext_map = {}
    file_extensions = {'json': '.+\\.json$', 'json.gz': '.+\\.json\\.gz$',
        'yaml': '.+\\.ya?ml$', 'yaml.gz': '.+\\.ya?ml\\.gz$', 'drep':
        '.+\\.drep$'}
    import re
    for key, value in file_extensions.items():
        file_pattern = re.compile(value)
        if file_pattern.findall(file_path):
            ext_map[key] = True
        else:
            ext_map[key] = False
    if ext_map['json']:
        import json
        try:
            file_data = open(file_path, 'rt')
            file_details = json.loads(file_data.read())
        except:
            raise ValueError('%s is not valid json data.' % _path_arg)
    elif ext_map['yaml']:
        import yaml
        try:
            file_data = open(file_path, 'rt')
            file_details = yaml.full_load(file_data.read())
        except:
            raise ValueError('%s is not valid yaml data.' % _path_arg)
    elif ext_map['json.gz']:
        import gzip
        import json
        try:
            file_data = gzip.open(file_path, 'rb')
        except:
            raise ValueError('%s is not valid gzip compressed data.' %
                _path_arg)
        try:
            file_details = json.loads(file_data.read().decode())
        except:
            raise ValueError('%s is not valid json data.' % _path_arg)
    elif ext_map['yaml.gz']:
        import gzip
        import yaml
        try:
            file_data = gzip.open(file_path, 'rb')
        except:
            raise ValueError('%s is not valid gzip compressed data.' %
                _path_arg)
        try:
            file_details = yaml.full_load(file_data.read().decode())
        except:
            raise ValueError('%s is not valid yaml data.' % _path_arg)
    elif ext_map['drep']:
        from labpack.compilers import drep
        try:
            file_data = open(file_path, 'rb').read()
            file_details = drep.load(encrypted_data=file_data, secret_key=
                secret_key)
        except:
            raise ValueError('%s is not valid drep data.' % _path_arg)
    else:
        raise ValueError('%s must be one of %s file types.' % (_path_arg,
            list(ext_map.keys())))
    return file_details


def _guess_platform_tag(epd_platform):
    """ Guess the platform tag from the given epd_platform.

    Parameters
    ----------
    epd_platform : EPDPlatform or None
    """
    if epd_platform is None:
        return None
    else:
        return epd_platform.pep425_tag


@classmethod
def get(cls, client, name):
    """Get a storage_pool by name.

        Implements GET /1.0/storage-pools/<name>

        :param client: The pylxd client object
        :type client: :class:`pylxd.client.Client`
        :param name: the name of the storage pool to get
        :type name: str
        :returns: a storage pool if successful, raises NotFound if not found
        :rtype: :class:`pylxd.models.storage_pool.StoragePool`
        :raises: :class:`pylxd.exceptions.NotFound`
        :raises: :class:`pylxd.exceptions.LXDAPIExtensionNotAvailable` if the
            'storage' api extension is missing.
        """
    client.assert_has_api_extension('storage')
    response = client.api.storage_pools[name].get()
    storage_pool = cls(client, **response.json()['metadata'])
    return storage_pool


@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
    """Construct a Crumb from a sequence or iterable."""
    result = new(cls, iterable)
    if 3 < len(result) < 7:
        raise TypeError('Expected 4-6 arguments, got %d' % len(result))
    return result


def split():
    """Split off selected geometry from connected unselected geometry

    """
    pass


@classmethod
def can_handle(cls, filepath: str) ->bool:
    """Determines if a given file can be handled by the current archive.

        Args:
            filepath (str): The filepath to check if can be handled
        """
    header = cls.header_struct.parse_file(filepath)
    return header.magic == b'BTDX' and header.version >= 1


def set_notify(where):
    """Where to report errors."""
    global WHERE
    WHERE = where


@staticmethod
def _get_parent_dn(dn):
    """
        Gets the dn of the parent object
        Meant to be overridden by inheriting classes.
        Raises exception if not overridden.

        :returns: string containing dn
        """
    return dn.split('/adj-')[0]


def bhp2watts(bhp):
    """convert brake horsepower (bhp) to watts"""
    return bhp * 745.7


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

        :param PaperContentRestoreDetails val:
        :rtype: EventDetails
        """
    return cls('paper_content_restore_details', val)


def get_form_weight(form):
    """Try to get form weight attribute"""
    try:
        return form.weight
    except AttributeError:
        return 0


def get_ubuntu_distribution_version():
    """
    Discover and return Ubuntu distribution version.

    :return: the Ubuntu distribution version of the build server.
    example: xenial, bionic
    """
    import distro
    distribution = distro.linux_distribution()
    if distribution[0] == 'Ubuntu' and distribution[1] == '16.04':
        return 'xenial'
    elif distribution[0] == 'Ubuntu' and distribution[1] == '18.04':
        return 'bionic'
    else:
        raise ValueError('Unsupported distribution', distribution)


def collection_duplicate():
    """Recursively duplicate the collection, all its children, objects and object data

    """
    pass


@classmethod
def transformToNative(cls, obj):
    """
        Turn a ContentLine or Component into a Python-native representation.

        If appropriate, turn dates or datetime strings into Python objects.
        Components containing VTIMEZONEs turn into VtimezoneComponents.

        """
    return obj


@classmethod
def alias_for(cls, field: str) ->str:
    """Return aliased field name.

        :param field: OPTIMADE field name
        :type field: str

        :return: Aliased field as found in PROVIDER_ALIASES + ALIASES
        :rtype: str
        """
    return dict(cls.all_aliases()).get(field, field)


def class_hook(cls, data):
    """Called for each class in a header"""


def _extract_prop_general(line):
    """
    Extract the (key, value)-tuple from a "standard" property line like:
    >>> 'hardware ethernet 12:34:56:78:90:AB'
    :param line:
    :return: tuple (key, value)
    """
    pos = line.find(' ')
    return line[:pos], line[pos + 1:]


@classmethod
def unregister_plugins(cls, plugins):
    """
        Unreguster plugins. The plugins parameter may be any iterable of models, or dict having models as keys,

        Just calls an unregister_plugin for every such a model.
        """
    for model in plugins:
        cls.unregister_plugin(model)


@classmethod
def instance(cls):
    """
        Get the singleton instance.

        @return: (object).
        @raise DoesNotExist: if instance does not exist.
        """
    return cls.objects.get(pk=cls.__PK)


@classmethod
def findContext(cls, ctxId):
    """ Special helper - look for a context given the ID.  If that
        doesn't work, look using the context as a name
        """
    ctx = cls.read(ctxId)
    if not ctx:
        lst = cls.objects(name=ctxId)
        if lst:
            ctx = lst[0]
    return ctx


def nptype(dtype):
    """ converts to numpy types

    :param dtype: h5 writer type type
    :type dtype: :obj:`str`
    :returns: nupy type
    :rtype: :obj:`str`
    """
    if str(dtype) in ['string', b'string']:
        return 'str'
    return dtype


def intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2):
    """Takes 2 segments (defined by 4 vectors) and returns a vector for their point of intersection or None.

	Warning: Despite its name, this function works on segments, and not on lines.

	Parameters:
	lineA_p1 (mathutils.Vector) – First point of the first line
	lineA_p2 (mathutils.Vector) – Second point of the first line
	lineB_p1 (mathutils.Vector) – First point of the second line
	lineB_p2 (mathutils.Vector) – Second point of the second line

	Returns: The point of intersection or None when not found

	Return type: mathutils.Vector or None"""
    from . import Vector
    return Vector


@classmethod
def geom_col_name(cls):
    """
        Return the name of the metadata column used to store the feature
        geometry column.
        """
    return 'f_geometry_column'


@classmethod
def from_string(cls, string: str) ->'Mode':
    """Get an enum value from a string, defaulting to NORMAL."""
    encode = {'average': cls.AVERAGE, 'critical': cls.CRIT, 'maximum': cls.MAX}
    return encode.get(string.lower(), cls.NORMAL)


def save_rdb(dic, keys, file):
    """
    From a disctionary 'dic' saves the columns related to the specified 'keys' into an .rdb file named 'file'.
    """
    out = open(file, 'w')
    n_keys = len(keys)
    for k in range(n_keys):
        if k != n_keys - 1:
            out.write('{}\t'.format(keys[k]))
        else:
            out.write('{}'.format(keys[k]))
    out.write('\n')
    for k in range(n_keys):
        if k != n_keys - 1:
            out.write('{}\t'.format('-' * len(keys[k])))
        else:
            out.write('{}'.format('-' * len(keys[k])))
    out.write('\n')
    for i in range(len(dic[keys[0]])):
        for k in range(n_keys):
            if k != n_keys - 1:
                out.write('{}\t'.format(dic[keys[k]][i]))
            else:
                out.write('{}'.format(dic[keys[k]][i]))
        out.write('\n')
    out.close()


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


def data(filename):
    """Read numerical data from an OOMMF `.odt` file.

    This function reads data from an OOMMF `.odt` file and returns it
    as a list of floats.

    Parameters
    ----------
    filename : str
        Name of an OOMMF `.odt` file

    Returns
    -------
    list(float)

    Examples
    --------
    1. Reading data from an OOMMF `.odt` file.

    >>> import os
    >>> import oommfodt as oo
    ...
    >>> odtfile = os.path.join(os.path.dirname(__file__),
    ...                        'tests', 'test_sample', 'file3.odt')
    >>> data = oo.data(odtfile)
    >>> type(data)
    <class 'list'>

    """
    with open(filename) as f:
        lines = f.readlines()
    values = []
    for line in lines:
        if not line.startswith('#'):
            values.append(list(map(float, line.split())))
    return values


@staticmethod
def get_dummy():
    """
        Dummy method to generate initial i18n
        """
    from django.utils import translation
    return translation.gettext_noop('Dummy')


def format_commit_lines(web_url: str, repo: repo, base: int, tip: int) ->str:
    """
    Format the per-commit information for the message, including the one-line
    commit summary and a link to the diff if a web URL has been configured:
    """
    if web_url:
        rev_base_url = web_url.rstrip('/') + '/rev/'
    commit_summaries = []
    for rev in range(base, tip):
        rev_node = repo.changelog.node(rev)
        rev_ctx = repo[rev_node]
        one_liner = rev_ctx.description().split('\n')[0]
        if web_url:
            summary_url = rev_base_url + str(rev_ctx)
            summary = '* [{summary}]({url})'.format(summary=one_liner, url=
                summary_url)
        else:
            summary = '* {summary}'.format(summary=one_liner)
        commit_summaries.append(summary)
    return '\n'.join(summary for summary in commit_summaries)


def askopenfilename(**kwargs):
    """Return file name(s) from Tkinter's file open dialog."""
    try:
        from Tkinter import Tk
        import tkFileDialog as filedialog
    except ImportError:
        from tkinter import Tk, filedialog
    root = Tk()
    root.withdraw()
    root.update()
    filenames = filedialog.askopenfilename(**kwargs)
    root.destroy()
    return filenames


def provideReferenceLayer(reference):
    """Return an object implementing IReferenceLayer."""


def aggregate_probability(probability: float, delta_t: float) ->float:
    """Transform the specified *probability* value, intended to represent
    a probability for events tested each time unit, into the
    probability for the specified time step (*delta_t*).

    Parameters
    ----------
    probability: float
        the probability value of an event (during 1 time unit)
    delta_t: float
        the value of the time step (expressed in time units)

    Returns
    -------
    float:
        the probability of the event during *delta_t* time units.
    """
    return 1 - (1 - probability) ** delta_t


def get_datatype_odim(datatype):
    """
    maps the config file radar data type name into the corresponding odim
    data type name and Py-ART field name

    Parameters
    ----------
    datatype : str
        config file radar data type name

    Returns
    -------
    metranet type : dict
        dictionary containing the odim data type name and its
        corresponding Py-ART field name

    """
    if datatype == 'dBZ':
        field_name = 'reflectivity'
        datatype_odim = 'DBZH'
    elif datatype == 'dBuZ':
        field_name = 'unfiltered_reflectivity'
        datatype_odim = 'TH'
    elif datatype == 'dBZc':
        field_name = 'corrected_reflectivity'
        datatype_odim = 'DBZHC'
    elif datatype == 'dBuZc':
        field_name = 'corrected_unfiltered_reflectivity'
        datatype_odim = 'THC'
    elif datatype == 'dBZv':
        field_name = 'reflectivity_vv'
        datatype_odim = 'DBZV'
    elif datatype == 'dBZvc':
        field_name = 'corrected_reflectivity_vv'
        datatype_odim = 'DBZVC'
    elif datatype == 'dBuZv':
        field_name = 'unfiltered_reflectivity_vv'
        datatype_odim = 'TV'
    elif datatype == 'dBuZvc':
        field_name = 'corrected_unfiltered_reflectivity_vv'
        datatype_odim = 'TVC'
    elif datatype == 'dBZ_bias':
        field_name = 'reflectivity_bias'
        datatype_odim = 'ZBIAS'
    elif datatype == 'eta_h':
        field_name = 'volumetric_reflectivity'
        datatype_odim = 'etah'
    elif datatype == 'eta_v':
        field_name = 'volumetric_reflectivity_vv'
        datatype_odim = 'etav'
    elif datatype == 'rcs_h':
        field_name = 'radar_cross_section_hh'
        datatype_odim = 'RCSH'
    elif datatype == 'rcs_v':
        field_name = 'radar_cross_section_vv'
        datatype_odim = 'RCSV'
    elif datatype == 'ZDR':
        field_name = 'differential_reflectivity'
        datatype_odim = 'ZDR'
    elif datatype == 'ZDRu':
        field_name = 'unfiltered_differential_reflectivity'
        datatype_odim = 'ZDRU'
    elif datatype == 'ZDRc':
        field_name = 'corrected_differential_reflectivity'
        datatype_odim = 'ZDRC'
    elif datatype == 'ZDRuc':
        field_name = 'corrected_unfiltered_differential_reflectivity'
        datatype_odim = 'ZDRUC'
    elif datatype == 'ZDR_prec':
        field_name = 'differential_reflectivity_in_precipitation'
        datatype_odim = 'ZDRPREC'
    elif datatype == 'ZDR_snow':
        field_name = 'differential_reflectivity_in_snow'
        datatype_odim = 'ZDRSNOW'
    elif datatype == 'dBm':
        field_name = 'signal_power_hh'
        datatype_odim = 'DBMH'
    elif datatype == 'dBmv':
        field_name = 'signal_power_vv'
        datatype_odim = 'DBMV'
    elif datatype == 'Nh':
        field_name = 'noisedBZ_hh'
        datatype_odim = 'NDBZH'
    elif datatype == 'Nv':
        field_name = 'noisedBZ_vv'
        datatype_odim = 'NDBZV'
    elif datatype == 'SNRh':
        field_name = 'signal_to_noise_ratio_hh'
        datatype_odim = 'SNRH'
    elif datatype == 'SNRv':
        field_name = 'signal_to_noise_ratio_vv'
        datatype_odim = 'SNRV'
    elif datatype == 'SQI':
        field_name = 'normalized_coherent_power'
        datatype_odim = 'SQIH'
    elif datatype == 'SQIv':
        field_name = 'normalized_coherent_power_vv'
        datatype_odim = 'SQIV'
    elif datatype == 'dBm_sun_hit':
        field_name = 'sun_hit_power_h'
        datatype_odim = 'DBM_SUNHIT'
    elif datatype == 'dBmv_sun_hit':
        field_name = 'sun_hit_power_v'
        datatype_odim = 'DBMV_SUNHIT'
    elif datatype == 'ZDR_sun_hit':
        field_name = 'sun_hit_differential_reflectivity'
        datatype_odim = 'ZDR_SUNHIT'
    elif datatype == 'dBm_sun_est':
        field_name = 'sun_est_power_h'
        datatype_odim = 'DBM_SUNEST'
    elif datatype == 'dBmv_sun_est':
        field_name = 'sun_est_power_v'
        datatype_odim = 'DBMV_SUNEST'
    elif datatype == 'ZDR_sun_est':
        field_name = 'sun_est_differential_reflectivity'
        datatype_odim = 'ZDR_SUNEST'
    elif datatype == 'sun_pos_h':
        field_name = 'sun_hit_h'
        datatype_odim = 'POSH_SUNHIT'
    elif datatype == 'sun_pos_v':
        field_name = 'sun_hit_v'
        datatype_odim = 'POSV_SUNHIT'
    elif datatype == 'sun_pos_zdr':
        field_name = 'sun_hit_zdr'
        datatype_odim = 'POSZDR_SUNHIT'
    elif datatype == 'RhoHV':
        field_name = 'cross_correlation_ratio'
        datatype_odim = 'RHOHV'
    elif datatype == 'uRhoHV':
        field_name = 'uncorrected_cross_correlation_ratio'
        datatype_odim = 'URHOHV'
    elif datatype == 'RhoHVc':
        field_name = 'corrected_cross_correlation_ratio'
        datatype_odim = 'RHOHVC'
    elif datatype == 'RhoHV_rain':
        field_name = 'cross_correlation_ratio_in_rain'
        datatype_odim = 'RHOHVRAIN'
    elif datatype == 'L':
        field_name = 'logarithmic_cross_correlation_ratio'
        datatype_odim = 'LRHOHV'
    elif datatype == 'CDR':
        field_name = 'circular_depolarization_ratio'
        datatype_odim = 'CDR'
    elif datatype == 'LDR':
        field_name = 'linear_polarization_ratio'
        datatype_odim = 'LDR'
    elif datatype == 'PhiDP':
        field_name = 'differential_phase'
        datatype_odim = 'PHIDP'
    elif datatype == 'uPhiDP':
        field_name = 'uncorrected_differential_phase'
        datatype_odim = 'UPHIDP'
    elif datatype == 'PhiDPc':
        field_name = 'corrected_differential_phase'
        datatype_odim = 'PHIDPC'
    elif datatype == 'PhiDP0':
        field_name = 'system_differential_phase'
        datatype_odim = 'PHIDP0'
    elif datatype == 'PhiDP0_bin':
        field_name = 'first_gate_differential_phase'
        datatype_odim = 'PHIDP0_BIN'
    elif datatype == 'KDP':
        field_name = 'specific_differential_phase'
        datatype_odim = 'KDP'
    elif datatype == 'KDPc':
        field_name = 'corrected_specific_differential_phase'
        datatype_odim = 'KDPC'
    elif datatype == 'V':
        field_name = 'velocity'
        datatype_odim = 'VRADH'
    elif datatype == 'Vh':
        field_name = 'velocity'
        datatype_odim = 'VRADH'
    elif datatype == 'dealV':
        field_name = 'dealiased_velocity'
        datatype_odim = 'VRADDH'
    elif datatype == 'Vc':
        field_name = 'corrected_velocity'
        datatype_odim = 'VRADHC'
    elif datatype == 'dealVc':
        field_name = 'dealiased_corrected_velocity'
        datatype_odim = 'VRADDHC'
    elif datatype == 'estV':
        field_name = 'retrieved_velocity'
        datatype_odim = 'VRADEST'
    elif datatype == 'stdV':
        field_name = 'retrieved_velocity_std'
        datatype_odim = 'sd_vvp'
    elif datatype == 'diffV':
        field_name = 'velocity_difference'
        datatype_odim = 'VDIFF'
    elif datatype == 'Vv':
        field_name = 'velocity_vv'
        datatype_odim = 'VRADV'
    elif datatype == 'dealVv':
        field_name = 'dealiased_velocity_vv'
        datatype_odim = 'VRADDV'
    elif datatype == 'W':
        field_name = 'spectrum_width'
        datatype_odim = 'WRADH'
    elif datatype == 'Wc':
        field_name = 'corrected_spectrum_width'
        datatype_odim = 'WRADHC'
    elif datatype == 'Wv':
        field_name = 'spectrum_width_vv'
        datatype_odim = 'WRADV'
    elif datatype == 'wind_vel_h_az':
        field_name = 'azimuthal_horizontal_wind_component'
        datatype_odim = 'AHWND'
    elif datatype == 'wind_vel_v':
        field_name = 'vertical_wind_component'
        datatype_odim = 'w'
    elif datatype == 'wind_vel_h_u':
        field_name = 'eastward_wind_component'
        datatype_odim = 'UWND'
    elif datatype == 'wind_vel_h_v':
        field_name = 'northward_wind_component'
        datatype_odim = 'VWND'
    elif datatype == 'windshear_v':
        field_name = 'vertical_wind_shear'
        datatype_odim = 'VSHR'
    elif datatype == 'WIND_SPEED':
        field_name = 'wind_speed'
        datatype_odim = 'ff'
    elif datatype == 'WIND_DIRECTION':
        field_name = 'wind_direction'
        datatype_odim = 'dd'
    elif datatype == 'Ah':
        field_name = 'specific_attenuation'
        datatype_odim = 'AH'
    elif datatype == 'Ahc':
        field_name = 'corrected_specific_attenuation'
        datatype_odim = 'AHC'
    elif datatype == 'PIA':
        field_name = 'path_integrated_attenuation'
        datatype_odim = 'PIA'
    elif datatype == 'PIAc':
        field_name = 'corrected_path_integrated_attenuation'
        datatype_odim = 'PIAC'
    elif datatype == 'Adp':
        field_name = 'specific_differential_attenuation'
        datatype_odim = 'ADP'
    elif datatype == 'Adpc':
        field_name = 'corrected_specific_differential_attenuation'
        datatype_odim = 'ADPC'
    elif datatype == 'PIDA':
        field_name = 'path_integrated_differential_attenuation'
        datatype_odim = 'PIDA'
    elif datatype == 'PIDAc':
        field_name = 'corrected_path_integrated_differential_attenuation'
        datatype_odim = 'PIDAC'
    elif datatype == 'TEMP':
        field_name = 'temperature'
        datatype_odim = 'TEMP'
    elif datatype == 'ISO0':
        field_name = 'iso0'
        datatype_odim = 'ISO0'
    elif datatype == 'H_ISO0':
        field_name = 'height_over_iso0'
        datatype_odim = 'HISO0'
    elif datatype == 'cosmo_index':
        field_name = 'cosmo_index'
        datatype_odim = 'COSMOIND'
    elif datatype == 'hzt_index':
        field_name = 'hzt_index'
        datatype_odim = 'HZTIND'
    elif datatype == 'ml':
        field_name = 'melting_layer'
        datatype_odim = 'ML'
    elif datatype == 'VIS':
        field_name = 'visibility'
        datatype_odim = 'VIS'
    elif datatype == 'echoID':
        field_name = 'radar_echo_id'
        datatype_odim = 'ECHOID'
    elif datatype == 'CLT':
        field_name = 'clutter_exit_code'
        datatype_odim = 'CLT'
    elif datatype == 'occurrence':
        field_name = 'occurrence'
        datatype_odim = 'OCC'
    elif datatype == 'freq_occu':
        field_name = 'frequency_of_occurrence'
        datatype_odim = 'OCCFREQ'
    elif datatype == 'RR':
        field_name = 'radar_estimated_rain_rate'
        datatype_odim = 'RATE'
    elif datatype == 'hydro':
        field_name = 'radar_echo_classification'
        datatype_odim = 'CLASS'
    elif datatype == 'entropy':
        field_name = 'hydroclass_entropy'
        datatype_odim = 'ENTROPY'
    elif datatype == 'propAG':
        field_name = 'proportion_AG'
        datatype_odim = 'propAG'
    elif datatype == 'propCR':
        field_name = 'proportion_CR'
        datatype_odim = 'propCR'
    elif datatype == 'propLR':
        field_name = 'proportion_LR'
        datatype_odim = 'propLR'
    elif datatype == 'propRP':
        field_name = 'proportion_RP'
        datatype_odim = 'propRP'
    elif datatype == 'propRN':
        field_name = 'proportion_RN'
        datatype_odim = 'propRN'
    elif datatype == 'propVI':
        field_name = 'proportion_VI'
        datatype_odim = 'propVI'
    elif datatype == 'propWS':
        field_name = 'proportion_WS'
        datatype_odim = 'propWS'
    elif datatype == 'propMH':
        field_name = 'proportion_MH'
        datatype_odim = 'propMH'
    elif datatype == 'propIH':
        field_name = 'proportion_IH'
        datatype_odim = 'propIH'
    elif datatype == 'time_avg_flag':
        field_name = 'time_avg_flag'
        datatype_odim = 'TAFLAG'
    elif datatype == 'colocated_gates':
        field_name = 'colocated_gates'
        datatype_odim = 'COLGATES'
    elif datatype == 'nsamples':
        field_name = 'number_of_samples'
        datatype_odim = 'ns'
    elif datatype == 'bird_density':
        field_name = 'bird_density'
        datatype_odim = 'dens'
    elif datatype == 'std':
        field_name = 'standard_deviation'
        datatype_odim = 'STD'
    elif datatype == 'sum':
        field_name = 'sum'
        datatype_odim = 'SUM'
    elif datatype == 'sum2':
        field_name = 'sum_squared'
        datatype_odim = 'SUM2'
    elif datatype == 'ff':
        field_name = 'wind_speed'
        datatype_odim = 'ff'
    elif datatype == 'dd':
        field_name = 'wind_direction'
        datatype_odim = 'dd'
    elif datatype == 'u':
        field_name = 'eastward_wind_component'
        datatype_odim = 'UWND'
    elif datatype == 'v':
        field_name = 'northward_wind_component'
        datatype_odim = 'VWND'
    elif datatype == 'w':
        field_name = 'vertical_wind_component'
        datatype_odim = 'w'
    elif datatype == 'width':
        field_name = 'height_resolution'
        datatype_odim = 'width'
    elif datatype == 'gap':
        field_name = 'gap'
        datatype_odim = 'gap'
    elif datatype == 'dbz':
        field_name = 'bird_reflectivity'
        datatype_odim = 'eta'
    elif datatype == 'eta':
        field_name = 'volumetric_reflectivity'
        datatype_odim = 'etah'
    elif datatype == 'dens':
        field_name = 'bird_density'
        datatype_odim = 'dens'
    elif datatype == 'n':
        field_name = 'number_of_samples_velocity'
        datatype_odim = 'n'
    elif datatype == 'n_dbz':
        field_name = 'number_of_samples_reflectivity'
        datatype_odim = 'n_dbz'
    elif datatype == 'sd_vvp':
        field_name = 'retrieved_velocity_std'
        datatype_odim = 'sd_vvp'
    elif datatype == 'DBZH':
        field_name = 'reflectivity'
        datatype_odim = 'DBZH'
    elif datatype == 'n_all':
        field_name = 'number_of_samples_velocity_all'
        datatype_odim = 'n_all'
    elif datatype == 'n_dbz_all':
        field_name = 'number_of_samples_reflectivity_all'
        datatype_odim = 'n_dbz_all'
    else:
        raise ValueError('ERROR: ODIM fields do not contain datatype ' +
            datatype)
    return {datatype_odim: field_name}


def duplicate_metaelems():
    """Duplicate selected metaelement(s)

    """
    pass


@classmethod
def deserialize(cls, config=None, **kwargs):
    """
        Method which takes kwargs as dict representing the Entity's data and return actuall instance of the Entity.
        """
    try:
        kwargs.pop('at')
    except KeyError:
        pass
    instance = cls.__new__(cls)
    instance._config = config
    instance.__change_dict__ = {}
    for key, field in instance.__fields__.items():
        try:
            value = kwargs[key]
        except KeyError:
            try:
                value = kwargs[field.mapped_field]
            except (KeyError, AttributeError):
                continue
        field.init(instance, value)
    return instance


def addon_enable(module: str=''):
    """Enable an add-on

    :param module: Module, Module name of the add-on to enable
    :type module: str
    """
    pass


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

    For discrete regressors the marginal effect is

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

    The row of the Jacobian for this variable is given by

    (f(XB)*X | d += 1 - f(XB)*X | d -= 1) / 2

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


def convert_to_float(value_string, parser_info={'parser_warnings': []}):
    """
    Tries to make a float out of a string. If it can't it logs a warning
    and returns True or False if convertion worked or not.

    :param value_string: a string
    :returns value: the new float or value_string: the string given
    :retruns: True or False
    """
    try:
        value = float(value_string)
    except TypeError:
        parser_info['parser_warnings'].append(
            'Could not convert: "{}" to float, TypeError'.format(value_string))
        return value_string, False
    except ValueError:
        parser_info['parser_warnings'].append(
            'Could not convert: "{}" to float, ValueError'.format(value_string)
            )
        return value_string, False
    return value, True


def __call__():
    """Return JSON compatible python data."""


def lowercase_range(code1, code2):
    """
    If the range of characters from code1 to code2-1 includes any
    upper case letters, return the corresponding lower case range.
    """
    code3 = max(code1, ord('A'))
    code4 = min(code2, ord('Z') + 1)
    if code3 < code4:
        d = ord('a') - ord('A')
        return code3 + d, code4 + d
    else:
        return None


def _strip(value):
    """ If `value` is a string, strip the whitespace """
    if hasattr(value, 'strip'):
        return value.strip()
    return value


def update_kwargs(kwargs, **keyvalues):
    """Update dict with keys and values if keys do not already exist.

    >>> kwargs = {'one': 1, }
    >>> update_kwargs(kwargs, one=None, two=2)
    >>> kwargs == {'one': 1, 'two': 2}
    True

    """
    for key, value in keyvalues.items():
        if key not in kwargs:
            kwargs[key] = value


def attribute_writer(model, target, value):
    """Write ``value`` to ``target`` attribute on ``model``.
    """
    setattr(model, target, value)


def input2xyz(abivar, basename, datasets):
    """
    Take an input object 'av' and write the
    corresponding XYZ file in the given
    'basename'
    """
    for idts in datasets:
        struct = abivar.get_structure(idts)
        natom = struct.natom
        if idts == '':
            filep = basename + '.xyz'
        else:
            filep = basename + '_DS' + str(idts) + '.xyz'
        wf = open(filep, 'w')
        wf.write(str(natom) + '\n\n')
        for iatom in range(natom):
            wf.write('%s %16.8f %16.8f %16.8f\n' % (struct.symbols[iatom],
                struct.positions[iatom, 0], struct.positions[iatom, 1],
                struct.positions[iatom, 2]))
        wf.close()


def create_field_volume_image(fieldmodule, image_filenames, name='volume_image'
    ):
    """
    Create an image field using the given fieldmodule.  The image filename must exist and
    be a known image type.

    :param fieldmodule: The fieldmodule to create the field in.
    :param image_filenames: Image filename.
    :param name: Optional name of the image field, defaults to 'volume_image'.
    :return: The image field created.
    """
    image_field = fieldmodule.createFieldImage()
    image_field.setName(name)
    image_field.setFilterMode(image_field.FILTER_MODE_LINEAR)
    stream_information = image_field.createStreaminformationImage()
    for image_filename in image_filenames:
        stream_information.createStreamresourceFile(image_filename)
    image_field.read(stream_information)
    return image_field


def strip_ips(stripped_packet):
    """
    Strip the IP addresses out of a packet that has had its mac addresses
    stripped out
    """
    return stripped_packet[0:28] + stripped_packet[44:]


def quarter(date, *, base=1):
    """
    Returns the quarter index of the given date

    Examples
    ------------
    >>> quarter(datetime.date(2020, 1, 10))
    1

    >>> quarter(datetime.date(2020, 1, 10), base=0)
    0
    """
    return (date.month - 1) // 3 + base


def get_name(friendly=False):
    """Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    if friendly:
        return 'Events log'
    return 'history'


def _check_action_params(reqd_keys, provided_keys):
    """Feedback on the keys provided"""
    log = str()
    for key in provided_keys:
        if key not in reqd_keys + ['type']:
            log += '\n.   - key ' + key + ' not accepted'
    if log != '':
        log += '\n.  - Accepted keys'
        log += '\n.      >'.join(reqd_keys)
    for key in reqd_keys:
        if key not in provided_keys:
            log += '\n key ' + key + ' is missing.'
    return log


def set_log_level(level):
    """
    Convenience function to set the log level of all hyperspy modules.

    Note: The log level of all other modules are left untouched.

    Parameters
    ----------
        level : {int | str}
            The log level to set. Any values that `logging.Logger.setLevel()`
            accepts are valid. The default options are:
                - 'CRITICAL'
                - 'ERROR'
                - 'WARNING'
                - 'INFO'
                - 'DEBUG'
                - 'NOTSET'

    Example use
    -----------

    For normal logging of hyperspy functions, you can set the log level like
    this:

        >>> import hyperspy.api as hs
        >>> hs.set_log_level('INFO')
        >>> hs.load(r'my_file.dm3')
        INFO:hyperspy.io_plugins.digital_micrograph:DM version: 3
        INFO:hyperspy.io_plugins.digital_micrograph:size 4796607 B
        INFO:hyperspy.io_plugins.digital_micrograph:Is file Little endian? True
        INFO:hyperspy.io_plugins.digital_micrograph:Total tags in root group: 15
        <Signal2D, title: My file, dimensions: (|1024, 1024)>

    If you need the log output during the initial import of hyperspy, you
    should set the log level like this:

        >>> from hyperspy.logger import set_log_level
        >>> set_log_level('DEBUG')
        >>> import hyperspy.api as hs
        DEBUG:hyperspy.gui:Loading hyperspy.gui
        DEBUG:hyperspy.gui:Current MPL backend: TkAgg
        DEBUG:hyperspy.gui:Current ETS toolkit: qt4
        DEBUG:hyperspy.gui:Current ETS toolkit set to: null

    """
    import logging
    logging.basicConfig()
    logging.getLogger('hyperspy').setLevel(level)


@classmethod
def all_features(cls):
    """
        All possible features for this item.
        Must implement if subclass implements featurize()
        """
    return [cls.__name__]


def set_year(datetime, new_year):
    """
    Change the year of a datetime to some new year. If datetime is a leapday then return None
    :param datetime.datetime datetime: Datetime object to change
    :param int new_year: The new year
    :return: A datetime with the same date as the original except the changed year
    """
    try:
        new_dt = datetime.replace(year=new_year)
    except ValueError:
        new_dt = None
    return new_dt


def session_hist_tex(f, session_data, threshold_requests_per_session):
    """
    Write session caracteristics in latex file

    Parameters
    ----------
        f: file

        session_data: pandas dataframe of sessions

        threshold_requests_per_session: int for filter number of requests per session

    Returns
    -------
        File (Optionnal)
    """
    digit_dic = {'0': 'Zero', '1': 'One', '2': 'Two', '3': 'Three', '4':
        'Four', '5': 'Five', '6': 'Six', '7': 'Seven', '8': 'Eight', '9':
        'Nine'}
    f.write('\n% 2. Histogram sessions with given requests')
    f.write('\n\\newcommand{\\%s}{%d}' % ('ThresholdRequestsPerSession',
        threshold_requests_per_session))
    for reqs in range(1, threshold_requests_per_session + 1):
        num_of_sessions = session_data[session_data.requests == reqs].shape[0]
        pc_of_sessions = 100.0 * num_of_sessions / session_data.shape[0]
        f.write('\n\\newcommand{\\%s}{%d}' % ('SessionsWith%sRequests' %
            digit_dic[str(reqs)], num_of_sessions))
        f.write('\n\\newcommand{\\%s}{%.1f}' % ('PCSessionsWith%sRequests' %
            digit_dic[str(reqs)], pc_of_sessions))
    num_of_sessions = session_data[session_data.requests >
        threshold_requests_per_session].shape[0]
    pc_of_sessions = 100.0 * num_of_sessions / session_data.shape[0]
    f.write('\n\\newcommand{\\%s}{%d}' % ('SessionsWithMT%sRequests' %
        digit_dic[str(threshold_requests_per_session)], num_of_sessions))
    f.write('\n\\newcommand{\\%s}{%.1f}' % ('PCSessionsWithMT%sRequests' %
        digit_dic[str(threshold_requests_per_session)], pc_of_sessions))
    return f


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 i(s):
    """A utility method for ensuring that a command line option argument is int.

    :param s: Option argument.
    :return: Integer or None.
    """
    if s:
        return int(s)
    return None


def get_fasttext_test_calls(test_file_path, fasttext_path, model_path):
    """
    Generates fastText command-line calls to apply a previously trained model to a test dataset. Note, this only
    supports binary classification scenarios.

    :param test_file_path: path to the test dataset
    :param fasttext_path: path to the fastText executable
    :param model_path: str, path to output model
    :return str - fastText calls for testing
    """
    class_count = 2
    predict_call = [fasttext_path, 'predict-prob', model_path,
        test_file_path, str(class_count)]
    return predict_call