def trimcase(string):
    """Convert string into trimmed string.
    Args:
        string: String to convert.
    Returns:
        string: Trimmed case string
    """
    return str(string).strip()


def build_type_define(build_type=None):
    """
    returns definitions specific to the build type (Debug, Release, etc.)
    like DEBUG, _DEBUG, NDEBUG
    """
    return 'NDEBUG' if build_type == 'Release' else ''


def add_feather_vertex_slide(MASK_OT_add_feather_vertex=None,
    MASK_OT_slide_point=None):
    """Add new vertex to feather and slide it

    :param MASK_OT_add_feather_vertex: Add Feather Vertex, Add vertex to feather
    :param MASK_OT_slide_point: Slide Point, Slide control points
    """
    pass


def create(client, user_id, group_id):
    """Create security credentials."""
    credentials = client.user.credentials(method='PUT', userId=user_id,
        groupId=group_id)
    return credentials


def __invert__(cls):
    """Obtain base class for namespace"""
    return getattr(cls, '.base')


@staticmethod
def has_battery():
    """Return whether the device has a battery."""
    return False


def start_support_data_export(dataSetType=None, fromDate=None, roleNameArn=
    None, destinationS3BucketName=None, destinationS3Prefix=None,
    snsTopicArn=None, customerDefinedValues=None):
    """
    Given a data set type and a from date, asynchronously publishes the requested customer support data to the specified S3 bucket and notifies the specified SNS topic once the data is available. Returns a unique request identifier that can be used to correlate requests with notifications from the SNS topic. Data sets will be published in comma-separated values (CSV) format with the file name {data_set_type}_YYYY-MM-DD'T'HH-mm-ss'Z'.csv. If a file with the same name already exists (e.g. if the same data set is requested twice), the original file will be overwritten by the new file. Requires a Role with an attached permissions policy providing Allow permissions for the following actions: s3:PutObject, s3:GetBucketLocation, sns:GetTopicAttributes, sns:Publish, iam:GetRolePolicy.
    See also: AWS API Documentation

    :example: response = client.start_support_data_export(
        dataSetType='customer_support_contacts_data'|'test_customer_support_contacts_data',
        fromDate=datetime(2015, 1, 1),
        roleNameArn='string',
        destinationS3BucketName='string',
        destinationS3Prefix='string',
        snsTopicArn='string',
        customerDefinedValues={
            'string': 'string'
        }
    )

    :type dataSetType: string
    :param dataSetType: [REQUIRED]
            Specifies the data set type to be written to the output csv file. The data set types customer_support_contacts_data and test_customer_support_contacts_data both result in a csv file containing the following fields: Product Id, Product Code, Customer Guid, Subscription Guid, Subscription Start Date, Organization, AWS Account Id, Given Name, Surname, Telephone Number, Email, Title, Country Code, ZIP Code, Operation Type, and Operation Time.
            customer_support_contacts_data Customer support contact data. The data set will contain all changes (Creates, Updates, and Deletes) to customer support contact data from the date specified in the from_date parameter.
            test_customer_support_contacts_data An example data set containing static test data in the same format as customer_support_contacts_data

    :type fromDate: datetime
    :param fromDate: [REQUIRED] The start date from which to retrieve the data set in UTC. This parameter only affects the customer_support_contacts_data data set type.

    :type roleNameArn: string
    :param roleNameArn: [REQUIRED] The Amazon Resource Name (ARN) of the Role with an attached permissions policy to interact with the provided AWS services.

    :type destinationS3BucketName: string
    :param destinationS3BucketName: [REQUIRED] The name (friendly name, not ARN) of the destination S3 bucket.

    :type destinationS3Prefix: string
    :param destinationS3Prefix: (Optional) The desired S3 prefix for the published data set, similar to a directory path in standard file systems. For example, if given the bucket name 'mybucket' and the prefix 'myprefix/mydatasets', the output file 'outputfile' would be published to 's3://mybucket/myprefix/mydatasets/outputfile'. If the prefix directory structure does not exist, it will be created. If no prefix is provided, the data set will be published to the S3 bucket root.

    :type snsTopicArn: string
    :param snsTopicArn: [REQUIRED] Amazon Resource Name (ARN) for the SNS Topic that will be notified when the data set has been published or if an error has occurred.

    :type customerDefinedValues: dict
    :param customerDefinedValues: (Optional) Key-value pairs which will be returned, unmodified, in the Amazon SNS notification message and the data set metadata file.
            (string) --
            (string) --

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

    :returns:
    (dict) -- Container for the result of the StartSupportDataExport operation.
    dataSetRequestId (string) -- A unique identifier representing a specific request to the StartSupportDataExport operation. This identifier can be used to correlate a request with notifications from the SNS topic.

    """
    pass


def pbar(obj, **tqdm_kw):
    """Empty progress bar."""
    return obj


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 homogeneous_to_cartesian_vectors(homogeneous_vector):
    """Converts a cartesian vector to an homogenous vector"""
    return homogeneous_vector[:-1]


def bone_layers(layers: bool=(False, False, False, False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False, False, False, False)):
    """Change the layers that the selected bones belong to

    :param layers: Layer, Armature layers that bone belongs to
    :type layers: bool
    """
    pass


def convert_h2(element, text):
    """
    Adds '-' to the bottom of the text
    """
    if text:
        text = text + '\n' + '-' * len(text)
    return text


@staticmethod
def switch_from_assisted():
    """Method to switch to Assisted from BYOC or BYOJ mode."""
    pass


def current_gesture() ->str:
    """Return the name of the current gesture.

    .. note::

        MicroPython understands the following gesture names: ``"up"``, ``"down"``,
        ``"left"``, ``"right"``, ``"face up"``, ``"face down"``, ``"freefall"``,
        ``"3g"``, ``"6g"``, ``"8g"``, ``"shake"``. Gestures are always
        represented as strings."""


def charge_evq(energy, voltage):
    """Usage: charge_evq(energy,voltage)"""
    return energy / voltage


def feature_collection(data, lat_field='latitude', lon_field='longitude',
    spatial_ref=4326):
    """
    Assemble an ArcREST featureCollection object
    spec: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Feature_object/02r3000000n8000000/
    """
    features = []
    for record in data:
        new_record = {'attributes': {}, 'geometry': {'spatialReference': {
            'wkid': spatial_ref}}}
        new_record['attributes'] = record
        if record.get('paths'):
            new_record['geometry']['paths'] = record.pop('paths')
        elif record.get(lat_field) and record.get(lon_field):
            new_record['geometry']['x'] = record.get(lon_field)
            new_record['geometry']['y'] = record.get(lat_field)
        else:
            new_record.pop('geometry')
        features.append(new_record)
    return features


@classmethod
def lines(cls, column_headers, lines, padding, alignment):
    """
        Yield lines to be printed.

        :param column_headers: column headers
        :type column_headers: list of str
        :param lines: line infos
        :type lines: list of dict
        :param int padding: number of spaces to pad on right
        :param alignment: alignment for column headers
        :type alignment: dict of str * str {'<', '>', '^'}
        """
    column_widths = cls.calculate_widths(column_headers, lines, padding)
    yield cls.header_str(column_widths, column_headers, alignment)
    fmt_str = cls.format_str(column_widths, column_headers, alignment)
    for line in lines:
        yield fmt_str.format(**line)


def apply_shot_selection(lists, stacks, min_chunk=None, reset_shot_index=True):
    """
    Applies the selection of shots as defined by the 'selected' column of the shot list, returning corresponding
    subsets of both lists (pandas DataFrames) and stacks (dask arrays).
    :param lists: flat dict of lists. Does not handle subsets, so use flat=True when reading from file
    :param stacks: dict of arrays. Again, not accounting for subsets. Use flat=True for reading
    :param min_chunk: minimum chunk size of the output arrays along the stacked dimension
    :param reset_shot_index: if True, the returned shot list has its index reset, with correspondingly updated serial
            numbers in peak list. Recommended.
    :return new_lists, new_stacks: subselected lists and stacks
    """
    shots = lists['shots']
    new_lists = lists.copy()
    new_lists['shots'] = lists['shots'].query('selected').copy()
    print('Keeping {} shots out of {}'.format(len(new_lists['shots']), len(
        shots)))
    if 'peaks' in lists.keys():
        peaksel = lists['peaks'].merge(shots[['selected']], left_on=
            'serial', right_index=True)['selected']
        new_lists['peaks'] = lists['peaks'].loc[(peaksel), :]
        if reset_shot_index:
            new_lists['shots']['newEv'] = range(len(new_lists['shots']))
            new_lists['peaks'] = new_lists['peaks'].merge(new_lists['shots'
                ].loc[:, (['newEv'])], left_on='serial', right_index=True)
            new_lists['peaks']['serial'] = new_lists['peaks']['newEv']
            new_lists['peaks'].drop('newEv', axis=1, inplace=True)
            new_lists['shots'].drop('newEv', axis=1, inplace=True)
    if reset_shot_index:
        new_lists['shots'].reset_index(drop=True, inplace=True)
    new_stacks = {}
    for k, stk in stacks.items():
        stack = stk[shots['selected'].values, ...]
        if min_chunk is not None:
            nchk = 0
            fchks = []
            for ii, chk in enumerate(stack.chunks[0]):
                nchk += chk
                if nchk >= min_chunk:
                    fchks.append(nchk)
                    nchk = 0
                elif ii == len(stack.chunks[0]) - 1:
                    fchks[-1] += nchk
            stack = stack.rechunk({(0): tuple(fchks)})
        new_stacks.update({k: stack})
    return new_lists, new_stacks


def psi_Ca_Mg_Cl_HMW84(T, P):
    """c-c'-a: calcium magnesium chloride [HMW84]."""
    psi = -0.012
    valid = T == 298.15
    return psi, valid


@classmethod
def from_file(cls, filename, *, strict=True):
    """ Create a new Config object from a configuration file.

        Args:
            filename (str): The location and name of the configuration file.
            strict (bool): If true raises a ConfigLoadError when the configuration
                cannot be found.

        Returns:
            An instance of the Config class.

        Raises:
            ConfigLoadError: If the configuration cannot be found.
        """
    config = cls()
    config.load_from_file(filename, strict=strict)
    return config


def literal_unicode_representer(dumper, data):
    """
    Use |- literal syntax for long strings
    """
    if '\n' in data:
        return dumper.represent_scalar(u'tag:yaml.org,2002:str', data,
            style='|')
    else:
        return dumper.represent_scalar(u'tag:yaml.org,2002:str', data)


def append_defined_component(component, node):
    """
    Function for append components defined by user from graph metadata.
    :param component: component list
    :param node: node name
    :return: list specific components for specific node
    """
    if isinstance(component[node], list):
        return component[node]
    else:
        return [component[node]]


def to_cmd_param(variable: str) ->str:
    """
        Convert a variable in a command parameter format
    """
    return variable.replace('_', '-')


def basicAuth(realm):
    """Challengenes the client for a Basic authentication."""
    assert '"' not in realm, 'Realms cannot contain the " (quote) character.'
    return 'Basic realm="%s"' % realm


