def get_election_summary(election, request, url=None):
    """ Returns some basic informations about the given election as a JSON
    seriazable dict. """
    last_modified = election.last_modified
    if last_modified:
        last_modified = last_modified.isoformat()
    return {'completed': election.completed, 'date': election.date.
        isoformat(), 'domain': election.domain, 'elected': election.
        elected_candidates, 'last_modified': last_modified, 'progress': {
        'counted': election.progress[0] or 0, 'total': election.progress[1] or
        0}, 'title': election.title_translations, 'type': 'election', 'url':
        url or request.link(election)}


def daily_usage_df(df, agg_functions, client_fields=client_fields):
    """
    generic function for rolling up experiment pings into a
    (client_id, branch, activity date) level
        note: the client_fields above are assumed to be provided by default
        note: you have to provide the agg functions and decide the roll up
              logic inside them individually
    """
    if client_fields:
        agg_functions = client_fields + agg_functions
    return df.groupby(['client_id', 'branch', 'activity_dt']).agg(*
        agg_functions)


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        Non dynamic discovery of type for:
            * data.renderedFields.description

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
         {
            "dynamic":true,
            "properties": {
                "data": {
                    "properties": {
                        "renderedFields": {
                            "dynamic":false,
                            "properties": {}
                        },
                        "operations": {
                            "dynamic":false,
                            "properties": {}
                        },
                        "fields": {
                            "dynamic":true,
                            "properties": {
                                "description": {
                                    "type": "text",
                                    "index": true
                                },
                                "environment": {
                                    "type": "text",
                                    "index": true
                                }
                            }
                        },
                        "changelog": {
                            "properties": {
                                "histories": {
                                    "dynamic":false,
                                    "properties": {}
                                }
                            }
                        },
                        "comments_data": {
                            "properties": {
                                "body": {
                                    "type": "text",
                                    "index": true
                                }
                            }
                        }
                    }
                }
            }
        }
        """
    return {'items': mapping}


def set_all_settings(settings):
    """Sets a value (the default one if not modified) for each setting.
    This allow settings to be visible in dconf-editor even if the schema
    is not installed.
    """
    for key in settings.list_keys():
        settings.set_value(key, settings.get_value(key))


def isOrExtends(other):
    """Test whether the specification is or extends another
        """


def gfftagstat_parser(subparsers):
    """
    Parser for the gfftagstat tool.
    """
    parser = subparsers.add_parser('gfftagstat', help=
        'get statistics on attribute tags of a GFF3 file', description=
        'Get statistics on attribure tags of a GFF file.')
    parser.add_argument('gff_file', help='a GFF3 file')
    parser.add_argument('-s', '--source', default=None, help=
        'filter GFF3 features by the specified source')
    parser.add_argument('-t', '--type', default=None, help=
        'filter GFF3 features by the specified type')


def beautify_fill(angle_limit: float=3.14159):
    """Rearrange some faces to try to get less degenerated geometry

    :param angle_limit: Max Angle, Angle limit
    :type angle_limit: float
    """
    pass


def wsz_registry():
    """
    Check Windows registry for 7-Zip executable location.
    """
    import winreg
    hk7z = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
    path = winreg.QueryValueEx(hk7z, 'Path')
    return path


def is_sequence(x):
    """ Returns whether x is a sequence (tuple, list).

    :param x: a value to check
    :returns: (boolean)

    """
    return not hasattr(x, 'strip') and hasattr(x, '__getitem__') or hasattr(x,
        '__iter__')


@classmethod
def get_cachevault(cls, session, server_key, controller):
    """Cachevault details
        Args:
            session:  database session
            server_key(int): key of the server cachevault belongs to
            controller(int): controller num
        Returns:
            dict: information about cachevault
        """
    query = []
    query.extend([
        'MATCH (:Asset {{ key: {} }})-[:HAS_CONTROLLER]->(ctrl:Controller {{ controllerNum: {} }})'
        .format(server_key, controller),
        'MATCH (ctr)-[:HAS_CACHEVAULT]->(cv:CacheVault)', 'RETURN cv'])
    results = session.run('\n'.join(query))
    record = results.single()
    return dict(record.get('cv')) if record else None


def new():
    """Create a new text data block

    """
    pass


def time_delta_2_hours(time_delta):
    """
    >>> time_delta_2_hours(datetime.timedelta(0, 1800))  # 1800 seconds = 30 minutes
    0.5
    """
    return time_delta.seconds / float(3600)


def predecessor_of(element, iterable, pairwise=pairwise):
    """Returns the predecessor of `element` in `iterable`"""
    for l, r in pairwise(iterable):
        if r == element:
            return l
    raise IndexError


def get_report(time, report, rdesc):
    """
    Translate the given report to a human readable format.
    """
    output = f'{time:>10s} '
    indent_2nd_line = len(output)
    output += rdesc.format_report(report)
    try:
        first_row = output.split('\n')[0]
    except IndexError:
        pass
    else:
        try:
            slash = first_row.index('/')
        except ValueError:
            indent_2nd_line = 2
        else:
            indent_2nd_line = slash - 1
    indent = f"\n{' ' * indent_2nd_line}"
    return indent.join(output.split('\n'))


@classmethod
def init(cls, *args, **kwargs):
    """
        Initialize a RadarlyAPI and set it as default api. The default API is
        the one that will be used each time you made a request if no API is
        passed in the parameter.

        Args:
            client_id (str): client_id you want to use to access data
            client_secret (str): secret token given by Linkfluence.
            autorefresh (bool, optional): whether or not refresh automatically
                the acces_token when it's expired.
            scope (list[str]): list of scope
            timeout (float): timeout for the requests
            proxies (dict): proxies to use for the requests.
        """
    api = cls(*args, **kwargs)
    cls.set_default_api(api)
    return api


def copy_db_cluster_snapshot(SourceDBClusterSnapshotIdentifier=None,
    TargetDBClusterSnapshotIdentifier=None, KmsKeyId=None, PreSignedUrl=
    None, CopyTags=None, Tags=None, SourceRegion=None):
    """
    Copies a snapshot of a DB cluster.
    To copy a DB cluster snapshot from a shared manual DB cluster snapshot, SourceDBClusterSnapshotIdentifier must be the Amazon Resource Name (ARN) of the shared DB cluster snapshot.
    You can copy an encrypted DB cluster snapshot from another AWS region. In that case, the region where you call the CopyDBClusterSnapshot action is the destination region for the encrypted DB cluster snapshot to be copied to. To copy an encrypted DB cluster snapshot from another region, you must provide the following values:
    To learn how to generate a Signature Version 4 signed request, see Authenticating Requests: Using Query Parameters (AWS Signature Version 4) and Signature Version 4 Signing Process .
    To cancel the copy operation once it is in progress, delete the target DB cluster snapshot identified by TargetDBClusterSnapshotIdentifier while that DB cluster snapshot is in "copying" status.
    For more information on copying encrypted DB cluster snapshots from one region to another, see Copying a DB Cluster Snapshot in the Same Account, Either in the Same Region or Across Regions in the Amazon RDS User Guide.
    For more information on Amazon Aurora, see Aurora on Amazon RDS in the Amazon RDS User Guide.
    See also: AWS API Documentation

    Examples
    The following example copies an automated snapshot of a DB cluster to a new DB cluster snapshot.
    Expected Output:

    :example: response = client.copy_db_cluster_snapshot(
        SourceDBClusterSnapshotIdentifier='string',
        TargetDBClusterSnapshotIdentifier='string',
        KmsKeyId='string',
        CopyTags=True|False,
        Tags=[
            {
                'Key': 'string',
                'Value': 'string'
            },
        ],
        SourceRegion='string'
    )

    :type SourceDBClusterSnapshotIdentifier: string
    :param SourceDBClusterSnapshotIdentifier: [REQUIRED]
            The identifier of the DB cluster snapshot to copy. This parameter is not case-sensitive.
            You cannot copy an encrypted, shared DB cluster snapshot from one AWS region to another.
            Constraints:
            Must contain from 1 to 63 alphanumeric characters or hyphens.
            First character must be a letter.
            Cannot end with a hyphen or contain two consecutive hyphens.
            Must specify a valid system snapshot in the 'available' state.
            If the source snapshot is in the same region as the copy, specify a valid DB snapshot identifier.
            If the source snapshot is in a different region than the copy, specify a valid DB cluster snapshot ARN. For more information, go to Copying a DB Snapshot or DB Cluster Snapshot .
            Example: my-cluster-snapshot1

    :type TargetDBClusterSnapshotIdentifier: string
    :param TargetDBClusterSnapshotIdentifier: [REQUIRED]
            The identifier of the new DB cluster snapshot to create from the source DB cluster snapshot. This parameter is not case-sensitive.
            Constraints:
            Must contain from 1 to 63 alphanumeric characters or hyphens.
            First character must be a letter.
            Cannot end with a hyphen or contain two consecutive hyphens.
            Example: my-cluster-snapshot2

    :type KmsKeyId: string
    :param KmsKeyId: The AWS KMS key ID for an encrypted DB cluster snapshot. The KMS key ID is the Amazon Resource Name (ARN), KMS key identifier, or the KMS key alias for the KMS encryption key.
            If you copy an unencrypted DB cluster snapshot and specify a value for the KmsKeyId parameter, Amazon RDS encrypts the target DB cluster snapshot using the specified KMS encryption key.
            If you copy an encrypted DB cluster snapshot from your AWS account, you can specify a value for KmsKeyId to encrypt the copy with a new KMS encryption key. If you don't specify a value for KmsKeyId , then the copy of the DB cluster snapshot is encrypted with the same KMS key as the source DB cluster snapshot.
            If you copy an encrypted DB cluster snapshot that is shared from another AWS account, then you must specify a value for KmsKeyId .
            To copy an encrypted DB cluster snapshot to another region, you must set KmsKeyId to the KMS key ID you want to use to encrypt the copy of the DB cluster snapshot in the destination region. KMS encryption keys are specific to the region that they are created in, and you cannot use encryption keys from one region in another region.

    :type PreSignedUrl: string
    :param PreSignedUrl: The URL that contains a Signature Version 4 signed request for the CopyDBClusterSnapshot API action in the AWS region that contains the source DB cluster snapshot to copy. The PreSignedUrl parameter must be used when copying an encrypted DB cluster snapshot from another AWS region.
            The pre-signed URL must be a valid request for the CopyDBSClusterSnapshot API action that can be executed in the source region that contains the encrypted DB cluster snapshot to be copied. The pre-signed URL request must contain the following parameter values:
            KmsKeyId - The KMS key identifier for the key to use to encrypt the copy of the DB cluster snapshot in the destination region. This is the same identifier for both the CopyDBClusterSnapshot action that is called in the destination region, and the action contained in the pre-signed URL.
            DestinationRegion - The name of the region that the DB cluster snapshot will be created in.
            SourceDBClusterSnapshotIdentifier - The DB cluster snapshot identifier for the encrypted DB cluster snapshot to be copied. This identifier must be in the Amazon Resource Name (ARN) format for the source region. For example, if you are copying an encrypted DB cluster snapshot from the us-west-2 region, then your SourceDBClusterSnapshotIdentifier looks like the following example: arn:aws:rds:us-west-2:123456789012:cluster-snapshot:aurora-cluster1-snapshot-20161115 .
            To learn how to generate a Signature Version 4 signed request, see Authenticating Requests: Using Query Parameters (AWS Signature Version 4) and Signature Version 4 Signing Process .
            Please note that this parameter is automatically populated if it is not provided. Including this parameter is not required

    :type CopyTags: boolean
    :param CopyTags: True to copy all tags from the source DB cluster snapshot to the target DB cluster snapshot; otherwise false. The default is false.

    :type Tags: list
    :param Tags: A list of tags.
            (dict) --Metadata assigned to an Amazon RDS resource consisting of a key-value pair.
            Key (string) --A key is the required name of the tag. The string value can be from 1 to 128 Unicode characters in length and cannot be prefixed with 'aws:' or 'rds:'. The string can only contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' (Java regex: '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-]*)$').
            Value (string) --A value is the optional value of the tag. The string value can be from 1 to 256 Unicode characters in length and cannot be prefixed with 'aws:' or 'rds:'. The string can only contain only the set of Unicode letters, digits, white-space, '_', '.', '/', '=', '+', '-' (Java regex: '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-]*)$').

    :type SourceRegion: string
    :param SourceRegion: The ID of the region that contains the snapshot to be copied.

    :rtype: dict
    :return: {
        'DBClusterSnapshot': {
            'AvailabilityZones': [
                'string',
            ],
            'DBClusterSnapshotIdentifier': 'string',
            'DBClusterIdentifier': 'string',
            'SnapshotCreateTime': datetime(2015, 1, 1),
            'Engine': 'string',
            'AllocatedStorage': 123,
            'Status': 'string',
            'Port': 123,
            'VpcId': 'string',
            'ClusterCreateTime': datetime(2015, 1, 1),
            'MasterUsername': 'string',
            'EngineVersion': 'string',
            'LicenseModel': 'string',
            'SnapshotType': 'string',
            'PercentProgress': 123,
            'StorageEncrypted': True|False,
            'KmsKeyId': 'string',
            'DBClusterSnapshotArn': 'string',
            'SourceDBClusterSnapshotArn': 'string',
            'IAMDatabaseAuthenticationEnabled': True|False
        }
    }

    :returns:
    TargetDBClusterSnapshotIdentifier - The identifier for the new copy of the DB cluster snapshot in the destination region.
    SourceDBClusterSnapshotIdentifier - The DB cluster snapshot identifier for the encrypted DB cluster snapshot to be copied. This identifier must be in the ARN format for the source region and is the same value as the SourceDBClusterSnapshotIdentifier in the pre-signed URL.

    """
    pass


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

        :param LoginSuccessDetails val:
        :rtype: EventDetails
        """
    return cls('login_success_details', val)


