Skip to content

Input Formats

gbcms accepts VCF and MAF files as variant input.

VCF (Variant Call Format)

Standard VCF format with required fields:

#CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO
chr1    12345   .       A       T       .       PASS    .
chr2    67890   .       G       C       .       PASS    .

Requirements

  • Tab-separated
  • #CHROM, POS, REF, ALT columns required
  • 1-based positions

ALT Alleles

Each ALT allele of a record is genotyped as its own variant (a multi-allelic record gives one output row per ALT). An ALT allele that names no sequence to count is skipped, not genotyped: * (an overlapping deletion), symbolic alleles (<DEL>, <INS>, ...), breakends, a missing ALT (.), and any other allele with a base outside A/C/G/T/N. A record whose REF is not a base sequence (an empty REF reads as .) is skipped the same way. The first few skips are logged individually as WARNINGs and the totals once per file, by reason. An ALT containing N is kept: preparation reports it as a FAIL row (ALT_CONTAINS_N), and an ALT equal to its REF likewise (ALT_EQUALS_REF).

Variant Types

A record's type label comes from its alleles: INSERTION / DELETION only when the one-base allele is the other's first base (the shared anchor, e.g. T>TGT, TAA>T); every other unequal pair (a delins such as TTAC>A or C>TA) and every multi-base substitution is COMPLEX. gbcms normalize reports this label. Counting does not read it: reads are classified by the alleles themselves.

MAF (Mutation Annotation Format)

Standard MAF format with required columns:

Hugo_Symbol  Chromosome  Start_Position  End_Position  Reference_Allele  Tumor_Seq_Allele2
TP53         chr17       7577120         7577120       C                 T
KRAS         chr12       25398284        25398284      G                 A

Required Columns