def sb_print(sandbox, message):
    """
    convenience printing method for printing to reservation output
    :param Sandbox sandbox:
    :param str message:
    :return:
    """
    sandbox.automation_api.WriteMessageToReservationOutput(sandbox.id, message)


def caller_locals():
    """Get the local variables in the caller's frame."""
    import inspect
    frame = inspect.currentframe()
    try:
        return frame.f_back.f_back.f_locals
    finally:
        del frame


def mpi_alloc_dmem(mpi_pool=None, **kwargs):
    """ List of keyworded arguments to be allocated in the distributed memory.

    This executes only if an mpi_pool is provided.

    Args:
      mpi_pool (:class:`mpi_map.MPI_Pool<mpi_map.MPI_Pool>`): pool of processors
    """
    if mpi_pool is not None:
        mpi_pool.alloc_dmem(**kwargs)


def try_encode(string, enc):
    """turn unicode encoding into a functional routine"""
    try:
        return string.encode(enc)
    except UnicodeEncodeError:
        return None


def float_check(value, default=None):
    """value must be a float or default."""
    try:
        return float(value)
    except ValueError:
        return default


def print_non_None(value):
    """
    Default formatter for values returned by functions decorated with Commands.
    """
    if value is not None:
        print(value)


def linewithpeaks(data, peaks):
    """
    plots line with overlaid peaks
    """
    from pylab import plot, show
    import numpy as np
    plot(data)
    for i in peaks:
        plot([i, i], [np.min(data), np.max(data)])
    show()


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 get_layer_spdxref(layer_obj):
    """Given the layer object, return an SPDX reference ID"""
    return 'SPDXRef-{}'.format(layer_obj.diff_id[:10])


def _voxel_brain(data, lut, vmin, vmax):
    """Plot spheres for volume source space

    Parameters
    ----------
    data : NDVar
        Data to plot.
    lut : array
        Color LUT.
    vmin, vmax : scalar
        Data range.
    """
    if data.dimnames != ('source',):
        raise ValueError('Can only plot 1 dimensional source space NDVars')
    from mayavi import mlab
    x, y, z = data.source.coordinates.T
    figure = mlab.figure()
    mlab.points3d(x, y, z, scale_factor=0.002, opacity=0.5)
    pts = mlab.points3d(x, y, z, data.x, vmin=vmin, vmax=vmax)
    pts.module_manager.scalar_lut_manager.lut.table = lut
    return figure


def get_web_acl_for_resource(ResourceArn=None):
    """
    Returns the web ACL for the specified resource.
    See also: AWS API Documentation

    :example: response = client.get_web_acl_for_resource(
        ResourceArn='string'
    )

    :type ResourceArn: string
    :param ResourceArn: [REQUIRED]
            The ARN (Amazon Resource Name) of the resource for which to get the web ACL.

    :rtype: dict
    :return: {
        'WebACLSummary': {
            'WebACLId': 'string',
            'Name': 'string'
        }
    }

    """
    pass


@staticmethod
def _format_value_without_quotes(value):
    """
        Formats and replaces values with escape character into value without quotes
        :param value: str
        :return: str
        """
    values = []
    if isinstance(value, list):
        for each in value:
            values.append('{}'.format(each.replace("'", '')))
        value = values
    else:
        value = value.replace("'", '')
    return value


def edition_check(data, conf):
    """
    Tests a content structure against the current configuration object to ensure
    that the editions match. Used so that content generation scripts can
    consistently filter out content from non-matching editions.

    :param dict,object data: A dictionary or object that holds content.

    :param giza.config.main.Configuration conf: A Configuration object.

    :returns: ``True`` if ``data`` does not contain an ``edition`` field or
       attribute of ``data`` matches the value of
       ``conf.project.edition``. ``False`` if the edition does not match
       ``conf.project.edition`` or if ``conf.project.edition`` is the same as
       the project name (i.e. ``conf.project.name``).

    :rtype: Boolean
    """
    if 'edition' in data:
        try:
            local_edition = data.edition
        except AttributeError:
            local_edition = data['edition']
        if conf.project.edition == conf.project.name:
            return True
        if isinstance(local_edition, list):
            return conf.project.edition in local_edition
        else:
            return local_edition == conf.project.edition
    else:
        return True


def _simplify_method_name(method):
    """Simplifies a gRPC method name.

    When gRPC invokes the channel to create a callable, it gives a full
    method name like "/google.pubsub.v1.Publisher/CreateTopic". This
    returns just the name of the method, in this case "CreateTopic".

    Args:
        method (str): The name of the method.

    Returns:
        str: The simplified name of the method.
    """
    return method.rsplit('/', 1).pop()


def load():
    """Load an existing IExtension instance"""


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 natural_key_fields(cls):
    """
        Digest is used as a natural key for UpdateRecords.
        """
    return 'digest',


@classmethod
def single_cell(cls, pattern, cell):
    """Construct a gridded permutation where the cells are all located in a
        single cell."""
    return cls(pattern, [cell for _ in range(len(pattern))])


@staticmethod
def get_workload(storage_group):
    """Get the workload from the storagegroup object.

        :param storage_group: storagegroup -- object
        :returns: workload -- str
        """
    try:
        workload = storage_group['workload']
    except KeyError:
        workload = 'NONE'
    return workload


def clipboard_copy():
    """Copies selected nodes to the clipboard

    """
    pass


def decode_source(source_bytes):
    """Decode bytes representing source code and return the string.
    Universal newline support is used in the decoding.
    """
    import _io
    import tokenize
    source_bytes_readline = _io.BytesIO(source_bytes).readline
    encoding = tokenize.detect_encoding(source_bytes_readline)
    newline_decoder = _io.IncrementalNewlineDecoder(None, True)
    return newline_decoder.decode(source_bytes.decode(encoding[0]))


def _scale_moment(magnitude, in_nm=False):
    """Returns the moment for a given magnitude.
    :param float magnitude:
        Earthquake magnitude
    :param bool in_nm:
        To return the value in newton metres set to true - otherwise in
        dyne-cm
    """
    if in_nm:
        return 10.0 ** (1.5 * magnitude + 9.05)
    else:
        return 10.0 ** (1.5 * magnitude + 16.05)


def get_trim_index(biased_list):
    """Returns the trim index from a ``bool`` list

    Provided with a list of ``bool`` elements (``[False, False, True, True]``),
    this function will assess the index of the list that minimizes the number
    of True elements (biased positions) at the extremities. To do so,
    it will iterate over the boolean list and find an index position where
    there are two consecutive ``False`` elements after a ``True`` element. This
    will be considered as an optimal trim position. For example, in the
    following list::

        [True, True, False, True, True, False, False, False, False, ...]

    The optimal trim index will be the 4th position, since it is the first
    occurrence of a ``True`` element with two False elements after it.

    If the provided ``bool`` list has no ``True`` elements, then the 0 index is
    returned.

    Parameters
    ----------
    biased_list: list
        List of ``bool`` elements, where ``True`` means a biased site.

    Returns
    -------
        x : index position of the biased list for the optimal trim.

    """
    if set(biased_list) == {False}:
        return 0
    for i, val in enumerate(biased_list):
        if val and set(biased_list[i + 1:i + 3]) == {False}:
            return i + 1
    return len(biased_list)


def _to_msec(tm):
    """
    Return the number of milliseconds corresponding to a timedelta object

    :param tm: timedelta
    :type  tm: class datetime.timedelta
    :return: milliseconds
    :rtype: int
    """
    return 1000 * (tm.days * 86400 + tm.seconds) + int(tm.microseconds / 1000.0
        )


def load_grid_tiny():
    """ Load a tiny parameter grid for the GenSVM grid search

    This function returns a parameter grid to use in the GenSVM grid search.
    This grid was obtained by analyzing the experiments done for the GenSVM
    paper and selecting the configurations that achieve accuracy within the
    95th percentile on over 90% of the datasets. It is a good start for a
    parameter search with a reasonably high chance of achieving good
    performance on most datasets.

    Note that this grid is only tested to work well in combination with the
    linear kernel.

    Returns
    -------

    pg : list
        List of 10 parameter configurations that are likely to perform
        reasonably well.

    """
    pg = [{'p': [2.0], 'kappa': [5.0], 'lmd': [pow(2, -16)], 'weights': [
        'unit']}, {'p': [2.0], 'kappa': [5.0], 'lmd': [pow(2, -18)],
        'weights': ['unit']}, {'p': [2.0], 'kappa': [0.5], 'lmd': [pow(2, -
        18)], 'weights': ['unit']}, {'p': [2.0], 'kappa': [5.0], 'lmd': [
        pow(2, -18)], 'weights': ['group']}, {'p': [2.0], 'kappa': [-0.9],
        'lmd': [pow(2, -18)], 'weights': ['unit']}, {'p': [2.0], 'kappa': [
        5.0], 'lmd': [pow(2, -14)], 'weights': ['unit']}, {'p': [2.0],
        'kappa': [0.5], 'lmd': [pow(2, -18)], 'weights': ['group']}, {'p':
        [1.5], 'kappa': [-0.9], 'lmd': [pow(2, -18)], 'weights': ['unit']},
        {'p': [2.0], 'kappa': [0.5], 'lmd': [pow(2, -16)], 'weights': [
        'unit']}, {'p': [2.0], 'kappa': [0.5], 'lmd': [pow(2, -16)],
        'weights': ['group']}]
    return pg


@classmethod
def delete_old(cls):
    """
        Deletes old events.
        """
    cls.objects.viewed().old().delete()


def weight_set(factor: float=1.0):
    """Set the weight of selected keys

    :param factor: Factor, Interpolation factor between current brush weight, and keys’ weights
    :type factor: float
    """
    pass


def _write_time(path, ts=None):
    """
    Write the current time in ms to the file at path.
    Returns `ts`
    """
    if not ts:
        ts = ''
    ts = str(ts)
    with open(path, 'w') as fd:
        fd.write(ts)
    return ts


def is_some_dict(arg, allow_none=False):
    """
    >>> is_some_dict(3)
    False
    >>> is_some_dict(3.5)
    False
    >>> is_some_dict('hi')
    False
    >>> is_some_dict([1, 2, 3])
    False
    >>> is_some_dict([[1, 2, 3], [1, 2, 3]])
    False
    >>> import numpy as np
    >>> is_some_dict(np.array([1, 2, 3]))
    False
    >>> is_some_dict(np.array([[1, 2, 3], [1, 2, 3]]))
    False
    >>> is_some_dict({'name': 'Paul', 'surname': 'Bilokon'})
    True
    >>> is_some_dict(col.OrderedDict((('name', 'Paul'), ('surname', 'Bilokon'))))
    True
    >>> is_some_dict(None)
    False
    >>> is_some_dict(None, allow_none=True)
    True
    """
    return allow_none and arg is None or hasattr(arg, 'keys')


def forwards_relation(src, rel):
    """
    Returns the SQL query for selecting the destination
    nodes given a relation and a source node.

    :param src: The source node.
    :param rel: The relation.
    """
    statement = 'SELECT dst FROM %s WHERE src = ?'
    return statement % rel, (src,)


