def linint(arr, x):
    """Interpolate an (X, Y) array linearly."""
    for v in arr:
        if v[0] == x:
            return v[1]
    xvals = [v[0] for v in arr]
    ux = max(xvals)
    lx = min(xvals)
    try:
        assert lx <= x <= ux
    except:
        raise
    for v in arr:
        if v[0] > x and v[0] - x <= ux - x:
            ux = v[0]
            uy = v[1]
        if v[0] < x and x - v[0] >= lx - x:
            lx = v[0]
            ly = v[1]
    return (float(x) - lx) / (ux - lx) * (uy - ly) + ly


@classmethod
def _add_ckan_admin_tabs(cls, config, route_name, tab_label, config_var=
    'ckan.admin_tabs'):
    """
        Update 'ckan.admin_tabs' dict the passed config dict.
        """
    admin_tabs_dict = config.get(config_var, {})
    admin_tabs_dict.update({route_name: tab_label})
    config.update({config_var: admin_tabs_dict})


def strip_namespace(obj):
    """
    Returns the given object name after striping the namespace
    :param obj: str, object to strip namespace from
    :return: str
    """
    return obj.split(':')[-1]


def zf(s):
    """
    Number digit with a '0'
    """
    s = str(s)
    if len(s) == 1:
        return '0' + s
    else:
        return s


@staticmethod
def never(src, dst, fn):
    """Never overwrite files on conflict."""
    return False


ttwidgets//ttwidgets - Copy (2).pyclass:TTWidget/fromwidgetclass

@classmethod
def fromwidgetclass(cls, widget_class, **kw):
    """Create a new TTWidget based on WIDGET_CLASS."""
    obj = cls(None, None, widget_class, **kw)
    return obj


def _pam_from_attrs(klass, sphere, peak_indices, peak_values, peak_dirs,
    gfa, qa, shm_coeff, B, odf):
    """
    Construct PeaksAndMetrics object (or subclass) from its attributes.

    This is also useful for pickling/unpickling of these objects (see also
    :func:`__reduce__` below).

    Parameters
    ----------
    klass : class
        The class of object to be created.
    sphere : `Sphere` class instance.
        Sphere for discretization.
    peak_indices : ndarray
        Indices (in sphere vertices) of the peaks in each voxel.
    peak_values : ndarray
        The value of the peaks.
    peak_dirs : ndarray
        The direction of each peak.
    gfa : ndarray
        The Generalized Fractional Anisotropy in each voxel.
    qa : ndarray
        Quantitative Anisotropy in each voxel.
    shm_coeff : ndarray
        The coefficients of the spherical harmonic basis for the ODF in
        each voxel.
    B : ndarray
        The spherical harmonic matrix, for multiplication with the
        coefficients.
    odf : ndarray
        The orientation distribution function on the sphere in each voxel.

    Returns
    -------
    pam : Instance of the class `klass`.
    """
    this_pam = klass()
    this_pam.sphere = sphere
    this_pam.peak_dirs = peak_dirs
    this_pam.peak_values = peak_values
    this_pam.peak_indices = peak_indices
    this_pam.gfa = gfa
    this_pam.qa = qa
    this_pam.shm_coeff = shm_coeff
    this_pam.B = B
    this_pam.odf = odf
    return this_pam


def _link_to_json(value):
    """Returns a list representation of the specified HTTP Link header
    information.

    `value` is a string containing the link header information. If the link
    header information (the part of after ``Link:``) looked like this::

        <url1>; rel="next", <url2>; rel="foo"; bar="baz"

    then this function returns a list that looks like this::

        [{"url": "url1", "rel": "next"},
         {"url": "url2", "rel": "foo", "bar": "baz"}]

    This example is adapted from the documentation of GitHub's API.

    """
    links = []
    replace_chars = ' \'"'
    for val in value.split(','):
        try:
            url, params = val.split(';', 1)
        except ValueError:
            url, params = val, ''
        link = {}
        link['url'] = url.strip('<> \'"')
        for param in params.split(';'):
            try:
                key, value = param.split('=')
            except ValueError:
                break
            link[key.strip(replace_chars)] = value.strip(replace_chars)
        links.append(link)
    return links


def p_builtin_variable(p):
    """
    variable : BUILTIN NAME
    variable : BUILTIN COUNT NAME
    """
    if len(p) == 3:
        p[0] = '_BUILTIN', (p[2], p[1])
    elif len(p) == 4:
        p[0] = '_BUILTIN', (p[3], str(p[2]) + p[1])


def get_m2m_fields_for(instance=None):
    """gets m2mfields for instance"""
    return instance._meta._many_to_many()


@classmethod
def get_short(cls, name):
    """ Returns the short name of a Maya asset name or path

        :param name: str, string that represents a possible name of an object
        :return: str, the short name of the maya node
        """
    return name.split('|')[-1].split('//')[-1]


def delete(mlist):
    """Remove the mailing list from the database.

        :param mlist: The mailing list to delete.
        :type mlist: `IMailingList`
        """


@classmethod
def create(cls, fqdn, flags, algorithm, public_key):
    """Create a dnssec key."""
    fqdn = fqdn.lower()
    params = {'flags': flags, 'algorithm': algorithm, 'public_key': public_key}
    result = cls.call('domain.dnssec.create', fqdn, params)
    return result


def _safe_set(input_):
    """Safely returns a set from input"""
    return {input_} if isinstance(input_, str) else set(input_)


def add_filter_args(diff_parser):
    """Adds configuration for git commands where filter use is flagged"""
    diff_parser.add_argument('--use-filter', action='store_true', default=
        False, help='apply any configured git filters on remote')


def get_modelseed_comps(kb_db, model_ids):
    """Get MongoIDs from KBase database for compounds in model(s)."""
    comp_ids, _ids = set(), set()
    for model_id in model_ids:
        comp_ids = kb_db.models.find_one({'_id': model_id}, {'Compounds': 1})[
            'Compounds']
        for comp_id in comp_ids:
            comp_ids.add(comp_id)
    for comp_id in comp_ids:
        comp_id = int(comp_id.split('.')[1])
        for comp in kb_db.compounds.find({'Model_SEED': comp_id}, {'_id': 1}):
            _ids.add(comp['_id'])
    return _ids


def get_conf(*args):
    """
        Returns one or many configuration values via Deferred. See
        control-spec for valid keys. The value will be a dictionary.
        """


def pretty_docs(wrapped, extradocs=None, name=None):
    """
    Modify wrapped, so that it 'looks' like what it's wrapping.

    This is primarily useful for introspection reasons- doc generators, direct
    user interaction with an object in the interpretter, etc.

    :param wrapped: functor to modify
    :param extradocs: ``__doc__`` override for wrapped; else it pulls from
        wrapped's target functor
    :param name: ``__name__`` override for wrapped; else it pulls from
        wrapped's target functor for the name.
    """
    wrapped.__module__ = wrapped.func.__module__
    doc = wrapped.func.__doc__
    if extradocs is None:
        wrapped.__doc__ = doc
    else:
        wrapped.__doc__ = extradocs
    if name:
        wrapped.__name__ = name
    return wrapped


def getValuesInInterval(dataTupleList, start, stop):
    """
    Gets the values that exist within an interval

    The function assumes that the data is formated as
    [(t1, v1a, v1b, ...), (t2, v2a, v2b, ...)]
    """
    intervalDataList = []
    for dataTuple in dataTupleList:
        time = dataTuple[0]
        if start <= time and stop >= time:
            intervalDataList.append(dataTuple)
    return intervalDataList


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


