def list_size_constraint_sets(NextMarker=None, Limit=None):
    """
    Returns an array of  SizeConstraintSetSummary objects.
    See also: AWS API Documentation

    Examples
    The following example returns an array of up to 100 size contraint match sets.
    Expected Output:

    :example: response = client.list_size_constraint_sets(
        NextMarker='string',
        Limit=123
    )

    :type NextMarker: string
    :param NextMarker: If you specify a value for Limit and you have more SizeConstraintSets than the value of Limit , AWS WAF returns a NextMarker value in the response that allows you to list another group of SizeConstraintSets . For the second and subsequent ListSizeConstraintSets requests, specify the value of NextMarker from the previous response to get information about another batch of SizeConstraintSets .

    :type Limit: integer
    :param Limit: Specifies the number of SizeConstraintSet objects that you want AWS WAF to return for this request. If you have more SizeConstraintSets objects than the number you specify for Limit , the response includes a NextMarker value that you can use to get another batch of SizeConstraintSet objects.

    :rtype: dict
    :return: {
        'NextMarker': 'string',
        'SizeConstraintSets': [
            {
                'SizeConstraintSetId': 'string',
                'Name': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def from_stream(cls, stream):
    """
        Return |Gif| instance having header properties parsed from GIF image
        in *stream*.
        """
    px_width, px_height = cls._dimensions_from_stream(stream)
    return cls(px_width, px_height, 72, 72)


def containsOnly(str, set):
    """Check whether sequence str contains ONLY items in set."""
    for c in str:
        if c not in set:
            return 0
    return 1


def no_op(*args):
    """No-op function for callbacks.
    """
    pass


def __retry_if_not_state(result):
    """Only keep retrying if the state is not what is expected.

        :return: negation of input
        """
    return not result


def cMultiplyRealInplace():
    """
    Return the kernel source of cMultiplyRealInplace.
    """
    R = """
    KERNEL void cMultiplyRealInplace(
    const unsigned int batch,
    GLOBAL_MEM const float *a,
    GLOBAL_MEM float2 *outb)
    {
    const unsigned int gid = get_global_id(0);
    // const unsigned int voxel_id = gid / batch;
    const unsigned int voxel_id = (float)gid / (float)batch;
    float mul = a[voxel_id];
    float2 orig = outb[gid];
    orig.x=orig.x*mul;
    orig.y=orig.y*mul;
    outb[gid]=orig;
    };
    """
    return R


def __len__():
    """Obtain the number of revisions stored for this manifest."""


def transform_from_local(xp, yp, cphi, sphi, mx, my):
    """ Transform from the local frame to absolute space.
    """
    x = xp * cphi - yp * sphi + mx
    y = xp * sphi + yp * cphi + my
    return x, y


def generate_url(len, elems):
    """Generate (a random) new url."""


def hook_add_newob():
    """Hook selected vertices to a newly created object

    """
    pass


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

    The ".dev0" means dirty.

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


def stabilize_2d_remove():
    """Remove selected track from translation stabilization

    """
    pass


@staticmethod
def merge_list_no_duplicates(a1, a2):
    """
        merge two lists by overwriting the original with the second one if the key exists
        :param a1:
        :param a2:
        :return:
        """
    r = []
    if isinstance(a1, list) and isinstance(a2, list):
        r = a1
        for i in a2:
            if i not in a1:
                r.append(i)
    return r


def context_cycle_int(data_path: str='', reverse: bool=False, wrap: bool=False
    ):
    """Set a context value (useful for cycling active material, vertex keys, groups, etc.)

    :param data_path: Context Attributes, RNA context string
    :type data_path: str
    :param reverse: Reverse, Cycle backwards
    :type reverse: bool
    :param wrap: Wrap, Wrap back to the first/last values
    :type wrap: bool
    """
    pass


def qualified_class_name(o):
    """Full name of an object, including the module"""
    module = o.__class__.__module__
    if module is None or module == str.__class__.__module__:
        return o.__class__.__name__
    return module + '.' + o.__class__.__name__


def ignore_existing_pidfile():
    """Normally, daemonize() or daemonize_start() will terminate the program
    with a message if a locked pidfile already exists.  If this function is
    called, an existing pidfile will be replaced, with a warning."""
    global _overwrite_pidfile
    _overwrite_pidfile = True


def intervals(seq):
    """Iterate over each successive pair in a sequence.

    Examples
    --------
    >>> for i in intervals([1, 2, 3, 45]):
    ...     print(i)
    ...
    (1, 2)
    (2, 3)
    (3, 45)
    """
    iterator = iter(seq)
    try:
        last = next(iterator)
    except StopIteration:
        return
    for item in iterator:
        yield last, item
        last = item


def _dispatch_setuptools_install(distribution, command_name):
    """
    setuptools hack:
    - handle dependencies in `install_requires` by calling fetch_build_eggs()
    """
    if distribution.install_requires:
        try:
            distribution.fetch_build_eggs(distribution.install_requires)
        except Exception:
            pass
    distribution.run_command(command_name)


def saturated_vapor_pressure4(t):
    """Calculate the saturated vapor pressure as described in
    http://www.vaisala.com/Vaisala%20Documents/Application%20notes/Humidity_Conversion_Formulas_B210973EN-F.pdf

    Parameters
    ---------
    t : float
        Temperature [C]

    Returns
    -------
    Saturated vapor pressure [mBar]
    """
    A = 6.116441
    m = 7.591386
    Tn = 240.7263
    return A * 10 ** (m * t / (t + Tn))


def format_signed(feature, formatter=None, **kwargs):
    """
    Format unhashed feature with sign.

    >>> format_signed({'name': 'foo', 'sign': 1})
    'foo'
    >>> format_signed({'name': 'foo', 'sign': -1})
    '(-)foo'
    >>> format_signed({'name': ' foo', 'sign': -1}, lambda x: '"{}"'.format(x))
    '(-)" foo"'
    """
    txt = '' if feature['sign'] > 0 else '(-)'
    name = feature['name']
    if formatter is not None:
        name = formatter(name, **kwargs)
    return '{}{}'.format(txt, name)


def create_sample_file(ip, op, num_lines):
    """ make a short version of an RDF file """
    with open(ip, 'rb') as f:
        with open(op, 'wb') as fout:
            for _ in range(num_lines):
                fout.write(f.readline())


def mp_worker(input, output):
    """
    Process an item from `input` queue and place results in `output` queue.

    Parameters
    ----------
    input : multiprocessing.Queue object
    output : multiprocessing.Queue object
    """
    for func, args in iter(input.get, 'STOP'):
        result = func(*args)
        output.put(result)


def package_root(varmap):
    """Return correct directory for the root package.

    The "root" package is the one where modules which do not
    belong to a package are located (see the distutils docs).
    This function should not need to be called directly in
    your actual setup script, but it can be useful for testing.
    Note that it looks for a ``package_root`` setup var, which
    can be used as a shortcut if your "root" package is not in
    the standard place (which is your setup script directory),
    rather than having to declare a ``package_dir`` dictionary
    with a ``''`` key.
    """
    try:
        return varmap['package_dir']['']
    except KeyError:
        try:
            result = varmap['package_root']
        except KeyError:
            return '.'
        else:
            dirmap = varmap.setdefault('package_dir', {})
            if '' not in dirmap:
                dirmap[''] = result
            return result


def tuplify(x):
    """Convert a list to a tuple, or wrap an object in a tuple if it's not a list or tuple."""
    if isinstance(x, list) or isinstance(x, tuple):
        return tuple(x)
    else:
        return tuple([x])


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 locstr(locs, strand):
    """genbank formatted location string, assumes no join'd combo of rev and fwd seqs"""
    locstr = ','.join(map(lambda x: str(x[0]) + '..' + str(x[1]), locs))
    if len(locs) > 1:
        locstr = 'join(' + locstr + ')'
    if int(strand) == -1:
        locstr = 'complement(' + locstr + ')'
    return locstr


def cut_long_name(name: str, max_len: int=12) ->str:
    """
    If the name is longer than `max_len`,
    cut it to `max_len` length and append "..."
    """
    if len(name) <= max_len:
        return name
    return f'{name[:max_len]}...'


def is_set(obj):
    """Helper method to see if the object is a Python set.

    >>> is_set(set())
    True
    """
    return type(obj) is set


@classmethod
def definedThreatEntryTypes(cls):
    """
        Class method to get all threat entry types defined in API v4.

        @return list of all defined threat entry types
        @rtype list of str
        """
    return ['THREAT_ENTRY_TYPE_UNSPECIFIED', 'URL', 'EXECUTABLE']


def adapt_pop(pop, params: dict, param_map: dict):
    """Changes the parametrization of a circuit.

    Parameters
    ----------
    pop
        ANNarchy population instance.
    params
        Key-value pairs of the parameters that should be changed.
    param_map
        Map between the keys in params and the circuit variables.

    Returns
    -------
    Population
        Updated population instance.

    """
    for key in params.keys():
        val = params[key]
        for op, var in param_map[key]['var']:
            nodes = param_map[key]['nodes'] if 'nodes' in param_map[key] else [
                ]
            for node in nodes:
                if node in pop.name:
                    try:
                        pop.set({var: float(val)})
                    except TypeError:
                        pop.set({var: val})
                    except (KeyError, ValueError):
                        pass
    return pop


def get_epoch(cls):
    """Return the current epoch of the AaaaHorodatage class."""
    return cls.epoch


def write_ind(out, triple, outfile):
    """
    Write the current output dictionary from test_individuals()
    to the file passed as an argument to the function.
    """
    for k, v in out.items():
        print(triple[0], '\t', k, '\t', triple[2], '\t', sep='', end='',
            file=outfile)
        print(v['Zscore'], '\t', sep='', end='', file=outfile)
        print(v['Pvalue'], '\t', sep='', end='', file=outfile)
        print(v['Gamma'], '\t', sep='', end='', file=outfile)
        print(v['AAAA'], '\t', sep='', end='', file=outfile)
        print(v['AAAB'], '\t', sep='', end='', file=outfile)
        print(v['AABA'], '\t', sep='', end='', file=outfile)
        print(v['AABB'], '\t', sep='', end='', file=outfile)
        print(v['AABC'], '\t', sep='', end='', file=outfile)
        print(v['ABAA'], '\t', sep='', end='', file=outfile)
        print(v['ABAB'], '\t', sep='', end='', file=outfile)
        print(v['ABAC'], '\t', sep='', end='', file=outfile)
        print(v['ABBA'], '\t', sep='', end='', file=outfile)
        print(v['BAAA'], '\t', sep='', end='', file=outfile)
        print(v['ABBC'], '\t', sep='', end='', file=outfile)
        print(v['CABC'], '\t', sep='', end='', file=outfile)
        print(v['BACA'], '\t', sep='', end='', file=outfile)
        print(v['BCAA'], '\t', sep='', end='', file=outfile)
        print(v['ABCD'], '\n', sep='', end='', file=outfile)