def invalidate_cache():
    """
        Invalidate current cache
        """


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

        :param SecondaryEmailDeletedType val:
        :rtype: EventType
        """
    return cls('secondary_email_deleted', val)


def pack_table(pbest, abest, iers, rec, param_columns, amp_column,
    ier_column=None):
    """
    Pack fitting parameters into table

    Parameters
    ----------
    pbest : list
        List of best-fit parameters.  See :py:func:`fit_NDregion` for format.
    abest : list
        List of best-fit amplitudes.
    iers : list
        List of fitting error return values.
    rec : recarray
        Records array (table) to save fitting parameters into. Updated with
        fitting parameter in place.
    param_columns : list
        List of parameter columns in rec. Format is the same as pbest.
    amp_columns : str
        Name of amplitude column in rec.
    ier_column : str or None, optional
        Name of column in rec to save iers to. None will not record this in the
        table.

    """
    rec[amp_column] = abest
    for dbest, dcolumns in zip(zip(*pbest), param_columns):
        for p, c in zip(zip(*dbest), dcolumns):
            rec[c] = p
    if ier_column is not None:
        rec[ier_column] = iers


@classmethod
def _give_report_month(cls, report):
    """Return month from report name."""
    report_month = report.split(' ')[0].split('-')[1]
    return report_month


@staticmethod
def get_project_root() ->str:
    """Method to get the project root directory

        Returns:
            str
        """
    return '/mnt/labbook'


def _rename_node(graph, node_id, copy_id):
    """ Rename `node_id` in `graph` to `copy_id`. """
    graph._add_node_silent(copy_id)
    graph.nodes[copy_id].update(graph.nodes[node_id])
    for nbr in graph.neighbors(node_id):
        wt = graph[node_id][nbr]['weight']
        graph.add_edge(nbr, copy_id, {'weight': wt})
    graph.remove_node(node_id)


def export_legend(legend, filename='legend.png'):
    """Export legend as seperate file
    """
    fig = legend.figure
    fig.canvas.draw()
    bbox = legend.get_window_extent().transformed(fig.dpi_scale_trans.
        inverted())
    fig.savefig(filename, dpi='figure', bbox_inches=bbox)


def _review(subs, shared):
    """Configure the `doorstop review` subparser."""
    info = 'absolve items of their unreviewed status'
    sub = subs.add_parser('review', description=info.capitalize() + '.',
        help=info, **shared)
    sub.add_argument('label', help="item UID, document prefix, or 'all'")
    group = sub.add_mutually_exclusive_group()
    group.add_argument('-i', '--item', action='store_true', help=
        "indicates the 'label' is an item UID")
    group.add_argument('-d', '--document', action='store_true', help=
        "indicates the 'label' is a document prefix")


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

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


@classmethod
def from_dbe(cls, dbe, ic_restored_in_progress=False):
    """Return an instance based on the corresponding database entry (dbe)"""
    return cls(filehandle=dbe.filehandle, ftype=dbe.ftype, mode=dbe.mode,
        nlink=dbe.nlink, mtime=dbe.mtime, ctime=dbe.ctime, atime=dbe.atime,
        size=dbe.size, uid=dbe.uid, gid=dbe.gid, dev=dbe.dev,
        first_backpointer=dbe.first_backpointer, state=dbe.state,
        source_inode_number=dbe.source_inode_number, source_path=dbe.
        source_path_bytes, reconcile_vers=dbe.reconcile_vers,
        child_dir_count=dbe.child_dir_count, pre_error_state=dbe.
        pre_error_state, ic_restored_in_progress=ic_restored_in_progress)


@classmethod
def has_archiving(cls):
    """Returns whether it supports archiving items on the fetch process.

        :returns: this backend supports items archive
        """
    return True


def is_ipxe_enabled(task):
    """Return true if ipxe is set.

    :param task: A TaskManager object
    :returns: boolean true if ``[pxe]ipxe_enabled`` is configured
              or if the task driver instance is the iPXE driver.
    """
    return 'ipxe_boot' in task.driver.boot.capabilities


@classmethod
def axesNames(cls):
    """ The names of the axes that this inspector visualizes.
            See the parent class documentation for a more detailed explanation.
        """
    return tuple(['Y', 'X'])


def one_or_more(schema: dict, unique_items: bool=True, min: int=1, max: int
    =None) ->dict:
    """
    Helper function to construct a schema that validates items matching
    `schema` or an array containing items matching `schema`.

    :param schema: The schema to use
    :param unique_items: Flag if array items should be unique
    :param min: Correlates to ``minLength`` attribute of JSON Schema array
    :param max: Correlates to ``maxLength`` attribute of JSON Schema array
    """
    multi_schema = {'type': 'array', 'items': schema, 'minItems': min,
        'uniqueItems': unique_items}
    if max:
        multi_schema['maxItems'] = max
    return {'oneOf': [multi_schema, schema]}


def _n_for_model_building_default(m):
    """truncate worst solutions for model building"""
    n = int(max((m.current_complexity + 2, m.settings.truncation_ratio * (m
        .size + 1))))
    return min((m.size, n))


def fig2bytes(fig, encode='png', dpi=None):
    """
    Convert matplotlib.figure.Figure object to image bytes.
    """
    import io
    buf = io.BytesIO()
    fig.savefig(buf, format=encode, dpi=None)
    buf.seek(0)
    img_bytes = buf.read()
    buf.close()
    return img_bytes


def _clean(txt):
    """Replace all whitespace with a single space."""
    return ' '.join(txt.split()).strip()


def get_client_by_id(clientid):
    """Returns the dict of a client configuration.
        """


def concat_environment(env1, env2):
    """ Concatenate two environments.

    1 - Check duplicated keys and concatenate their values.
    2 - Update the concatenated environment.

    Parameters
    ----------
    env1: dict (mandatory)
        First environment.
    env2: dict (mandatory)
        Second environment.

    Returns
    -------
    concat_env: dict
        Updated environment where the duplicated keys values are concatenated
        with ':'.
    """
    concat_env = env1
    for key, value in env2.items():
        if key in concat_env.keys():
            if value != concat_env[key]:
                concat_env[key] += ':' + env2[key]
        else:
            concat_env[key] = env2[key]
    return concat_env


def pt_getEngineContext(namespace):
    """Return an execution context from the expression engine."""


def format_size(size, threshold=1536):
    """Return file size as string from byte size.

    >>> format_size(1234)
    '1234 B'
    >>> format_size(12345678901)
    '11.50 GiB'

    """
    if size < threshold:
        return '%i B' % size
    for unit in ('KiB', 'MiB', 'GiB', 'TiB', 'PiB'):
        size /= 1024.0
        if size < threshold:
            return '%.2f %s' % (size, unit)


def model_query_scope_is_project(context, model):
    """Determine if a model should be scoped to a project.

    :param context: The context to check for admin and advsvc rights.
    :param model: The model to check the project_id of.
    :returns: True if the context is not admin and not advsvc and the model
        has a project_id. False otherwise.
    """
    return (not context.is_admin and hasattr(model, 'project_id')) and (not
        context.is_advsvc and hasattr(model, 'project_id'))


def map_category(output_db, scraper_id, scraper_category):
    """Get the canonical category corresponding to the
    given category in the scraper data."""
    select_sql = (
        'SELECT category FROM scraper_category_map WHERE scraper_id = ? AND scraper_category = ?'
        )
    rows = list(output_db.execute(select_sql, [scraper_id, scraper_category]))
    if rows:
        return rows[0][0]
    else:
        return None


def send(fromaddr, toaddrs, message):
    """Send an email message.

        `fromaddr` is the sender address (unicode string),

        `toaddrs` is a sequence of recipient addresses (unicode strings).

        `message` is a `Message` object from the stdlib
        `email.message` module.  If it does not contain a Message-Id
        header, one will be generated and added automatically.

        Messages are sent immediatelly.
        """


def _nval(val):
    """convert value to byte array"""
    if val < 0:
        raise ValueError
    buf = b''
    while val >> 7:
        m = val & 255 | 128
        buf += m.to_bytes(1, 'big')
        val >>= 7
    buf += val.to_bytes(1, 'big')
    return buf


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


def read_dict_text(fn):
    """
    Read a dictionary with several sections from plain text format. Section is denoted by first character being '#'.
    Returns dictionary of lists
    :param fn: filename
    :return: Dictionary with a list of lines for each section
    """
    dict = {}
    lines = []
    prevsec = ''
    with open(fn) as f:
        for x in f.readlines():
            x = x.strip()
            if x[0] == '#':
                if len(lines) > 0 and prevsec != '':
                    dict[prevsec] = lines
                    lines = []
                    prevsec = x[1:]
            else:
                lines.append(x)
    if len(lines) > 0 and prevsec != '':
        dict[prevsec] = lines
    return dict


def datetime_to_iso_8601(dt):
    """Format a datetime as an iso 8601 string - YYYY-MM-DDTHH:MM:SS with optional timezone +HH:MM."""
    if dt:
        return dt.replace(microsecond=0).isoformat()
    else:
        return None


def find_point_in_section_list(point, section_list):
    """Returns the start of the section the given point belongs to.

    The given list is assumed to contain start points of consecutive
    sections, except for the final point, assumed to be the end point of the
    last section. For example, the list [5, 8, 30, 31] is interpreted as the
    following list of sections: [5-8), [8-30), [30-31], so the points -32, 4.5,
    32 and 100 all match no section, while 5 and 7.5 match [5-8) and so for
    them the function returns 5, and 30, 30.7 and 31 all match [30-31].

    Parameters
    ---------
    point : float
        The point for which to match a section.
    section_list : sortedcontainers.SortedList
        A list of start points of consecutive sections.

    Returns
    -------
    float
        The start of the section the given point belongs to. None if no match
        was found.

    Example
    -------
    >>> from sortedcontainers import SortedList
    >>> seclist = SortedList([5, 8, 30, 31])
    >>> find_point_in_section_list(4, seclist)

    >>> find_point_in_section_list(5, seclist)
    5
    >>> find_point_in_section_list(27, seclist)
    8
    >>> find_point_in_section_list(31, seclist)
    30
    """
    if point < section_list[0] or point > section_list[-1]:
        return None
    if point in section_list:
        if point == section_list[-1]:
            return section_list[-2]
        ind = section_list.bisect(point) - 1
        if ind == 0:
            return section_list[0]
        return section_list[ind]
    try:
        ind = section_list.bisect(point)
        return section_list[ind - 1]
    except IndexError:
        return None


@staticmethod
def sortby(node_obj):
    """Sort by Data Schema item ID (which is also the name)."""
    return [-1 * node_obj.dcnt, node_obj.item_id]


def get_custom_ident(token):
    """If ``token`` is a keyword, return its name.

    Otherwise return ``None``.

    """
    if token.type == 'ident':
        return token.value


def Nu_vertical_cylinder_Touloukian_Morgan(Pr, Gr, turbulent=None):
    """Calculates Nusselt number for natural convection around a vertical
    isothermal cylinder according to the results of [1]_ correlated by [2]_, as
    presented in [3]_ and [4]_.

    .. math::
        Nu_H = 0.726 Ra_H^{0.25},\\; 2\\times 10^{8} < Ra < 4\\times 10^{10}

    .. math::
        Nu_H = 0.0674 (Gr_H Pr^{1.29})^{1/3},\\; 4\\times 10^{10} < Ra < 9\\times 10^{11}

    Parameters
    ----------
    Pr : float
        Prandtl number [-]
    Gr : float
        Grashof number [-]
    turbulent : bool or None, optional
        Whether or not to force the correlation to return the turbulent
		 result; will return the laminar regime if False; leave as None for
        automatic selection

    Returns
    -------
    Nu : float
        Nusselt number, [-]

    Notes
    -----
    Cylinder of diameters 2.75 inch, with heights of 6, 18, and 36.25 inch.
    Temperature was controlled via multiple separately controlled heating
    sections. Fluids were water and ethylene-glycol. Transition between ranges
    is not smooth. If outside of range, no warning is given. [2]_, [3]_, and
    [4]_ are in complete agreement about this formulation.

    Examples
    --------
    >>> Nu_vertical_cylinder_Touloukian_Morgan(.7, 2E10)
    249.72879961097854

    References
    ----------
    .. [1] Touloukian, Y. S, George A Hawkins, and Max Jakob. Heat Transfer by
       Free Convection from Heated Vertical Surfaces to Liquids.
       Trans. ASME 70, 13-18 (1948).
    .. [2] Morgan, V.T., The Overall Convective Heat Transfer from Smooth
       Circular Cylinders, in Advances in Heat Transfer, eds. T.F. Irvin and
       J.P. Hartnett, V 11, 199-264, 1975.
    .. [3] Popiel, Czeslaw O. "Free Convection Heat Transfer from Vertical
       Slender Cylinders: A Review." Heat Transfer Engineering 29, no. 6
       (June 1, 2008): 521-36. doi:10.1080/01457630801891557.
    .. [4] Boetcher, Sandra K. S. "Natural Convection Heat Transfer From
       Vertical Cylinders." In Natural Convection from Circular Cylinders,
       23-42. Springer, 2014.
    """
    Ra = Pr * Gr
    if turbulent or Ra > 40000000000.0 and turbulent is None:
        return 0.0674 * (Gr * Pr ** 1.29) ** (1 / 3.0)
    else:
        return 0.726 * Ra ** 0.25


def _proc(tr, sampling_rate=10):
    """
    Basic processing including downsampling, detrend, and demean.

    :param tr: raw trace
    :param sampling_rate:
    :return tr: trace after processing
    """
    tr2 = tr.copy()
    tr2.interpolate(sampling_rate)
    tr2.detrend(type='linear')
    tr2.detrend(type='demean')
    return tr2


@classmethod
def load_from_serialized(cls, data):
    """
        Create a new instance loading the values from JSON-serialised data as a string

        :param data: The string with the JSON-serialised data to load from
        """
    from aiida.common import json
    return cls.load_from_dict(json.loads(data))


def mate_same(aln):
    """ Check if mate has same start position

    Args:
        aln (:obj:`pysam.AlignedSegment`): An aligned segment

    Returns:
        bool: True if alignment's mate has same start position, False otherwise

    """
    return (aln.next_reference_id == aln.reference_id and aln.
        next_reference_start == aln.reference_start)


def plotRoadUsers(objects, colors):
    """Colors is a PlottingPropertyValues instance"""
    from matplotlib.pyplot import figure, axis
    figure()
    for obj in objects:
        obj.plot(colors.get(obj.userType))
    axis('equal')


def _highlight(value):
    """
    highlight 'type validator'.
    """
    if value not in ('html', 'ansi'):
        raise ValueError('Highlight must be "html" or "ansi", got {0}'.
            format(value))
    return value


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 construct(instance, tasks):
    """Recursively construct model evaluations report."""
    if hasattr(instance, 'task'):
        taskevals = instance.task.evaluations
        evaluations = {'Component': instance.component, 'Class': instance.
            name, 'tasks': tasks, 'sizes': taskevals[0]['cumulative'],
            'cumulative': tasks * taskevals[0]['cumulative']}
        return [evaluations] + taskevals
    else:
        evaluations = {'Component': instance.component, 'Class': instance.
            name, 'tasks': tasks, 'sizes': 1, 'cumulative': tasks}
        return [evaluations]


def getid(obj):
    """Return id if argument is a Resource.

    Abstracts the common pattern of allowing both an object or an object's ID
    (UUID) as a parameter when dealing with relationships.
    """
    try:
        if obj.uuid:
            return obj.uuid
    except AttributeError:
        pass
    try:
        return obj.id
    except AttributeError:
        return obj


def _print_if(condition, *args):
    """Print only if condition is True."""
    if condition:
        print(*args)


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

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

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


def VWAP(df, open='Open', high='High', low='Low', close='Close', volume=
    'Volume'):
    """
    Volume Weighted Average Price
    Returns: list of floats = jhta.VWAP(df, open='Open', high='High', low='Low', close='Close', volume='Volume')
    Source: book: An Introduction to Algorithmic Trading
    """
    vwap_list = []
    pvs = 0.0
    for i in range(len(df[close])):
        o = df[open][i]
        h = df[high][i]
        l = df[low][i]
        c = df[close][i]
        v = df[volume][i]
        pvs += sum([o, h, l, c]) / 4 * v
        vwap = pvs / sum(df[volume][0:i + 1])
        vwap_list.append(vwap)
    return vwap_list


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

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

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

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

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

    Defined in src/operator/tensor/elemwise_sum.cc:L155

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

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

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


@classmethod
def from_fileobj(cls, fileobj, check=True):
    """Read the struct from a file object."""
    if fileobj.name.endswith('.mat'):
        return cls.from_binary(fileobj)
    return cls.from_string(fileobj.read())


def shortest_path_pick():
    """Select shortest path between two selections

    """
    pass


def _slice_src(src, like, matching_dims):
    """
    Make sure src matches dst in dims that do not have to be regridded
    """
    slices = {}
    for dim in matching_dims:
        x0 = like[dim][0]
        x1 = like[dim][-1]
        slices[dim] = slice(x0, x1)
    return src.sel(slices).compute()


def create(netParams=None, simConfig=None, output=False):
    """ Sequence of commands to create network """
    from .. import sim
    import __main__ as top
    if not netParams:
        netParams = top.netParams
    if not simConfig:
        simConfig = top.simConfig
    sim.initialize(netParams, simConfig)
    pops = sim.net.createPops()
    cells = sim.net.createCells()
    conns = sim.net.connectCells()
    stims = sim.net.addStims()
    rxd = sim.net.addRxD()
    simData = sim.setupRecording()
    if output:
        return pops, cells, conns, rxd, stims, simData


def snip_line(line, max_width, split_at):
    """Shorten a line to a maximum length."""
    if len(line) < max_width:
        return line
    return line[:split_at] + ' … ' + line[-(max_width - split_at - 3):]


def identityfunc(arg, *args, **kwargs):
    """Single argument identity function.

    >>> identityfunc('arg')
    'arg'

    """
    return arg


def convert_to_codec_key(value):
    """
    Normalize code key value (encoding codecs must be lower case and must
    not contain any dashes).

    :param value: value to convert.
    """
    if not value:
        value = 'UTF-8'
    converted = value.replace('-', '_').lower()
    all_aliases = {'ascii': ['us_ascii', 'us', 'ansi_x3.4_1968', 'cp367',
        'csascii', 'ibm367', 'iso_ir_6', 'iso646_us', 'iso_646.irv:1991'],
        'utf-7': ['csunicode11utf7', 'unicode_1_1_utf_7',
        'unicode_2_0_utf_7', 'x_unicode_1_1_utf_7', 'x_unicode_2_0_utf_7'],
        'utf_8': ['unicode_1_1_utf_8', 'unicode_2_0_utf_8',
        'x_unicode_1_1_utf_8', 'x_unicode_2_0_utf_8'], 'utf_16': [
        'utf_16le', 'ucs_2', 'unicode', 'iso_10646_ucs2'], 'latin_1': [
        'iso_8859_1']}
    for key, aliases in all_aliases.items():
        if converted in aliases:
            return key
    return converted


@classmethod
def register(cls, n):
    """Return a 'register' of ``n`` QubitPlaceholders.

        >>> qs = QubitPlaceholder.register(8) # a qubyte
        >>> prog = Program(H(q) for q in qs)
        >>> address_qubits(prog).out()
        H 0
        H 1
        ...
        >>>

        The returned register is a Python list of QubitPlaceholder objects, so all
        normal list semantics apply.

        :param n: The number of qubits in the register
        """
    return [cls() for _ in range(n)]


def gencrossentropy(px, py, pxpy, alpha=1, logbase=2, measure='T'):
    """
    Generalized cross-entropy measures.

    Parameters
    ----------
    px : array-like
        Discrete probability distribution of random variable X
    py : array-like
        Discrete probability distribution of random variable Y
    pxpy : 2d array-like, optional
        Joint probability distribution of X and Y.  If pxpy is None, X and Y
        are assumed to be independent.
    logbase : int or np.e, optional
        Default is 2 (bits)
    measure : str, optional
        The measure is the type of generalized cross-entropy desired. 'T' is
        the cross-entropy version of the Tsallis measure.  'CR' is Cressie-Read
        measure.

    """


def safe_decode(txt):
    """Return decoded text if it's not already bytes."""
    try:
        return txt.decode()
    except AttributeError:
        return txt


