### Install cyvcf2 Source: https://github.com/brentp/cyvcf2/blob/main/docs/source/index.md Install the cyvcf2 library using pip. ```bash pip install cyvcf2 ``` -------------------------------- ### Install cyvcf2 with external htslib Source: https://github.com/brentp/cyvcf2/blob/main/README.md Use this command to install cyvcf2 when you need to link against an external system htslib.so. ```bash CYVCF2_HTSLIB_MODE=EXTERNAL python setup.py install ``` -------------------------------- ### Install cyvcf2 on Windows with System htslib using pip Source: https://github.com/brentp/cyvcf2/blob/main/README.md Install cyvcf2 on Windows using pip, with experimental support for MSYS2. This command assumes htslib has already been built and installed. It uses `SETUPTOOLS_USE_DISTUTILS=stdlib` to potentially resolve build issues. ```shell SETUPTOOLS_USE_DISTUTILS=stdlib pip install cyvcf2 ``` -------------------------------- ### Install cyvcf2 with System htslib using pip Source: https://github.com/brentp/cyvcf2/blob/main/README.md Install cyvcf2 using pip, linking against an externally installed htslib. Ensure htslib version 1.12 or higher is built and installed before running this command. This method is suitable if you manage htslib separately. ```shell CYVCF2_HTSLIB_MODE=EXTERNAL pip install --no-binary cyvcf2 cyvcf2 ``` -------------------------------- ### Run Tests Source: https://github.com/brentp/cyvcf2/blob/main/docs/source/index.md Install pytest and run the library's tests. ```bash pytest ``` -------------------------------- ### Build and Install cyvcf2 from GitHub Source Source: https://github.com/brentp/cyvcf2/blob/main/README.md Build cyvcf2 from its GitHub repository, including building htslib from source. This method is for developers or users who need the latest code or specific build configurations. Ensure `requirements.txt` is installed and consider cleaning old build files if necessary. ```shell git clone --recursive https://github.com/brentp/cyvcf2 pip install -r requirements.txt # sometimes it can be required to remove old files: # python setup.py clean_ext CYVCF2_HTSLIB_MODE=BUILTIN CYTHONIZE=1 python setup.py install ``` -------------------------------- ### Configure OpenSSL for compilation on OSX Source: https://github.com/brentp/cyvcf2/blob/main/README.md On OSX, if you encounter issues with compilers finding OpenSSL, set these environment variables before installation. This is often required when using Homebrew. ```bash export LDFLAGS="-L/usr/local/opt/openssl/lib" export CPPFLAGS="-I/usr/local/opt/openssl/include" ``` ```bash export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" ``` -------------------------------- ### Indexed Region Query with VCF.__call__ Source: https://context7.com/brentp/cyvcf2/llms.txt Performs an indexed region query on a VCF/BCF file using a tabix or CSI index. The region string format is "chrom:start-end". Each call restarts the iteration independently. Calling with no arguments iterates all records from the index start. ```python from cyvcf2 import VCF vcf = VCF("sample.vcf.gz") # must be bgzipped + tabix-indexed # Region query: chrom:1-based-start-end for v in vcf("1:10000-50000"): print(v.CHROM, v.POS, v.REF, v.ALT) # Whole-chromosome query for v in vcf("chr7"): if v.INFO.get("AF", 0) > 0.05: print(v.POS, v.INFO["AF"]) # Iterate all records via index (restarts cleanly each call) all_vars = list(vcf()) # uses HTS_IDX_START print(len(all_vars)) # total record count # BCF region query (uses CSI index automatically) bcf = VCF("sample.bcf") for v in bcf("chr1:69000-70000"): print(v.POS) bcf.close() vcf.close() ``` -------------------------------- ### Iterate and Access Variant Data in VCF Source: https://github.com/brentp/cyvcf2/blob/main/docs/source/index.md Iterate through variants in a VCF file and access common attributes like REF, ALT, CHROM, start, end, ID, FILTER, QUAL, and INFO fields. Also demonstrates accessing per-sample FORMAT fields using variant.format(). ```python from cyvcf2 import VCF for variant in VCF('some.vcf.gz'): # or VCF('some.bcf') variant.REF, variant.ALT # e.g. REF='A', ALT=['C', 'T'] variant.CHROM, variant.start, variant.end, variant.ID, \ variant.FILTER, variant.QUAL # numpy arrays of specific things we pull from the sample fields. # gt_types is array of 0,1,2,3==HOM_REF, HET, UNKNOWN, HOM_ALT variant.gt_types, variant.gt_ref_depths, variant.gt_alt_depths # numpy arrays variant.gt_phases, variant.gt_quals, variant.gt_bases # numpy array ## INFO Field. ## extract from the info field by it's name: variant.INFO.get('DP') # int variant.INFO.get('FS') # float variant.INFO.get('AC') # float # convert back to a string. str(variant) ## per-sample info... # Get a numpy array of the depth per sample: dp = variant.format('DP') # or of any other format field: sb = variant.format('SB') assert sb.shape == (n_samples, 4) # 4-values per # to do a region-query: vcf = VCF('some.vcf.gz') for v in vcf('11:435345-556565'): if v.INFO["AF"] > 0.1: continue print(str(v)) # to query "all records" via __call__: # this uses the index (HTS_IDX_START), so an index is required. # if no index is available, this yields zero records. all_vars = list(vcf()) # single sample of 0|1 in vcf becomes [[0, 1, True]] # 2 samples of 0/0 and 1|1 would be [[0, 0, False], [1, 1, True]] print v.genotypes ``` -------------------------------- ### VCF.__call__ - Indexed region query Source: https://context7.com/brentp/cyvcf2/llms.txt Allows querying variants within a specific genomic region using tabix or CSI indexes. Each call to the VCF object with a region string restarts the iteration independently and does not affect the main file iterator. An empty region string or no argument iterates all records from the index start. ```APIDOC ## VCF.__call__ - Indexed region query ### Description Returns an iterator over variants in a genomic region using a tabix or CSI index. The region string format is `"chrom:start-end"`. Calling with no argument or an empty string iterates all records from the index start. ### Parameters - **region** (str, optional) - The genomic region to query (e.g., `"1:10000-50000"`). If empty or omitted, iterates all records. ### Usage Examples ```python from cyvcf2 import VCF vcf = VCF("sample.vcf.gz") # must be bgzipped + tabix-indexed # Region query: chrom:1-based-start-end for v in vcf("1:10000-50000"): print(v.CHROM, v.POS, v.REF, v.ALT) # Whole-chromosome query for v in vcf("chr7"): if v.INFO.get("AF", 0) > 0.05: print(v.POS, v.INFO["AF"]) # Iterate all records via index (restarts cleanly each call) all_vars = list(vcf()) print(len(all_vars)) # BCF region query (uses CSI index automatically) bcf = VCF("sample.bcf") for v in bcf("chr1:69000-70000"): print(v.POS) bcf.close() vcf.close() ``` ``` -------------------------------- ### Writer - Create and write VCF/BCF output files Source: https://context7.com/brentp/cyvcf2/llms.txt Demonstrates how to create VCF/BCF output files using the Writer class. It covers inferring write modes from filenames, writing records, and creating writers from header strings. ```APIDOC ## Writer ### Description Creates an output file using a reader VCF as the header template. The write mode is inferred from the filename extension (`.vcf` → uncompressed VCF, `.vcf.gz` → compressed VCF, `.bcf` → compressed BCF) or set explicitly (`"w"`, `"wz"`, `"wb"`, `"wbu"`). ### Method `Writer(fname, tmpl, mode=None)` ### Parameters - `fname` (string) - The filename for the output VCF/BCF file. - `tmpl` (VCF object or string) - A VCF object to use as a header template, or a literal header string. - `mode` (string, optional) - Explicitly set the write mode (e.g., `"wz"` for gzipped VCF). ### Method `Writer.from_string(fname, header_string)` ### Description Creates a writer from a literal header string. ### Parameters - `fname` (string) - The filename for the output VCF/BCF file. - `header_string` (string) - The literal VCF header. ### Method `write_record(variant)` ### Description Writes a variant record to the output file. ### Parameters - `variant` (Variant object) - The variant to write. ### Method `variant_from_string(line)` ### Description Parses a raw VCF line into a `Variant` object for a `from_string` writer. ### Parameters - `line` (string) - A raw VCF line. ### Request Example ```python from cyvcf2 import VCF, Writer import numpy as np # Copy-and-annotate pattern vcf = VCF("input.vcf.gz") vcf.add_info_to_header({ 'ID': 'GENE', 'Number': '1', 'Type': 'String', 'Description': 'Gene annotation' }) with Writer("output.vcf.gz", vcf) as w: # mode inferred as "wz" for v in vcf: gene = lookup_gene(v.CHROM, v.start) # user-defined function if gene: v.INFO["GENE"] = gene # Modify FILTER if v.INFO.get("DP", 999) < 10: v.FILTER = ["LowDepth"] else: v.FILTER = "PASS" w.write_record(v) vcf.close() # Write to BCF vcf2 = VCF("input.vcf.gz") with Writer("output.bcf", vcf2) as w: # mode inferred as "wb" for v in vcf2: w.write_record(v) vcf2.close() # Writer.from_string: build from a header literal header = ( "##fileformat=VCFv4.2\n" "##FORMAT=\n" "##contig=\n" "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tSAMPLE1\n" ) w = Writer.from_string("scratch.vcf", header) var = w.variant_from_string("chr1\t100\t.\tA\tC\t60\tPASS\t.\tGT\t0/1") w.write_record(var) w.close() ``` ``` -------------------------------- ### Create and Write VCF/BCF Output Files Source: https://context7.com/brentp/cyvcf2/llms.txt Use Writer to create output files. The write mode is inferred from the filename extension or set explicitly. Writer.from_string creates a writer from a literal header string. variant_from_string parses a raw VCF line into a Variant. ```python from cyvcf2 import VCF, Writer import numpy as np # --- Copy-and-annotate pattern --- vcf = VCF("input.vcf.gz") vcf.add_info_to_header({ 'ID': 'GENE', 'Number': '1', 'Type': 'String', 'Description': 'Gene annotation' }) with Writer("output.vcf.gz", vcf) as w: # mode inferred as "wz" for v in vcf: gene = lookup_gene(v.CHROM, v.start) # user-defined function if gene: v.INFO["GENE"] = gene # Modify FILTER if v.INFO.get("DP", 999) < 10: v.FILTER = ["LowDepth"] else: v.FILTER = "PASS" w.write_record(v) vcf.close() # --- Write to BCF --- vcf2 = VCF("input.vcf.gz") with Writer("output.bcf", vcf2) as w: # mode inferred as "wb" for v in vcf2: w.write_record(v) vcf2.close() # --- Writer.from_string: build from a header literal --- header = ( "##fileformat=VCFv4.2\n" "##FORMAT=\n" "##contig=\n" "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tSAMPLE1\n" ) w = Writer.from_string("scratch.vcf", header) var = w.variant_from_string("chr1\t100\t.\tA\tC\t60\tPASS\t.\tGT\t0/1") w.write_record(var) w.close() ``` -------------------------------- ### cyvcf2 CLI help Source: https://github.com/brentp/cyvcf2/blob/main/README.md Display the help message for the cyvcf2 command-line interface. This shows available options for parsing VCF files directly from the terminal. ```bash $ cyvcf2 --help ``` -------------------------------- ### VCF.set_samples and VCF.set_index Source: https://context7.com/brentp/cyvcf2/llms.txt Covers methods for controlling sample inclusion and specifying index files for faster querying. ```APIDOC ## VCF.set_samples and VCF.set_index ### Description Methods to control sample columns and specify index files for efficient region queries. ### Method `vcf.set_samples(samples)` ### Description Restricts the sample columns after opening the VCF file. Must be called before iteration. Can accept a list of sample names, a comma-separated string, or an empty list to suppress all genotypes. ### Parameters - `samples` (list of strings or string) - The sample names to include, or `[]` to suppress genotypes. ### Method `vcf.set_index(index_path)` ### Description Loads a specific index file (`.tbi` or `.csi`) for region queries. ### Parameters - `index_path` (string) - The path to the index file. ### Property `vcf.num_records` ### Description Returns the total variant count from the index. This is much faster than iterating through all records. ### Request Example ```python from cyvcf2 import VCF # Subset to two samples after opening vcf = VCF("large_cohort.vcf.gz") print(len(vcf.samples)) # e.g. 1000 vcf.set_samples(["NA12878", "NA12891"]) print(len(vcf.samples)) # 2 v = next(iter(vcf)) print(v.gt_types.shape) # (2,) vcf.close() # Suppress all sample columns (faster if only INFO is needed) vcf = VCF("large_cohort.vcf.gz", samples=[]) for v in vcf: dp = v.INFO.get("DP") # INFO still available # v.gt_types, etc. will be empty arrays # Use a non-default index file vcf = VCF("data.vcf.gz") vcf.set_index("data.vcf.gz.tbi") for v in vcf("chr1:100000-200000"): print(v.POS) # Count records from index (much faster than iterating) vcf = VCF("data.bcf") print(vcf.num_records) # int vcf.close() ``` ``` -------------------------------- ### Query All Records Using Index in Python Source: https://github.com/brentp/cyvcf2/blob/main/README.md Retrieve all variants from a VCF/BCF file using the `__call__` method. This requires an index file (e.g., .tbi or .csi) to be present; otherwise, it will yield no records. ```Python # to query "all records" via __call__: # this uses the index (HTS_IDX_START), so an index is required. # if no index is available, this yields zero records. all_vars = list(vcf()) ``` -------------------------------- ### Access and Modify Variant INFO Fields with cyvcf2 Source: https://context7.com/brentp/cyvcf2/llms.txt Demonstrates safe and direct access to INFO fields, including typed values. Shows how to modify INFO fields in-place and delete them. Use INFO.get() for safe access with defaults. ```python from cyvcf2 import VCF with VCF("sample.vcf.gz") as vcf: for v in vcf: # Safe access with default dp = v.INFO.get("DP", 0) # int af = v.INFO.get("AF", None) # float or tuple of floats fs = v.INFO.get("FS", 0.0) # float flag= v.INFO.get("in_exac_flag", False) # bool (Flag type) # Direct access (KeyError if missing) try: ac = v.INFO["AC"] # int or tuple except KeyError: ac = None # Iterate all INFO key-value pairs info_dict = dict(v.INFO) # {key: typed_value, ...} # Modify INFO in-place v.INFO["DP"] = 42 # int v.INFO["AF"] = 0.123 # float v.INFO["GENE"] = "BRCA1" # str v.INFO["PASS_FLAG"] = True # Flag (set) / False (remove) # Delete an INFO field del v.INFO["DP"] print(v.CHROM, v.POS, info_dict) break ``` -------------------------------- ### Access and Modify Variant Genotypes Source: https://context7.com/brentp/cyvcf2/llms.txt Demonstrates accessing genotypes in both list-of-lists and Genotypes object formats. Shows how to modify genotypes and reassign them to the variant. Requires VCF and numpy imports. ```python from cyvcf2 import VCF, Writer import numpy as np, tempfile, os vcf = VCF("sample.vcf.gz") v = next(iter(vcf)) # List-of-lists representation: [[allele0, allele1, ..., is_phased], ...] gts = v.genotypes print(gts[0]) # e.g. [0, 0, False] → 0/0 unphased print(gts[1]) # e.g. [0, 1, True] → 0|1 phased # Modify and reassign genotypes for i in range(len(gts)): if gts[i][-1] is not None: # last element is phasing bool gts[i] = [0, 0, False] # set all to HOM_REF unphased v.genotypes = gts # must reassign for change to take effect # Genotypes object (mutable allele-level access) g = v.genotype # Genotypes object arr = g.array() # int16 array shape (n_samples, ploidy+1) # last column is phasing; allele columns use -1 for missing, -2 for padding print(arr[:3]) # e.g. [[0,0,0],[1,1,1],[0,1,0]] alleles_s0 = g.alleles(0) # list of allele indices for sample 0 phased_s0 = g.phased(0) # bool # Mutate individual allele via Allele object g[0][1].value = 1 # set second allele of sample 0 to alt g[0][1].phased = True # make it phased v.genotype = g # write back vcf.close() ``` -------------------------------- ### Access Sample Format Fields in Python Source: https://github.com/brentp/cyvcf2/blob/main/README.md Retrieve specific format fields (e.g., DP, SB) for all samples associated with a variant. The `format()` method returns a NumPy array, with `sb.shape` indicating the number of samples and the number of values per sample. ```Python # Get a numpy array of the depth per sample: dp = variant.format('DP') # or of any other format field: sb = variant.format('SB') assert sb.shape == (n_samples, 4) # 4-values per ``` -------------------------------- ### Sample QC Utilities: Relatedness and Heterozygosity Check Source: https://context7.com/brentp/cyvcf2/llms.txt Compute pairwise relatedness (kinship estimate) using IBS sharing with relatedness(), or assess per-sample heterozygosity and depth with het_check(). Both require gts012=True and return dictionaries with relevant QC metrics. ```python from cyvcf2 import VCF import warnings ``` -------------------------------- ### Check Heterozygosity and Depth in VCF Source: https://context7.com/brentp/cyvcf2/llms.txt Performs heterozygosity and depth checks for samples in a VCF file. Returns sample statistics, sites used, and a genotype matrix. Requires minimum depth per sample and uses percentiles for analysis. ```python import cyvcf2 vcf = cyvcf2.VCF("cohort.vcf.gz", gts012=True) sample_stats, sites_used, gt_matrix = vcf.het_check( min_depth=8, percentiles=(10, 90) ) for sample, stats in sample_stats.items(): print(f"{sample}: het_ratio={stats['het_ratio']:.3f} " f ``` -------------------------------- ### Extract Per-Sample Genotype Data with cyvcf2 Source: https://context7.com/brentp/cyvcf2/llms.txt Retrieves various per-sample genotype data as NumPy arrays, including genotype types, read depths, allele frequencies, phasing, quality, and bases. Arrays are backed by C memory and should be copied with np.array() for persistence. ```python from cyvcf2 import VCF import numpy as np with VCF("sample.vcf.gz", gts012=True) as vcf: n_samples = len(vcf.samples) for v in vcf: # Genotype classification: 0=HOM_REF, 1=HET, 2=HOM_ALT, 3=UNKNOWN gt_types = np.array(v.gt_types) # copy for safety; shape (n,) # Read depth arrays (from AD or RO/AO FORMAT fields) ref_dp = np.array(v.gt_ref_depths) # int32, -1 if missing alt_dp = np.array(v.gt_alt_depths) # int32, -1 if missing total = np.array(v.gt_depths) # ref + alt, -1 if both missing # Alt allele frequency per sample freqs = np.array(v.gt_alt_freqs) # float, -1 if unknown # Phasing and quality phases = np.array(v.gt_phases) # bool array quals = np.array(v.gt_quals) # float32, -1 if missing # String allele representation per sample bases = np.array(v.gt_bases) # e.g. ['A/A', 'A/C', './.'] # Genotype likelihood arrays (from PL or GL FORMAT fields) pl_ref = np.array(v.gt_phred_ll_homref) # int32 PL for HOM_REF pl_het = np.array(v.gt_phred_ll_het) # int32 PL for HET pl_alt = np.array(v.gt_phred_ll_homalt) # int32 PL for HOM_ALT # Aggregate statistics print(f"call_rate={v.call_rate:.3f} aaf={v.aaf:.4f}") print(f"hom_ref={v.num_hom_ref} het={v.num_het} " f"hom_alt={v.num_hom_alt} unknown={v.num_unknown}") # Filter to heterozygous samples with sufficient depth het_mask = (gt_types == vcf.HET) & (total >= 10) het_samples = np.array(vcf.samples)[het_mask] print("HET samples with depth>=10:", het_samples[:5]) break ``` -------------------------------- ### Subset Samples and Load Index Files Source: https://context7.com/brentp/cyvcf2/llms.txt Restrict sample columns after opening a VCF using set_samples, or suppress all genotypes for faster INFO-only processing. Load a specific index file for region queries with set_index. num_records returns the total variant count from the index. ```python from cyvcf2 import VCF # Subset to two samples after opening vcf = VCF("large_cohort.vcf.gz") print(len(vcf.samples)) # e.g. 1000 vcf.set_samples(["NA12878", "NA12891"]) print(len(vcf.samples)) # 2 v = next(iter(vcf)) print(v.gt_types.shape) # (2,) vcf.close() # Suppress all sample columns (faster if only INFO is needed) vcf = VCF("large_cohort.vcf.gz", samples=[]) for v in vcf: dp = v.INFO.get("DP") # INFO still available # v.gt_types, etc. will be empty arrays # Use a non-default index file vcf = VCF("data.vcf.gz") vcf.set_index("data.vcf.gz.tbi") for v in vcf("chr1:100000-200000"): print(v.POS) # Count records from index (much faster than iterating) vcf = VCF("data.bcf") print(vcf.num_records) # int vcf.close() ``` -------------------------------- ### VCF - Open and iterate a VCF/BCF file Source: https://context7.com/brentp/cyvcf2/llms.txt The VCF class opens VCF or BCF files for sequential iteration or indexed region queries. It supports various modes and options for genotype handling, lazy loading, strict genotype parsing, sample subsetting, and multi-threaded reading. The VCF object can be used as a context manager and an iterator. ```APIDOC ## VCF - Open and iterate a VCF/BCF file ### Description Opens a VCF or BCF file for sequential iteration or indexed region queries. Supports options like `gts012`, `lazy`, `strict_gt`, `samples`, and `threads`. The object is a context manager and an iterator. ### Parameters - **fname** (str) - Path to the VCF/BCF file. - **mode** (str, optional) - Mode for opening the file. Defaults to "r". - **gts012** (bool, optional) - If True, remaps genotype type constants (HOM_ALT=2, UNKNOWN=3). Defaults to False. - **lazy** (bool, optional) - If True, defers full record unpacking until a field is accessed. Defaults to False. - **strict_gt** (bool, optional) - If True, classifies any genotype containing '.' as UNKNOWN. Defaults to False. - **samples** (list[str], optional) - A list of sample names to restrict loaded columns. - **threads** (int, optional) - Number of threads to use for reading. ### Usage Examples ```python from cyvcf2 import VCF import numpy as np # Basic iteration vcf = VCF("sample.vcf.gz") print("Samples:", vcf.samples[:3]) print("Chromosomes:", vcf.seqnames[:5]) for variant in vcf: chrom = variant.CHROM pos = variant.POS start = variant.start end = variant.end vid = variant.ID ref = variant.REF alts = variant.ALT qual = variant.QUAL filt = variant.FILTER filters = variant.FILTERS break # show just one iteration vcf.close() # Context manager + gts012 mode with VCF("sample.vcf.gz", gts012=True) as vcf: v = next(iter(vcf)) print(v.gt_types) print(vcf.HOM_REF, vcf.HET, vcf.HOM_ALT, vcf.UNKNOWN) # Subset samples at open time with VCF("sample.vcf.gz", samples=["NA12878", "NA12891"]) as vcf: v = next(iter(vcf)) print(len(vcf.samples)) print(v.gt_types.shape) # Multi-threaded reading vcf = VCF("large.bcf", threads=4) count = sum(1 for _ in vcf) vcf.close() ``` ``` -------------------------------- ### Manipulate VCF Header Information Source: https://context7.com/brentp/cyvcf2/llms.txt Shows how to add, inspect, and remove INFO, FORMAT, and FILTER fields, as well as custom header lines. Requires VCF and Writer imports. ```python from cyvcf2 import VCF, Writer import tempfile, os vcf = VCF("sample.vcf.gz") # Add a new INFO field vcf.add_info_to_header({ 'ID': 'GENE', 'Number': '1', 'Type': 'String', 'Description': 'Overlapping gene name' }) # Add a new FORMAT field vcf.add_format_to_header({ 'ID': 'FILTER_CODE', 'Number': '1', 'Type': 'Integer', 'Description': 'Per-sample filter reason code' }) # Add a custom FILTER vcf.add_filter_to_header({ 'ID': 'LowDepth', 'Description': 'Total depth below threshold' }) # Add a raw header line vcf.add_to_header("##source=myPipeline_v1.0") # Inspect a header field csq_info = vcf["CSQ"] # dict with ID, Type, Number, Description print(csq_info["Type"]) # "String" # Check presence print("AF" in vcf) # True / False # Remove a header field vcf.add_info_to_header({'ID': 'TMPFIELD', 'Number': '.', 'Type': 'Float', 'Description': 'temp'}) vcf.remove_header('TMPFIELD') # header_iter: walk all header records for hrec in vcf.header_iter(): info = hrec.info() if info['HeaderType'] == 'INFO': print(info['ID'], info['Type'], info['Number']) vcf.close() ``` -------------------------------- ### Open and Iterate VCF/BCF Files with cyvcf2 Source: https://context7.com/brentp/cyvcf2/llms.txt Opens a VCF or BCF file for sequential iteration or indexed region queries. Supports options for genotype type remapping, lazy parsing, strict genotype handling, sample subsetting, and multi-threaded reading. The VCF object can be used as a context manager. ```python from cyvcf2 import VCF import numpy as np # --- Basic iteration --- vcf = VCF("sample.vcf.gz") print("Samples:", vcf.samples[:3]) # ['NA12878', 'NA12891', 'NA12892'] print("Chromosomes:", vcf.seqnames[:5]) # ['1', '2', '3', '4', '5'] for variant in vcf: # Core positional fields chrom = variant.CHROM # str, e.g. "1" pos = variant.POS # int, 1-based start = variant.start # int, 0-based end = variant.end # int vid = variant.ID # str or None ref = variant.REF # str, e.g. "A" alts = variant.ALT # list of str, e.g. ["C", "T"] qual = variant.QUAL # float or None filt = variant.FILTER # str, None for PASS/'.' filters= variant.FILTERS # list of str break # show just one iteration vcf.close() # --- Context manager + gts012 mode --- with VCF("sample.vcf.gz", gts012=True) as vcf: v = next(iter(vcf)) # gts012=True: 0=HOM_REF, 1=HET, 2=HOM_ALT, 3=UNKNOWN print(v.gt_types) # numpy int32 array, shape (n_samples,) print(vcf.HOM_REF, vcf.HET, vcf.HOM_ALT, vcf.UNKNOWN) # 0 1 2 3 # --- Subset samples at open time --- with VCF("sample.vcf.gz", samples=["NA12878", "NA12891"]) as vcf: v = next(iter(vcf)) print(len(vcf.samples)) # 2 print(v.gt_types.shape) # (2,) # --- Multi-threaded reading --- vcf = VCF("large.bcf", threads=4) count = sum(1 for _ in vcf) vcf.close() ``` -------------------------------- ### Perform Region Queries in Python Source: https://github.com/brentp/cyvcf2/blob/main/README.md Query a VCF/BCF file for variants within a specific genomic region. This method is efficient for targeted analysis. ```Python # to do a region-query: vcf = VCF('some.vcf.gz') for v in vcf('11:435345-556565'): if v.INFO["AF"] > 0.1: continue print(str(v)) ``` -------------------------------- ### Variant.genotypes / Variant.genotype — Structured genotype access Source: https://context7.com/brentp/cyvcf2/llms.txt Provides methods for accessing and modifying variant genotypes. `variant.genotypes` returns a list of per-sample allele lists, and can be used to set genotypes. `variant.genotype` returns a `Genotypes` object for more granular, mutable access to alleles and phasing information. ```APIDOC ## Variant.genotypes / Variant.genotype — Structured genotype access `variant.genotypes` returns a list of per-sample allele lists, each ending with a bool indicating phasing (e.g. `[0, 1, True]` for `0|1`). Setting `variant.genotypes = [...]` rewrites the GT field. `variant.genotype` returns a `Genotypes` object with `.array()`, `.alleles(i)`, `.phased(i)`, and per-allele `Allele` objects with mutable `.value` and `.phased`. ```python from cyvcf2 import VCF, Writer import numpy as np, tempfile, os vcf = VCF("sample.vcf.gz") v = next(iter(vcf)) # List-of-lists representation: [[allele0, allele1, ..., is_phased], ...] gts = v.genotypes print(gts[0]) # e.g. [0, 0, False] → 0/0 unphased print(gts[1]) # e.g. [0, 1, True] → 0|1 phased # Modify and reassign genotypes for i in range(len(gts)): if gts[i][-1] is not None: # last element is phasing bool gts[i] = [0, 0, False] # set all to HOM_REF unphased v.genotypes = gts # must reassign for change to take effect # Genotypes object (mutable allele-level access) g = v.genotype # Genotypes object arr = g.array() # int16 array shape (n_samples, ploidy+1) # last column is phasing; allele columns use -1 for missing, -2 for padding print(arr[:3]) # e.g. [[0,0,0],[1,1,1],[0,1,0]] alleles_s0 = g.alleles(0) # list of allele indices for sample 0 phased_s0 = g.phased(0) # bool # Mutate individual allele via Allele object g[0][1].value = 1 # set second allele of sample 0 to alt g[0][1].phased = True # make it phased v.genotype = g # write back vcf.close() ``` ``` -------------------------------- ### VCF.relatedness and VCF.het_check Source: https://context7.com/brentp/cyvcf2/llms.txt Provides utilities for sample quality control, including computing pairwise relatedness and assessing heterozygosity. ```APIDOC ## VCF.relatedness and VCF.het_check ### Description Sample QC utilities for computing pairwise relatedness and assessing heterozygosity. ### Method `vcf.relatedness(...)` ### Description Computes pairwise relatedness (kinship estimate) across all sample pairs using IBS sharing. Returns a dict with arrays `rel`, `ibs0`, `ibs2`, `sample_a`, `sample_b`, etc. ### Parameters - `gts012` (bool) - Must be set to `True`. ### Method `vcf.het_check(...)` ### Description Assesses per-sample heterozygosity and depth. Returns a per-sample dict with `het_ratio`, `mean_depth`, `median_depth`, percentile MAFs, and `range`. ### Parameters - `gts012` (bool) - Must be set to `True`. ### Request Example ```python from cyvcf2 import VCF import warnings # Example usage would typically involve opening a VCF and calling these methods. # Due to the nature of these functions (requiring a VCF object and specific parameters), # a direct runnable example without a VCF file is complex. The documentation # indicates their purpose and expected return types. # Placeholder for demonstration: # vcf = VCF("samples.vcf.gz") # relatedness_results = vcf.relatedness(gts012=True) # het_check_results = vcf.het_check(gts012=True) # print(relatedness_results) # print(het_check_results) # vcf.close() ``` ``` -------------------------------- ### Variant Genotype Arrays Source: https://context7.com/brentp/cyvcf2/llms.txt Provides access to per-sample genotype data as NumPy arrays. This includes genotype types, read depths, allele frequencies, phasing information, quality scores, and allele bases. These arrays are memory-backed and should be copied if persistence beyond the current iteration is needed. ```APIDOC ## Variant genotype arrays — NumPy per-sample genotype data `variant.gt_types`, `variant.gt_ref_depths`, `variant.gt_alt_depths`, `variant.gt_depths`, `variant.gt_bases`, `variant.gt_phases`, `variant.gt_quals`, and `variant.gt_alt_freqs` all return NumPy arrays of length `n_samples`. Arrays are backed by C memory tied to the variant's lifetime; copy with `np.array(...)` to persist beyond the current iteration. ```python from cyvcf2 import VCF import numpy as np with VCF("sample.vcf.gz", gts012=True) as vcf: n_samples = len(vcf.samples) for v in vcf: # Genotype classification: 0=HOM_REF, 1=HET, 2=HOM_ALT, 3=UNKNOWN gt_types = np.array(v.gt_types) # copy for safety; shape (n,) # Read depth arrays (from AD or RO/AO FORMAT fields) ref_dp = np.array(v.gt_ref_depths) # int32, -1 if missing alt_dp = np.array(v.gt_alt_depths) # int32, -1 if missing total = np.array(v.gt_depths) # ref + alt, -1 if both missing # Alt allele frequency per sample freqs = np.array(v.gt_alt_freqs) # float, -1 if unknown # Phasing and quality phases = np.array(v.gt_phases) # bool array quals = np.array(v.gt_quals) # float32, -1 if missing # String allele representation per sample bases = np.array(v.gt_bases) # e.g. ['A/A', 'A/C', './.'] # Genotype likelihood arrays (from PL or GL FORMAT fields) pl_ref = np.array(v.gt_phred_ll_homref) # int32 PL for HOM_REF pl_het = np.array(v.gt_phred_ll_het) # int32 PL for HET pl_alt = np.array(v.gt_phred_ll_homalt) # int32 PL for HOM_ALT # Aggregate statistics print(f"call_rate={v.call_rate:.3f} aaf={v.aaf:.4f}") print(f"hom_ref={v.num_hom_ref} het={v.num_het} " f"hom_alt={v.num_hom_alt} unknown={v.num_unknown}") # Filter to heterozygous samples with sufficient depth het_mask = (gt_types == vcf.HET) & (total >= 10) het_samples = np.array(vcf.samples)[het_mask] print("HET samples with depth>=10:", het_samples[:5]) break ``` ``` -------------------------------- ### Variant.INFO Access and Modification Source: https://context7.com/brentp/cyvcf2/llms.txt Demonstrates how to access and modify the INFO field of a VCF variant. The INFO field behaves like a dictionary, returning typed values based on the VCF header. It supports safe access with .get(), direct access with [], modification with assignment, and deletion with 'del'. ```APIDOC ## Variant.INFO — Access and modify the INFO field `variant.INFO` is a dict-like object that returns typed values (int, float, str, tuple, bool) according to the VCF header definition. Use `INFO.get(key, default)` for safe access, `INFO[key]` for direct access (raises `KeyError` if absent), `INFO[key] = value` to set a value, and `del INFO[key]` to remove a field. ```python from cyvcf2 import VCF with VCF("sample.vcf.gz") as vcf: for v in vcf: # Safe access with default dp = v.INFO.get("DP", 0) # int af = v.INFO.get("AF", None) # float or tuple of floats fs = v.INFO.get("FS", 0.0) # float flag= v.INFO.get("in_exac_flag", False) # bool (Flag type) # Direct access (KeyError if missing) try: ac = v.INFO["AC"] except KeyError: ac = None # Iterate all INFO key-value pairs info_dict = dict(v.INFO) # {key: typed_value, ...} # Modify INFO in-place v.INFO["DP"] = 42 # int v.INFO["AF"] = 0.123 # float v.INFO["GENE"] = "BRCA1" # str v.INFO["PASS_FLAG"] = True # Flag (set) / False (remove) # Delete an INFO field del v.INFO["DP"] print(v.CHROM, v.POS, info_dict) break ``` ``` -------------------------------- ### Variant.format() - Extract Per-Sample FORMAT Fields Source: https://context7.com/brentp/cyvcf2/llms.txt Explains how to use the `variant.format(field, vtype=None)` method to extract specific FORMAT fields from VCF records as 2-D NumPy arrays. The `vtype` parameter allows specifying the expected data type (int, float, str), which is inferred if omitted. The method returns `None` if the field is not present for the record. ```APIDOC ## Variant.format() — Extract per-sample FORMAT fields as NumPy arrays `variant.format(field, vtype=None)` returns a 2-D NumPy array of shape `(n_samples, values_per_sample)` for any FORMAT field defined in the header. `vtype` can be `int`, `float`, or `str`; if omitted it is inferred from the header. Returns `None` if the field is absent for that record. ```python from cyvcf2 import VCF import numpy as np with VCF("sample.vcf.gz") as vcf: for v in vcf: # PL (phred-scaled genotype likelihoods) — 3 values per diploid sample pl = v.format("PL", int) if pl is not None: assert pl.shape == (len(vcf.samples), 3) print("PL sample 0:", pl[0]) # e.g. [0, 7, 922] # DP per sample — 1 value per sample dp = v.format("DP", int) if dp is not None: assert dp.shape == (len(vcf.samples), 1) # SB (strand bias) — 4 values per sample sb = v.format("SB", int) if sb is not None: assert sb.shape == (len(vcf.samples), 4) # String FORMAT field gt_str = v.format("GT", str) if gt_str is not None: print("GT strings:", gt_str[:3]) # ['0/0', '0/1', '1/1'] break ``` ```