def _should_save_report_msg(msg):
    """Returns True if the given ForwardMsg should be serialized into
    a shared report.

    We serialize report & session metadata and deltas, but not transient
    events such as upload progress.

    """
    msg_type = msg.WhichOneof('type')
    return (msg_type == 'initialize' or msg_type == 'new_report' or
        msg_type == 'delta')


@staticmethod
def abs(tensor):
    """Computes the element-wise absolute value of the given input tensor.

        Parameters
        ----------
        tensor : tensor

        Returns
        -------
        out : tensor
        """
    raise NotImplementedError


@staticmethod
def _join_bc(sub1, sub2, axis=None):
    """ Determinae bc for the joined Subdomain. """
    if axis == 0:
        if sub1.axis == 0 and sub1.ix[0] < sub2.ix[0]:
            return f'{sub1.bc[0]}.{sub2.bc[2]}.'
        if sub1.axis == 0 and sub1.ix[0] > sub2.ix[0]:
            return f'{sub2.bc[0]}.{sub1.bc[2]}.'
    if axis == 1:
        if sub1.axis == 1 and sub1.iz[0] < sub2.iz[0]:
            return f'.{sub1.bc[1]}.{sub2.bc[3]}'
        if sub1.axis == 1 and sub1.iz[0] > sub2.iz[0]:
            return f'.{sub2.bc[1]}.{sub1.bc[3]}'
    return sub1.bc


def zip_has_files(files, zip_file):
    """Return True if zip has the files inside.

    :param files: list of files inside zip
    :type files: list
    :param zip_file: zip file to look inside.
    :type zip_file: :py:class:`zipfile.ZipFile`
    :returns: True if files inside of `:py:meth:`zipfile.ZipFile.namelist()`.
    :rtype: bool

    """
    if set(files).issubset(set(zip_file.namelist())):
        return True
    else:
        return False


def freestyle_modifier_remove():
    """Remove the modifier from the list of modifiers

    """
    pass


def anti_strand(strand):
    """
    Return the opposite strand
    Arguments:
    - `strand`: + or -
    """
    if strand == '+':
        return '-'
    else:
        return '+'


@classmethod
def flushAll(cls):
    """Flush all files in the pool."""
    for f in list(cls.pool.keys()):
        f.flush()


def read_SCF(g09_file):
    """
    Opens a g09 log file and returns the final SCF energy

    Parameters
    ----------
    g09_file: Path to g09 log file
        File path

    Returns
    ----------
    SCF: float
        Final SCF energy

    """
    energies = []
    with open(g09_file) as f:
        for line in f:
            if line.strip():
                if ' SCF Done:' in line:
                    energies.append(float(line.split()[4]))
        f.close()
    SCF = energies[-1]
    return SCF


@staticmethod
def __save_label_info_file(label_file, labels):
    """
        utility method for saving a file with labels
        :param label_file: path to the file to be written
        :param labels: label tensor
        :return: None (writes file to disk)
        """
    with open(label_file, 'w') as fp:
        for label in labels:
            fp.write(str(label.item()) + '\n')


def sort_magic_data(magic_data, sort_name):
    """
    Sort magic_data by header (like er_specimen_name for example)
    """
    magic_data_sorted = {}
    for rec in magic_data:
        name = rec[sort_name]
        if name not in list(magic_data_sorted.keys()):
            magic_data_sorted[name] = []
        magic_data_sorted[name].append(rec)
    return magic_data_sorted


def unsuppress_output_before_render(app, data):
    """
    This is a ``pre_render`` that unsuppresses console output if
    the ``YamlOutputHandler`` is triggered via command line so that the Yaml
    is the only thing in the output.

    :param app: The application object.

    """
    if not hasattr(app.pargs, 'output_handler_override'):
        return
    elif app.pargs.output_handler_override == 'yaml':
        app._unsuppress_output()


@staticmethod
def to_136_array(tiles):
    """
        Convert 34 array to the 136 tiles array
        """
    temp = []
    results = []
    for x in range(0, 34):
        if tiles[x]:
            temp_value = [x * 4] * tiles[x]
            for tile in temp_value:
                if tile in results:
                    count_of_tiles = len([x for x in temp if x == tile])
                    new_tile = tile + count_of_tiles
                    results.append(new_tile)
                    temp.append(tile)
                else:
                    results.append(tile)
                    temp.append(tile)
    return results


def fetch_mun_ine(connection):
    """
    Fetch teh INE code of the municipio

    :param connection:
    :return:
    :rtype: dict
    """
    ids_mun = connection.ResMunicipi.search([])
    data_mun = connection.ResMunicipi.read(ids_mun, ['ine', 'dc'])
    ret_vals = dict.fromkeys(ids_mun)
    for mun in data_mun:
        ret_vals[mun['id']] = '{0}{1}'.format(mun['ine'][-3:], mun['dc'])
    return ret_vals


def switch_visibility(widget, visibility):
    """
    Display/hide a widget with CSS.
    """
    if visibility:
        widget.remove_class('invisible')
        widget.add_class('visible')
    else:
        widget.remove_class('visible')
        widget.add_class('invisible')


def description(path, string, yaml):
    """Verify that Workbooks and Workflows have descriptions"""
    if 'workflows' not in yaml:
        yield 'Probably not a workbook. Not supported. {}'.format(path)
        raise StopIteration
    W101 = 'W101: Workbook {} has no description'
    W102 = 'W102: Workflow {}.{} has no description'
    workbook = yaml['name']
    if 'description' not in yaml:
        yield W101.format(workbook)
    for workflow, struct in yaml['workflows'].items():
        if 'description' not in struct:
            yield W102.format(workbook, workflow)


def load_numpy_core_multiarray(finder, module):
    """the numpy.core.multiarray module is an extension module and the numpy
       module imports * from this module; define the list of global names
       available to this module in order to avoid spurious errors about missing
       modules"""
    module.AddGlobalName('arange')


def broadcast_not_equal(lhs=None, rhs=None, out=None, name=None, **kwargs):
    """Returns the result of element-wise **not equal to** (!=) comparison operation with broadcasting.

    Example::

       x = [[ 1.,  1.,  1.],
            [ 1.,  1.,  1.]]

       y = [[ 0.],
            [ 1.]]

       broadcast_not_equal(x, y) = [[ 1.,  1.,  1.],
                                    [ 0.,  0.,  0.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_logic.cc:L64

    Parameters
    ----------
    lhs : NDArray
        First input to the function
    rhs : NDArray
        Second input to the function

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


def group_by_separator(sep, sfm_pairs):
    """Separate an iterator of tags and their values into groups.

    All groups are separated by the tag specified by `sep`.
    """
    entry = []
    for tag, value in sfm_pairs:
        if entry and tag == sep:
            yield entry
            entry = []
        entry.append((tag, value))
    if entry:
        yield entry


def _get_list_keys(nob):
    """Get the keys of the dictionnaries contained
    by a list

    Inputs :
    --------
    nob :  a list of dictionnaries

    Outputs :
    --------
    keys_list : a list of the dictionnaries keys
    """
    keys_list = []
    for item in nob:
        keys_list.extend(list(item.keys()))
    return keys_list


def hold_pack_lock(cursor):
    """Try to acquire the pack lock.

        Raise UnableToAcquirePackUndoLockError if packing or undo is already in progress.
        """


def zeros_like(input):
    """Create a zero tensor with the same shape, dtype and context of the
    given tensor.

    Parameters
    ----------
    input : Tensor
        The input

    Returns
    -------
    Tensor
        The result
    """
    pass


@classmethod
def _dissolve_cache_key(cls, cache_key):
    """Extract a hashdigest and a bucket key from `cache_key`.

        A `cache_key` consists of a hash digest and a bucket key. Both
        parts here are extracted from the given string if possible and
        returned as a tuple ``(<hash_digest>, <bucket-key>)``.

        Both items of the tuple can be ``None`` if they could not be
        extracted.
        """
    if not isinstance(cache_key, str):
        return None, None
    if not '_' in cache_key:
        return None, None
    return cache_key.split('_', 1)


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by this acitoolkit class.

        :returns: list of strings containing APIC class names
        """
    resp = ['pcAggrIf', 'ethpmAggrIf', 'pcRsMbrIfs']
    return resp


def isRetryableError(error):
    """Determine if the error is retryable.

        Returns true if any joined `IRetryDataManager` considers the
        error transient *or* if the error is an instance of
        `TransientError`. Such errors may occur due to concurrency
        issues in the underlying storage engine.
        """


def get_good_region(index, seq_count, arg):
    """
    Return regions marked for finding primers. Because of alignment gap, PCR
    product may smaller than given length limitation.
    """
    n = arg.max_product - arg.min_product
    good_region = set()
    for i, j in zip(index, seq_count):
        if j >= arg.resolution:
            good_region.update(range(i - arg.max_primer, i - n))
            good_region.update(range(i + arg.min_product, i - arg.
                max_primer + arg.max_product))
    return good_region


def cleanStr(str):
    """
    Do some cleaning, remove double spaces new lines, clean commas and others
    :param str:
    :return:
    """
    str = str.replace('\n', ' ')
    clean_space_from = ['( ', ' )', ', ', '[ ', ' ]']
    for str_to_replace in clean_space_from:
        actual = str_to_replace.replace(' ', '')
        str = str.replace(actual, str_to_replace)
    str = ' (' + str + ') '
    str = ' '.join(str.split())
    return str


def full_url():
    """URL of the image showing the large scale"""


@staticmethod
def digits_to_number(str):
    """
        1.5k; 1,200; 500+; 20k
        """
    if not str:
        return 0
    str = str.replace('+', '').replace(',', '').lower()
    ex = 1
    for k, e in {'k': 1000.0, 'm': 1000000.0, 'b': 1000000000.0}.items():
        if str.endswith(k):
            str = str[:-1]
            ex = e
            break
    return int(float(str) * ex)


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


@classmethod
def remove_function(cls, name):
    """Delete the function that is associated with `name` from all instances of this class

        Args:
            name (str): A name corresponding to the desired function.

        Raises:
            KeyError: If no function corresponding to `name` exists.
        """
    fun_name, length = cls._convert_name(name)
    if not hasattr(cls, fun_name):
        raise KeyError('A function corresponding to the name `' + name +
            '` does not exists')
    delattr(cls, fun_name)
    if cls.static_longest_name == length:
        cls.static_longest_name = cls._compute_static_longest_name()
    return cls


def frequency_to_channel(freq):
    """ Convert frequency in GHz to ITU DWDM channel in C-band

    >>> frequency_to_channel(193100)
    0
    >>> frequency_to_channel(192750)
    -7
    >>> frequency_to_channel(193550)
    9
    """
    itu_channel = (freq - 193100) / 50
    assert itu_channel == int(itu_channel)
    return int(itu_channel)


