@classmethod
def from_subject(cls, subject, owner):
    """Constructs a `HelpForClizeDocstring` instance and populates it with
        data from a `.Clize` instance.

        It uses the parameters' `.parser.Parameter.prepare_help` and reads
        the docstrings of functions from which the parameters originate.

        :param .Clize subject: The `.Clize` instance to document.
        :param object owner: The object of which ``subject`` is a member of,
            or `None`.

            This typically has a value if a CLI is defined as a class::

                class MyCli(object):
                    @clize.Clize
                    def cli(self, param):
                        ...

            ``owner`` would refer to an instance of ``MyCli``.
        """
    ret = cls.blank_from_signature(subject.signature)
    ret.add_from_parameters(subject.signature.parameters.values())
    ret.add_from_parameter_sources(subject)
    return ret


def Calc_Bulk_surface_resistance(sl_es_24, Rn_24, Refl_rad_water, air_dens,
    esat_24, eact_24, rah_pm_act, ETA_24, Lhv, Psychro_c):
    """
    Function to calculate the bulk surface resistance
    """
    bulk_surf_resis_24 = (((sl_es_24 * (Rn_24 - Refl_rad_water) + air_dens *
        1004 * (esat_24 - eact_24) / rah_pm_act) / (ETA_24 * Lhv / 86400) -
        sl_es_24) / Psychro_c - 1.0) * rah_pm_act
    bulk_surf_resis_24[ETA_24 <= 0.0] = 100000.0
    bulk_surf_resis_24 = bulk_surf_resis_24.clip(0.0, 100000.0)
    return bulk_surf_resis_24


def freestyle_lineset_copy():
    """Copy the active line set to a buffer

    """
    pass


def zero_or_greater(name, value):
    """Verify that value is zero or greater. If not, 'name'
    will be used in error message

    :raises: ValueError

    """
    if int(value) < 0:
        errmsg = '{} must be >= 0, but got {}'.format(name, value)
        raise ValueError(errmsg)


@classmethod
def usage(cls):
    """Print usage of provider."""
    print(f'{cls.__doc__} Supported query types:')
    for ioc_key in sorted(cls._IOC_QUERIES):
        ioc_key_elems = ioc_key.split('-', maxsplit=1)
        if len(ioc_key_elems) == 1:
            print(f'\tioc_type={ioc_key_elems[0]}')
        if len(ioc_key_elems) == 2:
            print(
                f'\tioc_type={ioc_key_elems[0]}, ioc_query_type={ioc_key_elems[1]}'
                )


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


def json_to_yaml(content):
    """
    TODO: convert json to yaml
    """
    return content


def escape_str(assertion_value: str) ->str:
    """
    Replace all special characters found in assertion_value
    by quoted notation.
    """
    assert isinstance(assertion_value, str), TypeError(
        'Expected assertion_value to be unicode (str), got %r' % (
        assertion_value,))
    return assertion_value.replace('\\', '\\5c').replace('*', '\\2a').replace(
        '(', '\\28').replace(')', '\\29').replace('\x00', '\\00')


def get_opt_out_collection(owner_id):
    """ Return the opt out collection for the specified owner.

        :param str owner_id:
            The id of the owner of the opt out store.
        """


@classmethod
def list(cls, options=None):
    """ List certificates."""
    options = options or {}
    return cls.call('cert.list', options)


@staticmethod
def mp_score_geneset(geneset, diffusion):
    """Static method for calculating geneset score

        For multiprocessing use

        Args:
            geneset (pd.Series): boolean pd.Series indicating which scoresVector genes are in the geneset
            scoresVector (matrix): vector with scores
            computedMatrix (matrix): diffusion kernel

        Returns:
            score (float)
        """
    score = diffusion.T[geneset].sum()
    return score


def _fmt_metric(value, show_stdv=True):
    """format metric string"""
    if len(value) == 2:
        return '%s:%g' % (value[0], value[1])
    if len(value) == 3:
        if show_stdv:
            return '%s:%g+%g' % (value[0], value[1], value[2])
        return '%s:%g' % (value[0], value[1])
    raise ValueError('wrong metric value')


@staticmethod
def get_sip_flags(target_configuration):
    """ Return the list of package specific flags to pass to SIP.
        target_configuration is the target configuration.
        """
    major = target_configuration.qt_version >> 16 & 255
    minor = target_configuration.qt_version >> 8 & 255
    patch = target_configuration.qt_version & 255
    if (major, minor) >= (5, 13):
        patch = 0
    elif (major, minor) == (5, 12):
        if patch > 4:
            patch = 4
    version_tag = 'QtWebEngine_%d_%d_%d' % (major, minor, patch)
    return ['-t', version_tag]


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

    The ".dev0" means dirty.

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


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

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

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


def _get_mro(cls):
    """Get an mro for a type or classic class"""
    if not isinstance(cls, type):

        class cls(cls, object):
            pass
        return cls.__mro__[1:]
    return cls.__mro__


def processing(scene, channel):
    """ Return the image difference

    * inverse of distance (i.e. distance -> nearness)
    """
    scene[(...), (3), :] = 1 / scene[(...), (3), :]
    return scene[(...), (channel), :]


def _set_summary_fields(ctx):
    """Sets related experiment viewer urls.

    """
    ctx.ext.summary_fields = ctx.doc.canonical_id.upper(), ctx.doc.long_name


@staticmethod
def index_of_ckpt_with_iter(ckpts_with_iterations, target_ckpt_itr):
    """ given a sorted list `ckpts_with_iterations` of (ckpt_iter, ckpt_path), returns the smallest index i in that
        list where target_ckpt_itr >= ckpt_iter """
    for i, (ckpt_iter, _) in reversed(list(enumerate(ckpts_with_iterations))):
        if target_ckpt_itr >= ckpt_iter:
            return i
    raise ValueError('*** Cannot find ckpt with iter >= {} in {}'.format(
        target_ckpt_itr, ckpts_with_iterations))


@staticmethod
def decode_esc_chars(data):
    """Replace 0xDBDC with 0xCO and 0xDBDD with 0xDB"""
    result = []
    while len(data):
        char = data.pop(0)
        if char == 219:
            char2 = data.pop(0)
            if char2 == 220:
                result.append(192)
            elif char2 == 221:
                result.append(219)
            else:
                raise Exception('Char 0xDB NOT followed by 0xDC or 0xDD')
        else:
            result.append(char)
    return result


def zoom(params, factor):
    """
    Applies a zoom on the current parameters.

    Computes the top-left plane-space coordinates from the Mandelbrot-space coordinates.

    :param params: Current application parameters.
    :param factor: Zoom factor by which the zoom ratio is divided (bigger factor, more zoom)
    """
    params.zoom /= factor
    n_x = params.mb_cx / params.zoom
    n_y = params.mb_cy / params.zoom
    params.plane_x0 = int((n_x + 1.0) * params.plane_w / (2.0 * params.
        plane_ratio)) - params.plane_w // 2
    params.plane_y0 = int((n_y + 1.0) * params.plane_h / 2.0
        ) - params.plane_h // 2


def cropRect(rect, cropTop, cropBottom, cropLeft, cropRight):
    """
	Crops a rectangle by the specified number of pixels on each side.

	The input rectangle and return value are both a tuple of (x,y,w,h).
	"""
    x, y, w, h = rect
    x += cropLeft
    y += cropTop
    w -= cropLeft + cropRight
    h -= cropTop + cropBottom
    return x, y, w, h


