def get_error_message(response):
    """
    Gets the error message from a JSON response.
    :return: the error message
    :rtype: string
    """
    error_message = 'Unknown error'
    try:
        error_json = response.json()
        if 'error' in error_json:
            if isinstance(error_json['error'], dict
                ) and 'description' in error_json['error']:
                error_message = error_json['error']['description']
            else:
                error_message = error_json['error']
        elif 'error_message' in error_json:
            error_message = error_json['error_message']
        elif 'message' in error_json:
            error_message = error_json['message']
        elif 'description' in error_json:
            error_message = error_json['description']
        elif 'errorMessage' in error_json:
            error_message = error_json['errorMessage']
        elif 'msg' in error_json:
            error_message = error_json['msg']
        return error_message
    except:
        return response.text or error_message


def read(filename, binary=True):
    """
    Open and read a file

    :param filename: filename to open and read
    :param binary: True if the file should be read as binary
    :return: bytes if binary is True, str otherwise
    """
    with open(filename, 'rb' if binary else 'r') as f:
        return f.read()


@staticmethod
def get_object_id(resource) ->str:
    """
        **Can be overridden**.

        Returns the id (string) of the resource. The default implementation
        looks for a property ``resource.id``, an id method ``resource.id()``,
        ``resource.get_id()`` or a key ``resource["id"]``.

        :arg resource:
            A resource object
        :rtype: str
        :returns:
            The string representation of ID of the *resource*
        """
    if hasattr(resource, 'id'):
        resource_id = resource.id() if callable(resource.id) else resource.id
    elif hasattr(resource, 'get_id'):
        resource_id = resource.get_id()
    elif 'id' in resource:
        resource_id = resource['id']
    else:
        raise Exception('Could not determine the resource id.')
    return str(resource_id)


def PreciseAMPM():
    """Return the time string for the object."""


def __eq__(other):
    """
        Weak references should be equal to other objects that
        weakly reference the same object.
        """


def getE1(n):
    """Small Correction term. Defaults to 0.01 for now"""
    return 0.01


def get_colmin(data):
    """
    Get rowwise column names with minimum values

    :param data: pandas dataframe
    """
    data = data.T
    colmins = []
    for col in data:
        colmins.append(data[col].idxmin())
    return colmins


@staticmethod
def check_module(target_configuration):
    """ Perform any module specific checks now that the target
        configuration is complete.  target_configuration is the target
        configuration.
        """


def unquote(s):
    """
    Undo the effects of quote(). Based heavily on urllib.unquote().
    """
    mychr = chr
    myatoi = int
    list = s.split('_')
    res = [list[0]]
    myappend = res.append
    del list[0]
    for item in list:
        if item[1:2]:
            try:
                myappend(mychr(myatoi(item[:2], 16)) + item[2:])
            except ValueError:
                myappend('_' + item)
        else:
            myappend('_' + item)
    return ''.join(res)


@classmethod
def post_init(cls, func):
    """A decorator for defining a routine to run after creation of a type object.

        An example use of this method would be to define a classmethod that gathers
        any defined methods or attributes after the base Python type construction (i.e. after
        :py:func:`type` has been called)
        """
    setattr(func, cls.__postinit, True)
    return classmethod(func)


def get(isdsAppliance, uuid, check_mode=False, force=False):
    """
    Get a specific rsyslog object
    """
    return isdsAppliance.invoke_get('Get a specific rsyslog object',
        '/rsp_rsyslog_objs/{0}'.format(uuid))


def write(data):
    """
        The producer will write data by calling this method.

        The implementation must be non-blocking and perform whatever
        buffering is necessary.  If the producer has provided enough data
        for now and it is a L{IPushProducer}, the consumer may call its
        C{pauseProducing} method.
        """


def outextend(things):
    """
        extend right side of outgoing things with `things`

        @param thing: some things
        """


def openhardlinks():
    """return true if it is safe to hold open file handles to hardlinks"""
    return True


def return_list_matching_keys(dicto, list_keys):
    """Return a list of values matching keys in a dictionary
    from a list of keys. Returns Values in the Same order as the List Keys.
    """
    results = []
    for each in list_keys:
        results.append(dicto[each])
    return results


def default_timestamp(start_time):
    """
    Returns the default timestamp.

    :param start_time:
        Run start time.
    :type start_time: datetime.datetime

    :return:
        Run timestamp.
    :rtype: str
    """
    return start_time.strftime('%Y%m%d_%H%M%S')


def encode_data(data):
    """
    Helper that converts :class:`str` or :class:`bytes` to :class:`bytes`.
    :class:`str` are encoded with UTF-8.
    """
    if isinstance(data, str):
        return data.encode('utf-8')
    elif isinstance(data, bytes):
        return data
    else:
        raise TypeError('data must be bytes or str')


@staticmethod
def _dot(x, y):
    """Alternative formulation of dot product to allow missing values in arrays/matrices"""
    pass


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

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

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


def delete_nonestimator_parameters(parameters):
    """
    Delete all parameters in a parameter dictionary that are not used for the
    actual estimator.
    """
    if 'Number' in parameters.keys():
        del parameters['Number']
    if 'UsePCA' in parameters.keys():
        del parameters['UsePCA']
        del parameters['PCAType']
    if 'Imputation' in parameters.keys():
        del parameters['Imputation']
        del parameters['ImputationMethod']
        del parameters['ImputationNeighbours']
    if 'SelectFromModel' in parameters.keys():
        del parameters['SelectFromModel']
    if 'Featsel_Variance' in parameters.keys():
        del parameters['Featsel_Variance']
    if 'FeatPreProcess' in parameters.keys():
        del parameters['FeatPreProcess']
    if 'FeatureScaling' in parameters.keys():
        del parameters['FeatureScaling']
    if 'StatisticalTestUse' in parameters.keys():
        del parameters['StatisticalTestUse']
        del parameters['StatisticalTestMetric']
        del parameters['StatisticalTestThreshold']
    if 'SampleProcessing_SMOTE' in parameters.keys():
        del parameters['SampleProcessing_SMOTE']
        del parameters['SampleProcessing_SMOTE_ratio']
        del parameters['SampleProcessing_SMOTE_neighbors']
        del parameters['SampleProcessing_SMOTE_n_cores']
    if 'SampleProcessing_Oversampling' in parameters.keys():
        del parameters['SampleProcessing_Oversampling']
    return parameters


@classmethod
def _stripe_object_destination_to_account(cls, target_cls, data):
    """
        Search the given manager for the Account matching this Charge object's
        ``destination`` field.

        :param target_cls: The target class
        :type target_cls: Account
        :param data: stripe object
        :type data: dict
        """
    if 'destination' in data and data['destination']:
        return target_cls._get_or_create_from_stripe_object(data, 'destination'
            )[0]


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

    """
    pass


def separate_block(comment):
    """
    We have a comment but it's not much use as a big chunk of text.

    This function simply strips away the opening and closing comment syntax
    and then splits the first line from the second.

    The meta elements (the first line) needs a bit of splitting up but as for
    the rest, because it's straight YAML, we can just parse the entire block
    without having to clean up or modify anything. Easy!

    :param comment: list
    :return: dictionary
    """
    block = dict()
    comment = comment.replace('"""\n', '').replace('\n"""', '')
    block['meta'] = comment.split('\n')[0]
    block['body'] = '\n'.join(comment.split('\n')[1:])
    return block


@staticmethod
def isAscii(_strIn):
    """
        Check if all characters in a string are ascii,

        @param _strIn: input string
        @type _strIn: python string
        @return: boolean
        @rtype: boolean
        """
    bIsAcii = True
    for i in _strIn:
        if ord(i) > 127:
            bIsAcii = False
            break
    return bIsAcii


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


def compress_dataset(ds):
    """
    Apply internal netCDF4 compression
    """
    for var in ds.data_vars:
        ds[var].encoding['zlib'] = True
    return ds


@staticmethod
def _serialize_bytes(value):
    """
        Serializes the value and pads to multiple of 32 bytes

        :param value:
        :type value: str or bytearray or Array
        """
    return value + bytearray(b'\x00' * (32 - len(value)))


def pick_one(iterable):
    """
    Helper function that returns an element of an iterable (it the iterable is ordered this will be the first
    element).
    """
    it = iter(iterable)
    return next(it)


def write(data):
    """Output some data to the target."""


def last_element(iter):
    """
    Returns the last element of sequence assuming they
    were generated by an iterator or a generator.

    @param      iter        iterator or generator
    @return                 element

    .. runpython::
        :showcode:

        from ensae_projects.hackathon.image_helper import last_element

        def gen():
            for i in range(10):
                yield "A%d" % i

        print(last_element(gen()))
    """
    el = None
    for el in iter:
        pass
    return el


@classmethod
def arg_yaxis(cls, parser):
    """Add an `~argparse.ArgumentGroup` for Y-axis options.
        """
    return cls._arg_axis('y', parser)


@staticmethod
def accepted_ct():
    """Return a list of content types accepted by the tile."""
    return ['Folder']


@classmethod
def load(cls, gpio_pin_str, mode_str):
    """Make an instance using the gpio_pin as a string."""
    delay, = cls._parse_mode_str(mode_str, cls.BOUNCE_REGEX, cls.BOUNCE_GROUP)
    return cls(gpio_pin_str, delay or cls.BOUNCE_DEFAULT)


def strfboard(board, render_characters='+ox', end='\n'):
    """
    Format a board as a string

    Parameters
    ----
    board : np.array
    render_characters : str
    end : str

    Returns
    ----
    s : str
    """
    s = ''
    for x in range(board.shape[0]):
        for y in range(board.shape[1]):
            c = render_characters[board[x][y]]
            s += c
        s += end
    return s[:-len(end)]


@classmethod
def create(cls, uri=None, search_spec=None, search_string=None, payload=
    None, **kwargs):
    """Creates an item on the server"""
    exists = cls.find(uri=uri, search_spec=search_spec, search_string=
        search_string, extended_fetch=False)
    if not exists.json():
        return cls.post(uri, payload)
    else:
        return exists


def BlockGrad(data=None, name=None, attr=None, out=None, **kwargs):
    """Stops gradient computation.

    Stops the accumulated gradient of the inputs from flowing through this operator
    in the backward direction. In other words, this operator prevents the contribution
    of its inputs to be taken into account for computing gradients.

    Example::

      v1 = [1, 2]
      v2 = [0, 1]
      a = Variable('a')
      b = Variable('b')
      b_stop_grad = stop_gradient(3 * b)
      loss = MakeLoss(b_stop_grad + a)

      executor = loss.simple_bind(ctx=cpu(), a=(1,2), b=(1,2))
      executor.forward(is_train=True, a=v1, b=v2)
      executor.outputs
      [ 1.  5.]

      executor.backward()
      executor.grad_arrays
      [ 0.  0.]
      [ 1.  1.]

    Defined in src/operator/tensor/elemwise_unary_op_basic.cc:L327

    Parameters
    ----------
    data : Symbol
        The input array.

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

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