def _colorize(text, color_code):
    """Return shell-escaped colored text string
    """
    return '\x1b[38;{}m{}\x1b[0m'.format(color_code, text)


def psi_Mg_CO3_OH_HMW84(T, P):
    """c-a-a': magnesium carbonate hydroxide [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def sendECard():
    """Calls send on the MailHost object, protected
           by our custom Send eCard permission
        """


def getAllDifferentValues(clustersPerEpoch):
    """
        Get all the different values ocurring during a simulation

        :param clustersPerEpoch: List with dictionaries for all epochs. The dictionary
            has the set of different values (according to column) and their
            number
        :type clustersPerEpoch: list

        :returns: set -- Set containing all values ocurring during a simulation
    """
    allValues = set()
    for epochSummary in clustersPerEpoch:
        for value in epochSummary:
            allValues.update([value])
    return allValues


def vdiff(v1, v2):
    """Return the vector difference of `v1` and `v2` (`v1-v2`)."""
    x1, y1, z1 = v1
    x2, y2, z2 = v2
    return x1 - x2, y1 - y2, z1 - z2


def distance_to_center_of_mass(primary_mass, secondary_mass, positions):
    """
    Return distance from primary and from secondary component to center of mass.

    :param primary_mass: float
    :param secondary_mass: float
    :param positions: numpy.array
    :return: Tuple
    """
    distance = positions[:, (1)]
    mass = primary_mass + secondary_mass
    com_from_primary = distance * secondary_mass / mass
    return com_from_primary, distance - com_from_primary


def get_attrlist(entry, attr):
    """
    Returns the whole list of values for an attribute in the given entry.

    If the attribute does not exist in the entry, return `None`.
    """
    a = entry.get(attr)
    if a is not None:
        return a
    else:
        return []


@classmethod
def override_accept(cls, session, languages, response=None):
    """
        Set the language preferences for the given session, thus overriding
        the preferences given in the HTTP header.

        :param session: the session.
        :param languages: a list of language identifiers.
        :param response: if not None, the preference will also be
                saved as a cookie.
        """
    if not isinstance(languages, list):
        languages = [languages]
    session[cls._SESSION_KEY + '.overridden'] = languages
    if not response is None:
        pass


def convert_by_vocab(vocab, items):
    """Converts a sequence of [tokens|ids] using the vocab."""
    output = []
    for item in items:
        output.append(vocab[item])
    return output


def view_show():
    """Toggle show render view

    """
    pass


def fn_string_join(context, text, separator=''):
    """
    http://www.w3.org/TR/xpath-functions/#func-string-join
    Returns a string created by concatenating the members of the
    text sequence using separator.

    :param context: Parent DOM context
        :type context: EtreeElement
    :param text: matches xpath results
        :type text: list[str]
    :param separator:
        :type separator: str
    :rtype: str
    """
    del context
    return separator.join(text)


def mmf(time, alpha, w0, gamma, rate):
    """
    Computes the Morgan-Mercer-Flodin growth model

    Parameters
    ----------
    time : time
    alpha : upper asymptote
    w0 : the value at time = 0
    gamma : parameter that controls the point of inflection
    rate : growth rate

    See Also
    --------
    mmf_inverse

    References
    ----------
    .. [1] A. Khamiz, Z. Ismail, and A. T. Muhammad, "Nonlinear growth models
           for modeling oil palm yield growth," Journal of Mathematics and
           Statistics, vol. 1, no. 3, p. 225, 2005.
    """
    result = (w0 * gamma + alpha * time ** rate) / (gamma + time ** rate)
    return result


def get_secret_value(client, secret_resource_name,
    secret_value_resource_name, show_value=False):
    """Retrieve the value of a specified version of a secret resource"""
    secret_value = None
    if show_value:
        secret_value = client.show(secret_resource_name,
            secret_value_resource_name)
    secret_data = client.get(secret_resource_name, secret_value_resource_name)
    if secret_value:
        secret_data.value = secret_value.value
    return secret_data


def test_ape(archive, compression, cmd, verbosity, interactive):
    """Test an APE archive."""
    return [cmd, archive, '-v']


@classmethod
def PATCH(cls, *n, **kw):
    """
        Perform a PATCH request using `RESTClient.request()`
        """
    return cls.IMPL.PATCH(*n, **kw)


def fake_translation(s):
    """
    A fake translation function to 'french' that can help you verify that you have tagged all text in the program
    """
    return 'Le %s' % s if s != '\n' else '\n'


def reverse_colourmap(cdict):
    """ Returns the inverted colorbar dictionary.

   I most definitely got this from the web somewhere ... Stackoverflow?

   :params cdict: a colorbar dictionary
   :type cdict: dict

   :return: the flipped dictionary
   :rtype: dict

   """
    new_cdict = {}
    for channel in cdict:
        data = []
        for t in cdict[channel]:
            data.append((1.0 - t[0], t[1], t[2]))
        new_cdict[channel] = data[::-1]
    return new_cdict


def delete_evaluation(EvaluationId=None):
    """
    Assigns the DELETED status to an Evaluation , rendering it unusable.
    After invoking the DeleteEvaluation operation, you can use the GetEvaluation operation to verify that the status of the Evaluation changed to DELETED .
    The results of the DeleteEvaluation operation are irreversible.
    See also: AWS API Documentation

    :example: response = client.delete_evaluation(
        EvaluationId='string'
    )

    :type EvaluationId: string
    :param EvaluationId: [REQUIRED]
            A user-supplied ID that uniquely identifies the Evaluation to delete.

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

    """
    pass


@classmethod
def deriv(cls, val, der):
    """Evaluate the derivative at value = `val` and derivative = `deriv`

        :param val: Number -- Value of the argument
        :param der: Number -- Value of the derivative of the argument
        :return: Number -- The derivative
        """
    raise NotImplementedError()


def check_missing_kwargs(kwargs=None, instance_kwargs=None, instance_of=None):
    """
    checks if all `kwargs` are all in `instance kwargs`
    :param kwargs: list
    :param instance_kwargs: list
    :param instance_of: object
    :return:
    """
    missing_kwargs = []
    for kwarg in kwargs:
        if kwarg not in instance_kwargs:
            missing_kwargs.append('`{}`'.format(kwarg))
    if len(missing_kwargs) > 0:
        raise ValueError('missing argument(s): {} in class instance {}'.
            format(', '.join(missing_kwargs), instance_of.__name__))


def create_cone(bm: 'bmesh.types.BMesh', cap_ends: bool, cap_tris: bool,
    segments: int, diameter1: float, diameter2: float, depth: float, matrix:
    'mathutils.Matrix', calc_uvs: bool) ->dict:
    """Creates a cone with variable depth at both ends

    :param bm: The bmesh to operate on.
    :type bm: 'bmesh.types.BMesh'
    :param cap_ends: whether or not to fill in the ends with faces
    :type cap_ends: bool
    :param cap_tris: fill ends with triangles instead of ngons
    :type cap_tris: bool
    :param segments: Undocumented.
    :type segments: int
    :param diameter1: diameter of one end
    :type diameter1: float
    :param diameter2: diameter of the opposite
    :type diameter2: float
    :param depth: distance between ends
    :type depth: float
    :param matrix: matrix to multiply the new geometry with
    :type matrix: 'mathutils.Matrix'
    :param calc_uvs: calculate default UVs
    :type calc_uvs: bool
    :return:  verts: output vertstype list of (bmesh.types.BMVert)
    """
    pass


def species_level(prediction):
    """Is this prediction at species level.

    Returns True for a binomial name (at least one space), False for genus
    only or no prediction.
    """
    assert ';' not in prediction, prediction
    return prediction and ' ' in prediction


def proto2methodprotofunc(proto):
    """Convert a prototype such as 'Ljava/lang/String;'
       into a string 'Ljava_lang_String" so we can append that to the
       'METHOD_myMethod' if its export python name contains the prototype
    """
    return proto.replace(' ', '').replace('(', '').replace('[', '').replace(')'
        , '').replace('/', '_').replace(';', '')


def get_dids():
    """the set of (known) document ids."""


def get_custom_ident(token):
    """If ``token`` is a keyword, return its name.

    Otherwise return ``None``.

    """
    if token.type == 'ident':
        return token.value


def find_matching_paren(string, index, lparen='(', rparen=')'):
    """Find the closing paren corresponding to the open paren at <index>
       in <string>.  Optionally, can provide other characters to match on.
       If found, returns the index of the matching parenthesis.  If not found,
       returns -1.
    """
    if not string[index] == lparen:
        raise ValueError("Character at index %d is '%s'. Expected '%s'" % (
            index, string[index], lparen))
    index += 1
    count = 1
    while index < len(string) and count > 0:
        while index < len(string) and string[index] not in (lparen, rparen):
            index += 1
        if string[index] == lparen:
            count += 1
        elif string[index] == rparen:
            count -= 1
    if count == 0:
        return index
    else:
        return -1


@classmethod
def generate_custom_tree(cls, lgbm_args):
    """Generates a custom LightGBM Classifier wrapper.
        :param lgbm_args: parameters to pass into the LightGBM Classifier
        :type lgbm_args: dict
        :rtype: cls
        """
    return type('Custom' + cls.__name__, (cls,), {'lgbm_args': lgbm_args})


def process_network_proto(caffe_root, deploy_proto):
    """
    Runs the caffe upgrade tool on the prototxt to create a prototxt in the latest format.
    This enable us to work just with latest structures, instead of supporting all the variants

    :param caffe_root: link to caffe root folder, where the upgrade tool is located
    :param deploy_proto: name of the original prototxt file
    :return: name of new processed prototxt file
    """
    processed_deploy_proto = deploy_proto + '.processed'
    from shutil import copyfile
    copyfile(deploy_proto, processed_deploy_proto)
    import os
    upgrade_tool_command_line = (caffe_root +
        '/build/tools/upgrade_net_proto_text.bin ' + processed_deploy_proto +
        ' ' + processed_deploy_proto)
    os.system(upgrade_tool_command_line)
    return processed_deploy_proto


def inverse_truncated_modal(M, num_modes, svd=None):
    """Invert `M` with `num_modes` modes.

	Modes are given by a singular value decomposition of the input matrix.
	If `svd` is given, it is used instead. Modes are ordered in descending
	order by their singular values.

	Parameters
	----------
	M : ndarray
		The matrix to invert. This matrix must be two-dimensional.
	num_modes : integer
		The number of modes to use for the inversion. Higher-order modes
		are ignored.
	svd : SVD object
		A precalculated singular value decomposition object. This will
		be used if supplied, to avoid recalculation of an SVD.

	Returns
	-------
	ndarray
		The inverted matrix.
	"""
    if svd is None:
        from .singular_value_decomposition import SVD
        svd = SVD(M, num_modes)
    U, S, Vt = svd.svd
    U = U[:, :num_modes]
    S = S[:num_modes]
    Vt = Vt[:num_modes, :]
    return (Vt.T / S).dot(U.T)


def get_file_text(filepath):
    """Return the text of a file in a given location, if it has text.

    Parameters
    ----------
    filepath : string
        Path to file to read

    Results
    -------
    string
        String containing text of file (Unicode string, UTF-8 decoded)

    Raises
    ------
    FileNotFoundError if there is no file at filepath
    """
    try:
        with open(filepath, 'r') as f:
            return f.read()
    except UnicodeDecodeError:
        return None


def avseth_gassmann(ksat1, kf1, kf2, kmin, phi):
    """
    Applies the Gassmann equation.

    Args:
        ksat1 (float): Ksat1.
        kf1 (float): Kfluid1.
        kf2 (float): Kfluid2.
        kmin (float): Kmineral.
        phi (float): Porosity.

    Returns:
        float: Ksat2.
    """
    s = ksat1 / (kmin - ksat1)
    f1 = kf1 / (phi * (kmin - kf1))
    f2 = kf2 / (phi * (kmin - kf2))
    ksat2 = kmin / (1 / (s - f1 + f2) + 1)
    return ksat2


def get_date_type(calendar):
    """Return the cftime date type for a given calendar name."""
    try:
        import cftime
    except ImportError:
        raise ImportError(
            'cftime is required for dates with non-standard calendars')
    else:
        calendars = {'noleap': cftime.DatetimeNoLeap, '360_day': cftime.
            Datetime360Day, '365_day': cftime.DatetimeNoLeap, '366_day':
            cftime.DatetimeAllLeap, 'gregorian': cftime.DatetimeGregorian,
            'proleptic_gregorian': cftime.DatetimeProlepticGregorian,
            'julian': cftime.DatetimeJulian, 'all_leap': cftime.
            DatetimeAllLeap, 'standard': cftime.DatetimeGregorian}
        return calendars[calendar]


def timedelta_to_seconds(td):
    """
    Converts a timedelta instance to seconds.
    """
    return td.seconds + td.days * 24 * 60 * 60


@classmethod
def _class_local(cls, name, default):
    """
        Returns an attribute directly associated with this class
        (as opposed to subclasses), setting default if necessary
        """
    result = cls.__dict__.get(name, default)
    setattr(cls, name, result)
    return result


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


@classmethod
def convert_transforms(cls, transforms):
    """
        Convert a stack of transforms to a format understood by the backend
        service.
        """
    backend_transforms = []
    for transform in transforms:
        converter = cls._transform_converters.get(transform.id)
        if not converter:
            converter = cls._transform_converters.get('__custom__')
        backend_transforms.append(converter(transform))
    return backend_transforms


def _removeMargins(widget):
    """Remove Nuke margins when docked UI
    Source: https://gist.github.com/maty974/4739917
    """
    for parent in (widget.parentWidget().parentWidget(), widget.
        parentWidget().parentWidget().parentWidget().parentWidget()):
        parent.layout().setContentsMargins(0, 0, 0, 0)


def glEvalPoint(i: int, j: int):
    """Generate and evaluate a single point in a mesh

    :param i: Specifies the integer value for grid domain variable i.
    :type i: int
    :param j: Specifies the integer value for grid domain variable j (glEvalPoint2 only).
    :type j: int
    """
    pass


def tap(x, label=None):
    """Prints x and then returns it."""
    if label:
        print('%s: %s' % (label, x))
    else:
        print(x)
    return x


def create_hkl_group(py_obj, h_group, call_id=0):
    """ Create a new group within the hickle file

    Args:
        h_group (h5.File.group): group to dump data into.
        call_id (int): index to identify object's relative location in the iterable.

    """
    h_subgroup = h_group.create_group('data_%i' % call_id)
    h_subgroup.attrs['type'] = [str(type(py_obj))]
    return h_subgroup


def getCardsForView():
    """Return a two dimensional array of images representing
           the number of images intended per row.
        """


def _getValueFormat(f, values, i):
    """Helper for buildPairPos{Glyphs|Classes}Subtable."""
    if f is not None:
        return f
    mask = 0
    for value in values:
        if value is not None and value[i] is not None:
            mask |= value[i].getFormat()
    return mask


@classmethod
def _partition_lines(cls, line, cell):
    """
        Check the code for additional use of %%opts. Enables
        multi-line use of %%opts in a single call to the magic.
        """
    if cell is None:
        return line, cell
    specs, code = [line], []
    for line in cell.splitlines():
        if line.strip().startswith('%%opts'):
            specs.append(line.strip()[7:])
        else:
            code.append(line)
    return ' '.join(specs), '\n'.join(code)


def list_delivery_streams(Limit=None, ExclusiveStartDeliveryStreamName=None):
    """
    Lists your delivery streams.
    The number of delivery streams might be too large to return using a single call to  ListDeliveryStreams . You can limit the number of delivery streams returned, using the Limit parameter. To determine whether there are more delivery streams to list, check the value of HasMoreDeliveryStreams in the output. If there are more delivery streams to list, you can request them by specifying the name of the last delivery stream returned in the call in the ExclusiveStartDeliveryStreamName parameter of a subsequent call.
    See also: AWS API Documentation

    :example: response = client.list_delivery_streams(
        Limit=123,
        ExclusiveStartDeliveryStreamName='string'
    )

    :type Limit: integer
    :param Limit: The maximum number of delivery streams to list.

    :type ExclusiveStartDeliveryStreamName: string
    :param ExclusiveStartDeliveryStreamName: The name of the delivery stream to start the list with.

    :rtype: dict
    :return: {
        'DeliveryStreamNames': [
            'string',
        ],
        'HasMoreDeliveryStreams': True|False
    }

    :returns:
    (string) --

    """
    pass


def skip(num: int):
    """Returns a collection containing all but the first num items
        in the input collection. Will return an empty collection
        if there are no items remaining after the indicated number of items have
        been skipped, or if the input collection is empty.
        If num is less than or equal to zero, the input collection
        is simply returned."""


def csv_skip_last_row(iterator):
    """Skip last CSV row.

    Args:
        iterator:

    Returns:

    """
    prev = next(iterator)
    for item in iterator:
        yield prev
        prev = item


def get_rows_to_keep(mode, df, grp, samp_grps, qthreshold,
    min_child_non_leaf, min_child_nsamp, min_peptides, min_pep_nsamp):
    """
    Use checking to find the rows (taxonomic or functional terms) that satisfy all of the filtering conditions for
    the specified group
    :param mode: either 'f', 't', or 'ft'
    :param df: data frame of functional and taxonomic terms. missing values are represented as 0.
    :param grp: grp to check conditions for
    :param samp_grps: SampleGroups() object
    :param qthreshold: minimum number of quantitations per grp
    :param min_child_non_leaf: minimum number of children for terms that are not leaves
    :param min_child_nsamp: minimum number of samples with sample children greater than min_child_non_leaf
    :param min_peptides: minimum number of peptides for each term
    :param min_pep_nsamp: minimum number of samples where the number of peptides has to be larger than
    min_peptides
    :return: boolean Series with rows to keep as True
    """
    intcols = samp_grps.sample_names[grp]
    keep_int = (df[intcols] > 0).apply(sum, axis=1) >= qthreshold
    peptide_cols = samp_grps.n_peptide_names_dict[grp]
    peptide_keep_series = df[peptide_cols] > min_peptides
    if min_pep_nsamp == 'all':
        keep_peptide = peptide_keep_series.all(axis=1)
    else:
        keep_peptide = peptide_keep_series.apply(sum, axis=1) >= int(
            min_pep_nsamp)
    if mode != 'ft':
        child_cols = samp_grps.samp_children_names_dict[grp]
        child_keep_series = (df[child_cols] >= min_child_non_leaf) | (df[
            child_cols] == 0)
        if min_child_nsamp == 'all':
            keep_child = child_keep_series.all(axis=1)
        else:
            keep_child = child_keep_series.apply(sum, axis=1) >= int(
                min_child_nsamp)
        all_keep = keep_int & keep_child & keep_peptide
    else:
        all_keep = keep_int & keep_peptide
    return all_keep


def get_last_items(number, number_id_days=0, meta_types=None):
    """Returns the last (number) published items
           This is _only_ used by News Viewers.
        """


def PolsRenewal(t):
    """Number of policies: Renewal policies"""
    return 0


def perpendicular_vector(v):
    """
    Compute a vector perpendicular to the input vector
    """
    if v[0] == v[1] == v[2] == 0:
        raise ValueError('zero-vector')
    if v[2] == 0:
        return [-v[1], v[0], 0]
    else:
        return [1.0, 1.0, -1.0 * (v[0] + v[1]) / v[2]]


def query_to_dict(results, descriptions):
    """
    Replacement method for cursor.dictfetchall() as that method no longer
    exists in psycopg2, and I'm guessing in other backends too.

    Converts the results of a raw SQL query into a list of dictionaries, suitable
    for use in templates etc.
    """
    output = []
    for data in results:
        row = {}
        i = 0
        for column in descriptions:
            row[column[0]] = data[i]
            i += 1
        output.append(row)
    return output


def dump(system):
    """
    Convert an atomman.System into the cell tuple used by spglib.

    Parameters
    ----------
    system : atomman.System
        A atomman representation of a system.

    Returns
    -------
    tuple
        (lattice, positions, and numbers) used as inputs for spglib
        functions.
    """
    lattice = system.box.vects
    positions = system.atoms_prop(key='pos', scale=True)
    numbers = system.atoms.atype
    return lattice, positions, numbers


@classmethod
def get_query_classes(cls, sub_classes=None):
    """
        Get the tuple of classes to be used for the entity query. If sub_classes is defined, each class will be
        validated by verifying that it is a sub class of the loader's orm base class.
        Validate a tuple of classes if a user passes in a specific one when attempting to load an entity. Each class
        should be a sub class of the entity loader's orm base class

        :param sub_classes: an optional tuple of orm classes, that should each be strict sub classes of the
            base orm class of the loader, that will narrow the queryset
        :returns: the tuple of orm classes to be used for the entity query
        :raises ValueError: if any of the classes are not a sub class of the entity loader's orm base class
        """
    if sub_classes is None:
        return cls.orm_base_class,
    if not isinstance(sub_classes, tuple):
        raise TypeError('sub_classes should be a tuple: {}'.format(sub_classes)
            )
    for sub_class in sub_classes:
        if not issubclass(sub_class, cls.orm_base_class):
            raise ValueError('{} is not a sub class of the base orm class {}'
                .format(sub_class, cls.orm_base_class))
    return sub_classes


def write_layout(files_model, ex_mets, media, biomasses, outfile=
    'Consortium_layout.txt', maxCycles=1000, timeStep=0.1, spaceWidth=0.05,
    deathRate=0, numRunThreads=2, maxSpaceBiomass=10, biom_name=
    'total_biomass_log_template.txt', media_name='media_log_template.txt',
    flux_name='flux_log_template.txt'):
    """
    Writes the comets layout
    INPUTS -> files_model: list of strings containing model files,
              ex_mets: list of extracellular metabolites,
              media: dictionary of metabolite:concentration
              dictionary of files_model:initial biomass
              ... some of the COMETS parameters, that are described in http://www.bu.edu/segrelab/comets-parameters/
    OUPUTS -> creates a COMETS layout in "Consortium_layout.txt
    """
    with open(outfile, 'w') as f:
        lines4 = 'model_file\t' + '\t'.join(files_model)
        lines4 += '\n\tmodel_world\n\t\tgrid_size\t1\t1\n\t\tworld_media\n'
        f.write(lines4)
        for met in ex_mets:
            if met not in media:
                f.write('\t\t\t' + met + '\t' + '0.0\n')
            else:
                f.write('\t\t\t' + met + '\t' + str(media[met]) + '\n')
        f.write('\t\t//\n\t\tmedia\n\t\t//\n\t//\n\tinitial_pop\n')
        biomass_line = '\t\t0\t0'
        for file in files_model:
            biomass_line += '\t' + biomasses[file]
        f.write(biomass_line + '\n\t//\n')
        params = 'parameters\n    maxCycles = ' + str(maxCycles) + '\n'
        params += '    timeStep = ' + str(timeStep) + '\n'
        params += '    spaceWidth = ' + str(spaceWidth) + '\n'
        params += '    deathRate = ' + str(deathRate) + '\n'
        params += '    maxSpaceBiomass = ' + str(maxSpaceBiomass) + '\n'
        params += '    numRunThreads = ' + str(numRunThreads) + '\n'
        params += '    pixelScale = 100\n'
        params += '    allowCellOverlap = true\n'
        params += '    saveslideshow = false\n'
        params += '    writetotalbiomasslog = true\n'
        params += '    totalbiomasslogname = ' + biom_name + '\n'
        params += '    writemedialog = true\n'
        params += '    medialogname = ' + media_name + '\n'
        params += '    writefluxlog = true\n'
        params += '    fluxlogname = ' + flux_name + '\n'
        params += '    uselognametimestamp = false\n'
        params += '    exchangestyle = Monod Style\n'
        params += '    defaultKm = 0.01\n'
        params += '    defaultVmax = 20\n//\n'
        f.write(params)
    return


def linspace(start, stop, num, endpoint=True):
    """
    Generate linear space. This is sometimes more appropriate than
    using `range`.

    Parameters
    ----------
    start : float
        The starting value of the sequence.
    stop : float
        The end value of the sequence.
    num : int
        Number of samples to generate.
    endpoint : bool, optional
        If True (default), the endpoint is included in the linear space.

    Yields
    ------
    val : float

    See also
    --------
    numpy.linspace : generate linear space as a dense array.
    """
    if endpoint:
        num -= 1
    step = (stop - start) / num
    val = start
    for _ in range(num):
        yield val
        val += step
    if endpoint:
        yield stop


@staticmethod
def lift(x):
    """
        Lifts the value into a constant function that always returns `x`
        regardless of its input.

        Arguments:
        x -- the value to always return from the function
        """
    return lambda _: x


def list_item_inside(_list, item):
    """
    is item in a list?
    """
    return item in _list


def check_valid_metric_parameter(metric: str):
    """ Check parameter is either 'distance' or 'similarity'. """
    if metric != 'distance' and metric != 'similarity':
        raise ValueError(
            "Parameter 'metric' must be 'distance' or 'similarity'.Got: " +
            metric.__str__())


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

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

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


def save_sentences_single(uid, text, output_dir, remove_non_english_chars=
    True, prefix=''):
    """save_sentence_single
    Write text to file
    Parameters
    ==========
    uid: int or string
        a unique ID for the article
    text: str
        raw text of the article
    output_dir: path
        full path to a plugins corpus directory
    """
    if prefix != '':
        prefix = '%s_' % prefix
    output_file = '%s/%s%s_sentences.txt' % (output_dir, uid, prefix)
    filey = open(output_file, 'wb')
    filey.write('%s\n' % text)
    filey.close()


def get_sinks_selection(sinks, p, R):
    """
    Select the sinks from the dataframe *sinks* within the distance *R* from
    the given point *p*.

    Parameters
    ----------
    sinks: DataFrame
        Dataframe of the sinks.
    p: Point or tuple
        Coordinates of the given point.
    R: float, optional
        Maximal distance from the point so that a street is selected.

    Returns
    -------
    DataFrame
        Dataframe of the selected sinks with indices from the dataframe
        *sinks*.
    """
    index = list()
    for idx, sink in sinks.iterrows():
        object = sink['geometry']
        d = object.distance(p)
        if d < R:
            index.append(idx)
    sinks_selection = sinks.loc[index]
    return sinks_selection


def end_file(current_output):
    """End an output file.
    This is smart enough to do nothing if current_output is None.
    @param current_output: the current file output (or None).
    @returns: None, to represent the closed stream.
    """
    if current_output:
        current_output.write('</iati-activities>\n')
        current_output.close()
    return None


@staticmethod
def _get_fn_input_details(function):
    """Return a List of all Function Inputs which are Dictionaries with
        the attributes: api_name, name, type, required, placeholder and tooltip"""
    fn_inputs = []
    for i in function.get('inputs', []):
        the_input = {}
        the_input['api_name'] = i.get('name')
        the_input['name'] = i.get('text')
        the_input['type'] = i.get('input_type')
        the_input['required'] = 'Yes' if 'always' in i.get('required', ''
            ) else 'No'
        the_input['placeholder'] = i.get('placeholder') if i.get('placeholder'
            ) else '-'
        the_input['tooltip'] = i.get('tooltip') if i.get('tooltip') else '-'
        fn_inputs.append(the_input)
    fn_inputs = sorted(fn_inputs, key=lambda i: i['api_name'])
    return fn_inputs


def __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


@classmethod
def mget(cls, ids):
    """Get multiple objects from elasticsearch
        """
    if not ids:
        return []
    docs = cls._get_es().mget(index=cls.INDEX, doc_type=cls.DOC_TYPE, body=
        {'ids': ids}).get('docs')
    result = []
    for doc in docs:
        if 'error' in doc or not doc.get('found', False):
            result.append(None)
            continue
        result.append(cls.from_raw_es_data(doc))
    return result


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

        :param GroupCreateType val:
        :rtype: EventType
        """
    return cls('group_create', val)