def snap_selected_to_cursor(use_offset: bool=True):
    """Snap selected item(s) to cursor

    :param use_offset: Offset
    :type use_offset: bool
    """
    pass


def ColumnValidator(parent, filepointer, nCol=5):
    """Validate a file to check that it contains columns of numbers"""
    l = filepointer.readline()
    line = 1
    while l[0] in ['#', '(']:
        l = filepointer.readline()
        line += 1
    for i in range(10):
        S = l.split()
        if len(S) < nCol:
            parent.errors = 'line ' + str(line) + ': invalid input\n' + l
            return False
        for v in S[:nCol]:
            try:
                float(v)
            except ValueError:
                parent.errors = 'line ' + str(line
                    ) + """: string found where a number is expected
""" + l
                return False
        l = filepointer.readline()
        line += 1
    return True


@classmethod
def remove_resource_decorator(cls, service_name, resource_name, method_names):
    """
    Removes the decorator function from the class' statically registered decorators.

    Class-registered decorators will be applied to every DecoratedSession object created.

    Arguments:
    service_name -- the boto3 name of the service to apply the decorator to.
    resource_name -- the boto3 name of the resource of the service to apply the decorator to.
    method_names -- one or more method names of the resource to apply the decorator to. Single names can be a string.
    """
    assert isinstance(method_names, (str, list, tuple, set, None)
        ), 'method_names must be a string, list, tuple, set or None'
    event_name = 'creating-resource-class.{}.{}'.format(service_name,
        resource_name)
    if not method_names or isinstance(method_names, str):
        cls.__remove_decorator(event_name, method_names)
    else:
        for method_name in method_names:
            cls.__remove_decorator(event_name, method_name)


def sizeof_fmt(num, suffix='B'):
    """Convert any number to human readable size. By Fred Cirera"""
    for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
        if abs(num) < 1024.0:
            return '%3.1f %s%s' % (num, unit, suffix)
        num /= 1024.0
    return '%.1f %s%s' % (num, 'Yi', suffix)


@staticmethod
def _get_disease(dct, rel, dst):
    """Get disease associated with a pathway."""
    assert dst['schemaClass'] == 'Disease'
    assert dst['databaseName'] == 'DOID'
    assert rel['stoichiometry'] == 1
    if 'disease' not in dct:
        dct['disease'] = [dst['displayName']]
    else:
        dct['disease'].append(dst['displayName'])


def no_none_string(string):
    """Determine whether a string is the literal 'None'.

    Args:
        string: (string) will be tested

    Returns:
        whether ot not the string is 'None'
    """
    return not string == 'None'


@staticmethod
def rename_energies(gmx_energy):
    """Rename GROMACS energy terms to PyRETIS convention."""
    energy_map = {'potential': 'vpot', 'kinetic en.': 'ekin', 'temperature':
        'temp', 'total energy': 'etot', 'pressure': 'press'}
    energy = {}
    for key, val in gmx_energy.items():
        name = energy_map.get(key, key)
        energy[name] = val[0]
    return energy


def convert_instance_profile_to_role(arn, iam_client):
    """Convert the arn to an instance profile

    Both role and instance profile arns are accepted
    raises botocore.exceptions.ClientError if there's a problem with the iam_client
    raises ValueError if there's a problem converting the arn to a role
    """
    if ':instance-profile/' in arn:
        name = arn.split(':instance-profile/')[-1]
        return iam_client.get_instance_profile(InstanceProfileName=name)[
            'InstanceProfile']['Roles'][0]['Arn']
    elif ':role/' in arn:
        return arn
    else:
        return ValueError(
            'Arn {} not recognized as either an instance-profile or a role'
            .format(arn))


def compare_first_4k(file, file_to_compare):
    """
        Should compare the first 4k of each file to see if they match
    """
    file_bytes = b''
    file_to_compare_bytes = b''
    with open(file, 'rb') as f:
        file_bytes = f.read(4096)
        if len(file_bytes) != 4096:
            raise IOError(
                'Filegardener - compare_first_4k: Did not read the expected file size:{}'
                .format(4096))
    with open(file_to_compare, 'rb') as f:
        file_to_compare_bytes = f.read(4096)
        if len(file_bytes) != 4096:
            raise IOError(
                'Filegardener - compare_first_4k: Did not read the expected file size:{}'
                .format(4096))
    if file_bytes == file_to_compare_bytes:
        return True
    else:
        return False


def debug_trace():
    """Set a tracepoint in the Python debugger that works with Qt"""
    from qtpy.QtCore import pyqtRemoveInputHook
    from pdb import set_trace
    pyqtRemoveInputHook()
    set_trace()


@staticmethod
def columnCount():
    """Provides the number of columns"""
    return 2


def Alphabet(texte):
    """Retourne les valeurs unique du texte donnee en parametre"""
    if isinstance(texte, bytes):
        texte = ''.join(map(chr, texte))
    return ''.join(sorted(list(set(texte))))


def get_rollout_size(rollout):
    """Gets a rollout's size.

    Args:
      rollout: a rollout (dict, a return from `sample_rollout` func).

    Returns:
      length of the rollout (int)
    """
    return len(rollout['reward'])


def finite_diff(expression, variable, increment=1):
    """
    Takes as input a polynomial expression and the variable used to construct
    it and returns the difference between function's value when the input is
    incremented to 1 and the original function value. If you want an increment
    other than one supply it as a third argument.

    Examples
    ========

    >>> from sympy.abc import x, y, z, k, n
    >>> from sympy.series.kauers import finite_diff
    >>> from  sympy import Sum
    >>> finite_diff(x**2, x)
    2*x + 1
    >>> finite_diff(y**3 + 2*y**2 + 3*y + 4, y)
    3*y**2 + 7*y + 6
    >>> finite_diff(x**2 + 3*x + 8, x, 2)
    4*x + 10
    >>> finite_diff(z**3 + 8*z, z, 3)
    9*z**2 + 27*z + 51
    """
    expression = expression.expand()
    expression2 = expression.subs(variable, variable + increment)
    expression2 = expression2.expand()
    return expression2 - expression


def disable_session_expiry_refresh(f):
    """
	Security policy dictates that the user's session should time out after a set duration.
	The user's session is automatically refreshed (that is, the expiration date
	of their session is moved forward to 30 minutes after the request time) whenever
	the user performs an action. Pages such as the Calendar, Tool Control, and Status Dashboard
	all have polling AJAX requests to update information on the page. These regular polling
	requests should not refresh the session (because it does not indicate the user took
	an action). Place this decorator on any view that is regularly polled so that the
	user's session is not refreshed.
	"""
    f.disable_session_expiry_refresh = True
    return f