def ToPdfRGB(R, G, B):
    """
    Tuple ToPdfRGB(Tuple RGB)

    Convert the standard RGB (0 ~ 255)
    to pdf normalized RGB (0 ~ 1)

    The RGB is 3 elements Tuple, i.e, (R, G, B).
    Returns pdfRGB in tupl, , i.e, (pdfR, pdfG, pdfB)
    """
    return 1.0 * R / 255, 1.0 * G / 255, 1.0 * B / 255


@classmethod
def process_name(cls):
    """ Return current process name for multithreaded envs """
    import multiprocessing
    mp_name = multiprocessing.current_process().name
    if mp_name is None:
        mp_name = 'Main'
    return mp_name


def delete(url, headers={}, ok_responses=[200]):
    """HTTP DELETE request
	:param purl: a Pico URL, formatted using the EventURL and ApiURL objects
	:param headers: additional HTTP headers to include in the request
	:param ok_responses: a list of HTTP response codes that don't trigger an error
	:return: a boolean, response object pair - (True, SuccessResponse) or (False, ErrorResponse)
	"""
    return None


def nullfunc(*args):
    """A simple no-op function to be used as dll replacement."""
    return


def create_media_entry(conn, model_id=None, model_type='document',
    collection_name='default', name=None, file_name=None, mime_type=
    'application/pdf', disk='media', size=None, manipulations='[]',
    custom_properties='[]', order_column=None, created_at=None, updated_at=None
    ):
    """
    Creates an entry in the database table 'media'.
    :param conn: Connection to database
    :param model_id: ID
    :param model_type: "car" or "document"
    :param collection_name: Type of the document
    :param name: ÜP or RP or something like this
    :param file_name: Name of uploaded file
    :param mime_type: "application/pdf"
    :param disk: "media"
    :param size: Filesize in byte
    :param manipulations: empty json
    :param custom_properties: empty json
    :param order_column: wtf?
    :param created_at: NOW!
    :param updated_at: Now or nothing
    :return:
    """
    query = (
        """INSERT INTO media
            (model_id, model_type, collection_name, name, file_name, mime_type, disk, size, manipulations,
             custom_properties, order_column, created_at, updated_at)
    VALUES ({}, '{}', '{}', '{}', '{}', '{}', '{}', {}, '{}', '{}', {}, '{}', '{}')
    """
        .format(model_id, model_type, collection_name, name, file_name,
        mime_type, disk, size, manipulations, custom_properties,
        order_column, created_at, updated_at))
    cur = conn.cursor()
    cur.execute(query)
    conn.commit()
    cur.close()


def __fix_context(context):
    """Return a new context dict based on original context.

    The new context will be a copy of the original, and some mutable
    members (such as script and css files) will also be copied to
    prevent polluting shared context.
    """
    COPY_LISTS = 'script_files', 'css_files'
    for attr in COPY_LISTS:
        if attr in context:
            context[attr] = context[attr][:]
    return context


def pretty_table(cursor):
    """
    美化打印table返回的数据(只支持select)
    :param cursor: cursor数据库的游标
    :return: None
    """
    from prettytable import from_db_cursor
    tb = from_db_cursor(cursor=cursor)
    tb.align = 'l'
    print(tb)
    return


def parse_pubsub_numsub(command, res, **options):
    """
    Result callback, handles different return types
    switchable by the `aggregate` flag.
    """
    aggregate = options.get('aggregate', True)
    if not aggregate:
        return res
    numsub_d = dict()
    for _, numsub_tups in res.items():
        for channel, numsubbed in numsub_tups:
            try:
                numsub_d[channel] += numsubbed
            except KeyError:
                numsub_d[channel] = numsubbed
    ret_numsub = []
    for channel, numsub in numsub_d.items():
        ret_numsub.append((channel, numsub))
    return ret_numsub


def close():
    """
        Close the wormhole.

        This frees all resources associated with the wormhole (including
        server-side queues and any established network connections).

        For operational purposes, it informs the server that the wormhole
        closed "happy".  Less-happy moods may be reported if the connection
        closed due to a ``WrongPasswordError`` or because of a timeout.

        ``close()`` returns a Deferred, which fires after the server has been
        informed and the sockets have been shut down.  One-shot applications
        should delay shutdown until this Deferred has fired, to increase the
        chances that server resources will be freed.  Long-running
        applications can probably ignore the Deferred, as they'll probably
        remain running long enough to allow the shutdown to complete.

        The Deferred will errback if the wormhole had problems, like a
        ``WrongPasswordError``.

        :return: a Deferred that fires when shutdown is complete
        :rtype: ``Deferred``
        """


def fixernames(ui):
    """Returns the names of [fix] config options that have suboptions"""
    names = set()
    for k, v in ui.configitems(b'fix'):
        if b':' in k:
            names.add(k.split(b':', 1)[0])
    return names


def named_list(items, name='item'):
    """named_list([1, 2, 3], 'number') -> 'numbers (1, 2, 3)"""
    if len(items) == 1:
        return '%s (%r)' % (name, items[0])
    else:
        if name.endswith('y'):
            name = name[:-1] + 'ie'
        return '%ss (%s)' % (name, ', '.join(map(repr, items)))


def getattrs(obj, *attrs):
    """
    Get existing attributes of an object lazy

    >>> from argparse import Namespace
    >>> d = Namespace(henk=1, klaas=2, hent=7)
    >>> r = getattrs(d, "klaas")
    >>> list(r)
    [2]
    >>> r = getattrs(d, "henk", "hent")
    >>> list(r)
    [1, 7]
    >>> r = getattrs(d, "henk", "kak")
    >>> list(r)
    [1, None]
    """
    for attr in attrs:
        yield getattr(obj, attr, None)


@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 theta_BOH4_Cl_FW86(T, P):
    """a-a': borate chloride [FW86]."""
    theta = -0.065
    valid = T == 298.15
    return theta, valid


@staticmethod
def read_file(file: str) ->str:
    """ Given a file path, we read it and print it out """
    file = str(file)
    with open(file) as f:
        text = f.read()
    return text


def _get_interpolator_nd(method, **kwargs):
    """helper function to select the appropriate interpolator class

    returns interpolator class and keyword arguments for the class
    """
    valid_methods = ['linear', 'nearest']
    try:
        from scipy import interpolate
    except ImportError:
        raise ImportError('Interpolation with method `%s` requires scipy' %
            method)
    if method in valid_methods:
        kwargs.update(method=method)
        interp_class = interpolate.interpn
    else:
        raise ValueError(
            '%s is not a valid interpolator for interpolating over multiple dimensions.'
             % method)
    return interp_class, kwargs


def writePhen(phen, filename, missing='9', sep='\t'):
    """
    must contain phen['iid'] and phen['vals']
    """
    N = phen['iid'].shape[0]
    M = phen['vals'].shape[1]
    assert N == phen['vals'].shape[0
        ], "number of individuals do not match up in phen['vals'] and phen['ids']"
    with open(filename, 'w') as f:
        for i in range(0, N):
            tmpstr = phen['iid'][i][0] + sep + phen['iid'][i][1]
            for m in range(0, M):
                tmpstr += sep + str(phen['vals'][i][m])
            tmpstr += '\n'
            f.write(tmpstr)


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 current_ratio(current_assets, current_liabilities, inventory=0):
    """Computes current ratio.

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

    returns
    -------
    Current ratio, int or float

    explanation
    -----------

    """
    return (current_assets - inventory) / current_liabilities


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


def validate_boolean(setting, value, option_parser, config_parser=None,
    config_section=None):
    """Check/normalize boolean settings:
         True:  '1', 'on', 'yes', 'true'
         False: '0', 'off', 'no','false', ''
    """
    if isinstance(value, bool):
        return value
    try:
        return option_parser.booleans[value.strip().lower()]
    except KeyError:
        raise LookupError('unknown boolean value: "%s"' % value)


def scan(pattern, string, *args, **kwargs):
    """ Returns True if pattern.search(Sentence(string)) may yield matches.
        If is often faster to scan prior to creating a Sentence and searching it.
    """
    return compile(pattern, *args, **kwargs).scan(string)


@staticmethod
def payload_for_create(nickname, **kwargs):
    """Build the API 'create subnet' payload from property values."""
    payload = {'nickname': nickname}
    return payload


def chunk_string_ignoring_whitespace(s, size):
    """Skip over whitespace when assembling chunks."""
    assert size > 1
    chunks = []
    chunk = ''
    for c in s:
        if c.isspace():
            continue
        chunk += c
        if len(chunk) == size:
            chunks.append(chunk)
            chunk = ''
    if chunk:
        chunks.append(chunk)
    return chunks


@staticmethod
def fit_deriv(x, amplitude, x_0, fwhm):
    """One dimensional Lorentzian model derivative with respect to parameters"""
    d_amplitude = fwhm ** 2 / (fwhm ** 2 + (x - x_0) ** 2)
    d_x_0 = amplitude * d_amplitude * (2 * x - 2 * x_0) / (fwhm ** 2 + (x -
        x_0) ** 2)
    d_fwhm = 2 * amplitude * d_amplitude / fwhm * (1 - d_amplitude)
    return [d_amplitude, d_x_0, d_fwhm]


def parse_time(time_str, ctx={}):
    """ start:stop:step (arbitrary types, with local ctx) OR index """
    if ':' not in time_str:
        return eval(time_str, {}, ctx)
    s = []
    for i in time_str.split(':'):
        if len(i) > 0:
            s.append(eval(i, {}, ctx))
        else:
            s.append(None)
    return slice(*s)


def metaSiteLabels(cls):
    """ Set cls.labels list withstations, e.g. ['100p1',...] """
    if cls.nc is None:
        return None
    for label_arr in cls.nc.variables['metaSiteLabel']:
        cls.labels.append(cls.byte_arr_to_string(label_arr))
    return cls.labels


@staticmethod
def write_file_undul_phot(undul_phot_dict, file_out='uphot.dat'):
    """
        write uphot.dat file from a dictionary with the output of undul_phot
        :param undul_phot_dict: a dictionary {'radiation':RN0, 'polarization':POL_DEG, 'photon_energy':E, 'theta':TT, 'phi':PP}
        :param file_out: name of the output file (Default: uphot.dat)
        :return:
        """
    Z2 = undul_phot_dict['radiation']
    POL_DEG = undul_phot_dict['polarization']
    e = undul_phot_dict['photon_energy']
    theta = undul_phot_dict['theta']
    phi = undul_phot_dict['phi']
    NG_E = e.size
    NG_T = theta.size
    NG_P = phi.size
    f = open(file_out, 'w')
    f.write('%d  %d  %d \n' % (NG_E, NG_T, NG_P))
    for ie in range(NG_E):
        f.write('%20.10f \n' % e[ie])
    for ie in range(NG_E):
        for t in range(NG_T):
            f.write('%20.10f \n' % theta[t])
    for ie in range(NG_E):
        for t in range(NG_T):
            for p in range(NG_P):
                f.write('%20.10f \n' % phi[p])
    for ie in range(NG_E):
        for t in range(NG_T):
            for p in range(NG_P):
                f.write('%20.10f \n' % Z2[ie, t, p])
    for ie in range(NG_E):
        for t in range(NG_T):
            for p in range(NG_P):
                f.write('%20.10f \n' % POL_DEG[ie, t, p])
    f.close()
    print('File written to disk: %s' % file_out)


