VCFLIB-API(1)

πŸ“¦
version 1.0.12 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– VCFLib API πŸ’–

okay bestie, welcome to vcflib-api(1) β€” this is the doc for the VCFLIB API, the way it gets used by all the vcflib modules and by the python ffi. and just so we're clear from the jump: vcflib follows the VCF standard, like, religiously. the spec lives at http://samtools.github.io/hts-specs/VCFv4.1.pdf if you wanna read it (it's giving textbook energy but it's the source of truth, so πŸ’…).


✨ the whole vibe (DESCRIPTION) ✨

ngl, VCFLIB has a lot going on β€” tons of functionality, so much. but the core thing you'll do, the thing that shows up in basically every module, is walking through a VCF file and grabbing info record by record. that part? super straightforward. you'll see it everywhere.

if you want a fresh example of it in the wild, go look at vcfwave. that's the recent one, that's the moment. πŸ‘‘


🌸 Open the VCF file 🌸

first things first, you gotta open the file. here's the ritual:

VariantCallFile variantFile;

if (optind < argc) {
    string filename = argv[optind];
    variantFile.open(filename);
} else {
    variantFile.open(std::cin);
}

if (!variantFile.is_open()) {
    return 1;
}

so like, if there's an arg left over (optind < argc), you grab the filename from argv[optind] and open that. otherwise? you just open std::cin, no big deal, we love a pipe-friendly icon. 🫢

and then the vibe check: if (!variantFile.is_open()) β€” if it's not open, return 1. no notes.


πŸ¦‹ Read records πŸ¦‹

now the fun part. this next bit parses the records for you, and you can print out the first two fields like this:

Variant var(variantFile);
while (variantFile.getNextVariant(var)) {
  cout << var.sequenceName << " " << var.position << endl;
}

literally that's it. getNextVariant keeps feeding you records until it can't, and you're just out here printing sequenceName and position. ate. πŸ”₯


πŸŽ€ Other fields πŸŽ€

in the file Variant.h (you can find it at https://github.com/vcflib/vcflib/blob/master/src/Variant.h), the Variant class is defined with a whole lil family of fields and accessors, like:

string sequenceName;
long position;
long zeroBasedPosition(void) const;
string id;
string ref;
vector<string> alt;      // a list of all the alternate alleles present at this locus
vector<string> alleles;  // a list all alleles (ref + alt) at this locus

to actually parse a file, go back up to the read records example β€” it's right there, bestie, it's the blueprint.

some things to know (important, write it down πŸ“): info fields get split into two buckets β€” the fields that have values live in info, and the flags that are just... true, live in infoFlags. BUT β€” and this is the cursed part β€” the order of info fields is not kept in the C++ map data structure. it's just not. so we have to keep track of the order ourselves, in an infoKeys vector. that's the workaround, that's the lore, iykyk. 😭


πŸ’… Output a VCF record πŸ’…

okay so the Variant class has a default string outputter, and it'll spit out a VCF record using the fields that are defined. watch:

Variant var(variantFile);
while (variantFile.getNextVariant(var)) {
  cout << var << endl;
}

and boom β€” that cout << var will output VCF. main character behavior fr fr. ✨


🧚 Mirroring in the Python FFI 🧚

the Python FFI follows this same API β€” like, it mirrors it β€” though fair warning: some accessors may get renamed along the way. πŸ™ˆ

if you wanna see the receipts, check pythonffi.cpp and pyvcflib.md. that's where it all lives.


and that's the whole page, bestie!! πŸ’œ tiny cute sign-off: the footer of this lil doc is literally just the coding cookie -- coding: utf-8 --() β€” no version numbers, no date, just the utf-8 vibe holding the whole thing together at the bottom. slay, encoding. πŸŒˆβ­πŸŽ€

πŸ“¦ where this page comes from