def stroke_change_color():
    """Move selected strokes to active color

    """
    pass


def cylindrical_receiver(rec_param, hemisphere='North'):
    """
    hemishpere : 'North' or 'South' hemisphere of the earth where the field located
                if North: the field is in the positive y direction
                if South: the field is in the negtive y direction
                this will influence:
                 (1) the setting of the receiver tilt angle,
                     if the front surface always facing to the field is desirable
                 (2) the position of the virtual target
    """
    rec_r = rec_param[0]
    rec_h = rec_param[1]
    slices = rec_param[2]
    x = rec_param[3]
    y = rec_param[4]
    z = rec_param[5]
    geom = ''
    geom += '- geometry: &%s\n' % 'target_g'
    geom += '  - material: *%s\n' % 'material_target'
    geom += '    cylinder: \n'
    geom += '      height: %s\n' % rec_h
    geom += '      radius: %s\n' % rec_r
    geom += '      slices: %d\n' % slices
    geom += '\n'
    entt = ''
    entt += '\n- entity:\n'
    entt += '    name: target_e\n'
    entt += '    primary: 0\n'
    entt += '    transform: { translation: %s, rotation: %s }\n' % ([x, y,
        z], [0.0, 0.0, 0.0])
    entt += '    geometry: *%s\n' % 'target_g'
    Vsize = 100.0
    pts = [[-rec_h * Vsize, -rec_h * Vsize], [-rec_h * Vsize, rec_h * Vsize
        ], [rec_h * Vsize, rec_h * Vsize], [rec_h * Vsize, -rec_h * Vsize]]
    slices = 4
    entt += '\n- entity:\n'
    entt += '    name: virtual_target_e\n'
    entt += '    primary: 0\n'
    entt += '    transform: { translation: %s, rotation: %s }\n' % ([x, y,
        z + rec_h / 2.0 + 1], [-180.0, 0, 0])
    entt += '    geometry: \n'
    entt += '      - material: *%s\n' % 'material_virtual'
    entt += '        plane: \n'
    entt += '          clip: \n'
    entt += '          - operation: AND \n'
    entt += '            vertices: %s\n' % pts
    entt += '          slices: %d\n' % slices
    rcv = ''
    rcv += '- name: target_e \n'
    rcv += '  side: %s \n' % 'FRONT_AND_BACK'
    rcv += '  per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
    rcv += '- name: virtual_target_e \n'
    rcv += '  side: %s \n' % 'FRONT'
    rcv += '  per_primitive: %s \n' % 'INCOMING'
    return geom, entt, rcv


def limtozero(x):
    """
    zero the value close to zero

    Parameters
    ----------
    x : float

    Returns
    -------
    0
    """
    if x < 1e-15:
        x = 0
    return x


def specific_actions():
    """Specific actions"""


def _silent_get(x, i):
    """
    Given a list x and an index i, returns the element from the list
    at index i if i is valid. Otherwise, return empty string - ''.
    >>> _silent_get([1,2,3,4], 2)
    3
    >>> _silent_get([1,2,3,4], 5)
    ''
    """
    if i < len(x):
        return x[i]
    else:
        return ''


def ask_confirmation():
    """Ask for confirmation to the user. Return true if the user confirmed
    the execution, false otherwise.

    :returns: bool
    """
    while True:
        print('Do you want to restart these brokers? ', end='')
        choice = input().lower()
        if choice in ['yes', 'y']:
            return True
        elif choice in ['no', 'n']:
            return False
        else:
            print("Please respond with 'yes' or 'no'")


def Bejan_p(dP, K, mu, alpha):
    """Calculates Bejan number of a permeability or `Be_p` for a fluid with
    the given parameters and a permeability `K` experiencing a pressure drop
    `dP`.

    .. math::
        Be_p = \\frac{\\Delta P K}{\\mu \\alpha}

    Parameters
    ----------
    dP : float
        Pressure drop, [Pa]
    K : float
        Permeability, [m^2]
    mu : float, optional
        Dynamic viscosity, [Pa*s]
    alpha : float
        Thermal diffusivity, [m^2/s]

    Returns
    -------
    Be_p : float
        Bejan number with respect to pore characteristics []

    Notes
    -----
    Termed a dimensionless number by someone in 1988.

    Examples
    --------
    >>> Bejan_p(1E4, 1, 1E-3, 1E-6)
    10000000000000.0

    References
    ----------
    .. [1] Awad, M. M. "The Science and the History of the Two Bejan Numbers."
       International Journal of Heat and Mass Transfer 94 (March 2016): 101-3.
       doi:10.1016/j.ijheatmasstransfer.2015.11.073.
    .. [2] Bejan, Adrian. Convection Heat Transfer. 4E. Hoboken, New Jersey:
       Wiley, 2013.
    """
    return dP * K / (alpha * mu)


def get_class_from_path(path):
    """
    Get class from given path.

    :argument path: dotted path to the target class
    :type path: str

    :returns: class
    """
    module_path, class_name = path.rsplit('.', 1)
    module = __import__(module_path, fromlist=[class_name])
    return getattr(module, class_name)


def _get_model_dim(model):
    """Return the dimensionality of a random model property."""
    return list(model.values())[0].dim()


def check(name, type, country, geometry, **args):
    """Should return True if this area is NEW, False if we should match"""
    if type == 'WMC' and country in ('E', 'W'):
        return True
    return False


def is_float(f):
    """Check if a variable is a `float` type.

    Args:
        f: The object to check.

    Returns:
        :obj:`bool`: If the object can be converted to a :obj:`float`.
    """
    if not f:
        return False
    try:
        float(f)
        return True
    except ValueError:
        return False


def from_key(key):
    """
    Returns a tuple ``(name, annotation)`` for a key formatted as defined in
    :attr:`~di.annotators.ANNOTATION_FORMAT`, e.g. ``('widget', 'text')`` for key ``'widget:text'``.

    :param key: A key
    :type key: str

    :rtype: tuple
    """
    parts = key.split(':', 1)
    return (parts[0], None) if len(parts) < 2 else parts


def chmod(ctx, path, mode):
    """Change fs object permissions."""
    ctx.sudo('chmod %s %s' % (mode, path))


@classmethod
def is_auto_type_cast(cls):
    """Shows if automatic type cast is enabled"""
    return cls._auto_type_cast


def normalize_class_name(cls, name=None):
    """
    Return the default class name from the given type.
    """
    if name:
        return name
    return cls.__name__.lower()


def dump(obj):
    """
    function for debugging - dumps object to sysout
    """
    for attr in dir(obj):
        print('obj.%s = %r' % (attr, getattr(obj, attr)))


def main():
    """Entry point for the application script"""
    print('Call your main application code here')


def circle(x, y, radius, color=None, width=None):
    """Return a circle shape

    args:
        x, y (float): center coordinates
        radius (float): circle radius
        color (str): a plotly color string
        width (int): line width
    """
    data = {'type': 'circle', 'xref': 'x', 'yref': 'y', 'fillcolor':
        'rgba(50, 171, 96, 0.7)', 'x0': x - radius, 'y0': y - radius, 'x1':
        x + radius, 'y1': y + radius, 'line': {}}
    if color:
        data['line']['color'] = color
    if width:
        data['line']['width'] = width
    return data


@classmethod
def from_path(cls, p, strict=True, **kwargs):
    """
        Create a Model from the given file path.

        Args:
            p (str): the file path to read from.
            strict (bool): if set to False then no exception will be raised when
                unknown dictionary keys are present.
            **kwargs: extra keyword arguments passed directly to `json.loads()`.

        Returns:
            Model: a new Model instance.
        """
    with open(p) as f:
        return cls.from_json(f.read(), strict=strict, **kwargs)


def ul(items, bullet='-'):
    """ Render the given `items` as a `bullet list
    <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#bullet-lists>`_.
    `items` must be an iterable whose elements are strings.

    If at least one item contains more than one paragraph,
    then all items are separated by an additional blank line.

    >>> print(ul(["Foo", "Bar", "Baz"]))
    - Foo
    - Bar
    - Baz
    <BLANKLINE>
    >>> print(ul([
    ...   "Foo", "An item\\nwith several lines of text.", "Bar"]))
    - Foo
    - An item
      with several lines of text.
    - Bar
    <BLANKLINE>
    >>> print(ul([
    ...   "A first item\\nwith several lines of text.",
    ...   "Another item with a nested paragraph:\\n\\n  Like this.\\n\\nWow."]))
    <BLANKLINE>
    - A first item
      with several lines of text.
    <BLANKLINE>
    - Another item with a nested paragraph:
    <BLANKLINE>
        Like this.
    <BLANKLINE>
      Wow.
    <BLANKLINE>

    """
    s = ''
    compressed = True
    for i in items:
        if '\n\n' in i:
            compressed = False
            break
    innersep = '\n' + ' ' * (len(bullet) + 1)
    if compressed:
        for i in items:
            text = innersep.join(i.splitlines())
            s += '%s %s\n' % (bullet, text)
    else:
        for i in items:
            text = innersep.join(i.splitlines())
            s += '\n%s %s\n' % (bullet, text)
    return s


def dummy_callback(_):
    """Dummy callback doing nothing."""
    pass


def pairwise():
    """every two incoming things as a tuple"""


def flat(chunks):
    """Concatnate chunks into a data
    Aimed for the use of crafting ROP chains

    Args:
        chunks    : The target chunks to concat

    Returns:
        bytes: split chunks
    """
    assert isinstance(chunks, list)
    result = chunks[0]
    for i in range(1, len(chunks)):
        result += chunks[i]
    return result


def remove_env_bin_from_path(env, env_bin_dir):
    """
    Remove bin directory of the current environment from PATH
    """
    return env.replace(env_bin_dir + ':', '')


def create_named_query(Name=None, Description=None, Database=None,
    QueryString=None, ClientRequestToken=None):
    """
    Creates a named query.
    For code samples using the AWS SDK for Java, see Examples and Code Samples in the Amazon Athena User Guide .
    See also: AWS API Documentation

    :example: response = client.create_named_query(
        Name='string',
        Description='string',
        Database='string',
        QueryString='string',
        ClientRequestToken='string'
    )

    :type Name: string
    :param Name: [REQUIRED]
            The plain language name for the query.

    :type Description: string
    :param Description: A brief explanation of the query.

    :type Database: string
    :param Database: [REQUIRED]
            The database to which the query belongs.

    :type QueryString: string
    :param QueryString: [REQUIRED]
            The text of the query itself. In other words, all query statements.

    :type ClientRequestToken: string
    :param ClientRequestToken: A unique case-sensitive string used to ensure the request to create the query is idempotent (executes only once). If another CreateNamedQuery request is received, the same response is returned and another query is not created. If a parameter has changed, for example, the QueryString , an error is returned.
            Warning
            This token is listed as not required because AWS SDKs (for example the AWS SDK for Java) auto-generate the token for users. If you are not using the AWS SDK or the AWS CLI, you must provide this token or the action will fail.
            This field is autopopulated if not provided.

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

    """
    pass


@classmethod
def from_json_type(cls, data):
    """Convert a dictionary of JSON safe data to an event"""
    data.pop('type')
    return cls(**data)