def module_is_namespace(mod):
    """Is the module object `mod` a PEP420 namespace module?"""
    return hasattr(mod, '__path__') and getattr(mod, '__file__', None) is None


def bench1(x):
    """A benchmark function for test purposes.

        f(x) = x ** 2

    It has a single minima with f(x*) = 0 at x* = 0.
    """
    return x[0] ** 2


def shape_key_retime():
    """Resets the timing for absolute shape keys

    """
    pass


def add_suffix(in_files, suffix):
    """
    Wrap nipype's fname_presuffix to conveniently just add a prefix

    >>> add_suffix([
    ...     '/path/to/sub-045_ses-test_T1w.nii.gz',
    ...     '/path/to/sub-045_ses-retest_T1w.nii.gz'], '_test')
    'sub-045_ses-test_T1w_test.nii.gz'

    """
    import os.path as op
    from nipype.utils.filemanip import fname_presuffix, filename_to_list
    return op.basename(fname_presuffix(filename_to_list(in_files)[0],
        suffix=suffix))


def insert_sort_key(event):
    """Sort / group function that batches events that share the same
    SCID and set of fields. We need to group together events that
    belong to the same schema AND that have the same set of fields.
    Please note that schemas allow for optional fields that might/might
    not have been included in the event.
    """
    return (event['schema'], event['revision']), tuple(sorted(event))


def create_generate(kind, project, resource, offset):
    """A factory for creating `Generate` objects

    `kind` can be 'variable', 'function', 'class', 'module' or
    'package'.

    """
    generate = eval('Generate' + kind.title())
    return generate(project, resource, offset)


def authGSSServerInit(service):
    """
    Initializes a context for GSSAPI server-side authentication with the given
    service principal.
    authGSSServerClean must be called after this function returns an OK result
    to dispose of the context once all GSSAPI operations are complete.

    @param service: A string containing the service principal in the form
        C{"type@fqdn"}. To initialize the context for the purpose of accepting
        delegated credentials, pass the literal string C{"DELEGATE"}.

    @return: A tuple of (result, context) where result is the result code (see
        above) and context is an opaque value that will need to be passed to
        subsequent functions.
    """


def red_bold(payload):
    """
    Format payload as red.
    """
    return u'\x1b[31;1m{0}\x1b[39;22m'.format(payload)


@classmethod
def from_module_dict(cls, environment, module_dict, globals):
    """Creates a template object from a module.  This is used by the
        module loader to create a template object.

        .. versionadded:: 2.4
        """
    return cls._from_namespace(environment, module_dict, globals)


def engine_map_modelfunc(coeff_values, X):
    """
    The function that models the engine-map.
    """
    a = coeff_values['a']
    b = coeff_values['b']
    c = coeff_values['c']
    a2 = coeff_values['a2']
    b2 = coeff_values['b2']
    loss0 = coeff_values['loss0']
    loss2 = coeff_values['loss2']
    pmf = X['pmf']
    cm = X['cm']
    bmep = (a + b * cm + c * cm ** 2) * pmf + (a2 + b2 * cm
        ) * pmf ** 2 + loss0 + loss2 * cm ** 2
    return bmep


def _get_windows_console_width() ->int:
    """
    A small utility function for getting the current console window's width, in Windows.

    :return: The current console window's width.
    """
    from ctypes import byref, windll
    import pyreadline
    out = windll.kernel32.GetStdHandle(-11)
    info = pyreadline.console.CONSOLE_SCREEN_BUFFER_INFO()
    windll.kernel32.GetConsoleScreenBufferInfo(out, byref(info))
    return info.dwSize.X


def _to_numeric(value):
    """
    Convert the value to a number
    """
    try:
        value = int(value)
    except (TypeError, ValueError):
        try:
            value = float(value)
        except (TypeError, ValueError):
            pass
    return value


def is_valid_iobes(tags):
    """Judge whether `tags' is a valid IOBES string.

    Parameters
    ----------
    tags: list
        List of tags.

    Returns
    -------
    is_valid: boolean
        True if `tags' is in valid IOBES format, otherwise False.

    """
    for i, tag in enumerate(tags):
        if tag == 'O':
            continue
        fields = tag.split('-')
        if len(fields) != 2 or fields[0] not in ['B', 'I', 'E', 'S']:
            return False
        pos, tag_name = fields
        if pos in ['B', 'I'] and (i + 1 == len(tags) or tags[i + 1].split(
            '-') not in [['I', tag_name], ['E', tag_name]]):
            return False
        if pos in ['I', 'E'] and (i == 0 or tags[i - 1].split('-') not in [
            ['B', tag_name], ['I', tag_name]]):
            return False
    return True


def __str__():
    """As a unique ASCII string"""


def text_copy():
    """Copy selected text to clipboard

    """
    pass


def sizeof_fmt(num: float) ->str:
    """Generates the human-readable version of a file size.

    >>> sizeof_fmt(512)
    512bytes
    >>> sizeof_fmt(2048)
    2KB

    :param num: Robot-readable file size in bytes
    :return: Human-readable file size"""
    for item in ['bytes', 'KB', 'MB', 'GB']:
        if num < 1024.0:
            return '%3.1f%s' % (num, item)
        num /= 1024.0
    return '%3.1f%s' % (num, 'TB')


def on_complete(harn):
    """
        custom callback typically used to evaluate or deploy the final model.

        Overload Encouraged
        """
    pass


@staticmethod
def _adp_bias_volts_to_raw_convert(value, inverse):
    """Convert ADP bias from user values to internal values (or reverse)."""
    ret = 0.0
    if inverse:
        ret = -(value * 5 * 18.18 / 4096) + 122
    else:
        ret = (-122 - value) * 4096 / (5 * 18.18)
    return ret


def ensure_list(obj):
    """
    This function ensures that *obj* is a list.  Typically used to convert a
    string to a list, for instance ensuring the *fields* as an argument is a
    list.
    """
    if obj is None:
        return [obj]
    if not isinstance(obj, list):
        return [obj]
    return obj


def get_parent_folder(path, sep='/'):
    """Returns the path corresponding to the parent folder of <path>."""
    l = len(path)
    n = -1
    for i in range(l - 2, -1, -1):
        if path[i] == sep:
            n = i
            break
    if n > 0:
        return path[:n + 1]
    else:
        return -1


def psi_K_CO3_Cl_HMW84(T, P):
    """c-a-a': potassium carbonate chloride [HMW84]."""
    psi = 0.004
    valid = T == 298.15
    return psi, valid


def _table_relabel(table, substitutions, replacements=None):
    """
    Change table column names, otherwise leaving table unaltered

    Parameters
    ----------
    substitutions

    Returns
    -------
    relabeled : TableExpr
    """
    if replacements is not None:
        raise NotImplementedError
    observed = set()
    exprs = []
    for c in table.columns:
        expr = table[c]
        if c in substitutions:
            expr = expr.name(substitutions[c])
            observed.add(c)
        exprs.append(expr)
    for c in substitutions:
        if c not in observed:
            raise KeyError('{0!r} is not an existing column'.format(c))
    return table.projection(exprs)


def _get_resource_tag(resource_type, tag, runtime, chip, resource_id=None):
    """
    Get resource tag by resource type.

    IMPORTANT:
        resource_id is optional to enable calling this method before the training resource has been created
        resource_tag will be incomplete (missing resource_id appended to the end) when resource_id is NOT supplied

    :param resource_type:   Type of resource (job, function, model, stream) - currently not used but here to enable generic method
    :param tag:             User defined tag for the resource
    :param runtime:         Runtime used to serve the resource  Valid values: python, tfserving, tflight
    :param chip:            Type of hardware chip used to server the resource
    :param resource_id:     (optional) Id that uniquely identifies the trained resource

    :return:                resource tag
    """
    resource_tag = tag + runtime + chip
    if resource_id:
        resource_tag += resource_id
    return resource_tag


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

        :param SharedLinkSettingsAllowDownloadDisabledDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_settings_allow_download_disabled_details', val)


def cont(x, D, mixed=False):
    """Generate fraction representation using Aberth method"""
    B = abs(x)
    P_2, P_1, P, Q_2, Q_1, Q = 0, 1, 0, 1, 0, 0
    while Q_1 < D:
        A = int(B)
        P = A * P_1 + P_2
        Q = A * Q_1 + Q_2
        if B - A < 5e-08:
            break
        B = 1.0 / (B - A)
        P_2, P_1 = P_1, P
        Q_2, Q_1 = Q_1, Q
    if Q > D:
        if Q_1 <= D:
            P, Q = P_1, Q_1
        else:
            P, Q = P_2, Q_2
    sgn = -1 if x < 0 else 1
    if not mixed:
        return [0, sgn * P, Q]
    q = divmod(sgn * P, Q)
    return [q[0], q[1], Q]


def time2str(date_time, pattern):
    """pattern: %Y-%m-%d, %H:%M:%S"""
    if not date_time:
        return None
    return date_time.strftime(pattern)


def get_model_instance(model_class, instance_or_id, raise_on_error=True):
    """
    Get model's instance by id.
    :param model_class:
    :param instance_or_id:
    :param raise_on_error: if False, return None instead of raise.
    :return:
    """
    if isinstance(instance_or_id, model_class):
        return instance_or_id
    else:
        try:
            return model_class.objects.get(pk=instance_or_id)
        except Exception as e:
            if raise_on_error:
                raise
            else:
                return None


def ndof_all():
    """Pan and rotate the view with the 3D mouse

    """
    pass


def transit_sec(in_sec, start_sec, end_sec, transit_list):
    """
    determine in what sectors the marked transit are.

    Parameters
    ----------
    in_sec : list
        the sectors that we are looking at.
    start_sec : list
        the start time of these sectors
    end_sec : list
        the end time of these sectors
    transit_list : list
        list of the marked peaks

    Returns
    -------
    transit_sec  : list
        list of the sectors in which the peaks appear.

    """
    transit_sec = []
    for peak in transit_list:
        for n, start in enumerate(start_sec):
            if peak >= start[0] and peak <= end_sec[n][0]:
                transit_sec.append(in_sec[n])
    return list(set(transit_sec))


def writeGastoDust(temp, model, ming2d=1.0):
    """Gas-to-dust ratios."""
    temp.append('void gasIIdust(double x, double y,')
    temp.append(' double z, double *gtd) {\n\n')
    if type(model.g2d) is float:
        temp.append('\t*gtd = %.1f;\n\n' % model.g2d)
    else:
        temp.append('\t*gtd = findvalue(x, y, z, gastodust);\n\n')
    temp.append('\tif (*gtd < 1e-4) {\n\t\t*gtd = 1e-4;\n\t}\n}\n\n\n')
    return


