def primitive_nurbs_surface_circle_add(radius: float=1.0, view_align: bool=
    False, enter_editmode: bool=False, location: float=(0.0, 0.0, 0.0),
    rotation: float=(0.0, 0.0, 0.0), layers: bool=(False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False, False, False, False, False)):
    """Construct a Nurbs surface Circle

    :param radius: Radius
    :type radius: float
    :param view_align: Align to View, Align the new object to the view
    :type view_align: bool
    :param enter_editmode: Enter Editmode, Enter editmode when adding this object
    :type enter_editmode: bool
    :param location: Location, Location for the newly added object
    :type location: float
    :param rotation: Rotation, Rotation for the newly added object
    :type rotation: float
    :param layers: Layer
    :type layers: bool
    """
    pass


def ds_meta(data_source_id, datasource, publisher, dataset, read_groups=[]):
    """
    Simple meta object for our data sources.
    Used in various publish methods.
    """
    return {'DATA_SOURCE_ID': data_source_id, 'DATA_SOURCE': datasource,
        'PUBLISHER': publisher, 'DATASET': dataset, 'readGroups': read_groups}


def whitespace_tokenize(text):
    """Runs basic whitespace cleaning and splitting on a piece of text."""
    text = text.strip()
    if not text:
        return []
    tokens = text.split()
    return tokens


@staticmethod
def get_object(conn, binding_name, cls):
    """
        Get a reference to a remote object using CORBA
        """
    raise RuntimeError('ORB not initialised')


def _is_sunder(name):
    """Returns True if a _sunder_ name, False otherwise."""
    return len(name) > 2 and name[0] == name[-1] == '_' and name[1:2
        ] != '_' and name[-2:-1] != '_'


def impl_ret_untracked(ctx, builder, retty, ret):
    """
    The return type is not a NRT object.
    """
    return ret


def add_separator(target):
    """Add separator to target only if last action is not a separator"""
    target_actions = list(target.actions())
    if target_actions:
        if not target_actions[-1].isSeparator():
            target.addSeparator()


def provider_parser(subparser):
    """Configure provider parser for EasyDNS"""
    subparser.add_argument('--auth-username', help=
        'specify username for authentication')
    subparser.add_argument('--auth-token', help=
        'specify token for authentication')


def should_clean(**kwargs):
    """
        whether or not old file should be cleaned
        """


def get_row_sql(row):
    """Function to get SQL to create column from row in PROC CONTENTS."""
    postgres_type = row['postgres_type']
    if postgres_type == 'timestamp':
        postgres_type = 'text'
    return row['name'].lower() + ' ' + postgres_type


def extract(txt, begin, end, pos=0):
    """Extract the text between 'begin' and 'end' from 'txt'

    Args:
        txt: String to search in
        begin: First string to be searched for
        end: Second string to be searched for after 'begin'
        pos: Starting position for searches in 'txt'

    Returns:
        The string between the two search-strings 'begin' and 'end' beginning
        with position 'pos' in 'txt' as well as the position after 'end'.

        If at least one of 'begin' or 'end' is not found, None and the original
        value of 'pos' is returned

    Examples:
        extract("abcde", "b", "d")    -> "c" , 4
        extract("abcde", "b", "d", 3) -> None, 3
    """
    try:
        first = txt.index(begin, pos) + len(begin)
        last = txt.index(end, first)
        return txt[first:last], last + len(end)
    except (ValueError, TypeError, AttributeError):
        return None, pos


@classmethod
def from_cli(cls, *plugins):
    """
        Creates a new instance of the bot using the utilities inside of the
        :mod:`disco.cli` module. Allows passing in a set of uninitialized
        plugin classes to load.

        Parameters
        ---------
        plugins : Optional[list(:class:`disco.bot.plugin.Plugin`)]
            Any plugins to load after creating the new bot instance

        """
    from disco.cli import disco_main
    inst = cls(disco_main())
    for plugin in plugins:
        inst.add_plugin(plugin)
    return inst


@classmethod
def _from_dict(cls, dct):
    """Create a model instance from dictionary of property values.

        The only advantage of this over ``__init__(**dct)`` is that using
        the property name ``self`` will not result in an error.

        :param dict dct: Property values by name.
        :rtype: .Model
        """
    model = object.__new__(cls)
    model.__init_from_dict(dct=dct, include_missing_properties=cls.
        _swagger_spec.config['include_missing_properties'])
    return model


def anyof(*args, **kwargs):
    """Test if at least one of the values is True.

    @rtype: bool
    """
    for i in (list(args) + list(kwargs.values())):
        if i:
            return True
    return False


def list_lzop(archive, compression, cmd, verbosity, interactive):
    """List a LZOP archive."""
    cmdlist = [cmd, '--list']
    if verbosity > 1:
        cmdlist.append('--verbose')
    cmdlist.extend(['--', archive])
    return cmdlist


def drange(v0, v1, d):
    """Returns a discrete range."""
    return range(int(v0) // d, int(v1 + d) // d)


def view_selected():
    """Reset viewable area to show selected keyframes range

    """
    pass


@classmethod
def _get_fields(cls):
    """
        Aggregates all available fields and their types from the class itself and its superclass
        (assuming it is a configuration as well).

        Returns:
        --------
        - dict
            Mapping from field names to types.
        """
    annotations = {}
    if hasattr(super(), '_get_fields'):
        annotations = {**annotations, **super()._get_fields()}
    if hasattr(cls, '__annotations__'):
        annotations = {**annotations, **cls.__annotations__}
    return annotations


def is_pid_cmdline_correct(pid, match):
    """Ensure that the cmdline for a pid seems sane

    Because pids are recycled, blindly killing by pid is something to
    avoid. This provides the ability to include a substring that is
    expected in the cmdline as a safety check.
    """
    try:
        with open('/proc/%d/cmdline' % pid) as f:
            cmdline = f.read()
            return match in cmdline
    except EnvironmentError:
        return False


@staticmethod
def getDefaultLifetime():
    """
        Get the default maximum lifetime (1 hour).

        :return: The lifetime in milliseconds.
        :rtype: float
        """
    return 3600.0 * 1000


def create_date_formats(day_first=True):
    """generate combinations of time and date
    formats with different delimeters
    """
    if day_first:
        date_formats = ['dd/mm/yyyy', 'dd/mm/yy', 'yyyy/mm/dd']
        python_date_formats = ['%d/%m/%Y', '%d/%m/%y', '%Y/%m/%d']
    else:
        date_formats = ['mm/dd/yyyy', 'mm/dd/yy', 'yyyy/mm/dd']
        python_date_formats = ['%m/%d/%Y', '%m/%d/%y', '%Y/%m/%d']
    date_formats += ['dd/bb/yyyy', 'dd/bbb/yyyy']
    python_date_formats += ['%d/%b/%Y', '%d/%B/%Y']
    both_date_formats = list(zip(date_formats, python_date_formats))
    time_formats = 'hh:mm:ssz hh:mm:ss hh:mm:sstzd'.split()
    python_time_formats = ('%H:%M%Z %H:%M:%S %H:%M:%S%Z %H:%M%z %H:%M:%S%z'
        .split())
    both_time_formats = list(zip(time_formats, python_time_formats))
    date_separators = ['-', '.', '/', ' ']
    all_date_formats = []
    for separator in date_separators:
        for date_format, python_date_format in both_date_formats:
            all_date_formats.append((date_format.replace('/', separator),
                python_date_format.replace('/', separator)))
    all_formats = {}
    for date_format, python_date_format in all_date_formats:
        all_formats[date_format] = python_date_format
        for time_format, python_time_format in both_time_formats:
            all_formats[date_format + time_format
                ] = python_date_format + python_time_format
            all_formats[date_format + 'T' + time_format
                ] = python_date_format + 'T' + python_time_format
            all_formats[date_format + ' ' + time_format
                ] = python_date_format + ' ' + python_time_format
    return list(all_formats.values())


def truncate_seq_pair(tokens_a, tokens_b, max_num_tokens, rng):
    """Truncates a pair of sequences to a maximum sequence length."""
    while True:
        total_length = len(tokens_a) + len(tokens_b)
        if total_length <= max_num_tokens:
            break
        trunc_tokens = tokens_a if len(tokens_a) > len(tokens_b) else tokens_b
        assert len(trunc_tokens) >= 1
        if rng.random() < 0.5:
            del trunc_tokens[0]
        else:
            trunc_tokens.pop()


def filter_merged(merged_df, off_target_max):
    """
    Filters the merged df to find only primers which align with initial primer pairs, and have a value
    below off target threshold.
    Args:
        merged_df (DataFrame): output df from merge_good_total()
        off_target_max (int): the maximum number of off target sites allowed (<= this value)
    Returns:
        off_target_filtered (DataFrame): the filtered dataframe
    """
    filtered_df = merged_df.loc[(merged_df['Primer Left Seq'] == merged_df[
        'Forward']) & (merged_df['Primer Right Seq'] == merged_df['Reverse'])]
    useful_filtered = filtered_df[['Sequence ID', 'Primer Rank',
        'Primer Left Seq', 'Primer Right Seq', 'Primer Left Len',
        'Primer Right Len', 'Primer Left TM', 'Primer Right TM',
        'Primer Left GC %', 'Primer Right GC %', 'Chromosome', 'Position1',
        'Position2', 'PCR_Prod_Len', 'Product GC%', 'FwdPrimerPos',
        'RvsPrimerPos', 'OffTargetCount']]
    off_target_filtered = useful_filtered.loc[useful_filtered[
        'OffTargetCount'] <= off_target_max]
    return off_target_filtered


def rsa_crt_dmq1(private_exponent, q):
    """
    Compute the CRT private_exponent % (q - 1) value from the RSA
    private_exponent (d) and q.
    """
    return private_exponent % (q - 1)


def _check_compatibility_fs(w1, w2):
    """Raise an exception if the sampling frequency of the two Waveforms
    are different."""
    if w1.fs != w2.fs:
        errmsg = 'Waveforms do not have the same fs: {} and {}.'
        raise ValueError(errmsg.format(w1.fs, w2.fs))


def iteritems(obj):
    """Handle the disappearance of `dict.iteritems` in Python 3"""
    try:
        itr = obj.iteritems()
    except AttributeError:
        itr = obj.items()
    return itr


@staticmethod
def _handle_api_response(json_response):
    """
        Throw exceptions on errors from API.

        :param json_response:
        :return:
        """
    if not json_response:
        raise ValueError('Error getting data from the api, no data returned')
    if 'error' in json_response:
        raise ValueError('Standard Error:: {} : {}'.format(json_response[
            'error'], json_response['error_description']))
    elif 'description' in json_response:
        if 'Service Error' in json_response['description']:
            raise ValueError('Service Error:: {} : {}'.format(json_response
                ['id'], json_response['description']))
    else:
        try:
            codes = json_response[list(json_response.keys())[0]]['return'][
                'returnCode']
            if codes['majorReturnCode'] != '000' or codes['minorReturnCode'
                ] != '0000':
                raise ValueError('Return Code Error:: Major: {}, Minor: {}'
                    .format(codes['majorReturnCode'], codes['minorReturnCode'])
                    )
        except KeyError:
            pass
    return json_response


def is_file(obj):
    """
    Check if an object is file-like

    Parameters
    ------------
    obj : object
       Any object type to be checked

    Returns
    -----------
    is_file : bool
        True if object is a file
    """
    return hasattr(obj, 'read') or hasattr(obj, 'write')


def trim_percentage(img, percentage):
    """
    Trim percentage of pixels off images

    :parameters:
        - percentage: int
            percentage of dimension to trim off.
            both sides are trimmed, half each side.

    >>> img = Image.new('L', (100, 200))
    >>> imgt = trim_percentage(img, 10)
    >>> imgt.size
    (90, 180)
    """
    px_w = img.size[0] * (percentage / 100.0)
    px_h = img.size[1] * (percentage / 100.0)
    box = map(int, (px_w / 2, px_h / 2, img.size[0] - px_w / 2, img.size[1] -
        px_h / 2))
    img = img.crop(box)
    return img


def _rename_and_clean_coords(ds, add_lon_lat=True):
    """Rename 'longitude' and 'latitude' columns to 'x' and 'y'

    Optionally (add_lon_lat, default:True) preserves latitude and longitude columns as 'lat' and 'lon'.
    """
    ds = ds.rename({'longitude': 'x', 'latitude': 'y'})
    if add_lon_lat:
        ds = ds.assign_coords(lon=ds.coords['x'], lat=ds.coords['y'])
    return ds


def volume_obelisk(a, b, A, B, height):
    """
    Calculates the volume of a obelisk given the base and top sides, and height.
    """
    return height / 6 * (A * b + a * B + 2 * (a * b + A * B))


def disambiguate(names, mark='1'):
    """
    Given a list of strings ``names``, return a new list of names where repeated names have been disambiguated by repeatedly appending the given mark.

    EXAMPLE::

        >>> disambiguate(['sing', 'song', 'sing', 'sing'])
        ['sing', 'song', 'sing1', 'sing11']

    """
    names_seen = set()
    new_names = []
    for name in names:
        new_name = name
        while new_name in names_seen:
            new_name += mark
        new_names.append(new_name)
        names_seen.add(new_name)
    return new_names


def mpl_get_cb_bound_next_to_plot(ax):
    """
    Return the coordinates for a colorbar axes next to the provided axes
    object. Take into account the changes of the axes due to aspect ratio
    settings.

    Parts of this code are taken from the transforms.py file from matplotlib

    Important: Use only AFTER fig.subplots_adjust(...)

    Use as:
    =======
    cb_pos = mpl_get_cb_bound_next_to_plot(fig.axes[15])
    ax1 = fig.add_axes(cb_pos, frame_on=True)

    cmap = mpl.cm.jet_r
    norm = mpl.colors.Normalize(vmin=float(23), vmax=float(33))
    cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=norm,
                                    orientation='vertical')
    cb1.locator = mpl.ticker.FixedLocator([23,28,33])
    cb1.update_ticks()
    cb1.ax.artists.remove(cb1.outline)    # remove framei
    """
    position = ax.get_position()
    figW, figH = ax.get_figure().get_size_inches()
    fig_aspect = figH / figW
    box_aspect = ax.get_data_ratio()
    pb = position.frozen()
    pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect).bounds
    ax_size = ax.get_position().bounds
    xdiff = (ax_size[2] - pb1[2]) / 2
    ydiff = (ax_size[3] - pb1[3]) / 2
    sizes = [ax_size[0] + xdiff + ax_size[2] + 0.01, ax_size[1] + ydiff,
        0.01, pb1[3]]
    return sizes


