def _findString(text, s, i):
    """ Helper function of findString, which is called recursively
    until a match is found, or it is clear there is no match. """
    i2 = text.find(s, i)
    if i2 < 0:
        return -1
    i1 = text.rfind('\n', 0, i2)
    if i1 < 0:
        return i2
    line = text[i1:i2]
    if not line.count('"') and not line.count("'") and not line.count('#'):
        return i2
    prev = ''
    inString = ''
    isComment = False
    for c in line:
        if c == '#':
            if not inString:
                isComment = True
                break
        elif c in '"\'':
            if not inString:
                inString = c
            elif prev != '\\':
                if inString == c:
                    inString = ''
                else:
                    pass
        prev = c
    if inString or isComment:
        return -i2
    else:
        return i2


def within_history(rev, windowdict):
    """Return whether the windowdict has history at the revision."""
    if not windowdict:
        return False
    begin = windowdict._past[0][0] if windowdict._past else windowdict._future[
        -1][0]
    end = windowdict._future[0][0] if windowdict._future else windowdict._past[
        -1][0]
    return begin <= rev <= end


def is_git_repo(template_repo):
    """ Returns True if the template_repo looks like a git repository. """
    return template_repo.startswith('git@') or template_repo.startswith(
        'https://')


def paginate(client, paginator, **kwargs):
    """
    Returns pages for given AWS paginator client and type.
    Example: iam client and "list_policies" paginator
    """
    marker = None
    while True:
        pages = client.get_paginator(paginator).paginate(**kwargs,
            PaginationConfig={'MaxItems': 10, 'PageSize': 10,
            'StartingToken': marker})
        for page in pages:
            yield page
        if 'NextMarker' not in page:
            break
        marker = page['NextMarker']


def load_model(filename):
    """Load a model from file"""
    pass


def validate_ip_tags(cmd, namespace):
    """ Extracts multiple space-separated tags in TYPE=VALUE format """
    IpTag = cmd.get_models('IpTag')
    if namespace.ip_tags and IpTag:
        ip_tags = []
        for item in namespace.ip_tags:
            tag_type, tag_value = item.split('=', 1)
            ip_tags.append(IpTag(ip_tag_type=tag_type, tag=tag_value))
        namespace.ip_tags = ip_tags


def _is_type(t):
    """Factory for a type checking function of type ``t`` or tuple of types."""
    return lambda x: isinstance(x.value, t)


def convert_for_sql(value, check_set=set(), single=True):
    """Convert a value for inserting into MySQL.

    :param value: Value that should be checked for conversion.
    :type value: misc
    :param check_set: Set of values to check against.
    :type check_set: set
    :param single: Indicates whether single quotes should be used.
    :type single: bool
    :returns:
        Returns either "NULL" or the value encapsulated in quotes
        ("'value'" or '"value"')
    :rtype: str
    """
    if value in check_set:
        value = 'NULL'
    elif single == True:
        value = f"'{value}'"
    else:
        value = f'"{value}"'
    return value


def process_items(item_list: list) ->str:
    """
	Runs through all found toc items and returns them as a string.

	INPUTS:
	item_list: list of ToC items

	OUTPUTS:
	A string representing (possibly nested) html lists of the structure of the ToC
	"""
    unclosed_ol = 0
    out_string = ''
    for index in range(0, len(item_list) - 1):
        this_item = item_list[index]
        next_item = item_list[index + 1]
        if next_item.level == this_item.level:
            out_string += '
\n'
            out_string += this_item.toc_link()
            out_string += '
\n'
        if next_item.level > this_item.level:
            out_string += '
\n'
            out_string += this_item.toc_link()
            out_string += '
\n'
            unclosed_ol += 1
        if next_item.level < this_item.level:
            out_string += '
\n'
            out_string += this_item.toc_link()
            out_string += '
\n'
            torepeat = this_item.level - next_item.level
            if torepeat > 0 and unclosed_ol > 0:
                for _ in range(0, torepeat):
                    out_string += '
\n'
                    unclosed_ol -= 1
                    out_string += '
\n'
    return out_string


@classmethod
def get_serializable(cls):
    """Return only the ExplainParams properties that have meaningful data values for serialization.

        :return: A set of property names, e.g., 'GLOBAL_IMPORTANCE_VALUES', 'MODEL_TYPE', etc.
        :rtype: set{str}
        """
    return set(filter(lambda x: not x.startswith('__') and not callable(
        getattr(cls, x)), vars(cls).keys())) - set(['DATA_MAPPER',
        'DATA_MAPPER_INTERNAL'])


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


@staticmethod
def envelope(message_type, input_message, log, success, output, error_message):
    """
        Creates an output message of a step's execution.

        :param message_type: The message type
        :param input_message: The input message
        :param log: The log of the step, as a single string
        :param success: whether or not the step was successful
        :param output: The step data output
        :param error_message: An error message if an error was thrown
        :return: An output message
        """
    output_message = {'log': log, 'status': 'ok' if success else 'error',
        'meta': input_message['body'].get('meta', None)}
    if success:
        output_message['output'] = output
    else:
        output_message['error'] = error_message
    return {'body': output_message, 'version': 'v1', 'type': message_type}


def _read_chan_name(orig):
    """Read channel labels, which can be across xml files.

    Parameters
    ----------
    orig : dict
        contains the converted xml information

    Returns
    -------
    list of str
        list of channel names
    ndarray
        vector to indicate to which signal a channel belongs to

    Notes
    -----
    This assumes that the PIB Box is the second signal.
    """
    sensors = orig['sensorLayout'][1]
    eeg_chan = []
    for one_sensor in sensors:
        if one_sensor['type'] in ('0', '1'):
            if one_sensor['name'] is not None:
                eeg_chan.append(one_sensor['name'])
            else:
                eeg_chan.append(one_sensor['number'])
    pns_chan = []
    if 'pnsSet' in orig:
        pnsSet = orig['pnsSet'][1]
        for one_sensor in pnsSet:
            pns_chan.append(one_sensor['name'])
    return eeg_chan + pns_chan, len(eeg_chan)


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


def find_union_coords(cases):
    """Take a list of cases and find the union of coordinates
    with which to index all cases. Sort the coords if possible.
    """
    for x in zip(*cases):
        try:
            yield sorted(set(x))
        except TypeError:
            yield list(set(x))


def get_cont_in_scale_points(tone_abs_height, prev_tone, c_3):
    """checks whether tone continues within the scale (up or down)"""
    assert len(prev_tone[0]) >= 0, 'prev_tone should be array'
    if prev_tone[0] == []:
        return 1
    if len(prev_tone[0]) > 1:
        return 10
    previous_tone_abs = prev_tone[0][0]
    previous_tone_rel = previous_tone_abs % 12
    assert c_3['basic_scale'][previous_tone_rel] == 1
    index = 1
    while index <= 12:
        if c_3['basic_scale'][(previous_tone_rel + index) % 12] == 1:
            next_tone_in_scale = (previous_tone_rel + index) % 12
            break
        index += 1
    if tone_abs_height % 12 == next_tone_in_scale:
        return 10
    index = 1
    while index <= 12:
        if c_3['basic_scale'][(previous_tone_rel - index) % 12] == 1:
            prev_tone_in_scale = (previous_tone_rel - index) % 12
            break
        index += 1
    if tone_abs_height % 12 == prev_tone_in_scale:
        return 10
    return 0.1


def provider_parser(subparser):
    """Configure provider parser for Constellix"""
    subparser.add_argument('--auth-username', help=
        'specify the API key username for authentication')
    subparser.add_argument('--auth-token', help=
        'specify secret key for authenticate=')


def get_system_serial_port(system):
    """ Work out the most likely serial port given the type of system. YMMV. """
    if system == 'Windows':
        return 'COM3'
    elif system == 'Linux':
        return '/dev/ttyUSB0'
    else:
        raise ValueError('Invalid system - unable to determine serial_port')


def let(namespace, **args):
    """allows local variable assignment, and macro blocks"""
    namespace.update(args)
    return ''


def nothing(json):
    """
    Pass value without doing anything.
    """
    return json


def meshdeform_bind(modifier: str=''):
    """Bind mesh to cage in mesh deform modifier

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


def as_twos_comp(value: int) ->int:
    """Interpret number as 32-bit twos comp value."""
    if value & 2147483648 != 0:
        flipped_value = ~value & 4294967295
        return -(flipped_value + 1)
    else:
        return value


def dissolve():
    """Delete selected points without splitting strokes

    """
    pass


def invert_dict(dictionary, multi_value=False):
    """
    Returns a new dictionary keyed by the values in <dictionary> and
    containing the matching key.

    If <multi_value> is True, values are sets of keys that matched each
    value in the iterables contained in <dictionary>.

    I realize that this is a poor explanation but I'm in a hurry here . . .
    """
    flipped_dict = {}
    if multi_value:
        for k, v in dictionary.items():
            for item in v:
                if item in flipped_dict:
                    flipped_dict[item].add(k)
                else:
                    flipped_dict[item] = set([k])
    else:
        for k, v in dictionary.items():
            flipped_dict[v] = k
    return flipped_dict


@classmethod
def from_golix(cls, golix_obj):
    """ Convert the golix object to a lightweight representation.
        """
    return cls(ghid=golix_obj.ghid, author=golix_obj.author)


def parse_kipoi_colname(colname):
    """Parse kipoi column name into:
    (model, version, type)
    input: "KV:dir:examples/rbp:DIFF"
    output: ("dir", "examples/rbp", "DIFF")
    """
    _, source_type, model, diff_type = colname.split(':', 3)
    return source_type, model, diff_type


def _merge_dicts(*dict_args):
    """Merge the given dictionaries into single dict.

    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.

    From http://stackoverflow.com/a/26853961/1706640
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result


@conf
def cc_add_flags(conf):
    """
	Adds CFLAGS / CPPFLAGS from os.environ to conf.env
	"""
    conf.add_os_flags('CPPFLAGS', dup=False)
    conf.add_os_flags('CFLAGS', dup=False)


@classmethod
def _cleanup(cls, batch):
    """Deletes all previous batches"""
    cls.objects.filter(batch__lt=batch).delete()


def TransformText(text, method, openDelim='{', closeDelim='}'):
    """Transform the text containing the given delimiters and return the
       transformed value. The method will be called whenever text is found
       between the given delimiters but not if the text contains another
       opening delimiter. Whatever is returned by the method will replace the
       text between the delimiters and the delimiters as well."""
    lastPos = 0
    results = []
    while True:
        startPos = text.find(openDelim, lastPos)
        if startPos < 0:
            break
        endPos = text.find(closeDelim, startPos)
        if endPos < 0:
            break
        textToReplace = text[startPos:endPos + 1]
        textInDelimiters = textToReplace[1:-1]
        if openDelim in textInDelimiters:
            results.append(text[lastPos:startPos + 1])
            lastPos = startPos + 1
            continue
        results.append(text[lastPos:startPos])
        results.append(method(textToReplace, textInDelimiters))
        lastPos = endPos + 1
    results.append(text[lastPos:])
    return ''.join(results)