def unaligned_read(read, tags=[]):
    """Create an unaligned sam record for a read.

    :param read: a `Read` namedtuple.
    :param tags: list containing additional tags to add to sam record.

    :returns: a (string) sam record.
    """
    sam = '\t'.join((read.read_id, '4', '*', '0', '255', '*', '*', '0', '0',
        read.sequence, read.quality, *tags))
    return sam


def disable_keep_transform():
    """Set the influence of this constraint to zero while trying to maintain the object’s transformation. Other active constraints can still influence the final transformation

    """
    pass


@staticmethod
def cook(raw_item, **params):
    """
        If it's convenient to cache a modified version of the item that was
        fetched, it can be transformed here.
        :param raw_item: item to be cooked
        :param params: other parameters that may be required
        :return: cooked item
        """
    return raw_item


def adapt_list(lst) ->str:
    """
    Adapt list entries before writing to database.

    This function takes a list and serializes it in order to
    write it to the sqlite database as string.
    """
    return '|'.join(lst)


def equals(first, second):
    """
    used to overload Dunder method __eq__ of any class
    Compare equality of first and second
    :param first: self of one object
    :param second: self of other object
    :return: True if all attributes value are same otherwise False
    """
    for k, v in first.__dict__.items():
        if not hasattr(second, k) or v != second.__dict__[k]:
            return False
    for k, v in second.__dict__.items():
        if not hasattr(first, k) or v != first.__dict__[k]:
            return False
    return True


@staticmethod
def do_nothing_node_stub(context, node):
    """ Just stub for do nothing on handling node attempt """


def lerp(v1: float, v2: float, u: float) ->float:
    """linearly interpolate between two values"""
    return v1 + (v2 - v1) * u


def introspection_query(description: bool=True) ->str:
    """
    Return a generic introspection query to be used by GraphQL clients.

    Args:
        description: If ``True`` the query will require descriptions.

    Returns:
        Canonical introspection query

    """
    return (
        """
    query IntrospectionQuery {
        __schema {
            queryType { name }
            mutationType { name }
            subscriptionType { name }

            types {
                ...FullType
            }

            directives {
                name
                %(description_field)s
                locations
                args {
                    ...InputValue
                }
            }
        }
    }

    fragment FullType on __Type {
        kind
        name
        %(description_field)s

        fields(includeDeprecated: true) {
            name
            %(description_field)s
            args {
                ...InputValue
            }
            type {
                ...TypeRef
            }
            isDeprecated
            deprecationReason
        }

        inputFields {
            ...InputValue
        }

        interfaces {
            ...TypeRef
        }

        enumValues(includeDeprecated: true) {
            name
            %(description_field)s
            isDeprecated
            deprecationReason
        }

        possibleTypes {
            ...TypeRef
        }
    }

    fragment InputValue on __InputValue {
        name
        %(description_field)s
        type { ...TypeRef }
        defaultValue
    }

    fragment TypeRef on __Type {
        kind
        name
        ofType {
            kind
            name
            ofType {
                kind
                name
                ofType {
                    kind
                    name
                    ofType {
                        kind
                        name
                        ofType {
                            kind
                            name
                            ofType {
                                kind
                                name
                                ofType {
                                    kind
                                    name
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    """
         % {'description_field': '' if not description else 'description'})


@staticmethod
def get_message_id_from_payload(message):
    """Get Iris message id from Gmail message payload

        :param message: Gmail message
        :return: Iris message id
        :rtype: int
        """
    try:
        ret = int(message.split()[0])
    except ValueError:
        raise
    if ret:
        return ret


def key(v):
    """Return the private key part (the left half) of a 64-byte sequence v."""
    return v[:32]


def car_object_scoper(object_name):
    """ Scopes a CAR object name, via dm-[object]-[action], or dm-[object]-* """
    return 'match(tag, "dm-{}-.*")'.format(object_name)


def get_set_wmf_eof(parent=None, new_value=None, **kwargs):
    """Size getter/setter for the length of a wmf file."""
    if parent is None:
        raise KeyError('Cannot get or set the size of the' +
            'wmf file without a supplied parent.')
    if new_value is None:
        return parent.header.filesize * 2 + parent.placeable_header.binsize
    parent.header.filesize = (new_value - parent.placeable_header.binsize) // 2


def identity(x):
    """ Identity function. Returns x.

    >>> identity(3)
    3
    """
    return x


def get_valid_keywords():
    """
    Among other things, this list is used by the color highlighting in
    personal.ini editing in plugin.  Note that it's separate from
    value checking and most keywords need to be added to both.
    """
    return list(['(in|ex)clude_metadata_(pre|post)', 'add_chapter_numbers',
        'add_genre_when_multi_category', 'adult_ratings',
        'allow_unsafe_filename', 'always_overwrite', 'anthology_tags',
        'anthology_title_pattern', 'background_color', 'bulk_load',
        'chapter_end', 'chapter_start', 'chapter_title_strip_pattern',
        'chapter_title_def_pattern', 'chapter_title_add_pattern',
        'chapter_title_new_pattern', 'chapter_title_addnew_pattern',
        'title_chapter_range_pattern', 'mark_new_chapters',
        'check_next_chapter', 'skip_author_cover', 'collect_series',
        'comma_entries', 'connect_timeout', 'convert_images_to',
        'cover_content', 'cover_exclusion_regexp',
        'custom_columns_settings', 'dateCreated_format',
        'datePublished_format', 'dateUpdated_format', 'default_cover_image',
        'description_limit', 'do_update_hook', 'use_archived_author',
        'use_view_full_work', 'always_login', 'exclude_notes',
        'remove_authorfootnotes_on_update', 'exclude_editor_signature',
        'extra_logpage_entries', 'extra_subject_tags',
        'extra_titlepage_entries', 'extra_valid_entries', 'extratags',
        'extracategories', 'extragenres', 'extracharacters', 'extraships',
        'extrawarnings', 'fail_on_password', 'file_end', 'file_start',
        'fileformat', 'find_chapters', 'fix_fimf_blockquotes',
        'keep_prequel_in_description', 'include_author_notes',
        'force_login', 'generate_cover_settings', 'grayscale_images',
        'image_max_size', 'include_images', 'include_logpage',
        'logpage_at_end', 'calibre_series_meta', 'include_subject_tags',
        'include_titlepage', 'include_tocpage', 'chardet_confidence_limit',
        'is_adult', 'join_string_authorHTML', 'keep_style_attr',
        'keep_title_attr', 'keep_html_attrs', 'replace_tags_with_spans',
        'keep_empty_tags', 'keep_summary_html', 'logpage_end',
        'logpage_entries', 'logpage_entry', 'logpage_start',
        'logpage_update_end', 'logpage_update_start', 'make_directories',
        'make_firstimage_cover', 'make_linkhtml_entries', 'max_fg_sleep',
        'max_fg_sleep_at_downloads', 'min_fg_sleep', 'never_make_cover',
        'no_image_processing', 'non_breaking_spaces',
        'download_text_version', 'nook_img_fix', 'output_css',
        'output_filename', 'output_filename_safepattern', 'password',
        'post_process_cmd', 'rating_titles', 'remove_transparency',
        'replace_br_with_p', 'replace_hr', 'replace_xbr_with_hr',
        'replace_metadata', 'slow_down_sleep_time', 'sort_ships',
        'sort_ships_splits', 'strip_chapter_numbers',
        'strip_chapter_numeral', 'strip_text_links',
        'centeredcat_to_characters', 'pairingcat_to_characters_ships',
        'romancecat_to_characters_ships', 'use_meta_keywords',
        'chapter_categories_use_all', 'clean_chapter_titles',
        'conditionals_use_lists', 'description_in_chapter',
        'inject_chapter_title', 'auto_sub', 'titlepage_end',
        'titlepage_entries', 'titlepage_entry', 'titlepage_no_title_entry',
        'titlepage_start', 'titlepage_use_table', 'titlepage_wide_entry',
        'tocpage_end', 'tocpage_entry', 'tocpage_start', 'tweak_fg_sleep',
        'universe_as_series', 'use_ssl_unverified_context', 'user_agent',
        'username', 'website_encodings', 'wide_titlepage_entries',
        'windows_eol', 'wrap_width', 'zip_filename', 'zip_output',
        'capitalize_forumtags', 'continue_on_chapter_error',
        'chapter_title_error_mark', 'minimum_threadmarks',
        'first_post_title', 'always_include_first_post',
        'always_reload_first_chapter', 'always_use_forumtags',
        'use_reader_mode', 'author_avatar_cover', 'reader_posts_per_page',
        'remove_spoilers', 'legend_spoilers', 'apocrypha_to_omake',
        'skip_threadmarks_categories', 'normalize_text_links',
        'internalize_text_links', 'replace_failed_smilies_with_alt_text',
        'use_threadmark_wordcounts', 'always_include_first_post_chapters',
        'order_threadmarks_by_date', 'use_threadmarks_description',
        'use_threadmarks_status', 'use_threadmarks_cover',
        'skip_sticky_first_posts', 'datethreadmark_format',
        'fix_pseudo_html', 'fix_excess_space', 'ignore_chapter_url_list',
        'dedup_chapter_list', 'max_zalgo', 'epub_version'])


def remove_initial_data(apps, schema_editor):
    """This function does nothing. The below code is commented out together
    with an explanation of why we don't need to bother reversing any of the
    initial data"""
    pass


def identity(x):
    """ Identity function. Return x

    >>> identity(3)
    3
    """
    return x


def get_library_by_root(library_db, path):
    """returns a list of loaded libraries"""
    from src.praxxis.sqlite import connection
    conn = connection.create_connection(library_db)
    cur = conn.cursor()
    get_library = 'SELECT * FROM "LibraryMetadata" WHERE Path = ?'
    cur.execute(get_library, (path,))
    conn.commit()
    rows = cur.fetchall()
    conn.close()
    return rows


@classmethod
def _get_parent_from_dn(cls, dn):
    """
        Derive the parent object using a dn

        :param dn: String containing a distinguished name of an object
        """
    parent_class = cls._get_parent_class()
    if parent_class is None:
        return None
    if isinstance(parent_class, list):
        for parent_class_name in parent_class:
            parent_name = parent_class_name._get_name_from_dn(dn)
            if parent_name is not None:
                parent_class = parent_class_name
                break
    else:
        parent_name = parent_class._get_name_from_dn(dn)
    if isinstance(parent_class, list):
        return None
    parent_dn = cls._get_parent_dn(dn)
    if parent_name is None:
        parent_obj = parent_class('')
    else:
        parent_obj = parent_class(parent_name, parent_class.
            _get_parent_from_dn(parent_dn))
    return parent_obj


@staticmethod
def _wrap_encode_items(items):
    """Return `items` encoded as bytes.

        Parameters
        ----------
        items : list of PDU items
            The items to encode.

        Returns
        -------
        bytes
            The encoded items.
        """
    bytestream = bytes()
    for item in items:
        bytestream += item.encode()
    return bytestream