def init(app, engine, session_factory):
    """Adds app.engine, and app.session_factory. Creates them if not passed in.

    :param app: flask app.
    :param engine: sqlalchemy engine.
    :param session_factory: session factory.
    """
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from flask_sqlalchemy_session import flask_scoped_session
    app.engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI']
        ) if engine is None else engine
    app.session_factory = sessionmaker(bind=app.engine
        ) if session_factory is None else session_factory
    app.scoped_session = flask_scoped_session(app.session_factory, app)


def uninstall(context):
    """Uninstall script"""


@staticmethod
def __strescape(string):
    """Escapes a string: hexifies it."""
    result = ''
    for fchar in string:
        if ord(fchar) >= 32 and ord(fchar) < 127:
            result += fchar
        else:
            result += '%02x' % ord(fchar)
    return result


def generate_exclusions(proteins):
    """
    Generate a series of exclusion spheres for some cavities
    :param proteins: a list of protein cavities
    :return: the combined exclusion spheres
    """
    pass


@conf
def common_flags_dmd(conf):
    """
	Set the flags required by *dmd* or *dmd2*
	"""
    v = conf.env
    v.D_SRC_F = ['-c']
    v.D_TGT_F = '-of%s'
    v.D_LINKER = v.D
    v.DLNK_SRC_F = ''
    v.DLNK_TGT_F = '-of%s'
    v.DINC_ST = '-I%s'
    v.DSHLIB_MARKER = v.DSTLIB_MARKER = ''
    v.DSTLIB_ST = v.DSHLIB_ST = '-L-l%s'
    v.DSTLIBPATH_ST = v.DLIBPATH_ST = '-L-L%s'
    v.LINKFLAGS_dprogram = ['-quiet']
    v.DFLAGS_dshlib = ['-fPIC']
    v.LINKFLAGS_dshlib = ['-L-shared']
    v.DHEADER_ext = '.di'
    v.DFLAGS_d_with_header = ['-H', '-Hf']
    v.D_HDR_F = '%s'