Column Description
Chromosome Chromosome name
Start_Position 1-based start position
End_Position 1-based end position (optional: gbcms places a variant by Start_Position and its alleles; MAF output keeps the input's value)
Reference_Allele Reference allele
Tumor_Seq_Allele2 Alternate allele

Tumor_Seq_Allele1 is optional (see below).

MAF Alleles

Alleles are read as maf2vcf reads them:

  • The variant allele is Tumor_Seq_Allele2, or Tumor_Seq_Allele1 when Tumor_Seq_Allele2 is empty or equal to the reference (older MAFs put the variant there). How many rows were read that way is logged as a WARNING.
  • An allele made only of -, ? or 0 is a placeholder for an empty allele and is read as -.
  • A row whose variant allele still equals its reference describes no change; preparation reports it as a FAIL row (ALT_EQUALS_REF) rather than counting it.
  • An allele that is not a base sequence (anything but A, C, G, T and N in either case, or -), such as an IUPAC code or a stray character from a hand edit, makes the row a FAIL row (NON_SEQUENCE_ALLELE): kept in MAF output, not counted. Lowercase bases are bases.
  • A Tumor_Seq_Allele1 that differs from both the reference and Allele2 is not a second allele: one row, one allele (vcf2maf's reading). cBioPortal picks Allele1 for such rows.

MAF Indel Normalization

MAF represents indels using - dashes, while gbcms internally uses VCF-style anchor-based coordinates. When a MAF file contains insertions (Reference_Allele = -) or deletions (Tumor_Seq_Allele2 = -), gbcms automatically converts them at input time.

Reference FASTA Required

MAF indel conversion requires --fasta to fetch the anchor base from the reference genome. Without it, indel variants cannot be normalized and will be skipped.

flowchart TD
    MAF(["📄 MAF Row"]):::start --> Check{"REF or ALT is '-'?"}
    Check -->|"No — SNP/MNP"| Direct["VCF POS = Start_Position"]
    Check -->|"Yes — Indel"| Type{"Which is '-'?"}

    Type -->|"REF = '-' (Insertion)"| InsResult["POS = Start_Position\nAnchor @ Start_Position (from FASTA)\nREF = anchor\nALT = anchor + inserted seq"]
    Type -->|"ALT = '-' (Deletion)\n-1 for anchor"| DelResult["POS = Start_Position − 1\nAnchor @ Start_Position−1 (from FASTA)\nREF = anchor + deleted seq\nALT = anchor"]

    Direct --> Out(["🧬 Internal Variant"]):::pass
    InsResult --> Out
    DelResult --> Out

    classDef start fill:#9b59b6,color:#fff,stroke:#7d3c98,stroke-width:2px;
    classDef pass fill:#27ae60,color:#fff,stroke:#1e8449,stroke-width:2px;
Use mouse to pan and zoom

Insertion Example

Insert TG after chr1:100 (where the reference base at position 100 is A):

Field MAF VCF (internal)
Position Start_Position = 100 POS = 100
REF - A (fetched from FASTA)
ALT TG ATG (anchor + inserted seq)

Deletion Example

Delete CG at chr1:101–102 (where the reference base at position 100 is A):

Field MAF VCF (internal)
Position Start_Position = 101 (first deleted base) POS = 100 (anchor)
REF CG ACG (anchor + deleted seq)
ALT - A (anchor only)

Position Shift for Deletions

For insertions, Start_Position already points to the anchor base. For deletions, Start_Position points to the first deleted base, so gbcms shifts back by one position to find the anchor. A deletion at Start_Position 1 has no base before it: the base after it is appended instead (the VCF spec's form at position 1, as gbcms's VCF output writes it), and the row is counted as the same event given as VCF is. An insertion at Start_Position 0 lies before the contig's first base and has no anchor either: the first base is appended after the inserted bases (REF the first base, ALT the inserted bases then that base, at position 1), and the row is counted the same way. A reference whose first base is N (human contigs) makes that ALT contain N, so the row is kept as FAIL with ALT_CONTAINS_N. Any other row at Start_Position 0 (a substitution, a deletion, a delins, or an insertion written with sequence alleles) names a base that does not exist: it is kept as a FAIL row with reason START_BEFORE_CONTIG, not counted. (A negative Start_Position is not a position at all: that row is skipped with a warning.)

A MAF row whose alleles are both sequences (an SNP, an MNP, or a delins such as TTAC>A) is used as written, at Start_Position, with no anchor base.

Variant Left-Normalization

gbcms automatically left-aligns indels and complex variants during the preparation step. For full details on the normalization algorithm, homopolymer decomposition detection, and REF validation, see Variant Normalization.

Left-Align Your Variants

Inconsistently normalized variants reduce the effectiveness of windowed indel detection. While the ±5bp window will catch most aligner-shifted indels, left-alignment ensures the anchor position is consistent with standard conventions.

# VCF: use bcftools norm
bcftools norm -f reference.fa -o normalized.vcf input.vcf

Reference FASTA

  • Must have corresponding .fai index
  • The reference is looked up by the variant's contig under any name that contig goes by: as written, with or without a chr prefix, and, for the mitochondrion, as any of M / chrM / chrMT / MT. The FASTA and the variant file therefore reconcile the same way the BAM does (see below). A variant whose contig is absent from the FASTA under all of these names is rejected with verdict FAIL and reason FETCH_FAILED.
# Create index if missing
samtools faidx reference.fa

BAM/CRAM Requirements

  • Must have corresponding index (.bam.bai or .bai for BAM; .cram.crai or .crai for CRAM)
  • Coordinate-sorted
  • Chromosome naming is auto-reconciled: chr-prefix differences (chr1 ↔ 1) and mitochondrial aliases (M / chrM / chrMT / MT) between the BAM and the variant file are normalized automatically. Only a contig with no match in the BAM is skipped — and gbcms logs a one-time WARN for it, rather than silently returning zero counts.
  • Reconciliation is internal only: the output keeps the variant file's own contig naming (MAF Chromosome/vcf_region, VCF CHROM and its ##contig lines, rescue labels, mFSD Parquet). When the variant file's naming differs from the reference's or a BAM's, one INFO line per run names both. The Observations Parquet (--observations-parquet) echoes the internal (normalized) contig name.

CRAM Support (v5.3.0+)

Both --bam and --bam-list accept CRAM files transparently. The --fasta reference is automatically used for CRAM decoding. Index discovery is automatic — see Samplesheet.