Upgrading to 2.0
immunum 2.0 makes every interface report errors the same way, finds every domain in a sequence, and fixes how flanking residues are segmented. Most code keeps working; this page lists what can break, by interface. The changelog has every change.
Every interface
Error messages lost their category prefix. The category is now a stable code: error_kind on
a result that failed (errorKind in JavaScript), and kind on an error that's raised or thrown.
Match on the code, not the message:
| 1.x message | 2.0 message | 2.0 code |
|---|---|---|
Invalid sequence: sequence length 4 is below minimum 30 |
sequence length 4 is below minimum 30 |
invalid_sequence |
Low confidence: 0.0416 < threshold 0.5000 |
alignment confidence 0.0416 is below min_confidence 0.5000 |
low_confidence |
Invalid chain type: unknown chain 'IGX' … |
unknown chain 'IGX' … |
invalid_chain |
The codes are listed under Errors.
segment keeps every residue. Residues the aligner leaves out before or after the domain
used to be dropped; they're now in prefix and postfix, so the regions always join back into
the sequence. A sequence with a leader or a constant region can get a longer prefix or
postfix than in 1.x, but the same FR and CDR regions.
min_confidence must be in [0, 1] in every interface; only Python checked it before.
Python
import immunum
annotator = immunum.Annotator(chains=["ig"], scheme="imgt")
result = annotator.number("AAAA")
# 1.x: result.error.startswith("Invalid sequence")
assert result.error_kind == "invalid_sequence"
try:
immunum.Annotator(chains=["IGX"], scheme="imgt")
except ValueError as e: # immunum.Error is a ValueError, so 1.x handlers still catch it
assert isinstance(e, immunum.Error)
assert e.kind == "invalid_chain"
SegmenationResultis renamedSegmentationResult.SegmentationResultlists its regions in sequence order,prefixfirst andpostfixlast, soas_dict()and the dataclass fields putprefixbeforefr1. In 1.x they came afterfr4.- Polars is an extra: install with
pip install "immunum[polars]"to useimmunum.polars.
Polars
number returns a numbering list of {position, residue} structs, with the fields Python's
Annotator.number returns: chain, scheme, confidence, numbering, query_start,
query_end, error and error_kind. 1.x returned positions and residues lists instead of
numbering. Code that read those lists can rebuild them:
import polars as pl
import immunum.polars as imp
df = pl.DataFrame({"sequence": [
"QVQLVQSGAEVKRPGSSVTVSCKASGGSFSTYALSWVRQAPGRGLEWMGGVIPLLTITNYAPRFQGRITITADRSTSTAYLELNSLRPEDTAVYYCAREGTTGKPIGAFAHWGQGTLVTVSS"
]})
numbering = df.select(
imp.number("sequence", chains=["ig"], scheme="imgt").struct.field("numbering")
)
lists = numbering.select(
pl.col("numbering").list.eval(pl.element().struct.field("position")).alias("positions"),
pl.col("numbering").list.eval(pl.element().struct.field("residue")).alias("residues"),
)
assert lists["positions"][0][:3].to_list() == ["1", "2", "3"]
assert lists["residues"][0][:3].to_list() == ["Q", "V", "Q"]
Or explode numbering and unnest it for one row per residue.
Numbering after a leader is fixed. For a sequence with residues before the domain, such as a
leader, 1.x Polars number paired each position with the residue that many places too early
(position 1 got the leader's first residue). 2.0 numbers it as every other interface does, so
these rows change.
numbering_method(expr, annotator=...)andsegmentation_method(expr, annotator=...)are deprecated and warn; usenumber(expr, annotator=...)andsegment(expr, annotator=...), which return the same.- An unknown chain or scheme name raises
immunum.Errorwhen you build the expression, not when the query runs. - Results carry
error_kindnext toerror.
JavaScript
const { Annotator } = require("immunum");
const annotator = new Annotator(["ig"], "imgt");
const sequence =
"QVQLVQSGAEVKRPGSSVTVSCKASGGSFSTYALSWVRQAPGRGLEWMGGVIPLLTITNYAPRFQGRITITADRSTSTAYLELNSLRPEDTAVYYCAREGTTGKPIGAFAHWGQGTLVTVSS";
const result = annotator.number(sequence);
result.queryStart; // 1.x: result.query_start
result.queryEnd; // 1.x: result.query_end
result.errorKind; // new: the code for a failed result
try {
new Annotator(["IGX"], "imgt");
} catch (e) {
// 1.x threw a string; 2.0 throws an Error with a `kind`
console.log(e.kind); // "invalid_chain"
console.log(e.message); // "unknown chain 'IGX' …"
}
- Results are camelCase throughout:
queryStart,queryEnd,errorKind. Every other field name is the same as in the other interfaces. - A failed
segmentresult sets every region tonull; 1.x left the region fields out.
CLI
- TSV output has an
error_kindcolumn aftererror, and JSON records anerror_kindfield. The columns before it are unchanged. - An argument is read as a sequence only when it's all letters. A path to a file that doesn't exist is an error (exit status 1); 1.x numbered it as a sequence and reported an invalid sequence.
Rust
Errors are split by how they're reported:
immunum::Erroris a setup mistake:InvalidChain,InvalidScheme,UnsupportedChain(wasInvalidScheme),InvalidMinConfidence,InvalidPosition,WrongSequence(wasInvalidSequence).immunum::SequenceErroris one sequence that couldn't be numbered:InvalidSequence,LowConfidence,DomainTooShort.Annotator::number,segment,domains,number_domainsandsegment_domainsreturn it.
use immunum::{Annotator, Chain, Scheme};
let annotator = Annotator::new(&[Chain::IGH], Scheme::IMGT, None)?; // immunum::Error
match annotator.number("AAAA") {
Ok(result) => println!("{:?}", result.chain),
Err(e) => println!("{}: {e}", e.kind()), // invalid_sequence: sequence length 4 …
}
- Both enums are
#[non_exhaustive]: add a_arm when you match on them. AlignmentError,ConsensusParseError,PositionMappingErrorandIoare gone.immunum::Result<T, E = Error>takes the error type as a second parameter.NumberedRecordandSegmentedRecordholdresult: Result<_, SequenceError>and are built withnew, instead ofsuccess/failureand separateresult/errorfields.ChainandSchemeparse errors areimmunum::Errorinstead ofstrum::ParseError.Chain::parse_chain_spec(spec)is removed; useChain::parse_names(spec.split(',')).- The
clifeature no longer bringschronoandtoml, and the crate needs Rust 1.89 or newer.