def vertical_percent(plot, percent=0.1):
    """
    Using the size of the y axis, return a fraction of that size.
    """
    plot_bottom, plot_top = plot.get_ylim()
    return percent * (plot_top - plot_bottom)


def rshift(val, n):
    """
    Arithmetic right shift, preserves sign bit.
    https://stackoverflow.com/a/5833119 .
    """
    return val % 4294967296 >> n


def optimizeAngle(angle):
    """
    Because any rotation can be expressed within 360 degrees
    of any given number, and since negative angles sometimes
    are one character longer than corresponding positive angle,
    we shorten the number to one in the range to [-90, 270[.
    """
    if angle < 0:
        angle %= -360
    else:
        angle %= 360
    if angle >= 270:
        angle -= 360
    elif angle < -90:
        angle += 360
    return angle


def gatk_contig_check():
    """ For Gatk contig style wrappers. Will create a bash sctring to
    determine if the contig is 'unmapped' and if so will set the contig
    param accordingly """
    return """# Check for the unmapped as the contig
# If not, write no_mapped_reads to outBam
if [ "$contig" == "unmapped" ]; then
	contigParam=""
else
	contigParam="-L $contig"
fi"""


def solidsFluxPembWake(rhop, emf, umf, us):
    """
    Calculates the solids entrainment flux for the surface of a bubbling bed
    with the bubble wake ejection model of Pemberton and Davidsion (Chem. Eng.
    Sci., 1986, 41, pp. 243-251). This model is suitable if multiple bubbles
    coalesce at the surface before bursting.

    Parameters
    ----------
    rhop : float
        Mass density of the particles
    emf : float
        Void fraction at minimum fluidization [-]
    umf : float
        Minimum fluidization velocity [m/s]
    us : float
        Superficial gas velocity [m/s]

    Returns
    -------
    F0 : float
        Solids entrainment flux at the top of the bed [kg/m^2/s]
    """
    F0 = 0.1 * rhop * (1 - emf) * (us - umf)
    return F0


def make_internal():
    """Make active text file internal

    """
    pass


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


@staticmethod
def error(message):
    """
        Prints a error message
        :param message: str
        :return:
        """
    print('[ERROR]: {}'.format(message))


@classmethod
def import_from_misfit(cls, misfit, uid, **kwargs):
    """ Derived classes should implement this """
    raise NotImplementedError


def _split_choices_in_list(choices_string):
    """
    Riceve una stringa e la splitta ogni ';'
    creando una lista di scelte
    """
    str_split = choices_string.split(';')
    return str_split


def surface_slot_remove():
    """Remove the selected surface slot

    """
    pass


def ansi_escape(text):
    """
    Replace characters with a special meaning.
    """
    return text.replace('\x1b', '?').replace('\x08', '?')


def calcInstrNoiseSq(photParams):
    """
    Combine all of the noise due to intrumentation into one value
    @param [in] photParams is an instantiation of the
    PhotometricParameters class that carries details about the
    photometric response of the telescope.
    @param [out] The noise due to all of these sources added in quadrature
    in ADU counts
    """
    instNoiseSq = (photParams.nexp * photParams.readnoise ** 2 + photParams
        .darkcurrent * photParams.exptime * photParams.nexp + photParams.
        nexp * photParams.othernoise ** 2)
    instNoiseSq = instNoiseSq / (photParams.gain * photParams.gain)
    return instNoiseSq


@classmethod
def encode(cls, value):
    """ Convert value to dictionary.
        """
    return {'value': value}


def ply_save_color_pcloud(path, pcloud, color):
    """
  Save point cloud into a .ply file with per-point color.

  Parameters
  ----------
  path : str
    Path to save the file.
  pcloud : np.ndarray, shape [n, 3]
    Point cloud to save.
  color : np.ndarray, shape [n, 3], dtype uint8
    Color for each point.
  """
    num_points = pcloud.shape[0]
    with open(path, 'wb') as f:
        f.write(b'ply\n')
        f.write(b'format ascii 1.0\n')
        f.write(b'element vertex %d\n' % num_points)
        f.write(b'property float32 x\n')
        f.write(b'property float32 y\n')
        f.write(b'property float32 z\n')
        f.write(b'property uchar red\n')
        f.write(b'property uchar green\n')
        f.write(b'property uchar blue\n')
        f.write(b'end_header\n')
        for i in range(num_points):
            v = pcloud[i]
            c = color[i]
            f.write(b'%f %f %f %d %d %d\n' % (v[0], v[1], v[2], c[0], c[1],
                c[2]))


def bandpass_filter(files, lowpass_freq=0.1, highpass_freq=0.01, tr=2):
    """Bandpass filter the input files

    Parameters
    ----------
    files: list of str
        List 4d nifti file paths.

    lowpass_freq: float
        Cutoff frequency for the low pass filter (in Hz).

    highpass_freq: float
        Cutoff frequency for the high pass filter (in Hz).

    tr: float
        The repetition time in seconds. The inverse of sampling rate (in Hz).
    """
    import os
    import nibabel as nb
    import numpy as np
    from nipype.utils.filemanip import filename_to_list, list_to_filename, split_filename
    fs = 1.0 / tr
    out_files = []
    for filename in filename_to_list(files):
        path, name, ext = split_filename(filename)
        out_file = os.path.join(os.getcwd(), name + '_bandpassed' + ext)
        img = nb.load(filename)
        timepoints = img.shape[-1]
        F = np.zeros(timepoints)
        lowidx = int(timepoints / 2) + 1
        if lowpass_freq > 0:
            lowidx = np.round(float(lowpass_freq) / fs * timepoints)
        highidx = 0
        if highpass_freq > 0:
            highidx = np.round(float(highpass_freq) / fs * timepoints)
        F[int(highidx):int(lowidx)] = 1
        F = (F + F[::-1] > 0).astype(int)
        data = img.get_data()
        if np.all(F == 1):
            filtered_data = data
        else:
            filtered_data = np.real(np.fft.ifftn(np.fft.fftn(data) * F))
        img_out = nb.Nifti1Image(filtered_data, img.affine, img.header)
        img_out.to_filename(out_file)
        out_files.append(out_file)
    return list_to_filename(out_files)


def export(ob, *names):
    """ Set attributes enumerated by names equal by values from registry """


def read_leap_seconds(tzfile='/usr/share/zoneinfo/right/UTC'):
    """
    Extract leap second information from tzdata.

    Based on example at http://stackoverflow.com/questions/19332902/            extract-historic-leap-seconds-from-tzdata

    See also 'man 5 tzfile'.
    """
    from struct import unpack, calcsize
    out = []
    with open(tzfile, 'rb') as f:
        fmt = '>4s c 15x 6l'
        (magic, format, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt,
            charcnt) = unpack(fmt, f.read(calcsize(fmt)))
        assert magic == 'TZif'.encode('US-ASCII'), 'Not a timezone file'
        fmt = '>%(timecnt)dl %(timecnt)dB %(ttinfo)s %(charcnt)ds' % dict(
            timecnt=timecnt, ttinfo='lBB' * typecnt, charcnt=charcnt)
        f.read(calcsize(fmt))
        fmt = '>2l'
        for i in range(leapcnt):
            tleap, nleap = unpack(fmt, f.read(calcsize(fmt)))
            out.append((tleap - nleap + 1, nleap))
    return out


def get_re_for_font_glyph_unicode(font_abreviation, glyph):
    """Function to get the regex for glyph unicode value"""
    font_awesome_regex = ['(?i)\\.{}-'.format(font_abreviation),
        ':before[^{}]*{\\s*content:\\s*[\'"]([^\'"]*)[\'"][^\\}]*\\}']
    return '|'.join([glyph]).join(font_awesome_regex)


def split_string_at_suffix(s, numbers_into_suffix=False):
    """
    Split a string into two parts: a prefix and a suffix. Splitting is done from the end,
    so the split is done around the position of the last digit in the string
    (that means the prefix may include any character, mixing digits and chars).
    The flag 'numbers_into_suffix' determines whether the suffix consists of digits or non-digits.
    """
    if not s:
        return s, ''
    pos = len(s)
    while pos and numbers_into_suffix == s[pos - 1].isdigit():
        pos -= 1
    return s[:pos], s[pos:]


def get_metrics(response):
    """
    Extract asked metrics from api response
    @list_metrics : list of dict
    """
    list_metrics = []
    for i in response['reports'][0]['columnHeader']['metricHeader'][
        'metricHeaderEntries']:
        list_metrics.append(i['name'])
    return list_metrics


def make_variogram(nug, nst, it1, cc1, azi1, hmaj1, hmin1, it2=1, cc2=0,
    azi2=0, hmaj2=0, hmin2=0):
    """Make a dictionary of variogram parameters for application with spatial
    estimation and simulation.

    :param nug: TODO
    :param nst: TODO
    :param it1: TODO
    :param cc1: TODO
    :param azi1: TODO
    :param hmaj1: TODO
    :param hmin1: TODO
    :param it2: TODO
    :param cc2: TODO
    :param azi2: TODO
    :param hmaj2: TODO
    :param hmin2: TODO
    :return: TODO
    """
    if cc2 == 0:
        nst = 1
    var = dict([('nug', nug), ('nst', nst), ('it1', it1), ('cc1', cc1), (
        'azi1', azi1), ('hmaj1', hmaj1), ('hmin1', hmin1), ('it2', it2), (
        'cc2', cc2), ('azi2', azi2), ('hmaj2', hmaj2), ('hmin2', hmin2)])
    if nug + cc1 + cc2 != 1:
        print(
            '\x1b[0;30;41m make_variogram Warning: sill does not sum to 1.0, do not use in simulation \x1b[0m'
            )
    if (cc1 < 0 or cc2 < 0 or nug < 0 or hmaj1 < 0 or hmaj2 < 0 or hmin1 <
        0 or hmin2 < 0):
        print(
            '\x1b[0;30;41m make_variogram Warning: contributions and ranges must be all positive \x1b[0m'
            )
    if hmaj1 < hmin1 or hmaj2 < hmin2:
        print(
            '\x1b[0;30;41m make_variogram Warning: major range should be greater than minor range \x1b[0m'
            )
    return var


def _mean(listvalue):
    """
    The mean value of the list data.
    """
    return sum(listvalue) / len(listvalue)


def _convert_yaml_to_bool(_yaml_bool_value):
    """This function converts the 'yes' and 'no' YAML values to traditional Boolean values.

    .. versionchanged:: 2.5.2
       A conversion is now only attempted if the value is not already in Boolean format.
    """
    if type(_yaml_bool_value) != bool:
        true_values = ['yes', 'true']
        if _yaml_bool_value.lower() in true_values:
            _yaml_bool_value = True
        else:
            _yaml_bool_value = False
    return _yaml_bool_value