def padded_len(s):
    """Length of a (byte)string rounded up to the nearest multiple of 8."""
    return 8 * ((len(s) + 7) // 8)


def findRelationshipTokens(source, maxDepth=1, filter=None):
    """As findRelationships, but returns tokens rather than the objects"""


def fallback_renders(template_content, *args, **kwargs):
    """
    Render given template string `template_content`.

    This is a basic implementation actually does nothing and just returns
    original template content `template_content`.

    :param template_content: Template content
    :params args:
        List of arguments like context, a dict or dict-like object to
        instantiate given template file
    :param kwargs: Keyword arguments such as:
        - at_paths: Template search paths
        - at_encoding: Template encoding
        - kwargs: Optional keyword arguments passed to the template engine to
          render templates with specific features enabled.

    :return: Rendered result string
    """
    return template_content


def format_dna(dna, width=80):
    """
    Format dna so each line is a fixed width.

    Parameters
    ----------
    dna : str
        dna sequence.
    width : int, optional
        Width of dna in chars. Default is 80.
    """
    ret = ''
    n = len(dna)
    for s in range(0, n, width):
        e = s + width
        if e > n:
            e = n
        ret += dna[s:e] + '\n'
    return ret


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

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

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


def partially_tracked(df, track_ratios):
    """Number of objects tracked between 20 and 80 percent of lifespan."""
    del df
    return track_ratios[(track_ratios >= 0.2) & (track_ratios < 0.8)].count()


@classmethod
def make_static_url(cls, settings, path):
    """Constructs a versioned url for the given path.

        This method may be overridden in subclasses (but note that it is
        a class method rather than an instance method).

        ``settings`` is the `Application.settings` dictionary.  ``path``
        is the static path being requested.  The url returned should be
        relative to the current host.
        """
    static_url_prefix = settings.get('static_url_prefix', '/static/')
    version_hash = cls.get_version(settings, path)
    if version_hash:
        return '%s%s?v=%s' % (static_url_prefix, path, version_hash)
    return '%s%s' % (static_url_prefix, path)


def _pandas_rolling_since_018(df, window, *args, **kwargs):
    """Use rolling() to compute a rolling average"""
    return df.rolling(window, *args, **kwargs).mean()


def has_permission(permission, context, request):
    """
    A function that calls :meth:`pyramid.request.Request.has_permission`
    and returns its result.

    .. deprecated:: 1.5
        Use :meth:`pyramid.request.Request.has_permission` instead.

    .. versionchanged:: 1.5a3
        If context is None, then attempt to use the context attribute of self;
        if not set, then the AttributeError is propagated.
    """
    return request.has_permission(permission, context)


@classmethod
def exception(cls, message, exception=None):
    """
        Logs an exception with level ERROR on this logger
        :param message: Log record content
        :type message: str
        :param exception: Exception instance
        :type exception: Exception
        """
    cls.log('ERROR', message, exception=exception)


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


def _default_interface():
    """Return the default interface name for common operating systems."""
    import platform
    system = platform.system()
    if system == 'Linux':
        return 'eth0'
    elif system == 'Darwin':
        return 'en0'
    return None


def median(iterable, sort=True):
    """ Returns the value that separates the lower half from the higher half of values in the list.
    """
    s = sorted(iterable) if sort is True else list(iterable)
    n = len(s)
    if n == 0:
        raise ValueError('median() arg is an empty sequence')
    if n % 2 == 0:
        return float(s[n // 2 - 1] + s[n // 2]) / 2
    return s[n // 2]


@classmethod
def load(cls, file_path, unflatten=True):
    """Load the data all at once (classmethod).

        # Arguments
            file_path: HDF5 file path
            unflatten: see `load_all`
        """
    with cls(file_path) as f:
        return f.load_all(unflatten=unflatten)


def modify_mount_target_security_groups(MountTargetId=None, SecurityGroups=None
    ):
    """
    Modifies the set of security groups in effect for a mount target.
    When you create a mount target, Amazon EFS also creates a new network interface. For more information, see  CreateMountTarget . This operation replaces the security groups in effect for the network interface associated with a mount target, with the SecurityGroups provided in the request. This operation requires that the network interface of the mount target has been created and the lifecycle state of the mount target is not deleted .
    The operation requires permissions for the following actions:
    See also: AWS API Documentation

    Examples
    This operation modifies the security groups associated with a mount target for a file system.
    Expected Output:

    :example: response = client.modify_mount_target_security_groups(
        MountTargetId='string',
        SecurityGroups=[
            'string',
        ]
    )

    :type MountTargetId: string
    :param MountTargetId: [REQUIRED]
            ID of the mount target whose security groups you want to modify.

    :type SecurityGroups: list
    :param SecurityGroups: Array of up to five VPC security group IDs.
            (string) --

    :return: response = client.modify_mount_target_security_groups(
        MountTargetId='fsmt-12340abc',
        SecurityGroups=[
            'sg-abcd1234',
        ],
    )

    print(response)

    :returns:
    MountTargetId (string) -- [REQUIRED]
    ID of the mount target whose security groups you want to modify.

    SecurityGroups (list) -- Array of up to five VPC security group IDs.

    (string) --

    """
    pass


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


def permission_id(name):
    """
        Return the permission used to check attribute access on *name*.

        This permission is used by both :meth:`check` and :meth:`check_getattr`.
        """


def get_quality_by_depth(var):
    """
    Returns the quality by depth or the variant confidence,
    or None if it isn't present in the VCF.
    """
    return var.INFO.get('QD')


def flush_log(console):
    """Flush console output log buffer.

    Console output is written to the log when end of line is reached. Call this
    function when you want to log the latest console output but the end of the
    last line has not been reached yet.

    .. note::

       In order to support this operation the
       :py:attr:`pexpect:pexpect.spawn.logfile_read` console attribute must be
       set to :py:class:`alpy.pexpect_log.LogfileRead` instance. The console
       objects returned by :py:func:`alpy.console.create` and
       :py:func:`alpy.console.connect` functions are configured in this way.

    :param console: console object
    :type console: :py:class:`pexpect:pexpect.spawn` - like class
    """
    console.logfile_read.log_remaining_text()


def select(extend: bool=False, fill: bool=False, open: bool=True):
    """Activate/select file

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    :param fill: Fill, Select everything beginning with the last selection
    :type fill: bool
    :param open: Open, Open a directory when selecting it
    :type open: bool
    """
    pass


def getStyleSheet():
    """
    Get style sheet from stylesheet.txt
    :return: styesheet (str) or empty string if it's not available
    """
    return ''
    return (
        'QToolTip{     border: 1px solid black;     background-color: #ffa02f;     padding: 1px;     border-radius: 3px;     opacity: 100;} QWidget {    color: #cecece;    background-color: #323232; }QWidget:item:selected{    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);}QMenuBar::item{    background: transparent;}QMenuBar::item:selected{    background: transparent;    border: 1px solid #ffaa00;}QMenuBar::item:pressed{    background: #6d6d6d;    border: 1px solid #000;    background-color: QLinearGradient(        x1:0, y1:0,        x2:0, y2:1,        stop:1 #212121,        stop:0.4 #343434/*,        stop:0.2 #343434,        stop:0.1 #ffaa00*/    );    margin-bottom:-1px;    padding-bottom:1px;}QMenu{    border: 1px solid #000;}QMenu::item{    padding: 2px 20px 2px 20px;}QMenu::item:selected{    color: #000000;}QWidget:disabled{    color: #777676;    background-color: #323232;}QAbstractItemView{    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0.1 #646464, stop: 1 #5d5d5d);}QLineEdit{    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);    padding: 1px;    border-style: solid;    border: 1px solid #1e1e1e;    border-radius: 5;}QPushButton{    color: #cecece;    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);    border-width: 1px;    border-color: #1e1e1e;    border-style: solid;    border-radius: 6;    padding: 3px;    font-size: 12px;    padding-left: 5px;    padding-right: 5px; height: 15px;}QPushButton:pressed{    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);}QPushButton:checked{    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);}QComboBox{    color: #ffffff; selection-background-color: #ffaa00;    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);    border-style: solid;    border: 1px solid #1e1e1e;    border-radius: 5;}QComboBox:hover,QPushButton:hover{    border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #51300a);}QComboBox:on{    padding-top: 3px;    padding-left: 4px;    background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);    selection-background-color: #ffaa00;}QComboBox QAbstractItemView{    border: 2px solid darkgray;    selection-background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);}QComboBox::drop-down{     subcontrol-origin: padding;     subcontrol-position: top right;     width: 15px;     border-left-width: 0px;     border-left-color: darkgray;     border-left-style: solid; /* just a single line */     border-top-right-radius: 2px; /* same radius as the QComboBox */     border-bottom-right-radius: 2px; }QGroupBox { border: 1px solid gray; border-radius: 2px; margin-top: 1ex; }QGroupBox::indicator{    color: #cecece;    background-color: #323232;    border: 1px solid #cecece;    width: 9px;    height: 9px;}QGroupBox::indicator:disabled, QRadioButton::indicator:disabled{    border: 1px solid #6d6d6d;}QGroupBox::indicator:checked{    background-color: #f77213;}QGroupBox::title { background-color: #323232 ; subcontrol-origin: margin; subcontrol-position: top center; padding: 0 3px; }QTextEdit:focus{    border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);}QScrollBar:horizontal {     border: 1px solid #222222;     background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);     height: 7px;     margin: 0px 16px 0 16px;}QScrollBar::handle:horizontal{      background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);      min-height: 20px;      border-radius: 2px;}QScrollBar::add-line:horizontal {      border: 1px solid #1b1b19;      border-radius: 2px;      background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);      width: 14px;      subcontrol-position: right;      subcontrol-origin: margin;}QScrollBar::sub-line:horizontal {      border: 1px solid #1b1b19;      border-radius: 2px;      background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);      width: 14px;     subcontrol-position: left;     subcontrol-origin: margin;}QScrollBar::right-arrow:horizontal, QScrollBar::left-arrow:horizontal{      border: 1px solid black;      width: 1px;      height: 1px;      background: white;}QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal{      background: none;}QScrollBar:vertical{      background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);      width: 7px;      margin: 16px 0 16px 0;      border: 1px solid #222222;}QScrollBar::handle:vertical{      background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);      min-height: 20px;      border-radius: 2px;}QScrollBar::add-line:vertical{      border: 1px solid #1b1b19;      border-radius: 2px;      background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);      height: 14px;      subcontrol-position: bottom;      subcontrol-origin: margin;}QScrollBar::sub-line:vertical{      border: 1px solid #1b1b19;      border-radius: 2px;      background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d7801a, stop: 1 #ffa02f);      height: 14px;      subcontrol-position: top;      subcontrol-origin: margin;}QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical{      border: 1px solid black;      width: 1px;      height: 1px;      background: white;}QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical{      background: none;}QTextEdit{    background-color: #242424;}QPlainTextEdit{    background-color: #242424;}QHeaderView::section{    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565);    color: white;    padding-left: 4px;    border: 1px solid #6c6c6c;}QCheckBox:disabled{ color: #414141;}QDockWidget::title{    text-align: center;    spacing: 3px; /* spacing between items in the tool bar */    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);}QDockWidget::close-button, QDockWidget::float-button{    text-align: center;    spacing: 1px; /* spacing between items in the tool bar */    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);}QDockWidget::close-button:hover, QDockWidget::float-button:hover{    background: #242424;}QDockWidget::close-button:pressed, QDockWidget::float-button:pressed{    padding: 1px -1px -1px 1px;}QMainWindow::separator{    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);    color: white;    padding-left: 4px;    border: 1px solid #4c4c4c;    spacing: 3px; /* spacing between items in the tool bar */}QMainWindow::separator:hover{    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d7801a, stop:0.5 #b56c17 stop:1 #ffa02f);    color: white;    padding-left: 4px;    border: 1px solid #6c6c6c;    spacing: 3px; /* spacing between items in the tool bar */}QMenu::separator{    height: 2px;    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);    color: white;    padding-left: 4px;    margin-left: 10px;    margin-right: 5px;}QProgressBar{    border: 2px solid grey;    border-radius: 5px;    text-align: center;}QProgressBar::chunk{    background-color: #d7801a;    width: 2.15px;    margin: 0.5px;}QTabBar::tab {    color: #cecece;    border: 1px solid #6d6d6d;    border-bottom-style: none;    background-color: #323232;    padding-left: 10px;    padding-right: 10px;    padding-top: 3px;    padding-bottom: 2px;    margin-right: -1px;}QTabWidget::pane {    border: 1px solid #6d6d6d;    top: 1px;}QTabBar::tab:last{    margin-right: 0; /* the last selected tab has nothing to overlap with on the right */    border-top-right-radius: 3px;}QTabBar::tab:first:!selected{ margin-left: 0px; /* the last selected tab has nothing to overlap with on the right */    border-top-left-radius: 3px;}QTabBar::tab:!selected{    color: #cecece;    border-bottom-style: solid;    margin-top: 3px;    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);}QTabBar::tab:selected{    border-top-left-radius: 3px;    border-top-right-radius: 3px;    margin-bottom: 0px;}QTabBar::tab:!selected:hover{    /*border-top: 2px solid #ffaa00;    padding-bottom: 3px;*/    border-top-left-radius: 3px;    border-top-right-radius: 3px;    background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);}QRadioButton::indicator:checked, QRadioButton::indicator:unchecked{    color: #cecece;    background-color: #323232;    border: 1px solid #cecece;    border-radius: 6px;}QRadioButton::indicator:checked{    background-color: qradialgradient(        cx: 0.5, cy: 0.5,        fx: 0.5, fy: 0.5,        radius: 1.0,        stop: 0.25 #ffaa00,        stop: 0.3 #323232    );}QRadioButton::indicator{border-radius: 6px;}QRadioButton::indicator:hover, QCheckBox::indicator:hover{    border: 1px solid #ffaa00;}QCheckBox::indicator{    color: #cecece;    background-color: #323232;    border: 1px solid #cecece;    width: 9px;    height: 9px;}QCheckBox{ width: 20px; }QCheckBox::indicator:disabled, QRadioButton::indicator:disabled{    border: 1px solid #6d6d6d;}QCheckBox::indicator:checked{    background-color: #f77213;}'
        )


def selector(zelf, *args, **kwargs):
    """ see if this things has the desired attributes. """
    wanted = args[0]
    if not wanted:
        return False
    go = False
    for arg in wanted:
        if arg in zelf and zelf[arg]:
            go = True
            break
    return go


def botAuthAction(bot, dbAction):
    """
  After bot auth success,
  can do some bot actions
  default: do nothing
  """
    return


def resolve(name):
    """Given a dotted name, returns an object imported from a Python module."""
    name = name.split('.')
    used = name.pop(0)
    found = __import__(used)
    for n in name:
        used += '.' + n
        try:
            found = getattr(found, n)
        except AttributeError:
            __import__(used)
            found = getattr(found, n)
    return found


def getitems(dictionary, *keys):
    """
    Get existing items of a dict lazy

    >>> d = {"henk": 1, "klaas": 2, "hent": 7}
    >>> r = getitems(d, "klaas")
    >>> list(r)
    [2]
    >>> r = getitems(d, "henk", "hent")
    >>> list(r)
    [1, 7]
    >>> r = getitems(d, "henk", "kak")
    >>> list(r)
    [1, None]
    """
    for key in keys:
        yield dictionary.get(key)


def one_dec_places(x, pos):
    """
    Adds 1/10th decimal to plot ticks.
    """
    return '%.1f' % x


def min_edit_distance_align(source, target, ins_cost=lambda _x: 1, del_cost
    =lambda _x: 1, sub_cost=lambda x, y: 0 if x == y else 1):
    """Finds a minimum cost alignment between two strings.

    Uses the Levenshtein weighting as a default, but offers keyword arguments
    to supply functions to measure the costs for editing with different
    characters. Note that the alignment may not be unique.

    Args:
        ins_cost: A function describing the cost of inserting a given char
        del_cost: A function describing the cost of deleting a given char
        sub_cost: A function describing the cost of substituting one char for

    Returns:
        A sequence of tuples representing character level alignments between
        the source and target strings.
    """
    n = len(target)
    m = len(source)
    dist = [([0] * (n + 1)) for _ in range(m + 1)]
    bptrs = [([[]] * (n + 1)) for _ in range(m + 1)]
    for i in range(1, m + 1):
        dist[i][0] = i
        bptrs[i][0] = i - 1, 0
    for j in range(1, n + 1):
        dist[0][j] = j
        bptrs[0][j] = 0, j - 1
    for j in range(1, n + 1):
        for i in range(1, m + 1):
            options = [(dist[i - 1][j] + ins_cost(target[j - 1]), (i - 1, j
                )), (dist[i - 1][j - 1] + sub_cost(source[i - 1], target[j -
                1]), (i - 1, j - 1)), (dist[i][j - 1] + del_cost(source[i -
                1]), (i, j - 1))]
            minimum, pointer = sorted(options)[0]
            dist[i][j] = minimum
            bptrs[i][j] = pointer
    bt = [(m, n)]
    cell = bptrs[m][n]
    while True:
        if not cell:
            break
        bt.append(cell)
        if bptrs[cell[0]][cell[1]]:
            cell = bptrs[cell[0]][cell[1]]
        else:
            break
    trace = list(reversed(bt))
    alignment = []
    for i in range(1, len(trace)):
        current = trace[i]
        prev = trace[i - 1]
        if current[0] - prev[0] == 1 and current[1] - prev[1] == 1:
            alignment.append((source[current[0] - 1], target[current[1] - 1]))
        elif current[0] - prev[0] == 1:
            alignment.append((source[current[0] - 1], ''))
        elif current[1] - prev[1] == 1:
            alignment.append(('', target[current[1] - 1]))
    return alignment


def __init__(A):
    """PaymentInformationStatusCode - a model defined in Swagger"""
    A.discriminator = None


def documentCount():
    """Return the number of documents currently indexed."""


@classmethod
def read(cls, path: str, inherit: bool=True) ->'Theme':
    """Read a theme from a path.

        Args:
            path (str): Path to a config file readable by Python configparser module.
            inherit (bool, optional): Switch to inherit default styles. Defaults to True.

        Returns:
            Theme: A new theme instance.
        """
    with open(path, 'rt') as config_file:
        return cls.from_file(config_file, source=path, inherit=inherit)


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

        :param Optional[str] val:
        :rtype: LookupError
        """
    return cls('malformed_path', val)


def RemoveComments(Line, Symbol='--'):
    """
	Remove comments from a string.
	"""
    if Symbol in Line:
        return Line[:Line.index(Symbol)]
    else:
        return Line


def inverse_mapper(val):
    """A mapping from axis space to data space"""
    raise NotImplementedError


def maxPowerOfTwo(x):
    """Return the highest exponent of two, so that
	(2 ** exponent) <= x.  Return 0 if x is 0.
	"""
    exponent = 0
    while x:
        x = x >> 1
        exponent = exponent + 1
    return max(exponent - 1, 0)


def _key_and_val_from_searchable_text(searchable_text):
    """Returns the key and arguments from a keyword query"""
    if ':' not in searchable_text:
        return None, None
    parts = searchable_text.split(':')
    key = parts[0].strip()
    val = parts[1].strip()
    val = val.replace('*', '')
    return key, val


def raw_tag(name, value):
    """Create a DMAP tag with raw data."""
    return name.encode('utf-8') + len(value).to_bytes(4, byteorder='big'
        ) + value


def print_all(xlist):
    """Print out the entity."""
    grp = None
    for obj in xlist:
        if grp:
            grp += f', {obj.name}'
        else:
            grp = obj.name
    if grp is None:
        grp = 'None'
    return grp


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

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

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


@classmethod
def promote_from_model(cls, literal_model):
    """
        Creates an object of this type from the model primitive defining it.
        :param flytekit.models.literals.Literal literal_model:
        :rtype: Generic
        """
    return cls(literal_model.scalar.generic)


@staticmethod
def translate_to_filename(plugin_name: str) ->str:
    """
        Static method to translate the plugin name to a standard prefix
        that could be used in a standard matter in the *Cache* class.

        :param plugin_name: The plugin to translate the name for.
        :returns: The translated plugin name.
        """
    return plugin_name.replace(':', '_').lower()


def has_python_shebang(filepath, accepted_shebangs=None):
    """Checks if the filepath is a python script.

    The file is a python script if the first line starts with '#!' and
    contains of the accepted shebangs. For example, a file starting with
    '#!usr/bin/python3' would return True if the list of shebangs was
    ['python'].

    Args:
        filepath (str): The filepath of the file to check.
        accepted_shebangs (list(str) or None): The list of shebangs
            that constitute a python script. If None, the default list
            of ['python'] is used.

    Returns:
        bool: True if the filepath matches the accepted shebangs.
    """
    if accepted_shebangs is None:
        accepted_shebangs = ['python']
    with open(filepath, 'r') as script:
        try:
            first_line = script.readline().strip()
        except UnicodeDecodeError:
            return False
    if first_line.startswith('#!'):
        for script in accepted_shebangs:
            if script in first_line:
                return True
    return False


@classmethod
def unverified_from_response(cls, user, response):
    """Create an AchUsNode instance for an ACH-US node that needs MFA.

        The API record is not actually created until the MFA has been correctly
        answered.
        """
    return cls(user=user, mfa_access_token=response['mfa']['access_token'],
        mfa_message=response['mfa']['message'], mfa_type=response['mfa'][
        'type'], mfa_verified=False)


def destroying():
    """Inform the repository that nodes are about to be destroyed."""


def remove_node(target, node_ref, root_nodes):
    """Remove a node (and it's children) from the tree.

    Parameters
    ----------
    target : string
        The target node, on form root->section->subcection.
    node_ref : dict
        A dict with all the nodes.
    root_nodes : list of objects like :py:class:`.SectionNode`
        The root nodes.

    """
    to_del = node_ref.pop(target, None)
    if to_del is None:
        pass
    else:
        visited = set()
        nodes = [to_del]
        while nodes:
            node = nodes.pop()
            if node not in visited:
                visited.add(node)
                for i in node.children:
                    nodes.append(i)
        parent = to_del.parent
        if parent is None:
            root_nodes.remove(to_del)
        else:
            parent.children.remove(to_del)
        del to_del
        for key in visited:
            remove = node_ref.pop(key, None)
            del remove


def gear_profile_3d_construction(c):
    """ construct the 3D-assembly-configurations of the gear_profile
  """
    gp_assembly_conf1 = []
    gp_assembly_conf1.append(('first_gear', 0.0, 0.0, 0.0, 0.0, c[
        'gear_profile_height'], 'i', 'xy', 0.0, 0.0, 0.0))
    if c['g2_exist']:
        gp_assembly_conf1.append(('second_gear', 0.0, 0.0, 0.0, 0.0, c[
            'gear_profile_height'], 'i', 'xy', 0.0, 0.0, 0.0))
    r_assembly = {}
    r_slice = {}
    r_assembly['gp_assembly_conf1'] = gp_assembly_conf1
    fgr = c['g1_param']['module'] * (c['gear_tooth_nb'] + 2) / 2.0
    hh = c['gear_profile_height'] / 2.0
    r_slice['gp_assembly_conf1'] = 2 * fgr, 2 * fgr, c['gear_profile_height'
        ], c['center_position_x'] - fgr, c['center_position_y'] - fgr, 0.0, [hh
        ], [], []
    return r_assembly, r_slice


def mpi_map_alloc_dmem(f, scatter_tuple=None, bcast_tuple=None,
    dmem_key_in_list=None, dmem_arg_in_list=None, dmem_val_in_list=None,
    dmem_key_out_list=None, obj=None, obj_val=None, reduce_obj=None,
    reduce_tuple=None, mpi_pool=None, splitted=False, concatenate=True):
    """ Interface for the parallel evaluation of a generic function on points ``x``

    Args:
      f (:class:`object` or :class:`str`): function or string identifying the
        function in object ``obj``
      scatter_tuple (tuple): tuple containing 2 lists of ``[keys]`` and ``[arguments]``
        which will be scattered to the processes.
      bcast_tuple (tuple): tuple containing 2 lists of ``[keys]`` and ``[arguments]``
        which will be broadcasted to the processes.
      dmem_key_in_list (list): list of string containing the keys
        to be fetched (or created with default ``None`` if missing) from the
        distributed memory and provided as input to ``f``.
      dmem_val_in_list (list): list of objects corresponding to the keys defined
        in ``dmem_key_in_list``, used in case we are not executing in parallel
      dmem_key_out_list (list): list of keys to be assigned to the outputs
        beside the first one
      obj (object): object where the function ``f_name`` is defined
      obj_val (object): object to be used in case not executing in parallel and
        ``obj`` is a string
      reduce_obj (object): object :class:`ReduceObject` defining the reduce
        method to be applied (if any)
      reduce_tuple (object): tuple containing 2 lists of ``[keys]`` and ``[arguments]``
        which will be scattered to the processes to be used by ``reduce_obj``
      mpi_pool (:class:`mpi_map.MPI_Pool<mpi_map.MPI_Pool>`): pool of processors
      splitted (bool): whether the scattering input is already splitted or not
      concatenate (bool): whether to concatenate the output (the output of ``f``
        must be a :class:`numpy.ndarray<numpy.ndarray>` object
    """
    if scatter_tuple is None:
        scatter_tuple = [], []
    if bcast_tuple is None:
        bcast_tuple = [], []
    if dmem_key_in_list is None:
        dmem_key_in_list = []
    if dmem_arg_in_list is None:
        dmem_arg_in_list = []
    if dmem_val_in_list is None:
        dmem_val_in_list = []
    if dmem_key_out_list is None:
        dmem_key_out_list = []
    if reduce_tuple is None:
        reduce_tuple = [], []
    if mpi_pool is None:
        args = {}
        for key, val in zip(scatter_tuple[0], scatter_tuple[1]):
            if splitted:
                if len(val) != 1:
                    raise ValueError(
                        'Serial execution but splitted input is %d long' %
                        len(val))
                args[key] = val[0]
            else:
                args[key] = val
        for key, val in zip(bcast_tuple[0], bcast_tuple[1]):
            args[key] = val
        for key, val in zip(dmem_arg_in_list, dmem_val_in_list):
            args[key] = val
        reduce_args = {}
        for key, val in zip(reduce_tuple[0], reduce_tuple[1]):
            if splitted:
                if len(val) != 1:
                    raise ValueError(
                        'Serial execution but splitted input is %d long' %
                        len(val))
                reduce_args[key] = val[0]
            else:
                reduce_args[key] = val
        if obj is not None:
            if isinstance(obj, str):
                f = getattr(obj_val, f)
            else:
                f = getattr(obj, f)
        pars = f(**args)
        if not isinstance(pars, tuple):
            pars = pars,
    else:
        obj_scatter = mpi_pool.split_data(scatter_tuple[1], scatter_tuple[0
            ], splitted=splitted)
        obj_bcast = {}
        for key, val in zip(bcast_tuple[0], bcast_tuple[1]):
            obj_bcast[key] = val
        obj_args_reduce = mpi_pool.split_data(reduce_tuple[1], reduce_tuple
            [0], splitted=splitted)
        pars = tuple([None] * len(dmem_key_out_list))
        mpi_pool.map_alloc_dmem(f, obj_scatter=obj_scatter, obj_bcast=
            obj_bcast, dmem_key_in_list=dmem_key_in_list, dmem_arg_in_list=
            dmem_arg_in_list, dmem_key_out_list=dmem_key_out_list, obj=obj,
            reduce_obj=reduce_obj, reduce_args=obj_args_reduce)
    return pars


@classmethod
def usable_id(cls, id):
    """Retrieve id from input which can be fqdn or id."""
    try:
        qry_id = int(id)
    except Exception:
        qry_id = cls.from_fqdn(id)
    if not qry_id:
        msg = 'unknown identifier %s' % id
        cls.error(msg)
    return qry_id


def rename_label(labels, old, new):
    """Rename a label in a parcellation

    Parameters
    ----------
    labels : list of Label
        The labels
    old, new : str
        Old and new names without hemi affix.

    Notes
    -----
    Modifies ``labels`` in-place, returns None.
    """
    delim = '-'
    for hemi in ('lh', 'rh'):
        old_ = delim.join((old, hemi))
        for label in labels:
            if label.name == old_:
                new_ = delim.join((new, hemi))
                label.name = new_


def shell_if_wheels(command):
    """ Take a shell command and convert it to shell command that runs
    only if Galaxy is new enough to use wheels.
    """
    return "$(grep -q 'skip-venv' run_tests.sh) && %s" % command


@staticmethod
def lookup(entry_qs):
    """
        The main lookup function.
        Edit the models in place.
        Overwrite this.
        :param entry_qs: The Entry query set
        """
    pass


@classmethod
def encode(cls, bytes_encoded):
    """
        encodes a DNA bytes string using 2 bits per base. N (and other ambiguous nucleotides)
        are randomized

        :param bytes bytes_encoded: a bytes string containing A, C, G, T nucleotides.
        :return int: encoded sequence
        """
    encoded = 0
    for character in bytes_encoded:
        encoded <<= 2
        encoded += cls.encoding_map[character]
    return encoded


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


@staticmethod
def process_session(res):
    """Return (got_session, error_details).
        error_details is (should_retry, reason, error_code) or None if got_session."""
    if 'sessionStatus' in res:
        return True, None
    if 'errorMessage' in res:
        try:
            error_code = res['errorMessage']['additionalInfo'][
                'uploader_service.GoogleRupioAdditionalInfo']['completionInfo'
                ]['customerSpecificInfo']['ResponseCode']
        except KeyError:
            error_code = None
        got_session = False
        if error_code == 503:
            should_retry = True
            reason = 'upload servers still syncing'
        elif error_code == 200:
            should_retry = False
            reason = 'this song is already uploaded'
        elif error_code == 404:
            should_retry = False
            reason = 'the request was rejected'
        else:
            should_retry = True
            reason = 'the server reported an unknown error'
        return got_session, (should_retry, reason, error_code)
    return False, (True, "the server's response could not be understood", None)


@staticmethod
def _test_rule_fallback(skeys: str, all_skeys: str, all_letters: str) ->bool:
    """ If execution reaches this point without a valid guess, use a guaranteed fallback rule. """
    return True


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

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

        :rtype: :class:`str`
        """
    return 'hudson.plugins.sectioned_view.ListViewSection'


def mergeDict(dict1, dict2):
    """ Merge dictionaries and add values of common keys"""
    dict3 = {**dict1, **dict2}
    for key, value in dict3.items():
        if key in dict1 and key in dict2:
            dict3[key] = value + dict1[key]
    return dict3


def _rhex(byte):
    """converts bytecode to hex, while reading from right to left"""
    rhex = byte[::-1].hex()
    return rhex


def gen_motion_parameters(subject_id, scan_id, movement_parameters,
    max_displacement):
    """  Method to calculate all the movement parameters.

    Parameters
    ----------
    subject_id : string
        subject name or id

    scan_id : string
        scan name or id

    max_displacement : string
        path of file with maximum displacement (in mm) for brain voxels in each volume

    movement_parameters : string
        path of 1D file containing six movement/motion parameters(3 Translation,
        3 Rotations) in different columns (roll pitch yaw dS  dL  dP)

    Returns
    -------
    out_file : string
        path to csv file contianing various motion parameters
    """
    import os
    import numpy as np
    import re
    out_file = 'motion_parameters.txt'
    with open(out_file, 'w') as f:
        header = """Subject,Scan,Mean_Relative_RMS_Displacement,Max_Relative_RMS_Displacement,Movements_gt_threshold,Mean_Relative_Mean_Rotation,Mean_Relative_Maxdisp,Max_Relative_Maxdisp,Max_Abs_Maxdisp,Max Relative_Roll,Max_Relative_Pitch,Max_Relative_Yaw,Max_Relative_dS-I,Max_Relative_dL-R,Max_Relative_dP-A,Mean_Relative_Roll,Mean_Relative_Pitch,Mean_Relative_Yaw,Mean_Relative_dS-I,Mean_Relative_dL-R,Mean_Relative_dP-A,Max_Abs_Roll,Max_Abs_Pitch,Max_Abs_Yaw,Max_Abs_dS-I,Max_Abs_dL-R,Max_Abs_dP-A,Mean_Abs_Roll,Mean_Abs_Pitch,Mean_Abs_Yaw,Mean_Abs_dS-I,Mean_Abs_dL-R,Mean_Abs_dP-A
"""
        f.write(header)
        f.write('%s,' % subject_id)
        f.write('%s,' % scan_id)
        arr = np.genfromtxt(movement_parameters)
        arr = arr.T
        rms = np.sqrt(arr[3] * arr[3] + arr[4] * arr[4] + arr[5] * arr[5])
        diff = np.diff(rms)
        MEANrms = np.mean(abs(diff))
        f.write('%.3f,' % MEANrms)
        MAXrms = np.max(abs(diff))
        f.write('%.3f,' % MAXrms)
        NUMmove = np.sum(abs(diff) > 0.1)
        f.write('%.3f,' % NUMmove)
        MEANrot = np.mean(np.abs(np.diff((abs(arr[0]) + abs(arr[1]) + abs(
            arr[2])) / 3)))
        f.write('%.3f,' % MEANrot)
        with open(max_displacement, 'r') as disp_f:
            lines = disp_f.readlines()
        list1 = []
        for l in lines:
            if re.match('^\\d+?\\.\\d+?$', l.strip()):
                list1.append(float(l.strip()))
        arr2 = np.array(list1, dtype='float')
        mean = np.mean(np.diff(arr2))
        f.write('%.3f,' % mean)
        relMAX = np.max(abs(np.diff(arr2)))
        f.write('%.3f,' % relMAX)
        MAX = np.max(arr2)
        f.write('%.3f,' % MAX)
        for i in range(6):
            f.write('%.6f,' % np.max(abs(np.diff(arr[i]))))
        for i in range(6):
            f.write('%.6f,' % np.mean(np.diff(arr[i])))
        for i in range(6):
            f.write('%.6f,' % np.max(abs(arr[i])))
        for i in range(6):
            f.write('%.6f,' % np.mean(abs(arr[i])))
    return os.path.abspath(out_file)


@classmethod
def get_slug(klass):
    """
        For a tagged patient list, the slug is made up of the tags.
        """
    s = klass.tag
    if hasattr(klass, 'subtag'):
        s += '-' + klass.subtag
    return s


def could_short_circuit(if_el):
    """
    Is there the potential to take advantage of Python's ability to short-
    circuit and collapse a nested IF into its parent as a single expression?

    The if_el must have an IF as its only child AND that nested IF must have an
    ORELSE as a child. But that ORELSE must have no children.

    :param element if_el: If element
    :return: True if the If has the potential to be short-circuited
    :rtype: bool
    """
    body_els = if_el.xpath('body')
    has_one_body = len(body_els) == 1
    if not has_one_body:
        return False
    body_el = body_els[0]
    body_children_els = body_el.getchildren()
    body_one_child = len(body_children_els) == 1
    if not body_one_child:
        return False
    body_child_el = body_children_els[0]
    sole_child_is_if = body_child_el.tag == 'If'
    if not sole_child_is_if:
        return False
    nested_if_el = body_child_el
    nested_if_orelse_els = nested_if_el.xpath('orelse')
    one_orelse = len(nested_if_orelse_els) == 1
    if not one_orelse:
        return False
    nested_if_orelse_el = nested_if_orelse_els[0]
    orelse_has_children = bool(nested_if_orelse_el.getchildren())
    if orelse_has_children:
        return False
    return True


def to_flat(A, flat_map):
    """Convert a square matrix A to a flat array alpha.

    Parameters
    ----------
    A : ndarray
        The transformation matrix A
    flat_map : ndarray
        Mapping from flat indices (k) to square (i,j) indices.

    Returns
    -------
    FlatenedA : ndarray
        flattened version of A
    """
    return A[flat_map[:, (0)], flat_map[:, (1)]]


def contains_mention(tweet):
    """Takes a python-native tweet obect (a dict). Returns True if a tweet contains a mention"""
    if 'entities' not in tweet:
        return False
    return True if len(tweet['entities']['user_mentions']) > 0 else False


def hello():
    """
    Display [Hello, World.].
    """
    print('Hello, World.')


@classmethod
def _import_it(cls):
    """
        Imports Future from tornado.concurrent.
        """
    from tornado.concurrent import Future
    return Future


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 norm(var, p=1):
    """
    Returns variable representing L-p norm of input variable var
    """
    return sum(abs(var) ** p) ** (1 / p)


def from_jd(jd):
    """Return tuple of ISO (year, week, day) for Julian day"""
    gpsweek = int((jd - 2444244.5) / 7)
    dow = ((jd - 2444244.5) / 7 - gpsweek) * 7
    dow = int(round(dow * 86400) / 86400)
    return gpsweek, dow


def _make_reflected_gradient(X, Y, angle):
    """Generates index map for reflected gradients."""
    import numpy as np
    theta = np.radians(angle % 360)
    Z = np.abs(np.cos(theta) * X - np.sin(theta) * Y)
    return Z


@classmethod
def _from_dict(cls, _dict):
    """Initialize a Corpus object from a json dictionary."""
    args = {}
    if 'name' in _dict:
        args['name'] = _dict.get('name')
    else:
        raise ValueError("Required property 'name' not present in Corpus JSON")
    if 'total_words' in _dict:
        args['total_words'] = _dict.get('total_words')
    else:
        raise ValueError(
            "Required property 'total_words' not present in Corpus JSON")
    if 'out_of_vocabulary_words' in _dict:
        args['out_of_vocabulary_words'] = _dict.get('out_of_vocabulary_words')
    else:
        raise ValueError(
            "Required property 'out_of_vocabulary_words' not present in Corpus JSON"
            )
    if 'status' in _dict:
        args['status'] = _dict.get('status')
    else:
        raise ValueError(
            "Required property 'status' not present in Corpus JSON")
    if 'error' in _dict:
        args['error'] = _dict.get('error')
    return cls(**args)


def get_tcon(v, index):
    """Gets the list indices in L of the tensors that have index as their
    leg.
    """
    tcon = []
    for i, inds in enumerate(v):
        if index in inds:
            tcon.append(i)
    l = len(tcon)
    if l > 2:
        raise ValueError(
            'In ncon.get_tcon, more than two tensors share a contraction index.'
            )
    elif l < 1:
        raise ValueError(
            'In ncon.get_tcon, less than one tensor share a contraction index.'
            )
    elif l == 1:
        how_many = v[tcon[0]].count(index)
        if how_many != 2:
            raise ValueError(
                'In ncon.get_tcon, a trace index is listed != 2 times for the same tensor.'
                )
    return tcon


@classmethod
def get_id_prefix(cls):
    """Return a prefix applied to task Ids"""
    return 'swm_task'


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


def alphanumeric_hash(s: str, size=5):
    """Short alphanumeric string derived from hash of given string"""
    import hashlib
    import base64
    hash_object = hashlib.md5(s.encode('ascii'))
    s = base64.b32encode(hash_object.digest())
    result = s[:size].decode('ascii').lower()
    return result


def __call__():
    """
            return substitution
        """


def dv_cont(T, P):
    """ Diffusivity of water vapor in air, neglecting non-continuum effects.

    See :func:`dv` for details.

    Parameters
    ----------
    T : float
        ambient temperature of air surrounding droplets, K
    P : float
        ambient pressure of surrounding air, Pa

    Returns
    -------
    float
        :math:`D_v(T, P)` in m^2/s

    See Also
    --------
    dv : includes correction for non-continuum effects

    """
    P_atm = P * 1.01325e-05
    return 0.0001 * (0.211 / P_atm) * (T / 273.0) ** 1.94


def is_power_of_2(value):
    """Check if a value is a power of 2 using binary operations.

    Parameters
    ----------
    value : `number`
        value to check

    Returns
    -------
    `bool`
        true if the value is a power of two, False if the value is no

    Notes
    -----
    c++ inspired implementation, see SO:
    https://stackoverflow.com/questions/29480680/finding-if-a-number-is-a-power-of-2-using-recursion

    """
    if value is 1:
        return False
    else:
        return bool(value and not value & value - 1)


def merge_dict(data, *override):
    """
    Utility function for merging dictionaries
    """
    result = {}
    for current_dict in ((data,) + override):
        result.update(current_dict)
    return result


def listToString(array):
    """
    A method that converts a list onto a string

    Args:
    -----
        array: A list of strings.

    Returns:
    --------
        A string containing the elements of the list separated by a ' '.
    """
    if isinstance(array, list):
        aux = ''
        for e in array:
            aux += e + ' '
        return aux
    return str(array)


def validate_format(*_arg):
    """
    This method can be overridden with format validation logic.
    """
    return True


@staticmethod
def _create_parameter_dict(parameter_df, keys, value):
    """
        Function to create parameters dictionary
        :param parameter_df:
        :param keys:
        :param value:
        :return:
        """
    parameter_df = parameter_df.set_index(keys)
    return parameter_df[value].to_dict()


def _get_df_between_date_by_index(data_df, date_frm, date_to):
    """
    该函数仅用于 return_risk_analysis 中计算使用
    :param data_df:
    :param date_frm:
    :param date_to:
    :return:
    """
    if date_frm is not None and date_to is not None:
        new_data_df = data_df[(data_df.index >= date_frm) & (data_df.index <=
            date_to)]
    elif date_frm is not None:
        new_data_df = data_df[data_df.index >= date_frm]
    elif date_to is not None:
        new_data_df = data_df[data_df.index <= date_to]
    else:
        new_data_df = data_df
    return new_data_df


def print_word_list(words, line_length=79):
    """Given a list, print it in a condensed form separated by spaces"""
    chars_left_in_line = line_length
    returning = ''
    for word in words:
        if not isinstance(word, str):
            word = str(word)
        if chars_left_in_line < len(word) + 1:
            returning += '\n'
            chars_left_in_line = line_length
        returning += ' %s' % word
        chars_left_in_line -= len(word) + 1
    return returning


def parse_orgs(org_file):
    """Parse csv table for organisms selection
    input: csv file with organisms
    return: set of organisms to exclude, set of organisms
    for which we want to select paralogs"""
    to_exlude = set()
    paralogs = set()
    with open(org_file) as lines:
        header = next(lines)
        if header.count(',') == 10:
            sgt_idx = 9
        else:
            sgt_idx = 6
        for line in lines:
            org = line.split(',')[0]
            sgt = line.split(',')[sgt_idx].strip()
            if sgt.lower() != 'yes':
                to_exlude.add(org)
            if header.count(',') == 10:
                if line.split(',')[sgt_idx + 1].strip().lower() == 'yes':
                    if org not in to_exlude:
                        paralogs.add(org)
    return to_exlude, paralogs


@classmethod
def from_upstream(cls, trace_id, parent_id, span_id, sampled, flags):
    """Build a TraceInfo from individual headers.

        :param int trace_id: The ID of the trace.
        :param int parent_id: The ID of the parent span.
        :param int span_id: The ID of this span within the tree.
        :param bool sampled: Boolean flag to determine request sampling.
        :param int flags: Bit flags for communicating feature flags downstream

        :raises: :py:exc:`ValueError` if any of the values are inappropriate.

        """
    if trace_id is None or not 0 <= trace_id < 2 ** 64:
        raise ValueError('invalid trace_id')
    if span_id is None or not 0 <= span_id < 2 ** 64:
        raise ValueError('invalid span_id')
    if parent_id is None or not 0 <= parent_id < 2 ** 64:
        raise ValueError('invalid parent_id')
    if sampled is not None and not isinstance(sampled, bool):
        raise ValueError('invalid sampled value')
    if flags is not None:
        if not 0 <= flags < 2 ** 64:
            raise ValueError('invalid flags value')
    return cls(trace_id, parent_id, span_id, sampled, flags)


def makeConnection(transport):
    """
        Make a connection to a transport and a server.
        """


def with_metaclass(meta, base=object):
    """Create a base class with a metaclass."""
    return meta('NewBase', (base,), {})


@staticmethod
def maybe_unwrap(func):
    """Return the given function, without its probe_wrapper if it has one."""
    if getattr(getattr(func, '__code__', None), 'co_name', ''
        ) == 'probe_wrapper':
        return func.__closure__[0].cell_contents
    else:
        return func


def _IOC(typ, nr, size, direction):
    """ generic IOCTL structure """
    r = direction << 30 | size << 16 | typ << 8 | nr
    return r


def create_xss_match_set(Name=None, ChangeToken=None):
    """
    Creates an  XssMatchSet , which you use to allow, block, or count requests that contain cross-site scripting attacks in the specified part of web requests. AWS WAF searches for character sequences that are likely to be malicious strings.
    To create and configure an XssMatchSet , perform the following steps:
    For more information about how to use the AWS WAF API to allow or block HTTP requests, see the AWS WAF Developer Guide .
    See also: AWS API Documentation

    Examples
    The following example creates an XSS match set named MySampleXssMatchSet.
    Expected Output:

    :example: response = client.create_xss_match_set(
        Name='string',
        ChangeToken='string'
    )

    :type Name: string
    :param Name: [REQUIRED]
            A friendly name or description for the XssMatchSet that you're creating. You can't change Name after you create the XssMatchSet .

    :type ChangeToken: string
    :param ChangeToken: [REQUIRED]
            The value returned by the most recent call to GetChangeToken .

    :rtype: dict
    :return: {
        'XssMatchSet': {
            'XssMatchSetId': 'string',
            'Name': 'string',
            'XssMatchTuples': [
                {
                    'FieldToMatch': {
                        'Type': 'URI'|'QUERY_STRING'|'HEADER'|'METHOD'|'BODY',
                        'Data': 'string'
                    },
                    'TextTransformation': 'NONE'|'COMPRESS_WHITE_SPACE'|'HTML_ENTITY_DECODE'|'LOWERCASE'|'CMD_LINE'|'URL_DECODE'
                },
            ]
        },
        'ChangeToken': 'string'
    }

    :returns:
    Name (string) -- [REQUIRED]
    A friendly name or description for the  XssMatchSet that you're creating. You can't change Name after you create the XssMatchSet .

    ChangeToken (string) -- [REQUIRED]
    The value returned by the most recent call to  GetChangeToken .

    """
    pass


def replacelines(clines, target, replacement):
    """This function executes the .replace() method on each element of a 'str' object list.

  Args:
      clines: A 'str' list object, the lines of text to read through to find and replace.
      target: A 'str', what to search for to replace.
      replacement: A 'str', what to replace the target with.

  Returns:
    a 'str' list object: The results of running the find and replace on the input text.
  """
    for i in range(0, len(clines), 1):
        clines[i] = clines[i].replace(target, replacement)
    return clines


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

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


def _get_str(obj):
    """ return str of obj """
    return str(obj)


def get_our_present(their_past, their_future):
    """
    Predicts the present style of speech we should use
    to influence a other person who is currently in
    their_past to become their_future
    :param their_past: the past of the other person
    :param their_future: the desired future of the other person
    :return: the present style we should use
    """
    if their_past * their_future < 0:
        return -10
    else:
        return 10


def attach_skins_and_materials(asset, definitions, material_name, default=True
    ):
    """Find all skins in the ``definitions`` asset which remap the material ``material_name``. Attach the found skin
    and references materials to the target ``asset``."""
    skins = definitions.retrieve_skins()
    for skin, materials in skins.iteritems():
        attach_skin = False
        for v, k in materials.iteritems():
            if v == material_name:
                attach_skin = True
                material = definitions.retrieve_material(k, default)
                asset.attach_material(k, raw=material)
        if attach_skin:
            asset.attach_skin(skin, materials)


def _sum_nan_conservative(x):
    """Sum that mark as NaN if all are NaN."""
    return x.sum(min_count=1)


def break_by_timegap(points, timegap=360):
    """Break into trip segments when time recorded between points is
       > timegap variable and group points by segment number in a dictionary"""
    trips = []
    group = 1
    for idx, row in enumerate(points):
        dt = row['timestamp_UTC']
        if idx == 0:
            previous_row = row
            period = 0
        else:
            period = int((dt - previous_row['timestamp_UTC']).total_seconds())
            if period > timegap:
                group += 1
            previous_row = row
        row['segment_group'] = group
        row['break_period'] = period
        row['note'] = ''
        row['merge_codes'] = []
        trips.append(dict(row))
    segment_groups = {}
    for t in trips:
        segment_groups.setdefault(t['segment_group'], []).append(t)
    return segment_groups


def get_unique_groups(input_list):
    """Function to get a unique list of groups."""
    out_list = []
    for item in input_list:
        if item not in out_list:
            out_list.append(item)
    return out_list


@staticmethod
def parseFileName(file_path):
    """Return cleaned name of the star without path and suffix"""
    end = None
    if file_path.rfind('.') != -1:
        end = file_path.rfind('.')
    return file_path[file_path.rfind('/') + 1:end]


def extents_equal(a_extent, b_extent):
    """Test if two extents are identical"""
    if (a_extent.xmin != b_extent.xmax or a_extent.xmax != b_extent.xmin or
        a_extent.ymin != b_extent.ymax or a_extent.ymax != b_extent.ymin):
        return False
    else:
        return True


@classmethod
def get_business_required_fields(cls):
    """
        get ``set`` of ``required fields`` for
        :attr:`BUSINESS_TYPE`

        Returns:
            ``set`` of fields
        """
    fields = cls.get_required_fields()
    return fields.union({'ein'})


def cleanup_dict(dictionary, key, empty_value):
    """deletes key from dictionary if it exists
    and the corresponding value equals the empty_value
    """
    if key in dictionary and dictionary[key] == empty_value:
        del dictionary[key]


def p_flag_case_insensitive(p):
    """flag : K_CASE K_INSENSITIVE
    """
    p[0] = [('case_insensitive', ())]


def get_absolute_airmass(airmass_relative, pressure=101325.0):
    """
    Determine absolute (pressure corrected) airmass from relative
    airmass and pressure

    Gives the airmass for locations not at sea-level (i.e. not at
    standard pressure). The input argument "AMrelative" is the relative
    airmass. The input argument "pressure" is the pressure (in Pascals)
    at the location of interest and must be greater than 0. The
    calculation for absolute airmass is

    .. math::
        absolute airmass = (relative airmass)*pressure/101325

    Parameters
    ----------
    airmass_relative : numeric
        The airmass at sea-level.

    pressure : numeric, default 101325
        The site pressure in Pascal.

    Returns
    -------
    airmass_absolute : numeric
        Absolute (pressure corrected) airmass

    References
    ----------
    .. [1] C. Gueymard, "Critical analysis and performance assessment of
       clear sky solar irradiance models using theoretical and measured
       data," Solar Energy, vol. 51, pp. 121-138, 1993.
    """
    airmass_absolute = airmass_relative * pressure / 101325.0
    return airmass_absolute


def update_title_paths(instance, **kwargs):
    """Update child pages paths in case when page was moved.
    """
    for title in instance.title_set.all():
        title.save()


def parse_values_to_remove(options):
    """Manual parsing of remove arguments.

    :param options: list of arguments following --remove argument
    :return: dictionary containing key paths with values to be removed
    :rtype: dict
    EXAMPLE: {'identity.username': [myname],
              'identity-feature-enabled.api_extensions': [http, https]}
    """
    parsed = {}
    for argument in options:
        if len(argument.split('=')) == 2:
            section, values = argument.split('=')
            if len(section.split('.')) != 2:
                raise Exception(
                    "Missing dot. The option --remove has to come in the format 'section.key=value[,value]', but got '%s'."
                     % argument)
            parsed[section] = values.split(',')
        else:
            parsed[argument] = []
    return parsed


def intersect_plane_plane(plane_a_co: 'mathutils.Vector', plane_a_no:
    'mathutils.Vector', plane_b_co: 'mathutils.Vector', plane_b_no:
    'mathutils.Vector') ->'mathutils.Vector':
    """Return the intersection between two planes

    :param plane_a_co: Point on the first plane
    :type plane_a_co: 'mathutils.Vector'
    :param plane_a_no: Normal of the first plane
    :type plane_a_no: 'mathutils.Vector'
    :param plane_b_co: Point on the second plane
    :type plane_b_co: 'mathutils.Vector'
    :param plane_b_no: Normal of the second plane
    :type plane_b_no: 'mathutils.Vector'
    :return:  The line of the intersection represented as a point and a vector
    """
    pass


def frequency_shrink_via_inverse_fft_image_filter(*args, **kwargs):
    """Procedural interface for FrequencyShrinkViaInverseFFTImageFilter"""
    import itk
    instance = itk.FrequencyShrinkViaInverseFFTImageFilter.New(*args, **kwargs)
    return instance.__internal_call__()


def merge_clusters(clusters, merge_to_which):
    """
    Recursively merges clusters together from smallest to largest according to a
    specified merge function.

    Parameters
    ----------
    clusters : list of clusters
        The clusters to be merged. All elements will be removed from this list
        when this function is called.
    merge_to_which : function
        Function that takes in a list of clusters and returns the index of the
        cluster the first cluster in the list should be merged into. If the
        first cluster in the list should not be merged, this function should
        return -1.

    Returns
    -------
    list of clusters
        The list of merged clusters.
    """
    merged_clusters = []
    while clusters:
        clusters.sort(key=lambda x: len(x), reverse=False)
        merge_to = merge_to_which(clusters)
        if merge_to == -1:
            merged_clusters.append(clusters.pop(0))
        else:
            clusters[merge_to].extend(clusters[0])
            clusters.pop(0)
    return merged_clusters


def get_separator(handle):
    """ get the column separator (assumes same on all lines)
    """
    current = handle.tell()
    line = handle.readline()
    handle.seek(current)
    if line.count('\t') > line.count(' '):
        return '\t'
    else:
        return ' '


def insertmany_query(tablename, objects):
    """
    Function to process the query for insert many  process
    """
    if isinstance(tablename, str):
        pass
    else:
        raise ValueError('Table name argument must be a string')
    if isinstance(objects, list):
        pass
    else:
        raise ValueError(' objects argument must be list')
    if isinstance(objects[0], dict):
        pass
    else:
        raise ValueError('A value in objects argument must be a dictionary')
    """
    Sanity check of bulk insert
    """
    len_objects = []
    for val in map(len, objects):
        len_objects.append(val)
    if len(set(len_objects)) != 1:
        raise ValueError('Objects are off different length')
    columns = set(objects[0].keys())
    for val in objects:
        if columns != set(val.keys()):
            raise ValueError(
                'The number of columns that has to be updated must be same across all the objects'
                )
    val = objects[0]
    cols = ''
    for i in tuple(val.keys()):
        cols += str(i) + ','
    cols = '(' + cols[:len(cols) - 1] + ')'
    placeholders = ''
    for i in tuple(val.keys()):
        placeholders += ':' + str(i) + ','
    placeholders = '(' + placeholders[:len(placeholders) - 1] + ')'
    query = 'INSERT INTO ' + tablename + ' ' + cols + ' values ' + placeholders
    return query


def fun_var(x, cf_cov, **kwargs):
    """Objective function given by the variance associated with
    a capacity distribution and a capacity factors covariance matrix.

    :param x: State vector.
    :param cf_cov: pv/wind capacity factors covariances.
    :type x: :py:class:`numpy.array`
    :type cf_cov: :py:class:`numpy.array`

    :returns: Value of objective function.
    :rtype: float
    """
    obj = x.dot(cf_cov.dot(x))
    return obj


def customdata_skin_add():
    """Add a vertex skin layer

    """
    pass


def get_config(data, expr, default=None):
    """
    使用a.[b].c表达式从对象中获取值
    :param data:     对象,支持getattr的任意对象
    :type data:      any
    :param expr:     路径表达式，eg. log.path
    :type expr:      str
    :param default:  如果表达式的值不存在，则返回默认值
    :type default:   any
    """
    names = expr.split('.')
    result = data
    for name in names:
        try:
            result = getattr(result, name)
        except AttributeError:
            result = default
            break
    return result


def disposition_debug_msg(disp):
    """Make a nice debug message of what the FileDisposition is doing."""
    if disp.trace:
        msg = 'Tracing %r' % (disp.original_filename,)
        if disp.file_tracer:
            msg += ': will be traced by %r' % disp.file_tracer
    else:
        msg = 'Not tracing %r: %s' % (disp.original_filename, disp.reason)
    return msg


def add_n(*args, **kwargs):
    """Adds all input arguments element-wise.

    .. math::
       add\\_n(a_1, a_2, ..., a_n) = a_1 + a_2 + ... + a_n

    ``add_n`` is potentially more efficient than calling ``add`` by `n` times.

    The storage type of ``add_n`` output depends on storage types of inputs

    - add_n(row_sparse, row_sparse, ..) = row_sparse
    - add_n(default, csr, default) = default
    - add_n(any input combinations longer than 4 (>4) with at least one default type) = default
    - otherwise, ``add_n`` falls all inputs back to default storage and generates default storage

    Defined in src/operator/tensor/elemwise_sum.cc:L155
    This function support variable length of positional input.

    Parameters
    ----------
    args : Symbol[]
        Positional input arguments

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

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


def charset_to_encoding(name):
    """Convert MySQL's charset name to Python's codec name"""
    if name in ('utf8mb4', 'utf8mb3'):
        return 'utf8'
    return name


def get_output_producers(ssa):
    """
    Given a ssa in the format produced by get_ssa(), returns a map from
    versioned blob into the operator index that produces that version of
    the blob. A versioned blob is a tuple (blob_name, version).
    """
    producers = {}
    for i, (_inputs, outputs) in enumerate(ssa):
        for o in outputs:
            producers[o] = i
    return producers


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


def p_fieldlist_many(p):
    """fieldlist : fieldlist ',' identifier  """
    if p[1] is None:
        p[0] = [p[3]]
    else:
        p[1].append(p[3])
        p[0] = p[1]


def s_one_pre(topics):
    """Performs segmentation on a list of topics.

    Notes
    -----
    Segmentation is defined as
    :math:`s_{pre} = {(W', W^{*}) | W' = w_{i}; W^{*} = {w_j}; w_{i}, w_{j} \\in W; i > j}`.

    Parameters
    ----------
    topics : list of np.array
        list of topics obtained from an algorithm such as LDA.

    Returns
    -------
    list of list of (int, int)
        :math:`(W', W^{*})` for all unique topic ids.

    Examples
    --------
    .. sourcecode:: pycon

        >>> import numpy as np
        >>> from gensim.topic_coherence import segmentation
        >>>
        >>> topics = [np.array([1, 2, 3]), np.array([4, 5, 6])]
        >>> segmentation.s_one_pre(topics)
        [[(2, 1), (3, 1), (3, 2)], [(5, 4), (6, 4), (6, 5)]]

    """
    s_one_pre_res = []
    for top_words in topics:
        s_one_pre_t = []
        for w_prime_index, w_prime in enumerate(top_words[1:]):
            for w_star in top_words[:w_prime_index + 1]:
                s_one_pre_t.append((w_prime, w_star))
        s_one_pre_res.append(s_one_pre_t)
    return s_one_pre_res


def generate_sql_query(project, dataset_id, table_id, columns=None,
    conditions=None):
    """
    Generates SQL query for querying a BigQuery dataset table
    :param project: project id
    :param dataset_id: bigquery dataset id
    :param table_id: bigquery table id
    :param columns: Array. Columns to select
    :param conditions: Array. conditions the data to retrive needs to satisfy
    :return: STRING of sql
    """
    bq_table = f'{project}.{dataset_id}.{table_id}'
    select = ''
    where_clause = ''
    if not columns:
        select = '*'
    else:
        last_col = len(columns) - 1
        for col in columns:
            if col == columns[last_col]:
                select += f'{col}'
            else:
                select += f'{col}, '
    if conditions:
        last_cond = len(conditions) - 1
        for condition in conditions:
            where_clause = 'WHERE'
            if condition == conditions[last_cond]:
                where_clause += f' {condition}'
            else:
                where_clause += f' {condition} AND'
    query_string = f'SELECT {select} FROM `{bq_table}` {where_clause}'
    return query_string


def sdbm(s):
    """Generic purpose string hash function (see http://www.cse.yorku.ca/~oz/hash.html)"""
    h = 0
    for c in s:
        h = ord(c) + (h << 6) + (h << 16) - h
        h &= 18446744073709551615
    return h


def generate_credential_report():
    """
    Generates a credential report for the AWS account. For more information about the credential report, see Getting Credential Reports in the IAM User Guide .
    See also: AWS API Documentation

    :example: response = client.generate_credential_report()

    :rtype: dict
    :return: {
        'State': 'STARTED'|'INPROGRESS'|'COMPLETE',
        'Description': 'string'
    }

    """
    pass


@staticmethod
def _is_indirect_jump(_, sim_successors):
    """
        Determine if this SimIRSB has an indirect jump as its exit
        """
    if sim_successors.artifacts['irsb_direct_next']:
        return False
    default_jumpkind = sim_successors.artifacts['irsb_default_jumpkind']
    if default_jumpkind not in ('Ijk_Call', 'Ijk_Boring', 'Ijk_InvalICache'):
        return False
    return True


def _from_iterable(iterables):
    """
    itertools.chain.from_iterable alternative.

    >>> list(_from_iterable([[1, 2], [3, 4]]))
    [1, 2, 3, 4]
    """
    for itr in iterables:
        for element in itr:
            yield element


def get_slice_in_dimension(volume, dimension, index):
    """From the given volume get a slice on the given dimension (x, y, z, ...) and then on the given index.

    Args:
        volume (ndarray): the volume, 3d, 4d or more
        dimension (int): the dimension on which we want a slice
        index (int): the index of the slice

    Returns:
        ndarray: A slice (plane) or hyperplane of the given volume
    """
    ind_pos = [slice(None)] * volume.ndim
    ind_pos[dimension] = index
    return volume[tuple(ind_pos)]


@classmethod
def get_context(cls):
    """Returns a user defined context. Override this in your ServiceBase
        subclass to customize context generation."""
    return None


def get_eventid(event):
    """Event id from event"""
    return str(event.resource_id).split('/')[-1]


def use_arraytype(arraytype):
    """pygame.sndarray.use_arraytype (arraytype): return None

    DEPRECATED - only numpy arrays are now supported.
    """
    arraytype = arraytype.lower()
    if arraytype != 'numpy':
        raise ValueError('invalid array type')


def content_disposition_value(file_name):
    """Return the value of a Content-Disposition HTTP header."""
    return 'attachment;filename="{}"'.format(file_name.replace('"', '_'))


@staticmethod
def p_address_extension(p):
    """address_extension : ADDRESS_EXTENSION_FREE
                             | ADDRESS_EXTENSION_ODT
                             | ADDRESS_EXTENSION_DAQ"""
    p[0] = p[1]


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


def rename_CHI_cols(data):
    """
    names columns of RGA data like they would be from PyExpLabSys+cinfdata
    """
    data_cols = data['data_cols'].copy()
    for col_0 in data_cols:
        for c0, c in [('Time/s', 'time/s'), ('Potential/V', 'Ewe/V'), (
            'Current/A', 'I/A'), ('Charge/C', '(Q-Qo)/C')]:
            if c0 in col_0:
                col = c
                break
        else:
            continue
        data[col] = data[col_0].copy()
        data['col_types'][col] = 'EC'
        data['data_cols'].add(col)
        print(col_0 + ' copied to ' + col)
    if 'I/A' in data and 'I/mA' not in data:
        data['I/mA'] = data['I/A'] * 1000.0
        data['col_types']['I/mA'] = 'EC'
        data['data_cols'].add('I/mA')


def get_shell_cmd(pmconf, rm=False):
    """Form the shell command with the right package manager.
    It must be ready to append the packages list.

    - pmconf: tuple: name of pm, dict with conf (file, pacman, etc).

    Return: a cmd ready to run (str).
    """
    pacman = None
    un_install = 'install'
    if rm:
        un_install = 'uninstall'
    if not pmconf:
        print('Package manager not found. Abort.')
        return 0
    conf = pmconf[1]
    cmd = '{} {} {}'.format(conf.get('sudo', 'sudo'), conf.get('pacman',
        pmconf[0]), conf.get(un_install, un_install))
    return cmd


def add(*text):
    """Adds an entry to the to-do list.

    :param text: The text associated with the entry.
    """
    return 'OK I will remember that.'


def to_tractime(t):
    """Convert time to trac time format.
    Type of t needs float, str or int."""
    st = ''
    if isinstance(t, str):
        st = t
    else:
        st = repr(t)
    st = ''.join(st.split('.'))
    if len(st) > 16:
        st = st[0:16]
    elif len(st) < 16:
        st = st + '0' * (16 - len(st))
    return int(st)


def filter_date_range_for_carbs(starts, values, absorptions, start_date,
    end_date):
    """ Returns an array of elements filtered by the specified date range.

    Arguments:
    starts -- start dates (datetime)
    values -- carb values (g)
    absorptions -- absorption times for entries

    start_date -- the earliest date of elements to return
    end_date -- the last date of elements to return

    Output:
    Filtered carb entries in format (starts, values, absorptions)
    """
    assert len(starts) == len(values) == len(absorptions
        ), 'expected input shapes to match'
    filtered_starts, filtered_values, filtered_absorptions = [], [], []
    for i in range(0, len(starts)):
        if start_date and starts[i] < start_date:
            continue
        if end_date and starts[i] > end_date:
            continue
        filtered_starts.append(starts[i])
        filtered_values.append(values[i])
        filtered_absorptions.append(absorptions[i])
    assert len(filtered_starts) == len(filtered_values) == len(
        filtered_absorptions), 'expected output shapes to match'
    return filtered_starts, filtered_values, filtered_absorptions


def get_next_batch(x, y, batch_idx, batch_size):
    """ Fetch next batch from data set for training.

    :param x: Feature matrix of size (num_samples, num_features).
    :param y: Label matrix of size (num_samples, 1)
    :param batch_idx: Index of the current batch.
    :param batch_size: Size of the batch
    :return: Tuple containing the current x and y batch.
    """
    start = batch_idx * batch_size
    end = (batch_idx + 1) * batch_size
    end = min(end, len(x) + 1)
    return x[start:end], y[start:end]


def indent_code(input_string):
    """
    Split code by newline character, and prepend 4 spaces to each line.
    """
    lines = input_string.strip().split('\n')
    output_string = ''
    for line in lines:
        output_string += '    {}\n'.format(line)
    output_string += '\n'
    return output_string


@staticmethod
def validate(data):
    """
        Validates `data` for use in this container
        """
    return hasattr(data, 'count') and callable(data.count) and hasattr(data,
        'order_by') and callable(data.order_by)


def run_async_gateway(gateway, stop_task=None):
    """Run an async gateway."""
    try:
        gateway.tasks.loop.run_until_complete(gateway.start_persistence())
        gateway.tasks.loop.run_until_complete(gateway.start())
        gateway.tasks.loop.run_forever()
    except KeyboardInterrupt:
        gateway.tasks.loop.run_until_complete(gateway.stop())
        if stop_task:
            gateway.tasks.loop.run_until_complete(stop_task)
        gateway.tasks.loop.close()


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


def device_id_generator():
    """
    Generate ID for unnamed device.
    :return: string
    """
    i = 0
    while True:
        yield u'Device_{}'.format(i)
        i += 1


def textbox_add():
    """Add a new text box

    """
    pass


def get_ipv6_range(numeric_netaddr, prefix_len):
    """
    Return the smallest and biggest possible IPv6 address of the specified
    network address (in numeric representation) and prefix length.
    """
    mask_bin_full = 340282366920938463463374607431768211455
    mask_inverted = 128 - prefix_len
    mask_bin = mask_bin_full >> mask_inverted << mask_inverted
    range_start = numeric_netaddr & mask_bin
    range_end = range_start | (1 << mask_inverted) - 1
    return range_start, range_end


@staticmethod
def _signextend(value):
    """Sign extend a 10-bit number

        Derived from https://stackoverflow.com/questions/32030412/
                             twos-complement-sign-extension-python

        """
    return (value & 511) - (value & 512)


def _update_recurs(dict1, dict2):
    """Update a dictionary with one level down."""
    for f in dict2:
        if f in dict1:
            dict1[f].update(dict2[f])
        else:
            dict1[f] = dict2[f]


def get_location():
    """Returns location
        """


def brew_strip_pkg_name(package):
    """Strip the tap information of a fully qualified package name.

    :returns: Unqualified package name. E.g. 'foo-pkg' for input
        'ros/hydro/foo-pkg'
    """
    if not isinstance(package, str):
        package = package.decode()
    return package.split('/')[-1]


@classmethod
def _init_default(cls, dialect, connection, dbapi_connection):
    """Initialize execution context for a ColumnDefault construct."""
    self = cls.__new__(cls)
    self.root_connection = connection
    self._dbapi_connection = dbapi_connection
    self.dialect = connection.dialect
    self.execution_options = connection._execution_options
    self.cursor = self.create_cursor()
    return self


def numericbrute(rangelist, zeropadding=0, template=None, defaults=False,
    staticbrute=[]):
    """numericbrute gives a yield generator. accepts either zeropadding or template as optional argument"""
    for statictry in staticbrute:
        yield statictry
    if defaults:
        for i in range(1000, 9999, 100):
            yield '%04i' % i
        for i in range(1001, 9999, 100):
            yield '%04i' % i
        for i in range(0, 9):
            for l in range(1, 8):
                yield '%s' % i * l
        for i in range(100, 999):
            yield '%s' % i
        for i in range(10000, 99999, 100):
            yield '%04i' % i
        for i in range(10001, 99999, 100):
            yield '%04i' % i
        for i in ['1234', '2345', '3456', '4567', '5678', '6789', '7890',
            '0123']:
            yield i
        for i in ['12345', '23456', '34567', '45678', '56789', '67890', '01234'
            ]:
            yield i
    if zeropadding > 0:
        format = '%%0%su' % zeropadding
    elif template is not None:
        format = template
    else:
        format = '%u'
    format % 1
    for x in rangelist:
        for y in x:
            r = format % y
            yield r


def expandPrefix(prefix):
    """Expand prefix string by adding a trailing period if needed.

    expandPrefix(p) should be used instead of p+'.' in most contexts.
    """
    if prefix and not prefix.endswith('.'):
        return prefix + '.'
    return prefix


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 get_ties(point_margin):
    """Determine a tie based on the point margin.

    Parameters
    ----------
    point_margin : int
        The point margin can be positive, zero, or negative.

    Returns
    -------
    tied : int
        If the point margin is equal to 0, return 1, else 0.

    """
    tied = 1 if point_margin == 0 else 0
    return tied


@classmethod
def _stripe_object_to_refunds(cls, target_cls, data, charge):
    """
        Retrieves Refunds for a charge
        :param target_cls: The target class to instantiate per refund
        :type target_cls: Type[djstripe.models.Refund]
        :param data: The data dictionary received from the Stripe API.
        :type data: dict
        :param charge: The charge object that refunds are for.
        :type charge: djstripe.models.Refund
        :return:
        """
    refunds = data.get('refunds')
    if not refunds:
        return []
    refund_objs = []
    for refund_data in refunds.auto_paging_iter():
        item, _ = target_cls._get_or_create_from_stripe_object(refund_data,
            refetch=False)
        refund_objs.append(item)
    return refund_objs


@classmethod
def process_return_type(cls, return_type):
    """Process an @return_type decorator."""
    ret_type = return_type.args[0]
    return None


def splitSSsym(SSymbol):
    """
    Splits supersymmetry symbol into two lists of strings
    """
    mssym = SSymbol.replace(' ', '').split(')')
    if len(mssym) > 1:
        modsym, gensym = mssym
    else:
        modsym = mssym[0]
        gensym = ''
    modsym = modsym.replace(',', '')
    if "1'" in modsym:
        gensym = gensym[:-1]
    modsym = modsym.replace("1'", '')
    if gensym in ['0', '00', '000', '0000']:
        gensym = ''
    nfrac = modsym.count('/')
    modsym = modsym.lstrip('(')
    if nfrac == 0:
        modsym = list(modsym)
    elif nfrac == 1:
        pos = modsym.find('/')
        if pos == 1:
            modsym = [modsym[:3], modsym[3], modsym[4]]
        elif pos == 2:
            modsym = [modsym[0], modsym[1:4], modsym[4]]
        else:
            modsym = [modsym[0], modsym[1], modsym[2:]]
    else:
        lpos = modsym.find('/')
        rpos = modsym.rfind('/')
        if lpos == 1 and rpos == 4:
            modsym = [modsym[:3], modsym[3:6], modsym[6]]
        elif lpos == 1 and rpos == 5:
            modsym = [modsym[:3], modsym[3], modsym[4:]]
        else:
            modsym = [modsym[0], modsym[1:4], modsym[4:]]
    gensym = list(gensym)
    return modsym, gensym


def _recipe_type(raw_configuration):
    """
    Given a raw repository configuration, returns its recipe type.

    :param raw_configuration: configuration as returned by the SCRIPT_NAME_GET
        groovy script.
    :type raw_configuration: dict
    :return: Group, Proxy or Hosted
    """
    return raw_configuration['recipeName'].split('-')[1].title()


def matplotlib_colourmap(name, samples=16):
    """
    Import a colourmap from a matplotlib

    Parameters
    ----------
    name : str
        Name of the matplotlib colourmap preset to import
    samples : int
        Number of samples to take for LinearSegmentedColormap type

    Returns
    -------
    list
        List of colours ready to be loaded by colourmap()
    """
    try:
        import matplotlib.pyplot as plt
        cmap = plt.get_cmap(name)
        if hasattr(cmap, 'colors'):
            data = cmap.colors
            if len(data) == 256 and samples is not None:
                subsample = int(256 / samples)
                data = data[0::subsample]
            return data
        if samples == None:
            samples = 16
        colours = []
        for i in range(samples):
            pos = i / float(samples - 1)
            colours.append(cmap(pos))
        return colours
    except Exception as e:
        return name
    return []


def inactivate():
    """Inactivate an active object"""


def mock(args):
    """execute subcommand mock"""
    if 'marker' in args.type.lower():
        from liesl.streams.mock import MarkerMock
        m = MarkerMock()
    else:
        from liesl.streams.mock import Mock
        m = Mock()
    print(m)
    m.start()


def polyhedron(shape, vertices, position=0.5, smoothing=False):
    """
    Render a simple polyhedron.

    Args:
        shape (int|Sequence[int]): The shape of the container in px.
        vertices (Sequence[Sequence[float]): Coordinates of the vertices in px.
        position (float|Sequence[float]): The position of the center.
            Values are relative to the lowest edge.
            They are interpreted as relative to the shape.
        smoothing (bool|int|float|None): The smoothing of the border.
            If None or False, no smoothing is performed and the data type of
            the result is bool.
            If int or float, smooths the border transition and the data type of
            the result is float.
            When the value is equal to 1 or True, the smoothing emulate
            the spatial anti-aliasing.

    Returns:
        rendered (np.ndarray[bool|float]): The rendered geometrical object.
            The data type depends on the value and type of smoothing.
    """
    raise NotImplementedError


def confirm_sign_up(ClientId=None, SecretHash=None, Username=None,
    ConfirmationCode=None, ForceAliasCreation=None):
    """
    Confirms registration of a user and handles the existing alias from a previous user.
    See also: AWS API Documentation

    :example: response = client.confirm_sign_up(
        ClientId='string',
        SecretHash='string',
        Username='string',
        ConfirmationCode='string',
        ForceAliasCreation=True|False
    )

    :type ClientId: string
    :param ClientId: [REQUIRED]
            The ID of the client associated with the user pool.

    :type SecretHash: string
    :param SecretHash: A keyed-hash message authentication code (HMAC) calculated using the secret key of a user pool client and username plus the client ID in the message.

    :type Username: string
    :param Username: [REQUIRED]
            The user name of the user whose registration you wish to confirm.

    :type ConfirmationCode: string
    :param ConfirmationCode: [REQUIRED]
            The confirmation code sent by a user's request to confirm registration.

    :type ForceAliasCreation: boolean
    :param ForceAliasCreation: Boolean to be specified to force user confirmation irrespective of existing alias. By default set to False . If this parameter is set to True and the phone number/email used for sign up confirmation already exists as an alias with a different user, the API call will migrate the alias from the previous user to the newly created user being confirmed. If set to False , the API will throw an AliasExistsException error.

    :rtype: dict
    :return: {}

    """
    pass