def energy_res_egret(e):
    """EGRET's energy resolution :math:`\\Delta E / E`.

    This is the most optimistic value, taken from
    `sec. 4.3.3 <http://adsabs.harvard.edu/doi/10.1086/191793>`_.
    """
    return 0.18


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

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

        key : str
            Fluid property to retrieve.

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

            .. math::

                val = \\begin{cases}
                10^5 & \\text{key = 'p'}\\\\
                5 \\cdot 10^5 & \\text{key = 'h'}
                \\end{cases}
        """
    if key == 'p':
        return 100000.0
    elif key == 'h':
        return 500000.0


@classmethod
def assert_valid_address(cls, address):
    """
        Raise an exception if the specified email address is not compliant
        with RFC 2822.

        :param address: an email address.

        @raise AssertError: if the specified email address is not compliant
            with RFC 2822.
        """
    assert cls.is_address_valid(address
        ), 'The email address "%s" is not valid' % address


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 dayOfYear():
    """Return the day of the year, in context of the timezone
        representation of the object"""


def create_group(Path=None, GroupName=None):
    """
    Creates a new group.
    For information about the number of groups you can create, see Limitations on IAM Entities in the IAM User Guide .
    See also: AWS API Documentation

    Examples
    The following command creates an IAM group named Admins.
    Expected Output:

    :example: response = client.create_group(
        Path='string',
        GroupName='string'
    )

    :type Path: string
    :param Path: The path to the group. For more information about paths, see IAM Identifiers in the IAM User Guide .
            This parameter is optional. If it is not included, it defaults to a slash (/).
            This paramater allows (per its regex pattern ) a string of characters consisting of either a forward slash (/) by itself or a string that must begin and end with forward slashes, containing any ASCII character from the ! (u0021) thru the DEL character (u007F), including most punctuation characters, digits, and upper and lowercased letters.

    :type GroupName: string
    :param GroupName: [REQUIRED]
            The name of the group to create. Do not include the path in this value.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: =,.@-. The group name must be unique within the account. Group names are not distinguished by case. For example, you cannot create groups named both 'ADMINS' and 'admins'.

    :rtype: dict
    :return: {
        'Group': {
            'Path': 'string',
            'GroupName': 'string',
            'GroupId': 'string',
            'Arn': 'string',
            'CreateDate': datetime(2015, 1, 1)
        }
    }

    """
    pass


@staticmethod
def _positive_tail_set(row):
    """
        Takes as input a row from the vol_adj_price DataFrame and then returns a list of names of the securites in the
        positive tail set, for this specific row date.

        This method is used in an apply() setting.

        :param row: (Series) of volatility adjusted prices.
        :return: (list) of securities in the positive tail set.
        """
    return list(row[row == 1].index)


def trunc_end_of_file(name) ->str:
    """
    Take only the start of the filename to avoid error with Python and Windows

    :param str name: Filename to truncate
    :return str:
    """
    return name[:240]


def reduction_collapses(inout, axis, verbose=0):
    """
    This collapse dimensions that are not needed when computing
    reduction.  This is usefull as it lower the indexing computation
    that is heavier on gpu then on cpu.

    This is a generic version. It collapse dimensions at any place in
    the shape.
    @param: inout: tuple(input, output)
    @param: axis: None, interger, list of 1 interger
                  The axis over witch we will do reduction.
    @return: (ndims, (input dims, input strides, input pattern), out strides)
             after collapsing.

    :note: we suppose that we can always collapse the output dimensions.
    """
    input = inout[0]
    out = inout[1]
    if axis is None:
        if input.flags['C_CONTIGUOUS'] or input.flags['F_CONTIGUOUS']:
            return 0, ((input.size,), (input.itemsize,), axis), (0,)
    if input.ndim == 1:
        assert axis == [0] or axis == 0 or axis is None
        return 1, (input.shape, input.strides, axis), (0,)
    if not isinstance(axis, (list, tuple)):
        local_axis = [axis]
    else:
        local_axis = list(axis)
    assert axis is None or len(local_axis) == 1
    local_dims = list(input.shape)
    local_str = list(input.strides)
    out_strides = list(out.strides)
    nd_orig = len(local_dims)
    collapsable = [1] * nd_orig
    nd_collapse = nd_orig
    if verbose > 2:
        print('before broadcast collapse')
        print(' nd_collapse', nd_collapse)
        print(' local_dims', local_dims)
        print(' local_str inputs', local_str)
        print(' local_axis', local_axis)
    for id in range(nd_collapse):
        if local_dims[id] == 1:
            for j in range(id + 1, nd_collapse):
                local_dims[j - 1] = local_dims[j]
                local_str[j - 1] = local_str[j]
                if axis is not None:
                    out_strides[j - 2] = out_strides[j - 1]
            if id in local_axis:
                local_axis.remove(id)
            for axis_pos in range(len(local_axis)):
                if local_axis[axis_pos] > id:
                    local_axis[axis_pos] -= 1
            nd_collapse -= 1
            id -= 1
    if verbose > 2:
        print('after broadcast collapse')
        print(' nd_collapse', nd_collapse)
        print(' local_dims', local_dims)
        print(' local_str inputs', local_str)
        print(' local_axis', local_axis)
        print(' out_strides', out_strides)
    nd_collapse_ = [1] * nd_orig
    for i in range(nd_collapse - 1, 0, -1):
        if local_str[i] * local_dims[i] != local_str[i - 1]:
            nd_collapse_[i] = 0
        elif (i in local_axis) != (i - 1 in local_axis):
            nd_collapse_[i] = 0
    if verbose > 1:
        print('nd_collapse_', nd_collapse_)
    nd_collapse2 = nd_collapse
    for i in range(nd_collapse - 1, 0, -1):
        if nd_collapse_[i] == 1:
            local_dims[i - 1] *= local_dims[i]
            local_str[i - 1] = local_str[i]
            for j in range(i + 1, nd_collapse):
                local_dims[j - 1] = local_dims[j]
                local_str[j - 1] = local_str[j]
                if axis is not None:
                    out_strides[j - 2] = out_strides[j - 1]
            if i in local_axis:
                local_axis.remove(i)
            for axis_pos in range(len(local_axis)):
                if local_axis[axis_pos] > i:
                    local_axis[axis_pos] -= 1
            nd_collapse2 -= 1
    nd_collapse = nd_collapse2
    if nd_collapse == 1:
        if local_str[nd_collapse - 1] == input.itemsize:
            nd_collapse = 0
    if verbose:
        print('end collapsing')
        print(' nd_collapse', nd_collapse)
    if verbose > 1:
        print(' local_dims', local_dims)
        print(' local_str inputs', local_str)
        print(' local_axis', local_axis)
        print(' out_strides', out_strides)
    local_dims = local_dims[:nd_collapse]
    local_str = local_str[:nd_collapse]
    out_strides = out_strides[:nd_collapse]
    return nd_collapse, (local_dims, local_str, local_axis), out_strides


def tokenizeValues(values, name):
    """Returns an iterable of tokens for the values of the given index
        name"""


def get_range_bins_to_avg(rad1_rng, rad2_rng):
    """
    Compares the resolution of two radars and determines if and which radar
    has to be averaged and the length of the averaging window

    Parameters
    ----------
    rad1_rng : array
        the range of radar 1
    rad2_rng : datetime
        the range of radar 2

    Returns
    -------
    avg_rad1, avg_rad2 : Boolean
        Booleans specifying if the radar data has to be average in range
    avg_rad_lim : array with two elements
        the limits to the average (centered on each range gate)

    """
    rad1_res = rad1_rng[1] - rad1_rng[0]
    rad2_res = rad2_rng[1] - rad2_rng[0]
    res_ratio = rad1_res / rad2_res
    avg_rad1 = False
    avg_rad2 = False
    avg_rad_lim = None
    if res_ratio > 1.5:
        avg_rad2 = True
        nbins = int(res_ratio)
        if nbins % 2 == 0:
            avg_rad_lim = [-int(nbins / 2) - 1, int(nbins / 2)]
        else:
            avg_rad_lim = [-int((nbins - 1) / 2), int((nbins - 1) / 2)]
    elif res_ratio < 1.0 / 1.5:
        avg_rad1 = True
        nbins = int(1.0 / res_ratio)
        if nbins % 2 == 0:
            avg_rad_lim = [-int(nbins / 2) - 1, int(nbins / 2)]
        else:
            avg_rad_lim = [-int((nbins - 1) / 2), int((nbins - 1) / 2)]
    return avg_rad1, avg_rad2, avg_rad_lim


def best_analogy_3cosmul(wrap, subframe, a1, b1, a2):
    """
    Find the best b2 to complete the analogy a1 : b1 :: a2 : b2, according
    to the 3CosMul metric.
    """
    va1 = wrap.get_vector(a1)
    vb1 = wrap.get_vector(b1)
    va2 = wrap.get_vector(a2)
    sa1 = subframe.dot(va1)
    sb1 = subframe.dot(vb1)
    sa2 = subframe.dot(va2)
    eps = 1e-06
    mul3cos = (sb1 + 1 + eps) * (sa2 + 1 + eps) / (sa1 + 1 + eps)
    best = mul3cos.dropna().nlargest(4)
    prompt = a1, b1, a2
    for term in best.index:
        if term not in prompt:
            return term


def dict_to_sequence(d):
    """Returns an internal sequence dictionary update."""
    if hasattr(d, 'items'):
        d = d.items()
    return d


def get_object_by_cmis_id(cmis_id, root=False):
    """Return an object by its id, adjusting its if it is a root.
        """


def writelines(iterable):
    """Write a sequence of strings to the file.
        """


def bound_scalar(x, lower, upper):
    """
    Bound x between lower and upper, where x is a scalar value.
    """
    return min(upper, max(lower, x))


@staticmethod
def _recalculate_opts():
    """Returns command options in a form that can be handled by the
        command parser."""
    opts = {'-h': {'type': bool, 'default': False}, '-s': {'type': str,
        'default': None}, '-f': {'type': str, 'default': None}, '-sb': {
        'type': str, 'default': None}, '-e': {'type': str, 'default': None},
        '-d': {'type': str, 'default': None}, '-t': {'type': str, 'default':
        None}}
    return opts


@classmethod
def update_all(cls, sheet):
    """
        Updates the sheet geometry by updating:
        * the edge vector coordinates
        * the edge lengths
        * the face centroids
        * the normals to each edge associated face
        * the face areas
        """
    cls.update_dcoords(sheet)
    cls.update_length(sheet)
    cls.update_centroid(sheet)
    cls.update_normals(sheet)
    cls.update_areas(sheet)
    cls.update_perimeters(sheet)


def _dicts_key_to_key(dictionaries):
    """
    creates a dummy map from the nominal key to the nominal key for
    multiple input dictionaries

    """
    out = {}
    for dicti in dictionaries:
        for key in dicti:
            out[key] = key
    return out


def def_commodities():
    """
    Produces the default commodities for a rickshaw simspec.

    Returns
    ----------
    spec : dict
        Dictionary representation of the niche-link to commodity setup.
    """
    commods = {('mine', 'enrichment'): 'natural_uranium', ('mine',
        'reactor:hwr'): 'natural_uranium_fuel', ('enrichment', 'fuel_fab'):
        'low_enriched_uranium', ('enrichment', 'reactor'):
        'low_enriched_uranium', ('enrichment', 'repository'):
        'enrichment_waste_stream', ('fuel_fab', 'reactor'): 'fresh_fuel', (
        'fuel_fab:uo2', 'reactor:lwr'): 'fresh_uox', ('fuel_fab:triso',
        'reactor:pb'): 'fresh_triso', ('reactor', 'storage'): 'used_fuel',
        ('reactor', 'repository'): 'used_fuel', ('reactor:lwr', 'storage'):
        'used_uox', ('reactor:pb', 'storage'): 'used_triso', ('reactor',
        'separations'): 'used_fuel', ('reactor:lwr', 'separations'):
        'used_uox', ('storage', 'separations'): 'stored_used_fuel', (
        'storage', 'repository'): 'stored_used_fuel', ('separations',
        'fuel_fab'): 'separated_product', ('separations', 'storage'):
        'separated_waste', ('separations', 'repository'): 'separated_waste'}
    return commods


def printHeader(header, character='=', padding=1, newLineBelow=True):
    """ Print a decorated header """
    assert type(character) == str and len(character
        ) == 1, 'Character must be string of length 1.'
    print(' ' * padding + header)
    print(character * (len(header) + padding * 2))
    if newLineBelow:
        print()


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 abort(transactionid):
    """STOMP abort transaction command.

    Rollback whatever actions in this transaction.

    transactionid:
        This is the id that all actions in this transaction.

    """
    return 'ABORT\ntransaction:%s\n\n\x00\n' % transactionid


@classmethod
def get_creatable_methods(cls, store, payment_type, separate):
    """Gets a list of methods that are creatable.
        Eg, you can use them to create new payments.

        :returns: a list of :class:`payment methods <PaymentMethod>`
        """
    methods = []
    for method in cls.get_active_methods(store):
        if not method.operation.creatable(method, payment_type, separate):
            continue
        methods.append(method)
    return methods


def is_empty(it):
    """ Returns True if the iterable `it` is already fully consumed. """
    try:
        next(it)
        return False
    except StopIteration:
        return True


def set_resample_spline_interpolation_order(order):
    """
    Set the spline interpolation order used during resampling of gantry tilted data
    """
    global resample_spline_interpolation_order
    resample_spline_interpolation_order = order


@staticmethod
def get_connection_arguments_model():
    """
        This is needed so the BaseConnection can validate the provided
        model explicitly states the arguments to be passed on each
        send message.
        return = {
            'required_connection_arguments': {
                'required_connection_arg_1': type,
                'required_connection_arg_2': type,
            },
            'optional_connection_arguments': {
                'optional_connection_arg_1': type,
                'optional_connection_arg_2': type,
            },
        }
        """
    return {'required_connection_arguments': {},
        'optional_connection_arguments': {}}


def read_caffe_mean(caffe_mean_file):
    """
    Reads caffe formatted mean file
    :param caffe_mean_file: path to caffe mean file, presumably with 'binaryproto' suffix
    :return: mean image, converted from BGR to RGB format
    """
    import caffe_parser
    import numpy as np
    mean_blob = caffe_parser.caffe_pb2.BlobProto()
    with open(caffe_mean_file, 'rb') as f:
        mean_blob.ParseFromString(f.read())
    img_mean_np = np.array(mean_blob.data)
    img_mean_np = img_mean_np.reshape(mean_blob.channels, mean_blob.height,
        mean_blob.width)
    img_mean_np[([0, 2]), :, :] = img_mean_np[([2, 0]), :, :]
    return img_mean_np


def debug(mode=True):
    """ Change the debug level.
    There is only one debug level supported at the moment."""
    global DEBUG
    DEBUG = bool(mode)


def grace(data, xlab='', ylab='', title=''):
    """
	Input data is of the form, [ [x1,y1], [x2,y2],....] where x and y are vectors
	"""
    try:
        import pygrace
        pg = pygrace.grace()
        for xy in data:
            pg.plot(xy[0], xy[1])
            pg.hold(1)
        pg.xlabel(xlab)
        pg.ylabel(ylab)
        pg.title(title)
        return True
    except:
        return False


def extract_gps_lat_lng_exif_tags(gps_exif_data):
    """
    Extracts the latitude and longitude tags of interest from the specified GPS EXIF data
    Returns: gps_latitude, gps_latitude_ref, gps_longitude, gps_longitude_ref
    """
    return gps_exif_data.get('GPSLatitude'), gps_exif_data.get('GPSLatitudeRef'
        ), gps_exif_data.get('GPSLongitude'), gps_exif_data.get(
        'GPSLongitudeRef')


def get_output_dim(net_spec_file, net_spec_attr, input):
    """Get the output dim so you don't need to manually calculate
    the dimensions of network
    :param net_spec_file:
    :param input: The input should be a legal input of the net
    :return: A shape(tuple)
    """
    from configs import utils, config_manager
    from torch.autograd import Variable
    input = Variable(input)
    net_spec_file = net_spec_file
    net_mgr = config_manager.NetConfig(net_spec_file)
    net = utils.build(net_mgr.cfg[net_spec_attr])
    output = net(input)
    return output.shape


def is_filelike(obj):
    """Return whether ``obj`` is a file-like object."""
    return hasattr(obj, 'read')


def set_ylabel(N, coordinates, id_number, flag, plotParams):
    """
    Sets the appropriate y-axis label according to the object being plotted

    N: number of points along y-axis (>= 1)
    coordinates: location of object being referenced on y-axis (only used if N == 1)
    id_number: the number of the object being plotted (e.g., 'Receiver 1')
    flag: string parameter describing the type of the object ('data', 'impulse', 'left', or 'right')
    plotParams: a dictionary of the plot parameters for styling
    """
    if flag == 'data' or flag == 'impulse' or flag == 'left':
        ylabel = 'Receiver'
    elif flag == 'right':
        ylabel = 'Source'
    if N == 1:
        au = plotParams['au']
        if coordinates is not None:
            xu = plotParams['xu']
            yu = plotParams['yu']
            if coordinates.shape[1] == 2:
                if au != '' and xu != '' and yu != '':
                    ylabel = (
                        'Amplitude (%s) [%s %s @ (%0.2f %s, %0.2f %s)]' % (
                        au, ylabel, id_number, coordinates[0, 0], xu,
                        coordinates[0, 1], yu))
                elif au == '' and xu != '' and yu != '':
                    ylabel = 'Amplitude [%s %s @ (%0.2f %s, %0.2f %s)]' % (
                        ylabel, id_number, coordinates[0, 0], xu,
                        coordinates[0, 1], yu)
                elif au != '' and xu == '' and yu == '':
                    ylabel = 'Amplitude (%s) [%s %s @ (%0.2f, %0.2f)]' % (au,
                        ylabel, id_number, coordinates[0, 0], coordinates[0, 1]
                        )
                elif au == '' and xu == '' and yu == '':
                    ylabel = 'Amplitude [%s %s @ (%0.2f, %0.2f)]' % (ylabel,
                        id_number, coordinates[0, 0], coordinates[0, 1])
            elif coordinates.shape[1] == 3:
                zu = plotParams['zu']
                if au != '' and xu != '' and yu != '' and zu != '':
                    ylabel = (
                        'Amplitude (%s) [%s %s @ (%0.2f %s, %0.2f %s, %0.2f %s)]'
                         % (au, ylabel, id_number, coordinates[0, 0], xu,
                        coordinates[0, 1], yu, coordinates[0, 2], zu))
                elif au == '' and xu != '' and yu != '' and zu != '':
                    ylabel = (
                        'Amplitude [%s %s @ (%0.2f %s, %0.2f %s, %0.2f %s)]' %
                        (ylabel, id_number, coordinates[0, 0], xu,
                        coordinates[0, 1], yu, coordinates[0, 2], zu))
                elif au != '' and xu == '' and yu == '' and zu == '':
                    ylabel = (
                        'Amplitude (%s) [%s %s @ (%0.2f, %0.2f, %0.2f)]' %
                        (au, ylabel, id_number, coordinates[0, 0],
                        coordinates[0, 1], coordinates[0, 2]))
                elif au == '' and xu == '' and yu == '' and zu == '':
                    ylabel = 'Amplitude [%s %s @ (%0.2f, %0.2f, %0.2f)]' % (
                        ylabel, id_number, coordinates[0, 0], coordinates[0,
                        1], coordinates[0, 2])
        elif au != '':
            ylabel = 'Amplitude (%s) [%s %s]' % (au, ylabel, id_number)
        else:
            ylabel = 'Amplitude [%s %s]' % (ylabel, id_number)
    return ylabel


def check(hub, rlist):
    """
    Chek the resolve list from the requisite systems and return errors from all
    errored requisites
    """
    errors = []
    for rdat in rlist:
        errors.extend(rdat.get('errors', []))
    return errors


def float16(val):
    """Convert a 16-bit floating point value to a standard Python float."""
    frac = val & 1023
    exp = val >> 10 & 31
    sign = val >> 15
    if exp:
        value = 2 ** (exp - 16) * (1 + float(frac) / 2 ** 10)
    else:
        value = float(frac) / 2 ** 9
    if sign:
        value *= -1
    return value


def slice_len(s: slice, l: int) ->int:
    """Returns length of `a[s]` where `len(a) == l`."""
    return len(range(*s.indices(l)))


def pack_contsign_as_key_image_as_val(k, v):
    """Calculate contsign of v and pack as kv."""
    from contsign_tool import calc_comma_contsign
    contsign = calc_comma_contsign(v)
    return contsign, v


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


@staticmethod
def _import_opts():
    """Returns command options in a form that can be handled by the
        command parser."""
    opts = {'-t': {'type': str, 'default': None}, '-pcap': {'type': str,
        'default': None}, '-h': {'type': bool, 'default': False}}
    return opts


def _adapt_parent_trials(node, parent_trials_node):
    """Adapt trials from the parent recursively

    .. note::

        To call with node.map(fct, node.parent) to connect with parents

    """
    if parent_trials_node is not None:
        adapter = node.item['experiment'].refers['adapter']
        for parent in parent_trials_node.root:
            parent.item['trials'] = adapter.forward(parent.item['trials'])
    return node.item, parent_trials_node


@classmethod
def find(cls, id, columns=None):
    """
        Find a model by its primary key.

        :param id: The id of the model
        :type id: mixed

        :param columns: The columns to retrieve
        :type columns: list

        :return: Either a Model instance or a Collection
        :rtype: Model
        """
    instance = cls()
    if isinstance(id, list) and not id:
        return instance.new_collection()
    if columns is None:
        columns = ['*']
    return instance.new_query().find(id, columns)


def def_attrs(cls, **kw):
    """
	Sets default attributes on a class instance

	:type cls: class
	:param cls: the class to update the given attributes in.
	:type kw: dict
	:param kw: dictionary of attributes names and values.
	"""
    for k, v in kw.items():
        if not hasattr(cls, k):
            setattr(cls, k, v)


def formula_2011_01_01(foyer_fiscal, period, parameters):
    """
        Investissements dans les DOM-TOM dans le cadre d'une entreprise.
        """
    f7ks = foyer_fiscal('f7ks', period)
    f7kt = foyer_fiscal('f7kt', period)
    f7ku = foyer_fiscal('f7ku', period)
    f7lg = foyer_fiscal('f7lg', period)
    f7lh = foyer_fiscal('f7lh_2012', period)
    f7li = foyer_fiscal('f7li', period)
    f7mm = foyer_fiscal('f7mm', period)
    f7ma = foyer_fiscal('f7ma', period)
    f7mb = foyer_fiscal('f7mb', period)
    f7mc = foyer_fiscal('f7mc', period)
    f7mn = foyer_fiscal('f7mn', period)
    f7oz = foyer_fiscal('f7oz', period)
    f7pa = foyer_fiscal('f7pa_2012', period)
    f7pb = foyer_fiscal('f7pb_2012', period)
    f7pd = foyer_fiscal('f7pd_2012', period)
    f7pe = foyer_fiscal('f7pe_2012', period)
    f7pf = foyer_fiscal('f7pf_2012', period)
    f7ph = foyer_fiscal('f7ph', period)
    f7pi = foyer_fiscal('f7pi_2012', period)
    f7pj = foyer_fiscal('f7pj_2012', period)
    f7pl = foyer_fiscal('f7pl', period)
    f7pz = foyer_fiscal('f7pz', period)
    f7qz = foyer_fiscal('f7qz_2012', period)
    f7qe = foyer_fiscal('f7qe', period)
    f7qf = foyer_fiscal('f7qf', period)
    f7qg = foyer_fiscal('f7qg', period)
    f7qi = foyer_fiscal('f7qi', period)
    f7qo = foyer_fiscal('f7qo_2012', period)
    f7qp = foyer_fiscal('f7qp_2012', period)
    f7qr = foyer_fiscal('f7qr_2012', period)
    f7qv = foyer_fiscal('f7qv', period)
    return (f7ks + f7kt + f7ku + f7lg + f7lh + f7li + f7mb + f7mn + f7mc +
        f7mm + f7ma + f7oz + f7pa + f7pb + f7pd + f7pe + f7pf + f7ph + f7pi +
        f7pj + f7pl + f7pz + f7qz + f7qf + f7qg + f7qi + f7qo + f7qp + f7qr +
        f7qe + f7qv)


def add_ago_to_since(since: str) ->str:
    """
    Backwards compatibility hack. Without this slices with since: 7 days will
    be treated as 7 days in the future.

    :param str since:
    :returns: Since with ago added if necessary
    :rtype: str
    """
    since_words = since.split(' ')
    grains = ['days', 'years', 'hours', 'day', 'year', 'weeks']
    if len(since_words) == 2 and since_words[1] in grains:
        since += ' ago'
    return since


@classmethod
def Remote(cls, username, password, cms_host, cms_port=0):
    """Create an authenticated CMS client by logging in at cms_host:cms_port first.
        Arguments as in remote_login().
        """
    return cls(*cls.remote_login(username, password, cms_host, cms_port))


@classmethod
def load(cls, dataset_uri: str, *, dataset_id: str=None, dataset_version:
    str=None, dataset_name: str=None) ->'Dataset':
    """
        Tries to load dataset from ``dataset_uri`` using all registered dataset loaders.

        Parameters
        ----------
        dataset_uri : str
            A datset URI to load.
        dataset_id : str
            Override dataset ID determined by the loader.
        dataset_version : str
            Override dataset version determined by the loader.
        dataset_name : str
            Override dataset name determined by the loader.

        Returns
        -------
        Dataset
            A loaded dataset.
        """
    for loader in cls.loaders:
        if loader.can_load(dataset_uri):
            return loader.load(dataset_uri, dataset_id=dataset_id,
                dataset_version=dataset_version, dataset_name=dataset_name)
    raise NotImplementedError(
        "No known loader could load dataset '{dataset_uri}'.".format(
        dataset_uri=dataset_uri))


@staticmethod
def __check_mean_size(left, right):
    """Apply f if the value is not None.

        This method is meant to be used with reduce. It will return either the
        right most numpy array or None if any of the array's had
        differing sizes. I wanted to use a Maybe monad here,
        but Python doesn't support that out of the box.

        Return
        ------
        None or numpy.array
            None values will propogate through the reduce automatically.

        """
    if left is None or right is None:
        return None
    elif left.shape != right.shape:
        return None
    return right


def revdict_lookup(dict, lookup_val):
    """(revdict_lookup):
        Performs a reverse dictionary lookup. Careful: only returns first match, but there may be others.
    """
    key = (key for key, value in dict.items() if value == lookup_val).next()
    return key


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 lower_case(value):
    """Return the value lowercased if it is within a specific set of values.

    :param value: The value to be checked.
    :type value: str
    :returns:
        The lowercased value if it is equivalent to
        'none', 'retrieve', or 'retain'.
    :rtype: str
    """
    lower_set = set(['none', 'retrieve', 'retain'])
    if isinstance(value, str):
        if value.lower() in lower_set:
            value = value.lower()
    return value


def remove_fs(module, filesystem, rm_mount_point):
    """ Remove an LVM file system or NFS entry. """
    rm_mount_point_opt = {(True): '-r', (False): ''}
    rm_mount_point = rm_mount_point_opt[rm_mount_point]
    rmfs_cmd = module.get_bin_path('rmfs', True)
    if not module.check_mode:
        cmd = '%s -r %s %s' % (rmfs_cmd, rm_mount_point, filesystem)
        rc, rmfs_out, err = module.run_command(cmd)
        if rc != 0:
            module.fail_json(msg='Failed to run %s. Error message: %s' % (
                cmd, err))
        else:
            changed = True
            msg = rmfs_out
            if not rmfs_out:
                msg = 'File system %s removed.' % filesystem
            return changed, msg
    else:
        changed = True
        msg = ''
        return changed, msg


def BCD_calc(TOP, P, AM):
    """
    Calculate BCD (Bray-Curtis dissimilarity).

    :param TOP: test outcome positive
    :type TOP : dict
    :param P: condition positive
    :type P : dict
    :param AM: Automatic/Manual
    :type AM : int
    :return: BCD as float
    """
    try:
        TOP_sum = sum(TOP.values())
        P_sum = sum(P.values())
        return abs(AM) / (P_sum + TOP_sum)
    except (ZeroDivisionError, TypeError, AttributeError):
        return 'None'


@classmethod
def from_cwl(cls, data):
    """Create instance from type definition."""
    if not isinstance(data, dict):
        data = {'type': data}
    return cls(**data)


def session_query(session, model):
    """Returns a SQLAlchemy query object for the specified `model`.

    If `model` has a ``query`` attribute already, ``model.query`` will be
    returned. If the ``query`` attribute is callable ``model.query()`` will be
    returned instead.

    If `model` has no such attribute, a query based on `session` will be
    created and returned.

    """
    if hasattr(model, 'query'):
        if callable(model.query):
            query = model.query()
        else:
            query = model.query
        if hasattr(query, 'filter'):
            return query
    return session.query(model)


def string_to_list(time):
    """Takes a time given in hh:mm:ss format and returns a list
    ['h','h','m','m','s','s'].
    Parameters:
    time: string format 'hh:mm:ss'
    """
    new_time = ''
    for letter in time:
        if letter != ':':
            new_time += letter
    new_time = list(new_time)
    if len(new_time) != 6:
        raise RuntimeError('Time list is not of length 6')
    return new_time


def _traverse(summary, function, *args):
    """Traverse all objects of a summary and call function with each as a
    parameter.

    Using this function, the following objects will be traversed:
    - the summary
    - each row
    - each item of a row
    """
    function(summary, *args)
    for row in summary:
        function(row, *args)
        for item in row:
            function(item, *args)


def walk_subclasses(root):
    """Does not yield the input class"""
    classes = [root]
    visited = set()
    while classes:
        cls = classes.pop()
        if cls is type or cls in visited:
            continue
        classes.extend(cls.__subclasses__())
        visited.add(cls)
        if cls is not root:
            yield cls


def strenumerate(iterable):
    """Works just as enumerate, but the returned index is a string.

    Parameters
    ----------
    iterable : Iterable
        An (guess what) iterable object.
    """
    for i, val in enumerate(iterable):
        yield str(i), val


def rle_get_at(rle, pos):
    """
    Return the attribute at offset pos.
    """
    x = 0
    if pos < 0:
        return None
    for a, run in rle:
        if x + run > pos:
            return a
        x += run
    return None


def new():
    """Add new paint curve

    """
    pass


def __new__(cls, *args):
    """
        Create an instance of configparser.ConfigParser,
        i.e. of the superclass. Let the superclass call
        the __init__() method.

        @param cls: newly minted instance of UtilsConfigParser
        @type cls: UtilsConfigParser
        @return: instance superclass
        @rtype: configparser.ConfigParser
        """
    if cls.config_parser is not None:
        return cls.config_parser
    obj = super().__new__(cls)
    super().__init__(obj)
    cls.config_parser = obj
    return obj


def _pack_list(lst):
    """
    The core method, convert list of strings to one big string.
    Every line in the string will store a single item from list. First
    line will keep a number of items. So items in the list should be a
    strings and not contain "