def convert_country(country):
    """
    For a given country, transform it using one of these rules
    :param country: string with the country name
    :return: string with the normalized country name
    """
    if (country and 'China' in country or country == 'Chin' or country ==
        'CHINA'):
        country = 'China'
    elif country and 'Brazil' in country or country == 'Brasil' or country == 'ITA - Instituto Tecnologico de Aeronautica (':
        country = 'Brazil'
    elif country and 'Argentina' in country:
        country = 'Argentina'
    elif country == 'Czechia':
        country = 'Czech Republic'
    elif 'Norwegian' in country:
        country = 'Norway'
    elif country and 'United Kingdom' in country:
        country = 'United Kingdom'
    elif country and 'Hong Kong' in country:
        country = 'Hong Kong'
    elif country == 'Cameroun':
        country = 'Cameroon'
    elif country and 'Chile' in country or country == 'CHILE':
        country = 'Chile'
    elif country and 'United States of America' in country or country == 'United States' or country == 'USA' or 'Florida' in country or 'California' in country or country == 'National Reference Centre for' or country == 'United State of America' or country == 'U.S.A.' or country == 'Virginia':
        country = 'United States of America'
    elif country == 'Republic of Panamá' or country == 'Panamá' or 'Panama' in country:
        country = 'Panama'
    elif 'Canada' in country:
        country = 'Canada'
    elif 'Colombia' in country or country == 'Universidad Aut':
        country = 'Colombia'
    elif 'Spain' in country or country == 'España':
        country = 'Spain'
    elif 'Iran' in country:
        country = 'Iran'
    elif 'Saudi Arabia' in country:
        country = 'Saudi Arabia'
    elif 'Italy' in country:
        country = 'Italy'
    elif 'Japan' in country:
        country = 'Japan'
    elif 'Germany' in country:
        country = 'Germany'
    elif 'Luxembourg' in country:
        country = 'Luxembourg'
    elif 'France' in country or country == 'Marseille':
        country = 'France'
    elif country == 'ROC' or country == 'R. O. C':
        country = 'Taiwan'
    elif country == 'Brasil':
        country = 'Brazil'
    elif country == 'México' or 'Mexico' in country or country == 'Centro de Investigación':
        country = 'Mexico'
    elif 'Slowakia' in country:
        country = 'Slowakia'
    elif country == 'Korea' or 'Republic of Korea' in country:
        country = 'South Korea'
    elif country == 'United Kindgom':
        country = 'United Kingdom'
    elif country and 'Netherlands' in country:
        country = 'Netherlands'
    elif country == 'Commonwealth of Australia' or 'Australia' in country:
        country = 'Australia'
    elif 'Singapore' in country:
        country = 'Singapore'
    elif country and (country[0].isdigit() or country[0] == '+'):
        country = 'N/A'
    return country


def Write(packer_type, buf, head, n):
    """ Write encodes `n` at buf[head] using `packer_type`. """
    packer_type.pack_into(buf, head, n)


@classmethod
def get(cls, key, *args):
    """
        Gets a generic system global.
        """
    return cls.misc.get(key, *args)


def blenderplayer_start():
    """Launch the blender-player with the current blend-file

    """
    pass


def fix_frame_records_filenames(records):
    """Try to fix the filenames in each record from inspect.getinnerframes().

    Particularly, modules loaded from within zip files have useless filenames
    attached to their code object, and inspect.getinnerframes() just uses it.
    """
    fixed_records = []
    for frame, filename, line_no, func_name, lines, index in records:
        if not filename.endswith(('.pyx', '.pxd', '.pxi')):
            better_fn = frame.f_globals.get('__file__', None)
            if isinstance(better_fn, str):
                filename = better_fn
        fixed_records.append((frame, filename, line_no, func_name, lines,
            index))
    return fixed_records


def block_format(pieces, width=79):
    """Concatenate strings, adding newlines.

    pieces -- iterable of bytes-like objects
    width  -- int (default 79)

    Returns b"".join(pieces), with added newlines between pieces as necessary
    to avoid lines longer than 'width' (using nothing more sophisticated than a
    byte-count).

    Leaves newlines inside 'pieces' untouched, and ignores them in its width
    calculation. If a single piece is longer than 'width', it will become a
    single long line in the output.

    """
    lines = []
    line = b''
    for bb in pieces:
        if len(line) + len(bb) > width:
            lines.append(line)
            line = b''
        line += bb
    if line:
        lines.append(line)
    return b'\n'.join(lines)


def support_vector_machine_train(X, Y, class_weight='balanced', C=1.0,
    kernel='linear', gamma='auto', coef0=0.0, degree=2, probability=False,
    shrinking=True, tol=0.001, verbose=False, max_iter=-1, random_state=
    None, cache_size=5000):
    """ Trains a support vector machine (SVM) using the SVC sklearn method. Very slow; 200k x 39 feats too large

    Args:
        X: 2D Narray of feature information
        Y: class labels to learn
        class_weight: (multi-class) Vector of weights to scale the C parameter for each class i, otherwise [1,]*num_classes
                      'balanced' yields [1/class_membership,] for each class to help balance assymetric class labels
        C           : The penalty parameter C for the error term; higher means stricter sensitivity to mismatch
        kernel      : 'linear','poly','rbf','sigmoid','precomputed' or a callable function. Default 'linear'
        gamma       : Kernel coefficient for 'rbf', 'poly', and 'sigmoid'. 'Auto' uses 1/num_features.
        degree      : Polynomial degree to use if kernel type 'poly'
        coef0       : Intercept to use in 'poly' and 'sigmoid' functions
        probability : Boolean, whether to attempt to calculate probability estimates. Significantly slows computation.
        shrinking   : Boolean, whether to use shrinking heuristic. Can speed up convergence in terms of runtime.
        tol         : Tolerance float for convergence monitoring, default 1e-3
        verbose     : Boolean, verbose mode
        max_iter    : How many iterations to permit, default = -1 (no limit)
        random_state: Random number seed to use, or None to generate new
        cache_size  : The cache size (MB) to use for storing frequently requested distances during training. Default 5000.

    >>> X = [[0, 0], [1, 1]]
    >>> Y = [0, 1]
    >>> classifier = support_vector_machine_train(X, Y, C = 1.0, kernel = 'rbf', gamma = 'auto', random_state = 0)

    >>> print(classifier.predict([[0, 0]]))
    [0]

    >>> print(classifier.predict([[1, 1]]))
    [1]

    >>> print(classifier.predict([[-0.8, -1],[0.8,1]]))
    [0 1]

    >>> numsamp = 20000
    >>> numfeat = 3
    >>> N.random.seed(0)
    >>> X = N.random.random((numsamp, numfeat))
    >>> Y = N.linspace(0,10,numsamp).astype(int)
    >>> classifier = support_vector_machine_train(X, Y, C = 1.0, kernel = 'linear', random_state = 0)
    >>> N.random.seed(0)
    >>> classifier.predict(N.random.random(numfeat).reshape(1, -1))
    array([6])

    """
    from sklearn import svm
    classifier = svm.SVC(C=C, kernel=kernel, degree=degree, gamma=gamma,
        coef0=coef0, shrinking=shrinking, probability=probability, tol=tol,
        class_weight=class_weight, verbose=verbose, max_iter=max_iter,
        decision_function_shape='ovr', random_state=random_state,
        cache_size=cache_size)
    classifier.fit(X, Y)
    return classifier


def system(cmd, data=None):
    """
  pipes the output of a program
  """
    import subprocess
    s = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=
        subprocess.PIPE)
    out, err = s.communicate(data)
    return out.decode('utf8')


@classmethod
def namespace(cls):
    """Return namespace corresponding to self.ARGUMENT

        ARGUMENT is a command line argument, thus something in the style of `--code-change-type`.
        When arguments are passed they are saved in namespace in the style of `code_change_type`.
        This property converts command-line style to namespace style.
        """
    if not cls.ARGUMENT:
        return None
    return cls.ARGUMENT.lstrip('-').replace('-', '_')


@classmethod
def generate_key(cls, secret_key, region, service, date, intermediates=False):
    """
        Generate the signing key string as bytes.

        If intermediate is set to True, returns a 4-tuple containing the key
        and the intermediate keys:

        ( signing_key, date_key, region_key, service_key )

        The intermediate keys can be used for testing against examples from
        Amazon.

        """
    init_key = ('AWS4' + secret_key).encode('utf-8')
    date_key = cls.sign_sha256(init_key, date)
    region_key = cls.sign_sha256(date_key, region)
    service_key = cls.sign_sha256(region_key, service)
    key = cls.sign_sha256(service_key, 'aws4_request')
    if intermediates:
        return key, date_key, region_key, service_key
    else:
        return key


def _resolve(name):
    """Resolve a dotted name to a global object."""
    name = name.split('.')
    used = name.pop(0)
    found = __import__(used)
    for n in name:
        used = used + '.' + n
        try:
            found = getattr(found, n)
        except AttributeError:
            __import__(used)
            found = getattr(found, n)
    return found


def edge_loops_from_edges(mesh, edges=None):
    """
    Edge loops defined by edges

    Takes me.edges or a list of edges and returns the edge loops

    return a list of vertex indices.
    [ [1, 6, 7, 2], ...]

    closed loops have matching start and end values.
    """
    line_polys = []
    if edges is None:
        edges = mesh.edges
    if not hasattr(edges, 'pop'):
        edges = edges[:]
    while edges:
        current_edge = edges.pop()
        vert_end, vert_start = current_edge.vertices[:]
        line_poly = [vert_start, vert_end]
        ok = True
        while ok:
            ok = False
            i = len(edges)
            while i:
                i -= 1
                ed = edges[i]
                v1, v2 = ed.vertices
                if v1 == vert_end:
                    line_poly.append(v2)
                    vert_end = line_poly[-1]
                    ok = 1
                    del edges[i]
                elif v2 == vert_end:
                    line_poly.append(v1)
                    vert_end = line_poly[-1]
                    ok = 1
                    del edges[i]
                elif v1 == vert_start:
                    line_poly.insert(0, v2)
                    vert_start = line_poly[0]
                    ok = 1
                    del edges[i]
                elif v2 == vert_start:
                    line_poly.insert(0, v1)
                    vert_start = line_poly[0]
                    ok = 1
                    del edges[i]
        line_polys.append(line_poly)
    return line_polys


def name(item):
    """ Return an item's name. """
    return item.__name__


def unseal(client, key):
    """Unseals a Vault server with the provided (decrypted) key"""
    client.unseal(key)


def getLine(s, i):
    """
    Return i,j such that s[i:j] is the line surrounding s[i].
    s[i] is a newline only if the line is empty.
    s[j] is a newline unless there is no trailing newline.
    """
    if i > len(s):
        i = len(s) - 1
    if i < 0:
        i = 0
    j = s.rfind('\n', 0, i)
    if j == -1:
        j = 0
    else:
        j += 1
    k = s.find('\n', i)
    if k == -1:
        k = len(s)
    else:
        k = k + 1
    return j, k


