import collections


def process_reads(alns, var_pos, min_mq, min_bq):
    """
    Read alignments from an iterator/iterable and makes observations for known
    variant positions. Each read is simplified into a signature of observed
    base per variant site.

    Args:
        alns: An iterator/iterable of pysam AlignedSegments
        var_pos: A sorted list of all known variant positions from Phylotree.
        min_mq: The minimum mapping quality score required for a read to be
                considered.
        min_bq: The minimum base quality score required for a base observation.

    Returns:
        read_obs: A dictionary that maps AlignedSegment query_names to
                  dictionaries mapping reference positions to base
                  observations.
    """
    read_obs = collections.defaultdict(dict)
    var_pos = set(var_pos)
    for aln in alns:
        if aln.mapping_quality >= min_mq:
            for qpos, rpos in aln.get_aligned_pairs(matches_only=True):
                qpos = int(qpos)
                rpos = int(rpos)
                if (aln.query_qualities is None
                        or aln.query_qualities[qpos] >= min_bq):
                    if rpos in var_pos:
                        obs = aln.query_sequence[qpos].upper()
                        # Add this to the list, if this is a known var site.
                        if rpos in read_obs[aln.query_name]:
                            # check if this position has been observed before.
                            if read_obs[aln.query_name][rpos] != obs:
                                read_obs[aln.query_name][rpos] = "N"
                        else:
                            read_obs[aln.query_name][rpos] = obs
    # Finished, do one pass to remove Ns
    for aln_id in read_obs:
        read_obs[aln_id] = {pos:base for pos, base in
                            list(read_obs[aln_id].items()) if base != 'N'}
    return read_obs