def batch_results(mgr, results, qname='output'):
    """*DEPRECATED*. Use TFNode.DataFeed class instead."""
    raise Exception('DEPRECATED: Use TFNode.DataFeed class instead')


def ca_to_h1h2(c, alpha):
    """
    Transform for power-2 law coefficients
    h1 = 1 - c*(1-0.5**alpha)
    h2 = c*0.5**alpha

    :param c: power-2 law coefficient, c
    :param alpha: power-2 law exponent, alpha

    returns: h1, h2

    """
    return 1 - c * (1 - 0.5 ** alpha), c * 0.5 ** alpha


def only(iterable, default=None, too_long=None):
    """If *iterable* has only one item, return it.
    If it has zero items, return *default*.
    If it has more than one item, raise the exception given by *too_long*,
    which is ``ValueError`` by default.

    >>> only([], default='missing')
    'missing'
    >>> only([1])
    1
    >>> only([1, 2])  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    ValueError: Expected exactly one item in iterable, but got 1, 2,
     and perhaps more.'
    >>> only([1, 2], too_long=TypeError)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    TypeError

    Note that :func:`only` attempts to advance *iterable* twice to ensure there
    is only one item.  See :func:`spy` or :func:`peekable` to check
    iterable contents less destructively.
    """
    it = iter(iterable)
    first_value = next(it, default)
    try:
        second_value = next(it)
    except StopIteration:
        pass
    else:
        msg = (
            'Expected exactly one item in iterable, but got {!r}, {!r}, and perhaps more.'
            .format(first_value, second_value))
        raise (too_long or ValueError(msg))
    return first_value


@staticmethod
def get_instance_impact(stream_defect, instance_number=1):
    """Get the current impact of the 'nth' incident of this issue (High/Medium/Low)"""
    counter = instance_number
    for instance in stream_defect.defectInstances:
        counter -= 1
        if counter == 0:
            return instance.impact.name
    return ''


def _trace_mm(x, y):
    """
    Computes ``trace(x.T @ y)``.
    """
    assert x.dim() >= 2
    assert y.dim() >= 2
    return (x * y).sum([-1, -2])


def ephem2juldate(num):
    """Convert ephem date (measured from noon, Dec. 31, 1899) to Julian date."""
    return float(num + 2415020.0)


def tarjan(graph):
    """Strongly connected components by Tarjan, iterative implementation

    :param graph: directed graph in listlist format, cannot be listdict
    :returns: list of lists for each component
    :complexity: linear
    """
    n = len(graph)
    dfs_num = [None] * n
    dfs_min = [n] * n
    waiting = []
    waits = [False] * n
    sccp = []
    dfs_time = 0
    times_seen = [-1] * n
    for start in range(n):
        if times_seen[start] == -1:
            times_seen[start] = 0
            to_visit = [start]
            while to_visit:
                node = to_visit[-1]
                if times_seen[node] == 0:
                    dfs_num[node] = dfs_time
                    dfs_min[node] = dfs_time
                    dfs_time += 1
                    waiting.append(node)
                    waits[node] = True
                children = graph[node]
                if times_seen[node] == len(children):
                    to_visit.pop()
                    dfs_min[node] = dfs_num[node]
                    for child in children:
                        if waits[child] and dfs_min[child] < dfs_min[node]:
                            dfs_min[node] = dfs_min[child]
                    if dfs_min[node] == dfs_num[node]:
                        component = []
                        while True:
                            u = waiting.pop()
                            waits[u] = False
                            component.append(u)
                            if u == node:
                                break
                        sccp.append(component)
                else:
                    child = children[times_seen[node]]
                    times_seen[node] += 1
                    if times_seen[child] == -1:
                        times_seen[child] = 0
                        to_visit.append(child)
    return sccp


def get(key):
    """
        Получить значения ключа.

        Если ключ не найден (не существует, потерян, истекло время жизни),
        возвращается исключение C{KeyError}.

        @param key: ключ
        @type key: C{str}
        @return: Deferred значение ключа, C{str} или C{int}
        @rtype: C{twisted.internet.Deferred}
        """


def convert_specimen_dm3_table(spec_df):
    """
    Convert MagIC specimen headers to short/readable
    headers for a figure (used by ipmag.specimens_extract)
    """
    from pmagpy import data_model3 as dm3
    dm = dm3.DataModel()
    meas_group = ['meas_step_min', 'meas_step_max', 'meas_step_unit']
    pint_group = dm.get_group_headers('specimens', 'Paleointensity')
    arai_group = dm.get_group_headers('specimens',
        'Paleointensity Arai Statistics')
    dm3_columns = list(meas_group) + list(pint_group) + list(arai_group)
    dm3_columns = filter(lambda x: '_rel' not in x, dm3_columns)
    meas_group_columns = ['meas_step_min', 'meas_step_max', 'meas_step_unit']
    pint_group_columns = list(spec_df.columns.intersection(pint_group))
    arai_group_columns = list(spec_df.columns.intersection(arai_group))
    columns = ['specimen', 'sample'
        ] + meas_group_columns + pint_group_columns + arai_group_columns
    spec_df = spec_df.copy()[columns]
    muT_list = ['int_abs', 'int_abs_sigma', 'int_treat_dc_field']
    meas_list = ['meas_step_min', 'meas_step_max']
    for el in muT_list:
        if el in columns:
            spec_df[el] = 1000000.0 * spec_df[el]
    if 'meas_step_unit' in columns:
        for el in meas_list:
            spec_df.loc[spec_df['meas_step_unit'] == 'K', el] = spec_df[el
                ] - 273
            spec_df.loc[spec_df['meas_step_unit'] == 'T', el
                ] = 1000.0 * spec_df[el]
        spec_df.loc[spec_df['meas_step_unit'] == 'K', 'meas_step_unit'] = 'C'
        spec_df.loc[spec_df['meas_step_unit'] == 'T', 'meas_step_unit'] = 'mT'
        spec_df['meas_step_min'] = spec_df['meas_step_min'].astype('int')
        spec_df['meas_step_max'] = spec_df['meas_step_max'].astype('int')
    dm3_columns = ['meas_step_min', 'meas_step_max', 'meas_step_unit',
        'int_abs', 'int_abs_sigma', 'int_abs_sigma_perc',
        'int_n_measurements', 'int_corr', 'int_corr_cooling_rate',
        'int_corr_aniso', 'int_corr_nlt', 'int_corr_arm',
        'int_viscosity_index', 'int_treat_dc_field', 'int_b', 'int_b_sigma',
        'int_b_beta', 'int_rsc', 'int_f', 'int_fvds', 'int_frac', 'int_g',
        'int_gmax', 'int_q', 'int_w', 'int_k', 'int_k_sse', 'int_k_prime',
        'int_k_prime_sse', 'int_scat', 'int_r2_corr', 'int_r2_det', 'int_z',
        'int_z_md']
    table_columns = ['Min', 'Max', 'Units', 'B (uT)', 'sigma', 'percent',
        'N', 'c/u', 'CR', 'Aniso.', 'NLT', 'AARM', 'VI', 'Lab Field', 'b',
        'b sigma', 'beta', 'R2', 'f', 'fvds', 'frac', 'g', 'gap max', 'q',
        'w', 'k', 'k sse', 'k prime', 'k prime sse', 'scat', 'r2 corr',
        'r2 det', 'Z', 'Z md']
    spec_mapping = dict(list(zip(dm3_columns, table_columns)))
    spec_df_out = spec_df.rename(columns=spec_mapping)
    if 'N' in spec_df_out.columns:
        spec_df_out['N'] = spec_df_out['N'].astype('int')
    if 'Lab Field' in spec_df_out.columns:
        spec_df_out['Lab Field'] = spec_df_out['Lab Field'].round().astype(
            'int')
    return spec_df_out


def safe_getitem(dct, key, item):
    """Return either dct[key][item],  dct[key].item, or None, whichever
    is appropriate
    """
    if key not in dct:
        return None
    value = dct[key]
    try:
        result = value[item]
    except TypeError:
        if isinstance(item, str):
            result = getattr(value, item, None)
        else:
            result = None
    except (KeyError, IndexError) as ex:
        result = None
    return result


def fix_name(player):
    """
    Get rid of (A) or (C) when a player has it attached to their name

    :param player: list of player info -> [number, position, name]

    :return: fixed list
    """
    if player[2].find('(A)') != -1:
        player[2] = player[2][:player[2].find('(A)')].strip()
    elif player[2].find('(C)') != -1:
        player[2] = player[2][:player[2].find('(C)')].strip()
    return player


def getColumnsClasses():
    """Returns all CSS classes based on columns presence.
        """


def replace_suffix(filename, old_suffix, new_suffix):
    """
    Replace `old_suffix` with `new_suffix`.
    """
    basename = filename[0:-len(old_suffix)]
    return basename + new_suffix


def face_select_linked_pick(deselect: bool=False):
    """Select linked faces under the cursor

    :param deselect: Deselect, Deselect rather than select items
    :type deselect: bool
    """
    pass


def sanitize_wordpiece(wordpiece: str) ->str:
    """
    Sanitizes wordpieces from BERT or RoBERTa tokenizers.
    """
    if wordpiece.startswith('##'):
        return wordpiece[2:]
    elif wordpiece.startswith('Ġ'):
        return wordpiece[1:]
    else:
        return wordpiece


def tga_pixel_bytes_size(parent=None, attr_index=None, new_value=None, **kwargs
    ):
    """Size getter for the byte size of tga pixel data"""
    if new_value is not None:
        return
    if parent is None:
        raise KeyError('Cannot calculate the size of tga ' +
            'pixels without without a supplied parent.')
    if attr_index is not None and hasattr(parent[attr_index], '__len__'):
        return len(parent[attr_index])
    header = parent.parent.header
    pixels = header.width * header.height
    image_type = header.image_type
    if image_type.format == 0:
        return pixels // 8
    elif header.bpp in (15, 16):
        return 2 * pixels
    return header.bpp * pixels // 8


@staticmethod
def class_weight():
    """Class weights used for rebalancing the dataset,
    by skewing the `loss` accordingly."""
    return [1.0, 4.0]


def visual_transform_apply():
    """Apply final constrained position of pose bones to their transform

    """
    pass


def dupliob_move_down():
    """Move dupli object down in the list

    """
    pass


def clean_name(name, replace='_'):
    """Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file. All characters besides A-Z/a-z, 0-9 are replaced with “_” or the replace argument if defined.

    """
    pass


@staticmethod
def _get_module_status(status, i):
    """Get the status dict for the module with the given pipeline index.

        Parameters
        ----------
        status : reV.pipeline.status.Status
            reV job status object.
        i : int
            pipeline index of desired module.

        Returns
        -------
        out : dict
            Status dictionary for the module with pipeline index i.
        """
    for module_status in status.data.values():
        i_current = module_status.get('pipeline_index', -99)
        if str(i) == str(i_current):
            out = module_status
            break
    return out