def _lookup(dic, key):
    """Lookup a key in a dictionary, where None returns an empty string
    but an unmatched key returns a question mark. Used in :class:`G2VarObj`
    """
    if key is None:
        return ''
    elif key == '*':
        return '*'
    else:
        return dic.get(key, '?')


def check_region(region):
    """
    Check that the given region dimensions are valid.

    For example, the west limit should not be greater than the east and there
    must be exactly 4 values given.

    Parameters
    ----------
    region : list = [W, E, S, N]
        The boundaries of a given region in Cartesian or geographic
        coordinates.

    Raises
    ------
    ValueError
        If the region doesn't have exactly 4 entries, W > E, or S > N.

    """
    if len(region) != 4:
        raise ValueError("Invalid region '{}'. Only 4 values allowed.".
            format(region))
    w, e, s, n = region
    if w > e:
        raise ValueError(
            "Invalid region '{}' (W, E, S, N). Must have W =< E. ".format(
            region) +
            "If working with geographic coordinates, don't forget to match geographic"
             + " region with coordinates using 'verde.longitude_continuity'.")
    if s > n:
        raise ValueError("Invalid region '{}' (W, E, S, N). Must have S =< N."
            .format(region))


@classmethod
def origin_index(cls, index):
    """Return the equivalent index when the supershape is at the origin."""
    row, col = index
    origin_row = 0
    origin_col = col % 2
    return origin_row, origin_col


@classmethod
def find_module(cls, fullname, path=None):
    """find the module on sys.path or 'path' based on sys.path_hooks and
        sys.path_importer_cache.

        This method is deprecated.  Use find_spec() instead.

        """
    spec = cls.find_spec(fullname, path)
    if spec is None:
        return None
    return spec.loader


@staticmethod
def __setting_has_pch(context, setting):
    """
        Return if there is precompiled header or not for given setting

        :param context: converter Context
        :type context: Context
        :param setting: related setting (Release|x64, Debug|Win32,...)
        :type setting: str
        :return: if use PCH or not
        :rtype: bool
        """
    has_pch = context.settings[setting]['PrecompiledHeader']
    return 'Use' in has_pch