def preDeployFile(file):
    """
    Called prior to deploying a single built file

    :param file: The file about to be deployed.
    :returns: None
    """
    pass


def remove_items(list, value):
    """Remove items from list
    The given list wil be returned withouth the items equal to value.
    Empty ('') is allowed. So this is een extension on list.remove()
    """
    ind_del = []
    for i in range(len(list)):
        if list[i] == value:
            ind_del.insert(0, i)
    if len(ind_del) > 0:
        for k in ind_del:
            del list[k]
    return list


@classmethod
def _get_namespace_name(cls) ->str:
    """Get the nicely formatted name of this namespace."""
    return cls.identifiers_recommended or cls.module_name


def commify(n):
    """
    Add commas to an integer `n`.

        >>> commify(1)
        '1'
        >>> commify(123)
        '123'
        >>> commify(1234)
        '1,234'
        >>> commify(1234567890)
        '1,234,567,890'
        >>> commify(123.0)
        '123.0'
        >>> commify(1234.5)
        '1,234.5'
        >>> commify(1234.56789)
        '1,234.56789'
        >>> commify('%.2f' % 1234.5)
        '1,234.50'
        >>> commify(None)
        >>>

    """
    if n is None:
        return None
    n = str(n)
    if '.' in n:
        dollars, cents = n.split('.')
    else:
        dollars, cents = n, None
    r = []
    for i, c in enumerate(str(dollars)[::-1]):
        if i and not i % 3:
            r.insert(0, ',')
        r.insert(0, c)
    out = ''.join(r)
    if cents:
        out += '.' + cents
    return out


def weekday(day):
    """
        Gives the weekday (0=Monday) of a positivist month and day.
        Note that the festival month does not have a day.
    """
    return day % 7 - 1


def path_shift(script_name, path_info, shift=1):
    """ Shift path fragments from PATH_INFO to SCRIPT_NAME and vice versa.

        :return: The modified paths.
        :param script_name: The SCRIPT_NAME path.
        :param script_name: The PATH_INFO path.
        :param shift: The number of path fragments to shift. May be negative to
          change the shift direction. (default: 1)
    """
    if shift == 0:
        return script_name, path_info
    pathlist = path_info.strip('/').split('/')
    scriptlist = script_name.strip('/').split('/')
    if pathlist and pathlist[0] == '':
        pathlist = []
    if scriptlist and scriptlist[0] == '':
        scriptlist = []
    if shift > 0 and shift <= len(pathlist):
        moved = pathlist[:shift]
        scriptlist = scriptlist + moved
        pathlist = pathlist[shift:]
    elif shift < 0 and shift >= -len(scriptlist):
        moved = scriptlist[shift:]
        pathlist = moved + pathlist
        scriptlist = scriptlist[:shift]
    else:
        empty = 'SCRIPT_NAME' if shift < 0 else 'PATH_INFO'
        raise AssertionError('Cannot shift. Nothing left from %s' % empty)
    new_script_name = '/' + '/'.join(scriptlist)
    new_path_info = '/' + '/'.join(pathlist)
    if path_info.endswith('/') and pathlist:
        new_path_info += '/'
    return new_script_name, new_path_info


def default(_):
    """
    A stub when there is no validation needed.
    """
    return True


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


def rlimits(inst, wfs, site, verbose=False):
    """
    Radius limits for guide star searches

    Parameters
        inst:       Instrument ['GMOS','F2']
        wfs:        Wavefront sensor ['OIWFS', 'PWFS1', 'PWFS2']
        site:       Gemini site ['N','S','mko','cpo']
        verbose     Verbose output?

    Return
        rmin [arcmin]
        rmax [arcmin]
    """
    rmin = 0.0
    rmax = 0.0
    oimin = {'GMOS-N': 0.33, 'GMOS-S': 0.33, 'F2': 0.33}
    oimax = {'GMOS-N': 4.8, 'GMOS-S': 4.8, 'F2': 3.75}
    p2min = {'GMOS-N': 5.3, 'GMOS-S': 5.3, 'F2': 5.3, 'GNIRS': 4.8, 'NIFS':
        4.0, 'NIRIF/6': 5.2, 'NIRIF/14': 4.8, 'NIRIF/32': 4.3}
    p1min = {'GMOS-N': 5.8, 'GMOS-S': 5.8, 'F2': 5.8, 'GNIRS': 5.0, 'NIFS':
        4.8, 'NIRIF/6': 5.7, 'NIRIF/14': 5.3, 'NIRIF/32': 4.8}
    pmax = 6.9
    if wfs == 'OIWFS':
        try:
            rmin = oimin[inst]
            rmax = oimax[inst]
        except Exception:
            if verbose:
                print('Only GMOS-N, GMOS-S, and F2 have supported OIs.')
    elif wfs == 'PWFS2':
        rmin = p2min[inst]
        rmax = pmax
    elif wfs == 'PWFS1':
        rmin = p1min[inst]
        rmax = pmax
    return rmin, rmax


def left_radius(ins_mode):
    """ A function that sets the defaut size of the left window depending on the mode."""
    if ins_mode[:3] == 'WFM':
        return 110
    elif ins_mode[:3] == 'NFM':
        return 6
    else:
        raise Exception('Mode undefined.')


def tuple_factory(colnames, rows):
    """
    Returns each row as a tuple

    Example::

        >>> from dse.query import tuple_factory
        >>> session = cluster.connect('mykeyspace')
        >>> session.row_factory = tuple_factory
        >>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
        >>> print rows[0]
        ('Bob', 42)

    """
    return rows


@classmethod
def host_collection(cls, options=None):
    """List associated host collections"""
    cls.command_sub = 'host-collections'
    return cls.execute(cls._construct_command(options))


def working_capital(current_assets, current_liabilities):
    """Computes working capital.

    @params
    -------
    current_assets: current assets
    current_liabilities: current liabilities

    returns
    -------
    Working capital, int or float

    explanation
    -----------
    Working capital is important for determining the financial strength of an enterprice.
    In the working capital is found the measure of the company's ability to carry on its normal business
    comfortably and without financial stringency, to expand its operations without the need of new financing,
    and to meet emergencies and losses without disaster.
    """
    working_cap = current_assets - current_liabilities
    return working_cap


def _h(text: str) ->str:
    """
    For some reason, :mod:`click` does not strip new line characters
    from helps in :func:`click.option` (although it does strip them
    from helps for :func:`click.command`). So, we have to do it
    ourselves.
    """
    return text.replace('\n', ' ')


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

    The ".dev0" means dirty.

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


@classmethod
def fromkeys(cls, default_factory, seq, value=None):
    """Create a new mapping with each key in `seq` set to `value`."""
    return cls(default_factory, dict.fromkeys(seq, value))


def old_col_fix():
    """This is to deal with the old df format"""
    return ['activation', 'hidden_layers']


def _add_stops_to_net(net, stops):
    """
    Add nodes to the network from the pandas dataframe describing (a part of the) stops table in the GTFS database.

    Parameters
    ----------
    net: networkx.Graph
    stops: pandas.DataFrame
    """
    for stop in stops.itertuples():
        data = {'lat': stop.lat, 'lon': stop.lon, 'name': stop.name}
        net.add_node(stop.stop_I, data)


def toordinal():
    """Return the proleptic Gregorian ordinal of the date

        January 1 of year 1 has ordinal 1. For any date object d,
        date.fromordinal(d.toordinal()) == d.
        """


def grid_translate(dx, dy, dz):
    """Translates the grid by (dx,dy,dz).
  """
    global x, y, z
    x += dx
    y += dy
    z += dz


def driver_delete_invalid():
    """Delete all visible drivers considered invalid

    """
    pass


def _esc_que_mark(analysis):
    """ Replaces a question mark in analysis (e.g. '//_N_ ? //')
        with an escaped version of the question mark #?
    """
    return analysis.replace(' ?', ' #?').replace(' ?', ' #?')


@classmethod
def _load_pkcs1_der(cls, keyfile):
    """Loads a key in PKCS#1 PEM format, implement in a subclass.

        :param keyfile: contents of a DER-encoded file that contains
            the public key.
        :type keyfile: bytes

        :return: the loaded key
        :rtype: AbstractKey
        """


def getGroupMemberIds():
    """ Return a list of the user ids of the group."""


@classmethod
def get_event(cls, session):
    """
        Gets the event that is pending for this class.  Events are
        returned in the form of objects.  Objects that have been deleted
        are marked as such.

        :param session:  the instance of Session used for APIC communication
        """
    urls = cls._get_subscription_urls()
    for url in urls:
        if not session.has_events(url):
            continue
        event = session.get_event(url)
        for class_name in cls._get_apic_classes():
            if class_name in event['imdata'][0]:
                break
        attributes = event['imdata'][0][class_name]['attributes']
        status = str(attributes['status'])
        dn = str(attributes['dn'])
        parent = cls._get_parent_from_dn(cls._get_parent_dn(dn))
        if status == 'created':
            name = str(attributes['name'])
        else:
            name = cls._get_name_from_dn(dn)
        obj = cls(name, parent=parent)
        obj._populate_from_attributes(attributes)
        if status == 'deleted':
            obj.mark_as_deleted()
        return obj


def from_bytes(data, big_endian=False):
    """Used on Python 2 to handle int.from_bytes"""
    if isinstance(data, str):
        data = bytearray(data)
    if big_endian:
        data = reversed(data)
    num = 0
    for offset, byte in enumerate(data):
        num += byte << offset * 8
    return num


def is_iterable(obj):
    """ Method that verifies if an object is iterable and not a string

    :param obj: Any object that will be tested if is iterable
    :return: True or False if the object can be iterated
    """
    return hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes))


@classmethod
def condition(cls, previous_value, value, has_changed=False, first_save=
    False, graph_property=None):
    """ Always save this value if it has changed

        :rtype: bool
        """
    return has_changed