def read_fullsamplelayers():
    """Read all render layers of current scene, in full sample

    """
    pass


def SizeBenefitAnn(t):
    """Annuity benefit per policy"""
    return 0


def describe_replication_groups(ReplicationGroupId=None, MaxRecords=None,
    Marker=None):
    """
    Returns information about a particular replication group. If no identifier is specified, DescribeReplicationGroups returns information about all replication groups.
    See also: AWS API Documentation

    :example: response = client.describe_replication_groups(
        ReplicationGroupId='string',
        MaxRecords=123,
        Marker='string'
    )

    :type ReplicationGroupId: string
    :param ReplicationGroupId: The identifier for the replication group to be described. This parameter is not case sensitive.
            If you do not specify this parameter, information about all replication groups is returned.

    :type MaxRecords: integer
    :param MaxRecords: The maximum number of records to include in the response. If more records exist than the specified MaxRecords value, a marker is included in the response so that the remaining results can be retrieved.
            Default: 100
            Constraints: minimum 20; maximum 100.

    :type Marker: string
    :param Marker: An optional marker returned from a prior request. Use this marker for pagination of results from this operation. If this parameter is specified, the response includes only records beyond the marker, up to the value specified by MaxRecords .

    :rtype: dict
    :return: {
        'Marker': 'string',
        'ReplicationGroups': [
            {
                'ReplicationGroupId': 'string',
                'Description': 'string',
                'Status': 'string',
                'PendingModifiedValues': {
                    'PrimaryClusterId': 'string',
                    'AutomaticFailoverStatus': 'enabled'|'disabled'
                },
                'MemberClusters': [
                    'string',
                ],
                'NodeGroups': [
                    {
                        'NodeGroupId': 'string',
                        'Status': 'string',
                        'PrimaryEndpoint': {
                            'Address': 'string',
                            'Port': 123
                        },
                        'Slots': 'string',
                        'NodeGroupMembers': [
                            {
                                'CacheClusterId': 'string',
                                'CacheNodeId': 'string',
                                'ReadEndpoint': {
                                    'Address': 'string',
                                    'Port': 123
                                },
                                'PreferredAvailabilityZone': 'string',
                                'CurrentRole': 'string'
                            },
                        ]
                    },
                ],
                'SnapshottingClusterId': 'string',
                'AutomaticFailover': 'enabled'|'disabled'|'enabling'|'disabling',
                'ConfigurationEndpoint': {
                    'Address': 'string',
                    'Port': 123
                },
                'SnapshotRetentionLimit': 123,
                'SnapshotWindow': 'string',
                'ClusterEnabled': True|False,
                'CacheNodeType': 'string'
            },
        ]
    }

    :returns:
    Redis versions earlier than 2.8.6.
    Redis (cluster mode disabled):T1 and T2 cache node types. Redis (cluster mode enabled): T1 node types.

    """
    pass