@classmethod
def HomogeneousWalthall(cls, param1, param2, param3, albedo):
    """Parameterisation for a surface BRDF based on the Walthall et al. model.

        The parameters are:

        - term in square ts*tv
        - term in square ts*ts+tv*tv
        - term in ts*tv*cos(phi) (limacon de pascal)
        - albedo

        """
    return (
        """0 Homogeneous surface
1 (directional effects)
4 (Walthall et al. model)
%f %f %f %f
"""
         % (param1, param2, param3, albedo))


def get_p2p_scatter_pfold_over_mad(model):
    """
    Get ratio of median of period-folded data over median absolute
    deviation of observed values.
    """
    return model['scatter_pfold_over_mad']


@classmethod
def parse_sync_check(cls, res_js):
    """Parse sync check javascript response."""
    js_locals = {'retcode': 'retcode', 'selector': 'selector'}
    window = cls.exec_js(res_js, js_locals=js_locals)
    return window.synccheck


def _sc_encode(gain, peak):
    """Encode ReplayGain gain/peak values as a Sound Check string.
    """
    peak *= 32768.0
    g1 = int(min(round(10 ** (gain / -10) * 1000), 65534))
    g2 = int(min(round(10 ** (gain / -10) * 2500), 65534))
    uk = 0
    values = g1, g1, g2, g2, uk, uk, int(peak), int(peak), uk, uk
    return u' %08X' * 10 % values


def map_profile_fields(data, fields):
    """Copy profile data from site-specific to standard field names.
    Standard keys will only be set if the site data for that key is not
    ``None`` and not empty string.

    :param data: Profile data from the site, to be modified in place.
    :param fields: Map of ``{destination: source}``. Destination is the
        standard name. Source source is the site-specific name, or
        a callable taking ``data`` and returning the value.
    :return: UserInfo fields
    """
    profile = {}
    for dst, src in fields.items():
        if callable(src):
            value = src(data)
        else:
            value = data.get(src)
        if value is not None and value != '':
            profile[dst] = value
    return profile


def color_add():
    """Add new color to active palette

    """
    pass


def makeID(board):
    """
        Function to make unique id's in a board.

        :Parameters:
            `board` : a pymongo.collection.Collection instance

        Returns an integer >= 1
    """
    board.find_one_and_update({'_id': 'count'}, {'$inc': {'count': 1}},
        upsert=True)
    return board.find_one({'_id': 'count'}).get('count')


def get_limited_to(headers, enforcer):
    """Return the user and project the request should be limited to.

    :param headers: HTTP headers dictionary
    :param enforcer: policy enforcer
    :return: A tuple of (user, project), set to None if there's no limit on
    one of these.

    """
    target = {}
    credentials = {'roles': headers.get('X-Roles', '').split(',')}
    rules = enforcer.rules.keys()
    rule_name = 'segregation' if 'segregation' in rules else 'context_is_admin'
    if not enforcer.enforce(rule_name, target, credentials):
        return headers.get('X-User-Id'), headers.get('X-Project-Id')
    return None, None


def adapt_decimal(value):
    """Convert decimal.Decimal to string."""
    return str(value)


@classmethod
def false(cls, key):
    """True if the specified key is present in the job document and
        evaluates to False."""
    return cls(lambda job: not job.document.get(key, False), 'false_' + key)


@staticmethod
def out_back(progress):
    """.. image:: images/anim_out_back.png
        """
    p = progress - 1.0
    return p * p * ((1.70158 + 1) * p + 1.70158) + 1.0


def split_conflicting(mas, agents, agent, eqclass):
    """
    Split the given equivalence class for agent into non conflicting subsets.

    mas -- a multi-agents system;
    agents -- a subset of agents of mas;
    agent -- an agent of agents;
    eqclass -- a subset of moves for agents composed of states equivalent for
               agent.

    Generate all splitted non conflicting subsets.
    """
    others_cube = mas.bddEnc.inputsCube - mas.inputs_cube_for_agents({agent})
    while eqclass.isnot_false():
        si = mas.pick_one_state_inputs(eqclass)
        ncss = eqclass & si.forsome(mas.bddEnc.statesCube | others_cube)
        eqclass = eqclass - ncss
        yield ncss


def is_similarity(m):
    """
    Return ``True`` if ``m`` is a similarity and ``False`` otherwise.

    EXAMPLES::

        sage: from flatsurf.geometry.matrix_2x2 import is_similarity

        sage: is_similarity(matrix([[0,1],[1,0]]))
        True
        sage: is_similarity(matrix([[0,-2],[2,0]]))
        True
        sage: is_similarity(matrix([[1,1],[0,1]]))
        False
    """
    n = m * m.transpose()
    return n[0, 1].is_zero() and n[1, 0].is_zero()


@staticmethod
def dict_factory(cursor, row):
    """Convert SQL result into a dictionary"""
    dictionary = {}
    for idx, col in enumerate(cursor.description):
        dictionary[col[0]] = row[idx]
    return dictionary


def reduceAngle(deg):
    """
    Reduces an angle (in degrees) to a value in [-180..180)
    """
    return (deg + 180.0) % 360.0 - 180.0


def has_len(item):
    """
    Helper function for determining if object has __len__ defined
    """
    try:
        len(item)
        return True
    except:
        return False


def isPadding(typeName):
    """
    Determines whether or not the given type is padding.

    Given the name of the type returns a True if it is
    padding or a False otherwise.

    Args:
        typeName (str): The name of the type to be checked.

    Returns:
        True if it is padding, False otherwise.

    Examples:
        >>> isPadding('padding')
        True
        >>> isPadding('boolean')
        False
        >>> isPadding('char')
        False
        >>> isPadding('string')
        False
        >>> isPadding('int')
        False
        >>> isPadding('float')
        False
    """
    return typeName == 'padding'


def _calc_data_point_ticks(x_locations, num_distributions,
    distribution_width, distribution_centered):
    """Returns a 1D numpy array of x-axis tick positions.

    These positions will be centered on each data point.

    Set distribution_centered to True for scatter and box plots because their
    plot types naturally center over a given horizontal position. Bar charts
    should use distribution_centered = False because the leftmost edge of a bar
    starts at a given horizontal position and extends to the right for the
    width of the bar.
    """
    dist_size = (num_distributions - 1 if distribution_centered else
        num_distributions)
    return x_locations + dist_size * distribution_width / 2


