def fetch_bases(samFile, chrom, POS, cell_tag='CR', UMI_tag='UR', min_MAPQ=
    20, max_FLAG=255, min_LEN=30):
    """ Fetch bases from all reads mapped to a given genome position.
    Filtering is also applied, including cell and UMI tags and read mapping 
    quality.
    """
    base_list, qual_list, UMIs_list, cell_list = [], [], [], []
    if samFile is None or chrom is None or POS is None:
        if samFile is None:
            print('Warning: samFile is None')
        if chrom is None:
            print('Warning: chrom is None')
        if POS is None:
            print('Warning: POS is None')
        return base_list, qual_list, UMIs_list, cell_list
    if type(POS) != int:
        POS = int(POS)
    for _read in samFile.fetch(chrom, POS - 1, POS):
        try:
            idx = _read.positions.index(POS - 1)
        except:
            continue
        if _read.mapq < min_MAPQ or _read.flag > max_FLAG or len(_read.
            positions) < min_LEN:
            continue
        if cell_tag is not None and _read.has_tag(cell_tag) == False:
            continue
        if UMI_tag is not None and _read.has_tag(UMI_tag) == False:
            continue
        if UMI_tag is not None:
            UMIs_list.append(_read.get_tag(UMI_tag))
        if cell_tag is not None:
            cell_list.append(_read.get_tag(cell_tag))
        _base = _read.query_alignment_sequence[idx].upper()
        base_list.append(_base)
        qual_list.append(_read.qqual[idx])
    return base_list, qual_list, UMIs_list, cell_list