def template_source(page_pk):
    """Create cache key for page template"""
    return 'powerpages:template:{0}'.format(page_pk)


def somme(li):
    """
    calcule la somme des éléments d'un tableau

    @param      li      tableau
    @return             somme

    .. exref::
        :tag: Base
        :title: calcul d'une somme

        Le calcul d'une somme fait toujours intervenir une boucle car le langage
        Python ne peut faire des additions qu'avec deux nombres.
        Le schéma est toujours le même : initialisation et boucle.

        ::

            li = [ 0, 434, 43, 6456 ]
            s  = 0                       # initialisation
            for l in li :                # boucle
                s += l                   # addition

        Ce code est équivalent à la fonction `sum <https://docs.python.org/3/library/functions.html#sum>`_.
        Dans ce cas où la somme intègre le résultat d'une fonction et non les éléments d'une liste,
        il faudrait écrire :

        ::

            def fonction (x) : return x*x
            s  = 0
            for l in li : s += fonction (l)

        Et ces deux lignes pourraient être résumées en une seule grâce
        à l'une de ces instructions :

        ::

            s = sum ( [fonction (l) for l in li] )
            s = sum ( fonction (l) for l in li )
            s = sum ( map (fonction, li) )

        L'avantage des deux dernières instructions est qu'elles évitent
        la création d'une liste intermédiaire,
        c'est un point à prendre en compte si la liste sur laquelle opère la
        somme est volumineuse.
    """
    return sum(li)