@staticmethod
def keys_where_value(dictionary, value):
    """ Searches the given dictionary for values matching the value provided, and returns the keys of those
        elements. """
    keys = []
    for x in dictionary:
        if dictionary[x].strip() == value.strip():
            keys.append(x)
    return keys


def nocomment(astr, com):
    """
    just like the comment in python.
    removes any text after the phrase 'com'
    """
    alist = astr.splitlines()
    for i in range(len(alist)):
        element = alist[i]
        pnt = element.find(com)
        if pnt != -1:
            alist[i] = element[:pnt]
    return '\n'.join(alist)


def get_prefix_recipe(recipe_name):
    """ Return the prefix recipe or None """
    from pybombs import recipe
    return recipe.get_recipe(recipe_name, target='prefix', fail_easy=True)


def plural(x):
    """
    Returns an 's' if plural

    Useful in print statements to avoid something like 'point(s)'
    """
    if x > 1:
        return 's'
    return ''


def delete_cached():
    """Remove a cached access token"""
    import keyring
    global ACCESS_TOKEN
    try:
        keyring.delete_password('system', 'grepme')
    except keyring.errors.PasswordDeleteError:
        pass
    ACCESS_TOKEN = None


def ndo_float(data, n):
    """mimic of gmx_fio_ndo_float in gromacs"""
    return [data.unpack_float() for i in range(n)]


@staticmethod
def _organize_model(cls, model):
    """
        Instantiate the model with all hyper-parameters,
        set all model parameters and then return the model.

        Do not use directly. Use the designated classmethod to load a model.

        Parameters
        ----------
        cls : instance of model that inherits from `BaseModelPackage`
            a model instance

        model : dict
            Model dict containing hyper-parameters and model-parameters

        Returns
        -------
        model: instance of model that inherits from `BaseModelPackage`
            instance of the model class with hyper-parameters and
            model parameters set from the passed model dict
        """
    model_params = model.pop('model_params')
    hyper_params = model.pop('hyper_params')
    inst = cls(**hyper_params)
    for p in model_params.keys():
        setattr(inst, p, model_params[p])
    return inst


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 terminal_encoding(term):
    """Return our best guess of encoding for the given *term*."""
    if getattr(term, 'encoding', None):
        return term.encoding
    import locale
    return locale.getpreferredencoding()


def _row_mask_to_nparams(mask):
    """
    @param mask: a boolean array
    """
    nparams = mask.sum() - 1
    if nparams < 0:
        msg = 'a stochastic vector cannot be all zeros'
        raise ValueError(msg)
    return nparams


def customdata_skin_clear():
    """Clear vertex skin layer

    """
    pass


def first_letter_upper(input_string):
    """
    Returns a new string with the first letter as uppercase
    :param input_string: str
    :return: str
    """
    return input_string[:1].capitalize() + input_string[1:]


def readtec_domain():
    """
    A dummy for the TECPLOT-domain output of OGS.

    It is not implemented, because the output is separated by element types,
    where VTK works out much better.
    """
    raise NotImplementedError('Reader for Tecplot domain ' +
        'output not yet implemented ' + '....please(!) generate vtk/pvd here')


@staticmethod
def _parse_user_id(session_info):
    """ Method for parsing user ID from session info
        """
    return session_info['user']['id']


@classmethod
def resolve_dist(cls, dist, working_set):
    """Given a local distribution and a working set, returns all dependencies from the set.

        :param dist: A single distribution to find the dependencies of
        :type dist: :class:`pkg_resources.Distribution`
        :param working_set: A working set to search for all packages
        :type working_set: :class:`pkg_resources.WorkingSet`
        :return: A set of distributions which the package depends on, including the package
        :rtype: set(:class:`pkg_resources.Distribution`)
        """
    deps = set()
    deps.add(dist)
    try:
        reqs = dist.requires()
    except (AttributeError, OSError, IOError):
        return deps
    for req in reqs:
        dist = working_set.find(req)
        deps |= cls.resolve_dist(dist, working_set)
    return deps


def _extract_class_dict(cls):
    """Retrieve a copy of the dict of a class without the inherited methods"""
    clsdict = dict(cls.__dict__)
    if len(cls.__bases__) == 1:
        inherited_dict = cls.__bases__[0].__dict__
    else:
        inherited_dict = {}
        for base in reversed(cls.__bases__):
            inherited_dict.update(base.__dict__)
    to_remove = []
    for name, value in clsdict.items():
        try:
            base_value = inherited_dict[name]
            if value is base_value:
                to_remove.append(name)
        except KeyError:
            pass
    for name in to_remove:
        clsdict.pop(name)
    return clsdict


def _new_format(template, variables):
    """Format a string that follows the {}-based syntax.
    """
    return template.format(**variables)


def get_application():
    """Helper function. Needed for easier testing"""
    from .models import APPLICATION
    return APPLICATION


def target_move_down():
    """Move particle target down in the list

    """
    pass


def validate_tile_size(tile_size, img_size=None):
    """Validates tile size argument provided for slicing.

    Parameters
    ----------
    tile_size : tuple
        Size of each tile in pixels, as a 2-tuple: (width, height).
    img_size : tuple, optional
        Size of original image in pixels, as a 2-tuple: (width, height).

    Returns
    ----------
    None

    Raises
    ----------
    ValueError
        If `tile_size` does not hold exactly `2` values
        If `tile_size` does not comply with `img_size`
    TypeError
        If `tile_size` or `img_size` are not of type tuple.
    """
    if img_size is None:
        if isinstance(tile_size, tuple):
            if len(tile_size) != 2:
                raise ValueError(
                    'Tile size must be a tuple of size 2 i.e., (w, h). The tuple provided was {}'
                    .format(tile_size))
        else:
            raise TypeError(
                'Tile size must be a tuple. The argument was of type {}'.
                format(type(tile_size)))
    elif isinstance(img_size, tuple):
        if sum(tile_size) >= sum(img_size) or tile_size[0] > img_size[0
            ] or tile_size[1] > img_size[1]:
            raise ValueError(
                'Tile size cannot exceed image size. Tile size was {} while image size was {}'
                .format(tile_size, img_size))
    else:
        raise TypeError(
            'Image size must be a tuple. The argument was of type {}'.
            format(type(img_size)))


@classmethod
def BackAssign(cls, other_entity_klass, this_entity_backpopulate_field,
    other_entity_backpopulate_field, is_many_to_one=False):
    """
        Assign defined one side mapping relationship to other side.

        For example, each employee belongs to one department, then one department
        includes many employees. If you defined each employee's department,
        this method will assign employees to ``Department.employees`` field.
        This is an one to many (department to employee) example.

        Another example would be, each employee has multiple tags. If you defined
        tags for each employee, this method will assign employees to
        ``Tag.employees`` field. This is and many to many (employee to tag) example.

        Support:

        - many to many mapping
        - one to many mapping

        :param other_entity_klass: a :class:`Constant` class.
        :param this_entity_backpopulate_field: str
        :param other_entity_backpopulate_field: str
        :param is_many_to_one: bool
        :return:
        """
    data = dict()
    for _, other_klass in other_entity_klass.Subclasses():
        other_field_value = getattr(other_klass, this_entity_backpopulate_field
            )
        if isinstance(other_field_value, (tuple, list)):
            for self_klass in other_field_value:
                self_key = self_klass.__name__
                try:
                    data[self_key].append(other_klass)
                except KeyError:
                    data[self_key] = [other_klass]
        elif other_field_value is not None:
            self_klass = other_field_value
            self_key = self_klass.__name__
            try:
                data[self_key].append(other_klass)
            except KeyError:
                data[self_key] = [other_klass]
    if is_many_to_one:
        new_data = dict()
        for key, value in data.items():
            try:
                new_data[key] = value[0]
            except:
                pass
        data = new_data
    for self_key, other_klass_list in data.items():
        setattr(getattr(cls, self_key), other_entity_backpopulate_field,
            other_klass_list)


@classmethod
def postfork(cls, **kwargs):
    """ This method will be called after uWSGI forks """


@classmethod
def type(cls):
    """Overrides the name to match the name of the parent query runner"""
    return 'presto'


def relationships(cls):
    """
        Relationships metadata, which can be overridden.
        """
    return [('cards', cls.card_id_field(), 'transactions', cls.
        card_id_field()), ('customers', cls.customer_id_field(), 'cards',
        cls.customer_id_field())]


@classmethod
def get_source(cls, name, ttype, lang, source=None):
    """Return translation for source"""
    args = name, ttype, lang, source
    result = cls.get_sources([args])
    return result[args]


def get_batch_info_status(batch_id):
    """
        Return a dictionary containing the latest event stats for the given
        batch_id.

        :param batch_id:
            The batch identifier for the batch to operate on.

        :returns:
            A dictionary containing counts for sent messages and events types.
            If async, a Deferred is returned instead.
        """


@classmethod
def all(cls, client):
    """Get all containers.

        Containers returned from this method will only have the name
        set, as that is the only property returned from LXD. If more
        information is needed, `Container.sync` is the method call
        that should be used.
        """
    response = client.api.containers.get()
    containers = []
    for url in response.json()['metadata']:
        name = url.split('/')[-1]
        containers.append(cls(client, name=name))
    return containers


def kindAsBreatheDirective(kind):
    """
    Returns the appropriate breathe restructured text directive for the specified kind.
    The output for a given kind is as follows:

    +-------------+--------------------+
    | Input Kind  | Output Directive   |
    +=============+====================+
    | "class"     | "doxygenclass"     |
    +-------------+--------------------+
    | "define"    | "doxygendefine"    |
    +-------------+--------------------+
    | "enum"      | "doxygenenum"      |
    +-------------+--------------------+
    | "enumvalue" | "doxygenenumvalue" |
    +-------------+--------------------+
    | "file"      | "doxygenfile"      |
    +-------------+--------------------+
    | "function"  | "doxygenfunction"  |
    +-------------+--------------------+
    | "group"     | "doxygengroup"     |
    +-------------+--------------------+
    | "namespace" | "doxygennamespace" |
    +-------------+--------------------+
    | "struct"    | "doxygenstruct"    |
    +-------------+--------------------+
    | "typedef"   | "doxygentypedef"   |
    +-------------+--------------------+
    | "union"     | "doxygenunion"     |
    +-------------+--------------------+
    | "variable"  | "doxygenvariable"  |
    +-------------+--------------------+

    The following breathe kinds are ignored:

    - "autodoxygenfile"
    - "doxygenindex"
    - "autodoxygenindex"

    Note also that although a return value is generated, neither "enumvalue" nor
    "group" are actually used.

    :Parameters:
        ``kind`` (str)
            The kind of the breathe compound / ExhaleNode object (same values).

    :Return (str):
        The directive to be used for the given ``kind``.  The empty string is returned
        for both unrecognized and ignored input values.
    """
    return 'doxygen{kind}'.format(kind=kind)


