Important Caveats¶
This page documents behaviours and conventions that may surprise new users of the library.
hom/het defaults¶
By default, select_variants(),
count_variants(),
select_samples(), and
count_samples() set both hom=True and
het=True. This means queries include both homozygous and heterozygous
variants.
This diverges from the proto default (where hom and het are false
by default). The Python client defaults are chosen for the most common use
case — querying all variant genotypes.
To query only homozygous or only heterozygous variants, set one to False:
# Only heterozygous variants
for v in client.select_variants(
region=Region("chr17", 7661779, 7687546),
hom=False,
het=True,
):
print(v)
limit semantics¶
On select_variants(),
select_variants_with_stats(), and the inheritance
methods (select_de_novo(),
select_het_dominant(),
select_hom_recessive()), limit is a
hard global cap. You receive at most limit results regardless of cluster
topology. Each ring hard-caps its own per-request response, so the
client fetches in internal constant-window batches and trims to exactly
limit — meaning limit may exceed a ring’s per-request cap and is
still honoured (e.g. limit=50000 works even where each ring returns at most
5000 per request).
When limit=None a single request is issued and each ring returns up to its
per-ring cap (DatasetInfo.max_variants_per_ring, default 5000).
Results for large regions are therefore truncated — pass a limit or use
paginate_* to retrieve everything.
On select_samples() (and
select_samples_hom_ref()), skip and limit
have standard global semantics — the server aggregates sample results across
nodes before applying skip/limit, so limit=10 returns exactly 10 (or fewer
if exhausted) regardless of cluster topology.
Use paginate_* for full result sets¶
If you need offset-based pagination through large result sets, use the
paginate_* methods instead of manually managing limit. See
Pagination for details.
to_dataframe() memory warning¶
to_list() and
to_dataframe() are terminal operations that
materialise the entire stream into memory. For genome-wide queries, this may
require substantial memory.
Consider iterating with a for loop for large result sets:
# Memory-safe: processes one variant at a time
for v in client.select_variants(region=region):
process(v)
# Memory-intensive: loads everything into RAM
df = client.select_variants(region=region).to_dataframe()
0.0 sentinel for unannotated float fields¶
Annotation float fields on Variant and
VariantWithStats use 0.0 as a sentinel meaning
“not annotated”:
gnomad_exomes_afgnomad_genomes_afcadd_rawcadd_phredam_score
This mirrors the proto convention where the default float value (0.0) indicates
absence of annotation data. When processing these fields, check for 0.0
to distinguish between “annotated as zero” and “not annotated”:
for v in client.select_variants(region=region):
if v.gnomad_exomes_af != 0.0:
print(f"gnomAD exomes AF: {v.gnomad_exomes_af}")
else:
print("Not annotated in gnomAD exomes")