def unquote():
    """Return the objects URL unquote representation."""


def _dct_from_mro(cls: type, attr_name: str) ->dict:
    """"Get a merged dictionary from `cls` bases attribute `attr_name`. MRO defines importance (closest = strongest)."""
    d = {}
    for c in reversed(cls.mro()):
        d.update(getattr(c, attr_name, {}))
    return d


def indices_to_text(h, k, l):
    """
	Returns a Matplotlib-compatible string representation of Miller indices,
	in LaTeX/Mathjax format.

	.. versionadded:: 2.0.2

	Parameters
	----------
	h, k, l : int
		Miller indices

	Returns
	-------
	s : string
		Matplotlib-compatible representation

	Examples
	--------
	>>> indices_to_text(1,0,0)
	'(100)'
	>>> indices_to_text(2,-1,1)
	'(2$\\bar{1}$1)'
	"""
    t = '('
    for index in (h, k, l):
        if index < 0:
            t = t + '$\\bar{' + f'{abs(index)}' + '}$'
        else:
            t = t + f'{index}'
    return t + ')'


def write_trimmed_reads(demultiplex_dict, samplesDict, settings):
    """Write the fastq data to the correct (demultiplexed) file."""
    barcode_dict = {}
    for sample in samplesDict:
        barcode_dict[samplesDict[sample]['barcode']] = sample
    for barcode in demultiplex_dict:
        if barcode != 'other':
            with open('{path}/{sample}_trimmed.fastq'.format(path=settings.
                path, sample=barcode_dict[barcode]), 'a') as fo:
                for read in demultiplex_dict[barcode]:
                    fo.write('@{n}\n{s}\n+\n{q}\n'.format(n=read.name, s=
                        read.sequence[slice(read.trim[0], read.trim[1])], q
                        =read.quality[slice(read.trim[0], read.trim[1])]))


def getPlayAgain(prompt):
    """Ask the player if they want to play again.
    Return True if they want to play again."""
    return input(prompt).startswith('y')


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

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

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


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


def clear():
    """Clear the set of acceptable posting aliases."""


def cmp_sort(a, b):
    """ Sorting key. If gantry angle is equal, then sort by couch angle.
    """
    if a['gantry'] == b['gantry']:
        return a['couch'] - b['couch']
    return a['gantry'] - b['gantry']


@staticmethod
def calc_map_types_split_index(types_string):
    """ Returns the index of the comma separating the key and value types in a map type.

        :param types_string: the string declaring the map's type.
        :returns: index of top-level separating comma
        :rtype: int

        """
    bracket_depth = 0
    for i, char in enumerate(types_string):
        if char == '<':
            bracket_depth += 1
        elif char == '>':
            bracket_depth -= 1
        elif char == ',' and bracket_depth == 0:
            return i
    return -1


@classmethod
def _get_overridden_method(cls, method):
    """Return None if the method is not overridden. Otherwise returns the overridden method."""
    return getattr(method.__func__, '__cog_special_method__', method)


def _call_constructed(class_reference, instance):
    """Check if a property is allowed to be unhandled."""
    if not hasattr(class_reference, '__deserialize_constructed__'):
        return
    class_reference.__deserialize_constructed__(instance)


def darken(color, ratio=0.5):
    """Creates a darker version of a color given by an RGB triplet.

    This is done by mixing the original color with black using the given
    ratio. A ratio of 1.0 will yield a completely black color, a ratio
    of 0.0 will yield the original color. The alpha values are left intact.
    """
    ratio = 1.0 - ratio
    red, green, blue, alpha = color
    return red * ratio, green * ratio, blue * ratio, alpha


def p_dynamic_type(p):
    """
     T : T LBRAKET RBRAKET
    """
    reps = None
    base_type = p[1]
    p[0] = 'array', reps, base_type


@classmethod
def GetRawBinding(cls, item_id):
    """Get the raw key binding tuple
        @param cls: Class Object
        @param item_id: MenuItem Id
        @return: tuple

        """
    return cls.key_binds.get(item_id, None)


def delete():
    """Delete active scene

    """
    pass


def undo(object, transaction_info):
    """Performs an undo operation.

        o Permission:  Undo changes
        """


def __get_str(section, name):
    """Get the forecasted string from json section."""
    try:
        return section[name]
    except (ValueError, TypeError, KeyError):
        return ''


def keyframe_delete_button(all: bool=True):
    """Delete current keyframe of current UI-active property

    :param all: All, Delete keyframes from all elements of the array
    :type all: bool
    """
    pass


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Net` from a :code:`net` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Net`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


@classmethod
def default_calendar(cls):
    """ get writable calendar
        """
    cal_lst = cls.get_calendarlst()
    if len(cal_lst) > 0:
        return cal_lst[0]
    else:
        return None


def addon_show(module: str=''):
    """Show add-on preferences

    :param module: Module, Module name of the add-on to expand
    :type module: str
    """
    pass


@staticmethod
def _inheritors(klass):
    """Return all defined classes that inherit from 'klass'.
        """
    subclasses = set()
    work = [klass]
    while work:
        parent = work.pop()
        for child in parent.__subclasses__():
            if child not in subclasses:
                subclasses.add(child)
                work.append(child)
    return subclasses


@classmethod
def create_attributes(klass, attributes, previous_object=None):
    """
        Attributes for resource creation.
        """
    if 'fields' not in attributes:
        if previous_object is None:
            attributes['fields'] = {}
        else:
            attributes['fields'] = previous_object.to_json()['fields']
    return {'fields': attributes['fields']}


def _sanitize_sdk_version(value):
    """Sanitize the raw values from androguard to handle bad values

    minSdkVersion/targetSdkVersion/maxSdkVersion must be integers, but
    that doesn't stop devs from doing strange things like setting them
    using Android XML strings. This method makes the Androguard output
    match the output from `aapt dump badging`: bad values are ignored.

    https://gitlab.com/souch/SMSbypass/blob/v0.9/app/src/main/AndroidManifest.xml#L29
    https://gitlab.com/souch/SMSbypass/blob/v0.9/app/src/main/res/values/strings.xml#L27

    """
    try:
        sdk_version = int(value)
        if sdk_version > 0:
            return sdk_version
    except (TypeError, ValueError):
        pass
    return None


def read_or_raise(fin, size):
    """ Instead of returning a result smaller than `size` like `io.read()`,
		it raises and EOFError.
	"""
    data = fin.read(size)
    if len(data) != size:
        raise EOFError
    return data


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