def et_to_str(node):
    """Get the text value of an Element, returning None if not found."""
    try:
        return node.text
    except AttributeError:
        return None


@staticmethod
def get_dns_challenge_change_batch(action, domain, txt_challenge):
    """
        Given action, domain and challenge, return a change batch to use with
        route53 call.

        :param action: DELETE | UPSERT
        :param domain: domain name
        :param txt_challenge: challenge
        :return: change set for a given action, domain and TXT challenge.
        """
    return {'Changes': [{'Action': action, 'ResourceRecordSet': {'Name':
        '_acme-challenge.{0}'.format(domain), 'Type': 'TXT', 'TTL': 60,
        'ResourceRecords': [{'Value': '"{0}"'.format(txt_challenge)}]}}]}


def get_doc():
    """Get documentation of this resource

    :return: rst string
    :rtype: str
    """
    return """
    The ``statsd`` model contains information to provide the monitored system performance
    data to StatsD.

    The Alignak backend will use those information to connect to a StatsD daemon and send the
    timeseries data. StatsD may be used as a front-end to Graphite or InfluxDB thus an
    instance of this data model may be related to a Graphite or InfluxDB instance.
    """


def not_supported_feature(feature, action=None):
    """
    Returns a templated note for the specified feature indicating that it is not supported.

    Parameters
    ----------

    feature : string
        Specifies the feature that is not supported. This will be inserted into the templated note message.

    action : string, optional
        Specifies if an action is taken for the not supported feature.

    Returns
    -------
    warning_message : str

    """
    if action is None:
        return '*** NOTE: ' + feature + ' is not supported yet.'
    else:
        return ('*** NOTE: ' + feature +
            ' is not supported yet. We took the following action: ' + action)


def join_or_single(start, end):
    """ Join passages range. If they are the same, return a single part of the range

    :param start: Start of the passage range
    :param end: End of the passage range
    :return: Finale Passage Chunk Identifier
    """
    if start == end:
        return start
    else:
        return '{}-{}'.format(start, end)


@staticmethod
def _build_instance_dict(response_dict):
    """Build an API resource instance given a dictionary"""
    return response_dict


def printr(expr):
    """
    Prints out an expression and returns it as well for inline diagnosis.
    You shouldn't use print to debug, but it's not like you're going to stop.

    Parameter + Return
    ------------------
    expr : any
        item to be analyzed/returned

    Example
    -------
    >>> #Use it within a comprehension to diagnose problems.
    >>> #If you just use print, the result would be [None,None,None,None]
    >>> [xt.printr(i)**3 for i in range(4)]
    0
    1
    2
    3
    [0, 1, 8, 27]

    """
    print(expr)
    return expr


def parse_h5_attr(f, attr):
    """A Python3-safe function for getting hdf5 attributes.

    If an attribute is supposed to be a string, this will return it as such.

    This was taken from yt.
    """
    val = f.attrs.get(attr, None)
    if isinstance(val, bytes):
        return val.decode('utf8')
    else:
        return val


def split_group(source, pos, maxline):
    """ Split a group into two subgroups.  The
        first will be appended to the current
        line, the second will start the new line.

        Note that the first group must always
        contain at least one item.

        The original group may be destroyed.
    """
    first = []
    source.reverse()
    while source:
        tok = source.pop()
        first.append(tok)
        pos += len(tok)
        if source:
            tok = source[-1]
            allowed = maxline + 1 if tok.endswith(' ') else maxline - 4
            if pos + len(tok) > allowed:
                break
    source.reverse()
    return first, source


def partition(iterable, n, rest=False):
    """Partition an iterable into tuples.

    The iterable `iterable` is progressively consumed `n` items at a time in order to
    produce tuples of length `n`.

    :param iterable iterable: The iterable to partition.
    :param int n: Length of the desired tuples.
    :param bool rest: Whether to return a possibly incomplete tuple at the end.
    :returns: A generator which yields subsequent `n`-uples from the original iterable.

    **Examples**

    By default, any remaining items which are not sufficient to form
    a new tuple of length `n` are discarded.

    >>> list(partition(range(8), 3))
    [(0, 1, 2), (3, 4, 5)]

    You can ask to return the remaining items at the end by setting the flag `rest`
    to ``True``.

    >>> list(partition(range(8), 3, rest=True))
    [(0, 1, 2), (3, 4, 5), (6, 7)]
    """
    it = iter(iterable)
    while True:
        res = []
        try:
            for _ in range(n):
                res.append(next(it))
        except StopIteration:
            if rest:
                yield tuple(res)
            return
        yield tuple(res)


def transpose2d(mtx):
    """Transpose a 2d matrix
       [
            [1,2,3],
            [4,5,6]
            ]
        becomes
        [
            [1,4],
            [2,5],
            [3,6]
            ]
    """
    return zip(*mtx)


def set_ants_transform_fixed_parameters(transform, parameters):
    """
    Set fixed parameters of an ANTsTransform

    ANTsR function: `setAntsrTransformFixedParameters`
    """
    transform.set_fixed_parameters(parameters)


def isNeutrino(pid):
    """Determine if the PID is that of a neutrino (incl 4th gen)"""
    return abs(pid) in [12, 14, 16, 18]


def dissolve_edges(use_verts: bool=True, use_face_split: bool=False):
    """Dissolve edges, merging faces

    :param use_verts: Dissolve Verts, Dissolve remaining vertices
    :type use_verts: bool
    :param use_face_split: Face Split, Split off face corners to maintain surrounding geometry
    :type use_face_split: bool
    """
    pass


def identify_table(soup, htmldict, numtable):
    """
    Checks whether the given BeautifulSoup tag is the table
    the user intends to process.
    """
    if soup is None or soup.name != 'table':
        return False
    elif 'table_id' not in htmldict:
        return numtable == 1
    table_id = htmldict['table_id']
    if isinstance(table_id, str):
        return 'id' in soup.attrs and soup['id'] == table_id
    elif isinstance(table_id, int):
        return table_id == numtable
    return False


def sql(c, sql, database='', port=None):
    """
    Execute some SQL as the 'postgres' user.
    """
    cmd = (
        'sudo -u postgres psql {port} --tuples-only --no-align --command="{sql}" {database}'
        .format(port='--port={}'.format(port) if port else '', sql=sql,
        database=database))
    return c.sudo(cmd, shell=False)


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

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


def reindexOnModify(content, event):
    """When an object is modified, re-index it in the catalog
    """
    if event.object is not content:
        return
    content.reindexObject()


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 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 model_with_weights(model, weights, skip_mismatch):
    """ Load weights for model.

    Args
        model         : The model to load weights for.
        weights       : The weights to load.
        skip_mismatch : If True, skips layers whose shape of weights doesn't match with the model.
    """
    if weights is not None:
        model.load_weights(weights, by_name=True, skip_mismatch=skip_mismatch)
    return model


def get_user_emails():
    """
        return the list of all pending emails
        """


def humanReadable(seconds):
    """
    Convert elapsed time (in seconds) to human-readable
    format (hours : minutes : seconds)
    """
    h = int(seconds / 3600)
    m = int(seconds % 3600 / 60)
    s = seconds % 60.0
    return '{}h : {:>02}m : {:>05.2f}s'.format(h, m, s)


def create_copy():
    """Create a new copy of the public version. Automatically
        assign a new id for this copy and register this as the
        next version. If there is already a next version, this
        operation will fail.
        """


def line_search_subject(line):
    """get the source one searches for"""
    l = line.split()
    if len(l) > 1 and 'search' in l:
        i = l.index('search')
        return l[i + 1]
    else:
        return ''


@staticmethod
def playable_card(card, fireworks):
    """A card is playable if it can be placed on the fireworks pile."""
    return card['rank'] == fireworks[card['color']]


@classmethod
def _register(cls, name, func):
    """
        Register func as a recognized control command with the given
        name.
        """
    cls._commands[name] = func


def get_traffic_policy(Id=None, Version=None):
    """
    Gets information about a specific traffic policy version.
    See also: AWS API Documentation

    :example: response = client.get_traffic_policy(
        Id='string',
        Version=123
    )

    :type Id: string
    :param Id: [REQUIRED]
            The ID of the traffic policy that you want to get information about.

    :type Version: integer
    :param Version: [REQUIRED]
            The version number of the traffic policy that you want to get information about.

    :rtype: dict
    :return: {
        'TrafficPolicy': {
            'Id': 'string',
            'Version': 123,
            'Name': 'string',
            'Type': 'SOA'|'A'|'TXT'|'NS'|'CNAME'|'MX'|'NAPTR'|'PTR'|'SRV'|'SPF'|'AAAA',
            'Document': 'string',
            'Comment': 'string'
        }
    }

    """
    pass


def p_ReturnType(p):
    """ReturnType : Type"""
    p[0] = p[1]


def handle_smsdr(message):
    """ Handles an Incoming Delivery Receipt for a sent SMS-MT

        message parameter is the SMS-MT, updated with DR info """
    return


def controller_remove(controller: str='', object: str=''):
    """Remove a controller from the active object

    :param controller: Controller, Name of the controller to edit
    :type controller: str
    :param object: Object, Name of the object the controller belongs to
    :type object: str
    """
    pass


def str2float(inp):
    """
    Convert a set number of columns to float, or returns None.

    Parameters
    ----------
    inp : str
        string with a list of floats in it

    Returns
    -------
    output : float
        all columns returned as floats
    """
    if inp.strip() == '':
        return None
    return float(inp)


def download_competition(ctx=None):
    """ setup files for a competition """


@classmethod
def get(cls, project_id, model_id):
    """ Retrieve a model blueprint chart.

        Parameters
        ----------
        project_id : str
            The project's id.
        model_id : str
            Id of model to retrieve model blueprint chart.

        Returns
        -------
        ModelBlueprintChart
            The queried model blueprint chart.
        """
    url = 'projects/{}/models/{}/blueprintChart/'.format(project_id, model_id)
    return cls.from_location(url)


def _is_bytes(thing):
    """Check that **thing** is bytes.

    :param thing: The thing to check if it's bytes.
    :rtype: bool
    :returns: ``True`` if **thing** is bytes or a bytearray.
    """
    if isinstance(thing, (bytes, bytearray)):
        return True
    return False


def import_symbol(dotted_name):
    """Import an arbitrary symbol (including modules) by its dotted name"""
    try:
        spec = dotted_name.rsplit('.', 1)
        try:
            mod_name, attr = spec
        except ValueError:
            sym = __import__(dotted_name, None, None, [])
        else:
            mod = __import__(mod_name, None, None, [attr])
            sym = getattr(mod, attr)
    except (ImportError, AttributeError, ValueError):
        raise ImportError('Can not import %r' % dotted_name)
    return sym


def remove_unwanted(doc):
    """Remove attributes unecessary to superdesk from documents.

    As the name suggests this function removes unwanted attributes from doc to make an entry in Mongo and Elastic.
    """
    if doc:
        for attr in ['_type', 'desk', 'archived']:
            if attr in doc:
                del doc[attr]