def threshold(data, delta=1e-07):
    """
    给定一组成双峰分布的数据 data 计算双峰之间的分界值

    Args:
        data : numpy.array
        delta: 精确度，默认 delta = 1e-7
    """
    threshold = m1 = m2 = data.mean()
    while True:
        g1 = data[data < threshold]
        g2 = data[data > threshold]
        m1 = g1.mean()
        m2 = g2.mean()
        t = (m1 + m2) / 2
        if abs(threshold - t) < delta:
            break
        threshold = t
    return threshold


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

        :param ShowcaseEditCommentType val:
        :rtype: EventType
        """
    return cls('showcase_edit_comment', val)


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


def get_metadata(bucket, key_name):
    """
    Return a dictionary of all metadata on the given key

    bucket      The bucket (boto) object
    key_name    The name of the key
    """
    return bucket.get_key(key_name).metadata


def set(object, value):
    """Set the value of the field for the object

        Raises a type error if the field is a read-only field.
        """


def subtract(x, y):
    """Subtract one number from another.

    Parameters
    ----------
    x : int
        The first number.
    y : int
        The second number.

    Returns
    -------
    z : int
        The first number minus the second number

    Example
    -------
    >>> subtract(2, 1)
    """
    return x - y


def init_legendre_poly(result, x, pos, cur_var):
    """Initialize the first and second order before starting the recursion.

    Mathematically this amounts to
    P_1 = x
    P_2 = 3/2 * P_1*P_1 - 1/2 .

    .. note::

        The procedure on how an init function is built can be found in the
        docstring of the init function for
        standard polynomials *init_standard_poly*.

    :param result: Contains the observations along the first dimension
        and the function values of expansion w.r.t. an observation
        along the second dimension.
    :type result: numpy.ndarray

    :param x: The data to be expanded.
    :type x: numpy.ndarray

    :param pos: The index of the element to be computed, along the second
        dimension of result.
    :type int: int

    :param cur_var: The index of the current variable to be considered in the
        recursion. This value will have to be lower than x.shape[1].
    :type cur_var: int

    :returns: The index of the next element that will be computed in the
        recursion, the order of the next element, and the index of a special
        element. Is this case the first order Legendre polynomial of the
        current variable is the special element.
    :rtype: Tuple[int, int, int]
    """
    result[:, (pos)] = x[:, (cur_var)]
    result[:, (pos + 1)] = 3.0 / 2.0 * result[:, (pos)] * result[:, (pos)
        ] - 0.5
    return pos + 2, 3, pos


def _swap_2opt(route, i, k):
    """ Swapping the route """
    new_route = route[0:i]
    new_route.extend(reversed(route[i:k + 1]))
    new_route.extend(route[k + 1:])
    return new_route


def _utc_datetime_to_iso(datetime_object):
    """
    Takes a UTC datetime object and returns an ISO formatted string
    :param datetime_object: datetime.datetime
    :return: string with datetime in ISO format
    """
    if datetime_object:
        return datetime_object.strftime('%Y-%m-%dT%H:%M:%SZ')
    return None


def parse_attributes(fields):
    """Parse list of key=value strings into a dict"""
    attributes = {}
    for field in fields:
        pair = field.split('=')
        attributes[pair[0]] = pair[1]
    return attributes


def has_key(o, key):
    """
    TODO migrate to PyBase
    :param o:
    :param key:
    :return:
    """
    return hasattr(o, '__iter__') and key in o


def progress_type(text):
    """Return plain progress text, turning aliases into their value."""
    return {'dot': '.', 'percent': '{percent}%\n', 'pages':
        '{page}/{total}\n', 'none': ''}.get(text, text)


def changelog():
    """
    PyBDSF Changelog.
    -----------------------------------------------------------------------
    2019/12/05 - Version 1.9.2

    2019/12/04 - Fix exception behaviour if spline order change does not work

    2019/09/27 - Add check for frequency info in header

    2019/09/25 - Version 1.9.1

    2019/09/25 - Fix various minor bugs

    2019/06/06 - Fix blank_limit check_low error (#100)

    2019/05/09 - Fix various shapelet decomposition issues

    2019/05/08 - Fix crash in Gaussian fitting (#96)

    2019/03/25 - Version 1.9.0

    2018/10/18 - Add support for Python 3

    2018/10/18 - Fix various minor bugs

    2018/10/12 - Version 1.8.15

    2018/10/09 - Fix segfault in Gaussian fitting (#63)

    2018/10/04 - Fix math domain error (#76)

    2018/06/21 - Fix setup.py for boost versions > 1.63

    2018/05/18 - Version 1.8.14

    2018/05/18 - Fix an error on total flux density (#50)

    2018/05/18 - Add the possibility to provide an external noise and mean maps (#43)

    2018/05/18 - Append the image FITS header into catalog FITS header (#53)

    2018/05/18 - Make PyBDSF compatible with newer boost libraries, specifically
        those used in Ubuntu 18.04 (#55)

    2017/11/17 - Version 1.8.13

    2017/11/17 - Remove deprecated boolean operators

    2017/09/01 - Version 1.8.12

    2017/09/01 - Fix crash with tiny regions

    2017/09/01 - Fix very low centroid peak fluxes

    2017/09/01 - Fix compile error with numpy 1.13

    2017/06/01 - Version 1.8.11

    2017/06/01 - Fix for interactive shell problem

    2017/05/31 - Version 1.8.10

    2017/05/31 - Fixes for various installation and runtime issues on modern systems.

    2017/03/23 - Version 1.8.9

    2017/03/23 - Fix to bug that causes an error when grouping Gaussians
        into sources

    2017/03/17 - Version 1.8.8

    2017/03/17 - Rename to PyBDSF, move to github, add setup.py installer

    2017/02/28 - Fix to issues related to numpy >= 1.12 and astropy >= 1.3

    2016/06/10 - Version 1.8.7

    2016/06/10 - Fix to bug that caused incorrect output images when input
        image was not square.

    2016/01/20 - Version 1.8.6

    2016/01/15 - Fix to bug that caused incorrect island mask when two
        islands are very close together.

    2015/12/07 - Fix to bug that caused crash when image is masked and
        the src_ra_dec option is used.

    2015/11/30 - Version 1.8.5

    2015/11/25 - Fix to bug in export_image that resulted in incorrect
        output image when both trim_box and pad_image were used.

    2015/11/20 - Fix to bug in wavelet module related to merging of islands.

    2015/11/20 - Fix to bug in polarization module related to numbering of
        new islands.

    2015/11/20 - Fix to bug in spectral index module related to rms map
        calculation.

    2015/11/20 - Added option to use much faster (but also much more memory
        intensive) SciPy fftconvolve function instead of custom PyBDSM one.
        The option (use_scipy_fft) defaults to True.

    2015/11/20 - Increased number of digits for values in output text
        catalogs

    2015/08/06 - Version 1.8.4

    2015/08/06 - Improved speed of wavelet module.

    2015/08/06 - Added option to use PyFFTW in wavelet module if available.

    2015/08/06 - Fix to IPython version check.

    2015/08/06 - Fix to bug that caused a failure to write shapelet models
        in FITS format.

    2014/11/07 - Fix to bug that caused a crash when both atrous_do = True
        and output_all = True. Fixed a bug that caused a crash on machines
        with only one core.

    2014/09/26 - Version 1.8.3

    2014/09/26 - Fix to bug that caused a crash when using the wavelet
        module and all Gaussians in an island were flagged.

    2014/07/03 - Mask will now be expanded to match input image shape. Fix
        to bug that caused image read failure when image lacks a Stokes axis.

    2014/05/14 - Version 1.8.2

    2014/05/15 - Fix to bug in CASA masks generated with export_image() that
        caused cleaning to fail in CASA 4.2 and above.

    2014/02/05 - Fix to bug that resulted in output file names being
        converted to lower case inappropriately.

    2014/01/14 - Version 1.8.1

    2014/01/13 - Added option (bbs_patches = 'mask') to allow patches in
        an output BBS sky model to be defined using a mask image.

    2014/01/09 - Fix to bug that caused the incl_empty option to be
        ignored when format='fits' in the write_catalog task.

    2013/12/05 - Enabled output of images in CASA format in the export_image
    	task (img_format = 'casa'). Added an option to export_image task to
    	export an island-mask image, with ones where there is emission and
    	zeros elsewhere (image_type = 'island_mask'). Features in the island
    	mask may be optionally dilated by specifying the number of dilation
    	iterations with the mask_dilation parameter. Added an option to
    	write a CASA region file to the write_catalog task (format =
    	'casabox'). Added an option to write a CSV catalog to the
    	write_catalog task (format = 'csv').

    2013/11/04 - Added error message when the rms is zero in some part of the
        rms map.

    2013/10/16 - Version 1.8.0

    2013/10/16 - Improved wavelet fitting. Added option so that wavelet
    	fitting can be done to the sum of images on the remaining wavelet
    	scales, improving the signal for fitting (controlled with the
    	atrous_sum option). Added option so that user can choose whether to
    	include new islands found only in the wavelet images in the final
    	fit or not (controlled with the atrous_orig_isl option).

    2013/10/10 - Fixed a bug that could lead to incomplete fitting of
        some islands. Improved overall convergence of fits.

    2013/10/10 - Version 1.7.7

    2013/10/10 - Improved fitting of bright sources under certain
        circumstances.

    2013/09/27 - Version 1.7.6

    2013/09/27 - Changed caching behavior to ensure that temporary files
        are always deleted after they are no longer needed or on exit.

    2013/09/05 - Renamed blank_zeros to blank_limit. The blank_limit
        option now specifies a limit below which pixels are blanked.

    2013/09/05 - Enabled SAGECAL sky-model output.

    2013/09/02 - Version 1.7.5

    2013/09/02 - Fix to bug that caused a crash when images with 2 or
        3 axes were used. Improved rms and mean calculation (following the
        implementation used in PySE, see http://dare.uva.nl/document/174052
        for details). The threshold used to determine the clipped rms and
        mean values is now determined internally by default (kappa_clip =
        None).

    2013/08/27 - Version 1.7.4

    2013/08/29 - Fix to bug in show_fit() that caused error when
        'i' is pressed in the plot window and shapelet decomposition
        had not been done. Tweak to 'pybdsm' startup shell script to
        avoid problems with the Mac OS X matplotlib backend on non-
        framework Python installations (such as Anaconda Python).

    2013/08/28 - Fix to bug in process_image() that could result in
        wavelet Gaussians being excluded from model image under certain
        conditions.

    2013/08/27 - Version 1.7.3

    2013/08/27 - Fix to bug in image reading that caused images to be
        distorted.

    2013/08/23 - Version 1.7.2

    2013/08/23 - Improved handling of non-standard FITS CUNIT keywords.
        Improved loading of FITS images when trim_box is specified.

    2013/08/22 - Version 1.7.1

    2013/08/21 - Fix to bug that caused cached images to be deleted when
        rerunning an analysis. Fix to bug in show_fit() due to undefined
        images. Fix to bug in process_image() that would result in unneeded
        reprocessing.

    2013/08/20 - Version 1.7.0

    2013/08/19 - PyBDSM will now use Astropy if installed for FITS and WCS
        modules.

    2013/08/11 - Fix to avoid excessive memory usage in the wavelet module
        (replaced scipy.signal.fftconvolve with a custom function).

    2013/08/11 - Added option to use disk caching for internally derived
    	images (do_cache). Caching can reduce memory usage and is
    	therefore useful when processing large images.

    2013/07/11 - Implemented a variable operation chain for process_image
        (and img.process()) that allows unneeded steps to be skipped if
        the image is being reprocessed.

    2013/07/11 - Fixed a bug that could cause Gaussian fitting to hang
        during iterative fitting of large islands.

    2013/06/24 - Added option (fix_to_beam) to fix the size and position
    	angle of Gaussians to the restoring beam during fitting. Fix to
    	bug that caused the position angle used to initialize fitting to
    	be incorrect.

    2013/03/22 - Version 1.6.1

    2013/03/21 - Fix to bug in ds9 and kvis catalog files that resulted in
        incorrect position angles. Fix to bug in position-dependent WCS
        transformations that caused incorrect source parameters in output
        catalogs. Added option to output uncorrected source parameters
        to a BBS sky model file (correct_proj).

    2013/03/14 - Removed sky transformations for flagged Gaussians, as
        these could sometimes give math domain errors. Disabled aperture
        flux measurement on wavelet images as it is not used/needed.

    2013/02/25 - Version 1.6.0

    2013/02/25 - Improved speed and accuracy of aperture flux
        calculation.

    2013/02/20 - Added option to use the curvature map method of
        Hancock et al. (2012) for the initial estimation of Gaussian
        parameters (ini_method = 'curvature') and for grouping of
        Gaussians into sources (group_method = 'curvature').

    2013/02/18 - Fix to bug in spectral index module that caused sources
        with multiple Gaussians to be skipped. Minor adjustments to the
        wavelet module to improve performance.

    2013/02/08 - Implemented position-dependent WCS transformations.

    2013/02/08 - Added option to fit to any arbitrary location in the
        image within a given radius (src_ra_dec and src_radius_pix).

    2013/02/04 - Fix to bug in wavelet module that caused crash when
       no Gaussians were fit to the main image.

    2013/01/30 - Fix to bug that resulted in incorrect numbering of
       wavelet Gaussians. Added 'srl' output in ds9 format when using
       output_all = True.

    2013/01/28 - Fix to bug in source grouping algorithm. Improved fitting
       when background mean is nonzero. Fix to allow images with GLAT and
       GLON WCS coordinates. Fix to bug when equinox is taken from the
       epoch keyword.

    2012/12/19 - Version 1.5.1

    2012/12/19 - Fix to bug in wavelet module that occurred when the
        center of the wavelet Gaussian lies outside of the image. Fix
        to re-enable srl output catalogs in ds9 region format. Fix to
        bug that resulted in the output directory not always being
        created. Added an option (aperture_posn), used when aperture
        fluxes are desired, to specify whether to center the aperture
        on the source centroid or the source peak.

    2012/12/02 - Changes to reduce memory usage, particularly in the
        wavelet module.

    2012/11/30 - Fix to bypass bug in matplotlib when display variable
        is not set.

    2012/11/21 - Fixed bug that caused a crash when a detection image
        was used. Fixed a bug with incorrect save directory when
        plot_allgaus = True.

    2012/10/29 - Version 1.5.0

    2012/10/29 - Improved handling of WCS information so that a much
        greater variety of WCS systems may be used. Fixed a bug in logging
        that occurred when negative values were found in the rms map.
        Updated installation instructions.

    2012/10/12 - Version 1.4.5

    2012/10/12 - Added option (incl_empty) to include empty islands (that
        have no un-flagged Gaussians) in output catalogs. Any such empty
        islands are given negative source IDs and positions given by the
        location of the peak of the island.

    2012/10/10 - Fixed a bug in Gaussian fitting that could cause a crash
        when fitting fails. Fixed a bug in parallelization that could
        cause a crash due to improper concatenation of result lists.

    2012/10/09 - Version 1.4.4

    2012/10/09 - Improved logging. Added a warning when one or more islands
        are not fit properly (i.e., no valid, unflagged Gaussians were
        fit). Fixed a bug in parallelization of Gaussian fitting that
        could cause a crash due to improper mapping of island lists to
        processes.

    2012/10/05 - Added code to handle images with no unblanked pixels.
        Improved fitting robustness.

    2012/10/04 - Version 1.4.3

    2012/10/04 - Fixed a bug in the mean map calculation that caused mean
        maps with constant values (i.e., non-2D maps) to have values of
        0.0 Jy/beam unless mean_map = 'const' was explicitly specified.
        Fixed a bug in Gaussian fitting that could cause an island to be
        skipped.

    2012/10/02 - Fixed a bug in the PSF vary module that resulted in
        incorrect PSF generators being used. Added an option to smooth
        the resulting PSF images (psf_smooth). Parallelized the PSF
        interpolation and smoothing steps. Improved PSF vary documentation.

    2012/09/25 - Version 1.4.2

    2012/09/25 - Dramatically reduced the time required to identify valid
        wavelet islands.

    2012/09/21 - Fixed bug that resulted in output FITS gaul tables being
        improperly sorted. Fixed cosmetic bug in the statusbar that could
        sometimes cause improper formatting. Added example of SAMP usage
        to the documentation.

    2012/09/20 - Version 1.4.1

    2012/09/20 - Fixed a bug in the wavelet module that caused a crash when
        no Gaussians were fit to the ch0 image.

    2012/09/19 - Added option (broadcast) to show_fit task to send
    	coordinates and row highlight request to a SAMP hub when a Gaussian
    	is clicked. Fixed bug in aperture flux masking that sometimes caused
    	the mask to be the wrong shape.

    2012/09/18 - Added option to send images and catalogs to a SAMP hub
        (activated by setting outfile = 'SAMP' in the export_image and
        write_catalog tasks).

    2012/09/13 - Improved speed of plotting when images are large and in
        mean/rms map generation. Fixed bug that caused residual image
        statistics to fail when NaNs are present.

    2012/09/11 - Version 1.4.0

    2012/09/11 - Parallelized Gaussian fitting, shapelet decomposition,
        validation of wavelet islands, and mean/rms map generation.
        The number of cores to be used can be specified with the ncores
        option (default is to use up to 8). Fixed bug in SED plotting in
        the show_fit task.

    2012/08/29 - Fixed incorrect terminal size in parameter listing. Added
        logging of non-default input parameters and internally derived
        parameters.

    2012/08/22 - Version 1.3.2

    2012/08/22 - Fixed a bug that caused the user-specified rms_box to be
        ignored. Added an option to enable the Monte Carlo error estimation
        for 'M'-type sources (the do_mc_errors option), which is now
        disabled by default.

    2012/07/11 - Version 1.3.1

    2012/07/11 - Cleaned up unused options.

    2012/07/10 - Fixed a bug that caused a segfault during Gaussian
        fitting. Fixed a bug that caused a crash when a detection image
        is used.

    2012/07/05 - Fixed a bug that caused images written when output_all =
        True to be transposed. Added frequency information to all output
        images. Improved fitting robustness to prevent rare cases in
        which no valid Gaussians could be fit to an island. Modified the
        island-finding routine to handle NaNs properly.

    2012/07/03 - Version 1.3

    2012/07/03 - Fixed a bug in calculation of the positional errors of
        Gaussians. If interactive=True and image is large (> 4096 pixels),
        display is limited to 'ch0_islands' only; otherwise, show_fit()
        is very slow. Tweaked show_fit() to better display a single image.

    2012/07/02 - Adjusted rms_box algorithm to check for negative rms
        values (due to interpolation with cubic spline). If negative
        values are found, either the box size is increased or the
        interpolation is done with order=1 (bilinear) instead.

    2012/06/28 - Output now includes the residual image produced by
        using only wavelet Gaussians (if any) when atrous_do=True and
        output_all=True. Improved organization of files when
        output_all=True. Added logging of simple statistics (mean,
        std. dev, skew, and kurtosis) of the residual images.

    2012/06/22 - Included image rotation (if any) in beam definition.
        Rotation angle can vary across the image (defined by image WCS).

    2012/06/19 - Changed exception handling to raise exceptions when
        the interactive shell is not being used. Fixed bug that
        caused a crash when using show_fit() when no islands were
        found.

    2012/06/15 - Added Sagecal output format for Gaussian catalogs.

    2012/06/14 - Added check for newer versions of the PyBDSM
        software tar.gz file available on ftp.strw.leidenuniv.nl.

    2012/06/13 - Added total island flux (from sum of pixels) to
        "gaul" and "srl" catalogs.

    2012/06/06 - Version 1.2

    2012/06/06 - Added option to calculate fluxes within a specified
        aperture radius in pixels (set with the "aperture" option).
        Aperture fluxes, if measured, are output in the 'srl' catalogs.
        Changed code that determines terminal width to be more robust.

    2012/05/07 - Removed dependencies on matplotlib -- if matplotlib is
    	not available, plotting is disabled. Corrected inconsistencies,
    	spelling mistakes, etc. in help text and documentation. Cleaned
    	up unneeded modules and files.

    2012/05/02 - Added option to output flux densities for every channel
    	found by the spectral index module. Added option to spectral index
    	module to allow use of flux densities that do not meet the desired
    	SNR. Changed flag_maxsnr criterion to also flag if the peak flux
    	density per beam of the Gaussian exceeds the value at its center.
    	Removed incl_wavelet option.

    2012/04/20 - Promoted the adaptive_rms_box parameter to the main options
    	listing and added the rms_box_bright option so that the user can
    	specify either (or both) of the rms_boxes. Fixed bug in wavelet
    	module so that invalid Gaussians (i.e., those that lie outside of
    	islands in the ch0 image) are not used when making the residual
    	images at each scale. Improved speed of Gaussian fitting to wavelet
    	images. Fixed bug that resulted in pixels found to be outside the
    	universe (check is enabled with the check_outsideuniv option) not
    	being masked properly.

    2012/04/17 - Fixed bug in psf_vary module that resulted in PSF major and
    	minor axis maps in terms of sigma instead of FWHM. Added option
    	(psf_stype_only) to allow PSF fitting to non- S-type sources
    	(useful if sources are very distorted).

    2012/04/12 - Fixed bug in adaptive scaling code that could cause
    	incorrect small-scale rms_box size. Added a parameter
    	(adaptive_thresh) that controls the minimum threshold for sources
    	used to set the small-scale rms_box size.

    2012/04/02 - Implemented an adaptive scaling scheme for the rms_box
    	parameter that shrinks the box size near bright sources and expands
    	it far from them (enabled with the adaptive_rms_box option when
    	rms_box=None). This scheme generally results in improved rms and
    	mean maps when both strong artifacts and extended sources are
    	present. Fixed bug that prevented plotting of results during wavelet
    	decomposition when interactive = True.

    2012/03/29 - Fixed bug in wavelet module that could cause incorrect
    	associations of Gaussians. Fixed bug in show_fit that displayed
    	incorrect model and residual images when wavelets were used.

    2012/03/28 - Version 1.1

    2012/03/28 - Fixed bug that caused mask to be ignored when determining
    	whether variations in rms and mean maps is significant. Fixed bug
    	that caused internally derived rms_box value to be ignored.

    2012/03/27 - Modified calculation of rms_box parameter (when rms_box
    	option is None) to work better with fields composed mainly of point
    	sources when strong artifacts are present. Tweaked flagging on FWHM
    	to prevent over-flagging of Gaussians in small islands. Changed
    	wavelet module to flag Gaussians whose centers fall outside of
    	islands found in the original image and removed atrous_orig_isl
    	option (as redundant).

    2012/03/26 - Modified fitting of large islands to adopt an iterative
    	fitting scheme that limits the number of Gaussians fit
    	simultaneously per iteration to 10. This change speeds up fitting of
    	large islands considerably. The options peak_fit and peak_maxsize
    	control whether iterative fitting is done. Added new Gaussian
    	flagging condition (flag_maxsize_fwhm) that flags Gaussians whose
    	sigma contour times factor extends beyond the island boundary. This
    	flag prevents fitting of Gaussians that extend far beyond the island
    	boundary.

    2012/03/23 - Tweaked settings that affect fitting of Gaussians to
    	improve fitting in general.

    2012/03/19 - Added output of shapelet parameters to FITS tables. Fixed
    	issue with resizing of sources in spectral index module.

    2012/03/16 - Fixed bugs in polarisation module that caused incorrect
    	polarization fractions.

    2012/03/13 - Improved plotting speed (by factor of ~ 4) in show_fit when
    	there is a large number of islands. Simplified the spectral index
    	module to make it more user friendly and stable. Added the option to
    	use a "detection" image for island detection (the detection_image
    	option); source properties are still measured from the main input
    	image.

    2012/03/01 - Fixed a bug in the polarisation module that could result in
    	incorrect flux densities. Changed logging module to suppress output
    	of ANSI color codes to the log file.

    2012/02/27 - Implemented fitting of Gaussians in polarisation module,
    	instead of simple summation of pixel values, to determine polarized
    	flux densities.

    2012/02/17 - In scripts, process_image() will now accept a dictionary of
    	parameters as input.

    2012/02/10 - Sources that appear only in Stokes Q or U (and hence not in
    	Stokes I) are now identified and included in the polarisation
    	module. This identification is done using the polarized intensity
    	(PI) image. show_fit() and export_image() were updated to allow
    	display and export of the PI image.

    2012/02/06 - Fixed bug in island splitting code that could result in
    	duplicate Gaussians.

    2012/02/02 - Improved polarisation module. Polarization quantities are
    	now calculated for Gaussians as well as sources.

    2012/01/27 - Fixed bug in psf_vary module that affected tesselation.
    	Fixed many small typos in parameter descriptions.

    2012/01/18 - Fixed a bug that resulted in incorrect coordinates when the
    	trim_box option was used with a CASA image. Added option
    	(blank_zeros) to blank pixels in the input image that are exactly
    	zero.

    2012/01/13 - Fixed minor bugs in the interactive shell and updated
    	pybdsm.py to support IPython 0.12.

    2011/12/21 - Fixed bug in gaul2srl module due to rare cases in which an
    	island has a negative rms value. Fixed a memory issue in which
    	memory was not released after using show_fit.

    2011/11/28 - Added option to have minpix_isl estimated automatically as
    	1/3 of the beam area. This estimate should help exclude false
    	islands that are much smaller than the beam. This estimate is not
    	let to fall below 6 pixels.

    2011/11/11 - Fixed bugs in source generation that would lead to masking
    	of all pixels for certain sources during moment analysis. Adjusted
    	calculation of jmax in wavelet module to use island sizes (instead
    	of image size) if opts.atrous_orig_isl is True.

    2011/11/04 - Implemented new island fitting routine (enabled with the
    	peak_fit option) that can speed up fitting of large islands. Changed
    	plotting of Gaussians in show_fit to use Ellipse artists to improve
    	plotting speed.

    2011/11/03 - Altered reading of images to correctly handle 4D cubes.
    	Fixed bug in readimage that affected filenames.

    2011/10/26 - Extended psf_vary module to include fitting of stacked PSFs
    	with Gaussians, interpolation of the resulting parameters across the
    	image, and correction of the de- convolved source sizes using the
    	interpolated PSFs. Changed plotting of Gaussians in show_fit() to
    	use the FWHM instead of sigma. Modified error calculation of M
    	sources to be more robust when sources are small. Fixed spelling of
    	"gaussian" in bbs_patches option list.

    2011/10/24 - Many small bug fixes to the psf_vary module. Fixed use of
    	input directory so that input files not in the current directory are
    	handled correctly.

    2011/10/14 - Added residual rms and mean values to sources and source
    	list catalogs. These values can be compared to background rms and
    	mean values as a quick check of fit quality.

    2011/10/13 - Modified deconvolution to allow 1-D Gaussians and sources.
    	Added FREQ0, EQUINOX, INIMAGE keywords to output fits catalogs.
    	Fixed bug in source position angles. Adjusted column names of output
    	catalogs slightly to be more descriptive.

    2011/10/12 - Added errors to source properties (using a Monte Carlo
    	method for M sources). Fixed bug in output column names.

    2011/10/11 - Tweaked autocomplete to support IPython shell commands
    	(e.g., "!more file.txt"). Fixed bug in gaul2srl that resulted in
    	some very nearby Gaussians being placed into different sources.
    	Added group_tol option so that user can adjust the tolerance of how
    	Gaussians are grouped into sources.

    2011/10/05 - Added output of source lists. Changed name of write_gaul
    	method to write_catalog (more general).

    2011/10/04 - Added option to force source grouping by island
    	(group_by_isl). Added saving of parameters to a PyBDSM save file to
    	Op_output.

    2011/09/21 - Fixed issue with shapelet centering failing: it now falls
    	back to simple moment when this happens. Fixed issue with
    	plotresults when shapelets are fit.

    2011/09/14 - Placed output column names and units in TC properties of
    	Gaussians. This allows easy standardization of the column names and
    	units.

    2011/09/13 - Fixes to trim_box and resetting of Image objects in
    	interface.process(). Changed thr1 --> thr2 in fit_iter in
    	guasfit.py, as bright sources are often "overfit" when using thr1,
    	leading to large negative residuals. Restricted fitting of Gaussians
    	to wavelet images to be only in islands found in the original image
    	if opts.atrous_orig_isl is True.

    2011/09/08 - Version 1.0

    2011/09/08 - Versioning system changed to use _version.py.

    """
    pass


def serialize():
    """
        Получить сериализованное значение атрибута.

        @return: сериализованное значение атрибута
        """


def dB2Mag(dBnum):
    """Takes in number in dB, returns magnitude = 10^(dB/20)"""
    return 10 ** (dBnum / 20.0)


@classmethod
def _v_codecs(cls):
    """Returns a list of supported :term:`VFE` string codecs.

        :returns: supported string codecs
        :rtype:   (bytes,)

        """
    return b'utf8', b'utf16'


def _readlines(fname):
    """Read all lines from file."""
    with open(fname, 'r') as fobj:
        return fobj.readlines()


def p_repeat_stmt(p):
    """repeat_stmt : REPEAT suite"""
    p[0] = ['REPEAT', p[2]]


def match(sample, lookup, threshold):
    """returns list of matches for items in sample or None if num matches below threshold"""
    cnt = sample.count()
    bad_cnt, matches = 0, []
    for x in sample:
        if isinstance(x, str):
            x = x.strip().lower()
        match = lookup(x)
        matches.append(match)
        if not match:
            bad_cnt += 1
            if bad_cnt / cnt > 1 - threshold:
                return
    return matches


def str2bin(s):
    """
    String to binary.
    """
    ret = []
    for c in s:
        ret.append(bin(ord(c))[2:].zfill(8))
    return ''.join(ret)


@staticmethod
def _check_name(value=None):
    """Check the name provided is valid"""
    if value in ('', None):
        raise ValueError('Name cannot be none, blank, or empty string.')
    if not isinstance(value, str):
        raise TypeError('Name must be a string')


def create_software_id(regid, unique_id):
    """
    Create a Software-ID by joining the Regid and the Unique-ID with a double underscore.

    Args:
        regid (str):
            The Regid string.
        unique_id (str):
            The Unique-ID string.

    Returns:
        The Software-ID string.

    """
    return '{regid}__{unique_id}'.format(regid=regid, unique_id=unique_id)


def p_loop(p):
    """loop : WHILE LPAREN expr RPAREN LBRACE statement_list RBRACE"""
    p[0] = 'loop', p[3], p[6]


def serialize_serializable(obj, spec, ctx):
    """ Serialize any class that defines a ``serialize`` method. """
    return obj.serafin_serialize(spec, ctx)


def var_to_dict(standard_name, data, units, long_name):
    """
    Convert variable information to a dictionary.
    """
    d = {}
    d['data'] = data[:]
    d['units'] = units
    d['long_name'] = long_name
    d['standard_name'] = standard_name
    return d


@staticmethod
def _get_index_parameter_text(operation, name, description):
    """
        Get a formatted string for logging document index parameters.

        :param dict operation: Dictionary containing the index operation
            parameters.
        :param str name: Name of the parameter to retrieve.
        :param str description: Text description for the parameter.
        :return: Formatted string for logging.
        :rtype: str
        """
    value = operation.get(name)
    return ', {}: {}'.format(description, value if value else '<None>')


def advanced_join(iterator, newline=False):
    """
    Used to join inner html elements
    together with a new line if True
    """
    if newline == True:
        spacer = '\n'
    else:
        spacer = ''
    if len(iterator) == 1:
        return str(iterator[0])
    joined = ''
    for i in iterator:
        joined += spacer + str(i)
    return joined


def filter_out_hydrogens(mol):
    """Get indices for non-hydrogen atoms.

    Parameters
    ----------
    mol : rdkit.Chem.rdchem.Mol
        RDKit molecule instance.

    Returns
    -------
    indices_left : list of int
        Indices of non-hydrogen atoms.
    """
    indices_left = []
    for i, atom in enumerate(mol.GetAtoms()):
        atomic_num = atom.GetAtomicNum()
        if atomic_num != 1:
            indices_left.append(i)
    return indices_left


def df_query_with_ratio(df_in, query, ratio_name='ratio'):
    """
    This function calls the .query() method on a DataFrame
    and additionally computes the ratio of resulting rows
    over the original number of rows.

    The result is a tuple with the filtered dataframe as first
    element and the filter ratio as second element.
    """
    df_out = df_in.query(query)
    ratio = df_out.shape[0] / df_in.shape[0]
    print('{} = {:.2f} %'.format(ratio_name, 100 * ratio))
    return df_out, ratio


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

    The ".dev0" means dirty.

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


def shorten(s, width=78):
    """
  Helper method to shorten string (to 78 chars, terminal width)
  for pretty-printing.

  >>> print(shorten('abcdefghijklmnopqrstuvwxyz'))  # not 78
  abcdefghijklmnopqrstuvwxyz

  >>> print(shorten('abcdefghijklmnopqrstuvwxyz'*10))
  abcdefghijklmnopqrstuvwxyzabcdefghijkl...pqrstuvwxyzabcdefghijklmnopqrstuvwxyz

  """
    s = str(s)
    return s if len(s) < width else s[0:width / 2 - 1] + '...' + s[len(s) -
        width / 2 + 2:]


@staticmethod
def get_new(klass, attrs):
    """
        Return a new instance of klass.

        :param klass: The class to create a new instance of.
        :type klass: :class:
        :param attrs: The attributes to set for this new instance.
        :type attrs: dict
        :returns: new instance of klass
        """
    n = klass(**attrs)
    n._new = False
    n._changed = []
    return n


def round(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise rounded value to the nearest integer of the input.

    Example::

       round([-1.5, 1.5, -1.9, 1.9, 2.1]) = [-2.,  2., -2.,  2.,  2.]

    The storage type of ``round`` output depends upon the input storage type:

      - round(default) = default
      - round(row_sparse) = row_sparse
      - round(csr) = csr

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

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

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

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


@staticmethod
def clean_object(metadata, analysistype):
    """
        Remove certain attributes from the object; they take up too much room on the .json report
        :param metadata: Metadata object
        :param analysistype: Current analysis type
        """
    for sample in metadata:
        try:
            delattr(sample[analysistype], 'targetnames')
        except AttributeError:
            pass
        try:
            delattr(sample[analysistype], 'targets')
        except AttributeError:
            pass
        try:
            delattr(sample[analysistype], 'dnaseq')
        except AttributeError:
            pass
        try:
            delattr(sample[analysistype], 'protseq')
        except AttributeError:
            pass


@staticmethod
def count(timeseries):
    """Extract good_count, bad_count tuple from Stackdriver Monitoring API
        response.

        Args:
            timeseries (list): List of timeseries objects.

        Returns:
            tuple: A tuple (good_event_count, bad_event_count).
        """
    good_event_count, bad_event_count = 0, 0
    for timeserie in timeseries:
        event_type = timeserie.metric.labels['event_type']
        value = timeserie.points[0].value.double_value
        if event_type == 'bad':
            bad_event_count = value
        elif event_type == 'good':
            good_event_count = value
    return good_event_count, bad_event_count


def dos_splitext(dos_name):
    """Return trunk and extension excluding the dot."""
    assert isinstance(dos_name, bytes), type(dos_name)
    elements = dos_name.split(b'.', 1)
    if len(elements) == 1:
        trunk, ext = elements[0], b''
    else:
        trunk, ext = elements
    return trunk, ext


def cancel_url():
    """ Returns the url to be redirected to after cancellation
        """


@classmethod
def write_cache(cls, data, **kwargs):
    """Écrit les données dans le cache (qui est sensé exister).

        L'argument `kwargs` est le même que celui décrit dans la classe :class:`Cache`.
        """
    raise NotImplementedError()


@staticmethod
def _report_specified_fields(specified_fields, nrows, nsample):
    """Transform the data objects to report objects

        Parameters
        ----------
        specified_fields : dict
            Dictionary with a `~pywhip.reporters.SpecificationErrorHandler`
            object for each field-specification combination.
        nrows : int
            Total rows of the current document working with, used to calculate
            passed rows as well
        nsample : int
            Number of samples (ordered on the number of rows) to retain for
            reporting purposes
        """
    for field, rules in specified_fields.items():
        for rule, error_report in rules.items():
            specified_fields[field][rule] = specified_fields[field][rule
                ].build_error_report(nrows, nsample)
    return specified_fields


def anomaly_dict_generator_static(static_anomalies_list):
    """Return a dict with a key None and one single anomaly from static
    anomalies list. This means that all injections using this use one
    single static anomalies list, irrespective of where they are
    injected.

    :param static_anomalies_list: List of static bad data (e.g.,
    static_anomalies.py)
    """
    anomalies = iter(static_anomalies_list)
    for a in anomalies:
        yield {None: a}


def ccm_extinction(wave, ebv, r_v=3.1):
    """
    The extinction (A_lambda) for given wavelength (or vector of wavelengths)
    from the CCM 1989 (and O'Donnell 1994) parameterization. Returns an
    array of extinction values for each wavelength in 'wave'

    INPUTS:
    wave - array of wavelengths (in Angstroms)
    ebv - colour excess E(B-V) float. If a negative ebv is supplied
          fluxes will be reddened rather than dereddened

    OPTIONAL INPUT:
    r_v - float specifying the ratio of total selective
          extinction R(V) = A(V)/E(B-V). If not specified,
          then r_v = 3.1

    OUTPUTS:
    funred - unreddened calibrated flux array, same number of
             elements as wave

    NOTES:
    1. This function was converted from the IDL Astrolib procedure
       last updated in April 1998. All notes from that function
       (provided below) are relevant to this function

    2. (From IDL:) The CCM curve shows good agreement with the Savage & Mathis (1979)
       ultraviolet curve shortward of 1400 A, but is probably
       preferable between 1200 and 1400 A.

    3. (From IDL:) Many sightlines with peculiar ultraviolet interstellar extinction
       can be represented with a CCM curve, if the proper value of
       R(V) is supplied.

    4. (From IDL:) Curve is extrapolated between 912 and 1000 A as suggested by
       Longo et al. (1989, ApJ, 339,474)

    5. (From IDL:) Use the 4 parameter calling sequence if you wish to save the
       original flux vector.

    6. (From IDL:) Valencic et al. (2004, ApJ, 616, 912) revise the ultraviolet CCM
       curve (3.3 -- 8.0 um-1).    But since their revised curve does
       not connect smoothly with longer and shorter wavelengths, it is
       not included here.

    7. For the optical/NIR transformation, the coefficients from
       O'Donnell (1994) are used

    >>> ccm_unred([1000, 2000, 3000], [1, 1, 1], 2 )
    array([9.7976e+012, 1.12064e+07, 32287.1])
    """
    import numpy as np
    scalar = not np.iterable(wave)
    if scalar:
        wave = np.array([wave], float)
    else:
        wave = np.array(wave, float)
    x = 10000.0 / wave
    npts = wave.size
    a = np.zeros(npts, float)
    b = np.zeros(npts, float)
    good = np.where((x > 0.3) & (x < 1.1))
    a[good] = 0.574 * x[good] ** 1.61
    b[good] = -0.527 * x[good] ** 1.61
    good = np.where((x >= 1.1) & (x < 3.3))
    y = x[good] - 1.82
    c1 = np.array([1.0, 0.104, -0.609, 0.701, 1.137, -1.718, -0.827, 1.647,
        -0.505])
    c2 = np.array([0.0, 1.952, 2.908, -3.989, -7.985, 11.102, 5.491, -
        10.805, 3.347])
    a[good] = np.polyval(c1[::-1], y)
    b[good] = np.polyval(c2[::-1], y)
    good = np.where((x >= 3.3) & (x < 8))
    y = x[good]
    F_a = np.zeros(np.size(good), float)
    F_b = np.zeros(np.size(good), float)
    good1 = np.where(y > 5.9)
    if np.size(good1) > 0:
        y1 = y[good1] - 5.9
        F_a[good1] = -0.04473 * y1 ** 2 - 0.009779 * y1 ** 3
        F_b[good1] = 0.213 * y1 ** 2 + 0.1207 * y1 ** 3
    a[good] = 1.752 - 0.316 * y - 0.104 / ((y - 4.67) ** 2 + 0.341) + F_a
    b[good] = -3.09 + 1.825 * y + 1.206 / ((y - 4.62) ** 2 + 0.263) + F_b
    good = np.where((x >= 8) & (x <= 11))
    y = x[good] - 8.0
    c1 = [-1.073, -0.628, 0.137, -0.07]
    c2 = [13.67, 4.257, -0.42, 0.374]
    a[good] = np.polyval(c1[::-1], y)
    b[good] = np.polyval(c2[::-1], y)
    a_v = r_v * ebv
    a_lambda = a_v * (a + b / r_v)
    if scalar:
        a_lambda = a_lambda[0]
    return a_lambda


def p_language_blocks(t):
    """language_blocks : language_block
                       | language_blocks language_block"""
    if len(t) == 2:
        t[0] = [t[1]]
    else:
        t[0] = t[1] + [t[2]]


def keyof(map, obj):
    """find key that obj is stored at in map by exhaustive search"""
    for k in map:
        if map[k] is obj:
            return k
    return None


def IvyGetApplicationName(client):
    """
    Equivalent to ``client.agent_name``

    :param client: an :py:class:`ivy.ivy.IvyClient` object, as returned by
      :py:func:`IvyGetApplication()`
    """
    return client.agent_name


def map(function, dictionary, recursive=True):
    """

    Apply function to every value of dictionary and return a dictionary of the
    results.
    """
    result = {}
    if function == None:
        function = lambda x: x
    for key in dictionary:
        value = dictionary[key]
        if recursive and type(value) == dict:
            value = map(function, value)
        key, value = function(key, value)
        result[key] = value
    return result