def create_cython_ext_modules(cython_modules, profile_cython=False, debug=False
    ):
    """
    Create :class:`~distutils.extension.Extension` objects from
    *cython_modules*.

    *cython_modules* must be a dict, as returned by :func:`parse_setup_cfg`.

    If *profile_cython* is true, Cython modules are compiled to support Python
    proiflers.

    Debug symbols are included if *debug* is true.
    """
    if profile_cython:
        from Cython.Distutils import Extension
    else:
        from distutils.extension import Extension
    ret = []
    for name, mod_data in cython_modules.items():
        kwargs = {'name': name}
        kwargs.update(mod_data)
        if profile_cython:
            cython_directives = kwargs.setdefault('cython_directives', {})
            cython_directives['profile'] = True
        if debug:
            for args_name in ('extra_compile_args', 'extra_link_args'):
                args = kwargs.setdefault(args_name, [])
                if '-g' not in args:
                    args.append('-g')
        ext = Extension(**kwargs)
        ret.append(ext)
    return ret


def check_dht_value_type(value):
    """
    Checks to see if the type of the value is a valid type for
    placing in the dht.
    """
    typeset = [int, float, bool, str, bytes]
    return type(value) in typeset


def strip(s):
    """Convert `s` to a string and return it white-space stripped."""
    return str(s).strip()


def read_in_chunks(file_object, size=1024):
    """Lazy function (generator) to read a file piece by piece."""
    while True:
        data = file_object.read(size)
        if not data:
            break
        yield data


def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


def _axIs3D(axhandle):
    """Check if given axes handle object is a 3D plot.

    :param axhandle: matplotlib axes handle object
    :type axhandle: mpl.axes.Axes or mpl_toolkits.mplot3d.axes3d.Axes3D
    """
    return hasattr(axhandle, 'get_zlim')


def make_column_height_width_dict(column, cell_width_dicts):
    """
    For a non-column-spanned column, determine it's height at breakpoint
    widths and make a dictionary of the heights:widths
    """
    breakpoints = []
    for row in range(len(cell_width_dicts)):
        for col in range(len(cell_width_dicts[row])):
            if col == column:
                breakpoints.extend(list(cell_width_dicts[row][col].keys()))
    breakpoints = list(set(breakpoints))
    height_widths = {}
    for bp in breakpoints:
        column_height = 0
        for row in range(len(cell_width_dicts)):
            for col in range(len(cell_width_dicts[row])):
                if column == col:
                    keys = list(sorted(cell_width_dicts[row][column].keys(),
                        reverse=True))
                    added = False
                    for i in range(len(keys)):
                        if bp >= keys[i] and added == False:
                            column_height += cell_width_dicts[row][column][
                                keys[i]]
                            added = True
                    if added == False:
                        column_height += cell_width_dicts[row][column][keys[-1]
                            ] + 1
        try:
            if bp < height_widths[column_height]:
                height_widths[column_height] = bp
        except KeyError:
            height_widths[column_height] = bp
    return height_widths


def trace2index_flat(shape, ntrace):
    """
    Calculate the index of a trace assuming a flat structure
    """
    q = ntrace
    index = []
    for s in shape[:0:-1]:
        q, r = divmod(q, s)
        index.insert(0, r)
    index.insert(0, q)
    return tuple(index)


@classmethod
def from_nlp(cls, nlp, **cfg):
    """Factory to add to Language.factories via entry point."""
    return cls(nlp.vocab, **cfg)


def _get_color_definitions(data):
    """Returns the list of custom color definitions for the TikZ file.
    """
    definitions = []
    ff = data['float format']
    for name, rgb in data['custom colors'].items():
        definitions.append(
            f'\\definecolor{{{name}}}{{rgb}}{{{rgb[0]:{ff}},{rgb[1]:{ff}},{rgb[2]:{ff}}}}'
            )
    return definitions


def target_distribution(q):
    """
    Calculate the target distribution

    Attributes
    ----------
    q : array
        the input data

    Returns
    -------
    target distribution
    """
    weight = q ** 2 / q.sum(0)
    return (weight.T / weight.sum(1)).T


@classmethod
def instance(cls, *args, **kwargs):
    """
        Creates an instance of this class with all *args* and *kwargs*, saves it in
        :py:attr:`_instance`, and returns it. When :py:attr:`_instance` was already set before, no
        new instance is created.
        """
    if cls._instance is None:
        cls._instance = cls(*args, **kwargs)
    return cls._instance


@staticmethod
def _recSortKey(r):
    """
        Sort order for Features, by genomic coordinate,
        disambiguated by feature type (alphabetically).
        """
    return r.seqname, r.start, -r.end, r.type


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 join_query_string():
    """Unir parametros en query string"""
    pass


def build_default_endpoint_prefixes(records_rest_endpoints):
    """Build the default_endpoint_prefixes map."""
    pid_types = set()
    guessed = set()
    endpoint_prefixes = {}
    for key, endpoint in records_rest_endpoints.items():
        pid_type = endpoint['pid_type']
        pid_types.add(pid_type)
        is_guessed = key == pid_type
        is_default = endpoint.get('default_endpoint_prefix', False)
        if is_default:
            if pid_type in endpoint_prefixes and pid_type not in guessed:
                raise ValueError('More than one "{0}" defined.'.format(
                    pid_type))
            endpoint_prefixes[pid_type] = key
            guessed -= {pid_type}
        elif is_guessed and pid_type not in endpoint_prefixes:
            endpoint_prefixes[pid_type] = key
            guessed |= {pid_type}
    not_found = pid_types - set(endpoint_prefixes.keys())
    if not_found:
        raise ValueError('No endpoint-prefix for {0}.'.format(', '.join(
            not_found)))
    return endpoint_prefixes


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

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

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


@classmethod
def index(cls, value):
    """Return an index into the Enum given a value."""
    return cls.ALL.index(value)


@classmethod
def from_nds2(cls, nds2channel):
    """Generate a new channel using an existing nds2.channel object
        """
    return cls(nds2channel.name, sample_rate=nds2channel.sample_rate, unit=
        nds2channel.signal_units or None, dtype=nds2channel.data_type, type
        =nds2channel.channel_type)


def enableFaulthandler():
    """ Enable faulthandler for all threads.

    If the faulthandler package is available, this function disables and then
    re-enables fault handling for all threads (this is necessary to ensure any
    new threads are handled correctly), and returns True.

    If faulthandler is not available, then returns False.
    """
    try:
        import faulthandler
        faulthandler.disable()
        faulthandler.enable(all_threads=True)
        return True
    except ImportError:
        return False


@staticmethod
def _is_debug(name, arch):
    """ Return True if a name implies a debug version. """
    if arch == 'linux':
        return name.endswith('.debug')
    if arch == 'macos':
        return name.endswith('_debug.dylib') or name.endswith('.dSYM')
    if arch == 'win':
        return name.endswith('.pdb') or name.endswith('d.dll')


def sum(u, v):
    """Error free transformation of a sum."""
    s = u + v
    up = s - v
    vpp = s - up
    up -= u
    vpp -= v
    t = -(up + vpp)
    return s, t


def show_plugin_install_info():
    """Print the documentation on how to install the ginga plugins."""
    print('See http://stginga.readthedocs.org/en/latest/run.html')


def start_console(transpyler, console='auto', turtle='auto'):
    """
    Starts a regular python console with the current transpyler.

    Args:
        console:
            Can be one of 'jupyter', 'console', 'qtconsole', 'auto'. This
            chooses the default console application. The default behavior
            (auto) is to try jupyter and fallback to console if it is
            not available.
        turtle:
            Sets the turtle backend. It can be either 'qt', 'tk', 'none' or
            'auto'. The defaut strategy (auto) is to try the qt first and
            fallback to tk.
    """
    if console == 'auto':
        try:
            import IPython
        except ImportError:
            console = 'console'
        else:
            console = 'jupyter'
    if console == 'qtconsole':
        from .jupyter import start_jupyter
        start_jupyter(transpyler=transpyler, gui=True)
    elif console == 'jupyter':
        from .jupyter import start_jupyter
        start_jupyter(transpyler=transpyler, gui=False)
    elif console == 'console':
        from .console import start_console
        start_console(transpyler=transpyler)


def data_type_dict():
    """Returns a dictionary from data type string to the data type.

    The dictionary should include at least:
    float16
    float32
    float64
    uint8
    int8
    int16
    int32
    int64

    This function will be called only *once* during the initialization fo the
    backend module. The returned dictionary will become the attributes of the
    backend module.

    Examples
    --------
    >>> import torch as th
    >>> def data_type_dict():
    >>>   return { 'float16' : th.float16, 'float32' : th.float32, ... }

    After the module is initialized.

    >>> import backend as F
    >>> F.float16  # this will point to torch.float16

    Returns
    -------
    dict of str to data type
        The data type dict.
    """
    pass


def __rmul__(A, B):
    """
        * If A TTvec and B scalar -> multiplication by scalar
        """
    return A * B


def noneToDefaultOrValue(value, default=''):
    """Convert a NoneType to a default or pass back the value.

    Parameters
    ----------
    value : anything
        The value to possibly convert.
    default : anything, optional
        The default to return if value is NoneType.

    Returns
    -------
    anything
        The converted value.
    """
    return default if value is None else value


def get_config(argv):
    """
    parse the module arguments and put them in a config dict

    :param argv: array of arguments from the config file
    :return: config dict
    """
    config = {}
    config['url'] = 'https://localhost/validate/simplecheck'
    config['prompt'] = 'Your OTP:'
    config['debug'] = False
    if 'debug' in argv:
        config['debug'] = True
    for arg in argv:
        if arg.startswith('url='):
            config['url'] = arg[len('url='):]
        if arg.startswith('realm='):
            config['realm'] = arg[len('realm='):]
        if arg.startswith('prompt='):
            prompt = arg[len('prompt='):]
            config['prompt'] = prompt.replace('_', ' ')
    return config


def _is_log10(filename):
    """Return True if this result file contains log10 data, False otherwise
    """
    if filename.startswith('f_'):
        return False
    files_in_linear_scale = ['decade_loadings_results.dat']
    if filename in files_in_linear_scale:
        return False
    return True


def _check_1st_line(line, **kwargs):
    """First line check.

    Check that the first line has a known component name followed by a colon
    and then a short description of the commit.

    :param line: first line
    :type line: str
    :param components: list of known component names
    :type line: list
    :param max_first_line: maximum length of the first line
    :type max_first_line: int
    :return: errors as in (code, line number, *args)
    :rtype: list

    """
    components = kwargs.get('components', ())
    max_first_line = kwargs.get('max_first_line', 50)
    errors = []
    lineno = 1
    if len(line) > max_first_line:
        errors.append(('M190', lineno, max_first_line, len(line)))
    if line.endswith('.'):
        errors.append(('M191', lineno))
    if ':' not in line:
        errors.append(('M110', lineno))
    else:
        component, msg = line.split(':', 1)
        if component not in components:
            errors.append(('M111', lineno, component))
    return errors


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

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

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