def partition_domain(dom):
    """partitions domain dom into two.
    """
    split = len(dom) // 2
    dom1 = set(list(dom)[:split])
    dom2 = dom - dom1
    return dom1, dom2


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 validate_post_plugin_load():
    """Checks if the configuration variables are valid.

    If the configuration is invalid then the method will return an error
    message. If all is OK then it will return None.
    """
    message = None
    return message


def secant(x1, x2, f, steptol=1e-12, roottol=1e-12, maxIter=30, callback=None):
    """
	Find an approximation to a point xf such that f(xf)=0 for a
	scalar function f using the secant method.  The method requires
	two initial points x1 and x2, ideally close to a root,
	and proceeds iteratively.

	Parameters
	----------
	x1 : float or complex
		An initial point for iteration, should be close to a
		root of f.
	x2 : float or complex
		An initial point for iteration, should be close to a
		root of f.  Should not equal x1.
	f : function
		Function of a single variable which we seek to find a root of.
	steptol: float, optional
		The routine ends if the step size, dx, between sucessive
		iterations satisfies abs(dx) < steptol and attemptBest is False.
	roottol: float, optional
		The routine ends if abs(f(x)) < roottol and attemptBest is False.
	maxIter : int, optional
		The routine ends after maxIter iterations.
	callback : function, optional
		After each iteration callback(x, dx, f(x), iteration) will be
		called where 'x' is the current iteration of the estimated root,
		'dx' is the step size between the previous and current 'x' and
		'iteration' the number of iterations that have been taken.  If
		the callback function evaluates to True then the routine will end.

	Returns
	-------
	complex
		The approximation to a root of f.
	float
		abs(f(x)) where x is the final approximation for the root of f.
	"""
    y1, y2 = f(x1), f(x2)
    if abs(y1) < abs(y2):
        x1, x2 = x2, x1
        y1, y2 = y2, y1
    for iteration in range(maxIter):
        dx = -(x2 - x1) * y2 / (y2 - y1)
        x1, x2 = x2, x2 + dx
        y1, y2 = y2, f(x2)
        if callback is not None and callback(x2, dx, y2, iteration + 1):
            break
        if abs(dx) < steptol or abs(y2) < roottol:
            break
    return x2, abs(y2)


def is_acute(lengths):
    """Check if a triangle is acute with Pythgoras theorem."""
    l = sorted(lengths)
    return l[0] * l[0] + l[1] * l[1] >= l[2] * l[2]


def time_in_seconds(time_str):
    """Takes time code string, returns integer time in seconds"""
    hours = int(time_str[:2])
    minutes = int(time_str[3:5])
    seconds = int(time_str[6:])
    seconds_total = hours * 3600 + minutes * 60 + seconds
    return seconds_total


def do_task(fn, args_filename, result_filename):
    """Actually do the task."""
    import cPickle
    args, kw_args = cPickle.load(open(args_filename))
    result = fn(*args, **kw_args)
    cPickle.dump(result, open(result_filename, 'w'))


def deregister_instance(InstanceId=None):
    """
    Deregister a registered Amazon EC2 or on-premises instance. This action removes the instance from the stack and returns it to your control. This action can not be used with instances that were created with AWS OpsWorks Stacks.
    See also: AWS API Documentation

    :example: response = client.deregister_instance(
        InstanceId='string'
    )

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

    """
    pass


@staticmethod
def p_directive_next(symbols):
    """directive_next : SPACE COLON directive_argument
                          | COLON directive_argument
                          | empty
        """
    if len(symbols) == 3:
        symbols[0] = symbols[2].strip()
    elif len(symbols) == 4:
        symbols[0] = symbols[3].strip()
    elif len(symbols) == 2 and symbols[1] == ':':
        symbols[0] = ''
    else:
        symbols[0] = None


def getsuffix(subject):
    """
  Returns the suffix of a filename. If the file has no suffix, returns None.
  Can return an empty string if the filenam ends with a period.
  """
    index = subject.rfind('.')
    if index > subject.replace('\\', '/').rfind('/'):
        return subject[index + 1:]
    return None


@staticmethod
def score(uri: str) ->int:
    """
        Returns a score value for the give uri. E.g. 0 for unlikely/unknown, 20 for yes, probably thats the file format the reader can read.

        :param uri: str
        :return: int
        """
    return 0


def redir_dest_to_path(destination: str):
    """ Convert a redirection destination to a path fragment """
    if destination.startswith('/'):
        return destination[1:]
    return destination


def try_address(fqdn):
    """
    Check if the fqdn is valid
    Args:
        fqdn (str): fully qualified domain name
    """
    import socket
    try:
        socket.gethostbyname_ex(fqdn)
    except (socket.gaierror, UnicodeEncodeError):
        return False
    else:
        return True


def is_android_raw(raw):
    """
        Returns a string that describes the type of file, for common Android
        specific formats
    """
    val = None
    if raw[0:2] == b'PK' and b'META-INF/MANIFEST.MF' in raw:
        val = 'APK'
    elif raw[0:3] == b'dex':
        val = 'DEX'
    elif raw[0:3] == b'dey':
        val = 'DEY'
    elif raw[0:4] == b'\x03\x00\x08\x00':
        val = 'AXML'
    elif raw[0:4] == b'\x02\x00\x0c\x00':
        val = b'ARSC'
    return val


def box_label(key, verbose=False):
    """ Label boxes in graph by chunk index

    >>> box_label(('x', 1, 2, 3))
    '(1, 2, 3)'
    >>> box_label(('x', 123))
    '123'
    >>> box_label('x')
    ''
    """
    if isinstance(key, tuple):
        key = key[1:]
        if len(key) == 1:
            [key] = key
        return str(key)
    elif verbose:
        return str(key)
    else:
        return ''


def _delegate_methods(receiver, target):
    """Delegate target's public methods to receiver."""
    receiver_methods = frozenset(dir(receiver))
    target_methods = frozenset(dir(target))
    forward_methods = target_methods.difference(receiver_methods)
    for method in forward_methods:
        if not method.startswith('_'):
            ref = getattr(target, method)
            setattr(receiver, method, ref)


@classmethod
def to_bytes(cls, value):
    """
        Returns str(value). This should be overridden if this is not enough.
        """
    return str(value)


def _raise_error_if_not_function(arg, arg_name=None):
    """
    Check if the input is of expected type.

    Parameters
    ----------
    arg            : Input argument.

    arg_name      : The name of the variable in the function being used. No
                    name is assumed if set to None.

    Examples
    --------
    _raise_error_if_not_function(func, 'func')

    """
    display_name = '%s ' % arg_name if arg_name is not None else ''
    err_msg = 'Argument %smust be a function.' % display_name
    if not hasattr(arg, '__call__'):
        raise TypeError(err_msg)


@classmethod
def singleton(cls, cell, table):
    """
        Construct a bag with one cell in it
        """
    bag = cls(table=table)
    bag.add(cell)
    return bag


def are_aligned(shape1, shape2):
    """Check if two numpy arrays are aligned.

    Parameters
    ----------
    shape1, shape2 : iterable

    Returns
    -------
    isaligned : bool

    """
    isaligned = True
    shape1 = list(shape1)
    shape2 = list(shape2)
    try:
        while isaligned is True:
            dim1 = shape1.pop()
            dim2 = shape2.pop()
            if dim1 != dim2 and (dim1 != 1 and dim2 != 1):
                isaligned = False
    except IndexError:
        return isaligned
    return isaligned


def textparts(msg):
    """Return a set of all msg parts with content maintype 'text'."""
    return set(filter(lambda part: part.get_content_maintype() == 'text',
        msg.walk()))


def is_tel_link(href=None):
    """Utility function to determine whether the supplied href
    attribute is a telephone link."""
    print('is_tel_link()')
    return href and 'tel:' in href


def FillAtomLookUp(atomData, indx):
    """create a dictionary of atom indexes with atom IDs as keys

    :param list atomData: Atom table to be used

    :returns: dict atomLookUp: dictionary of atom indexes with atom IDs as keys

    """
    atomLookUp = {}
    for iatm, atom in enumerate(atomData):
        atomLookUp[atom[indx]] = iatm
    return atomLookUp


def _load_generic(packname, package, section, target):
    """Loads the settings for generic options that take FQDN and a boolean value
    (1 or 0).

    Args:
        packname (str): name of the package to get config settings for.
        package: actual package object.
    """
    from acorn.config import settings
    spack = settings(packname)
    if spack.has_section(section):
        secitems = dict(spack.items(section))
        for fqdn, active in secitems.items():
            target[fqdn] = active == '1'


def patch_prior_1_0(plotter_d, versions):
    """Patch psy_simple plotters for versions smaller than 1.0

    Before psyplot 1.0.0, the plotters in the psy_simple package where part of
    the psyplot.plotter.simple module. This has to be corrected"""
    plotter_d['cls'] = 'psy_simple.plotters', plotter_d['cls'][1]


@classmethod
def adapt_type(cls, name):
    """Convert a generic type name into this engine's version.

        E.g. for SQLite::

            >>> engine.adapt_type('SERIAL PRIMARY KEY')
            'INTEGER PRIMARY KEY'

        This is case insensitive, and passes through unknown type untouched::

            >>> engine.adapt_type('unknown')
            'unknown'

        """
    return cls._types.get(name.lower(), name)


@classmethod
def check_reserved(cls, name):
    """Check if an account name is reserved.

        :param str name: The account name to check
        :returns bool: True if the name is reserved, else False

        """
    return name in cls.RESERVED


def select_choice_from_multiple_matches(filename, match_set):
    """
    Function to ask user to choice which issue metadata to write,
    when there are multiple choices
    """
    print(f'\n{filename.name} - Multiple results found:')
    match_set = sorted(match_set, key=lambda m: m['cover_date'])
    for counter, match in enumerate(match_set, start=1):
        print(f"{counter}. {match['__str__']} ({match['cover_date']})")
    while True:
        i = input("Choose a match #, or 's' to skip: ")
        if i.isdigit() and int(i) in range(1, len(match_set) + 1) or i == 's':
            break
    if i != 's':
        i = int(i) - 1
        issue_id = match_set[i]['id']
    else:
        issue_id = None
    return issue_id


@classmethod
def ensure_type(cls, resource):
    """
        Ensure that resource is of python type 'cls'
        """
    if not isinstance(resource, cls):
        return cls(resource)
    else:
        return resource


def set_ht(A, a):
    """ Return the half-top of the given array.
    """
    nx, _ = A.shape
    li = int(nx / 2)
    A[:li, :] = a


@classmethod
def get_parsed(cls, name, content):
    """Initialize, parse and return instance"""
    instance = cls()
    instance.parse(name, content)
    return instance


@classmethod
def set(cls, key, value):
    """Set the congigure item """
    cls.cfg[key] = value