".\\ This is useful to store a list of
    users IDs in the local file.
    """
    return str(len(lst)) + u'\n' + u'\n'.join(lst)


def check_spec(instance, options):
    """ Checks to see if there are differences in command-line option
    provided spec_version and the spec_version found with bundles
    and/or objects.
    """
    warnings = []
    if options.version:
        try:
            if instance['type'] == 'bundle' and 'spec_version' in instance:
                if instance['spec_version'] != options.version:
                    warnings.append(instance['id'] +
                        ': spec_version mismatch with supplied option. Treating as {} content.'
                        .format(options.version))
            if instance['type'] == 'bundle' and 'objects' in instance:
                for obj in instance['objects']:
                    if 'spec_version' in obj:
                        if obj['spec_version'] != options.version:
                            warnings.append(obj['id'] +
                                ': spec_version mismatch with supplied option. Treating as {} content.'
                                .format(options.version))
        except Exception:
            pass
    return warnings


def GetClusterTags(r):
    """
    Gets the cluster tags.

    @rtype: list of str
    @return: cluster tags
    """
    return r.request('get', '/2/tags')


def blankimage(file, scale):
    """Draw blank image."""
    import pyx
    m = 0.4
    tm = 1.2
    c = pyx.canvas.canvas()
    c.stroke(pyx.path.rect(0, 0, (9 + 2 * m) * scale, (9 + m + tm) * scale),
        [pyx.color.grey(1)])
    for i in range(10):
        if i % 3 == 0:
            c.stroke(pyx.path.line((i + m) * scale, m * scale, (i + m) *
                scale, (9 + m) * scale), [pyx.style.linewidth.THIck])
            c.stroke(pyx.path.line(m * scale, (i + m) * scale, (9 + m) *
                scale, (i + m) * scale), [pyx.style.linewidth.THIck])
        else:
            c.stroke(pyx.path.line((i + m) * scale, m * scale, (i + m) *
                scale, (9 + m) * scale))
            c.stroke(pyx.path.line(m * scale, (i + m) * scale, (9 + m) *
                scale, (i + m) * scale))
    c.writeEPSfile(file)
    return


def parse_positive_double(elt):
    """
    urn:com.microsoft.wc.thing.types:positiveDouble
    http://developer.healthvault.com/sdk/docs/urn.com.microsoft.wc.thing.types.positiveDouble.1.html
    """
    return float(elt.text)


@classmethod
def P2SH_address_from_hash160(cls, hash160):
    """Return a coin address given a hash160."""
    assert len(hash160) == 20
    return cls.ENCODE_CHECK(cls.P2SH_VERBYTES[0] + hash160)


def condense_style(html):
    """Condense style html tags.

    >>> condense_style('
a b c')
    '
a b c'
    """
    return html.replace('


@staticmethod
def load(collada, localscope, node):
    """Load and return a class instance from an XML node.

        Inspect the data inside node, which must match
        this class tag and create an instance out of it.

        :param collada.Collada collada:
          The collada file object where this object lives
        :param dict localscope:
          If there is a local scope where we should look for local ids
          (sid) this is the dictionary. Otherwise empty dict ({})
        :param node:
          An Element from python's ElementTree API

        """
    raise Exception('Not implemented')


def get_dataset_prov(client, dataset):
    """Get dataset provenance.

	Args:
	    :client: the pyAMI client [ pyAMI.client.Client ]
	    :dataset: the dataset [ str ]

	Returns:
	    a map of python dictionnaries. The key "node" gives a list of dataset with the distance to the given dataset and the key "edge" gives the list of successive pairs of input an output datasets.
	"""
    command = ['AMIGetDatasetProv', '-logicalDatasetName="%s"' % dataset]
    result = client.execute(command, format='dom_object')
    return {'node': result.get_rows('node'), 'edge': result.get_rows('edge')}


@classmethod
def retrive(cls, storage_name, k8s_namespace=None):
    """
        Initialize storage class from K8S object and load

        :param cls: linked class
        :type cls: :py:class:`legion.k8s.properties.K8SPropertyStorage`
        :param storage_name: name of storage
        :type storage_name: str
        :param k8s_namespace: k8s namespace of None for auto deducing (auto deducing works only in-cluster)
        :type k8s_namespace: str or None
        :return: :py:class:`legion.k8s.properties.K8SPropertyStorage` -- built and initialized object
        """
    instance = cls(storage_name, k8s_namespace)
    instance.load()
    return instance


def stationarity_check(df, col='BidClose', window=80, freq='BH'):
    """From learn.co lesson: use ADFuller Test for Stationary and Plot"""
    import matplotlib.pyplot as plt
    TS = df[col].copy()
    TS = TS.asfreq(freq)
    TS.fillna(method='ffill', inplace=True)
    TS.dropna(inplace=True)
    from statsmodels.tsa.stattools import adfuller
    import pandas as pd
    import numpy as np
    rolmean = TS.rolling(window=window, center=False).mean()
    rolstd = TS.rolling(window=window, center=False).std()
    dftest = adfuller(TS)
    fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(8, 4))
    ax[0].set_title('Rolling Mean & Standard Deviation')
    ax[0].plot(TS, color='blue', label='Original')
    ax[0].plot(rolmean, color='red', label='Rolling Mean', alpha=0.6)
    ax[1].plot(rolstd, color='black', label='Rolling Std')
    ax[0].legend()
    ax[1].legend()
    plt.tight_layout()
    print('Results of Dickey-Fuller Test:')
    print('\tIf p<.05 then timeseries IS stationary.')
    dfoutput = pd.Series(dftest[0:4], index=['Test Statistic', 'p-value',
        '#Lags Used', 'Number of Observations Used'])
    for key, value in dftest[4].items():
        dfoutput['Critical Value (%s)' % key] = value
    print(dfoutput)
    return None


@staticmethod
def format_output_success(result):
    """
        This method accepts the result dictionary from a successful ping and generates colorized output
        :param result:
        :return: An html-formatted colorized string containing the timestamp, sequence number, text, packet size and
        responding IP from a successful ping
        """
    delay = result['Delay']
    if delay > 100:
        color = 'red'
    elif delay > 50:
        color = '#FF9900'
    else:
        color = 'green'
    ms = "{:.2f}".format(color, delay)
    output = '{:s} {:d} - {:s} - {:d} bytes from {:s} time={:s} ms'.format(
        result['Timestamp'], result['SeqNumber'], result['Message'], result
        ['PacketSize'], result['Responder'], ms)
    return output


def view_zoom_ratio(ratio: float=1.0):
    """Change zoom ratio of sequencer preview

    :param ratio: Ratio, Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out
    :type ratio: float
    """
    pass


def _all_valid(links):
    """Iterates over all links, forgetting emtpy registers."""
    for k, v in links.items():
        for i in v:
            yield k, i


def __setifunset(adict, key, val):
    """ sets value in dict if not set so far """
    if 'key' not in adict:
        adict['key'] = val


def _ipython_in_multiline(ip):
    """
    Return ``False`` if the user has entered only one line of input so far,
    including the current line, or ``True`` if it is the second or later line.

    :type ip:
      ``InteractiveShell``
    :rtype:
      ``bool``
    """
    if hasattr(ip, 'input_splitter'):
        return bool(ip.input_splitter.source)
    elif hasattr(ip, 'buffer'):
        return bool(ip.buffer)
    else:
        return False


def hm_to_float(h, m):
    """Convert 7, 30 to 7.5 hours."""
    return float(h) + float(m) / 60.0


def _default_value(argument, default):
    """Returns ``default`` if ``argument`` is ``None``"""
    if argument is None:
        return default
    else:
        return argument


def manifest_header(type_name, version='1.0'):
    """Returns a header, suitable for use in a manifest.

    >>> manifest_header("signature")
    "Signature-Version: 1.0"

    :param type_name: The kind of manifest which needs a header:
        "manifest", "signature".
    :param version: The manifest version to encode in the header
        (default: '1.0')
    """
    return u'{}-Version: {}'.format(type_name.title(), version)


def _jupyter_bundlerextension_paths():
    """
    Entrypoint for Jupyter Notebook Bundler

    Shows up in the 'Download' menu on Jupyter Classic Notebook
    """
    return [{'name': 'chrome_pdf_export', 'label': 'PDF via Chrome (.pdf)',
        'module_name': 'nbpdfexport.bundler', 'group': 'download'}]


def select_border(gesture_mode: int=0, xmin: int=0, xmax: int=0, ymin: int=
    0, ymax: int=0, extend: bool=True):
    """Select markers using border selection

    :param gesture_mode: Gesture Mode
    :type gesture_mode: int
    :param xmin: X Min
    :type xmin: int
    :param xmax: X Max
    :type xmax: int
    :param ymin: Y Min
    :type ymin: int
    :param ymax: Y Max
    :type ymax: int
    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    """
    pass


def get_gateway_map(bpmn_graph, consider_all_elements_to_be_task=False,
    use_node_id=False, relax_condition_one_entry=True):
    """
    Gets the gateway map out of a BPMN diagram

    Parameters
    ------------
    bpmn_graph
        BPMN graph
    consider_all_elements_to_be_task
        Boolean value that sets all the elements to be tasks
    use_node_id
        Use the node ID for storing elements in the gateway map
    relax_condition_one_entry
        Relax condition on the single entry of the gateway

    Returns
    -----------
    gateway_map
        Map whose:
        - key is the gateway ID
        - value is a dictionary containing:
            - type of the gateway
            - task that is source of the gateway
            - decision rules that are added
    edges_map
        Map of edge ID to edge object
    """
    gateway_map = {}
    edges_map = {}
    wanted_ret_el = 'id' if use_node_id else 'node_name'
    dg = bpmn_graph.diagram_graph
    for e in dg.edges:
        edge = dg.edges[e]
        edges_map[edge['id']] = edge
    for n in dg.nodes:
        node = dg.nodes[n]
        node_type = node['type']
        if node_type == 'exclusiveGateway' or node_type == 'eventBasedGateway':
            node_incoming = []
            node_outgoing = []
            for x in node['incoming']:
                if x in edges_map and edges_map[x]['sourceRef'] in dg.nodes:
                    node_incoming.append(dg.nodes[edges_map[x]['sourceRef']])
            for x in node['outgoing']:
                if x in edges_map and edges_map[x]['targetRef'] in dg.nodes:
                    node_outgoing.append(dg.nodes[edges_map[x]['targetRef']])
            if consider_all_elements_to_be_task:
                incoming_tasks = [x for x in node_incoming]
                task_nodes = [x for x in node_outgoing]
            else:
                incoming_tasks = [x for x in node_incoming if 'task' in x[
                    'type'].lower()]
                task_nodes = [x for x in node_outgoing if 'task' in x[
                    'type'].lower()]
            if (len(incoming_tasks) == 1 or relax_condition_one_entry) and len(
                node_outgoing) > 1:
                gateway_nodes = [x for x in node_outgoing if 'gateway' in x
                    ['type'].lower()]
                other_nodes = [x for x in node_outgoing if x not in
                    task_nodes and x not in gateway_nodes]
                if consider_all_elements_to_be_task or len(other_nodes
                    ) == 0 and task_nodes:
                    if gateway_nodes and len(task_nodes) == 1:
                        if len(incoming_tasks
                            ) > 0 and wanted_ret_el in incoming_tasks[0]:
                            gateway_map[n] = {'type': 'gateway', 'source':
                                incoming_tasks[0][wanted_ret_el], 'edges': {}}
                            for task in task_nodes:
                                gateway_map[n]['edges'][task[wanted_ret_el]
                                    ] = {'edge': task['incoming'][0],
                                    'rules': []}
                    elif len(task_nodes) > 1:
                        if len(incoming_tasks
                            ) > 0 and wanted_ret_el in incoming_tasks[0]:
                            gateway_map[n] = {'type': 'onlytasks', 'source':
                                incoming_tasks[0][wanted_ret_el], 'edges': {}}
                            for task in task_nodes:
                                gateway_map[n]['edges'][task[wanted_ret_el]
                                    ] = {'edge': task['incoming'][0],
                                    'rules': []}
    return gateway_map, edges_map


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

        :param InsufficientPlan val:
        :rtype: PermissionDeniedReason
        """
    return cls('insufficient_plan', val)


def get_preferred_sparse_format():
    """Get the preferred sparse matrix format supported by the backend.

    Different backends have their preferred backend. This info is useful when
    constructing a sparse matrix.
    """
    return 'coo'


def tostr(array):
    """ Create a string from an array of numbers """
    tmpstr = ''
    for val in array:
        tmpstr = tmpstr + ' ' + repr(val)
    return tmpstr.strip()