def gethistory():
    """
    @api {post} /music/search/gethistory 获取搜索记录
    @apiVersion 1.0.0
    @apiGroup Search
    @apiDescription 获取搜索记录

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

    @apiSuccess (Success) {Object} keyword 搜索关键字

    @apiSuccessExample {json} Success-Response:
    {
        "data": [
            {
                "keyword": "经典老歌"
            }
        ]
    }

    """


def storerandcat(z, ra, dec, rweights, rcatname):
    """Create random catalog file to store generated random catalog from randcatprep method"""
    fobj = open(rcatname, 'w')
    fobj.write('z\t ra\t dec\t radial_weight\n ')
    for i in range(0, len(z)):
        fobj.write('%f\t ' % z[i])
        fobj.write('%f\t %f\t %f\n' % (ra[i], dec[i], rweights[i]))
    fobj.close()


@classmethod
def global_config(cls, key, *args):
    """ This reads or sets the global settings stored in class.settings. """
    if args:
        cls.settings = cls.settings.copy()
        cls.settings[key] = args[0]
    else:
        return cls.settings[key]


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

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

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


def sumlogdiag(A=None, name=None, attr=None, out=None, **kwargs):
    """Computes the sum of the logarithms of the diagonal elements of a square matrix.
    Input is a tensor *A* of dimension *n >= 2*.

    If *n=2*, *A* must be square with positive diagonal entries. We sum the natural
    logarithms of the diagonal elements, the result has shape (1,).

    If *n>2*, *sumlogdiag* is performed separately on the trailing two dimensions for all
    inputs (batch mode).

    .. note:: The operator supports float32 and float64 data types only.

    Examples::

       Single matrix reduction
       A = [[1.0, 1.0], [1.0, 7.0]]
       sumlogdiag(A) = [1.9459]

       Batch matrix reduction
       A = [[[1.0, 1.0], [1.0, 7.0]], [[3.0, 0], [0, 17.0]]]
       sumlogdiag(A) = [1.9459, 3.9318]

    Defined in src/operator/tensor/la_op.cc:L445

    Parameters
    ----------
    A : Symbol
        Tensor of square matrices

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

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


def p_raw_dict_chain(t):
    """raw_dict : raw_dict COMMA raw_dict"""
    t[1].update(t[3])
    t[0] = t[1]


def _value_is_in_bounds(value, bounds):
    """Check if a value is within bounds.

    Parameters
    ----------
    value : float or ndarray
        The test value.
    bounds : (lower, upper)
        The lower and upper bounds.

    Returns
    -------
    bool
        ``True`` if the value is within the bounds. Otherwise, ``False``.

    Examples
    --------
    >>> from landlab.grid.raster_funcs import _value_is_in_bounds
    >>> import numpy as np
    >>> _value_is_in_bounds(.5, (0, 1))
    True
    >>> _value_is_in_bounds(1, (0, 1))
    False
    >>> _value_is_in_bounds(0, (0, 1))
    True
    >>> _value_is_in_bounds(np.array((0, 1)), (0, 1))
    array([ True, False], dtype=bool)
    """
    dummy = value >= bounds[0]
    dummy &= value < bounds[1]
    return dummy


def slogdet(A=None, name=None, attr=None, out=None, **kwargs):
    """Compute the sign and log of the determinant of a matrix.
    Input is a tensor *A* of dimension *n >= 2*.

    If *n=2*, *A* is a square matrix. We compute:

      *sign* = *sign(det(A))*
      *logabsdet* = *log(abs(det(A)))*

    If *n>2*, *slogdet* is performed separately on the trailing two dimensions
    for all inputs (batch mode).

    .. note:: The operator supports float32 and float64 data types only.
    .. note:: The gradient is not properly defined on sign, so the gradient of
              it is not backwarded.
    .. note:: No gradient is backwarded when A is non-invertible. Please see
              the docs of operator det for detail.

    Examples::

       Single matrix signed log determinant
       A = [[2., 3.], [1., 4.]]
       sign, logabsdet = slogdet(A)
       sign = [1.]
       logabsdet = [1.609438]

       Batch matrix signed log determinant
       A = [[[2., 3.], [1., 4.]],
            [[1., 2.], [2., 4.]],
            [[1., 2.], [4., 3.]]]
       sign, logabsdet = slogdet(A)
       sign = [1., 0., -1.]
       logabsdet = [1.609438, -inf, 1.609438]

    Defined in src/operator/tensor/la_op.cc:L1031

    Parameters
    ----------
    A : Symbol
        Tensor of square matrix

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

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


@staticmethod
def net_shortwave_radiation(rs, albedo):
    """The net shortwave radiation (:math:`R_{ns}`) *[MJ/m²day]* resulting from the balance between incoming
        and reflected solar radiation as defined in
        `FAO 56 <http://www.fao.org/tempref/SD/Reserved/Agromet/PET/FAO_Irrigation_Drainage_Paper_56.pdf>`_
        (eq. 38, p. 51):

        .. math::

            R_{ns} = (1 − \\alpha) R_s

        :param rs: daily shortwave radiation (:math:`R_s`) *[MJ/m²day]*. See :meth:`shortwave_radiation`
        :type rs: float or np.array
        :param albedo: albedo or reflection coefficient (:math:`\\alpha` *[-]*). Range:
            :math:`0.0  \\leq \\alpha \\leq 1.0` (:math:`\\alpha=0.23` for the hypothetical grass reference crop).
            See :class:`PenmanMonteithDaily` and :meth:`et0`
        :type albedo: float or np.array
        :return: (*float or np.array*) daily net shortwave radiation (:math:`R_{ns}`) *[MJ/m²day]* reaching the earth
        """
    return (1.0 - albedo) * rs


def target_remove():
    """Remove the selected particle target

    """
    pass


def _instance_namespace(instance, dct, name):
    """Return a Namespace associated with the instance, if possible."""
    try:
        return dct.get_namespace(instance, dct.path)
    except TypeError:
        raise AttributeError(name)


def _parse_unit(unit, placement_str):
    """Parse a unit as part of the unit placement.

    Return the unit as an integer or None.
    Raise a ValueError if the unit is specified but it is not a digit.
    """
    if not unit:
        return None
    try:
        return int(unit)
    except (TypeError, ValueError):
        msg = 'unit in placement {} must be digit'.format(placement_str)
        raise ValueError(msg.encode('utf-8'))


@classmethod
def is_macvtap_assigned(cls, ifname, ip_link_show_output):
    """Check if vf has macvtap interface assigned

        Parses the output of ip link show command and checks
        if macvtap[0-9]+@<vf interface> regex matches the
        output.
        @param ifname: vf interface name
        @param ip_link_show_output: 'ip link show' result to parse
        @return: True on match otherwise False
        """
    for line in ip_link_show_output.splitlines():
        pattern_match = cls.MACVTAP_REG_EX.match(line)
        if pattern_match:
            if ifname == pattern_match.group('vf_interface'):
                return True
    return False


def normalized_difference(x, y):
    """
    Normalized difference helper function for computing an index such
    as NDVI.

    Example
    -------
    >>> import descarteslabs.workflows as wf
    >>> col = wf.ImageCollection.from_id("landsat:LC08:01:RT:TOAR",
    ...     start_datetime="2017-01-01",
    ...     end_datetime="2017-05-30")
    >>> nir, red = col.unpack_bands("nir red")
    >>> # geoctx is an arbitrary geocontext for 'col'
    >>> wf.normalized_difference(nir, red).compute(geoctx) # doctest: +SKIP
    ImageCollectionResult of length 2:
      * ndarray: MaskedArray<shape=(2, 1, 512, 512), dtype=float64>
      * properties: 2 items
      * bandinfo: 'nir_sub_red_div_nir_add_red'
      * geocontext: 'geometry', 'key', 'resolution', 'tilesize', ...
    """
    return (x - y) / (x + y)


def eval_elems(lista):
    """Checks the boolean value of the list:
     - if one of them is False returns False
     - else it returns a list with the amount of True's

     :param lista:
     """
    new_list = []
    for l in lista:
        if l is False:
            return False
        elif l is not True:
            new_list.append(l)
    return new_list


def _searchsorted(array, val, side='left'):
    """
    Call np.searchsorted or use a custom binary
    search if necessary.
    """
    if hasattr(array, 'searchsorted'):
        return array.searchsorted(val, side=side)
    begin = 0
    end = len(array)
    while begin < end:
        mid = (begin + end) // 2
        if val > array[mid]:
            begin = mid + 1
        elif val < array[mid]:
            end = mid
        elif side == 'right':
            begin = mid + 1
        else:
            end = mid
    return begin


def addSub(sub):
    """Add a new sub-registry to the node.

        .. caution:: This method should *not* be used manually. It is
            automatically called by `setNext`. To add a new registry to the
            tree, use ``sub.setNext(self, self.base)`` instead!
        """


def p_default_declaration_(t):
    """default_declaration : DEFAULT COLON declaration SEMI"""
    t[0] = [t[3]]


def _monkeypatch_copy(source, destination):
    """
    Mutates the destination object to behave like the source object.
    """
    for attr_name in dir(destination):
        if not hasattr(source, attr_name):
            delattr(destination, attr_name)
    for attr_name in dir(source):
        attr = getattr(source, attr_name)
        try:
            setattr(destination, attr_name, attr)
        except AttributeError:
            continue


def select_software(baseos, minN=10, maxN=50):
    """select software will select a random set of software
    to install based on a particular os.
    """
    print('Vanessa needs to write me!')


def requirements_consistency(setup, txt='requirements.txt', conda_recipe=None):
    """
    Checks that the requirements defined in setup.py, requirements.txt, and
    (optionally) the conda recipe's meta.yaml file are all in agreement.
    Includes version checks (for pins) on requirements.txt and the conda
    recipe.
    """
    pass


def vertex_group_assign():
    """Assign the selected vertices to the active vertex group

    """
    pass


def map_transaction(txn):
    """
    Maps a single transaction row to a dictionary.

    Parameters
    ----------
    txn : pd.DataFrame
        A single transaction object to convert to a dictionary.

    Returns
    -------
    dict
        Mapped transaction.
    """
    if isinstance(txn['sid'], dict):
        sid = txn['sid']['sid']
        symbol = txn['sid']['symbol']
    else:
        sid = txn['sid']
        symbol = txn['sid']
    return {'sid': sid, 'symbol': symbol, 'price': txn['price'], 'order_id':
        txn['order_id'], 'amount': txn['amount'], 'commission': txn[
        'commission'], 'dt': txn['dt']}


def _allowed_file(filename):
    """Return True if file extension is allowed, False otherwise."""
    extensions = ['csv', 'xls', 'xlsx']
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in extensions