def create_icosphere(bm: 'bmesh.types.BMesh', subdivisions: int, diameter:
    float, matrix: 'mathutils.Matrix', calc_uvs: bool) ->dict:
    """Creates a grid with a variable number of subdivisions

    :param bm: The bmesh to operate on.
    :type bm: 'bmesh.types.BMesh'
    :param subdivisions: how many times to recursively subdivide the sphere
    :type subdivisions: int
    :param diameter: diameter
    :type diameter: float
    :param matrix: matrix to multiply the new geometry with
    :type matrix: 'mathutils.Matrix'
    :param calc_uvs: calculate default UVs
    :type calc_uvs: bool
    :return:  verts: output vertstype list of (bmesh.types.BMVert)
    """
    pass


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

        :param str val:
        :rtype: PathRoot
        """
    return cls('root', val)


@classmethod
def listen_packet(cls, *args, **kwargs):
    """
        Binds the function to listen for a given gateway op code.
        """
    return cls.add_meta_deco({'type': 'listener', 'what': 'packet', 'args':
        args, 'kwargs': kwargs})


def pdist(m):
    """Function returns the 2D distance between two points. Matrix form has:
       x1 y1
       x2 y2"""
    return ((m[0, 0] - m[1, 0]) ** 2 + (m[0, 1] - m[1, 1]) ** 2) ** 0.5


def moveObjectsToTop(ids, subset_ids=None):
    """ Move specified sub-objects to top of container. """


def gaps(data):
    """
    Return a list of the gap sizes, given a list of numbers.  (If input
    is length n, result is length n-1)
    """
    result = []
    for i in range(len(data) - 1):
        result.append(data[i + 1] - data[i])
    return result


def confirm_action(question, force=False):
    """confirm if the user wants to perform a certain action

       Parameters
       ==========
       question: the question that will be asked
       force: if the user wants to skip the prompt
    """
    if force is True:
        return True
    response = input(question)
    while len(response) < 1 or response[0].lower().strip() not in 'ynyesno':
        response = input('Please answer yes or no: ')
    if response[0].lower().strip() in 'no':
        return False
    return True


def add_linear_gather_for_mode(m, Fr, Ft, Fz, exptheta_m, Fr_grid, Ft_grid,
    Fz_grid, iz_lower, iz_upper, ir_lower, ir_upper, S_ll, S_lu, S_lg, S_ul,
    S_uu, S_ug):
    """
    Add the contribution of the gathered field from azimuthal mode `m` to the
    fields felt by one macroparticle (`Fr`, `Ft`, `Fz`), using linear weights.

    Parameters:
    -----------
    m: int
        The index of the azimuthal mode that is added.

    Fr, Ft, Fz: floats
        The fields felt by one macroparticle, which represent either E or B
        (before the contribution of mode `m` has been added)

    exptheta_m: complex
        The complex azimuthal factor $e^{-i m 	heta}$ where $	heta$ is
        the azimuthal position of the macroparticle considered.

    Fr_grid, Ft_grid, Fz_grid: 2darrays of complexs
        The fields on the interpolation grid for mode `m`

    iz_lower, iz_upper, ir_lower, ir_upper: ints
        Lower and upper index in z and r from which the macroparticle
        considered should gather the fields (in the arrays F*_grid)

    S_ll, S_lu, S_lg, S_ul, S_uu, S_ug: floats
        The weights with which the fields are gathered, for the macroparticle
        considered. `S_lg` and `S_ug` are used for fields gathered from below
        the axis.

    Returns:
    --------
    Fr, Ft, Fz: floats
        The fields felt by one macroparticle, which represent either E or B
        (after the contribution of mode `m` has been added)
    """
    Fr_m = 0.0j
    Ft_m = 0.0j
    Fz_m = 0.0j
    Fr_m += S_ll * Fr_grid[iz_lower, ir_lower]
    Ft_m += S_ll * Ft_grid[iz_lower, ir_lower]
    Fz_m += S_ll * Fz_grid[iz_lower, ir_lower]
    Fr_m += S_lu * Fr_grid[iz_lower, ir_upper]
    Ft_m += S_lu * Ft_grid[iz_lower, ir_upper]
    Fz_m += S_lu * Fz_grid[iz_lower, ir_upper]
    Fr_m += S_ul * Fr_grid[iz_upper, ir_lower]
    Ft_m += S_ul * Ft_grid[iz_upper, ir_lower]
    Fz_m += S_ul * Fz_grid[iz_upper, ir_lower]
    Fr_m += S_uu * Fr_grid[iz_upper, ir_upper]
    Ft_m += S_uu * Ft_grid[iz_upper, ir_upper]
    Fz_m += S_uu * Fz_grid[iz_upper, ir_upper]
    if ir_lower == ir_upper == 0:
        flip_factor = (-1.0) ** m
        Fr_m += -flip_factor * S_lg * Fr_grid[iz_lower, 0]
        Ft_m += -flip_factor * S_lg * Ft_grid[iz_lower, 0]
        Fz_m += flip_factor * S_lg * Fz_grid[iz_lower, 0]
        Fr_m += -flip_factor * S_ug * Fr_grid[iz_upper, 0]
        Ft_m += -flip_factor * S_ug * Ft_grid[iz_upper, 0]
        Fz_m += flip_factor * S_ug * Fz_grid[iz_upper, 0]
    if m == 0:
        factor = 1.0
    else:
        factor = 2.0
    Fr += factor * (Fr_m * exptheta_m).real
    Ft += factor * (Ft_m * exptheta_m).real
    Fz += factor * (Fz_m * exptheta_m).real
    return Fr, Ft, Fz


def hash_str(x, p, m):
    """
       Compute the hash of a string with polynomial rolling hash function.

       Parameters
       ----------
       x : str
           element
       p : int
           Prime number. Recommended p is 53.
       m : int
           The size of hashing space. Usually, The size of the bloom filter.

       Returns
       -------
       hash : hash value of x
       """
    hash_value = 0
    p_i = p
    for c in x:
        hash_value += ord(c) * p_i % m
        p_i = p_i * p % m
    try:
        hash_value = int(hash_value)
        return hash_value
    except:
        raise TypeError("Can't cast {} to integer".format(type(hash_value)))


def optical_phonon_disperion():
    """Standard equation for the dispersion of an optical phonon

    """
    pass


def get_location_standard(location):
    """
    This function will provide a standarized comman separated location value
    """
    result = ''
    for keys_data in ['city', 'county', 'state', 'country']:
        value = location.get(keys_data, None)
        if value:
            if result == '':
                result = value
            else:
                result += ', ' + value
    return result


@staticmethod
def _wrap_bytes(bytestream):
    """Return `bytestream` without changing it."""
    return bytestream


def _file_iter_range(fp, offset, bytes, maxread=1024 * 1024):
    """ Yield chunks from a range in a file. No chunk is bigger than maxread."""
    fp.seek(offset)
    while bytes > 0:
        part = fp.read(min(bytes, maxread))
        if not part:
            break
        bytes -= len(part)
        yield part


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


def _isfullcopytraceable(repo, c1, base):
    """ Checks that if base, source and destination are all no-public branches,
    if yes let's use the full copytrace algorithm for increased capabilities
    since it will be fast enough.

    `experimental.copytrace.sourcecommitlimit` can be used to set a limit for
    number of changesets from c1 to base such that if number of changesets are
    more than the limit, full copytracing algorithm won't be used.
    """
    if c1.rev() is None:
        c1 = c1.p1()
    if c1.mutable() and base.mutable():
        sourcecommitlimit = repo.ui.configint(b'experimental',
            b'copytrace.sourcecommitlimit')
        commits = len(repo.revs(b'%d::%d', base.rev(), c1.rev()))
        return commits < sourcecommitlimit
    return False


def tweakmode_enter(isolate_action: bool=False):
    """Enter tweaking mode for the action referenced by the active strip to edit its keyframes

    :param isolate_action: Isolate Action, Enable ‘solo’ on the NLA Track containing the active strip, to edit it without seeing the effects of the NLA stack
    :type isolate_action: bool
    """
    pass


def gen_delta_msg(total_changes):
    """Return string of changes for the PR message."""
    delta = 'Changes:\n'
    delta += '========\n'
    for distro in sorted(total_changes):
        if not total_changes[distro]:
            continue
        delta += '%s Changes:\n' % distro.title()
        delta += '---------------\n'
        for d in sorted(total_changes[distro]):
            delta += '* {0}\n'.format(d)
        delta += '\n'
    return delta


def eq_15_plume_velocity(T_0: float, g: float, c_p_0_kJ_kg_K: float, rho_0:
    float, Q_dot_c_kW: float, z: float, z_0: float):
    """Equation 15 in Section 8.3.3 PD 7974-1:2019 calculates mean gas velocity along fire centre-line.

    :param T_0: in K, ambient air temperature.
    :param g: in m/s^2, acceleration due to gravity.
    :param c_p_0_kJ_kg_K: in kJ/kg/K, specific heat capacity of ambient air.
    :param rho_0: in kg/m^3, density of ambient air.
    :param Q_dot_c_kW: in kW, convective heat release rate.
    :param z: in m, height above fuel surface.
    :param z_0: in m, virtual fire origin.
    :return u_bar_cl: in m/s, mean gas velocity of plume.
    """
    aa = (g / (c_p_0_kJ_kg_K * rho_0 * T_0)) ** (1 / 3)
    bb = Q_dot_c_kW ** (1 / 3)
    cc = (z - z_0) ** (-1 / 3)
    u_bar_cl = 3.4 * aa * bb * cc
    return u_bar_cl


def filter_user(user_ref):
    """Filter out private items in a user dict.

    'password', 'tenants' and 'groups' are never returned.

    :returns: user_ref

    """
    if user_ref:
        user_ref = user_ref.copy()
        user_ref.pop('password', None)
        user_ref.pop('tenants', None)
        user_ref.pop('groups', None)
        user_ref.pop('domains', None)
        try:
            user_ref['extra'].pop('password', None)
            user_ref['extra'].pop('tenants', None)
        except KeyError:
            pass
        if 'password_expires_at' not in user_ref:
            user_ref['password_expires_at'] = None
    return user_ref


def get_principals_for_role(role_id):
    """Get the principals that have been granted a role.

        Return the list of (principal id, setting) who have been assigned or
        removed from a role.

        If no principals have been assigned this role,
        then the empty list is returned.
        """


@staticmethod
def fit_deriv(x, *params):
    """One dimensional multiply model derivative with respect to parameter"""
    d_factor = x
    return [d_factor]


def _adjust_postponed(date):
    """Return actual date of fast day.

    For usual date of a fast day returns fast day adjusted for any
    postponements.
    """
    if date.weekday() == 7:
        if date.month in [12, 13]:
            date -= 2
        else:
            date += 1
    return date


def rm_covered(object, pos_df, neg_df):
    """Return pos and neg dfs of examples that are not covered by object.

    Parameters
    ----------
    object : Cond, Rule, or Ruleset
        Object whose coverage predictions to invoke.
    pos_df : DataFrame
        Positive examples.
    neg_df : DataFrame
        Negative examples.

    Return
    ------
    tuple<DataFrame>
        Positive and negative examples not covered by object.
    """
    return pos_df.drop(object.covers(pos_df).index, axis=0, inplace=False
        ), neg_df.drop(object.covers(neg_df).index, axis=0, inplace=False)


def sub_double_copy(logs, log):
    """Check two copy only rips and score as T&C Rip."""
    if logs[0].has_deduction('Test & Copy') and len(logs[0].tracks) == len(log
        .tracks):
        for new_track, original_track in zip(log.tracks.values(), logs[0].
            tracks.values()):
            if 'copy crc' in new_track and 'copy crc' in original_track:
                if new_track['copy crc'] != original_track['copy crc']:
                    break
        else:
            logs[0].remove_deduction('Test & Copy')


def is_string_type(thetype):
    """Returns true if the type is one of: STRING, TIMESTAMP, DATE, or
    TIME."""
    return thetype in ['STRING', 'TIMESTAMP', 'DATE', 'TIME', 'QINTEGER',
        'QFLOAT', 'QBOOLEAN']


@classmethod
def get_user_from_request(cls, request):
    """This method can be overwritten to implement custom user/session mechanizms
        currently it uses standard django.contrib.auth"""
    if not hasattr(request, 'user') or not hasattr(request.user,
        'is_authenticated'):
        return None
    return request.user if request.user.is_authenticated() else None


def to_youtrack_state(trac_resolution, yt_bundle):
    """
    Creates YT state in yt_bundle with trac_resolution name.

    Args:
        track_resolution: Name of new state to add.
        yt_bundle: FieldBundle to create new state in.

    Returns:
        New resolved YT state with trac_resolution name.
    """
    state = yt_bundle.createElement(trac_resolution.name)
    state.isResolved = True
    return state


def snap_cursor_to_grid():
    """Snap 3D cursor to the nearest grid division

    """
    pass


def camel_to_snake_base(string: str) ->str:
    """Base function to convert a camel-case string to snake-case string."""
    res = []
    byte = string.encode('ascii')
    max_index = len(byte)
    _index = 0
    while _index < max_index and not 65 <= byte[_index
        ] <= 90 and not 97 <= byte[_index] <= 122:
        res.append(byte[_index])
        _index += 1
    if _index < max_index and 65 <= byte[_index] <= 90:
        res.append(byte[_index] + 32)
        _index += 1
        while _index < max_index and 65 <= byte[_index] <= 90:
            if _index + 1 < max_index:
                if 65 <= byte[_index + 1] <= 90:
                    res.append(byte[_index] + 32)
                    _index += 1
                elif not 97 <= byte[_index + 1] <= 122:
                    res.append(byte[_index] + 32)
                    res.append(byte[_index + 1])
                    _index += 2
                else:
                    if res[-1] != 95:
                        res.append(95)
                    res.append(byte[_index] + 32)
                    res.append(byte[_index + 1])
                    _index += 2
                    break
            else:
                res.append(byte[_index] + 32)
                _index += 1
                break
    while _index < max_index:
        if 65 <= byte[_index] <= 90:
            if res[-1] != 95:
                res.append(95)
            res.append(byte[_index] + 32)
            _index += 1
            while _index < max_index and 65 <= byte[_index] <= 90:
                if _index + 1 < max_index:
                    if 65 <= byte[_index + 1] <= 90:
                        res.append(byte[_index] + 32)
                        _index += 1
                    elif not 97 <= byte[_index + 1] <= 122:
                        res.append(byte[_index] + 32)
                        res.append(byte[_index + 1])
                        _index += 2
                    else:
                        if res[-1] != 95:
                            res.append(95)
                        res.append(byte[_index] + 32)
                        res.append(byte[_index + 1])
                        _index += 2
                        break
                else:
                    res.append(byte[_index] + 32)
                    _index += 1
                    break
        else:
            res.append(byte[_index])
            _index += 1
    res = bytearray(res).decode('ascii')
    return res


def merge_section(key, prnt_sec, child_sec):
    """ Synthesize a output numpy docstring section.

    Parameters
    ----------
    key: str
        The numpy-section being merged.
    prnt_sec: Optional[str]
        The docstring section from the parent's attribute.
    child_sec: Optional[str]
        The docstring section from the child's attribute.
    Returns
    -------
    Optional[str]
        The output docstring section."""
    if prnt_sec is None and child_sec is None:
        return None
    if key == 'Short Summary':
        header = ''
    else:
        header = '\n'.join((key, ''.join('-' for i in range(len(key))), ''))
    if child_sec is None:
        body = prnt_sec
    else:
        body = child_sec
    return header + body


def get_parameters(kwarg):
    """
    Called for qdiscs and filters. Should return
    the structure to be embedded as the qdisc parameters
    (`TCA_OPTIONS`).
    """
    return None


def genus_species_split(name):
    """Return (genus, species) splitting on first space.

    If there are no spaces, returns (name, '') instead.
    """
    if ' ' in name:
        return name.split(' ', 1)
    else:
        return name, ''


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 value_or_result(potential):
    """Return `potential` or its return value.

    If `potential` is callable then the result of calling it without arguments
    is returned instead.

    """
    if callable(potential):
        return potential()
    return potential


def bind(metadata=None, engine=None):
    """
        binds introspector to a particular bound metadata, if metadata is none, create a new
        metadata and bind to the passed in engine
        """


def int_intensity(F2, L, P, I0, wavelength, cell_vol, cryst_vol):
    """
    Calculate the reflection intensities scaling factor

    INPUT:
    F2        : the structure factor squared
    L         : Lorentz factor
    P         : Polarisation factor
    I0        : Incoming beam flux
    wavelength: in Angstroem
    cell_vol  : Volume of unit cell in AA^3
    cryst_vol : Volume of crystal in mm^3

    OUTPUT:
    int_intensity: integrated intensity

    """
    emass = 9.1093826e-31
    echarge = 1.60217653e-19
    pi4eps0 = 1.11265e-10
    c = 299792458.0
    k1 = (echarge ** 2 / (pi4eps0 * emass * c ** 2) * 1000) ** 2
    k2 = wavelength ** 3 * cryst_vol * 1e+21 / cell_vol ** 2
    return k1 * k2 * I0 * L * P * F2


def is_blank(text):
    """
    Determine the line is blank or not.
    If `True`, the line is blank.
    """
    if len(text.strip()) == 0:
        return True
    return False


def is_dict(obj):
    """Returns True if the object is a python dictionary.
    """
    return isinstance(obj, dict)


def cond(predicate, consequence, alternative=None):
    """
    Function replacement for if-else to use in expressions.

        >>> x = 2
        >>> cond(x % 2 == 0, "even", "odd")
        'even'
        >>> cond(x % 2 == 0, "even", "odd") + '_row'
        'even_row'
    """
    if predicate:
        return consequence
    else:
        return alternative


def describe_account_attributes(DryRun=None, AttributeNames=None):
    """
    Describes attributes of your AWS account. The following are the supported account attributes:
    See also: AWS API Documentation

    Examples
    This example describes the supported-platforms attribute for your AWS account.
    Expected Output:
    This example describes the attributes for your AWS account.
    Expected Output:

    :example: response = client.describe_account_attributes(
        DryRun=True|False,
        AttributeNames=[
            'supported-platforms'|'default-vpc',
        ]
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type AttributeNames: list
    :param AttributeNames: One or more account attribute names.
            (string) --

    :rtype: dict
    :return: {
        'AccountAttributes': [
            {
                'AttributeName': 'string',
                'AttributeValues': [
                    {
                        'AttributeValue': 'string'
                    },
                ]
            },
        ]
    }

    :returns:
    DryRun (boolean) -- Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .
    AttributeNames (list) -- One or more account attribute names.

    (string) --

    """
    pass


def p_statements(p):
    """statements : statement
                 | statements statement """
    if len(p) == 2:
        p[0] = p[1]
    else:
        p[0] = ['STATEMENTS', p[1][1] + [p[2]]]


def force_text(value):
    """
    Helper to deal with bytes and str in Python 2 vs. Python 3. Needed to have
    always username and password as a string (i Python 3 it's bytes).
    """
    if issubclass(type(value), str):
        return value
    if isinstance(value, bytes):
        return str(value, 'utf-8')
    return str(value)


def copy_value(obj):
    """
    Copy SBValue object and preserve dynamic type.

    Useful when `SetPreferDynamicValue()` cannot be used on original object.

    :param lldb.SBValue obj: LLDB object.
    :return: Copy of obj.
    :rtype: lldb.SBValue
    """
    c = obj.GetDynamicValue(obj.GetPreferDynamicValue())
    return c


def occlude(image, x, y, w, h, color=0):
    """
    Occlude image with a rectangular region.

    Occludes an image region with dimensions w,h centered on x,y with the
    given color. Invalid x,y coordinates will be clipped to ensure complete
    occlusion rectangle is within the image.

    >>> import numpy as np
    >>> image = np.ones((4, 5)).astype('uint8')
    >>> occlude(image, 2, 2, 2, 3)
    array([[1, 1, 1, 1, 1],
           [1, 0, 0, 1, 1],
           [1, 0, 0, 1, 1],
           [1, 0, 0, 1, 1]], dtype=uint8)

    >>> image = np.ones((4, 4)).astype('uint8')
    >>> occlude(image, 0.5, 0.5, 0.5, 0.5)
    array([[1, 1, 1, 1],
           [1, 0, 0, 1],
           [1, 0, 0, 1],
           [1, 1, 1, 1]], dtype=uint8)

    :param numpy array image: Numpy array.
    :param int|float x: x coordinate for center of occlusion region.
                        Can be provided as fraction (float) of image width
    :param int|float y: y coordinate for center of occlusion region.
                        Can be provided as fraction (float) of image height
    :param int|float w: width of occlusion region.
                        Can be provided as fraction (float) of image width
    :param int|float h: height of occlusion region.
                        Can be provided as fraction (float) of image height
    :param int|tuple color: gray-scale or RGB color of occlusion.
    :return: Copy of input image with occluded region.
    :rtype: numpy array
    """
    frac = lambda c, m: int(m * c) if isinstance(c, float) else c
    iw, ih = image.shape[:2]
    x, y = frac(x, iw), frac(y, ih)
    w, h = frac(w, iw), frac(h, ih)
    r, c = int(y - h // 2), int(x - w // 2)
    r, c = max(min(r, ih - h), 0), max(min(c, iw - w), 0)
    image2 = image.copy()
    image2[r:r + h, c:c + w] = color
    return image2


@staticmethod
def sgn(z):
    """
        Compute the sign function :math:`\\mathrm{sgn}(z)` factor for
        deflection as sugggested by Bray (1984). For current implementation, returning 1 is sufficient.

        :param z: Complex variable :math:`z = x + \\mathrm{i}y`
        :type z: ``complex``
        :return: :math:`\\mathrm{sgn}(z)`
        :rtype: ``float``
        """
    return 1.0


def extractTwos(m):
    """m is a positive integer. A tuple (s, d) of integers is returned
    such that m = (2 ** s) * d."""
    assert m >= 0
    i = 0
    while m & 2 ** i == 0:
        i += 1
    return i, m >> i


def check_input_validity(current_code):
    """
    Check if user input is valid
    :param current_code:
    :return:
    """
    if len(current_code) != 13:
        return False
    try:
        int(current_code)
        return True
    except ValueError:
        return False


@staticmethod
def is_complex():
    """Returns `True` if the instance is a complexType, `False` otherwise."""
    raise NotImplementedError()


def anypats(pats, opts):
    """Checks if any patterns, including --include and --exclude were given.

    Some commands (e.g. addremove) use this condition for deciding whether to
    print absolute or relative paths.
    """
    return bool(pats or opts.get(b'include') or opts.get(b'exclude'))


def calc_delay2(freq, freqref, dm, scale=None):
    """ Calculates the delay in seconds due to dispersion delay.
    freq is array of frequencies. delay is relative to freqref.
    default scale is 4.1488e-3 as linear prefactor (reproducing for rtpipe<=1.54 requires 4.2e-3).
    """
    scale = 0.0041488 if not scale else scale
    return scale * dm * (1.0 / freq ** 2 - 1.0 / freqref ** 2)


def add_args(p):
    """Add arguments to global Argparser"""
    p.add_argument('filter', metavar='PROFILE', default=['%'], nargs='*',
        help='Teradata profile name')


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

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


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


@staticmethod
def _condense_services_localizations_into_structures(structures_w_lang,
    default_lang, structures_services):
    """add corresponding service name localizations to structure's services"""
    structures = structures_w_lang[default_lang]
    for structure in structures:
        if 'services' in structure and structure['services']:
            structure_id = structure['structure_id']
            for lang in structures_w_lang.keys():
                if lang != default_lang and lang in structures_services[
                    structure_id]:
                    for service, name_loc in zip(structure['services'],
                        structures_services[structure_id][lang]):
                        service['name_' + lang] = name_loc
    return structures


def is_tty(stream):
    """Returns True if the given stream is a tty, else False"""
    return hasattr(stream, 'isatty') and stream.isatty()


def header_slit(input_file, output_base, output_size, extension='.smi'):
    """Splits the lines in an input file (including a header)
    into a series of output files.

    :param input_file: The input file
    :type input_file: ``str``
    :param output_base: The basename of the output files. The files are written
                        to the current working directory with a numerical
                        suffix and .smi. If the base is `x` the first output
                        file will be named `x_1[extension]`.
    :type output_base: ``str``
    :param output_size: The number of lines in each output file.
    :type output_size: ``int``
    :param extension: The extension for the output files.
    :type extension: ``str``
    """
    with open(input_file) as smiles_file:
        smiles_file.seek(0, 0)
        header = smiles_file.readline()
        file_line_count = 0
        file_number = 1
        output_file = None
        line = smiles_file.readline()
        while line and line.strip():
            if file_line_count == 0:
                name = output_base + '_' + str(file_number) + extension
                output_file = open(name, 'w')
                output_file.write(header)
                file_line_count = 0
            output_file.write(line)
            file_line_count += 1
            if file_line_count == output_size:
                output_file.close()
                output_file = None
                file_line_count = 0
                file_number += 1
            line = smiles_file.readline()
        if output_file:
            output_file.close()


def set_time_based_auto_scaling(InstanceId=None, AutoScalingSchedule=None):
    """
    Specify the time-based auto scaling configuration for a specified instance. For more information, see Managing Load with Time-based and Load-based Instances .
    See also: AWS API Documentation

    :example: response = client.set_time_based_auto_scaling(
        InstanceId='string',
        AutoScalingSchedule={
            'Monday': {
                'string': 'string'
            },
            'Tuesday': {
                'string': 'string'
            },
            'Wednesday': {
                'string': 'string'
            },
            'Thursday': {
                'string': 'string'
            },
            'Friday': {
                'string': 'string'
            },
            'Saturday': {
                'string': 'string'
            },
            'Sunday': {
                'string': 'string'
            }
        }
    )

    :type InstanceId: string
    :param InstanceId: [REQUIRED]
            The instance ID.

    :type AutoScalingSchedule: dict
    :param AutoScalingSchedule: An AutoScalingSchedule with the instance schedule.
            Monday (dict) --The schedule for Monday.
            (string) --
            (string) --

            Tuesday (dict) --The schedule for Tuesday.
            (string) --
            (string) --

            Wednesday (dict) --The schedule for Wednesday.
            (string) --
            (string) --

            Thursday (dict) --The schedule for Thursday.
            (string) --
            (string) --

            Friday (dict) --The schedule for Friday.
            (string) --
            (string) --

            Saturday (dict) --The schedule for Saturday.
            (string) --
            (string) --

            Sunday (dict) --The schedule for Sunday.
            (string) --
            (string) --

    """
    pass


def mon_hosts(mons):
    """
    Iterate through list of MON hosts, return tuples of (name, host).
    """
    for m in mons:
        if m.count(':'):
            name, host = m.split(':')
        else:
            name = m
            host = m
            if name.count('.') > 0:
                name = name.split('.')[0]
        yield name, host


def abort():
    """
        Abort the transaction.
        """


def face_split_by_edges():
    """Weld loose edges into faces (splitting them into new faces)

    """
    pass


def as_zarr(catalog):
    """
    Create a zarr dataset from a collection of GeoTiff files

    Zarr datasets are optimal Dask analysis.
    """
    raise NotImplementedError()


def count_to_write(link_counters):
    """Find the to_write count in the counters returned by a CommunicationLink."""
    for processor in link_counters.values():
        if 'to_write' in processor:
            return processor['to_write']


@classmethod
def _set_config(cls, config_module):
    """Set configuration from Python's module.

        :param config_module: config module to be used for attributes assignment
        """
    cls.task_classes = config_module['task_classes']
    cls.edge_table = config_module['edge_table']
    cls.failures = config_module['failures']
    cls.nowait_nodes = config_module['nowait_nodes']
    cls.eager_failures = config_module['eager_failures']
    cls.flows = list(cls.edge_table.keys())
    cls.node_args_from_first = config_module['node_args_from_first']
    cls.async_result_cache = config_module['async_result_cache']
    cls.propagate_finished = config_module['propagate_finished']
    cls.propagate_node_args = config_module['propagate_node_args']
    cls.propagate_parent = config_module['propagate_parent']
    cls.propagate_compound_finished = config_module[
        'propagate_compound_finished']
    cls.output_schemas = config_module['output_schemas']
    cls.storage_mapping = config_module['storage2instance_mapping']
    cls.storage_task_name = config_module['storage_task_name']
    cls.task2storage_mapping = config_module['task2storage_mapping']
    cls.max_retry = config_module['max_retry']
    cls.retry_countdown = config_module['retry_countdown']
    cls.storage_readonly = config_module['storage_readonly']
    cls.storage2storage_cache = config_module['storage2storage_cache']
    cls.throttle_tasks = config_module['throttle_tasks']
    cls.throttle_flows = config_module['throttle_flows']
    cls.dispatcher_queues = config_module['dispatcher_queues']
    cls.task_queues = config_module['task_queues']
    cls.strategies = config_module['strategies']
    cls.selective_run_task = config_module['selective_run_task']
    cls.migration_dir = config_module['migration_dir']
    config_module['init'](cls)


def scientific(value, precision=2):
    """Return number in string scientific notation z.wq x 10ⁿ.

    Examples:
        float(0.3) will return "3.00 x 10⁻¹"
        int(500) will return "5.00 x 10²"
    This will always return a string.

    Args:
        value (int, float, string): Input number.
        precision (int): Number of decimal for first part of the number.

    Returns:
        str: number in scientific notation z.wq x 10ⁿ.
    """
    exponents = {'0': '⁰', '1': '¹', '2': '²', '3': '³', '4': '⁴', '5': '⁵',
        '6': '⁶', '7': '⁷', '8': '⁸', '9': '⁹', '+': '⁺', '-': '⁻'}
    negative = False
    try:
        if '-' in str(value):
            value = str(value).replace('-', '')
            negative = True
        if isinstance(value, str):
            value = float(value)
        fmt = '{:.%se}' % str(int(precision))
        n = fmt.format(value)
    except (ValueError, TypeError):
        return value
    part1, part2 = n.split('e')
    if '-0' in part2:
        part2 = part2.replace('-0', '-')
    if '+0' in part2:
        part2 = part2.replace('+0', '')
    new_part2 = []
    if negative:
        new_part2.append(exponents['-'])
    for char in part2:
        new_part2.append(exponents[char])
    final_str = part1 + ' x 10' + ''.join(new_part2)
    return final_str


def parse_params(params: dict, parse_functions: (dict, None)=None) ->dict:
    """
    参数后处理，根据parse_functions中定义的转换函数，对params中的变量值进行转换。
    例如，可用于将无法直接dump的变量转换成可以dump的变量。

    Examples
    --------
    >>> params = {"a": 1}
    >>> parse_functions = {"a": lambda x: x + x}
    >>> parse_params(params, parse_functions)
    {'a': 2}
    >>> params = {"a": 1}
    >>> parse_params(params)
    {'a': 1}

    """
    if parse_functions is not None:
        for name, func in parse_functions.items():
            if name in params:
                params[name] = func(params[name])
    return params


def parallel_trails_mask_rows_tag_from_parallel_trails_mask_rows(
    parallel_trails_mask_rows):
    """Generate a parallel_trails_mask_rows tag, to customize phase names based on the number of rows in the charge
    injection region in the trails of the parallel clocking direction are masked during the fit,

    This changes the phase name 'phase_name' as follows:

    parallel_trails_mask_rows = None -> phase_name
    parallel_trails_mask_rows = (0, 10) -> phase_name_parallel_trails_mask_rows_(0,10)
    parallel_trails_mask_rows = (20, 60) -> phase_name_parallel_trails_mask_rows_(20,60)
    """
    if parallel_trails_mask_rows == None:
        return ''
    else:
        x0 = str(parallel_trails_mask_rows[0])
        x1 = str(parallel_trails_mask_rows[1])
        return '_par_trails_mask_rows_(' + x0 + ',' + x1 + ')'


def getExclusiveReactionsMutants(project, ref_id, muts=set()):
    """
    Given a bunch of organisms, get two dicts
    mreacts: org_id -->  set(re_id, ...) (wild-type)
    mix: org_id --> set(re_id, ...) (mutated but also in wild-type)
    ereacts: org_id -->  set(re_id, ...) (exclusive mutated)
    """
    from ductape.storage.SQLite.database import Kegg
    kegg = Kegg(project)
    ereacts = kegg.getExclusiveReactionsMutants(ref_id, muts)
    mreacts = {}
    mix = {}
    for mut_id in muts:
        mut = set()
        for oR in kegg.getOrgReact(mut_id):
            mut.add(oR.re_id)
        mreacts[mut_id] = set()
        mix[mut_id] = set()
        for oR in kegg.getReferenceReact(mut_id, ref_id):
            if oR.re_id in mut:
                mix[mut_id].add(oR.re_id)
            else:
                mreacts[mut_id].add(oR.re_id)
    return mreacts, mix, ereacts


@staticmethod
def _get_name(x, full_path=False):
    """
        Get name of an hdf5 node

        Returns the short or long group/dataset name.

        Parameters
        ----------
        x : h5py.Dataset or h5py.Group
            The node for which the name is desired
        full_path : bool, optional
            If True returns the full path in file. Default is False.

        Returns
        -------
        name : str
            The name of the node
        """
    if not full_path:
        name = x.name.split('/')[-1]
    else:
        name = x.name
    if not name:
        name = '/'
    return name


def put_record(DeliveryStreamName=None, Record=None):
    """
    Writes a single data record into an Amazon Kinesis Firehose delivery stream. To write multiple data records into a delivery stream, use  PutRecordBatch . Applications using these operations are referred to as producers.
    By default, each delivery stream can take in up to 2,000 transactions per second, 5,000 records per second, or 5 MB per second. Note that if you use  PutRecord and  PutRecordBatch , the limits are an aggregate across these two operations for each delivery stream. For more information about limits and how to request an increase, see Amazon Kinesis Firehose Limits .
    You must specify the name of the delivery stream and the data record when using  PutRecord . The data record consists of a data blob that can be up to 1,000 KB in size, and any kind of data, for example, a segment from a log file, geographic location data, web site clickstream data, etc.
    Firehose buffers records before delivering them to the destination. To disambiguate the data blobs at the destination, a common solution is to use delimiters in the data, such as a newline (
 ) or some other character unique within the data. This allows the consumer application(s) to parse individual data items when reading the data from the destination.
    The  PutRecord operation returns a RecordId , which is a unique string assigned to each record. Producer applications can use this ID for purposes such as auditability and investigation.
    If the  PutRecord operation throws a ServiceUnavailableException , back off and retry. If the exception persists, it is possible that the throughput limits have been exceeded for the delivery stream.
    Data records sent to Firehose are stored for 24 hours from the time they are added to a delivery stream as it attempts to send the records to the destination. If the destination is unreachable for more than 24 hours, the data is no longer available.
    See also: AWS API Documentation

    :example: response = client.put_record(
        DeliveryStreamName='string',
        Record={
            'Data': b'bytes'
        }
    )

    :type DeliveryStreamName: string
    :param DeliveryStreamName: [REQUIRED]
            The name of the delivery stream.

    :type Record: dict
    :param Record: [REQUIRED]
            The record.
            Data (bytes) -- [REQUIRED]The data blob, which is base64-encoded when the blob is serialized. The maximum size of the data blob, before base64-encoding, is 1,000 KB.

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

    """
    pass


def load_dummy_threading(finder, module):
    """the dummy_threading module plays games with the name of the threading
       module for its own purposes; ignore that here"""
    finder.ExcludeModule('_dummy_threading')


def xxx_memcpy(jitter):
    """
    #include <string.h>
    void *memcpy(void *dest, const void *src, size_t n);

    copies n bytes from memory area src to memory area dest.
    """
    ret_addr, args = jitter.func_args_systemv(['dest', 'src', 'n'])
    jitter.vm.set_mem(args.dest, jitter.vm.get_mem(args.src, args.n))
    return jitter.func_ret_systemv(ret_addr, args.dest)


def _filter_points_to_get_convex_hull(roc_sorted):
    """Find the convex hull.

    Uses a simplified version of Andrew's monotone chain convex hull algorithm
    https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
    to get the convex hull. Since we can assume the points (0,0) and (1,1) to be part
    of the convex hull the problem is simpler and we only need to make a single pass
    through the data.

    :param roc_sorted: DataFrame with ROC curve points sorted by 'x'
    :type roc_sorted: pandas.DataFrame
    :return: the list of points that make up the convex hull
    :rtype: list of named tuples
    """
    selected = []
    for r2 in roc_sorted.itertuples():
        while len(selected) >= 2:
            r1 = selected[-1]
            r0 = selected[-2]
            if (r1.y - r0.y) * (r2.x - r0.x) <= (r2.y - r0.y) * (r1.x - r0.x):
                selected.pop()
            else:
                break
        selected.append(r2)
    return selected


def cr_uid_ids_context(method):
    """ Decorate a traditional-style method that takes ``cr``, ``uid``, ``ids``,
        ``context`` as parameters. Such a method::

            @api.cr_uid_ids_context
            def method(self, cr, uid, ids, args, context=None):
                ...

        may be called in both record and traditional styles, like::

            # recs = model.browse(cr, uid, ids, context)
            recs.method(args)

            model.method(cr, uid, ids, args, context=context)

        It is generally not necessary, see :func:`guess`.
    """
    method._api = 'cr_uid_ids_context'
    return method


@classmethod
def supported(cls, conn):
    """Return whether public key authentication is supported"""
    return conn.public_key_auth_supported()


def merge_overlapping_ranges(ranges):
    """Merge overlapping and adjacent ranges

    Parameters
    ----------
    ranges : iterable with 2-elements
        Element 1 is the start of the range.
        Element 2 is the end of the range.

    Yields
    -------
    sorted_merged_range : 2-element tuple
        Element 1 is the start of the merged range.
        Element 2 is the end of the merged range.

    >>> list(_merge_overlapping_ranges([(5,7), (3,5), (-1,3)]))
    [(-1, 7)]
    >>> list(_merge_overlapping_ranges([(5,6), (3,4), (1,2)]))
    [(1, 2), (3, 4), (5, 6)]
    >>> list(_merge_overlapping_ranges([]))
    []

    References
    ----------
    .. [1] http://codereview.stackexchange.com/questions/21307/consolidate-
    list-of-ranges-that-overlap

    """
    ranges = iter(sorted(ranges))
    current_start, current_stop = next(ranges)
    for start, stop in ranges:
        if start > current_stop:
            yield current_start, current_stop
            current_start, current_stop = start, stop
        else:
            current_stop = max(current_stop, stop)
    yield current_start, current_stop


def runProject(simplaceInstance):
    """Run the project."""
    simplaceInstance.run()


def new_or_existing(key):
    """ Return a mapping for 'key', creating it if needed.

        o The returned object must be Acquisition-wrappable.
        """


def calculate_setting_time(updated):
    """
    Calculate time to set a chunk in a buffer.
    """
    try:
        val = updated.delay
    except AttributeError:
        val = 0
    return val


def default_gctf_v1_06():
    """
    Content of GCtf version 1.06.

    Arguments:
    None

    Return:
    Content items as list
    """
    items = [['WIDGETS MAIN', '7', int, '', 'PLAIN', '', ''], [
        'WIDGETS ADVANCED', '7', int, '', 'PLAIN', '', ''], ['WIDGETS RARE',
        '7', int, '', 'PLAIN', '', ''], ['--apix', '1.34', float, '',
        'PLAIN', 'Main', 'Pixel size'], ['--dstep', '14.0', float, '',
        'PLAIN', 'Main',
        "Detector size in micrometer; don't worry if unknown; just use default."
        ], ['--kV', '300', float, '', 'PLAIN', 'Main',
        'High tension in Kilovolt, typically 300, 200 or 120'], ['--cs',
        '2.7', float, '', 'PLAIN', 'Main',
        'Spherical aberration, in  millimeter'], ['--ac', '0.1', float, '',
        'PLAIN', 'Main',
        "Amplitude contrast; normal range 0.04~0.1; pure ice 0.04, carbon 0.1; but doesn't matter too much if using wrong value"
        ], ['Phase plate', ['False', 'True'], bool, '', 'COMBO', 'Main',
        'Use phase plate options'], ['--phase_shift_L', '0.0', float,
        'Phase plate:True', 'PLAIN', 'Main',
        'User defined phase shift, lowest phase shift,  in degree; typically, ~90.0 for micrographs using phase plate '
        ], ['--phase_shift_H', '180.0', float, 'Phase plate:True', 'PLAIN',
        'Main',
        'User defined phase shift, highest phase shift, final range will be (phase_shift_L, phase_shift_H)'
        ], ['--phase_shift_S', '5.0', float, 'Phase plate:True', 'PLAIN',
        'Main',
        "User defined phase shift search step; don't worry about the accuracy; this is just the search step, Gctf will refine the phase shift anyway."
        ], ['--phase_shift_T', '1', int, 'Phase plate:True', 'PLAIN',
        'Main',
        'Phase shift target in the search; 1: CCC; 2: resolution limit;'],
        ['--defL', '5000', float, '', 'PLAIN', 'Main',
        'Lowest defocus value to search, in angstrom'], ['--defH', '90000',
        float, '', 'PLAIN', 'Main',
        'Highest defocus value to search, in angstrom'], ['--defS', '500',
        float, '', 'PLAIN', 'Main',
        'Step of defocus value used to search, in angstrom'], ['--astm',
        '1000', float, '', 'PLAIN', 'Main',
        "Estimated astigmation in angstrom, don't need to be accurate, within 0.1~10 times is OK"
        ], ['--bfac', '150', float, '', 'PLAIN', 'Advanced',
        'Bfactor used to decrease high resolution amplitude,A^2; NOT the estimated micrograph Bfactor! suggested range 50~300 except using "REBS method".'
        ], ['--resL', '50', float, '', 'PLAIN', 'Advanced',
        'Lowest Resolution to be used for search, in angstrom'], ['--resH',
        '4', float, '', 'PLAIN', 'Advanced',
        'Highest Resolution to be used for search, in angstrom'], [
        '--boxsize', '1024', int, '', 'PLAIN', 'Advanced',
        'Boxsize in pixel to be used for FFT, 512 or 1024 highly recommended'
        ], ['--overlap', '0.5', float, '', 'PLAIN', 'Advanced',
        'Overlapping factor for grid boxes sampling, for boxsize=512, 0.5 means 256 pixeles overlapping'
        ], ['--convsize', '85', float, '', 'PLAIN', 'Advanced',
        'Boxsize to be used for smoothing, suggested 1/10 ~ 1/20 of boxsize in pixel, e.g. 40 for 512 boxsize'
        ], ['--do_EPA', '0', int, '', 'PLAIN', 'Advanced',
        "1: Do Equiphase average; 0: Don't do;  only for nice output, will NOT be used for CTF determination."
        ], ['--do_Hres_ref', '0', int, '', 'PLAIN', 'Advanced',
        'Whether to do High-resolution refinement or not, very useful for selecting high quality micrographs'
        ], ['--Href_resL', '15.0', float, '', 'PLAIN', 'Advanced',
        'Lowest Resolution  to be used for High-resolution refinement, in angstrom'
        ], ['--Href_resH', '4.0', float, '', 'PLAIN', 'Advanced',
        'Highest Resolution  to be used for High-resolution refinement, in angstrom'
        ], ['--Href_bfac', '50', float, '', 'PLAIN', 'Advanced',
        'Bfactor to be used for High-resolution refinement,A^2 NOT the estimated micrograph Bfactor!'
        ], ['--refine_after_EPA', '0', int, '', 'PLAIN', 'Advanced',
        'Refinement after EPA'], ['--estimate_B', '1', int, '', 'PLAIN',
        'Advanced', 'Estimate B-Factor'], ['--B_resL', '15', float, '',
        'PLAIN', 'Advanced',
        'Lowest resolution for Bfactor estimation; This output Bfactor is the real estimation of the micrograph'
        ], ['--B_resH', '6', float, '', 'PLAIN', 'Advanced',
        'Highest resolution for Bfactor estimation'], ['Use movies', [
        'False', 'True'], bool, '', 'COMBO', 'Advanced',
        'Enable Gctf movie mode'], ['--do_mdef_refine', '0', int,
        'Use movies:True', 'PLAIN', 'Advanced',
        'Whether to do CTF refinement of each frames, by default it will do averaged frames. Not quite useful at the moment, but maybe in future.'
        ], ['--mdef_ave_type', '0', int, 'Use movies:True', 'PLAIN',
        'Advanced',
        '0: coherent average, average FFT with phase information(suggested for movies); 1:incoherent average, only average amplitude(suggested for particle stack);'
        ], ['--mdef_aveN', '7', int, 'Use movies:True', 'PLAIN', 'Advanced',
        'Average number of movie frames for movie or particle stack CTF refinement'
        ], ['--mdef_fit', '0', int, 'Use movies:True', 'PLAIN', 'Advanced',
        '0: no fitting; 1: linear fitting defocus changes in Z-direction'],
        ['--do_local_refine', '0', int, '', 'PLAIN', 'Advanced',
        '0: do not refine local defocus(default); 1: refine local defocus, need .box or .star coordinate files ("--boxsuffix" option).'
        ], ['--local_radius', '1024', float, '', 'PLAIN', 'Advanced',
        'Radius for local refinement, no weighting if the distance is larger than that'
        ], ['--local_boxsize', '512', float, '', 'PLAIN', 'Advanced',
        'Boxsize for local refinement'], ['--local_overlap', '0.5', float,
        '', 'PLAIN', 'Advanced',
        'Overlapping factor for grid boxes sampling'], ['--local_avetype',
        '0', float, '', 'PLAIN', 'Advanced',
        '0: equal weights for all local areas, neither distance nor frequency is weighted; 1: single weight for each local area, only distance is weighted;'
        ], ['--do_phase_flip', '0', int, '', 'PLAIN', 'Advanced',
        'Whether to do phase flip and write a new micrograph'], [
        '--do_validation', '0', int, '', 'PLAIN', 'Advanced',
        'Whether to validate the CTF determination.'], ['--ctfout_resL',
        '100.0', float, '', 'PLAIN', 'Advanced',
        'Lowest resolution for CTF diagnosis file. NOTE this only affects the final output of .ctf file, nothing related to CTF determination.'
        ], ['--ctfout_resH', '2.8', float, '', 'PLAIN', 'Advanced',
        'Highest resolution for CTF diagnosis file, ~Nyqiust by default.'],
        ['--ctfout_bfac', '50', float, '', 'PLAIN', 'Advanced',
        'Bfactor for CTF diagnosis file. NOTE this only affects the final output of .ctf file, nothing related to CTF determination.'
        ], ['--gid', '0', [int] * 99, '', 'PLAIN', 'Advanced',
        "GPU id, normally it's 0, use gpu_info to get information of all available GPUs."
        ], ['Split Gpu?', ['True', 'False'], bool, '', 'COMBO', 'Advanced',
        'NOT A CRYOLO OPTION. Split the gpu values specified in --gpu to be able to run mutliple crYOLO jobs in parallel.'
        ]]
    return items


def mi_rank(score):
    """Rank the score with a letter:

        * A if :math:`\\text{score} > 19`;
        * B if :math:`9 < \\text{score} \\le 19`;
        * C if :math:`\\text{score} \\le 9`.
    """
    return chr(65 + (9 - score >= 0) + (19 - score >= 0))


@classmethod
def instance(cls):
    """Returns the default global ivy bootstrapper."""
    if cls._INSTANCE is None:
        cls._INSTANCE = cls()
    return cls._INSTANCE


def str2func(str1, *args):
    """args = all user inputs
    example:
        strtofunc('mxnlist',2,3)#output [[[], [], []], [[], [], []]]
    """
    return globals()[str1](*args)


def FillFormWithValues(window, values_dict):
    """
    Fills a window with values provided in a values dictionary { element_key : new_value }

    :param window:  The window object to fill
    :type window: (Window)
    :param values_dict:  A dictionary with element keys as key and value is values parm for Update call
    :type values_dict: (Dict[Any:Any])
    """
    for element_key in values_dict:
        try:
            window.AllKeysDict[element_key].Update(values_dict[element_key])
        except Exception as e:
            print(
                'Problem filling form. Perhaps bad key?  This is a suspected bad key: {}'
                .format(element_key))


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

        :param ShowcaseRequestAccessDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_request_access_details', val)


def _get_format_control(values, option):
    """Get a format_control object."""
    return getattr(values, option.dest)


def ensure_model_obj_has_mapping_constructor(model_obj):
    """
    Ensure that `model_obj` has a 'get_mappings_for_fit' method. Raises a
    helpful ValueError if otherwise.
    """
    if not hasattr(model_obj, 'get_mappings_for_fit'):
        msg = "model_obj MUST have a 'get_mappings_for_fit' method."
        raise ValueError(msg)
    return None


@staticmethod
def get_alexa_error(data):
    """Gets the error message from the Alexa API response.

        Args:
            data: Response received from the Alexa API .

        Returns:
            A string representing the value of message, or ``None`` if no error message was received.

        """
    if 'request' in data and 'err' in data['request'] and 'message' in data[
        'request']['err']:
        return data['request']['err']['message']
    else:
        return None


def view_selected():
    """Reset viewable area to show selected strips range

    """
    pass


def trim_start(transcript, cds_start, max_length=0):
    """
    Method to trim the beginning of a transcript, given both
    the cds_start and the maximal allowed length after trimming.
    :param transcript: the transcript to be trimmed
    :type transcript: Transcript

    :param cds_start: the position at which the CDS starts for this transcript.
    :type cds_start: int

    :param max_length: maximum length of terminal exons.
    :type max_length: int

    :rtype: Transcript

    """
    first = transcript.exons[0]
    if first[1] < cds_start:
        if first[1] - first[0] + 1 > max_length:
            newfirst = tuple([first[1] - max_length, first[1]])
            transcript.remove_exon(first)
            transcript.add_exon(newfirst)
        else:
            newfirst = first
    elif first[0] < cds_start <= first[1]:
        if first[1] - first[0] + 1 > max_length:
            newfirst = tuple([min(cds_start, first[1] - max_length), first[1]])
            transcript.remove_exon(first)
            transcript.add_exon(newfirst)
            transcript.add_exon((cds_start, newfirst[1]), feature='CDS')
        else:
            newfirst = first
    else:
        newfirst = first
    transcript.start = newfirst[0]
    return transcript


def combine_hex(data):
    """ Combine list of integer values to one big integer """
    output = 0
    for i, value in enumerate(reversed(data)):
        output |= value << i * 8
    return output


def _sp(count, singular, plural):
    """format ``count``+ ``singular` or ``plural`` depending on ``count``"""
    return '{} {}'.format(count, singular if count == 1 else plural)


def bool_tag(name, value):
    """Create a DMAP tag with boolean data."""
    return name.encode('utf-8') + b'\x00\x00\x00\x01' + (b'\x01' if value else
        b'\x00')


def getCategoryIds():
    """Get IDs of category and sub-categories"""


def print_nonl(*args, **kwargs):
    """
    print(value, ..., sep=' ', end='
', file=sys.stdout, flush=False)

    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
      file:  a file-like object (stream); defaults to the current sys.stdout.
      sep:   string inserted between values, default a space.
      end:   string appended after the last value, default a newline.
      flush: whether to forcibly flush the stream.
    """
    print(*args, end='', **kwargs)


def counts2flux(cps, band):
    """
    Converts GALEX counts per second to flux (erg sec^-1 cm^-2 A^-1).
        See: http://asd.gsfc.nasa.gov/archive/galex/FAQ/counts_background.html

    :param cps: The flux in counts per second.

    :type cps: float

    :param band: The band to use, either 'FUV' or 'NUV'.

    :type band: str

    :returns: float -- The converted flux in erg sec^-1 cm^-2 A^-1.
    """
    scale = 1.4e-15 if band == 'FUV' else 2.06e-16
    return scale * cps


def __getitem__(name):
    """Return the form field with the given name

        If the desired firld has a prefix, then the given name should
        be the prefix, a dot, and the unprefixed name.  Otherwise, the
        given name is just the field name.

        Raise a KeyError if a field can't be found for the given name.
        """


def extract_add_server(pb2_grpc):
    """
    Extract add to server function from pb2_grpc module
    :param pb2_grpc:
    :return: function for add_to_server
    :type: function
    """
    members = dir(pb2_grpc)
    for name in members:
        if name.startswith('add_') and name.endswith('_to_server'):
            _add_to_server = getattr(pb2_grpc, name)
            return _add_to_server
    return None


def proxy_group_for_user(account):
    """
    Gets a firecloud proxy group name for a given account
    """
    if account == 'jcha@broadinstitute.org':
        return 'jcha-lapdog'
    info = account.split('@')
    return info[0] + '-' + info[1].split('.')[0] + '-lapdog'


def get_transform_type(tile_id):
    """
    Get the transform type specified in the tile id.
    Parameters
    ----------
    cooler_tile_id: str
        A tile id for a 2D tile (cooler)
    Returns
    -------
    transform_type: str
        The transform type requested for this tile
    """
    tile_id_parts = tile_id.split('.')
    if len(tile_id_parts) > 4:
        transform_method = tile_id_parts[4]
    else:
        transform_method = 'default'
    return transform_method


@classmethod
def has_sequence(cls):
    """Return if database supports sequence querying and assignation"""
    return False


def list_zoo(archive, compression, cmd, verbosity, interactive):
    """List a ZOO archive."""
    return [cmd, '-list', archive]


@classmethod
def parse(cls, api, json):
    """Parse a JSON object into a model instance."""
    raise NotImplementedError


def pattern_to_unique_symbols(pattern):
    """ Builds for each set a sorted string with unique symbols"""
    return ''.join(sorted(list(set(pattern))))


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def override_subcommand(section_name, section_items, args):
    """
    Given a specific section in the configuration file that maps to
    a subcommand (except for the global section) read all the keys that are
    actual argument flags and slap the values for that one subcommand.

    Return the altered ``args`` object at the end.
    """
    _boolean_states = {'yes': True, 'true': True, 'on': True, 'no': False,
        'false': False, 'off': False}
    for k, v in section_items:
        try:
            normalized_value = v.lower()
        except AttributeError:
            normalized_value = v
        value = _boolean_states.get(normalized_value, v)
        setattr(args, k, value)
    return args


@classmethod
def subclasses(cls):
    """Return a set of all subclasses, recursively."""
    seen = set()
    queue = set([cls])
    while queue:
        c = queue.pop()
        seen.add(c)
        sc = c.__subclasses__()
        for c in sc:
            if c not in seen:
                queue.add(c)
    seen.remove(cls)
    return seen


def get_applied_stereotypes(element):
    """
    Get collection of applied stereotypes to an element.
    """
    return element.appliedStereotype[:].classifier


def hg_to_git_spaces(name):
    """Spaces are allowed in mercurial, but not in git. We convert them to
    the unlikely string ___"""
    return name.replace(' ', '___')


def theta_Br_OH_PK74(T, P):
    """a-a': bromide hydroxide [PK74]."""
    theta = -0.065
    valid = T == 298.15
    return theta, valid


def p_headers(t):
    """headers : header
               | headers header"""
    if len(t) == 2:
        t[0] = [t[1]]
    else:
        t[0] = t[1] + [t[2]]


def savefile(filename, names, data):
    """Save the file using tabfileio"""
    try:
        import tabfileio
    except ImportError:
        raise ValueError(
            'external tabfileio package required to load file type')
    tabfileio.write_file(filename, names, data)


def submit_plugin_form_data(form_entry, request, form, form_element_entries
    =None, **kwargs):
    """Submit plugin form data for all plugins.

    :param fobi.models.FormEntry form_entry: Instance of
        ``fobi.models.FormEntry``.
    :param django.http.HttpRequest request:
    :param django.forms.Form form:
    :param iterable form_element_entries:
    """
    if not form_element_entries:
        form_element_entries = form_entry.formelemententry_set.all()
    for form_element_entry in form_element_entries:
        form_element_plugin = form_element_entry.get_plugin(request=request)
        updated_form = form_element_plugin._submit_plugin_form_data(form_entry
            =form_entry, request=request, form=form, form_element_entries=
            form_element_entries, **kwargs)
        if updated_form:
            form = updated_form
    return form


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

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

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


def get_ansible_command(playbook=False):
    """Get the ansible command"""
    cmd = 'ansible'
    if playbook:
        cmd = 'ansible-playbook'
    return cmd


def get(isamAppliance, cert_dbase_id, check_mode=False, force=False):
    """
    Get details of a certificate database
    """
    return isamAppliance.invoke_get(
        'Retrieving details of a certificate database',
        '/isam/ssl_certificates/{0}/details'.format(cert_dbase_id))


def get_single_nic_with_vif_port_id(task):
    """Returns the MAC address of a port which has a VIF port id.

    :param task: a TaskManager instance containing the ports to act on.
    :returns: MAC address of the port connected to deployment network.
              None if it cannot find any port with vif id.
    """
    for port in task.ports:
        if task.driver.network.get_current_vif(task, port):
            return port.address


def get_app_label(app):
    """
    Returns the _internal_ app label for the given app module.
    i.e. for <module django.contrib.auth.models> will return 'auth'
    """
    return app.__name__.split('.')[-2]


@classmethod
def first_or_create(cls, parent=None, **attributes):
    """
        Attempts to find the first resource with the same attributes, creates the resource if no matches are found.
        This will trigger an api GET request and a POST request if the resource does not exist.
        :param parent ResourceBase: the parent of the resource - used for nesting the request url, optional
        :param **attributes: any number of keyword arguments as attributes to search/create the resource
        :returns: a resource instance - the existing one if found, otherwise the newly created one
        """
    existing_resource = cls.find_by(parent, **attributes)
    if existing_resource:
        return existing_resource
    return cls(**attributes).create()


@classmethod
def parse(cls, s, schema_only=False):
    """
        Parse an ARFF File already loaded into a string.
        """
    a = cls()
    a.state = 'comment'
    a.lineno = 1
    for l in s.splitlines():
        a.parseline(l)
        a.lineno += 1
        if schema_only and a.state == 'data':
            break
    return a


@classmethod
def represent(cls, dumper, data):
    """Ensure that the string is dumped with double-quotes."""
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')


def psi_H_Mnjj_Cl_PK74(T, P):
    """c-c'-a: hydrogen manganese(II) chloride [PK74]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def get_account_id(arn: str):
    """Returns the account ID from a string ARN."""
    return arn.split(':')[4]


def detach_load_balancer_from_subnets(LoadBalancerName=None, Subnets=None):
    """
    Removes the specified subnets from the set of configured subnets for the load balancer.
    After a subnet is removed, all EC2 instances registered with the load balancer in the removed subnet go into the OutOfService state. Then, the load balancer balances the traffic among the remaining routable subnets.
    See also: AWS API Documentation

    Examples
    This example detaches the specified load balancer from the specified subnet.
    Expected Output:

    :example: response = client.detach_load_balancer_from_subnets(
        LoadBalancerName='string',
        Subnets=[
            'string',
        ]
    )

    :type LoadBalancerName: string
    :param LoadBalancerName: [REQUIRED]
            The name of the load balancer.

    :type Subnets: list
    :param Subnets: [REQUIRED]
            The IDs of the subnets.
            (string) --

    :rtype: dict
    :return: {
        'Subnets': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def license_storage_node(session, cloud_name, sn_id, return_type=None, **kwargs
    ):
    """
    Storage Node license

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type cloud_name: str
    :param cloud_name: Cloud Name: i.e: zadaraqa9

    :type sn_id: str
    :param sn_id: Storage Node ID

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    path = '/api/clouds/{0}/nodes/{1}/license.json'.format(cloud_name, sn_id)
    return session.post_api(path=path, return_type=return_type, **kwargs)


def get_elapsed_time(time_in_seconds):
    """ Helper function to get elapsed time in human-readable format.

    Parameters
    ----------
    time_in_seconds : float
        runtime, in seconds

    Returns
    -------
    str
        formatted human-readable string describing the time
    """
    if time_in_seconds < 60:
        return '%.1f seconds' % time_in_seconds
    elif time_in_seconds < 3600:
        return '%.1f minutes' % (time_in_seconds / 60)
    else:
        return '%.1f hours' % (time_in_seconds / 3600)


def get_rect_ymax(data):
    """Find maximum y value from four (x,y) vertices."""
    return max(data[0][1], data[1][1], data[2][1], data[3][1])


def intro_interps(toc, reg_part):
    """Logic to fill in any introduction headers for the entire
    interpretations. Note that at some point, we might have headers randomly
    appear elsewhere in the interpretations, unrelated to a specific
    section. That's a @todo."""
    elements = []
    for el in toc.get(reg_part + '-Interp', []):
        if el['index'][1] == 'Interp':
            elements.append({'label': 'Interpretations', 'sub_label': el[
                'title'], 'index': el['index'], 'section_id': '-'.join(el[
                'index'])})
    return elements


def check_trna(trna_obj, eval_flags):
    """Check a TrnaFeature object for errors."""
    if eval_flags['check_trna']:
        pass
    else:
        pass


def dict_patch(d, patch, *, inplace=False):
    """
    Apply a `dict patch` to a dict.

    If `inplace` is set to `True`, the dict `d` is modified in place;
    the default is to make a (shallow) copy before any changes are
    applied.

    This is the reverse of dict_diff().
    """
    if not inplace:
        d = d.copy()
    modifications, deletions = patch
    d.update(modifications)
    for k in deletions:
        del d[k]
    return d


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

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


@classmethod
def get_error_type(cls, api_response):
    """
        Get the error type if the API response is or contain an error.

        :param dict api_response: The API response.

        :rtype: None,str
        """
    if cls.is_error(api_response):
        return api_response['error_type']
    return None


def create_cluster(clusterName=None):
    """
    Creates a new Amazon ECS cluster. By default, your account receives a default cluster when you launch your first container instance. However, you can create your own cluster with a unique name with the CreateCluster action.
    See also: AWS API Documentation

    Examples
    This example creates a cluster in your default region.
    Expected Output:

    :example: response = client.create_cluster(
        clusterName='string'
    )

    :type clusterName: string
    :param clusterName: The name of your cluster. If you do not specify a name for your cluster, you create a cluster named default . Up to 255 letters (uppercase and lowercase), numbers, hyphens, and underscores are allowed.

    :rtype: dict
    :return: {
        'cluster': {
            'clusterArn': 'string',
            'clusterName': 'string',
            'status': 'string',
            'registeredContainerInstancesCount': 123,
            'runningTasksCount': 123,
            'pendingTasksCount': 123,
            'activeServicesCount': 123
        }
    }

    """
    pass


def symmetric_difference(list_1: list, list_2: list) ->list:
    """llogic.symmetric_difference(list_1, list_2)

    Returns the symmetric difference of two lists (omitting repetitions). The
    order of the elements of the output depends on their order in the lists.
    The order of the inputs lists does affect the result. Usage:

    >>> alist = [1, 2, 3, 4, 5]
    >>> blist = [7, 6, 5, 4, 3]
    >>> llogic.symmetric_difference(alist, blist)
    [1, 2, 7, 6]
    >>> llogic.symmetric_difference(blist, alist)
    [7, 6, 1, 2]

    >>> alist = [1, 2, 3, 3, 4, 4, 5, 5, 5]
    >>> blist = [3, 3, 4, 5, 5, 6]
    >>> llogic.symmetric_difference(alist, blist)
    [1, 2, 6]

    Note that llogic.symmetric_difference does not flatten the lists so nested
    lists are of type list:

    >>> alist = [3, 4, 1, 5, 2]
    >>> blist = [1, 2, 3, 4, 5]
    >>> llogic.symmetric_difference(alist, blist)
    []
    >>> alist = [3, 4, [1, [5, 2]]]
    >>> blist = [1, 2, 3, 4, 5]
    >>> llogic.symmetric_difference(alist, blist)
    [[1, [5, 2]], 1, 2, 5]

    The lists can contain any datatype:

    >>> alist = [1, 2.3, 'foo', (3, 7)]
    >>> blist = ['foo', 7+3j, (3, 7)]
    >>> llogic.symmetric_difference(alist, blist)
    [1, 2.3, 7+3j]
    """
    if not isinstance(list_1, list):
        raise TypeError("'list_1' must be 'list'")
    if not isinstance(list_2, list):
        raise TypeError("'list_2' must be 'list'")
    output_list = []
    for item in (list_1 + list_2):
        if item not in list_1 or item not in list_2:
            if item not in output_list:
                output_list.append(item)
    return output_list


def get_lmax(cilm, lmax=None):
    """Return truncated coefficients and maximum degree.

    """
    lmax_comp = cilm[0].shape[0] - 1
    if lmax is not None and 0 < lmax < lmax_comp:
        cilm = cilm[:, :lmax + 1, :lmax + 1]
        lmax_comp = lmax
    return cilm, lmax_comp


def ratio_black(image, rect):
    """ Return the ratio of black pixels to non-black pixels in the rectangle in the image.
    """
    x1, y1, x2, y2 = rect
    x1, x2 = ((x1, x2), (x2, x1))[x1 > x2]
    y1, y2 = ((y1, y2), (y2, y1))[y1 > y2]
    slice = image.crop((x1, y1, x2, y2)).convert('1')
    pixels = slice.size[0] * slice.size[1]
    if pixels == 0:
        return 1.0
    histogram = slice.histogram()
    return histogram[0] / float(pixels)


def get_remote_ip(request):
    """
    Find the IP address of the current request.
    This may require reading a different request header depending on the server setup.
    However, we recommend using wsgiunproxy instead,
    so all packages can read the same header consistently.
    """
    return request.META.get('REMOTE_ADDR', None)


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


def get_function_handle(method, var):
    """
    Return a function handle to a given calculation method.

    Parameters
    ----------
    method : str
        Identifier of the calculation method to return a handle to.
    var : dict
        Local variables needed in the mu update method.

    Returns
    -------
    f_handle : function
        Handle to the calculation method defined in this globals scope.

    """
    return globals()['wrap_calculate_using_' + method](var)


def robot_command(api, command, exp_id, nodes_list=()):
    """ Launch commands ('status',) on nodes_list

    :param api: API Rest api object
    :param command: command that should be run
    :param exp_id: Target experiment id
    :param nodes_list: List of nodes where to run command.
                       Empty list runs on all nodes
    """
    assert command in ('status',)
    result = api.robot_command(command, exp_id, nodes_list)
    return result


@classmethod
def autoupdate_reload(cls):
    """
        After an update - try to auto reload the service that need to be reloaded.
        """
    pass


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

        :param FileMoveType val:
        :rtype: EventType
        """
    return cls('file_move', val)


def draw_multi_line(cr, draw_stroke, lines):
    """
    Draw multiple lines.

    A line is tuple

    - width of a line
    - collection of points

    :param cr: Cairo context.
    :param draw_stroke: Drawing stroke function (i.e. line or filled area).
    :param lines: Collection of lines to draw.
    """
    for width, points in lines:
        cr.new_path()
        cr.set_line_width(width)
        for x, y in points:
            cr.line_to(x, y)
        draw_stroke()


def loop_copy(src, dest):
    """ Copies a source array into a destination array, looping
		through the source array until the entire destination array
		is written.

		# Arguments

		src: numpy array. The source array.
		dest: numpy array. The destination array.

		# Return value

		The destination array.

		# Notes

		If the source array is longer than the destination array, then
		only the first N entries of the source array are copied into the
		destination, where N is the length of the destination array.

		If the source array is shorter than, or of equal length with, the
		destination array, then it will be copied into the destination array
		and repeated, back-to-back, until the destination is filled up (almost
		tiling the destination, if you will).
	"""
    if len(src) > len(dest):
        dest[:] = src[:len(dest)]
    else:
        i = 0
        while i < len(dest):
            entries_to_copy = min(len(dest) - i, len(src))
            dest[i:i + entries_to_copy] = src[:entries_to_copy]
            i += len(src)
    return dest


@classmethod
def from_node_meta(cls, meta_description):
    """
        Create an `NodeItem` instance from a node meta description.
        """
    self = cls()
    self.setWidgetDescription(meta_description)
    return self


def reshaped(data):
    """
    check if data is 1d and if so reshape to a column vector
    """
    import pandas as pd
    import numpy as np
    if isinstance(data, (pd.Series, pd.DataFrame)):
        if len(data.shape) == 1:
            data = data.values.reshape(-1, 1)
        elif len(data.shape) == 2 and data.shape[1] == 1:
            data = data.values.reshape(-1, 1)
    elif isinstance(data, np.ndarray):
        if len(data.shape) == 1:
            data = data.reshape(-1, 1)
    elif isinstance(data, list):
        data = np.array(data)
        if len(data.shape) == 1:
            data = data.reshape(-1, 1)
    return data


def _improve_answer_span(doc_tokens, input_start, input_end, tokenizer,
    orig_answer_text):
    """Returns tokenized answer spans that better match the annotated answer."""
    tok_answer_text = ' '.join(tokenizer.tokenize(orig_answer_text))
    for new_start in range(input_start, input_end + 1):
        for new_end in range(input_end, new_start - 1, -1):
            text_span = ' '.join(doc_tokens[new_start:new_end + 1])
            if text_span == tok_answer_text:
                return new_start, new_end
    return input_start, input_end