def cols_to_strip_commas(df, columns):
    """Strip commas from selected dataframe columns.

    Args:
        df: Pandas dataframe.
        columns: List of columns to convert.

    Returns:
        Original dataframe with converted column data.
    """
    for col in columns:
        df[col] = df[col].str.replace(',', '')
    return df


@staticmethod
def homogenize_types(df, groupby_cols):
    """Converting all GROUPBY columns to strings

        When grouping by a numeric (say FLOAT) column, pydruid returns
        strings in the dataframe. This creates issues downstream related
        to having mixed types in the dataframe

        Here we replace None with <NULL> and make the whole series a
        str instead of an object.
        """
    for col in groupby_cols:
        df[col] = df[col].fillna('<NULL>').astype('unicode')
    return df


@classmethod
def format_datum(cls, datum):
    """ datumsschreibweise: dd.mm.yyyy
        """
    if not isinstance(datum, type(None)):
        try:
            return datum.strftime('%d.%m.%Y')
        except:
            return str(datum)
    else:
        return '--.--.----'


@classmethod
def dt_is_naive(cls, dt):
    """
        Return true if dt is naive
        :param dt: datetime.datetime
        :type dt: datetime.datetime
        :return bool
        :rtype bool
        """
    if not dt.tzinfo:
        return True
    return False


@staticmethod
def payload_for_create(to_type, to_id, amount, currency, ip, **kwargs):
    """Build the API 'create transaction' payload from property values."""
    payload = {'to': {'type': to_type, 'id': to_id}, 'amount': {'amount':
        amount, 'currency': currency}, 'extra': {'ip': ip, 'supp_id':
        kwargs.get('supp_id') or '', 'note': kwargs.get('note') or ''}}
    if 'process_in' in kwargs:
        payload['extra']['process_on'] = kwargs['process_in']
    fees = []
    if 'fee_amount' in kwargs:
        fee = {'fee': kwargs['fee_amount'], 'note': kwargs.get('fee_note'),
            'to': {'id': kwargs['fee_to_id']}}
        fees.append(fee)
    if fees:
        payload['fees'] = fees
    if 'fees' in kwargs:
        payload['fees'] = kwargs['fees']
    return payload


def old_version(spec_ver):
    """Get the old version that was updated.

    :param spec_ver:  A tuple from current_version.
    """
    eq_ver = spec_ver[1]
    gte_ver = spec_ver[3]
    if eq_ver is not None:
        return eq_ver
    if gte_ver is not None:
        return gte_ver
    return 'Unknown'


def undo_push(message: str='Addanundostep*functionmaybemoved*'):
    """Add an undo state (internal use only)

    :param message: Undo Message
    :type message: str
    """
    pass


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

        :param SharedLinkShareDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_share_details', val)


def reprocess_wfc3ir(parallel=False, cpu_count=0, clean_dark_refs=True):
    """
    Run reprocessing script to flatten IR backgrounds

    """
    if parallel:
        import matplotlib as mpl
        mpl.rcParams['backend'] = 'agg'
    import glob
    import os
    import astropy.io.fits as pyfits
    try:
        from reprocess_wfc3 import reprocess_wfc3
    except:
        try:
            from mywfc3 import reprocess_wfc3
        except:
            print(
                """
    Couldn't `import reprocess_wfc3`.
    Get it from https://github.com/gbrammer/reprocess_wfc3 """
                )
            return False
    print('\ngrizli.pipeline.reprocess: Fetch calibrations...\n')
    files = glob.glob('*raw.fits')
    for file in files:
        reprocess_wfc3.fetch_calibs(file, ftpdir=
            'https://hst-crds.stsci.edu/unchecked_get/references/hst/',
            verbose=False)
    if parallel:
        files = glob.glob('*raw.fits')
        files.sort()
        reprocess_wfc3.show_ramps_parallel(files, cpu_count=cpu_count)
        files = glob.glob('*raw.fits')
        files.sort()
        reprocess_wfc3.reprocess_parallel(files, cpu_count=cpu_count)
    else:
        files = glob.glob('*raw.fits')
        files.sort()
        for file in files:
            if not os.path.exists(file.replace('raw.fits', 'ramp.png')):
                reprocess_wfc3.show_MultiAccum_reads(raw=file, stats_region
                    =[[300, 700], [300, 700]])
        for file in files:
            if not os.path.exists(file.replace('raw.fits', 'flt.fits')):
                reprocess_wfc3.make_IMA_FLT(raw=file, stats_region=[[300,
                    700], [300, 700]])
    if clean_dark_refs:
        files = glob.glob('*raw.fits')
        files.sort()
        for file in files:
            im = pyfits.open(file)
            dark_file = im[0].header['DARKFILE'].replace('iref$', '')
            dark_file = os.path.join(os.getenv('iref'), dark_file)
            im.close()
            if os.path.exists(dark_file):
                print('clean_dark: {0}'.format(dark_file))
                os.remove(dark_file)


def k62a(d):
    """Evaluate k in Eq. (6.2a)

    :param float d: The effective depth of a section of concrete ``[m]``
    :rtype: float
    """
    return 1 + (0.2 / d) ** 0.5


