'Returns a dict with the following attributes::
data - a list of reads with the format
[<guid>, <start>, <end>, <name>, <read_1>, <read_2>, [empty], <mapq_scores>]
where <read_1> has the format
[<start>, <end>, <cigar>, <strand>, <read_seq>]
and <read_2> has the format
[<start>, <end>, <cigar>, <strand>, <read_seq>]
Field 7 is empty so that mapq scores\' location matches that in single-end reads.
For single-end reads, read has format:
[<guid>, <start>, <end>, <name>, <cigar>, <strand>, <seq>, <mapq_score>]
NOTE: read end and sequence data are not valid for reads outside of
requested region and should not be used.
max_low - lowest coordinate for the returned reads
max_high - highest coordinate for the returned reads
message - error/informative message'

def process_data(self, iterator, start_val=0, max_vals=None, ref_seq=None, iterator_type='nth', mean_depth=None, start=0, end=0, **kwargs):

    if (iterator is None):
        return {'data': [], 'message': None}
    def decode_strand(read_flag, mask):
        '    Decode    strand    from    read    flag.    '
        strand_flag = ((read_flag & mask) == 0)
        if strand_flag:
            return '+'
        else:
            return '-'
    def _random_read_iterator(read_iterator, threshold):
        '\n                                                An    iterator    that    returns    a    random    stream    of    reads    from    the    read_iterator\n                                                as    well    as    corresponding    pairs    for    returned    reads.\n                                                threshold    is    a    value    in    [0,1]    that    denotes    the    percentage    of    reads\n                                                to    return.\n                                                '
        for e in read_iterator:
            if ((e.qname in paired_pending) or (random.uniform(0, 1) <= threshold)):
                (yield e)
    def _nth_read_iterator(read_iterator, threshold):
        '\n                                                An    iterator    that    returns    every    nth    read.\n                                                '
        n = int((1 / threshold))
        return itertools.islice(read_iterator, None, None, n)
    try:
        first_read = next(iterator)
    except StopIteration:
        return {'data': [], 'message': None, 'max_low': start, 'max_high': start}
    read_len = len(first_read.seq)
    num_reads = max((((end - start) * mean_depth) / float(read_len)), 1)
    threshold = (float(max_vals) / num_reads)
    iterator = itertools.chain(iter([first_read]), iterator)
    if ((iterator_type == 'sequential') or (threshold >= 1)):
        read_iterator = iterator
    elif (iterator_type == 'random'):
        read_iterator = _random_read_iterator(iterator, threshold)
    elif (iterator_type == 'nth'):
        read_iterator = _nth_read_iterator(iterator, threshold)
    results = []
    paired_pending = {}
    unmapped = 0
    message = None
    count = 0
    for read in read_iterator:
        if (count < start_val):
            continue
        if (((count - start_val) - unmapped) >= max_vals):
            message = (self.error_max_vals % (max_vals, 'reads'))
            break
        is_mapped = ((read.flag & 4) == 0)
        if (not is_mapped):
            unmapped += 1
            continue
        qname = read.qname
        seq = read.seq
        strand = decode_strand(read.flag, 16)
        if (read.cigar is not None):
            read_len = sum([cig[1] for cig in read.cigar])
        else:
            read_len = len(seq)
        if read.is_proper_pair:
            if (qname in paired_pending):
                pair = paired_pending[qname]
                results.append([hash(('%i_%s' % (pair['start'], qname))), pair['start'], (read.pos + read_len), qname, [pair['start'], pair['end'], pair['cigar'], pair['strand'], pair['seq']], [read.pos, (read.pos + read_len), read.cigar, strand, seq], None, [pair['mapq'], read.mapq]])
                del paired_pending[qname]
            else:
                paired_pending[qname] = {'start': read.pos, 'end': (read.pos + read_len), 'seq': seq, 'mate_start': read.mpos, 'rlen': read_len, 'strand': strand, 'cigar': read.cigar, 'mapq': read.mapq}
                count += 1
        else:
            results.append([hash(('%i_%s' % (read.pos, qname))), read.pos, (read.pos + read_len), qname, read.cigar, strand, read.seq, read.mapq])
            count += 1
    for (qname, read) in paired_pending.iteritems():
        if (read['mate_start'] < read['start']):
            read_start = read['mate_start']
            read_end = read['end']
            r1 = [read['mate_start'], read['mate_start']]
            r2 = [read['start'], read['end'], read['cigar'], read['strand'], read['seq']]
        else:
            read_start = read['start']
            read_end = read['mate_start']
            r1 = [read['start'], read['end'], read['cigar'], read['strand'], read['seq']]
            r2 = [read['mate_start'], read['mate_start']]
        results.append([hash(('%i_%s' % (read_start, qname))), read_start, read_end, qname, r1, r2, [read['mapq'], 125]])
    def compress_seq_and_cigar(read, start_field, cigar_field, seq_field):
        '\n                                                Use    reference-based    compression    to    compress    read    sequence    and    cigar.\n                                                '
        (read_seq, read_cigar) = get_ref_based_read_seq_and_cigar(read[seq_field].upper(), read[start_field], ref_seq.sequence, ref_seq.start, read[cigar_field])
        read[seq_field] = read_seq
        read[cigar_field] = read_cigar
    def convert_cigar(read, start_field, cigar_field, seq_field):
        '\n                                                Convert    read    cigar    from    pysam    format    to    string    format.\n                                                '
        cigar_ops = 'MIDNSHP=X'
        read_cigar = ''
        for op_tuple in read[cigar_field]:
            read_cigar += ('%i%s' % (op_tuple[1], cigar_ops[op_tuple[0]]))
        read[cigar_field] = read_cigar
    if ref_seq:
        ref_seq.sequence = ref_seq.sequence.upper()
        process_read = compress_seq_and_cigar
    else:
        process_read = convert_cigar
    for read in results:
        if isinstance(read[5], list):
            if (len(read[4]) > 2):
                process_read(read[4], 0, 2, 4)
            if (len(read[5]) > 2):
                process_read(read[5], 0, 2, 4)
        else:
            process_read(read, 1, 4, 6)
    (max_low, max_high) = get_bounds(results, 1, 2)
    return {'data': results, 'message': message, 'max_low': max_low, 'max_high': max_high}