def remove_duplicates(l):
    """
    Function to remove duplicates items from a
    list
    l: a list of string
    Returns a list
    """
    return list(set(l))


def roessler(r, tree='beech'):
    """Estimate bark thickness

    Returns the estimated bark thickness as published by Rössler (2008)

    Parameters
    ----------
    r : float
        tree radius at breast height (in cm)
    tree : str
        Tree name, for which to calculate bark thickness.
        Can be one of ['beech', 'oak']

    Returns
    -------
    db : float
        bark thickness (in mm)

    Raises
    ------
    NotImplementedError : if tree is not in ('oak', 'beech')

    References
    ----------
    Rössler, G.: Rindenabzug richtig bemessen, Forstzeitung, 4, p. 21, 2008.
    """
    if tree == 'beech':
        db = 2.61029 + 0.28522 * 2 * r
    elif tree == 'oak':
        db = 9.88855 + 0.56734 * 2 * r
    else:
        raise NotImplementedError("Only 'beech' and 'oak' supported.")
    return db / 10


@classmethod
def runtime(cls):
    """Return GDALVersion of current GDAL runtime"""
    from rasterio._base import gdal_version
    return cls.parse(gdal_version())


@staticmethod
def load_from_function(function, path_to_file, **kwargs):
    """Load a file according to a given function

        Parameters
        ----------
        function: func
            callable function that will load in your file
        path_to_file: str
            path to the file that you wish to load
        kwargs: dict
            all kwargs are passed to the function
        """
    return function(path_to_file, **kwargs)


def _get_windowed_dataframe(time_series, segments, window_start, window_end):
    """For each segment, return a dataframe with the time relative to
    the start of the segment + window_offset.
    """
    for segment_start, segment_end in segments:
        if window_end is not None:
            segment_end = segment_start + window_end
        time_series_segment = time_series.loc[segment_start + window_start:
            segment_end, :]
        new_time = time_series_segment.index - segment_start
        yield time_series_segment.set_index(new_time)


def _wind_height_adjust(uz, zw):
    """Wind speed at 2 m height based on full logarithmic profile (Eq. 33)

    Parameters
    ----------
    uz : ee.Image or ee.Number
        Wind speed at measurement height [m s-1].
    zw : ee.Image or ee.Number
        Wind measurement height [m].

    Returns
    -------
    ee.Image or ee.Number
        Wind speed at 2 m height [m s-1].

    Notes
    -----
    u2 = uz * 4.87 / log(67.8 * zw - 5.42)

    """
    return uz.multiply(4.87).divide(zw.multiply(67.8).subtract(5.42).log())


def add_lists(*args):
    """
    Append lists. This is trivial but it's here for symmetry with add_dicts
    """
    out = []
    for arg in args:
        out.extend(arg)
    return out


@staticmethod
def storeDB(conn, urls):
    """Overwrite the URLs in the table with the specified URLs (string) in the database."""
    c = conn.cursor()
    vals = []
    for url in urls:
        vals.append((url,))
    c.execute('delete from url')
    c.executemany('insert into url(url) values (?)', iter(vals))
    c.close()


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


def getDestination():
    """
        Return destination this will try to connect to.

        @return: An object which provides L{IAddress}.
        """


def loop_to_region(select_bigger: bool=False):
    """Select region of faces inside of a selected loop of edges

    :param select_bigger: Select Bigger, Select bigger regions instead of smaller ones
    :type select_bigger: bool
    """
    pass


def pformat(obj, verbose=False):
    """Prettyprint an object.  Either use the `pretty` library or the
    builtin `pprint`.
    """
    try:
        from pretty import pretty
        return pretty(obj, verbose=verbose)
    except ImportError:
        from pprint import pformat
        return pformat(obj)


def p_PRIMARY_KEY(p):
    """opt_column_def_options : PRIMARY KEY"""
    p[0] = {'primary': True}


def create_label_groups(groups):
    """Create info dictionaries for label groups."""
    group_dicts = []
    if groups:
        for item in groups:
            dic = {}
            if len(item) == 1:
                dic['label'] = item[0]
                dic['name'] = item[0]
            elif len(item) == 2:
                dic['label'] = item[0]
                dic['name'] = item[1]
            else:
                raise ValueError('Label group takes 1 or 2 arguments')
            group_dicts.append(dic)
    return group_dicts


@classmethod
def from_required_key(cls, key, cls_ref):
    """
        Run time error. A required key was absent in data.
        """
    return cls("%s: Key '%s' required in data." % (cls_ref.__name__, key))


@staticmethod
def equals(A, B):
    """
        Test if matrices A and B are identical.
        """
    if A.data.shape[0] != B.data.shape[0]:
        return False
    if (A.data != B.data).any():
        return False
    if hasattr(A, 'indices') and hasattr(B, 'indices') and (A.indices != B.
        indices).any():
        return False
    if hasattr(A, 'rows') and hasattr(B, 'rows') and (A.rows != B.rows).any():
        return False
    return True


def _character_matches(name1, name2):
    """Yield the number of characters that match the beginning of each string.
    """
    if name1[0] == '*':
        for i in range(len(name2) + 1):
            yield 1, i
    if name2[0] == '*':
        for i in range(len(name1) + 1):
            yield i, 1
    if name1[0] == name2[0]:
        yield 1, 1


def area_options():
    """Operations for splitting and merging

    """
    pass


def getBuilds():
    """Return a list of IBuildStatus objects for each Build that has been
        started in an attempt to satisfy this BuildRequest."""


def _apply_over_vars_with_dim(func, self, dim=None, **kwargs):
    """Wrapper for datasets
    """
    ds = type(self)(coords=self.coords, attrs=self.attrs)
    for name, var in self.data_vars.items():
        if dim in var.dims:
            ds[name] = func(var, dim=dim, **kwargs)
        else:
            ds[name] = var
    return ds


def NE(x=None, y=None):
    """
    Compares two values and returns:
        true when the values are not equivalent.
        false when the values are equivalent.
    See https://docs.mongodb.com/manual/reference/operator/aggregation/ne/
    for more details
    :param x: first value or expression
    :param y: second value or expression
    :return: Aggregation operator
    """
    if x is None and y is None:
        return {'$ne': []}
    return {'$ne': [x, y]}


@staticmethod
def defaultBotModError():
    """The default function that gives an error when a Discord Member is trying to run a Bot Moderator command
        without having the proper permissions.
        """
    return 'You do not have the proper permissions to run this command.'


@classmethod
def name(cls):
    """Return a short name for displaying in the status bar"""
    return str(cls)


def label_gen(index):
    """Generates label set for individual gaussian
        index = index of peak location

        output string format:
        'a' + index + "_" + parameter"""
    assert isinstance(index, (float, int))
    pref = str(int(index))
    comb = 'a' + pref + '_'
    cent = 'center'
    sig = 'sigma'
    amp = 'amplitude'
    fract = 'fraction'
    center = comb + cent
    sigma = comb + sig
    amplitude = comb + amp
    fraction = comb + fract
    assert isinstance((center, sigma, amplitude, fraction, comb), str)
    return center, sigma, amplitude, fraction, comb


@classmethod
def shortname(cls, sCanonical):
    """Translate a canonical name into a short name.
           """
    raise NotImplementedError


def verbose(value=1):
    """
    Set verbose level

    :param value: verbose level (default = 1)
    """
    global verbose_level
    verbose_level = value


def remove_node_rescue_password(node, save=True):
    """Helper to remove rescue password from a node.

    Removes rescue password from node. It saves node by default.
    If node should not be saved, then caller needs to explicitly
    indicate it.

    :param node: an Ironic node object.
    :param save: Boolean; True (default) to save the node; False
                 otherwise.
    """
    instance_info = node.instance_info
    if 'rescue_password' in instance_info:
        del instance_info['rescue_password']
    if 'hashed_rescue_password' in instance_info:
        del instance_info['hashed_rescue_password']
    node.instance_info = instance_info
    if save:
        node.save()