def listinfo():
    """
    @api {post} /music/moreinfo/listinfo 歌单信息
    @apiVersion 1.0.0
    @apiGroup More
    @apiDescription 歌单信息

    @apiParam (Headers) {string} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳

    @apiParam (Body) {String} categoryid 分类编号

    @apiSuccess (Success) {Object} response 响应
    @apiSuccess (Success) {String} response.start 开始
    @apiSuccess (Success) {String} response.docs 响应文档

    @apiSuccess (Success) {String} response.docs.total 歌曲总数
    @apiSuccess (Success) {String} response.docs.modifydate 修改日期
    @apiSuccess (Success) {String} response.docs.likeCount 喜欢次数
    @apiSuccess (Success) {String} response.docs.categoryID 分类编号
    @apiSuccess (Success) {String} response.docs.tag 标签
    @apiSuccess (Success) {String} response.docs.categoryType 分类类型
    @apiSuccess (Success) {String} response.docs.categoryCode 分类代号
    @apiSuccess (Success) {String} response.docs.havemore 剩余焦点图对象数
    @apiSuccess (Success) {String} response.docs.listenCount 试听次数
    @apiSuccess (Success) {String} response.docs.size 文件大小
    @apiSuccess (Success) {String} response.docs.author 作者
    @apiSuccess (Success) {String} response.docs.rank 等级
    @apiSuccess (Success) {String} response.docs.imagePathMap 图像路径图
    @apiSuccess (Success) {String} response.docs.imagePathMap.value 图像路径图值
    @apiSuccess (Success) {String} response.docs.imagePathMap.key 图像路径图键
    @apiSuccess (Success) {String} response.docs.description 描述
    @apiSuccess (Success) {String} response.docs.name 名称

    @apiSuccess (Success) {String} response.docs.stationItems 专辑单曲列表
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo 信息
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.genre 流派类型
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.bitrates 比特率
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.releasedate 发布日期
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.label 标签
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.exclusivity 歌曲版权付费模式（FREE，Normal，Purchase，ALAKA，Streaming，Cache）
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.translatename 翻译名称
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.version 版本
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.duration 歌曲时长
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.side 歌曲位于专辑的片（面）数
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.explicit 脏标
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.description 描述
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.name 名称
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.tracknumber 声音编号
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.rating 收听总数
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.cpItemID 出版商单曲编号
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.pinyinname 拼音名称
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.languagetype 语言类型
    @apiSuccess (Success) {String} response.docs.stationItems.datainfo.priceCode 价格代号

    @apiSuccess (Success) {String} response.docs.stationItems.artists 歌手列表
    @apiSuccess (Success) {String} response.docs.stationItems.artists.genre 歌手流派类型
    @apiSuccess (Success) {String} response.docs.stationItems.artists.region 歌手区域
    @apiSuccess (Success) {String} response.docs.stationItems.artists.birthday 歌手生日
    @apiSuccess (Success) {String} response.docs.stationItems.artists.itemcount 歌手单曲数量
    @apiSuccess (Success) {String} response.docs.stationItems.artists.translatename 歌手翻译名称
    @apiSuccess (Success) {String} response.docs.stationItems.artists.imagePathMap 歌手图像路径图
    @apiSuccess (Success) {String} response.docs.stationItems.artists.imagePathMap.value 歌手图像路径图值
    @apiSuccess (Success) {String} response.docs.stationItems.artists.imagePathMap.key 歌手图像路径图键
    @apiSuccess (Success) {String} response.docs.stationItems.artists.artistID 歌手编号
    @apiSuccess (Success) {String} response.docs.stationItems.artists.description 歌手描述
    @apiSuccess (Success) {String} response.docs.stationItems.artists.name 歌手名称
    @apiSuccess (Success) {String} response.docs.stationItems.artists.gender 歌手性别
    @apiSuccess (Success) {String} response.docs.stationItems.artists.rating 歌手收听总数
    @apiSuccess (Success) {String} response.docs.stationItems.artists.pinyinname 歌手拼音姓名
    @apiSuccess (Success) {String} response.docs.stationItems.artists.albumcount 歌手专辑数量

    @apiSuccess (Success) {String} response.docs.stationItems.itemID 单曲编号

    @apiSuccess (Success) {String} response.docs.stationItems.imagePath 图片路径

    @apiSuccess (Success) {String} response.docs.stationItems.description 描述

    @apiSuccess (Success) {String} response.docs.stationItems.album 专辑列表
    @apiSuccess (Success) {String} response.docs.stationItems.album.genre 专辑流派类型
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo 专辑出版商信息
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.contentProviderGroupID 专辑版权唱片公司分组编号
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.cpGroupName 专辑出版公司组名
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.cpGroupAltName 专辑出版公司组名更改名
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.cpName 专辑出版公司名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.cpCode 专辑出版公司代号
    @apiSuccess (Success) {String} response.docs.stationItems.album.cpInfo.contentProviderID 专辑版权唱片公司ID
    @apiSuccess (Success) {String} response.docs.stationItems.album.albumID 专辑专辑编号
    @apiSuccess (Success) {String} response.docs.stationItems.album.releasedate 专辑发布日期
    @apiSuccess (Success) {String} response.docs.stationItems.album.translatename 专辑翻译名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.version 专辑版本
    @apiSuccess (Success) {String} response.docs.stationItems.album.artists 专辑歌手
    @apiSuccess (Success) {String} response.docs.stationItems.album.artists.artistname 专辑歌手名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.artists.artistID 专辑歌手编号
    @apiSuccess (Success) {String} response.docs.stationItems.album.artists.artisttranslatename 专辑歌手翻译名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.artists.artistpinyinname 专辑歌手拼音名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.totaltrack 专辑总声音数量
    @apiSuccess (Success) {String} response.docs.stationItems.album.imagePathMap 专辑图像路径图
    @apiSuccess (Success) {String} response.docs.stationItems.album.imagePathMap.value 专辑图像路径图值
    @apiSuccess (Success) {String} response.docs.stationItems.album.imagePathMap.key 专辑图像路径图键
    @apiSuccess (Success) {String} response.docs.stationItems.album.explicit 专辑排他性
    @apiSuccess (Success) {String} response.docs.stationItems.album.albumPriceCode 专辑价格代号
    @apiSuccess (Success) {String} response.docs.stationItems.album.description 专辑描述
    @apiSuccess (Success) {String} response.docs.stationItems.album.name 专辑名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.totaldisk 专辑总磁盘
    @apiSuccess (Success) {String} response.docs.stationItems.album.rating 专辑收听总数
    @apiSuccess (Success) {String} response.docs.stationItems.album.pinyinname 专辑拼音名称
    @apiSuccess (Success) {String} response.docs.stationItems.album.languagetype 专辑语言类型

    @apiSuccess (Success) {String} response.docs.stationItems.itemType 单曲类型

    @apiSuccess (Success) {String} response.docs.offset 偏移量

    @apiSuccess (Success) {String} response.docs.favorivateCount 喜欢数量

    @apiSuccess (Success) {String} response.numFound 查找数量

    @apiSuccess (Success) {Object} responseHeader 响应头
    @apiSuccess (Success) {String} responseHeader.errorinfo 错误信息
    @apiSuccess (Success) {String} responseHeader.status 状态

    @apiSuccessExample {json} Success-Response:
    {
        "data": {
            "response": {
                "start": 0,
                "docs": {
                    "total": 4,
                    "modifydate": "2018-06-22",
                    "likeCount": 1324,
                    "categoryID": 2,
                    "tag": "",
                    "categoryType": "CT_SUBJECT",
                    "categoryCode": "ST_Subject_2",
                    "havemore": 0,
                    "listenCount": 11734,
                    "size": 4,
                    "author": "爱听站长",
                    "rank": 3,
                    "imagePathMap": [
                        {
                            "value": "/station/000/2-JPG-320X320-STATION.jpg",
                            "key": "JPG-320X320-STATION"
                        }
                    ],
                    "description": "奥斯卡百年",
                    "name": "奥斯卡百年",
                    "stationItems": [
                        {
                            "datainfo": {
                                "genre": "Pop",
                                "bitrates": [
                                    "LRC-LRC",
                                    "MP3-128K-FTD",
                                    "MP3-192K-FTD",
                                    "MP3-256K-FTD",
                                    "MP3-320K-FTD"
                                ],
                                "releasedate": "2000-05-02",
                                "label": "Columbia",
                                "exclusivity": 1,
                                "translatename": "Things Have Changed",
                                "version": "",
                                "duration": "05:08",
                                "side": 1,
                                "explicit": 0,
                                "description": "",
                                "name": "Things Have Changed",
                                "tracknumber": 1,
                                "rating": 49569,
                                "cpItemID": "2202629_FTD",
                                "pinyinname": "Things Have Changed",
                                "languagetype": "ENG",
                                "priceCode": ""
                            },
                            "artists": [
                                {
                                    "genre": "Pop",
                                    "region": "US",
                                    "birthday": "1941-5-24",
                                    "itemcount": 4497,
                                    "translatename": "鲍勃·迪伦",
                                    "imagePathMap": [
                                        {
                                            "value": "/artist/000/2303-JPG-240X240-ARTIST.jpg",
                                            "key": "JPG-240X240-ARTIST"
                                        }
                                    ],
                                    "artistID": 2303,
                                    "description": "Bob Dylan 的原名是Robert Allen Zi-mmerman，1941年5月24日生于明尼苏达州的杜勒斯（Duluth），6 岁时全家移居到一个叫希宾（Hibbing）的靠近矿区的小镇上，少年时期的Dylan 只不过是一个喜爱音乐的平凡男孩，对乡村乐感兴趣。1961年1月，Bob Dylan从明尼苏达州立大学辍学，开始专心致力于歌唱工作，并来到纽约Cate Wha 民谣音乐城（Folk City）和煤气灯（Gaslight）等著名的表演场所演出。由于 Dylan的民谣歌曲受到知识分子的喜爱与",
                                    "name": "Bob Dylan",
                                    "gender": "Male",
                                    "rating": 1362949,
                                    "pinyinname": "Bob Dylan",
                                    "albumcount": 275
                                }
                            ],
                            "itemID": 721799,
                            "imagePath": "",
                            "description": "",
                            "album": {
                                "genre": "Pop",
                                "cpInfo": [
                                    {
                                        "contentProviderGroupID": 52,
                                        "cpGroupName": "索尼音乐",
                                        "cpGroupAltName": "索尼音乐",
                                        "cpName": "Columbia",
                                        "cpCode": "Columbia",
                                        "contentProviderID": 3755
                                    }
                                ],
                                "albumID": 73511,
                                "releasedate": "2000-05-02",
                                "translatename": "Best Of Bob Dylan, Vol. 2",
                                "version": "",
                                "artists": [
                                    {
                                        "artistname": "Bob Dylan",
                                        "artistID": 2303,
                                        "artisttranslatename": "鲍勃·迪伦",
                                        "artistpinyinname": "Bob Dylan"
                                    }
                                ],
                                "totaltrack": 17,
                                "imagePathMap": [
                                    {
                                        "value": "/album/007/73511-JPG-240X240-ALBUM.jpg",
                                        "key": "JPG-240X240-ALBUM"
                                    }
                                ],
                                "explicit": 0,
                                "albumPriceCode": -1,
                                "description": "",
                                "name": "Best Of Bob Dylan, Vol. 2",
                                "totaldisk": 1,
                                "rating": 45068,
                                "pinyinname": "Best Of Bob Dylan, Vol. 2",
                                "languagetype": "ENG"
                            },
                            "itemType": "FTD"
                        }
                    ],
                    "offset": 0,
                    "favorivateCount": 1296
                },
                "numFound": 1
            },
            "responseHeader": {
                "errorinfo": "",
                "status": "00"
            }
        }
    }

    @apiError (Error) 31015 No categoryid id in the request params!

    @apiErrorExample {json} Error-Response:
    {
        "data": "No categoryid id in the request params!"
    }
    """


@staticmethod
def format_issue_link(link):
    """Converts issue link to tuple."""
    try:
        link_target = link.outwardIssue
        link_type = link.type.outward
    except AttributeError:
        link_target = link.inwardIssue
        link_type = link.type.inward
    return ('I{0}'.format(link.id), link_type, link_target.fields.summary,
        link_target.fields.status.name, '')


def titleize(s):
    """fooBar -> FooBar"""
    if not s:
        return s
    else:
        return '{}{}'.format(s[0].upper(), s[1:])


def libcxx_flag(compiler, libcxx):
    """
    returns flag specific to the target C++ standard library
    """
    if not compiler or not libcxx:
        return ''
    if str(compiler) in ['clang', 'apple-clang']:
        if str(libcxx) in ['libstdc++', 'libstdc++11']:
            return '-stdlib=libstdc++'
        elif str(libcxx) == 'libc++':
            return '-stdlib=libc++'
    elif str(compiler) == 'sun-cc':
        return {'libCstd': '-library=Cstd', 'libstdcxx': '-library=stdcxx4',
            'libstlport': '-library=stlport4', 'libstdc++': '-library=stdcpp'
            }.get(libcxx, '')
    elif str(compiler) == 'qcc':
        return '-Y _%s' % str(libcxx)
    return ''


def make_collection(iterable_or_singleton, type=list):
    """Make a collection from either an iterable of elements or a singleton element."""
    try:
        iterator = iter(iterable_or_singleton)
        return type(iterator)
    except TypeError:
        return type((iterable_or_singleton,))


def normalize(data):
    """
    Function to normalize data to have mean 0 and unity standard deviation
    (also called z-transform)

    Parameters
    ----------
    data : numpy.ndarray

    Returns
    -------
    numpy.ndarray
        z-transform of input array

    """
    data = data.astype(float)
    data -= data.mean()
    return data / data.std()


def doNext(action):
    """Process something if next action get exceuted."""


def bitstobytes(bits):
    """
    Interprets an indexable list of booleans as bits, MSB first, to be
    packed into a list of integers from 0 to 256, MSB first, with LSBs
    zero-padded. Note this padding behavior means that round-trips of
    bytestobits(bitstobytes(x, width=W)) may not yield what you expect
    them to if W % 8 != 0

    Does *NOT* pack the returned values into a bytearray or the like.

    >>> import peepdf.lzw
    >>> bitstobytes([0, 0, 0, 0, 0, 0, 0, 0, "Yes, I'm True"]) == [ 0x00, 0x80 ]
    True
    >>> bitstobytes([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0]) == [ 0x01, 0x30 ]
    True
    """
    ret = []
    nextbyte = 0
    nextbit = 7
    for bit in bits:
        if bit:
            nextbyte = nextbyte | 1 << nextbit
        if nextbit:
            nextbit = nextbit - 1
        else:
            ret.append(nextbyte)
            nextbit = 7
            nextbyte = 0
    if nextbit < 7:
        ret.append(nextbyte)
    return ret


@classmethod
def from_file(cls, filename):
    """
        Create a public blob from a ``-cert.pub``-style file on disk.
        """
    with open(filename) as f:
        string = f.read()
    return cls.from_string(string)


def update_model():
    """TODO: implement this"""
    pass


@classmethod
def from_table(cls, table):
    """Create from `~astropy.table.Table`."""
    if 'ENERG_LO' in table.colnames:
        e_lo = table['ENERG_LO'].quantity[0]
        e_hi = table['ENERG_HI'].quantity[0]
    elif 'ETRUE_LO' in table.colnames:
        e_lo = table['ETRUE_LO'].quantity[0]
        e_hi = table['ETRUE_HI'].quantity[0]
    else:
        raise ValueError(
            'Invalid column names. Need "ENERG_LO/ENERG_HI" or "ETRUE_LO/ETRUE_HI"'
            )
    o_lo = table['THETA_LO'].quantity[0]
    o_hi = table['THETA_HI'].quantity[0]
    m_lo = table['MIGRA_LO'].quantity[0]
    m_hi = table['MIGRA_HI'].quantity[0]
    matrix = table['MATRIX'].quantity[0].transpose()
    return cls(e_true_lo=e_lo, e_true_hi=e_hi, offset_lo=o_lo, offset_hi=
        o_hi, migra_lo=m_lo, migra_hi=m_hi, data=matrix)


@staticmethod
def tmpl_upper(s):
    """Covert a string to upper case."""
    return s.upper()


@staticmethod
def _gamma_limit(gamma):
    """
        limits the power-law slope to certain bounds

        :param gamma: power-law slope
        :return: bounded power-law slopte
        """
    return gamma