def group_clusters(df, cluster_id, date_col):
    """ Use pandas to group clusters by cluster identifier
    df = pandas dataframe
    cluster_id = column that identifies cluster membership, which can
        be a basic string like "hospital cluster A"
    date_col = onset or report date column
    """
    clusters = df[df[date_col].notnull()]
    groups = clusters.groupby(clusters[cluster_id])
    return groups


def abort(store_connection, txn=None):
    """
        Abort the commit, ignoring certain exceptions.

        If *txn* is not None, phase 1 is also aborted.

        :param store_connection: An :class:`IManagedStoreConnection`

        :return: A true value if the connection was rolled back
                 without ignoring any exceptions; if an exception was
                 ignored, returns a false value (and the connection
                 and cursor are closed before this method returns).
        """


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

    """
    ctx.ext.summary_fields += (ctx.doc.canonical_name, ctx.doc.name, ctx.
        doc.long_name)


def _get_fs(fs, nyq):
    """
    Utility for replacing the argument 'nyq' (with default 1) with 'fs'.
    """
    if nyq is None and fs is None:
        fs = 2
    elif nyq is not None:
        if fs is not None:
            raise ValueError("Values cannot be given for both 'nyq' and 'fs'.")
        fs = 2 * nyq
    return fs


def is_conflicting(fsm, agents, agent, eqclass):
    """
    Return whether the given equivalence class for agent is conflicting or not.

    mas -- a multi-agents system;
    agents -- a subset of agents of mas;
    agent -- an agent of agents;
    eqclass -- a subset of moves for agents composed of states equivalent for
               agent.

    """
    si = fsm.pick_one_state_inputs(eqclass)
    others_cube = fsm.bddEnc.inputsCube - fsm.inputs_cube_for_agents({agent})
    return (eqclass - (eqclass & si.forsome(fsm.bddEnc.statesCube |
        others_cube))).isnot_false()


@classmethod
def local(cls):
    """Switch to saving the current session to a local file."""
    cls.save = True
    cls.save_locally = True


def _tem_writer(tem_name, shape, line_data):
    """ User accessible version of Modellers tem_writer function, for saving templates.
    """
    with open(tem_name, 'w') as tem_file:
        tem_file.write('%s\n' % len(shape))
        for line in shape.astype('str').tolist():
            tem_file.write('\t'.join(line) + '\n')
        for line_value in line_data:
            tem_file.write('%s\n' % ' '.join(line_value))


def edge_rotate(edge: 'bmesh.types.BMEdge', ccw: bool=False
    ) ->'bmesh.types.BMEdge':
    """Rotate the edge and return the newly created edge. If rotating the edge fails, None will be returned.

    :param edge: The edge to rotate.
    :type edge: 'bmesh.types.BMEdge'
    :param ccw: When True the edge will be rotated counter clockwise.
    :type ccw: bool
    :return:  The newly rotated edge.
    """
    pass


def drop(k, v):
    """return None, indicating the item should be dropped"""
    return None


def source_path():
    """Returns the physical path of the versioned content."""


@classmethod
def _constructor(cls, mapping, configuration):
    """
        A standardized constructor.
        """
    return cls(mapping, sequence_type=configuration)


def uint256_from_compact(c):
    """Convert compact encoding to uint256

    Used for the nBits compact encoding of the target in the block header.
    """
    nbytes = c >> 24 & 255
    if nbytes <= 3:
        v = (c & 16777215) >> 8 * (3 - nbytes)
    else:
        v = (c & 16777215) << 8 * (nbytes - 3)
    return v


@classmethod
def create(cls, **kwargs):
    """Overrtite if you can persiste the data."""
    raise NotImplementedError('canot persiste the dict.')


def perm_get_request_by_did(issuer, kwargs):
    """
    Checks if an account can get a request by DID.

    :param issuer: Account identifier which issues the command.
    :param kwargs: List of arguments for the action.
    :returns: True if account is allowed, otherwise False
    """
    return True


def normalize_extension(extension: str) ->str:
    """Ensures all extensions begin with a dot."""
    assert extension
    if extension and extension[0] != '.':
        extension = f'.{extension}'
    return extension.lower()


@classmethod
def from_file(cls, f, filename='?', namespace=None):
    """
        Initializes the config from a file object ``f``. The file is expected to contain a variable named ``CONFIG``.
        """
    ns = dict(__file__=filename)
    if namespace is not None:
        ns.update(namespace)
    return cls.from_string(f.read(), namespace=namespace)


@classmethod
def unbound(cls, value):
    """
        Unbound, void of all separation, `suchasthis`
        """
    return cls.separator(value=cls.normalize(value), separator='')


def fireTransitionForVersions(state, transition_id):
    """Fire a transition for all versions in a state.
        """


def reset():
    """Reset UV projection

    """
    pass


def _validate_dependencies_met():
    """
    Verifies that PyOpenSSL's package-level dependencies have been met.
    Throws `ImportError` if they are not met.
    """
    from cryptography.x509.extensions import Extensions
    if getattr(Extensions, 'get_extension_for_class', None) is None:
        raise ImportError(
            "'cryptography' module missing required functionality.  Try upgrading to v1.3.4 or newer."
            )
    from OpenSSL.crypto import X509
    x509 = X509()
    if getattr(x509, '_x509', None) is None:
        raise ImportError(
            "'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer."
            )


def populate_obj(obj, data):
    """
    Populates an object with the data passed to it

    :param obj: Object to be populated
    :param data: The data to populate it with (dict)

    :returns: obj populated with data
    :rtype: obj.__class__

    """
    for name, value in data.items():
        if hasattr(obj, name):
            setattr(obj, name, value)
    return obj


def verlet(x, v, dt, a):
    """
    This is a simple implementation of the velocity verlet algorithm.
    INPUT
    x: scalar or vector of current positions
    v: scalar or vector of current velocities
    dt: scalar double of the current time step
    a: a function pointer to the acceleration function

    OUTPUT:
    xnew: scalar or vector of the updated positions. The data type (scalar or vector) will be the
          same as what is passed in to x, as the type will be infered.
    vnew: scalar of vector of the updated velocities. The data type (scalar or vector) will be the
          same as what is passed in to v, as the type will be infered.
    """
    xnew = x + v * dt + a(x) * dt ** 2 / 2
    vnew = v + (a(x) + a(xnew)) / 2 * dt
    return xnew, vnew


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

        :param TeamFolderChangeStatusType val:
        :rtype: EventType
        """
    return cls('team_folder_change_status', val)


def _eliminate_duplicates(l):
    """
    Removes duplicates from a list while maintaining the order of the elements (stable).
    :param l: The input list.
    :return: List with removed duplicates.
    """
    duplicate = [False] * len(l)
    for i1 in range(len(l)):
        e = l[i1]
        for i2 in range(i1 + 1, len(l)):
            if e == l[i2]:
                duplicate[i2] = True
    unique = []
    for i, d in zip(range(len(duplicate)), duplicate):
        if not d:
            unique.append(l[i])
    return unique


def delete_small(seqbuddy, min_value):
    """
    Deletes records with sequence smaller than a certain size
    :param seqbuddy: SeqBuddy object
    :param min_value: The minimum threshold for sequence length
    :return: The modified SeqBuddy object
    """
    retained_records = []
    for rec in seqbuddy.records:
        if len(str(rec.seq)) >= min_value:
            retained_records.append(rec)
    seqbuddy.records = retained_records
    return seqbuddy


def multires_reshape(modifier: str=''):
    """Copy vertex coordinates from other object

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    """
    pass


def mkdir(path, recursive=True, **kwargs):
    """Unix equivalent *mkdir*"""
    import os
    if recursive:
        os.makedirs(path, **kwargs)
    else:
        os.mkdir(path, **kwargs)


def get_computer_names():
    """
    Retrieve the list of computers in the DB.
    """
    from aiida.orm.querybuilder import QueryBuilder
    builder = QueryBuilder()
    builder.append(entity_type='computer', project=['name'])
    if builder.count() > 0:
        return next(zip(*builder.all()))
    return []


def read_file(fname):
    """
    read a CSV file (ref_classes.csv) and return the
    list of names
    """
    print('NO - dont use this function read_file(fname):')
    exit(1)
    lst = []
    with open(fname, 'r') as f:
        for line in f:
            lst.append(line.strip('\n'))
    return lst


def _rewrite_if_then_else(schema):
    """
    Rewrites the "if", "then" and "else" properties by converting it into a "oneOf"
    property.
    """
    if_ = schema.get('if')
    then_ = schema.get('then')
    else_ = schema.get('else', {})
    if not (if_ and then_):
        return schema
    schema['oneOf'] = [{'allOf': [if_, then_]}, {'allOf': [{'not': if_},
        else_]}]
    del schema['if']
    del schema['then']
    del schema['else']
    return schema


def from_none(exc):
    """raise from_none(ValueError('a')) == raise ValueError('a') from None"""
    exc.__cause__ = None
    exc.__suppress_context__ = True
    return exc


def checkHasAllTags(tags):
    """
        Проверить, содержит ли сообщение все указанные тэги.

        @param tags: список тэгов
        @type tags: C{list(str)}
        @return: содержит ли все указанные тэги?
        @rtype: C{bool}
        """


def split_ranges(total, after=False, before=False):
    """
    Given a range 1, 2, ..., total (page numbers of a doc).
    Split it in two lists.
    Example:
    Input: total = 9, after=1, before=False
    Output: list1 = [1]; list2 = [2, 3, 4, ..., 9].

    Input: total = 9; after=False, before=1
    Output: list1 = [], list2 = [1, 2, 3, 4, ..., 9]

    Input: total = 5; after=4; before=False
    Output: list1 = [1, 2, 3, 4] list2 = [5]

    Input: total = 5; after=False; before=False;
    Output: list1 = [1, 2, 3, 4, 5], list2 = []
    (it means, by default, all pages are inserted at the end of the doc)
    """
    if after and not before:
        if not isinstance(after, int):
            raise ValueError("argument 'after' is supposed to be an int")
        list1 = list(range(1, after + 1))
        list2 = list(range(after + 1, total + 1))
        return list1, list2
    if not after and before:
        if not isinstance(before, int):
            raise ValueError("argument 'before' is supposed to be an int")
        list1 = list(range(1, before))
        list2 = list(range(before, total + 1))
        return list1, list2
    list1 = list(range(1, total + 1))
    list2 = []
    return list1, list2


@classmethod
def from_kwargs(cls, *, charge=0, phase=None, **kwargs):
    """
		Create a new :class:`Species` object from keyword arguments representing the elements in the compound

		:param charge:
		:type charge: int, optional

		:rtype: :class:`Formula`
		"""
    return cls(kwargs, charge=charge, phase=phase)


def slow_parent_set():
    """Set the object’s slow parent

    """
    pass