Code overview - Pa-Tou/stoat GitHub Wiki

This page goes through the broad steps of the pipeline and where the code can be found. Note that some of the line numbers of the links may be a bit off but they all point to the correct file so there should be enough context to figure out what they're supposed to be pointing at. The general workflow of the pipeline is to run either stoat graph or stoat vcf to produce an intermediate genotype file, then run stoat test to do the statistics on it.

Important classes

  • SnarlDataCollection: used to store per-snarl information.
    • Internally, the SnarlDataCollection stores per-snarl information as a snarl_info_internal_t. It exposes to the user a snarl_info_t when accessing snarls.
    • Information is added to the SnarlDataCollection using SnarlDataCollection.fill_in_snarl_info() which will go through all snarls in the snarl tree and call the user-provided functions to find the user-specified information about each snarl. Since different use cases require different information (alleles, genotypes, walks, sequences), this function takes several bools to specify which information should be filled in and in which order, and the user provides functions to find this information given a snarl. The class provides some default functions that can be used as input to fill_in_snarl_info()
    • The information stored in the SnarlDataCollection can be written to a file using write_snarl_data_collection() and loaded from a file using load_snarl_data_collection().
  • VCFParser: parse a VCF and optionally resolve conflicting calls.
  • EdgeBySampleMatrix: used to keep track of which edges in the graph are traversed by which samples, according to the VCF. Can be queried to find which samples are on a given path.
  • FeatureBySampleTable: generic class for storing per-sample information
  • PathTraversal: represents a path through the graph/netgraph. Contains the walk and the minimum and maximum lengths of the path (the length could be different depending on paths through nested snarls).
  • SnarlAnalyzer: put all the data together and test it
  • Classes for doing statistics
  • Writer: Write the output
  • snarl traversals: This isn't actually a class but I put the code for finding walks through snarls here.
    • There are two functions here, one for finding all possible walks through the snarl's netgraph and one that follows paths in the GBWT to only find walks supported by haplotype paths.
  • SnarlCoordinates: Hold information for finding the reference coordinates of snarls

Subcommand workflow

stoat graph

stoat graph takes as input a graph with embedded haplotypes and fills in a SnarlDataCollection by calling fill_in_snarl_info(). For each snarl, this partitions the haplotype paths based on the walk they take through the snarl's netgraph then (optionally) finds the actual walks of each allele. It then writes an intermediate snarl file containing the genotype for each embedded path.

There are two methods for partitioning paths in snarls.

  • partition_embedded_paths_in_snarl(): partition paths by the set of edges that they include, taking into account the number and ordering of edges leaving the same node. The walks can then be found using get_walks_from_alleles()
  • partition_embedded_paths_in_snarl_with_gbwt(): partition paths by tracing their walks through the snarl netgraph. Since the walks will be found during this process, there is no extra step to find the walks, they are just saved as the snarl collection gets filled in. This is faster than the other method when using a gbwt/r-index due to the cost of certain operations using a gbwt.

stoat vcf

stoat vcf runs through the snarls twice: once to find all possible paths through every snarl (the potential alleles), and a second time to match the samples in the VCF to the alleles found in the snarls. An intermediate snarl file can be written after each of these steps. The general algorithm is:

  1. Fill in the SnarlDataCollection with all possible walks through each snarl netgraph (the alleles for the snarl). This is done using the get_all_(haplotype_)walks_through_snarl() function. The intermediate snarls file can be written here containing the walks but not genotypes.
  2. Find the genotypes of samples in the VCF by calling genotype_snarls_by_chr_from_vcf(). Per chromosome (or potentially chunk of VCF, as long as chunks are non-overlapping along the top-level chain), this does:
    1. Parse the VCF with a VCFParser, optionally resolving contradictions in the calls.
    2. Build an EdgeBySampleMatrix for the chromosome. For each sample, the matrix stores a boolean for whether or not the sample traverses each edge. The edges found from the VCF are added to the EdgeBySampleMatrix by calling load_vcf_chunk().
    3. Assign an allele to each sample by calling add_alleles_by_sample() with a function that matches the alleles found in step 1 with the sample's path stored in the edge matrix.
  3. Write the SnarlDataCollection to an intermediate file containing genotypes.

stoat test

This is where all the statistics happens. It takes as input a phenotype file and the intermediate genotype file from either stoat graph or stoat vcf.

  1. The genotypes file is loaded as a SnarlDataCollection
  2. The phenotype file is loaded as the appropriate type of FeatureBySampleTable
  3. A SnarlAnalyzer puts all the data together with some additional stats functions and does statistics.
  4. The final output is written using a Writer

Common utilities