Genomic annotation

Labelling each AR set by its gene context — promoter, UTR, exon, intron, intergenic — with a Genes model parsed from a GTF.

Table of contents

  1. Why annotate
  2. Building a gene model
  3. Annotating a Loci set
  4. Pie charts per set

Why annotate

Where a regulatory element sits relative to genes is a first clue to how it acts. Distal enhancers cluster in introns and intergenic space; promoter-proximal sites suggest direct core-promoter regulation. Comparing the annotation breakdown of AR+F vs AR−F asks whether the two cistromes occupy different parts of the genome.

Building a gene model

Genes.make parses a GTF (here GENCODE v49, protein-coding) into a Genes object — a dictionary of genes, each with transcripts, exons, CDS and UTRs:

from genomeblocks import Genes

genes = Genes.make(GTF)            # GTF path; promoter_r defaults to 1000 bp

From these features Genes lazily derives the interval sets it needs for annotation — promoters (TSS ± promoter_r), exons, 5′/3′ UTRs, and gene bodies — and merges each.

Annotating a Loci set

genes.annotations(loci) returns a pandas.DataFrame with one row per input locus (uid) and its region class:

annot_pf = genes.annotations(ARpF)
annot_mf = genes.annotations(ARmF)

Each locus is assigned the first matching class in a fixed priority order, so every locus gets exactly one label:

class meaning
Promoter-TSS overlaps a TSS ± promoter_r window
5UTR / 3UTR overlaps a 5′ / 3′ UTR
Exonic overlaps an exon
Intronic inside a gene body but not the above
Intergenic none of the above

The priority order means a peak that touches both a promoter and an intron is called Promoter-TSS — the most specific, regulatorily-meaningful class wins.

Pie charts per set

A value_counts() on the annotation column gives the composition of each set, drawn as side-by-side pies:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2, figsize=(9, 4))
for ax, df, title in [(axes[0], annot_pf, "AR+F"), (axes[1], annot_mf, "AR-F")]:
    vc = df["annotation"].value_counts()
    ax.pie(vc.values, labels=vc.index, autopct="%1.0f%%", textprops={"fontsize": 7})
    ax.set_title(f"{title}  (n={len(df):,})")

A typical enhancer-dominated cistrome is mostly Intronic + Intergenic; a shift in the promoter fraction between AR+F and AR−F is the kind of difference this view surfaces.

annotations() is the lightweight, region-class labeller. genes also exposes nearest_genes(loci) to attach the closest gene to each peak — useful when you want to name targets rather than just classify location.

Next: Motif & ChIP-Atlas enrichment →


Copyright © 2024–2026 Umut Berkay Altintas. MIT Licensed.

This site uses Just the Docs, a documentation theme for Jekyll.