Skip to Content
ReferenceAPIResistance interpretation

Resistance interpretation

Turning variant calls into HIV-1 drug-resistance calls. The scoring engine reproduces 3,348 published Stanford expectations exactly; see validation.

Positions must be in whole-genome HXB2 K03455 coordinates. A reference numbered any other way — a pol-relative one is the case that matters — is refused before any compute, as a ReferenceFrameError; declare the frame it is numbered along with lg.reference(..., frame=(...)). This was silent until the SAWA evaluation found it.

ResistanceReport

class ResistanceReport(core: '_core.Dataset') -> 'None'

An interpreted drug-resistance report.

ResistanceReport.applicable

applicable: tuple[str, ...] # property

The dimensions that mean anything for this kind of data.

A dimension outside this set is not a gap to be filled in: asking a FASTA for its quality encoding is a category error.

ResistanceReport.contigs

contigs: list[Contig] | None # property

The contigs of the reference this data is on, in file order.

ResistanceReport.dimension

dimension(self, name: 'str') -> 'DimensionValue | None'

One dimension’s value, or None if it is unknown or inapplicable.

ResistanceReport.dimensions

dimensions: Mapping[str, DimensionValue] # property

Every dimension that has a known value, by name.

ResistanceReport.file

file: str # property

The file this data is, for code that has to open it.

path is the honest answer to “where did this come from, if anywhere?”, so it can be None — a step’s output carries dimensions worked out before anything ran, and has no file of its own until it does. This is the answer for the other question, the one a lg.write body asks:

return lg.write(lambda out: interpret(v.file, out))

Inside that function the steps above have run, so there is a file, and saying so in the type is what keeps a body from having to prove it.

Raises

RaisesWhen
ValueErrorIf this data has no file behind it at all.

ResistanceReport.files

files: tuple[str, ...] # property

Every file this data is, in order.

One for most kinds and two for a pair of FASTQ mates, in mate order. file names the primary one, which is what a message quotes; this is what code that has to open all of them wants.

ResistanceReport.kind

kind: str # property

The name of the kind of data this holds.

ResistanceReport.notes

notes: tuple[str, ...] # property

What loading this noticed, as one sentence each.

Usually empty. A note is not a failure and never stops anything: it is something true of the data that you cannot act on without being told. A gene list is the file this exists for — its symbols can arrive already corrupted by a spreadsheet, which is a fact about the input rather than about any step, so no step’s output could report it.

ResistanceReport.origin

origin: RemoteOrigin | None # property

Where this was fetched from, or None if it was not fetched.

The overwhelming majority of inputs are files somebody has, and for those this says nothing by being None.

ResistanceReport.path

path: str | None # property

The file this was loaded from.

ResistanceReport.samples

samples: list[str] | None # property

The samples this data covers, in order.

ResistanceReport.unknown_reason

unknown_reason(self, name: 'str') -> 'str | None'

Why an applicable dimension has no value.

None when the dimension is known, or when it does not apply to this kind of data at all.

hivdb.interpret

interpret( variants: 'Variants', reference: 'Reference', *, coverage: 'Alignment | None' = None, algorithm: 'str' = 'HIVDB_9.8', mixture: 'float' = 0.15, depth: 'int' = 100, gene_coverage: 'float' = 0.8, ) -> 'ResistanceReport'

Score a sample’s variants against a vendored resistance algorithm.

Parameters

ParameterDescription
variantsThe calls to interpret.
referenceThe reference they were called against. Required: codons cannot be assembled without it.
coverageThe alignment the calls came from. Without it no position can be known to be unread and no codon can be phased, and the reading notes both assumptions — which the run report then says and pipe.run() carries on the step’s notes.
algorithmWhich vendored algorithm to use, from ALGORITHMS.
mixtureThe fraction of reads an allele must reach to count as present. Where both the reference and an alternate reach it the codon holds both amino acids, exactly as an ambiguous base does to Stanford’s own interpreter — taking the majority instead would discard the minority resistance that deep sequencing exists to find. With an alignment it also decides which combinations of those alleles are real: a VCF says what is at each position and not what travels together, so reads spanning a codon are counted as the triplets they carry and the codon holds the amino acids reaching this fraction of them.
depthThe depth a position must reach to count as read. A codon whose bases do not all reach it is reported as unread rather than as reference.
gene_coverageThe share of a gene’s scored codons — the ones algorithm’s rules name — that must be read for the gene to be assessed at all. A gene below it is reported as not assessed rather than scored against the little that was seen, because a gene whose scored positions are mostly unread scores zero, and zero reads as susceptible. Counted over the scored codons rather than the gene because a position no rule names cannot change an answer.

Returns

A recipe, typed as the report the step declares.

Raises

RaisesWhen
ValueErrorIf algorithm is not one the engine ships. The error names the ones it does.
ReferenceFrameErrorWhen the recipe runs, if reference cannot be the frame the gene windows are stated in. A pipeline is refused earlier than this, by check(), where the reference’s declared frame is known.

hivdb.fingerprint

fingerprint() -> 'str'

What the vendored algorithms are, and which engine reads them.

This is what a step declaring tool="hivdb" records as its tool version, so it is what puts the rules into the cache key. It names every vendored algorithm rather than only the one in use, because the engine probes versions before any step body has said which it wants.

It ends with this engine’s own version, because the rules are only half of what the step is: the other half is the engine’s judgements about reading them — which codons count as read, how much of a gene has to be — and those move between releases.

Returns

A line naming each algorithm, its version, its date and the BLAKE3 of its rules, then the version of the engine reading them.

hivdb.ALGORITHMS

hivdb.ALGORITHMS: tuple = ('HIVDB_10.2', 'HIVDB_9.8')

hivdb.DEFAULT

hivdb.DEFAULT: str = 'HIVDB_9.8'

hivdb.MIXTURE

hivdb.MIXTURE: float = 0.15

hivdb.DEPTH

hivdb.DEPTH: int = 100

hivdb.GENE_COVERAGE

hivdb.GENE_COVERAGE: float = 0.8
Last updated on