@classmethod
def from_MPOModel(cls, mpo_model):
    """Initialize a NearestNeighborModel from a model class defining an MPO.

        This is especially usefull in combination with :meth:`MPOModel.group_sites`.

        Parameters
        ----------
        mpo_model : :class:`MPOModel`
            A model instance implementing the MPO.
            Does not need to be a :class:`NearestNeighborModel`, but should only have
            nearest-neighbor couplings.

        Examples
        --------
        The `SpinChainNNN2` has next-nearest-neighbor couplings and thus only implements an MPO:

        >>> from tenpy.models.spins_nnn import SpinChainNNN2
        >>> nnn_chain = SpinChainNNN2({'L': 20})
        parameter 'L'=20 for SpinChainNNN2
        >>> print(isinstance(nnn_chain, NearestNeighborModel))
        False
        >>> print("range before grouping:", nnn_chain.H_MPO.max_range)
        range before grouping: 2

        By grouping each two neighboring sites, we can bring it down to nearest neighbors.

        >>> nnn_chain.group_sites(2)
        >>> print("range after grouping:", nnn_chain.H_MPO.max_range)
        range after grouping: 1

        Yet, TEBD will not yet work, as the model doesn't define `H_bond`.
        However, we can initialize a NearestNeighborModel from the MPO:

        >>> nnn_chain_for_tebd = NearestNeighborModel.from_MPOModel(nnn_chain)
        """
    return cls(mpo_model.lat, mpo_model.calc_H_bond_from_MPO())


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

        :param TeamLogInfo val:
        :rtype: ContextLogInfo
        """
    return cls('organization_team', val)


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

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

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


def attach_network_interface(DryRun=None, NetworkInterfaceId=None,
    InstanceId=None, DeviceIndex=None):
    """
    Attaches a network interface to an instance.
    See also: AWS API Documentation

    Examples
    This example attaches the specified network interface to the specified instance.
    Expected Output:

    :example: response = client.attach_network_interface(
        DryRun=True|False,
        NetworkInterfaceId='string',
        InstanceId='string',
        DeviceIndex=123
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type NetworkInterfaceId: string
    :param NetworkInterfaceId: [REQUIRED]
            The ID of the network interface.

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

    :type DeviceIndex: integer
    :param DeviceIndex: [REQUIRED]
            The index of the device for the network interface attachment.

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

    """
    pass


def match_automaton(string, automaton, boundary_check=None):
    """
    See if can match string to string matching automaton.
    This is aided by a boundary check callable which helps ascertain
    whether the matched substring occurs within some boundaries (e.g. token boundaries).

    """
    for end_position, (length, *tail) in automaton.iter(string):
        end_idx = end_position + 1
        start_idx = end_idx - length
        if boundary_check and not boundary_check(string, start_idx, end_idx):
            continue
        return True
    return False


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

        :param SharedLinkSettingsChangePasswordDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_settings_change_password_details', val)


@classmethod
def pre_command(cls):
    """
        Runs a function before a command is triggered.
        """
    return cls.add_meta_deco({'type': 'pre_command'})


def examplefn(vec):
    """
    example function that will be applied across CSV chunks
    :param vec: a row of a data frame, used inside a pandas.apply(function, axis = 1)
    """
    vec[0] = vec[0] + 1000
    return vec


def polygon_from_x0y0x1y1(x0y0x1y1):
    """Construct polygon coordinates in numeric list representation from a string list representing a bounding box."""
    minx = int(x0y0x1y1[0])
    miny = int(x0y0x1y1[1])
    maxx = int(x0y0x1y1[2])
    maxy = int(x0y0x1y1[3])
    return [[minx, miny], [maxx, miny], [maxx, maxy], [minx, maxy]]


def ascii_encode(obj):
    """
  Encodes a string using ASCII encoding.

  :param obj:
      String to encode.
  :returns:
      ASCII-encoded bytes.
  """
    return obj.encode('ascii')


def basis_function_one(degree, knot_vector, span, knot):
    """ Computes the value of a basis function for a single parameter.

    Implementation of Algorithm 2.4 from The NURBS Book by Piegl & Tiller.

    :param degree: degree, :math:`p`
    :type degree: int
    :param knot_vector: knot vector
    :type knot_vector: list, tuple
    :param span: knot span, :math:`i`
    :type span: int
    :param knot: knot or parameter, :math:`u`
    :type knot: float
    :return: basis function, :math:`N_{i,p}`
    :rtype: float
    """
    if span == 0 and knot == knot_vector[0] or span == len(knot_vector
        ) - degree - 2 and knot == knot_vector[len(knot_vector) - 1]:
        return 1.0
    if knot < knot_vector[span] or knot >= knot_vector[span + degree + 1]:
        return 0.0
    N = [(0.0) for _ in range(degree + span + 1)]
    for j in range(0, degree + 1):
        if knot_vector[span + j] <= knot < knot_vector[span + j + 1]:
            N[j] = 1.0
    for k in range(1, degree + 1):
        saved = 0.0
        if N[0] != 0.0:
            saved = (knot - knot_vector[span]) * N[0] / (knot_vector[span +
                k] - knot_vector[span])
        for j in range(0, degree - k + 1):
            Uleft = knot_vector[span + j + 1]
            Uright = knot_vector[span + j + k + 1]
            if N[j + 1] == 0.0:
                N[j] = saved
                saved = 0.0
            else:
                temp = N[j + 1] / (Uright - Uleft)
                N[j] = saved + (Uright - knot) * temp
                saved = (knot - Uleft) * temp
    return N[0]


def resolve_tuple(value, default=None):
    """Resolve tuple (convert provided value if not tuple).

    :param value: Value
    :type value: any

    :param default: Default tuple function
    :type default: function
    """
    if value is None:
        return tuple()
    if default is None:
        default = lambda v: (v,)
    if not isinstance(value, tuple):
        return default(value)
    return value


def humantime(seconds, ndigits=2, one_hour_digit=False):
    """Format a duration as a human readable string.

    The duration in seconds (a nonnegative float) is formatted as
    ``HH:MM:SS.frac``, where the number of fractional digits is
    controlled by `ndigits`; if `ndigits` is 0, the decimal point is not
    printed. The number of hour digits (``HH``) can be reduced to one
    with the `one_hour_digits` option.

    Parameters
    ----------
    seconds : float
        Duration in seconds, must be nonnegative.
    ndigits : int, optional
        Number of digits after the decimal point for the seconds part.
        Default is 2. If 0, the decimal point is suppressed.
    one_hour_digit : bool, optional
        If ``True``, only print one hour digit (e.g., nine hours is
        printed as 9:00:00.00). Default is ``False``, i.e., two hour
        digits (nine hours is printed as 09:00:00.00).

    Returns
    -------
    human_readable_duration : str

    Raises
    ------
    ValueError:
        If `seconds` is negative.

    Examples
    --------
    >>> humantime(10.55)
    '00:00:10.55'
    >>> humantime(10.55, ndigits=1)
    '00:00:10.6'
    >>> humantime(10.55, ndigits=0)
    '00:00:11'
    >>> humantime(10.55, one_hour_digit=True)
    '0:00:10.55'
    >>> # two hours digits for >= 10 hours, even if one_hour_digit is
    >>> # set to True
    >>> humantime(86400, one_hour_digit=True)
    '24:00:00.00'
    >>> humantime(-1)
    Traceback (most recent call last):
        ...
    ValueError: seconds=-1.000000 is negative, expected nonnegative value

    """
    if seconds < 0:
        raise ValueError(
            'seconds=%f is negative, expected nonnegative value' % seconds)
    hh = int(seconds) // 3600
    mm = int(seconds) // 60 % 60
    ss = seconds - int(seconds) // 60 * 60
    hh_str = '%01d' % hh if one_hour_digit else '%02d' % hh
    mm_str = '%02d' % mm
    if ndigits == 0:
        ss_str = '%02d' % round(ss)
    else:
        ss_format = '%0{0}.{1}f'.format(ndigits + 3, ndigits)
        ss_str = ss_format % ss
    return '%s:%s:%s' % (hh_str, mm_str, ss_str)


def ref(series, n):
    """
    简单移动: 求series序列位移n个周期的结果

        注意: 当n为0, 函数返回原序列; 当n为有效值但当前的series序列元素个数不足 n + 1 个, 函数返回 NaN 序列

    Args:
        series (pandas.Series): 数据序列

        n (int): 位移周期

    Returns:
        pandas.Series: 位移后的序列

    Example::

        from tqsdk import TqApi, TqSim, tafunc

        api = TqApi(TqSim())
        klines = api.get_kline_serial("CFFEX.IF1908", 24 * 60 * 60)
        pre_close = tafunc.ref(klines.close, 1)  # 将收盘价序列右移一位, 得到昨收盘序列
        change = klines.close - pre_close        # 收盘价序列 - 昨收盘序列, 得到涨跌序列
        print(list(change))
    """
    m = series.shift(n)
    return m


def encode_id_unit(legrandid: str, unit: str) ->str:
    """Encode the input legrand_id and unit."""
    legrandid = hex(int(legrandid))
    return int(legrandid + unit, 0)


@staticmethod
def log_issue(failure, logger=None):
    """
        Nicely log issue and possibly its URL.

        :param gluetool.glue.Failure failure: ``Failure`` instance describing the exception.
        :param gluetool.log.ContextAdapter logger: logger to use for logging.
        """
    if not logger or not failure:
        return
    logger.error("Submitted as Sentry issue '{}'".format(failure.
        sentry_event_id))
    if failure.sentry_event_url:
        logger.error('See {} for details.'.format(failure.sentry_event_url))


def arange(start, stop):
    """Create a 1D range int64 tensor.

    Parameters
    ----------
    start : int
        The range start.
    stop : int
        The range stop.

    Returns
    -------
    Tensor
        The result tensor.
    """
    pass


@classmethod
def from_json_if_need(cls, config_name: str, filename: str='config.json'):
    """
        Создать экземпляр только если он ещё не существует
        """
    if cls.has_instance():
        return cls.get_instance()
    return cls.from_json(config_name, filename)


def spin(steps: int=9, dupli: bool=False, angle: float=1.5708, center:
    float=(0.0, 0.0, 0.0), axis: float=(0.0, 0.0, 0.0)):
    """Extrude selected vertices in a circle around the cursor in indicated viewport

    :param steps: Steps, Steps
    :type steps: int
    :param dupli: Dupli, Make Duplicates
    :type dupli: bool
    :param angle: Angle, Rotation for each step
    :type angle: float
    :param center: Center, Center in global view space
    :type center: float
    :param axis: Axis, Axis in global view space
    :type axis: float
    """
    pass


def add_mail(app):
    """ Add mailing functionality """
    from boiler.feature.mail import mail_feature
    mail_feature(app)


def get_col_type(me, xid):
    """get_col_type with transparent index mapping."""
    xid = me._colmap.map(xid) if xid else xid
    if xid > 0:
        return me._get_col_type(xid)


def socket_set_hwm(socket, hwm=-1):
    """libzmq 2/3/4 compatible sethwm"""
    try:
        socket.sndhwm = socket.rcvhwm = hwm
    except AttributeError:
        socket.hwm = hwm


def oct2int(number):
    """Convert 3 numbers to be able to chmod.

    Given a (string or int) representation of a file mode, such as "777"
    -- you have to realize that is actually an octal number --,
    returns the corresponding integer to be able to chmod.
    """
    return eval('0o' + str(number))


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


def fixedToFloat(value, precisionBits):
    """Converts a fixed-point number to a float given the number of
	precisionBits.  Ie. value / (1 << precisionBits)

	>>> import math
	>>> f = fixedToFloat(-10139, precisionBits=14)
	>>> math.isclose(f, -0.61883544921875)
	True
	"""
    return value / (1 << precisionBits)


def unquote_header_value(value, is_filename=False):
    """Unquotes a header value.  (Reversal of :func:`quote_header_value`).
    This does not use the real unquoting but what browsers are actually
    using for quoting.

    :param value: the header value to unquote.
    :rtype: str
    """
    if value and value[0] == value[-1] == '"':
        value = value[1:-1]
        if not is_filename or value[:2] != '\\\\':
            return value.replace('\\\\', '\\').replace('\\"', '"')
    return value


@classmethod
def from_garlic(cls, garlic_value):
    """
        Instantiate a config model and load it using the given GarlicValue.
        """
    return cls.from_dict(garlic_value.py_value())


@classmethod
def parse(cls, s):
    """
        Convert a string to a unit object.
        """
    raise NotImplementedError(f'Can not parse {cls.__name__}')


def stringify_tag(package, tag):
    """Write the appropriate string for a tag of a package"""
    return '{}.{}'.format(package, tag)


def InverseHough(rhotheta, halfsemiaxes=(1.2, 0.6), centerofproj=(0.0, 0.0)):
    """ from rho and theta in hough space
    gives extreme points of a straight line where must lie all spots
    belonging to the same zone axis
    In a rigourous manner, we must find the intersection of the straight line with an ellipse.
    Here, we consider simply a rectangle!
    """
    pass


def pretty_file_size(size, use_decimal=False, **kwargs):
    """
    Return a human readable representation of the provided ``size``.

    :param size: The size to convert
    :param use_decimal: use decimal instead of binary prefixes (e.g. kilo = 1000 instead of 1024)

    :keyword units: A list of unit names in ascending order.
        Default units: ['B', 'KB', 'MB', 'GB', 'TB', 'PB']

    :return: The converted size
    """
    try:
        size = max(float(size), 0.0)
    except (ValueError, TypeError):
        size = 0.0
    remaining_size = size
    units = kwargs.pop('units', ['B', 'KB', 'MB', 'GB', 'TB', 'PB'])
    block = 1024.0 if not use_decimal else 1000.0
    for unit in units:
        if remaining_size < block:
            return '{0:3.2f} {1}'.format(remaining_size, unit)
        remaining_size /= block
    return size