def rdann(record_name, extension, sampfrom=0, sampto=None, shift_samps=False,
          pb_dir=None, return_label_elements=['symbol'],
          summarize_labels=False):
    """
    Read a WFDB annotation file record_name.extension and return an
    Annotation object.

    Parameters
    ----------
    record_name : str
        The record name of the WFDB annotation file. ie. for file '100.atr',
        record_name='100'.
    extension : str
        The annotatator extension of the annotation file. ie. for  file
        '100.atr', extension='atr'.
    sampfrom : int, optional
        The minimum sample number for annotations to be returned.
    sampto : int, optional
        The maximum sample number for annotations to be returned.
    shift_samps : bool, optional
        Specifies whether to return the sample indices relative to `sampfrom`
        (True), or sample 0 (False).
    pb_dir : str, optional
        Option used to stream data from Physiobank. The Physiobank database
        directory from which to find the required annotation file. eg. For
        record '100' in 'http://physionet.org/physiobank/database/mitdb':
        pb_dir='mitdb'.
    return_label_elements : list, optional
        The label elements that are to be returned from reading the annotation
        file. A list with at least one of the following options: 'symbol',
        'label_store', 'description'.
    summarize_labels : bool, optional
        If True, assign a summary table of the set of annotation labels
        contained in the file to the 'contained_labels' attribute of the
        returned object. This table will contain the columns:
        ['label_store', 'symbol', 'description', 'n_occurrences']

    Returns
    -------
    annotation : Annotation
        The Annotation object. Call help(wfdb.Annotation) for the attribute
        descriptions.

    Notes
    -----
    For every annotation sample, the annotation file explictly stores the
    'sample' and 'symbol' fields, but not necessarily the others. When reading
    annotation files using this function, fields which are not stored in the
    file will either take their default values of 0 or None, or will be carried
    over from their previous values if any.

    Examples
    --------
    >>> ann = wfdb.rdann('sample-data/100', 'atr', sampto=300000)

    """

    return_label_elements = check_read_inputs(sampfrom, sampto,
                                              return_label_elements)

    # Read the file in byte pairs
    filebytes = load_byte_pairs(record_name, extension, pb_dir)

    # Get wfdb annotation fields from the file bytes
    (sample, label_store, subtype,
     chan, num, aux_note) = proc_ann_bytes(filebytes, sampto)

    # Get the indices of annotations that hold definition information about
    # the entire annotation file, and other empty annotations to be removed.
    potential_definition_inds, rm_inds = get_special_inds(sample, label_store,
                                                          aux_note)

    # Try to extract information describing the annotation file
    (fs,
     custom_labels) = interpret_defintion_annotations(potential_definition_inds,
                                                      aux_note)

    # Remove annotations that do not store actual sample and label information
    (sample, label_store, subtype,
     chan, num, aux_note) = rm_empty_indices(rm_inds, sample, label_store,
                                             subtype, chan, num, aux_note)

    # Convert lists to numpy arrays dtype='int'
    (sample, label_store, subtype,
     chan, num) = lists_to_int_arrays(sample, label_store, subtype, chan, num)

    # Try to get fs from the header file if it is not contained in the
    # annotation file
    if fs is None:
        try:
            rec = record.rdheader(record_name, pb_dir)
            fs = rec.fs
        except:
            pass

    # Create the annotation object
    annotation = Annotation(record_name=os.path.split(record_name)[1],
                            extension=extension, sample=sample,
                            label_store=label_store,  subtype=subtype,
                            chan=chan, num=num, aux_note=aux_note, fs=fs,
                            custom_labels=custom_labels)

    # Apply the desired index range
    if sampfrom > 0 and sampto is not None:
        annotation.apply_range(sampfrom=sampfrom, sampto=sampto)

    # If specified, obtain annotation samples relative to the starting
    # index
    if shift_samps and len(sample) > 0 and sampfrom:
        annotation.sample = annotation.sample - sampfrom

    # Get the set of unique label definitions contained in this
    # annotation
    if summarize_labels:
        annotation.get_contained_labels(inplace=True)

    # Set/unset the desired label values
    annotation.set_label_elements(return_label_elements)

    return annotation
Read a WFDB annotation file record_name.extension and return an
    Annotation object.

    Parameters
    ----------
    record_name : str
        The record name of the WFDB annotation file. ie. for file '100.atr',
        record_name='100'.
    extension : str
        The annotatator extension of the annotation file. ie. for  file
        '100.atr', extension='atr'.
    sampfrom : int, optional
        The minimum sample number for annotations to be returned.
    sampto : int, optional
        The maximum sample number for annotations to be returned.
    shift_samps : bool, optional
        Specifies whether to return the sample indices relative to `sampfrom`
        (True), or sample 0 (False).
    pb_dir : str, optional
        Option used to stream data from Physiobank. The Physiobank database
        directory from which to find the required annotation file. eg. For
        record '100' in 'http://physionet.org/physiobank/database/mitdb':
        pb_dir='mitdb'.
    return_label_elements : list, optional
        The label elements that are to be returned from reading the annotation
        file. A list with at least one of the following options: 'symbol',
        'label_store', 'description'.
    summarize_labels : bool, optional
        If True, assign a summary table of the set of annotation labels
        contained in the file to the 'contained_labels' attribute of the
        returned object. This table will contain the columns:
        ['label_store', 'symbol', 'description', 'n_occurrences']

    Returns
    -------
    annotation : Annotation
        The Annotation object. Call help(wfdb.Annotation) for the attribute
        descriptions.

    Notes
    -----
    For every annotation sample, the annotation file explictly stores the
    'sample' and 'symbol' fields, but not necessarily the others. When reading
    annotation files using this function, fields which are not stored in the
    file will either take their default values of 0 or None, or will be carried
    over from their previous values if any.

    Examples
    --------
    >>> ann = wfdb.rdann('sample-data/100', 'atr', sampto=300000)