Collect the read evidence support for the given variants.

    Parameters
    ----------

    variants : iterable of varcode.Variant

    allele_support_df : dataframe
        Allele support dataframe, as output by the varlens-allele-support tool.
        It should have columns: source, contig, interbase_start, interbase_end,
        allele. The remaining columns are interpreted as read counts of various
        subsets of reads (e.g. all reads, non-duplicate reads, etc.)

    ignore_missing : boolean
        If True, then varaints with no allele counts will be interpreted as
        having 0 depth. If False, then an exception will be raised if any
        variants have no allele counts.

    Returns
    ----------

    A pandas.Panel4D frame with these axes:

    labels (axis=0) : the type of read being counted, i.e. the read count
        fields in allele_support_df.

    items (axis=1)  : the type of measurement (num_alt, num_ref, num_other,
        total_depth, alt_fraction, any_alt_fraction)

    major axis (axis=2) : the variants

    minor axis (axis=3) : the sources

def variant_support(variants, allele_support_df, ignore_missing=False):
    '''
    Collect the read evidence support for the given variants.

    Parameters
    ----------

    variants : iterable of varcode.Variant

    allele_support_df : dataframe
        Allele support dataframe, as output by the varlens-allele-support tool.
        It should have columns: source, contig, interbase_start, interbase_end,
        allele. The remaining columns are interpreted as read counts of various
        subsets of reads (e.g. all reads, non-duplicate reads, etc.)

    ignore_missing : boolean
        If True, then varaints with no allele counts will be interpreted as
        having 0 depth. If False, then an exception will be raised if any
        variants have no allele counts.

    Returns
    ----------

    A pandas.Panel4D frame with these axes:

    labels (axis=0) : the type of read being counted, i.e. the read count
        fields in allele_support_df.

    items (axis=1)  : the type of measurement (num_alt, num_ref, num_other,
        total_depth, alt_fraction, any_alt_fraction)

    major axis (axis=2) : the variants

    minor axis (axis=3) : the sources
    '''
    missing = [
        c for c in EXPECTED_COLUMNS if c not in allele_support_df.columns
    ]
    if missing:
        raise ValueError("Missing columns: %s" % " ".join(missing))

    # Ensure our start and end fields are ints.
    allele_support_df[["interbase_start", "interbase_end"]] = (
        allele_support_df[["interbase_start", "interbase_end"]].astype(int))

    sources = sorted(allele_support_df["source"].unique())

    allele_support_dict = collections.defaultdict(dict)
    for (i, row) in allele_support_df.iterrows():
        key = (
            row['source'],
            row.contig,
            row.interbase_start,
            row.interbase_end)
        allele_support_dict[key][row.allele] = row["count"]

    # We want an exception on bad lookups, so convert to a regular dict.
    allele_support_dict = dict(allele_support_dict)

    dataframe_dicts = collections.defaultdict(
        lambda: collections.defaultdict(list))

    for variant in variants:
        for source in sources:
            key = (source, variant.contig, variant.start - 1, variant.end)
            try:
                alleles = allele_support_dict[key]
            except KeyError:
                message = (
                    "No allele counts in source %s for variant %s" % (
                        source, str(variant)))
                if ignore_missing:
                    logging.warning(message)
                    alleles = {}
                else:
                    raise ValueError(message)

            alt = alleles.get(variant.alt, 0)
            ref = alleles.get(variant.ref, 0)
            total = sum(alleles.values())

            other = total - alt - ref

            dataframe_dicts["num_alt"][source].append(alt)
            dataframe_dicts["num_ref"][source].append(ref)
            dataframe_dicts["num_other"][source].append(other)
            dataframe_dicts["total_depth"][source].append(total)
            dataframe_dicts["alt_fraction"][source].append(
                float(alt) / max(1, total))
            dataframe_dicts["any_alt_fraction"][source].append(
                float(alt + other) / max(1, total))

    dataframes = dict(
        (label, pandas.DataFrame(value, index=variants))
        for (label, value) in dataframe_dicts.items())

    return pandas.Panel(dataframes)