def procmap(method, item_list):
    """
    Like map(), but where the method being applied has no return value. In
    other words, the procedure is called on every item in the list
    sequentially, but since each call has no return value, the call to
    procmap() also has no return value.

    @param method: The procedure to call each time.
    @param item_list: The list of items to apply the procedure to.
    @return: None
    """
    for item in item_list:
        method(item)


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

        :param MemberChangeEmailType val:
        :rtype: EventType
        """
    return cls('member_change_email', val)


def html_escape(string):
    """ Escape HTML special characters ``&<>`` and quotes ``'"``. """
    return string.replace('&', '&').replace('<', '<').replace('>',
        '>').replace('"', '"').replace("'", ''')


def enabled(username):
    """ Whether secure login is enabled for the provided user
        """


def rand_str(length):
    """Generate random string"""
    import string, random
    available_chars = string.ascii_uppercase + string.digits
    return ''.join(random.choice(available_chars) for _ in range(length))


def subset_data_stack_variables(data, varset, seatype='total', mode='subset'):
    """
        Subset variables of a dataset stack. This function is just a shorthand to not have to specify all vaiables when subsetting dataframes. Not the most clever way to deal with this honestly.

        :param data: dataframe of data to subset
        :param varset: keyword specifiying the subset to get
        :param seatype: defaults to total. When "wave" parameters are to be retrieved, specify which kind of sea parameters to have
        :param mode: subset : return actual dataframe or returnnames: return only column names per subset
        :returns: either dataframe of data, or list of columns names.
    """
    if (varset.lower() == 'wave') | (varset.lower() == 'waves'):
        cols_total = ['hs', 'tp', 'steep', 'phase_vel', 'age', 'wind']
        cols_wind = ['hs_w', 'tp_w', 'steep_w', 'phase_vel_w', 'age_w', 'wind']
    elif varset.lower() == 'wave_nowind':
        cols_total = ['hs', 'tp', 'steep', 'phase_vel']
        cols_wind = ['hs_w', 'tp_w', 'steep_w', 'phase_vel_w']
    elif varset.lower() == 'wave_reduced':
        cols_total = ['hs', 'tp', 'wind']
        cols_wind = ['hs_w', 'tp_w', 'wind']
    elif varset.lower() == 'wave_ecmwf':
        cols_total = ['hs', 'tp', 'steep', 'phase_vel', 'age', 'wind', 't',
            'slp', 'q', 'v', 'u', 'iwc', 'ps', 'rh', 'th', 'lsp', 'cp',
            'rtot', 'blh', 'blhp', 'td2m', 't2m', 'skt', 'sif', 'the', 'lsm']
        cols_wind = ['hs_w', 'tp_w', 'steep_w', 'phase_vel_w', 'age_w',
            'wind', 't', 'slp', 'q', 'v', 'u', 'iwc', 'ps', 'rh', 'th',
            'lsp', 'cp', 'rtot', 'blh', 'blhp', 'td2m', 't2m', 'skt', 'sif',
            'the', 'lsm']
    elif varset.lower() == 'ecmwf':
        cols_total = ['t', 'slp', 'q', 'v', 'u', 'iwc', 'ps', 'rh', 'th',
            'lsp', 'cp', 'rtot', 'blh', 'blhp', 'td2m', 't2m', 'skt', 'sif',
            'the', 'lsm']
    elif varset.lower() == 'wholeset':
        cols_total = data.columns.tolist()[:-1]
    else:
        print('variables not specified')
        return
    if seatype == 'total':
        cols = cols_total
    elif seatype == 'wind':
        cols = cols_wind
    else:
        print('seatype not correct')
        return
    if mode == 'subset':
        if 'parbin' in data.columns:
            cols.append('parbin')
        return data[cols]
    elif mode == 'returnnames':
        print(cols)
        return cols


def get_group(GroupName=None, Marker=None, MaxItems=None):
    """
    Returns a list of IAM users that are in the specified IAM group. You can paginate the results using the MaxItems and Marker parameters.
    See also: AWS API Documentation

    :example: response = client.get_group(
        GroupName='string',
        Marker='string',
        MaxItems=123
    )

    :type GroupName: string
    :param GroupName: [REQUIRED]
            The name of the group.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: =,.@-

    :type Marker: string
    :param Marker: Use this parameter only when paginating results and only after you receive a response indicating that the results are truncated. Set it to the value of the Marker element in the response that you received to indicate where the next call should start.

    :type MaxItems: integer
    :param MaxItems: (Optional) Use this only when paginating results to indicate the maximum number of items you want in the response. If additional items exist beyond the maximum you specify, the IsTruncated response element is true .
            If you do not include this parameter, it defaults to 100. Note that IAM might return fewer results, even when there are more results available. In that case, the IsTruncated response element returns true and Marker contains a value to include in the subsequent call that tells the service where to continue from.

    :rtype: dict
    :return: {
        'Group': {
            'Path': 'string',
            'GroupName': 'string',
            'GroupId': 'string',
            'Arn': 'string',
            'CreateDate': datetime(2015, 1, 1)
        },
        'Users': [
            {
                'Path': 'string',
                'UserName': 'string',
                'UserId': 'string',
                'Arn': 'string',
                'CreateDate': datetime(2015, 1, 1),
                'PasswordLastUsed': datetime(2015, 1, 1)
            },
        ],
        'IsTruncated': True|False,
        'Marker': 'string'
    }

    :returns:
    CreateUser
    GetUser
    ListUsers

    """
    pass


def read_uic3tag(fh, byteorder, dtype, plane_count):
    """Read MetaMorph STK UIC3Tag from file and return as dictionary."""
    assert dtype == '2I' and byteorder == '<'
    values = fh.read_array('<u4', 2 * plane_count).reshape(plane_count, 2)
    return {'wavelengths': values[:, (0)] / values[:, (1)]}


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_cigar(var):
    """
    Return the cigar string describing how to align an
    alternate allele to the reference allele
    """
    return var.INFO.get('CIGAR')


def height_to_resolution(height):
    """Convert height to resolution."""
    if height >= 4320:
        return '8K'
    if height >= 2160:
        return '4K'
    if height >= 1080:
        return '1080p'
    if height >= 720:
        return '720p'
    return f'{height}p'


def _fewer_tokens(tokens, remove):
    """Process the output of `tokenize.generate_tokens` removing
    the tokens specified in `remove`.
    """
    for values in tokens:
        if values[0] in remove:
            continue
        yield values


def _format_field_name(attr):
    """Format an object attribute in a human-friendly way."""
    parts = attr.rsplit(':', 1)
    name = parts[-1].replace('_', ' ')
    if name.isupper() or name.islower():
        name = name.title()
    parts[-1] = name
    return ': '.join(parts)


def cluster_attach_policy(base, cluster_id, policy_id, expected_status=
    'SUCCEEDED', wait_timeout=None):
    """Utility function that attach a policy to cluster."""
    params = {'policy_attach': {'enabled': True, 'policy_id': policy_id}}
    res = base.client.trigger_action('clusters', cluster_id, params=params)
    action_id = res['location'].split('/actions/')[1]
    res = base.client.wait_for_status('actions', action_id, expected_status,
        wait_timeout)
    return res['body']['status_reason']


def encode(i: int) ->bytes:
    """Return the varint bytes encoding of an integer."""
    if i <= 252:
        return bytes([i])
    elif i <= 65535:
        return b'\xfd' + i.to_bytes(2, byteorder='little')
    elif i <= 4294967295:
        return b'\xfe' + i.to_bytes(4, byteorder='little')
    elif i <= 18446744073709551615:
        return b'\xff' + i.to_bytes(8, byteorder='little')
    else:
        raise ValueError(f'integer too large ({hex(i)}) for varint encoding')


@staticmethod
def text_external_link(text, link=''):
    """ Using this method can be created an external link of a file or a web page.

        :param text: Text to be displayed.
        :type text: str
        :param link: External Link.
        :type link: str
        :return: return a string like this: ``'[Text to be shown](https://write.link.com)'``
        :rtype: str"""
    return '[' + text + '](' + link + ')'


def MakeListItems(items):
    """
    Turns a list into listItems used by form fields. Each item in the list is
    converted into a dict. e.g. ``("a","b","c")`` or ``(("a","Name a"),("b","Name b"),("c","Name c"))``

    :param items: list of items
    :return: listItems
    """
    li = []
    for i in items:
        if isinstance(i, str):
            li.append(dict(id=i, name=i))
        elif isinstance(i, (list, tuple)):
            li.append(dict(id=i[0], name=i[1]))
        else:
            i = str(i)
            li.append(dict(id=i, name=i))
    return li


def isFirstLevelAnalysis(settings):
    """Returns ``True`` if the FEAT analysis described by ``settings``
    is a first level analysis, ``False`` otherwise.

    :arg settings: A FEAT settings dictionary (see :func:`loadSettings`).
    """
    return settings['level'] == '1'


def compare_dicom_key(dcm):
    """ Specifying the sorting key for CT images.
    """
    return float(dcm.ImagePositionPatient[2])


def complete_lifecycle_action(LifecycleHookName=None, AutoScalingGroupName=
    None, LifecycleActionToken=None, LifecycleActionResult=None, InstanceId
    =None):
    """
    Completes the lifecycle action for the specified token or instance with the specified result.
    This step is a part of the procedure for adding a lifecycle hook to an Auto Scaling group:
    For more information, see Auto Scaling Lifecycle in the Auto Scaling User Guide .
    See also: AWS API Documentation

    Examples
    This example notifies Auto Scaling that the specified lifecycle action is complete so that it can finish launching or terminating the instance.
    Expected Output:

    :example: response = client.complete_lifecycle_action(
        LifecycleHookName='string',
        AutoScalingGroupName='string',
        LifecycleActionToken='string',
        LifecycleActionResult='string',
        InstanceId='string'
    )

    :type LifecycleHookName: string
    :param LifecycleHookName: [REQUIRED]
            The name of the lifecycle hook.

    :type AutoScalingGroupName: string
    :param AutoScalingGroupName: [REQUIRED]
            The name of the group for the lifecycle hook.

    :type LifecycleActionToken: string
    :param LifecycleActionToken: A universally unique identifier (UUID) that identifies a specific lifecycle action associated with an instance. Auto Scaling sends this token to the notification target you specified when you created the lifecycle hook.

    :type LifecycleActionResult: string
    :param LifecycleActionResult: [REQUIRED]
            The action for the group to take. This parameter can be either CONTINUE or ABANDON .

    :type InstanceId: string
    :param InstanceId: The ID of the instance.

    :rtype: dict
    :return: {}

    :returns:
    LifecycleHookName (string) -- [REQUIRED]
    The name of the lifecycle hook.

    AutoScalingGroupName (string) -- [REQUIRED]
    The name of the group for the lifecycle hook.

    LifecycleActionToken (string) -- A universally unique identifier (UUID) that identifies a specific lifecycle action associated with an instance. Auto Scaling sends this token to the notification target you specified when you created the lifecycle hook.
    LifecycleActionResult (string) -- [REQUIRED]
    The action for the group to take. This parameter can be either CONTINUE or ABANDON .

    InstanceId (string) -- The ID of the instance.

    """
    pass


def config(path):
    """
    Set CONFIG_FILE, the path to the configuration JSON file,
    to the given path, and return the new path.

    No error or sanity checking is performed.
    """
    global CONFIG_FILE
    CONFIG_FILE = path
    return CONFIG_FILE


@staticmethod
def delay_as_int(delay):
    """ By convention, None means no delay """
    return 0 if delay is None else int(delay)


def create_matrix33_view(mat):
    """Returns a view into the matrix in Matrix33 format.

    This is different from matrix33.create_from_matrix44, in that
    changes to the returned matrix will also alter the original matrix.

    :rtype: numpy.array
    :return: A view into the matrix in the format of a matrix33 (shape (3,3)).
    """
    return mat[0:3, 0:3]


def ask_yes_no(prompt='', response_attempt=1):
    """Function to get the user's yes/no response to a question.

    Accepts variations of yes/y, true/t, no/n, false/f, exit/quit/q.

    :param prompt: the question to ask the user.
    :type prompt: str
    :param response_attempt:

        The number of the number of attempts allowed before the
        function exits. This prevents the script from getting stuck in a loop.

    :type response_attempt: int
    :returns:

        The default is False (e.g. user hits Enter without typing
        anything else), but variations of yes or true responses will return
        True instead. If the response is 'exit' or 'quit', the loop is exited
        and None is returned.

    :rtype: bool, None
    """
    response_valid = False
    while response_valid is False and response_attempt > 0:
        response = input(prompt)
        response_attempt -= 1
        if response.lower() in set(['yes', 'y', 't', 'true']):
            response = True
            response_valid = True
        elif response.lower() in set(['no', 'n', 'f', 'false', '']):
            response = False
            response_valid = True
        elif response.lower() in set(['exit', 'quit', 'q']):
            response = None
            response_valid = True
        else:
            response = None
            print('Invalid response. Enter [yes/no/exit].')
    return response


def get_environment_by_name(name):
    """Returns environment of given `name` or None if not found."""


def get_file_lines(name):
    """
    Get the number of lines in a file
    Parameters
    ----------
    str name: filepath and name of file
    """
    lines = 0
    with open(name, 'r') as stream:
        lines = len(stream.readlines())
    return lines


def graph_delete_curve():
    """Delete track corresponding to the selected curve

    """
    pass


def iterDefaultQueryFactories():
    """return iterator of all available factories"""


@classmethod
def get_key(cls, key):
    """Get the path to `key` in the config file."""
    return cls.get().get(key, cls.DEFAULT_CONFIG.get(key, None))


def _translate_shards(shards):
    """Converts the dicts from DescribeStream to the internal Shard format."""
    for shard in shards:
        yield {'shard_id': shard['ShardId'], 'iterator_type': None,
            'sequence_number': None, 'iterator_id': None, 'parent': shard.
            get('ParentShardId')}


@staticmethod
def wait_workflow(workflow_id, wf_ctrl):
    """
        Waits for workflow execution to end.

        Parameters
        ----------
        workflow_id: workflow identifier

        wf_ctrl: client.WorkflowController
        """
    wf_ctrl.wait_workflow(workflow_id)


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


def encode_base128_int(val):
    """Convert an integer into a 7-bit lsb encoding."""
    data = bytearray()
    count = 0
    while val >= 128:
        data.append((val | 128) & 255)
        val >>= 7
    data.append(val)
    return bytes(data)


def propertyMaker(func):
    """
    Create a property from C{func}'s return values.

    @type func: C{callable} returning an iterable
    @param func: Callable whose return values are passed on as positional
        arguments to C{property}

    @rtype: C{property} instance
    """
    return property(*func())


def gseq(ratio, initval=1):
    """A geometric sequence generator.  Works with any type with * defined.

	>>> from decimal import Decimal
	>>> gseq(Decimal('.2')) >> item[:4]
	[1, Decimal('0.2'), Decimal('0.04'), Decimal('0.008')]
	"""
    while 1:
        yield initval
        initval *= ratio


@staticmethod
def _fetch_file_metadata(client, path):
    """Return metadata for a single file."""
    for _, dataset in client.datasets.items():
        for file_ in dataset.files:
            if file_.path == path:
                return file_


@staticmethod
def __do(work):
    """
        Helper function for `HttpClient._parallelize`.
        """
    fn = work[0]
    args = work[1:]
    return fn(*args)


@classmethod
def refresh(cls):
    """Force the refresh of the index when you insert, delete or update and search after."""
    cls._refresh(cls.get_index_name())


def is_int(obj):
    """
    True & False is not considered valid integers even if python considers them 1 & 0 in some versions
    """
    return isinstance(obj, int) and not isinstance(obj, bool)


def toggleDeprecatedMessages(enabled):
    """
		toggleDeprecatedMessages - Normally, a deprecated message will log up to once per message.
		  Call toggleDeprecatedMessages(False) to turn them off altogether (like on a Production codebase)

		@param enabled <bool> - False to disable deprecated messages, otherwise True.
	"""
    global __deprecatedMessagesEnabled
    __deprecatedMessagesEnabled = enabled


def get_type(obj):
    """
    Get the type of object or if it is a class, return the class itself.
    """
    return obj if type(obj) is type else type(obj)


def _find_class_construction_fn(cls):
    """Find the first __init__ or __new__ method in the given class's MRO."""
    for base in type.mro(cls):
        if '__init__' in base.__dict__:
            return base.__init__
        if '__new__' in base.__dict__:
            return base.__new__


@classmethod
def stopPreciseCoverage(cls):
    """Disable precise code coverage. Disabling releases unnecessary execution count records and allows
executing optimized code.
        """
    return cls.build_send_payload('stopPreciseCoverage', {}), None


def count_number_overrides_excluding_repeated(override_times,
    override_values, post_override_time_to_exclude):
    """
        In order to do checks to see how the overrides are calibrated we need to filter any repeated overrides otherwise they will be double counted
        there are probably issues with this because of cases like multuple overrides in a row where eventually they will extend past the post_override_time_to_exclude bit
        assumes override_times and override_values have already been condensed to times when the value changes
    """
    override_to_on_ct = 0
    override_to_off_ct = 0
    last_override_time = None
    for i in range(len(override_times)):
        cur_time = override_times[i]
        cur_value = override_values[i]
        if (last_override_time is None or cur_time > last_override_time +
            post_override_time_to_exclude):
            last_override_time = cur_time
            if cur_value == 0:
                override_to_off_ct += 1
            else:
                override_to_on_ct += 1
    return override_to_on_ct, override_to_off_ct


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

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


def trailing_whitespace(physical_line):
    """Trailing whitespace is superfluous.

    The warning returned varies on whether the line itself is blank, for easier
    filtering for those who want to indent their blank lines.

    Okay: spam(1)\\n#
    W291: spam(1) \\n#
    W293: class Foo(object):\\n    \\n    bang = 12
    """
    physical_line = physical_line.rstrip('\n')
    physical_line = physical_line.rstrip('\r')
    physical_line = physical_line.rstrip('\x0c')
    stripped = physical_line.rstrip(' \t\x0b')
    if physical_line != stripped:
        if stripped:
            return len(stripped), 'W291 trailing whitespace'
        else:
            return 0, 'W293 blank line contains whitespace'


def send_arduino_simple(msg, serial_connection):
    """
    Send the *msg* over the *serial_connection*

    Same as :code:`send_arduino`, but doesn't add anything to the message
    before sending it.

    Parameters
    ----------
    msg : str or bytes
        the message you want to send
    serial_connection : object
        the :code:`serial.Serial` object you want to use for sending
    """
    if not isinstance(msg, bytes):
        msg = str(msg).encode()
    serial_connection.write(msg)


def is_an_upcast(type1, type2):
    """Given two data types (as strings), check if converting to
    type2 from type1 constitutes an upcast.
    Differs from theano.scalar.upcast

    """
    category = {'bool': (0, 0), 'uint8': (1, 1), 'uint16': (1, 2), 'uint32':
        (1, 3), 'uint64': (1, 4), 'int8': (2, 1), 'int16': (2, 2), 'int32':
        (2, 3), 'int64': (2, 4), 'float16': (3, 1.5), 'float32': (3, 2.5),
        'float64': (3, 3.5), 'complex64': (4, 3), 'complex128': (4, 4)}
    cat1 = category[type1]
    cat2 = category[type2]
    if cat2[0] >= cat1[0] and cat2[1] > cat1[1]:
        return True
    else:
        return False


def output_ami_permissions(perms=None):
    """
    @type perms: dict
    """
    out = ''
    for i, launch_perm in enumerate(perms.get('LaunchPermissions')):
        if 'UserId' in launch_perm:
            out += 'UserId: {0}'.format(launch_perm.get('UserId'))
        if i < len(perms.get('LaunchPermissions')) - 1:
            out += '\n'
    return out


@classmethod
def get_client_info(cls, net_info, para_name, default_value=None):
    """
        获取指定客户端连接的信息，根据传入的参数获取参数值（具体可以获取什么参数由实现类自定义）

        @param {object} net_info - 客户端网络连接信息对象
        @param {string} para_name - 参数名

        @returns {object} - 返回具体的参数值对象（实现类自定义）

        """
    if para_name == 'ip':
        return net_info.raddr[0]
    elif para_name == 'port':
        return net_info.raddr[1]
    elif para_name == 'socket':
        return net_info.csocket
    elif hasattr(net_info, para_name):
        return eval('net_info.' + para_name)
    else:
        return default_value


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


def _(val):
    """Dummy placeholder for translation function used in Django code

    May implement late
    """
    return val


def _is_shutting_down(_shutting_down=_shutting_down):
    """
    Whether the interpreter is currently shutting down.
    For use in finalizers, __del__ methods, and similar; it is advised
    to early bind this function rather than look it up when calling it,
    since at shutdown module globals may be cleared.
    """
    return _shutting_down[0]


def Strip(v):
    """Strip whitespace from a string.

    >>> s = Schema(Strip)
    >>> s('  hello world  ')
    'hello world'
    """
    return str(v).strip()


def iterrsplit(s, c):
    """Split string `s` on `c` and rejoin on `c` from the end of `s`.

    Parameters
    ----------
    s : :class:`str`
        String to split
    c : :class:`str`
        Split on this string.

    Returns
    -------
    :class:`str`
        Iteratively return the joined parts of `s`.
    """
    ss = s.split(c)
    i = -1
    while abs(i) <= len(ss):
        yield c.join(ss[i:])
        i -= 1
    return


@staticmethod
def initialise_source(c, key):
    """
        Return a starting value for pressure and enthalpy at outlet.

        Parameters
        ----------
        c : tespy.connections.connection
            Connection to perform initialisation on.

        key : str
            Fluid property to retrieve.

        Returns
        -------
        val : float
            Starting value for pressure/enthalpy in SI units.

            .. math::

                val = \\begin{cases}
                10^6 & \\text{key = 'p'}\\\\
                3 \\cdot 10^5 & \\text{key = 'h'}
                \\end{cases}
        """
    if key == 'p':
        return 1000000.0
    elif key == 'h':
        return 300000.0


def p_formulas(p):
    """concat :  math_object formula"""
    if p[0] == None:
        p[0] = p[1] + p[2]
    else:
        p[0] = p[0] + p[1] + p[2]


@conf
def gxx_modifier_platform(conf):
    """Execute platform-specific functions based on *gxx_modifier_+NAME*"""
    gxx_modifier_func = getattr(conf, 'gxx_modifier_' + conf.env.DEST_OS, None)
    if gxx_modifier_func:
        gxx_modifier_func()


def apply_shot_selection(lists, stacks, min_chunk=None, reset_shot_index=True):
    """
    Applies the selection of shots as defined by the 'selected' column of the shot list, returning corresponding
    subsets of both lists (pandas DataFrames) and stacks (dask arrays).
    :param lists: flat dict of lists. Does not handle subsets, so use flat=True when reading from file
    :param stacks: dict of arrays. Again, not accounting for subsets. Use flat=True for reading
    :param min_chunk: minimum chunk size of the output arrays along the stacked dimension
    :param reset_shot_index: if True, the returned shot list has its index reset, with correspondingly updated serial
            numbers in peak list. Recommended.
    :return new_lists, new_stacks: subselected lists and stacks
    """
    shots = lists['shots']
    new_lists = lists.copy()
    new_lists['shots'] = lists['shots'].query('selected').copy()
    print('Keeping {} shots out of {}'.format(len(new_lists['shots']), len(
        shots)))
    if 'peaks' in lists.keys():
        peaksel = lists['peaks'].merge(shots[['selected']], left_on=
            'serial', right_index=True)['selected']
        new_lists['peaks'] = lists['peaks'].loc[(peaksel), :]
        if reset_shot_index:
            new_lists['shots']['newEv'] = range(len(new_lists['shots']))
            new_lists['peaks'] = new_lists['peaks'].merge(new_lists['shots'
                ].loc[:, (['newEv'])], left_on='serial', right_index=True)
            new_lists['peaks']['serial'] = new_lists['peaks']['newEv']
            new_lists['peaks'].drop('newEv', axis=1, inplace=True)
            new_lists['shots'].drop('newEv', axis=1, inplace=True)
    if reset_shot_index:
        new_lists['shots'].reset_index(drop=True, inplace=True)
    new_stacks = {}
    for k, stk in stacks.items():
        stack = stk[shots['selected'].values, ...]
        if min_chunk is not None:
            nchk = 0
            fchks = []
            for ii, chk in enumerate(stack.chunks[0]):
                nchk += chk
                if nchk >= min_chunk:
                    fchks.append(nchk)
                    nchk = 0
                elif ii == len(stack.chunks[0]) - 1:
                    fchks[-1] += nchk
            stack = stack.rechunk({(0): tuple(fchks)})
        new_stacks.update({k: stack})
    return new_lists, new_stacks


def reload():
    """Update objects paths list with new data from the archive

    """
    pass


def add_arg(func, *args, **kwargs):
    """Bind CLI arguments to a shell.py `do_foo` function."""
    if not hasattr(func, 'arguments'):
        func.arguments = []
    if (args, kwargs) not in func.arguments:
        func.arguments.insert(0, (args, kwargs))


def chunked(iterator, chunksize):
    """
    Yields items from 'iterator' in chunks of size 'chunksize'.

    >>> list(chunked([1, 2, 3, 4, 5], chunksize=2))
    [(1, 2), (3, 4), (5,)]
    """
    chunk = []
    for idx, item in enumerate(iterator, 1):
        chunk.append(item)
        if idx % chunksize == 0:
            yield chunk
            chunk = []
    if chunk:
        yield chunk


def angle_diff(angle1, angle2):
    """show the difference between two angles in degrees"""
    ret = angle1 - angle2
    if ret > 180:
        ret -= 360
    if ret < -180:
        ret += 360
    return ret


def findAll(**names):
    """
        Find all L{EnumItem}s with matching extra values.

        @param **names: Extra values to match

        @rtype:  C{iterable} of L{EnumItem}
        """


def makeView(items, view=None):
    """ Create and return a new view for the given collection.

    items -- given collection
    view -- an optional argument of an already existing repository view, if
    not None, a new view is NOT created and it is returned as is for reusal

    return DBRepositoryView

    """
    newView = view
    if view is None:
        newView = items.itsView.repository.createView()
    return newView


@staticmethod
def axis_set_facecolor(axis, color):
    """ Allow safe use of Axes.set_facecolor and  (available in MPL v1.5.x) """
    try:
        axis.set_facecolor(color)
    except AttributeError:
        axis.set_axis_bgcolor(color)


def filter_and_join_taxonomy(feat_table, taxonomy, num_string, denom_string):
    """Perform taxonomy searching and join with feature table.

    Parameters:
    -----------
        feat_table: pd.DataFrame of features x samples
        taxonomy: pd.DataFrame of features x [Taxon, ...]
        num_string: numerator string to search for in taxonomy
        denom_string: denominator string to search for in taxonomy

    Returns:
    --------
        num_df: pd.DataFrame of numerator features x samples
        denom_df: pd.DataFrame of denominator features x samples
    """
    feat_table_copy = feat_table.loc[:, ((feat_table != 0).any(axis=0))]
    taxonomy = taxonomy.copy()
    taxonomy = taxonomy[['Taxon']]
    taxonomy_joined_df = taxonomy.join(feat_table_copy, how='inner',
        rsuffix='_q')
    num_indices = taxonomy_joined_df['Taxon'].str.contains(num_string)
    denom_indices = taxonomy_joined_df['Taxon'].str.contains(denom_string)
    tax_num_df = taxonomy_joined_df.loc[num_indices]
    tax_denom_df = taxonomy_joined_df.loc[denom_indices]
    tax_num_df.drop(columns='Taxon', inplace=True)
    tax_denom_df.drop(columns='Taxon', inplace=True)
    if 'Taxon_q' in taxonomy_joined_df:
        tax_num_df.rename(columns={'Taxon_q': 'Taxon'}, inplace=True)
        tax_denom_df.rename(columns={'Taxon_q': 'Taxon'}, inplace=True)
    if tax_num_df.shape[0] == 0:
        if tax_denom_df.shape[0] == 0:
            raise ValueError(
                'No feature(s) found matching either numerator or denominator string!'
                )
        else:
            raise ValueError('No feature(s) found matching numerator string!')
    if tax_denom_df.shape[0] == 0:
        raise ValueError('No feature(s) found matching denominator string!')
    tax_num_df = tax_num_df.loc[:, ((tax_num_df != 0).any(axis=0))]
    tax_denom_df = tax_denom_df.loc[:, ((tax_denom_df != 0).any(axis=0))]
    samp_to_keep = set(tax_num_df.columns).intersection(set(tax_denom_df.
        columns))
    if not samp_to_keep:
        raise ValueError(
            'No samples contain both numerator and denominator features!')
    tax_num_df = tax_num_df[samp_to_keep]
    tax_denom_df = tax_denom_df[samp_to_keep]
    return tax_num_df, tax_denom_df


def is_numeric(*p):
    """ Returns false unless all elements in p are of numerical type
    """
    from symbols.type_ import Type
    try:
        for i in p:
            if not i.type_.is_basic or not Type.is_numeric(i.type_):
                return False
        return True
    except:
        pass
    return False


def setRoundIntegerFunction(func):
    """ Globally set function for rounding floats to integers.

    The function signature must be:

        def func(value: float) -> int
    """
    global _ROUND_INTEGER_FUNC
    _ROUND_INTEGER_FUNC = func


@staticmethod
def get_link_page_text(link_page):
    """
        Construct the dialog box to display a list of links to the user.
        """
    text = ''
    for i, link in enumerate(link_page):
        capped_link_text = link['text'] if len(link['text']) <= 20 else link[
            'text'][:19] + '…'
        text += '[{}] [{}]({})\n'.format(i, capped_link_text, link['href'])
    return text


def wsgi_path_item(environ, name):
    """Extract the value of a named field in a URL.

    Return None if the name is not present or there are no path items.
    """
    try:
        return environ['wsgiorg.routing_args'][1][name]
    except (KeyError, IndexError):
        return None


def reverse_key(key):
    """
    Tenant aware function to reverse a cache key.

    Required for django-redis REVERSE_KEY_FUNCTION setting.
    """
    return key.split(':', 3)[3]


def supplements(parms, countrate=None):
    u"""Supplementary parameters:
        [12]  n₁ = n*F₁     Particle number of species 1
        [13]  n₂ = n*F₂     Particle number of species 2
        [14]  n₃ = n*F₃     Particle number of species 3 (F₃ = 1-F₁-F₂)
    """
    n = parms[0]
    F1 = parms[4]
    F2 = parms[5]
    Info = list()
    Info.append([u'n₁', n * F1])
    Info.append([u'n₂', n * F2])
    Info.append([u'n₃', n * (1 - F1 - F2)])
    if countrate is not None:
        cpp = countrate / n
        Info.append(['cpp [kHz]', cpp])
    return Info


def sourceRemoved(catalog):
    """message: you've been removed as a listener from the given catalog.
        """


@staticmethod
def parse_args(parser=None, args=None):
    """Parses the passed-in args"""
    if not args:
        args = ['-h']
    return parser.parse_known_args(args)


def _extract_prop_set(line):
    """
    Extract the (key, value)-tuple from a string like:
    >>> 'set foo = "bar"'
    :param line:
    :return: tuple (key, value)
    """
    pattern = ' = "'
    line = line[4:]
    pos = line.find(pattern)
    return line[:pos], line[pos + 4:-1]


@classmethod
def _connection_info(cls):
    """
        Return a dictionary containing the connection info based on
        `config_host` and `config_port` or `config_uri`. If `config_uri` is
        specified, it takes precedence.

        """
    if cls.config_uri:
        return {'host': cls.config_uri}
    return {'host': cls.config_host, 'port': cls.config_port}


@staticmethod
def _to_field(config_key):
    """Convert a config key to a field name"""
    return config_key


def _get_field_ix(line, field):
    """Get position of field ('GT' or 'DS') in FORMAT"""
    fmt = line[8].split(':')
    if field not in fmt:
        raise ValueError('FORMAT field does not contain {}'.format(field))
    return fmt.index(field)


def copy():
    """Copy selected keyframes to the copy/paste buffer

    """
    pass


def configure(roomJID, options):
    """
        Configure a room.

        @param roomJID: The room to configure.
        @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}

        @param options: A mapping of field names to values, or C{None} to
            cancel.
        @type options: C{dict}
        """


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

        :param ShowcaseResolveCommentType val:
        :rtype: EventType
        """
    return cls('showcase_resolve_comment', val)


def fix_time_range(s):
    """change a time range to the middle of year in the range.
    e.g. fix_time_range('1980-90') = 1985
    """
    if '-' not in s:
        return int(s)
    else:
        t1, t2 = s.split('-')
        if len(t1) == 4 and len(t2) == 4:
            span = int(t2) - int(t1)
            return int(int(t1) + span / 2)
        else:
            d = len(t2)
            hund1 = int(t1[:4 - d])
            tens1 = int(t1[-d:])
            tens2 = int(t2)
            y1 = int(t1)
            if tens1 > tens2:
                hund2 = hund1 + 1
                y2 = hund2 * 10 ** d + tens2
            else:
                y2 = hund1 * 10 ** d + tens2
            return int(y1 + (y2 - y1) / 2)


def seconds2human(time_on_seconds=0, do_year=True, unit_words={'y':
    ' Years ', 'd': ' Days ', 'h': ' Hours ', 'm': ' Minutes ', 's':
    ' Seconds '}):
    """Calculate time, with precision from seconds to days."""
    minutes, seconds = divmod(int(abs(time_on_seconds)), 60)
    hours, minutes = divmod(minutes, 60)
    days, hours = divmod(hours, 24)
    human_time_string = ''
    yea = '{0}' + str(unit_words.get('y', ' Years '))
    dayz = '%02d' + str(unit_words.get('d', ' Days '))
    hou = '%02d' + str(unit_words.get('h', ' Hours '))
    minu = '%02d' + str(unit_words.get('m', ' Minutes '))
    seco = '%02d' + str(unit_words.get('s', ' Seconds '))
    years = int(int(days) / 365)
    if days and years and do_year and years > 1:
        human_time_string += yea.format(years)
        days = days - 365 * years
    if days:
        human_time_string += dayz % days
    if hours:
        human_time_string += hou % hours
    if minutes:
        human_time_string += minu % minutes
    human_time_string += seco % seconds
    return human_time_string.strip()


def filter_thermal_celsius(thermal, min_celsius=-9320, max_celsius=7070):
    """
    Provide an index of observations within a brightness temperature range.

    Thermal min/max must be provided as a scaled value in degrees celsius.

    The range in unscaled degrees celsius is (-93.2C,70.7C)
    The range in scaled degrees celsius is (-9320, 7070)

    Arguments:
        thermal: 1-d array of thermal values
        min_celsius: minimum temperature in degrees celsius
        max_celsius: maximum temperature in degrees celsius

    Returns:
        1-d bool ndarray
    """
    return (thermal > min_celsius) & (thermal < max_celsius)


def assert_consistent_regions(from_spec, from_command_line, builder_exception):
    """
    Verifies the regions passed with --region CLI argument and the ones
    specified in regionalOptions are the same (if both CLI and spec were used)
    """
    if from_spec is None or from_command_line is None:
        return
    if set(from_spec) != set(from_command_line):
        raise builder_exception(
            "--region and the 'regionalOptions' key in the JSON file do not agree"
            )


def parenthesise(_value):
    """Adds a parenthesis around a values."""
    return '(' + _value + ')'


def get_all_clouds(session, return_type=None, **kwargs):
    """
    Retrieves details for all clouds on the Cloud.

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

    :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.json'
    return session.get_api(path=path, return_type=return_type, **kwargs)


def unescape(s):
    """Revert escaped characters back to their special version.

    For example, \\\\n => \\n and \\\\t => \\t

    :param s: string to unescape
    """
    return s.replace('\\n', '\n').replace('\\t', '\t').replace('\\r', '\r')


def getCookie(key):
    """
        Get a cookie that was sent from the network.

        @type key: L{bytes}
        @param key: The name of the cookie to get.

        @rtype: L{bytes} or L{None}
        @returns: The value of the specified cookie, or L{None} if that cookie
            was not present in the request.
        """


def action_sanitize():
    """Make action suitable for use as a Pose Library

    """
    pass


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


def hasInput():
    """
        Returns ``True`` if the widget has input.

        Input is used by the widget to calculate an 'input value', which is
        a value that can be legally assigned to a field.

        Note that the widget may return ``True``, indicating it has input, but
        still be unable to return a value from `getInputValue`. Use
        `hasValidInput` to determine whether or not `getInputValue` will return
        a valid value.

        A widget that does not have input should generally not be used
        to update its bound field.  Values set using
        `setRenderedValue()` do not count as user input.

        A widget that has been rendered into a form which has been
        submitted must report that it has input.  If the form
        containing the widget has not been submitted, the widget
        shall report that it has no input.
        """


def get_tentacle_path(exchange_name=None, tentacle_type=None, tentacle_name
    =None) ->list:
    """
    Returns the path related to the tentacle name, type and exchange name
    :param tentacle_type: the tentacle type to add in the path, ignored if None
    :param tentacle_name: the tentacle name to add in the path, ignored if None
    :param exchange_name: the exchange name to add in the path (as the first element), ignored if None
    :return: a list of string that represents the path of the given params
    """
    node_path = []
    if exchange_name is not None:
        node_path.append(exchange_name)
    if tentacle_type is not None:
        node_path.append(tentacle_type)
    if tentacle_name is not None:
        node_path.append(tentacle_name)
    return node_path


def handle_arguments(args):
    """Called when command line arguments have been parsed.

        :type: :class:`argparse.Namespace`
        """


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

        :param MemberAccessLevelResult val:
        :rtype: FileMemberActionError
        """
    return cls('no_explicit_access', val)


def eval_kwarg(x):
    """If x is a string, eval it. Otherwise just return it.

    Args:
        x (str, obj): String to be evaluated as an object or an object.

    Returns:
        obj: Result of evaluated string or the input object.

    """
    if isinstance(x, str):
        try:
            return eval(x)
        except NameError:
            return x
    return x


@classmethod
def get_name(cls):
    """Return the name associated with this subtype.

        Returns
        -------
        name : str
            The name associated with this subtype.

        """
    return cls.__name__


@classmethod
def supportedComplexModes(cls):
    """Returns the list of supported complex visualization modes.

        See :class:`ComplexMode` and :meth:`setComplexMode`.

        :rtype: List[ComplexMode]
        """
    if cls._SUPPORTED_COMPLEX_MODES is None:
        return cls.ComplexMode.members()
    else:
        return cls._SUPPORTED_COMPLEX_MODES


def show_message(parent=None, title='Title', message='Message', msgtype=
    'Information'):
    """Opens a simple message box

      msgtype = 'Information', 'Warning', or 'Critical'
    """
    if msgtype == 'Information':
        print(message)
    else:
        print(msgtype + ': ' + message)


@staticmethod
def heartbeat():
    """Update member status to indicate it is still alive.

        Method to run once in a while to be sure that the member is not dead
        and is still an active member of a group.

        :return: The number of seconds to wait before sending a new heartbeat.
        """
    pass


def load_yaml(s):
    """Load a Yaml document.

    This is a helper function which tries to use the fast ``CLoader``
    implementation and falls back to the native Python version on failure.
    """
    import yaml
    try:
        from yaml import CLoader as Loader
    except ImportError:
        from yaml import Loader
    return yaml.load(s, Loader=Loader)


def page_name_original_metadata(index):
    """Get the key name for the page name metadata data for the indexed tiff page

    These are TIFF IFD #'s 285+

    index - zero-based index of the page
    """
    return 'PageName #%d' % index


def _cleanup_spark(spark, current_spark_config, row_group_size_mb=None):
    """
    Cleans up config changes performed in _init_spark
    """
    hadoop_config = spark.sparkContext._jsc.hadoopConfiguration()
    for key, val in current_spark_config.items():
        if val is not None:
            hadoop_config.set(key, val)
        else:
            hadoop_config.unset(key)


@staticmethod
def _exclude_id(jar):
    """Create a string identifier for the Exclude key.

        :param Exclude jar: key for an excluded jar
        :returns: String representing the key as a maven coordinate
        """
    return '{0}:{1}'.format(jar.org, jar.name) if jar.name else jar.org


def buildFunction(functionType, name, dll):
    """Abstract away the ctypes function-creation operation"""
    return functionType((name, dll))


def set_linebreaks(desc: str) ->str:
    """
    Sets newlines after max 45 characters (or the latest space to avoid non-sense separation)
    :param desc: The parsed long description for the sepcific template
    :return: The formatted string with inserted newlines
    """
    linebreak_limit = 50
    last_space = -1
    cnt = 0
    idx = 0
    while idx < len(desc):
        if cnt == linebreak_limit:
            desc = desc[:last_space] + '\n' + desc[last_space + 1:]
            cnt = 0
        elif desc[idx] == ' ':
            last_space = idx
        cnt += 1
        idx += 1
    return desc


def parse_email(address):
    """
    Returns "Marco Polo", "marco@polo.com" from "Marco Polo <marco@polo.com"
    Returns "", "marco@polo.com" from "marco@polo.com"
    """
    if ' ' in address.strip():
        assert '<' in address and '>' in address, 'Invalid address structure: %s' % (
            address,)
        parts = address.split(' ')
        name = ' '.join(parts[:-1])
        address = parts[-1][1:-1]
        return name, address
    else:
        return '', address


def create_from_cap(writecap, readcap=None, deep_immutable=False, name=
    u'<unknown name>'):
    """I create an IFilesystemNode from the given writecap/readcap. I can
        only provide nodes for existing file/directory objects: use my other
        methods to create new objects. I return synchronously."""


def get_samplerate_mstimer(timerdata):
    """detemine sample rate based on ms timer

    Function to determine sample rate of data from ms-based timer list or array.

    Parameters
    ----------
    timerdata : 1d numpy array or list
        sequence containing values of a timer, in ms

    Returns
    -------
    out : float
        the sample rate as determined from the timer sequence provided

    Examples
    --------
    first we load a provided example dataset

    >>> data, timer = load_exampledata(example = 1)

    since it's a timer that counts miliseconds, we use this function.
    Let's also round to three decimals

    >>> round(get_samplerate_mstimer(timer), 3)
    116.996

    of course if another time unit is used, converting it to ms-based
    should be trivial.
    """
    sample_rate = len(timerdata) / (timerdata[-1] - timerdata[0]) * 1000
    return sample_rate


def i_am_the_lord(legion_name):
    """Returns flag indicating whether you are the lord
    of the given legion.

    * http://uwsgi.readthedocs.io/en/latest/Legion.html#legion-api

    :param str|unicode legion_name:

    :rtype: bool
    """
    return False


def run_command(c):
    """
    Run an arbitrary python command.
    """
    exec(c, globals())


def _file_mtime_recent(planner, resource):
    """Returns true if a file has been more recently modified."""
    history = planner.history[planner.task.hash]
    previous = history['inputs'][resource.ref()]
    current = planner.platform.file_mtime(resource.path)
    if current > previous:
        return True
    return False


def no_log_warn(logical_line):
    """Disallow 'LOG.warn('

    Deprecated LOG.warn(), instead use LOG.warning
    https://bugs.launchpad.net/senlin/+bug/1508442

    M331
    """
    msg = 'M331: LOG.warn is deprecated, please use LOG.warning!'
    if 'LOG.warn(' in logical_line:
        yield 0, msg


def ip2Long(ip):
    """Returns IP in Int format from Octet form"""
    octs = list(map(int, ip.split('.')))
    return octs[0] * 2 ** 24 + octs[1] * 2 ** 16 + octs[2] * 2 ** 8 + octs[3]


def entuple(x, n=2):
    """
    Make sure given value is a tuple. It is useful, for example, when you want to provide dimentions of an image either
    as a tuple, or as an int - in which case you can use `(w,h) = entuple(x)`.
    :param x: Either atomic value or a tuple. If the value is atomic, it is converted to a tuple of length `n`. It the value
    is a tuple - it is inchanged
    :param n: Number of elements in a tuple
    :return: Tuple of a specified size
    """
    if type(x) is tuple:
        return x
    elif type(x) is list:
        return tuple(x)
    else:
        return tuple([x] * n)


def rhog(mw, p, tk):
    """
    Calculate gas density from molecular weight, pressure, and temperature.

    Parameters
    ----------
    mw : float
        Molecular weight of gas [g/mol]
    p : float
        Pressure of the gas [Pa]
    tk : float
        Temperature of the gas [K]

    Returns
    -------
    rho : float
        Density of gas [kg/m^3]

    Examples
    --------
    >>> rhog(28, 101325, 773)
    0.4414
    """
    mw = mw / 1000
    r = 8.3145
    rho = p * mw / (r * tk)
    return rho


def start(*args, **kwargs):
    """Starts the server. This is typically a blocking call."""


def neighbor_equality(w1, w2):
    """
    Test if the neighbor sets are equal between two weights objects

    Parameters
    ----------

    w1 : W
        instance of spatial weights class W

    w2 : W
        instance of spatial weights class W

    Returns
    -------
    Boolean

    Notes
    -----
    Only set membership is evaluated, no check of the weight values is carried out.

    Examples
    --------
    >>> from libpysal.weights.util import neighbor_equality
    >>> from libpysal.weights import lat2W, W
    >>> w1 = lat2W(3,3)
    >>> w2 = lat2W(3,3)
    >>> neighbor_equality(w1, w2)
    True
    >>> w3 = lat2W(5,5)
    >>> neighbor_equality(w1, w3)
    False
    >>> n4 = w1.neighbors.copy()
    >>> n4[0] = [1]
    >>> n4[1] = [4, 2]
    >>> w4 = W(n4)
    >>> neighbor_equality(w1, w4)
    False
    >>> n5 = w1.neighbors.copy()
    >>> n5[0]
    [3, 1]
    >>> n5[0] = [1, 3]
    >>> w5 = W(n5)
    >>> neighbor_equality(w1, w5)
    True

    """
    n1 = w1.neighbors
    n2 = w2.neighbors
    ids_1 = set(n1.keys())
    ids_2 = set(n2.keys())
    if ids_1 != ids_2:
        return False
    for i in ids_1:
        if set(w1.neighbors[i]) != set(w2.neighbors[i]):
            return False
    return True


@staticmethod
def _get_kwargs_from_urls(path):
    """If kwargs can be encoded in the paths, extract them here

        This should happen before instantiation of the class; incoming paths
        then should be amended to strip the options in methods.

        Examples may look like an sftp path "sftp://user@host:/my/path", where
        the user and host should become kwargs and later get stripped.
        """
    return {}


def conv_output_length(input_length, filter_size, padding, stride, dilation=1):
    """Determines output length of a convolution given input length.
    Arguments:
        input_length: integer.
        filter_size: integer.
        padding: one of "same", "valid", "full", "causal"
        stride: integer.
        dilation: dilation rate, integer.
    Returns:
        The output length (integer).
    """
    if input_length is None:
        return None
    assert padding in {'same', 'valid', 'full', 'causal'}
    dilated_filter_size = filter_size + (filter_size - 1) * (dilation - 1)
    if padding in ['same', 'causal']:
        output_length = input_length
    elif padding == 'valid':
        output_length = input_length - dilated_filter_size + 1
    elif padding == 'full':
        output_length = input_length + dilated_filter_size - 1
    return (output_length + stride - 1) // stride


@staticmethod
def system_user_exists(user):
    """Check if the user exists on the system"""
    import pwd
    try:
        pwd.getpwnam(user.name)
    except KeyError:
        return False
    else:
        return True


@classmethod
def remove_user(cls, options=None):
    """Removes an user from an org"""
    cls.command_sub = 'remove-user'
    return cls.execute(cls._construct_command(options))


def atfile_ivm(filename):
    """
    Return the filename of the IVM file
    which is assumed to be the second word
    in the atfile the user gave.
    """
    return filename.split()[1]


def ask_question(question, accept_confirmation=False):
    """Method to ask the user a yes/no question

    Args:
        question(str): A question to ask the user
        accept_confirmation(bool): Optional flag, if True will automatically accept question

    Returns:
        bool: True if yes, False if no
    """
    if accept_confirmation:
        return True
    valid_response = {'yes': True, 'y': True, 'no': False, 'n': False}
    while True:
        print('{} [y/n]: '.format(question), end='')
        choice = input().lower().strip()
        if choice in valid_response:
            return valid_response[choice]
        else:
            print("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")


def decode_string(v, encoding='utf-8'):
    """ Returns the given value as a Unicode string (if possible).
    """
    if isinstance(encoding, str):
        encoding = ((encoding,),) + (('windows-1252',), ('utf-8', 'ignore'))
    if isinstance(v, bytes):
        for e in encoding:
            try:
                return v.decode(*e)
            except:
                pass
        return v
    return str(v)


def modifier_remove(modifier: str=''):
    """Remove a modifier from the active object

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    """
    pass


@staticmethod
def add_u_before_strings(text):
    """Add unicode 'u' in front of strings for Python 2"""
    separator = "'"
    if text.find('"') > text.find("'"):
        separator = '"'
    output = []
    lst = text.split(separator)
    for i, item in enumerate(lst):
        if not i % 2:
            output.append(lst[i])
        else:
            output.append('u' + separator + lst[i] + separator)
    return ''.join(output)


def hinton(df, fig=1, shrink=2, method='square', bgcolor='grey', cmap=
    'gray_r', binarise_color=True):
    """Hinton plot (simplified version of correlation plot)

    :param df: the input data as a dataframe or list of items (list, array). See
        :class:`~sequana.viz.corrplot.Corrplot` for details.
    :param fig: in which figure to plot the data
    :param shrink: factor to increase/decrease sizes of the symbols
    :param method: set the type of symbols for each coordinates. (default to square). See
        :class:`~sequana.viz.corrplot.Corrplot` for more details.
    :param bgcolor: set the background and label colors as grey
    :param cmap: gray color map used by default
    :param binarise_color: use only two colors. One for positive values and one for
        negative values.

    .. plot::
        :include-source:
        :width: 80%

        from sequana.viz import hinton
        df = np.random.rand(20, 20) - 0.5
        hinton(df)

    .. note:: Idea taken from a matplotlib recipes
        http://matplotlib.org/examples/specialty_plots/hinton_demo.html
        but solely using the implementation within :class:`~sequana.viz.corrplot.Corrplot`

    .. note:: Values must be between -1 and 1. No sanity check performed.
    """
    from sequana.viz import corrplot
    c = corrplot.Corrplot(df)
    c.plot(colorbar=False, cmap=cmap, fig=fig, method=method, facecolor=
        bgcolor, shrink=shrink, label_color=bgcolor, binarise_color=
        binarise_color)


def is_number(s, na_re=False):
    """ Check if string is float """
    if na_re:
        is_na = na_re.match(s)
        if is_na:
            return False
    try:
        converted = float(s)
        return True
    except:
        return False


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


@staticmethod
def _shortener(x, renamer=None, max_char_len=20):
    """Shorten a feature ID to minimize the amount of messy text on plots

        Parameters
        ----------
        x : str
            A feature ID
        renamer : function, optional (default=None)
            A function to rename feature IDs to known gene symbols
        max_char_len : int, optional (default=20)
            Maximum length of the feature ids

        Returns
        -------
        shortened : str
            A potentially renamed, shortened string
        """
    if renamer is not None:
        renamed = renamer(x)
    else:
        renamed = x
    if isinstance(renamed, float):
        return renamed
    elif len(renamed) > max_char_len:
        return '{}...'.format(renamed[:max_char_len])
    else:
        return renamed


def delete_vm_instance(nova, vm_inst):
    """
    Deletes a VM instance
    :param nova: the nova client
    :param vm_inst: the snaps.domain.VmInst object
    """
    nova.servers.delete(vm_inst.id)


@staticmethod
def getFitting(fitting, requirement, file):
    """
        Get ponies that fit the terminal

        @param  fitting:add(str)→void  The set to fill
        @param  requirement:int        The maximum allowed value
        @param  file:istream           The file with all data
        """
    data = file.read()
    ptr = 0
    while data[ptr] != 47:
        ptr += 1
    ptr += 1
    size = 0
    while data[ptr] != 47:
        size = size * 10 - (data[ptr] & 15)
        ptr += 1
    ptr += 1
    jump = ptr - size
    stop = 0
    backjump = 0
    while ptr < jump:
        size = 0
        while data[ptr] != 47:
            size = size * 10 - (data[ptr] & 15)
            ptr += 1
        ptr += 1
        if -size > requirement:
            if backjump > 0:
                ptr = backjump
                while data[ptr] != 47:
                    stop = stop * 10 - (data[ptr] & 15)
                    ptr += 1
                stop = -stop
            break
        backjump = ptr
        while data[ptr] != 47:
            ptr += 1
        ptr += 1
    if ptr == jump:
        stop = len(data)
    else:
        ptr = jump
        stop += ptr
    passed = data[jump:stop].decode('utf8', 'replace').split('/')
    for pony in passed:
        fitting.add(pony)


def canonicalShape(shape):
    """Calculates a *canonical* shape, how the given ``shape`` should
    be presented. The shape is forced to be at least three dimensions,
    with any other trailing dimensions of length 1 ignored.
    """
    shape = list(shape)
    for i in reversed(range(len(shape))):
        if shape[i] == 1:
            shape = shape[:i]
        else:
            break
    if len(shape) < 3:
        shape = shape + [1] * (3 - len(shape))
    return shape


def update_query(tablename, objects, condition):
    """
    Function to process the query for update process
    """
    if isinstance(tablename, str):
        pass
    else:
        raise ValueError('Table name should be a String')
    if condition == None or isinstance(condition, str):
        pass
    else:
        raise ValueError('Condition can only be either None or String')
    if isinstance(objects, dict):
        pass
    else:
        raise ValueError('Object can only be Dictionary')
    cols = ''
    for i in objects.keys():
        if isinstance(objects[i], str):
            substr = str(i) + " = '" + str(objects[i]) + "',"
        else:
            substr = str(i) + ' = ' + str(objects[i]) + ','
        cols = cols + substr
    cols = cols[:len(cols) - 1]
    if condition == None:
        query = 'Update ' + tablename + ' set ' + cols
    else:
        query = 'Update ' + tablename + ' set ' + cols + ' where ' + condition
    return query


@classmethod
def run_hooks(cls, hook_type, *args, **kwargs):
    """Run all hooks of specified type.

        :param cls: class that registers hooks
        :param hook_type: hook type, e.g., '__pre_parse_args__'
        :param args: args to be passed to every hook function
        :param kwargs: kwargs to be passed to every hook function
        """
    hook_funcs = cls._hooks_map.get(hook_type) or []
    for hook_func in hook_funcs:
        hook_func(*args, **kwargs)


@staticmethod
def _decode(**fetches):
    """ Performs decoding on the output
            :param fetches: A dictionary of fetches from the model.
            :return: A dictionary of decoded results
        """
    del fetches
    return {}


def pack_varint(integer):
    """
    Packs a variable length integer.
    """
    while integer > 127:
        yield bytes([integer & 127 | 128])
        integer >>= 7
    yield bytes([integer])


def vertex_group_deselect():
    """Deselect all selected vertices assigned to the active vertex group

    """
    pass


@staticmethod
def split_category(entry):
    """Split the entry category from the entry itself.

        Return a tuple (category, task).
        """
    if ': ' in entry:
        return tuple(entry.split(': ', 1))
    elif entry.endswith(':'):
        return entry.partition(':')[0], ''
    else:
        return None, entry


def utf_8_encoder(unicode_csv_data):
    """Converts every unicode string in an array into a UTF8-encoded string"""
    for line in unicode_csv_data:
        yield line.encode('utf-8')


@staticmethod
def are_equivalent(track_1, track_2):
    """Returns true if the given tracks are equivalent (ie: same track name and artist)"""
    return track_1.track_name.casefold() == track_2.track_name.casefold(
        ) and track_1.artist.casefold() == track_2.artist.casefold()


def symbol(currency):
    """
    Format the currency name to a symbol one.

    :return: The currency name as a utf-8 circled symbol.
    """
    letter = currency[0]
    u = ord('Ⓐ') + ord(letter) - ord('A')
    return chr(u)


def zip_until_right(*iterables):
    """
    A zip function that validates that the right iterable is consumed.

    Args:
        *iterables: the iterables to pass to `zip`.

    Yields:
        each zipped element.

    Raises:
        ValueError: if the left iterable is consumed before the right.
    """
    lefts = iterables[:-1]
    right = iter(iterables[-1])
    iterables = lefts + (right,)
    for item in zip(*iterables):
        yield item
    try:
        next(right)
        raise ValueError('the right-most iterable was not consumed')
    except StopIteration:
        pass


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


def do_sqlite_begin(dbapi_connection):
    """Ensure SQLite transaction are started properly.

    For further details see "Foreign key support" sections on
    https://docs.sqlalchemy.org/en/rel_1_0/dialects/sqlite.html#pysqlite-serializable # noqa
    """
    dbapi_connection.execute('BEGIN')


def merge_shards(shard_data, existing):
    """
    Compares ``shard_data`` with ``existing`` and updates ``shard_data`` with
    any items of ``existing`` that take precedence over the corresponding item
    in ``shard_data``.

    :param shard_data: a dict representation of shard range that may be
        modified by this method.
    :param existing: a dict representation of shard range.
    :returns: True if ``shard data`` has any item(s) that are considered to
        take precedence over the corresponding item in ``existing``
    """
    if not existing:
        return True
    if existing['timestamp'] < shard_data['timestamp']:
        return True
    elif existing['timestamp'] > shard_data['timestamp']:
        return False
    new_content = False
    for k in ('lower', 'upper', 'deleted'):
        shard_data[k] = existing[k]
    if existing['meta_timestamp'] >= shard_data['meta_timestamp']:
        for k in ('object_count', 'bytes_used', 'meta_timestamp'):
            shard_data[k] = existing[k]
    else:
        new_content = True
    if existing['state_timestamp'] == shard_data['state_timestamp'
        ] and shard_data['state'] > existing['state']:
        new_content = True
    elif existing['state_timestamp'] >= shard_data['state_timestamp']:
        for k in ('state', 'state_timestamp', 'epoch'):
            shard_data[k] = existing[k]
    else:
        new_content = True
    return new_content


def unswap():
    """swap to default context"""


def recent_date(**kwargs):
    """Select a recent date range for a location selector.

    :keyword resolution: One keyword time resolution specifier, e.g. ``hours``
        or ``days``.
    :type resolution: int

    >>> recent_date(months=6)
    {'recent': {'months': 6}}
    >>> recent_date(weeks=3)
    {'recent': {'weeks': 3}}
    """
    if not len(kwargs) == 1:
        raise ValueError('Must specify a single date resolution')
    resolution = list(kwargs.keys())[0]
    value = list(kwargs.values())[0]
    if resolution not in 'minuteshoursdaysweeksmonthsyears':
        raise ValueError('Invalid date resolution: %s' % resolution)
    payload = {'recent': {resolution: value}}
    return payload


def last_two_indices_swap(array_ind_two_body_term):
    """
    Swap 2 last indices of an array

    Args:
        array_ind_two_body_term (list): TBD

    Returns:
        list: TBD
    """
    swapped_indices = [0, 0, 0, 0]
    swapped_indices[0] = array_ind_two_body_term[0]
    swapped_indices[1] = array_ind_two_body_term[1]
    swapped_indices[2] = array_ind_two_body_term[3]
    swapped_indices[3] = array_ind_two_body_term[2]
    return swapped_indices


def file_mode_allows_reading(file_mode):
    """Return True if the given "file_mode" allows reading"""
    return file_mode in {'r', 'rb', 'r+', 'rb+', 'w+', 'wb+', 'a+', 'ab+'}


def _copy_array_if_base_present(a):
    """Copy the array if its base points to a parent array."""
    if a.base is not None:
        return a.copy()
    return a


@classmethod
def convertValue(class_, val):
    """Converts a JSON p_val into a Python value"""
    if isinstance(val, list):
        class_.convertList(val)
        res = val
    elif isinstance(val, dict):
        res = class_.convertDict(val)
    else:
        res = val
    return res


@staticmethod
def _get_pos_tag(tag):
    """
            Drops syntatic information to keep only the POS tag.

            :param tag str: Floresta tag that contains syntatic
                information followed by the PoS tag
            :return: PoS tag
        """
    return tag.split('+')[-1]


def _get_industry_url(**kwargs):
    """Get url for QCEW data by industry.

    Parameters
    ----------
    year : string
        'YYYY'
    qtr : string
        Use `a` for annual averages.
    industry : string
        For all industry codes and titles see:
        http://www.bls.gov/cew/doc/titles/industry/industry_titles.htm

    Returns
    -------
    string
        URL that will be used for main function.

    """
    for arg in ['year', 'qtr', 'industry']:
        if arg not in kwargs:
            raise ValueError('Must specify {}'.format(arg))
    url = 'http://data.bls.gov/cew/data/api/[YEAR]/[QTR]/industry/[IND].csv'
    url = url.replace('[YEAR]', kwargs.get('year'))
    url = url.replace('[QTR]', kwargs.get('qtr').lower())
    url = url.replace('[IND]', kwargs.get('industry'))
    return url


def ip_int_to_packed(n):
    """Convert an integer to a packed IP address byte string."""
    return n.to_bytes(16, 'big')


def find_person(player, name):
    """
    Find a person by name in the current tile

    :param text_game_maker.player.player.Player player: player object
    :param str name: name of person to search for
    :return: found person. If no matching person is found, None is returned.
    :rtype: text_game_maker.game_objects.person.Person
    """
    for loc in player.current.people:
        itemlist = player.current.people[loc]
        for item in itemlist:
            if item.name.lower().startswith(name.lower()) or name.lower(
                ) in item.name.lower():
                return item
    return None


def route(request, c):
    """Resolve ``request`` to view-callable. For a successful match,
        populate relevant attributes, like `matchdict` and `view`, in
        ``request`` plugin.  A view-callable can be a plain python callable
        that accepts request and context arguments or a plugin implementing
        :class:`IHTTPView` interface.

        ``request``,
            Plugin instance implementing :class:`IHTTPRequest` interface.

        ``c``
            Context dictionary for response, and templates.
        """


def _diff_fieldnames(fieldnames, fieldnames_key):
    """
    Returns the difference in the members of fieldnames and fieldnames_key.

    Checking membership is one-sided; There may be members of fieldnames_key
    that aren't members of fieldnames. This would be true if there are multiple
    delimited text files with different fieldnames that need to be merged. In
    that case, fieldnames_key would be the set of all fieldnames needed in the
    merged file, and fieldnames would only be made up of the fieldnames in a
    single delimited text file.
    """
    fieldnames = set(fieldnames)
    return fieldnames - fieldnames_key


def remove_adjacent_letters(name):
    """Removes digits that repeats.

    Removes duplicate digits that are adjacent to each other with a few
    exceptions.

    Duplicate digit that are adjacent are removed. If duplicate digits are
    separated by a 'w' or 'h' then remove one of the digits. If duplicate
    digits are separated by a 'w' or 'h' then remove one of the digits. If
    duplicate digits are separated by a 'w' or 'h' then remove one of the
    digits. If duplicate digits are separated by a vowel then leave the
    duplicate numbers.

    >>> remove_adjacent_letters(['4', '2', '2'])
    ['4', '2']

    >>> remove_adjacent_letters(['4', '2', 'h', '2'])
    ['4', 'h', '2']

    >>> remove_adjacent_letters(['4', '2', 'a', '2'])
    ['4', '2', 'a', '2']

    :param name: A list of soudex numbers and vowels including 'w' and 'h'.
    :type name: list
    :return: Soundex numbers with duplicated numbers removed.
    :rtype: list

    """
    if name == []:
        return []
    last_letter = name[0]
    for index, element in enumerate(name[1:]):
        if element == last_letter:
            name.pop(index)
            last_letter = element
        elif element in ('h', 'w'):
            if name[index] == name[index + 2]:
                name.pop(index)
                last_letter = element
        else:
            last_letter = element
    return name


def delete():
    """Remove all selected keyframes

    """
    pass


@classmethod
def read(cls, filename: str) ->'HipsSurveyPropertiesList':
    """Read HiPS list from file (`HipsSurveyPropertiesList`).

        Parameters
        ----------
        filename : str
            HiPS list filename
        """
    with open(filename, encoding='utf-8', errors='ignore') as fh:
        text = fh.read()
    return cls.parse(text)


@staticmethod
def _get_accumulators(outputs: dict):
    """
        builds and returns a dictionary containing a key for each step output.
        The outputs of each learning step is stored on this dictionary.
        :param outputs: A dictionary containing the learning step outputs.
        """
    accumulators = dict()
    for output_name in outputs.keys():
        if output_name is not 'update_op':
            accumulators[output_name] = list()
    return accumulators


def endcap():
    """
    Forcibly ends Bash capture by re-enabling the default line prefix.
    """
    global BURLAP_COMMAND_PREFIX
    BURLAP_COMMAND_PREFIX = 1


def get(isamAppliance, file_path='/', recursive=True, check_mode=False,
    force=False):
    """
    Retrieving the contents of a directory from the file downloads area
    """
    return isamAppliance.invoke_get(
        'Retrieving the contents of a directory from the file downloads area',
        '/isam/downloads/{0}/?recursive={1}'.format(file_path, recursive))


def clean(text):
    """
    Return an updated and cleaned Text object from a `text` Text object
    normalizing some pucntuations around some name and acronyms.
    """
    if not text:
        return text
    text = text.replace('A. M.', 'A.M.')
    return text


def to_xml():
    """Return xml node:
          <node name=".." path=".." title=".."
                icon_url=".." is_container="..true/..false"
                size=".." length=".." />"""


def calculate():
    """Caclculate checksum
        """


def get_environ(environ):
    """
    Returns our whitelisted environment variables.
    """
    for key in ('REMOTE_ADDR', 'SERVER_NAME', 'SERVER_PORT'):
        if key in environ:
            yield key, environ[key]


def mean_multiplicative_bias(da_cmp, da_ref, over_dims):
    """
        Returns the multiplicative bias between comparison and reference datasets
        Author: Dougie Squire
        Date: 28/04/2018

        Parameters
        ----------
        da_cmp : xarray DataArray
            Array containing data to be compared to reference dataset (usually forecasts)
        da_ref : xarray DataArray
            Array containing reference data (usually observations)
        over_dims : str or sequence of str, optional
            Dimensions over which to compute the mean multiplicative bias

        Returns
        -------
        mean_multiplicative_bias : xarray DataArray
            Array containing the mean multiplicative biases

        Examples
        --------
        >>> da_cmp = xr.DataArray(np.random.normal(size=(3,3)),
        ...                       coords=[('x', np.arange(3)), ('y', np.arange(3))])
        >>> da_ref = xr.DataArray(np.random.normal(size=(3,3)),
        ...                       coords=[('x', np.arange(3)), ('y', np.arange(3))])
        >>> doppyo.skill.mean_multiplicative_bias(da_cmp, da_ref, over_dims='x')
        <xarray.DataArray 'mean_multiplicative_bias' (y: 3)>
        array([ 2.108882,  4.356835, -0.83234 ])
        Coordinates:
          * y        (y) int64 0 1 2

        Notes
        -----
        See http://www.cawcr.gov.au/projects/verification/
    """
    if isinstance(over_dims, str):
        over_dims = [over_dims]
    if over_dims == None:
        over_dims = []
    return (da_cmp / da_ref).mean(dim=over_dims, skipna=True).rename(
        'mean_multiplicative_bias')


def reqall(container, first, *options):
    """ If the first option is present require all the others. """
    if first is not None and container.get(first) is None:
        return
    for option in options:
        if container.get(option) is not None:
            continue
        if first is None:
            raise ValueError('options %s is required' % (option,))
        raise ValueError('option %s requires option %s' % (first, option))


def clean_text(text):
    """ cleaned-down version of text as Youtube is very permissive with descriptions """
    return text.strip().replace('\n', ' ').replace('\r', ' ')


def access(dct, keys):
    """
    Access a value from an arbitrarily-nested dictionary, given a set of keys.

    If any key doesn't exist, returns None.

    >>> access({'a': {'aa': {'aaa': {'b': 1, 'c': 2}}}}, keys=['a', 'aa', 'aaa', 'b'])
    1
    """
    o = dct
    for k in keys:
        o = o.get(k)
        if o is None:
            return None
    return o


def SVGParseFloat(s, i=0):
    """
    Parse first float value from string

    Returns value as string
    """
    start = i
    n = len(s)
    token = ''
    while i < n and (s[i].isspace() or s[i] == ','):
        i += 1
    if i == n:
        return None, i
    if s[i] == '-':
        token += '-'
        i += 1
    elif s[i] == '+':
        i += 1
    if s[i].isdigit():
        while i < n and s[i].isdigit():
            token += s[i]
            i += 1
    if i < n and s[i] == '.':
        token += '.'
        i += 1
        if s[i].isdigit():
            while i < n and s[i].isdigit():
                token += s[i]
                i += 1
        elif s[i].isspace() or s[i] == ',':
            pass
        else:
            raise Exception('Invalid float value near ' + s[start:start + 10])
    if i < n and (s[i] == 'e' or s[i] == 'E'):
        token += s[i]
        i += 1
        if s[i] == '+' or s[i] == '-':
            token += s[i]
            i += 1
        if s[i].isdigit():
            while i < n and s[i].isdigit():
                token += s[i]
                i += 1
        else:
            raise Exception('Invalid float value near ' + s[start:start + 10])
    return token, i


def pre_setUpWidgets(ignore_request=False):
    """ Called before the forms setUpWidgets is called
        """


def random_forest_feature_importance(forest, features, precision=4):
    """
    Given a trained `sklearn.ensemble.RandomForestClassifier`, plot the
    different features based on their importance according to the classifier,
    from the most important to the least.

    Parameters:
    -----------
    forest : sklearn.ensemble.RandomForestClassifier
        A trained `RandomForestClassifier`
    features : list
        A list of the names of the features the classifier was trained on,
        ordered by the same order the appeared
        in the training data
    precision : int, default = 4
        Precision of feature importance
    """
    return sorted(zip(map(lambda x: round(x, precision), forest.
        feature_importances_), features), reverse=True)


def theta_acetate_Cl_M83(T, P):
    """a-a': acetate chloride [M83]."""
    theta = -0.017
    valid = T == 298.15
    return theta, valid


def getmeths(method_type):
    """
    returns MagIC  method codes available for a given type
    """
    meths = []
    if method_type == 'GM':
        meths.append('GM-PMAG-APWP')
        meths.append('GM-ARAR')
        meths.append('GM-ARAR-AP')
        meths.append('GM-ARAR-II')
        meths.append('GM-ARAR-NI')
        meths.append('GM-ARAR-TF')
        meths.append('GM-CC-ARCH')
        meths.append('GM-CC-ARCHMAG')
        meths.append('GM-C14')
        meths.append('GM-FOSSIL')
        meths.append('GM-FT')
        meths.append('GM-INT-L')
        meths.append('GM-INT-S')
        meths.append('GM-ISO')
        meths.append('GM-KAR')
        meths.append('GM-PMAG-ANOM')
        meths.append('GM-PMAG-POL')
        meths.append('GM-PBPB')
        meths.append('GM-RATH')
        meths.append('GM-RBSR')
        meths.append('GM-RBSR-I')
        meths.append('GM-RBSR-MA')
        meths.append('GM-SMND')
        meths.append('GM-SMND-I')
        meths.append('GM-SMND-MA')
        meths.append('GM-CC-STRAT')
        meths.append('GM-LUM-TH')
        meths.append('GM-UPA')
        meths.append('GM-UPB')
        meths.append('GM-UTH')
        meths.append('GM-UTHHE')
    else:
        pass
    return meths


def update_instance(InstanceId=None, LayerIds=None, InstanceType=None,
    AutoScalingType=None, Hostname=None, Os=None, AmiId=None, SshKeyName=
    None, Architecture=None, InstallUpdatesOnBoot=None, EbsOptimized=None,
    AgentVersion=None):
    """
    Updates a specified instance.
    See also: AWS API Documentation

    :example: response = client.update_instance(
        InstanceId='string',
        LayerIds=[
            'string',
        ],
        InstanceType='string',
        AutoScalingType='load'|'timer',
        Hostname='string',
        Os='string',
        AmiId='string',
        SshKeyName='string',
        Architecture='x86_64'|'i386',
        InstallUpdatesOnBoot=True|False,
        EbsOptimized=True|False,
        AgentVersion='string'
    )

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

    :type LayerIds: list
    :param LayerIds: The instance's layer IDs.
            (string) --

    :type InstanceType: string
    :param InstanceType: The instance type, such as t2.micro . For a list of supported instance types, open the stack in the console, choose Instances , and choose + Instance . The Size list contains the currently supported types. For more information, see Instance Families and Types . The parameter values that you use to specify the various types are in the API Name column of the Available Instance Types table.

    :type AutoScalingType: string
    :param AutoScalingType: For load-based or time-based instances, the type. Windows stacks can use only time-based instances.

    :type Hostname: string
    :param Hostname: The instance host name.

    :type Os: string
    :param Os: The instance's operating system, which must be set to one of the following. You cannot update an instance that is using a custom AMI.
            A supported Linux operating system: An Amazon Linux version, such as Amazon Linux 2016.09 , Amazon Linux 2016.03 , Amazon Linux 2015.09 , or Amazon Linux 2015.03 .
            A supported Ubuntu operating system, such as Ubuntu 16.04 LTS , Ubuntu 14.04 LTS , or Ubuntu 12.04 LTS .
            CentOS Linux 7
            Red Hat Enterprise Linux 7
            A supported Windows operating system, such as Microsoft Windows Server 2012 R2 Base , Microsoft Windows Server 2012 R2 with SQL Server Express , Microsoft Windows Server 2012 R2 with SQL Server Standard , or Microsoft Windows Server 2012 R2 with SQL Server Web .
            For more information on the supported operating systems, see AWS OpsWorks Stacks Operating Systems .
            The default option is the current Amazon Linux version. If you set this parameter to Custom , you must use the AmiId parameter to specify the custom AMI that you want to use. For more information on the supported operating systems, see Operating Systems . For more information on how to use custom AMIs with OpsWorks, see Using Custom AMIs .
            Note
            You can specify a different Linux operating system for the updated stack, but you cannot change from Linux to Windows or Windows to Linux.

    :type AmiId: string
    :param AmiId: The ID of the AMI that was used to create the instance. The value of this parameter must be the same AMI ID that the instance is already using. You cannot apply a new AMI to an instance by running UpdateInstance. UpdateInstance does not work on instances that are using custom AMIs.

    :type SshKeyName: string
    :param SshKeyName: The instance's Amazon EC2 key name.

    :type Architecture: string
    :param Architecture: The instance architecture. Instance types do not necessarily support both architectures. For a list of the architectures that are supported by the different instance types, see Instance Families and Types .

    :type InstallUpdatesOnBoot: boolean
    :param InstallUpdatesOnBoot: Whether to install operating system and package updates when the instance boots. The default value is true . To control when updates are installed, set this value to false . You must then update your instances manually by using CreateDeployment to run the update_dependencies stack command or by manually running yum (Amazon Linux) or apt-get (Ubuntu) on the instances.
            Note
            We strongly recommend using the default value of true , to ensure that your instances have the latest security updates.

    :type EbsOptimized: boolean
    :param EbsOptimized: This property cannot be updated.

    :type AgentVersion: string
    :param AgentVersion: The default AWS OpsWorks Stacks agent version. You have the following options:
            INHERIT - Use the stack's default agent version setting.
            version_number - Use the specified agent version. This value overrides the stack's default setting. To update the agent version, you must edit the instance configuration and specify a new version. AWS OpsWorks Stacks then automatically installs that version on the instance.
            The default setting is INHERIT . To specify an agent version, you must use the complete version number, not the abbreviated number shown on the console. For a list of available agent version numbers, call DescribeAgentVersions .
            AgentVersion cannot be set to Chef 12.2.

    """
    pass


def parameters_ui(layout, params):
    """ Create the ui for the rig parameters.

    """
    r = layout.row()
    r.label(text='Primary rotation axis:')
    r.prop(params, 'palm_rotation_axis', text='')