def list_deelgemeente_adapter(obj, request):
    """
    Adapter for rendering a list of
    :class:`crabpy.gateway.crab.Deelgemeente` to json.
    """
    return {'id': obj.id, 'naam': obj.naam}


@staticmethod
def from_array(array, force_copy=False, force_numpy=True, try_optimizing=
    False, wrapped=True):
    """
        Build a new object of the type corresponding to the wrapper from the supplied `array` (a 1D numpy array or a list).

        If ``force_copy==True``, make a copy of supplied array.
        For a :class:`Column1DWrapper`, if `column` is a list and ``force_numpy==True``, turn it into a numpy array and return :class:`.ArrayDataColumn`
        (by default lists are wrapped into :class:`.ListDataColumn`).
        For a :class:`Column1DWrapper`, if ``try_optimizing==True``, check if the column can be turned into a :class:`.LinearDataColumn`.
        If ``wrapped==True``, return a new wrapper contating the column; otherwise, just return the column.
        """
    raise NotImplementedError('I1DWrapper.from_array')


def parselinenos(spec, total):
    """
    Parse a line number spec (such as "1,2,4-6") and return a list of wanted line numbers.

    copied from sphinx.util import parselinenos
    """
    items = list()
    parts = spec.split(',')
    for part in parts:
        try:
            begend = part.strip().split('-')
            if len(begend) > 2:
                raise ValueError
            if len(begend) == 1:
                items.append(int(begend[0]) - 1)
            else:
                start = begend[0] == '' and 0 or int(begend[0]) - 1
                end = begend[1] == '' and total or int(begend[1])
                items.extend(range(start, end))
        except Exception:
            raise ValueError('invalid line number spec: %r' % spec)
    return items


@classmethod
def validate_type(cls, argument_name, argument, expected_type):
    """
        Validate ``argument`` is a subclass of ``expected_type``
        """
    if not issubclass(argument, expected_type):
        raise TypeError(cls._ARGUMENT_TYPE_MESSAGE.format(name=
            argument_name, type=expected_type, arg=argument))


def dxrange(start, end=None, inc=None, include_end=False):
    """ The xrange function for Decimal """
    from decimal import Decimal
    assert inc != 0, 'inc should not be zero'
    if end is None:
        end = start
        start = 0
    if inc is None:
        inc = 1
    inc = Decimal(inc)
    start = Decimal(start)
    end = Decimal(end)
    nextv = start
    while True:
        if inc > 0 and (not include_end and nextv == end or nextv > end
            ) or inc < 0 and (not include_end and nextv == end or nextv < end):
            break
        yield nextv
        nextv += inc


def extract(text, starter=None, ender=None):
    """Return string in text between starter and ender.

    If starter is None, truncate at ender.
    """
    if starter and starter in text:
        text = text.partition(starter)[2]
    if ender:
        return text.partition(ender)[0]
    return text


def get_dims(da):
    """
    Simple function to retrieve dimensions from a given dataset/datarray.
    Currently returns as a list, but can add keyword to select tuple or
    list if desired for any reason.
    """
    return list(da.dims)


def lineWidth(requestContext, seriesList, width):
    """
    Takes one metric or a wildcard seriesList, followed by a float F.

    Draw the selected metrics with a line width of F, overriding the default
    value of 1, or the &lineWidth=X.X parameter.

    Useful for highlighting a single metric out of many, or having multiple
    line widths in one graph.

    Example::

        &target=lineWidth(server01.instance01.memory.free,5)

    """
    for series in seriesList:
        series.options['lineWidth'] = width
    return seriesList


def project_opened(project):
    """This function is called after opening the project"""


def is_leap_year(year):
    """
    Indicates whether the specified year is a leap year.

    Every year divisible by 4 is a leap year -- 1912, 1996, 2016, 2032, etc.,
    are leap years -- UNLESS the year is divisible by 100 AND NOT by 400. Thus,
    1200, 1600, 2000, 2400, etc., are leap years, while 1800, 1900, 2100, etc.,
    are not.

    Why do we have this logic?
    This is because the earth orbits the sun in approximately 365.2425 days.
    Over 400 orbits, that comes out to 146,097 days (365.2425 * 400).

    Ignoring the century rule (making every fourth year a leap year, including
    1800, 1900, etc.), gives us 146,100 days, overcounting by 3 days every
    400 years. Thus, making 3 out of every 4 century boundaries non-leap years
    fixes this overcounting.
    """
    return year % 400 == 0 or year % 4 == 0 and year % 100 != 0


def send_data_to_gpu(simulation):
    """
    Send the simulation data to the GPU.
    Calls the functions of the particle and field package
    that send the data to the GPU.

    Parameters :
    ------------
    simulation : object
        A simulation object that contains the particle
        (ptcl) and field object (fld)
    """
    for species in simulation.ptcl:
        if species.use_cuda:
            species.send_particles_to_gpu()
    simulation.fld.send_fields_to_gpu()


def resolveRelationToken(token):
    """Returns a relation for the given token"""


def compoundSectorialization(agents):
    """Compute and return sections with compound criteria

    agents is a dict with keys "d", "id", "od", "s", "is", "os"
    with sectorialized_agents__ with each of these criteria
    """
    exc_h = set(agents['d'][-1][2]) & set(agents['id'][-1][2]) & set(agents
        ['od'][-1][2]) & set(agents['s'][-1][2]) & set(agents['is'][-1][2]
        ) & set(agents['os'][-1][2])
    exc_i = set(agents['d'][-1][1]) & set(agents['id'][-1][1]) & set(agents
        ['od'][-1][1]) & set(agents['s'][-1][1]) & set(agents['is'][-1][1]
        ) & set(agents['os'][-1][1])
    exc_p = set(agents['d'][-1][0]) & set(agents['id'][-1][0]) & set(agents
        ['od'][-1][0]) & set(agents['s'][-1][0]) & set(agents['is'][-1][0]
        ) & set(agents['os'][-1][0])
    exc = exc_p, exc_i, exc_h
    inc_h = set(agents['d'][-1][2]) | set(agents['id'][-1][2]) | set(agents
        ['od'][-1][2]) | set(agents['s'][-1][2]) | set(agents['is'][-1][2]
        ) | set(agents['os'][-1][2])
    inc_i = set(agents['d'][-1][1]) | set(agents['id'][-1][1]) | set(agents
        ['od'][-1][1]) | set(agents['s'][-1][1]) | set(agents['is'][-1][1]
        ) | set(agents['os'][-1][1])
    inc_p = set(agents['d'][-1][0]) | set(agents['id'][-1][0]) | set(agents
        ['od'][-1][0]) | set(agents['s'][-1][0]) | set(agents['is'][-1][0]
        ) | set(agents['os'][-1][0])
    inc = inc_p, inc_i, inc_h
    total = set(agents['d'][-1][0] + agents['d'][-1][1] + agents['d'][-1][2])
    excc_h = exc[2]
    excc_p = inc[0]
    excc_i = total - (exc[2] | inc[0])
    excc = excc_p, excc_i, excc_h
    incc_h = inc[2]
    incc_p = excc[0]
    incc_i = total - (incc_h | incc_p)
    incc = incc_p, incc_i, incc_h
    exce_h = exc[2]
    exce_i = inc[1]
    exce_p = total - (exce_h | exce_i)
    exce = exce_p, exce_i, exce_h
    ince_h = inc[2]
    ince_i = exc[1]
    ince_p = total - (ince_h | ince_i)
    ince = ince_p, ince_i, ince_h
    return dict(total=total, exc=exc, inc=inc, excc=excc, incc=incc, exce=
        exce, ince=ince)


def __call__(authentication):
    """Creates a principal.

        The authentication utility that called the factory is passed
        and should be included in the principal-created event.
        """


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


def _check_arg_length(fname, args, max_fname_arg_count, compat_args):
    """
    Checks whether 'args' has length of at most 'compat_args'. Raises
    a TypeError if that is not the case, similar to in Python when a
    function is called with too many arguments.
    """
    if max_fname_arg_count < 0:
        raise ValueError("'max_fname_arg_count' must be non-negative")
    if len(args) > len(compat_args):
        max_arg_count = len(compat_args) + max_fname_arg_count
        actual_arg_count = len(args) + max_fname_arg_count
        argument = 'argument' if max_arg_count == 1 else 'arguments'
        raise TypeError(
            f'{fname}() takes at most {max_arg_count} {argument} ({actual_arg_count} given)'
            )


@staticmethod
def toggle_prev_img(_):
    """Toggles the preview image."""
    print('Toggling')
    pass


def _getLigatureKey(components):
    """Computes a key for ordering ligatures in a GSUB Type-4 lookup.

    When building the OpenType lookup, we need to make sure that
    the longest sequence of components is listed first, so we
    use the negative length as the primary key for sorting.
    To make buildLigatureSubstSubtable() deterministic, we use the
    component sequence as the secondary key.

    For example, this will sort (f,f,f) < (f,f,i) < (f,f) < (f,i) < (f,l).
    """
    return -len(components), components


def _flavor_string(capacity_key, primary_disk):
    """Removed the _X_YEAR_TERM from capacity_key and adds the primary disk size, creating the flavor keyName

    This will work fine unless 10 year terms are invented... or flavor format changes...
    """
    flavor = '%sX%s' % (capacity_key[:-12], primary_disk)
    return flavor


def get_index(samp):
    """Return Sample samp's index."""
    return samp.get_index()


def _domcmc(input_tuple):
    """Function to be run in parallel on different CPUs
    Input is a tuple: first element is an emcee sampler object, second is an array of
    initial positions, third is number of steps to run before doing a convergence check
    """
    sampler = input_tuple[0]
    ipos = input_tuple[1]
    check_interval = input_tuple[2]
    sampler.run_mcmc(ipos, check_interval)
    return sampler


def round_to_base(value, base=1):
    """
    This method expects an integer or float value, and will round it to any
    given integer base.  For example:

      1.5, 2 -> 2
      3.5, 2 -> 4
      4.5, 2 -> 4

      11.5, 20 -> 20
      23.5, 20 -> 20
      34.5, 20 -> 40

    The default base is '1'.
    """
    return int(base * round(float(value) / base))


def m_step(ind_base_prob):
    """
    Update allele frequency.

    Parameters
    ----------

    ``ind_base_prob``: 2d-array like, n x 4 matrix.

    """
    sample_size = ind_base_prob.shape[0]
    expect_allele_prob = ind_base_prob.sum(axis=0) / sample_size
    return expect_allele_prob


@classmethod
def run_model(cls, model, inputs, device=None, **kwargs):
    """
        Compute the prediction.

        :param model: :class:`onnxruntime.InferenceSession` returned
            by function *prepare*
        :param inputs: inputs
        :param device: requested device for the computation,
            None means the default one which depends on
            the compilation settings
        :param kwargs: see :class:`onnxruntime.RunOptions`
        :return: predictions
        """
    rep = cls.prepare(model, device, **kwargs)
    return rep.run(inputs, **kwargs)