def shellsub(command):
    """shellsub(command) --> command formatted for remote shell invocation"""
    import re
    command = re.compile("'").sub("\\'", command)
    command = re.compile('"').sub('\\"', command)
    command = re.compile('\\$').sub('\\\\$', command)
    command = re.compile('\\(').sub('\\\\(', command)
    command = re.compile('\\)').sub('\\\\)', command)
    return command


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

        :param DomainInvitesEmailExistingUsersType val:
        :rtype: EventType
        """
    return cls('domain_invites_email_existing_users', val)


def import_certificate(CertificateArn=None, Certificate=None, PrivateKey=
    None, CertificateChain=None):
    """
    Imports an SSL/TLS certificate into AWS Certificate Manager (ACM) to use with ACM's integrated AWS services .
    For more information about importing certificates into ACM, including the differences between certificates that you import and those that ACM provides, see Importing Certificates in the AWS Certificate Manager User Guide .
    To import a certificate, you must provide the certificate and the matching private key. When the certificate is not self-signed, you must also provide a certificate chain. You can omit the certificate chain when importing a self-signed certificate.
    The certificate, private key, and certificate chain must be PEM-encoded. For more information about converting these items to PEM format, see Importing Certificates Troubleshooting in the AWS Certificate Manager User Guide .
    To import a new certificate, omit the CertificateArn field. Include this field only when you want to replace a previously imported certificate.
    This operation returns the Amazon Resource Name (ARN) of the imported certificate.
    See also: AWS API Documentation

    :example: response = client.import_certificate(
        CertificateArn='string',
        Certificate=b'bytes',
        PrivateKey=b'bytes',
        CertificateChain=b'bytes'
    )

    :type CertificateArn: string
    :param CertificateArn: The Amazon Resource Name (ARN) of an imported certificate to replace. To import a new certificate, omit this field.

    :type Certificate: bytes
    :param Certificate: [REQUIRED]
            The certificate to import. It must meet the following requirements:
            Must be PEM-encoded.
            Must contain a 1024-bit or 2048-bit RSA public key.
            Must be valid at the time of import. You cannot import a certificate before its validity period begins (the certificate's NotBefore date) or after it expires (the certificate's NotAfter date).

    :type PrivateKey: bytes
    :param PrivateKey: [REQUIRED]
            The private key that matches the public key in the certificate. It must meet the following requirements:
            Must be PEM-encoded.
            Must be unencrypted. You cannot import a private key that is protected by a password or passphrase.

    :type CertificateChain: bytes
    :param CertificateChain: The certificate chain. It must be PEM-encoded.

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

    """
    pass


def is_tokenizer_serializable(tokenizer, language):
    """Extend with other tokenizers which are found to not be serializable
    """
    if tokenizer == 'spacy':
        return False
    return True


def uncomment(line):
    """
    Remove OGS comments from a given line of an OGS file.

    Comments are indicated by ";". The line is then splitted by whitespaces.

    Parameters
    ----------
    line : str
        given line
    """
    return line.split(';')[0].split('//')[0].split()


def window_from_array(array):
    """Convert a `numpy.ndarray` into a LAL `Window` object
    """
    from ...utils.lal import find_typed_function
    dtype = array.dtype
    seq = find_typed_function(dtype, 'Create', 'Sequence')(array.size)
    seq.data = array
    return find_typed_function(dtype, 'Create', 'WindowFromSequence')(seq)


def parse_message_id(value, **kwargs):
    """Parse a Message-ID: header."""
    return value.strip('\n')


@classmethod
def update(cls, uri, search_spec='name', search_string='test',
    extended_fetch=False, **kwargs):
    """Upate an Organization on the server"""
    exists = cls.find(uri=uri, search_spec=search_spec, search_string=
        search_string)
    if not exists.json():
        updates = cls.payload(**kwargs)
        return cls.post(uri, updates)
    else:
        return exists


def stage(hub, name):
    """
    Apply the exclude value
    """
    high = hub.idem.exclude.apply(hub.idem.RUNS[name]['high'])
    hub.idem.RUNS[name]['high'] = high


def count_collisions(Collisions):
    """
    Counts the number of unique collisions and gets the collision index.

    Parameters
    ----------
    Collisions : array_like
        Array of booleans, containing true if during a collision event, false otherwise.

    Returns
    -------
    CollisionCount : int
        Number of unique collisions
    CollisionIndicies : list
        Indicies of collision occurance
    """
    CollisionCount = 0
    CollisionIndicies = []
    lastval = True
    for i, val in enumerate(Collisions):
        if val == True and lastval == False:
            CollisionIndicies.append(i)
            CollisionCount += 1
        lastval = val
    return CollisionCount, CollisionIndicies


def human2bytes(s):
    """
    Attempts to guess the string format based on default symbols
    set and return the corresponding bytes as an integer.
    When unable to recognize the format ValueError is raised.

      >>> human2bytes('0 B')
      0
      >>> human2bytes('1 K')
      1024
      >>> human2bytes('1 M')
      1048576
      >>> human2bytes('1 Gi')
      1073741824
      >>> human2bytes('1 tera')
      1099511627776

      >>> human2bytes('0.5kilo')
      512
      >>> human2bytes('0.1  byte')
      0
      >>> human2bytes('1 k')  # k is an alias for K
      1024
      >>> human2bytes('12 foo')
      Traceback (most recent call last):
          ...
      ValueError: can't interpret '12 foo'
    """
    init = s
    num = ''
    SYMBOLS = {'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'),
        'customary_ext': ('byte', 'kilo', 'mega', 'giga', 'tera', 'peta',
        'exa', 'zetta', 'iotta'), 'iec': ('Bi', 'Ki', 'Mi', 'Gi', 'Ti',
        'Pi', 'Ei', 'Zi', 'Yi'), 'iec_ext': ('byte', 'kibi', 'mebi', 'gibi',
        'tebi', 'pebi', 'exbi', 'zebi', 'yobi')}
    while s and s[0:1].isdigit() or s[0:1] == '.':
        num += s[0]
        s = s[1:]
    num = float(num)
    letter = s.strip()
    for name, sset in SYMBOLS.items():
        if letter in sset:
            break
    else:
        if letter == 'k':
            sset = SYMBOLS['customary']
            letter = letter.upper()
        else:
            raise ValueError("can't interpret %r" % init)
    prefix = {sset[0]: 1}
    for i, s in enumerate(sset[1:]):
        prefix[s] = 1 << (i + 1) * 10
    return int(num * prefix[letter])


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


@staticmethod
def metadata_updated_on(item):
    """Extracts and coverts the update time from a Docker Hub item.

        The timestamp is extracted from 'fetched_on' field. This field
        is not part of the data provided by Docker Hub. It is added
        by this backend.

        :param item: item generated by the backend

        :returns: a UNIX timestamp
        """
    return item['fetched_on']


def parallel_finalize_cpdir(cpdir, outdir, cpfileglob='checkplot-*.pkl*',
    objfits=None):
    """This is a parallel driver for `finalize_checkplot`, operating on a
    directory of checkplots.

    Parameters
    ----------

    cpdir : str
        This is the path to the directory containing all the checkplot pickles
        to process and run through the finalization process.

    outdir : str
        The directory to where the finalized checkplot pickles will be written.

    objfits : str
        Path to the FITS file containing a WCS header and detections of all
        objects observed by the actual instrument that obtained the light
        curves. This should generally be a high quality 'reference' frame so
        that all of the objects whose checkplots we're finalizing (in `cplist`)
        can be seen on the frame.

    Returns
    -------

    dict
        Dict indicating the success/failure (as True/False) of the checkplot
        finalize operations for each checkplot pickle provided in `cplist`.

    """


def touch_file(filepath):
    """
    Creates a new file
    """
    open(filepath, 'a').close()


def list_bootstrap_actions(ClusterId=None, Marker=None):
    """
    Provides information about the bootstrap actions associated with a cluster.
    See also: AWS API Documentation

    :example: response = client.list_bootstrap_actions(
        ClusterId='string',
        Marker='string'
    )

    :type ClusterId: string
    :param ClusterId: [REQUIRED]
            The cluster identifier for the bootstrap actions to list.

    :type Marker: string
    :param Marker: The pagination token that indicates the next set of results to retrieve.

    :rtype: dict
    :return: {
        'BootstrapActions': [
            {
                'Name': 'string',
                'ScriptPath': 'string',
                'Args': [
                    'string',
                ]
            },
        ],
        'Marker': 'string'
    }

    :returns:
    (string) --

    """
    pass


def _wanmen_get_boke_id_by_json_topic_part(json_content, tIndex, pIndex):
    """JSON, int, int, int->str

    Get one BokeCC video ID with courseid+topicID+partID."""
    return json_content[0]['Topics'][tIndex]['Parts'][pIndex]['ccVideoLink']


def getgrnam(name):
    """Wrapper function to protect against `grp` not being available
    on Windows
    """
    import grp
    return grp.getgrnam(name)


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 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 _to_numeric(value):
    """Try to convert a string to an integer or a float.
    If not possible, returns the initial string.
    """
    try:
        value = int(value)
    except:
        try:
            value = float(value)
        except:
            pass
    return value


def remove_inspection_residues(flow):
    """Remove all the changes made by prepare_training_inspection."""
    try:
        for method_name in flow._snapshot_instance_methods_:
            delattr(flow, method_name)
        del flow._snapshot_counter_
        del flow._snapshot_path_
        del flow._snapshot_name_
        del flow._snapshot_instance_methods_
    except:
        pass


def get_libsqreen_version():
    """ Return the Sqreen Library version if present.
    """
    try:
        from sq_native import get_lib_version
    except ImportError:
        return None
    else:
        return get_lib_version()


@staticmethod
def parse_csv_line(line):
    """
        Parse a CSV line and return the corresponding city information in
        a dictionnary.

        Array fields ( http://download.geonames.org/export/zip/readme.txt ) :

        country code : iso country code, 2 characters
        postal code  : varchar(20)
        place name   : varchar(180)
        admin name1  : 1. order subdivision (state) varchar(100)
        admin code1  : 1. order subdivision (state) varchar(20)
        admin name2  : 2. order subdivision (county/province) varchar(100)
        admin code2  : 2. order subdivision (county/province) varchar(20)
        admin name3  : 3. order subdivision (community) varchar(100)
        admin code3  : 3. order subdivision (community) varchar(20)
        latitude     : estimated latitude (wgs84)
        longitude    : estimated longitude (wgs84)
        accuracy     : accuracy of lat/lng from 1=estimated to 6=centroid
        """
    city_information = {'country': {'code': line[0]}, 'state': {'code':
        line[4], 'name': line[3]}, 'county': {'code': line[6], 'name': line
        [5]}, 'community': {'code': line[8], 'name': line[7]}, 'city': {
        'postcode': line[1], 'name': line[2], 'latitude': line[9],
        'longitude': line[10], 'accuracy': line[11]}}
    return city_information


def Smith(x, rhol, rhog):
    """Calculates void fraction in two-phase flow according to the model of
    [1]_, also given in [2]_ and [3]_.

    .. math::
        \\alpha = \\left\\{1 + \\left(\\frac{1-x}{x}\\right)
        \\left(\\frac{\\rho_g}{\\rho_l}\\right)\\left[K+(1-K)
        \\sqrt{\\frac{\\frac{\\rho_l}{\\rho_g} + K\\left(\\frac{1-x}{x}\\right)}
        {1 + K\\left(\\frac{1-x}{x}\\right)}}\\right] \\right\\}^{-1}

    Parameters
    ----------
    x : float
        Quality at the specific tube interval []
    rhol : float
        Density of the liquid [kg/m^3]
    rhog : float
        Density of the gas [kg/m^3]

    Returns
    -------
    alpha : float
        Void fraction (area of gas / total area of channel), [-]

    Notes
    -----
    [1]_ is an easy to read paper and has been reviewed.
    The form of the expression here is rearranged somewhat differently
    than in [1]_ but has been verified to be numerically equivalent. The form
    of this in [3]_ is missing a square root on a bracketed term; this appears
    in multiple papers by the authors.

    Examples
    --------
    >>> Smith(.4, 800, 2.5)
    0.959981235534199

    References
    ----------
    .. [1] Smith, S. L. "Void Fractions in Two-Phase Flow: A Correlation Based
       upon an Equal Velocity Head Model." Proceedings of the Institution of
       Mechanical Engineers 184, no. 1 (June 1, 1969): 647-64.
       doi:10.1243/PIME_PROC_1969_184_051_02.
    .. [2] Xu, Yu, and Xiande Fang. "Correlations of Void Fraction for Two-
       Phase Refrigerant Flow in Pipes." Applied Thermal Engineering 64, no.
       1-2 (March 2014): 242–51. doi:10.1016/j.applthermaleng.2013.12.032.
    .. [3] Dalkilic, A. S., S. Laohalertdecha, and S. Wongwises. "Effect of
       Void Fraction Models on the Two-Phase Friction Factor of R134a during
       Condensation in Vertical Downward Flow in a Smooth Tube." International
       Communications in Heat and Mass Transfer 35, no. 8 (October 2008):
       921-27. doi:10.1016/j.icheatmasstransfer.2008.04.001.
    """
    K = 0.4
    x_ratio = (1 - x) / x
    root = ((rhol / rhog + K * x_ratio) / (1 + K * x_ratio)) ** 0.5
    alpha = (1 + x_ratio * (rhog / rhol) * (K + (1 - K) * root)) ** -1
    return alpha


def Cookie(request):
    """
    Get cookie value(s).

    Set `request.cookie` with Cookie object.
    """
    pass


def rename(in_files, suffix=None):
    """Rename all the files in `in_files` adding the `suffix` keeping its
    extension and basedir."""
    import os.path as path
    from nipype.utils.filemanip import filename_to_list, split_filename, list_to_filename
    out_files = []
    for idx, filename in enumerate(filename_to_list(in_files)):
        base, name, ext = split_filename(filename)
        if suffix is None:
            new_name = name + '_%03d' % idx + ext
        else:
            new_name = name + suffix + ext
        out_files.append(path.join(base, new_name))
    return list_to_filename(out_files)


def ar_3(provider):
    """Issue A-RELEASE confirmation primitive and close transport connection."""
    provider.to_service_user.put(provider.primitive)
    provider.dul_socket.close()
    provider.dul_socket = None
    return 'Sta1'


def get_recess_int(df, Q, maxper=18, minper=6, thresh=30, inplace=False):
    """Gets intervals of recession from a hydrograph

    :param df: DataFrame with hydrograph data
    :param Q: Field in DataFrame with discharge data
    :param maxper: Period of record to scan discharge data for maxima; created for daily values; defaults to 18
    :param minper: Period of record to scan discharge data for minima; should be less than maxper; defaulst to 6
    :param thresh: Threshold of discharge below which maxima are not considered; defaults to 30
    :param inplace: Append to input database or create new one; defaults to False
    :return: DataFrame of original data and Max and Min, Indexes of maxima, Indexes of minima
    """
    if inplace:
        data = df
    else:
        data = df.copy()
    data['max'] = data[Q].rolling(maxper, center=True).max()
    data['max'] = data.ix[data['max'] == data['value'], 'max']
    data['max'] = data.ix[data['max'] > thresh, 'max']
    data['min'] = data[Q].rolling(minper, center=True).min()
    data['min'] = data.ix[data['min'] == data['value'], 'min']
    maxlist = data.index[data['max'].notnull()]
    firstmin = []
    for ind in maxlist:
        firstmin.append(data.ix[ind:, ('min')].first_valid_index())
    data['min'] = data.ix[data.index.isin(firstmin), 'min']
    return data, maxlist, firstmin


@staticmethod
def itransform_name_define(transform):
    """
        This function is used for model results table, displaying any transformations performed
        """
    if transform == 'tanh':
        return 'arctanh'
    elif transform == 'exp':
        return 'log'
    elif transform == 'logit':
        return 'ilogit'
    elif transform is None:
        return ''
    else:
        return None


def _schema_from_verb(verb, partial=False):
    """Return an instance of schema for given verb."""
    from .verbs import Verbs
    return getattr(Verbs, verb)(partial=partial)


@conf
def link_add_flags(conf):
    """
	Adds LINKFLAGS / LDFLAGS from os.environ to conf.env
	"""
    conf.add_os_flags('LINKFLAGS', dup=False)
    conf.add_os_flags('LDFLAGS', dup=False)


def unzip(items):
    """Performs the reverse of zip, i.e. produces separate lists from tuples.

    items should be list of k-element tuples. Will raise exception if any
    tuples contain more items than the first one.

    Conceptually equivalent to transposing the matrix of tuples.

    Returns list of lists in which the ith list contains the ith element of
    each tuple.

    Note: zip expects *items rather than items, such that unzip(zip(*items))
    returns something that compares equal to items.

    Always returns lists: does not check original data type, but will accept
    any sequence.

    This function is ported from PyCogent (http://www.pycogent.org). PyCogent
    is a GPL project, but we obtained permission from the authors of this
    function to port it to the BIOM Format project (and keep it under BIOM's
    BSD license).
    """
    if items:
        return list(map(list, zip(*list(items))))
    else:
        return []


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 img2gray(img, mode='L'):
    """
    Converts an image (:epkg:`PIL`) to gray scale.

    @param      img     see *Image* from :epkg:`PIL`
    @param      mode    ``'L'`` or ``'LA'``
    @return             see *Image* from :epkg:`PIL`
    """
    return img.convert(mode)


def export_commands() ->dict:
    """Lists the available sub-commands of the 'chado export' command with corresponding descriptions"""
    return {'fasta':
        'export genome/protein sequences from the CHADO database to a FASTA file'
        , 'gff':
        'export genomic data from the CHADO database to a GFF3 file', 'gaf':
        'export gene annotation data from the CHADO database to a GAF file'}


def provider_parser(subparser):
    """Generate a subparser for Azure DNS"""
    subparser.description = """
        The Azure provider orchestrates the DNS zones hosted in a resource group for a subscription
        in Microsoft Azure Cloud. To authenticate, an App registration must be created in an Azure
        Active Directory. This App registration must be granted Admin for API permissions to
        Domain.ReadWrite.All" to this Active Directory, and must have a usable Client secret.
    """
    subparser.add_argument('--auth-client-id', help=
        'specify the client ID (aka application ID) of the App registration')
    subparser.add_argument('--auth-client-secret', help=
        'specify the client secret of the App registration')
    subparser.add_argument('--auth-tenant-id', help=
        'specify the tenant ID (aka directory ID) of the App registration')
    subparser.add_argument('--auth-subscription-id', help=
        'specify the subscription ID attached to the resource group')
    subparser.add_argument('--resource-group', help=
        'specify the resource group hosting the DNS zone to edit')


def _on_message_simple(client, userdata, message):
    """Internal callback"""
    if userdata['msg_count'] == 0:
        return
    if message.retain and not userdata['retained']:
        return
    userdata['msg_count'] = userdata['msg_count'] - 1
    if userdata['messages'] is None and userdata['msg_count'] == 0:
        userdata['messages'] = message
        client.disconnect()
        return
    userdata['messages'].append(message)
    if userdata['msg_count'] == 0:
        client.disconnect()


def unpause():
    """
        Remove this L{IPause} from the set of L{IPause}s obstructing delivery
        from an L{IFount}.  When no L{IPause}s remain, the flow will resume.

        The spice must flow.

        @raise AlreadyUnpaused: An L{IPause} may only be C{unpause}d once; it
            can not be re-paused.  Therefore a second invocation of this
            method is invalid and will raise an L{AlreadyUnpaused} exception.
        """


def get_fqn(the_type):
    """Get module.type_name for a given type."""
    module = the_type.__module__
    name = the_type.__qualname__
    return '%s.%s' % (module, name)


@staticmethod
def filter_with_english_letters(buf):
    """
        Returns a copy of ``buf`` that retains only the sequences of English
        alphabet and high byte characters that are not between <> characters.
        Also retains English alphabet and high byte characters immediately
        before occurrences of >.

        This filter can be applied to all scripts which contain both English
        characters and extended ASCII characters, but is currently only used by
        ``Latin1Prober``.
        """
    filtered = bytearray()
    in_tag = False
    prev = 0
    for curr in range(len(buf)):
        buf_char = buf[curr:curr + 1]
        if buf_char == b'>':
            in_tag = False
        elif buf_char == b'<':
            in_tag = True
        if buf_char < b'\x80' and not buf_char.isalpha():
            if curr > prev and not in_tag:
                filtered.extend(buf[prev:curr])
                filtered.extend(b' ')
            prev = curr + 1
    if not in_tag:
        filtered.extend(buf[prev:])
    return filtered


def applyMutinfoCorr(mutinfo, corr='prod'):
    """Returns a copy of *mutinfo* array after average product correction
    (default) or average sum correction is applied.  See [DSD08]_ for details.

    .. [DSD08] Dunn SD, Wahl LM, Gloor GB. Mutual information without the
       influence of phylogeny or entropy dramatically improves residue
       contact prediction. *Bioinformatics* **2008** 24(3):333-340."""
    try:
        ndim, shape = mutinfo.ndim, mutinfo.shape
    except AttributeError:
        raise TypeError('mutinfo must be a 2D square array')
    if ndim != 2 or shape[0] != shape[1]:
        raise ValueError('mutinfo must be a 2D square array')
    try:
        sw = corr.startswith
    except AttributeError:
        raise TypeError('correction must be a string')
    avg_mipos = mutinfo.sum(1) / (shape[0] - 1)
    avg_mi = avg_mipos.mean()
    mi = mutinfo.copy()
    if sw('prod') or sw('apc'):
        for i, i_avg in enumerate(avg_mipos):
            for j, j_avg in enumerate(avg_mipos):
                mi[i, j] -= i_avg * j_avg / avg_mi
    elif sw('sum') or sw('asc'):
        for i, i_avg in enumerate(avg_mipos):
            for j, j_avg in enumerate(avg_mipos):
                mi[i, j] -= i_avg + j_avg - avg_mi
    else:
        raise ValueError('correction must be prod or sum, not ' + corr)
    return mi


def _valid_param(param):
    """Check parameter are valid for _args_kwargs.

    * no space
    * a name before '='
    """
    if ' ' in param:
        raise ValueError('no space allowed')
    if param.startswith('='):
        raise ValueError("name required for kwarg '%s'" % param)


@classmethod
def is_site_in_topic(cls) ->bool:
    """True if site id is in topic."""
    return True


@classmethod
def get_table_names(cls, schema, inspector):
    """Need to consider foreign tables for PostgreSQL"""
    tables = inspector.get_table_names(schema)
    tables.extend(inspector.get_foreign_table_names(schema))
    return sorted(tables)


def view_frame():
    """Reset viewable area to show range around current frame

    """
    pass


def formula(foyer_fiscal, period, parameters):
    """
        Impôt sans quotient familial
        """
    rni = foyer_fiscal('rni', period)
    nb_adult = foyer_fiscal('nb_adult', period)
    bareme = parameters(period).impot_revenu.bareme
    A = bareme.calc(rni / nb_adult)
    return nb_adult * A


def set_global_constants(posdef_inv_method=None, tf_replicator=None):
    """Sets various global constants used by the classes in this module."""
    global POSDEF_INV_METHOD
    global _TF_REPLICATOR
    if posdef_inv_method is not None:
        POSDEF_INV_METHOD = posdef_inv_method
    if tf_replicator is not None:
        _TF_REPLICATOR = tf_replicator


def minimise(ts):
    """
    Returns a tree sequence with the minimal information required to represent
    the tree topologies at its sites.

    This is a convenience function used when we wish to use a subset of the
    sites in a tree sequence for ancestor matching. It is a thin-wrapper
    over the simplify method.
    """
    return ts.simplify(reduce_to_site_topology=True, filter_sites=False)


def rgetattr(obj, attr):
    """
    Recursively get an attribute from object. Extends getattr method

    :param obj: object
    :param attr: attribute to get
    :return:
    """
    attributes = attr.split('.')
    curr_object = obj
    for attribute in attributes:
        list_indices = []
        splitted = attribute.split('[')
        if not splitted:
            splitted = [attribute]
        curr_object = getattr(curr_object, splitted[0])
        if len(splitted) > 1:
            for i in range(1, len(splitted)):
                list_indices.append(splitted[i].replace(']', '').replace(
                    "'", ''))
        for item in list_indices:
            try:
                curr_object = curr_object[item]
            except (KeyError, TypeError, IndexError):
                curr_object = curr_object[int(item)]
    return curr_object


def parse_operating_point(operating_point, operating_kinds, class_names):
    """Checks the operating point contents and extracts the three defined
    variables

    """
    if 'kind' not in operating_point:
        raise ValueError('Failed to find the kind of operating point.')
    elif operating_point['kind'] not in operating_kinds:
        raise ValueError(
            'Unexpected operating point kind. Allowed values are: %s.' %
            ', '.join(operating_kinds))
    if 'threshold' not in operating_point:
        raise ValueError('Failed to find the threshold of the operatingpoint.')
    if operating_point['threshold'] > 1 or operating_point['threshold'] < 0:
        raise ValueError('The threshold value should be in the 0 to 1 range.')
    if 'positive_class' not in operating_point:
        raise ValueError(
            'The operating point needs to have a positive_class attribute.')
    else:
        positive_class = operating_point['positive_class']
        if positive_class not in class_names:
            raise ValueError(
                'The positive class must be one of theobjective field classes: %s.'
                 % ', '.join(class_names))
    kind = operating_point['kind']
    threshold = operating_point['threshold']
    return kind, threshold, positive_class


def getSize(size='original'):
    """
        Returns the width and height registered for the specific size

        The sizes are taken from the raptus_article properties sheet
        and are formed by the following name schema:

            flash_<size>_(height|width)
        """


def init_csrf(csrf_generation_function):
    """
    Calling this function will initialised CSRF behaviour in all forms in the application.
    Pass in a function that returns a string containing a valid CSRF token, and this function
    will be called in each form, and will add a hidden input named "_csrf_token". This does
    not validate the token.
    """
    global _csrf_generation_function
    _csrf_generation_function = csrf_generation_function


@staticmethod
def terminate_starting_postmaster(postmaster):
    """Terminates a postmaster that has not yet opened ports or possibly even written a pid file. Blocks
        until the process goes away."""
    postmaster.signal_stop('immediate')
    postmaster.wait()


@classmethod
def __factory(cls, data):
    """
        This factory makes that any returned value is a measure
        instead of a float.
        """
    return cls(data)


def truncate_to_max(errors, max_errors):
    """If max_errors was specified, truncate the list of errors.

    Give the total number of times that the error was found elsewhere.
    """
    if len(errors) > max_errors:
        start1, end1, err1, msg1, replacements = errors[0]
        if len(errors) == max_errors + 1:
            msg1 += ' Found once elsewhere.'
        else:
            msg1 += ' Found {} times elsewhere.'.format(len(errors))
        errors = errors[1:max_errors]
        errors = [(start1, end1, err1, msg1, replacements)] + errors
    return errors


def scaled(target, prop, factor):
    """
    Scales an existing value by a factor.  Useful for constricting some throat
    property.

    Parameters
    ----------
    target : OpenPNM Object
        The object which this model is associated with. This controls the
        length of the calculated array, and also provides access to other
        necessary properties.

    prop : string
        The dictionary key of the array containing the values to be scaled.

    factor : scalar
        The factor by which the values should be scaled.

    Returns
    -------
    value : NumPy ndarray
        Array containing ``target[prop]`` values scaled by ``factor``.

    """
    value = target[prop] * factor
    return value


def build_tracker(tile_grid, store, **kwds):
    """ Build the ``gee`` section and return a Tracker
    """
    from ..tracker import Tracker
    tracker = Tracker(tile_grid, store, **kwds)
    return tracker


def validate_multiple_cols(clsname, cols):
    """Validate that there are at least two columns to evaluate.

    This is used for various feature selection techniques, as well as
    in several feature extraction techniques.

    Parameters
    ----------
    clsname : str or unicode
        The name of the class that is calling the function.
        Used for more clear error messages.

    cols : array-like, shape=(n_features,)
        The columns to evaluate. If ``cols`` is not None
        and the length is less than 2, will raise a
        ``ValueError``.
    """
    if len(cols) < 2:
        raise ValueError(
            '%s requires at least two features. Your data (or the passed ``cols`` parameter) includes too few features (%i)'
             % (clsname, len(cols)))


@classmethod
def delete_conntrack_helper(cls, cth, client=None):
    """Delete conntrack helper

        :param client: Client to be used
        If client is not given it will use the client used to create the
        conntrack helper, or cls.client if unknown.
        """
    client = client or cth.get('client') or cls.client
    client.delete_conntrack_helper(cth['router_id'], cth['id'])


@staticmethod
def email_users(users, subject, text_body, html_body=None, sender=None, cc=
    None, bcc=None, configuration=None, **kwargs):
    """Email a list of users

        Args:
            users (List[User]): List of users in To address
            subject (str): Email subject
            text_body (str): Plain text email body
            html_body (str): HTML email body
            sender (Optional[str]): Email sender. Defaults to SMTP username.
            cc (Optional[List[User]]: List of users to cc. Defaults to None.
            bcc (Optional[List[User]]: List of users to bcc. Defaults to None.
            configuration (Optional[Configuration]): HDX configuration. Defaults to configuration of first user in list.
            **kwargs: See below
            mail_options (List): Mail options (see smtplib documentation)
            rcpt_options (List): Recipient options (see smtplib documentation)

        Returns:
            None
        """
    if not users:
        raise ValueError('No users supplied')
    recipients = list()
    for user in users:
        recipients.append(user.data['email'])
    ccemails = list()
    for user in cc:
        ccemails.append(user.data['email'])
    bccemails = list()
    for user in bcc:
        bccemails.append(user.data['email'])
    if configuration is None:
        configuration = users[0].configuration
    configuration.emailer().send(recipients, subject, text_body, html_body=
        html_body, sender=sender, cc=ccemails, bcc=bccemails, **kwargs)


@classmethod
def cx(cls, *args):
    """
        Either the x position of cursor, or sets the x position.
        Example:
        ::

            # gets the x position of cursor
            my_x = cls.cx()

            # set the x position to 20
            cls.cx(20)

            # moves right 2 spots
            cls.cx(cls.cx() + 2)

        :param x: optional x position to move to
        :return: if x not specified, returns the x position of cursor
        """
    x, y = cls.getxy()
    if not args:
        return x
    return cls.move(args[0], y)


@classmethod
def validate(cls, value: str) ->None:
    """Value validation method.

    Valid values are ``ON`` and ``OFF``.

    Args:
      value (str): The value to validate.

    Raises:
      ValueError: Raises ValueError if an invalid value has been specified.
    """
    super().validate(value)
    if value not in ['ON', 'OFF']:
        raise ValueError()


def get_translations():
    """
        get all the translated objects (including the context)
        """


def scan_module(module, interface):
    """Return all the items in a module that conform to an interface.

    Scan every item named in the module's `__all__`.  If that item conforms to
    the given interface, *and* the item is not declared as an
    `@abstract_component`, then return the item.

    :param module: A module object.
    :type module: module
    :param interface: The interface that returned objects must conform to.
    :type interface: `Interface`
    :return: The sequence of matching components.
    :rtype: items implementing `interface`
    """
    missing = object()
    for name in module.__all__:
        component = getattr(module, name, missing)
        assert component is not missing, '%s has bad __all__: %s' % (module,
            name)
        if interface.implementedBy(component
            ) and '__abstract_component__' not in component.__dict__:
            yield component


def set_lim(lim, get_lim_f, set_lim_f):
    """Set x or y limitis of the plot

    lim can be a tuple containing the limits or the string "default"
    or "range".  "default" does nothing and uses matplotlib default.
    "range" extends the current margin by 10%.  This is useful since
    the default xlim and ylim of the plots sometimes make it harder to
    see data that is just in the margin.

    """
    if lim == 'default':
        return
    if lim == 'range':
        cur_lim = get_lim_f()
        lim = cur_lim[0] - 0.1 * (cur_lim[1] - cur_lim[0]), cur_lim[1
            ] + 0.1 * (cur_lim[1] - cur_lim[0])
    set_lim_f(lim[0], lim[1])


@classmethod
def from_mesh(cls, mesh):
    """Creates a ``BoundingVolume`` from a :class:`compas.datastructures.Mesh`.

        Parameters
        ----------
        mesh: `compas.datastructures.Mesh`

        Examples
        --------
        >>> import compas
        >>> from compas.datastructures import Mesh
        >>> from compas_fab.robots import BoundingVolume
        >>> mesh = Mesh.from_obj(compas.get('faces.obj'))
        >>> bv = BoundingVolume.from_mesh(Mesh)
        >>> bv.type
        3
        """
    return cls(cls.MESH, mesh)


def func_configuration(args):
    """show internal configuration of punx"""
    from . import cache_manager
    from . import github_handler
    cm = cache_manager.CacheManager()
    print('Locally-available versions of NeXus definitions (NXDL files)')
    print(cm.table_of_caches())
    print('default NXDL file set: ', cm.default_file_set.ref)


def class_to_fqn(cls):
    """Returns the fully qualified name for cls"""
    return '%s.%s' % (cls.__module__, cls.__name__)


def find_differences(s1, s2):
    """Return the index of differences between two sequences."""
    indices = list()
    for i in range(len(s1)):
        if s1[i] != s2[i]:
            indices.append(i)
    return indices


def reorder_list(org_list, selected):
    """
    if the first is in the list.
    move the first in front of the list
    if not, add first to the list
    """
    if isinstance(selected, list) and len(selected) == 0:
        return org_list, selected
    if not isinstance(selected, list):
        selected = [selected]
    new_list = list(org_list)
    for item in selected:
        try:
            new_list.remove(item)
        except ValueError:
            pass
    updated_list = list(selected)
    updated_list.extend(new_list)
    return updated_list, selected


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 location_clear(clear_delta: bool=False):
    """Clear the object’s location

    :param clear_delta: Clear Delta, Clear delta location in addition to clearing the normal location transform
    :type clear_delta: bool
    """
    pass


@classmethod
def to_time(cls, amazon_time):
    """
        Parses alexa time output string to mapped time.

        :param (str) amazon_time: Amazon string time. Possible choices: [MO, AV, EV, NI].

        :returns: Time tuple with hour as first element and minutes as second,
            otherwise None when amazon_time is not parsable.
        :rtype: tuple
        """
    time = None
    if not amazon_time:
        return time
    try:
        time = cls.DAY_TIME_MAPPER[amazon_time]
    except KeyError:
        pass
    try:
        time = map(int, amazon_time.split(':'))
    except (ValueError, AttributeError):
        pass
    return time


@staticmethod
def p_attribute_value_list_optional(p):
    """attribute_values_list_optional : empty
                                          | attribute_values_list"""
    p[0] = p[1]


def removed(object, oldParent=None, oldName=None):
    """Send an :class:`~.IObjectRemovedEvent` for ``object``.

        ``oldParent`` is the container ``object`` was removed from.
        ``oldName`` was the name used to store ``object`` in `oldParent`.

        If either of these is not provided or is ``None``, they will
        be taken from the values of ``object.__parent__`` or
        ``object.__name__``, respectively.
        """


def comment_wrap(message):
    """ Put wrap the message with comment pattern in markdown file
    """
    return '<!-- ' + message + ' -->'


@staticmethod
def __encode_record(record):
    """
        Class for encode the record for correct send
        :param record: the record to encode
        :return: record encoded for PY3
        """
    if not isinstance(record, bytes):
        return record.encode('utf-8')
    return record


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


def get_config_from_package(package):
    """ Breaks a package string in module and class.

    :param package: A package string.
    :return: A config dict with class and module.
    """
    package_x = package.split('.')
    package_conf = {}
    package_conf['class'] = package_x[-1]
    package_conf['module'] = '.'.join(package_x[:-1][:])
    return package_conf


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

        :param PendingSecondaryEmailAddedDetails val:
        :rtype: EventDetails
        """
    return cls('pending_secondary_email_added_details', val)


def dbh_serial_viewer(path, contenttype, extension, roottag, nsurl):
    """ Generic Serial Handler - Returns serial handler for Arduino output logs """
    if extension.lower() == 'serial':
        return 'db_serial_viewer'
    else:
        return False


def get_task_prerun_attachment(task_id, task, args, kwargs, **cbkwargs):
    """Create the slack message attachment for a task prerun."""
    message = 'Executing -- ' + task.name.rsplit('.', 1)[-1]
    lines = ['Name: *' + task.name + '*']
    if cbkwargs['show_task_id']:
        lines.append('Task ID: ' + task_id)
    if cbkwargs['use_fixed_width']:
        if cbkwargs['show_task_args']:
            lines.append('args: ' + '`' + str(args) + '`')
        if cbkwargs['show_task_kwargs']:
            lines.append('kwargs: ' + '`' + str(kwargs) + '`')
    else:
        if cbkwargs['show_task_args']:
            lines.append('args: ' + str(args))
        if cbkwargs['show_task_kwargs']:
            lines.append('kwargs: ' + str(kwargs))
    executing = '\n'.join(lines)
    attachment = {'attachments': [{'fallback': message, 'color': cbkwargs[
        'slack_task_prerun_color'], 'text': executing, 'title': message,
        'mrkdwn_in': ['text']}], 'text': ''}
    if cbkwargs['flower_base_url']:
        attachment['attachments'][0]['title_link'] = cbkwargs['flower_base_url'
            ] + '/task/{tid}'.format(tid=task_id)
    return attachment


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

        :param PaperFolderChangeSubscriptionDetails val:
        :rtype: EventDetails
        """
    return cls('paper_folder_change_subscription_details', val)


def select_all_toggle(invert: bool=False):
    """Select or deselect all NLA-Strips

    :param invert: Invert
    :type invert: bool
    """
    pass


def user_id(openid):
    """generate user_id from openid"""
    import re
    ESGF_OPENID_REXP = 'https://(.*)/esgf-idp/openid/(.*)'
    user_id = None
    mo = re.match(ESGF_OPENID_REXP, openid)
    try:
        hostname = mo.group(1)
        username = mo.group(2)
        user_id = '%s_%s' % (username, hostname)
    except:
        raise Exception('unsupported openid')
    return user_id


def previewrange_clear():
    """Clear Preview Range

    """
    pass


def setCaching(onOff):
    """Enable or disable global caching behavior"""
    global __sinbadCacheEnabled
    __sinbadCacheEnabled = onOff


def set_name_h(name_x, name_q):
    """Set the full instruments names in regression; return generic name if user
    provides no explicit name."

    Parameters
    ----------
    name_x      : list of strings
                  User provided exogenous variable names.
    name_q      : list of strings
                  User provided instrument variable names.

    Returns
    -------
    name_h      : list of strings

    """
    return name_x + name_q


def cumprod(x, axis=None):
    """Compute the cumulative product along the given axis.

    Parameters
    ----------
    x : Tensor
        The input tensor.
    axis : int
        The axis to sum. Default is ``None`` (Along all axes).

    """
    raise NotImplementedError()


def normalize_dihedral(d):
    """ Normalize any number to the range (-180, 180], including 180 """
    return d + (180 - d) // 360 * 360


def set_prefs(prefs):
    """This function is called before opening the project"""
    prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', '.hg',
        '.svn', '_svn', '.git', '__pycache__', '.tox', '.env',
        'node_modules', 'bower_components']
    prefs['save_objectdb'] = True
    prefs['compress_objectdb'] = False
    prefs['automatic_soa'] = True
    prefs['soa_followed_calls'] = 0
    prefs['perform_doa'] = True
    prefs['validate_objectdb'] = True
    prefs['max_history_items'] = 32
    prefs['save_history'] = True
    prefs['compress_history'] = False
    prefs['indent_size'] = 4
    prefs['extension_modules'] = []
    prefs['import_dynload_stdmods'] = True
    prefs['ignore_syntax_errors'] = False
    prefs['ignore_bad_imports'] = False


def load_reference_image(filepath: str='', filter_image: bool=True,
    filter_folder: bool=True, view_align: bool=True):
    """Add a reference image into the scene between objects

    :param filepath: filepath
    :type filepath: str
    :param filter_image: filter_image
    :type filter_image: bool
    :param filter_folder: filter_folder
    :type filter_folder: bool
    :param view_align: Align to view
    :type view_align: bool
    """
    pass


def group_by_signature(r):
    """Grouping function for ``PairTransformer``.

    Parameters
    ----------
    :param r: iterable
        signature in a singleton.

    Returns
    -------
    :returns: string
        Signature id
    """
    return r[0]['signature_id']


def compute_same_padding_size(kernel_length: int) ->(int, int):
    """
    Computes padding for 'same' padding *per* dimension given

    :param kernel_length: int Kernel size
    :returns: Tuple -- (padStart, padStop) , padding on left/right or top/bottom

    Note : Only works for stride 1
    """
    start = kernel_length // 2
    stop = start - 1 if kernel_length % 2 == 0 else start
    return start, stop


def url():
    """Give the URL of the object.
        """


def select_mirror(extend: bool=False):
    """Select the Mirror objects of the selected object eg. L.sword -> R.sword

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    """
    pass


def mtf_ts_to_dataframe(tan, sag, freqs, field=0, focus=0):
    """Create a Pandas dataframe from tangential and sagittal MTF data.

    Parameters
    ----------
    tan : `numpy.ndarray`
        vector of tangential MTF data
    sag : `numpy.ndarray`
        vector of sagittal MTF data
    freqs : iterable
        vector of spatial frequencies for the data
    field : `float`
        relative field associated with the data
    focus : `float`
        focus offset (um) associated with the data

    Returns
    -------
    pandas dataframe.

    """
    import pandas as pd
    rows = []
    for f, t, s in zip(freqs, tan, sag):
        base_dict = {'Field': field, 'Focus': focus, 'Freq': f}
        rows.append({**base_dict, **{'Azimuth': 'Tan', 'MTF': t}})
        rows.append({**base_dict, **{'Azimuth': 'Sag', 'MTF': s}})
    return pd.DataFrame(data=rows)


def _one_iteration():
    """The work done in one iteration of the main loop.

        Can be overridden by subclasses.

        :return: The number of files still left to process.
        :rtype: int
        """


@staticmethod
def invert_y(z, y):
    """
        Return the inverted Y value of the tile

        z -- zoom level
        """
    if z == 0:
        return 0
    else:
        return (1 << z - 1) - y - 1


@classmethod
def get_from_string(cls, string_phase):
    """
        Convert string value obtained from k8s API to PodPhase enum value
        :param string_phase: str, phase value from Kubernetes API
        :return: PodPhase
        """
    if string_phase == 'Pending':
        return cls.PENDING
    elif string_phase == 'Running':
        return cls.RUNNING
    elif string_phase == 'Succeeded':
        return cls.SUCCEEDED
    elif string_phase == 'Failed':
        return cls.FAILED
    elif string_phase == 'Unknown':
        return cls.UNKNOWN
    return cls.UNKNOWN


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 render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

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

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


@classmethod
def _normalize_options(cls, options: list, input_type: str):
    """
        Takes the list passed as options and returns a dictionary enumerating
        all the options, i.e. if we pass ['option_1', 'options_2'], then we
        return {'1': 'option_1', '2': 'option_2'}
        """
    normalized_options = {}
    if options is not None:
        if input_type == cls.BOOL:
            if len(options) < 2:
                options = ['True', 'False']
            else:
                options = options[:2]
        elif len(options) < 2:
            raise ValueError("'options' must contain at least two items")
    else:
        options = ['True', 'False'] if input_type == cls.BOOL else []
    for option in range(len(options)):
        normalized_options[str(option + 1)] = str(options[option])
    return normalized_options


def add_log_arguments(parser, level=None):
    """
    Adds command line arguments to control logging behaviour.

    :param parser: The argparse.ArgumentParser object to add to.
    :param level: the default log level if not given as command line parameter. defaults to None which means no logging
    """
    parser.add_argument('--log', action='store', dest='loglevel', default=
        level, help='Set the log level of the script', choices=['DEBUG',
        'INFO', 'WARNING', 'ERROR', 'CRITICAL'])


def variance_features_query(table_name='%(table_name)s'):
    """
    Create variance features which are part of the final feature set.
    For all ratio variables (outgoing over incoming of calls, sms and
    call volume in seconds) the variance over all weeks is being
    calculated. This feature tries to capture the volatility of the
    relation between outgoing and incoming traffic over time.

    Inputs
    ------
    table_name : name of the table the query is supposed to run on,
                 defaulting to '%(table_name)s', i.e. no substitution

    Output
    ------
    Partial final features dataframe which holds features
    calculated over the variance over weekly ratios.
    """
    query = """
        SELECT
          antenna_id,
          -- variance over these ratios
          VARIANCE(calls_ratio) as calls_ratio_var,
          VARIANCE(sms_ratio) as sms_ratio_var,
          VARIANCE(vol_ratio) as vol_ratio_var
        FROM
        (
          SELECT
            antenna_id,
            week_number,
            -- ratios per week
            SUM(og_calls)/SUM(ic_calls) as calls_ratio,
            SUM(og_sms)/SUM(ic_sms) as sms_ratio,
            SUM(og_vol)/SUM(ic_vol) as vol_ratio
          FROM %(table_name)s
          GROUP BY antenna_id, week_number
        )
        GROUP BY antenna_id
    """
    return query % {'table_name': table_name}


def classdot2func(path):
    """ Convert a path such as 'android.support.v4.app.ActivityCompat'
        into a method string 'CLASS_Landroid_support_v4_app_ActivityCompat'
        so we can call d.CLASS_Landroid_support_v4_app_ActivityCompat.get_source()
    """
    func = 'CLASS_L' + path.replace('.', '_').replace('$', '_')
    return func


def fv_multi(formname, *pairs):
    """
    >> fv_multi <formname> [ <pair1> [ <pair2> [ <pair3> ]]]

    Set multiple form fields; each pair should be of the form

        fieldname=value

    The pair will be split around the first '=', and
    'fv <formname> fieldname value' will be executed in the order the
    pairs are given.
    """
    from twill import commands
    for p in pairs:
        fieldname, value = p.split('=', 1)
        commands.fv(formname, fieldname, value)


def set_contract_backend(backend):
    """Set the default backend used for tensor contractions, via 'opt_einsum'.

    See Also
    --------
    get_contract_backend, set_tensor_linop_backend, get_tensor_linop_backend,
    tensor_contract
    """
    global _CONTRACT_BACKEND
    _CONTRACT_BACKEND = backend


def get_all(isamAppliance, kdb_id, check_mode=False, force=False):
    """
    Retrieving signer certificate names and details in a certificate database
    """
    return isamAppliance.invoke_get(
        'Retrieving signer certificate names and details in a certificate database'
        , '/isam/ssl_certificates/{0}/signer_cert'.format(kdb_id))


def dr(prox_f, prox_g, dim, gamma=1, rho=1, Z0=None, tol=None):
    """
    Douglas-Rachford proximal splitting algorithm with two proximal
    mappings as inputs

    DR(prox_f,prox_g,dim) runs the Douglas-Rachford splitting algorithm for the objective function
    f + g, where:
        1. prox_f(Z,gamma) and prox_g(Z,gamma) are funcionts that derive the proximal mappings of
        gamma*f and gamma*g evalutaed in Z.
        2. dim is the dimension of the output of f and g.

    Note: If f and g are convex, then X = argmin(f(X) + g(X)).

    X,Z_fix,iter,D = DR(prox_f,prox_g,dim) returns:
        1. Solution X
        2. Z_fix = fix point of that Douglas-Rachford iterations
        3. iter = total number of Douglas-Rachford iterations
        4. D = Z_fix - X, which is the solution of the dual problem if f
        and g are convex.

    ... = DR(prox_f,prox_g,dim,option) allows to specify further options:
        1. ... = DR(prox_f,prox_g,dim,...,rho = rho_val,...) set the step
        length update of the fix-point update, i.e.,
        Z_{k+1} = Z_k + rho*(Y_k - X_k), where 0 < rho < 2.
        The default value is rho = 1.
        2. ... = DR(prox_f,prox_g,dim,...,gamma = gamma_val,...) sets gamma
        to another value than the default gamma = 1.
        3. ... = DR(prox_f,prox_g,dim,...,Z0 = Z0_val,...) sets the
        initial value of the fix-point iteration.
        The default choice is Z0 = 0.
        4. ... = DR(prox_f,prox_g,dim,...,tol=tol_val,...)
        sets the tolerance for zero entries as well as to stop the
        iteratrions once norm(Y_k-X_k,'fro') < tol
        The default tol-value is sqrt(eps).
    """
    import numpy as np
    if Z0 is None:
        Z = np.zeros(dim)
    else:
        Z = Z0
    if tol is None:
        tol = np.sqrt(np.finfo(float).eps)
    iter = 0
    X = np.zeros(dim)
    Y = np.zeros(dim)
    err_XY = tol + 1
    err_bound = 0.1
    while err_XY >= tol:
        iter += 1
        if err_XY <= err_bound:
            print('Error between X_' + str(iter) + ' and ' + 'Y_' + str(
                iter) + ' <= ' + str(err_bound))
            err_bound /= 10
        X = prox_f(Z=Z, gamma=gamma)
        if isinstance(X, tuple):
            X = X[0]
        Y = prox_g(Z=2 * X - Z, gamma=gamma)
        if isinstance(Y, tuple):
            Y = Y[0]
        Z = Z + rho * (Y - X)
        err_XY = np.linalg.norm(X - Y, ord='fro')
    X = Y
    D = (Z - X) / gamma
    Z[np.absolute(Z) < 0] = 0
    if iter > 0:
        Z_fix = Z
    else:
        Z_fix = X
    X[np.absolute(X) < tol] = 0
    return X, Z_fix, iter, D


def _repr_svg_(shp):
    """SVG representation for iPython notebook"""
    svg_top = (
        '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" '
        )
    if shp.is_empty:
        return svg_top + '/>'
    else:
        xmin, ymin, xmax, ymax = shp.bounds
        if xmin == xmax and ymin == ymax:
            xmin, ymin, xmax, ymax = shp.buffer(1).bounds
        else:
            expand = 0.04
            widest_part = max([xmax - xmin, ymax - ymin])
            expand_amount = widest_part * expand
            xmin -= expand_amount
            ymin -= expand_amount
            xmax += expand_amount
            ymax += expand_amount
        dx = xmax - xmin
        dy = ymax - ymin
        width = min([max([100.0, dx]), 300])
        height = min([max([100.0, dy]), 300])
        try:
            scale_factor = max([dx, dy]) / max([width, height])
        except ZeroDivisionError:
            scale_factor = 1.0
        view_box = '{0} {1} {2} {3}'.format(xmin, ymin, dx, dy)
        transform = 'matrix(1,0,0,-1,0,{0})'.format(ymax + ymin)
        svg_templ = (svg_top +
            'width="{1}" height="{2}" viewBox="{0}" preserveAspectRatio="# XXX: MinYMin meet"><g transform="{3}">'
            .format(view_box, width, height, transform))
        return scale_factor, svg_templ + '{0}</g></svg>'


def get_unused_var_name(prefix, var_table):
    """ Get a new var name with a given prefix and
        make sure it is unused in the given variable table.
    """
    cur = 0
    while True:
        var = prefix + str(cur)
        if var not in var_table:
            return var
        cur += 1


def empty_if_none(_string, _source=None):
    """If _source if None, return an empty string, otherwise return string.
    This is useful when you build strings and want it to be empty if you don't have any data.
    For example when building a comma-separated string with a dynamic number of parameters:
    .. code-block:: python

    command = (_id +";" +  +  empty_if_none(";"+str(_comment), _comment))
    """
    if _source is None:
        return ''
    else:
        return str(_string)


@conf
def gcc_modifier_win32(conf):
    """Configuration flags for executing gcc on Windows"""
    v = conf.env
    v.cprogram_PATTERN = '%s.exe'
    v.cshlib_PATTERN = '%s.dll'
    v.implib_PATTERN = '%s.dll.a'
    v.IMPLIB_ST = '-Wl,--out-implib,%s'
    v.CFLAGS_cshlib = []
    v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import'])


def item_list(items):
    """Generate normal-text version of list of items, with commas and "and" as needed."""
    return ' and '.join(', '.join(items).rsplit(', ', 1))


@staticmethod
def toggle_all_outputs(ramp):
    """Generate a command that toggles all output-ports.

        Toggle mode: (on->off, off->on).

        :param    int    ramp:    Ramp value
        :return:    The PCK command (without address header) as text
        :rtype:    str
        """
    return 'AU{:03d}'.format(ramp)


def _is_file_like(obj):
    """
    Checks if an object is file-like enough to be sent to requests.

    In particular, file, StringIO and cStringIO objects are file-like.
    Refs http://stackoverflow.com/questions/3450857/python-determining-if-an-object-is-file-like
    """
    return hasattr(obj, 'read') and hasattr(obj, 'seek')


@classmethod
def handle_cursor(cls, cursor, query, session):
    """Handle a live cursor between the execute and fetchall calls

        The flow works without this method doing anything, but it allows
        for handling the cursor and updating progress information in the
        query object"""
    pass


def getdispatchrepo(repo, proto, command):
    """Obtain the repo used for processing wire protocol commands.

    The intent of this function is to serve as a monkeypatch point for
    extensions that need commands to operate on different repo views under
    specialized circumstances.
    """
    viewconfig = repo.ui.config(b'server', b'view')
    return repo.filtered(viewconfig)


@staticmethod
def mm_to_px(measure):
    """Convert millimeters to pixel."""
    return measure * 3.779527559


def limit(min, max, v):
    """limits the range of v between min and max
    """
    if min > max:
        raise RuntimeError('Min value (%f) larger than max (%f)' % (min, max))
    if v < min:
        return min
    elif v < max:
        return v
    else:
        return max


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

        :param AllowDownloadEnabledDetails val:
        :rtype: EventDetails
        """
    return cls('allow_download_enabled_details', val)


def sequence(value):
    """Return tuple containing value if value is not a sequence.

    >>> sequence(1)
    (1,)
    >>> sequence([1])
    [1]

    """
    try:
        len(value)
        return value
    except TypeError:
        return value,


@classmethod
def get_from_string(cls, msgctxt):
    """
        Looks for the SegmentTranslationContext that the given string represents.
        """
    object_id, path = msgctxt.split(':')
    path_id = cls.get_path_id(path)
    return cls.objects.get(object_id=object_id, path_id=path_id)