BUG FIXES:
inferGenotypeAllele() duplicated rows and inflated the per-locus depth when
the threshold table held more than one row per genotyped allele. The table is
joined into the genotype counts with all.x = TRUE, so a repeated key produced
one output row per threshold row, each carrying that allele's whole count.
Because depth is a shared denominator, this was not confined to the duplicated
rows: every row reported the inflated depth, and z_score moved with it, so the
genotype call itself could change. With four alleles collapsing into one cluster,
a true read count of 42 was reported as 108 and the cluster's z-score fell from
339 to 212.
The join key is now reduced to one row per genotyped allele. Two situations
triggered it. With asc_annotation = TRUE the key is asc_allele, which is
non-unique by design since collapsing several alleles into one similarity cluster
is the point, and the bundled allele_threshold_table has seven such rows. With
asc_annotation = FALSE the key is allele, which a caller-supplied table can
repeat. Output is unchanged wherever the key was already unique, verified against
1.5.1 on the bundled table.
inferGenotypeAllele() failed when the threshold table had no asc_allele
column and the data contained an allele the table did not list. The appended row
named asc_allele literally, so a three-column table received a four-column row
and rbind failed with a column-count message from inside rbindlist, naming
neither the caller nor the column. The appended row is now built from whatever
columns the table actually has. Alleles missing from the table were never dropped
from the output; only this path errored.
BUG FIXES:
inferGenotypeAllele() failed when allele_threshold_table was a plain
data.frame, which is the documented type and the class of the bundled
allele_threshold_table. The function adds a tag column with data.table
:= syntax, so a data.frame raised "Check that is.data.table(DT) == TRUE".
The table is now converted once on entry. The conversion copies, so a
data.table passed by a caller no longer gains a tag column by reference.NEW FEATURES:
The paired sequence-comparison helpers are renamed for what they do:
allele_diff_indices_parallel2() becomes allele_diff_paired() and
insert_gaps2_vec() becomes insert_gaps(). The old names said parallel, which
was an argument rather than a behaviour and never had any effect since the package
is not built with OpenMP, and carried a 2 marking a second attempt. The parallel
argument is gone from the new functions and ignored by the old names, which remain
exported and working indefinitely. Results are unchanged.
Gene-usage QTL analysis, moved in from the analysis scripts it was developed in
so it can be reused and checked. runGeneUsageQTL() scans every variant against
every gene group's usage; ascUsagePhenotype() builds the phenotype it explains.
The scan primitives are exported separately: qtlScanUnivariate() (vectorised
OLS), qtlScanMultivariate() (closed-form Pillai), qtlLDGroups() (exact-LD
collapse), qtlClump() (independent leads) and qtlSmallestGenotypeClass().
Conditional gene-pairing analysis, generalised to any anchor and partner segment
rather than only D and J: pairingTable(), pairingPhenotype(),
pairingScan(), pairingCellTests(), pairingLeadCharacter() and the
runPairingQTL() driver. pairingScan() requires conditional to be stated,
since the two anchorings are separate scans over the same variants and pooling
them double-reports. IGH D/J is the established use; light-chain V-J and heavy
V-D / V-J run through the same code and are documented as exploratory.
ascIUISVocabulary() builds the ASC subgroup to IUIS gene-group labels, and
annotateRepertoireIUIS() applies them to a repertoire. The vocabulary also
returns an identity table giving the member alleles behind each label and a hash
of their sequences, so a label that moves when its reference set moves can be
detected rather than silently re-joined.
BUG FIXES:
allele_diff_indices_parallel() read past the end of the input sequence whenever
the input was shorter than the germline, returning counts drawn partly from
adjacent memory: 160 characters against 8 returned 144. It also ignored gaps and
ambiguous bases only on the germline side. It is now a deprecated alias for
allele_diff_paired(), which pads the shorter sequence and ignores such positions
on either side. Its counts change -- 194 of 400 real germline pairs differ, by
a mean of 8 -- so results that depended on the old numbers need re-checking.
Lead clumping broke ties on the p-value alone. Variants in perfect linkage disequilibrium fit identically, so their p-values differ only by floating-point noise from the order of operations, which then decided which variant was named as the lead. Ties now break on the variant name: still arbitrary between variants no data distinguishes, but the same choice every run.
NEW FEATURES:
inferGenotypeAllele() gains a depth_adjusted_threshold argument (default
FALSE). When TRUE, each allele's presence threshold is raised to a
depth-aware floor max(Tai, default_allele_threshold, 1/N), where Tai is the
allele threshold and N the per-locus repertoire depth, so shallow repertoires
cannot clear an unrealistically low threshold.
inferGenotypeAllele() gains a z_score_threshold argument (default 0) and
returns a new logical column in_genotype flagging alleles with
z_score >= z_score_threshold. This is a flag only; no rows are dropped.
inferGenotypeAllele() now returns a logical observed column marking alleles
actually seen in the data (in single or multiple assignment). Alleles never
seen carry only a smoothing pseudo-count (which still contributes to the
per-locus depth) and are marked FALSE. genotypeToTigger() now excludes
these unseen alleles so the genotype table is not inflated with alleles absent
from the data.
inferGenotypeAllele(find_unmutated = TRUE) now warns and skips the
unmutated-call step when the call column is a D or J segment. Unmutated-call
detection assumes the V-region IMGT alignment (comparison anchored at
position 1); D and J segments are heavily trimmed, so it is biased there.
API CHANGES:
Column renames in AlleleClusterTable with backward-compatible deprecation warnings:
imgt_allele → iuis_allele (IUIS is the correct naming authority; IMGT is a database)Family → family (lowercase snake_case for consistency)Allele_Cluster → allele_cluster (lowercase snake_case for consistency)Backward compatibility: accessing old column names via $ or [[ on an
AlleleClusterTable object emits a deprecation warning and redirects to the
new name. Functions accepting an alleleClusterTable as input also silently
rename old columns via an internal .compat_allele_table() shim.
assignAlleleClusters(): default from_col changed from "imgt_allele" to
"iuis_allele".
Output columns of inferGenotypeAllele_asc() renamed: imgt_alleles →
iuis_alleles, genotyped_imgt_alleles → genotyped_iuis_alleles.
NEW FEATURES:
GermlineCluster objects now store the raw family cut data.frame as the
hidden slot .familiesCut (columns iuis_allele and family), produced
at the hierarchical-clustering step before merging with allele-cluster
assignments.
inferGenotypeAllele() and inferGenotypeAllele_asc() now compute the
repertoire depth per locus (IGH / IGK / IGL, derived from the allele
prefix) instead of using a single global depth. This allows heavy- and
light-chain calls in the same table (e.g. single-cell AIRR data) to each be
normalised against their own depth when computing allele fractions and
z-scores. Single-locus input is unaffected (it collapses to one group,
reproducing the previous global depth).
New genotypeToTigger() converts the output of inferGenotypeAllele() or
inferGenotypeAllele_asc() into the per-gene TIgGER/VDJbase genotype table
layout (gene, alleles, counts, total, z_score, genotyped_alleles).
The input type is detected automatically, the row key is selectable with
level = c("gene", "asc"), and the set of genotyped_alleles is determined by
a z-score threshold (z_threshold, default 0). An optional file argument
writes the table as a tab-separated file.
inferGenotypeAllele() and inferGenotypeAllele_asc() gain a novel
argument accepting a tigger::findNovelAlleles() table. Novel germline
sequences are added to germline_db and the novel alleles become genotype
candidates (as in tigger::inferGenotypeBayesian); each novel allele inherits
the threshold of its base allele. genotypeToTigger() keeps the novel suffix
and allelePalette() renders novels as a semi-transparent shade of the base
allele's color.
New allelePalette() returns VDJbase-style allele colors and generates
additional distinct colors when there are more alleles than the curated set.
New plotGenotypeAllele() plots a genotype in the style of
tigger::plotGenotype(), with an aligned confidence panel. Because PIgLET
assigns a z-score per allele (rather than one value per gene), the confidence
panel mirrors the allele bars and colors each allele segment by its own
z-score. Accepts either a genotypeToTigger() table or a raw genotype.
BUG FIXES:
inferGenotypeAllele_asc(single_assignment = TRUE) previously failed with
"object 'gene' not found" because the per-gene aggregation did not name its
grouping columns; it now runs correctly (and benefits from the per-locus
depth above).BUG FIXES:
Leiden clustering now uses hierarchical clustering for Family assignment, matching the behavior of the reference script. Previously, Family was set equal to Allele_Cluster (both from Leiden), losing the hierarchical family structure. Now Family comes from hierarchical clustering and Allele_Cluster from Leiden community detection.
Leiden results now populate hclustAlleleCluster and family_threshold,
enabling plotTruncatedTree() to work with Leiden-based results.
MAJOR CHANGES:
Leiden Community Detection: Added support for Leiden algorithm as an alternative
to hierarchical clustering. Use clustering_method = "leiden" in inferAlleleClusters().
This is particularly useful for D and J segments with variable-length sequences.
Generalized Distance Functions: The new igDistance() function supports multiple
distance calculation methods:
Multi-locus Support: inferAlleleClusters() now explicitly supports all V/D/J
segments with the locus parameter.
New Visualization Functions:
plotTruncatedTree(): Publication-quality circular tree with collapsed subgroupsplotCommunityNetwork(): Network visualization of cluster relationshipsplotSilhouetteOptimization(): Resolution parameter optimization plotplotClusterComparison(): Compare hierarchical and Leiden clustering resultsCLASS SYSTEM CHANGES:
GermlineCluster is now an S3 class instead of S4.
$ instead of @ (e.g., result$alleleClusterTable)print(), summary(), and plot() S3 methodsclusteringMethod, communityObject, graphObject, distanceMatrix,
silhouetteScore, resolutionParameter, locusAPI CHANGES:
ighvDistance() is deprecated in favor of igDistance() (backward compatible wrapper provided)ighvClust() is deprecated in favor of igClust() (backward compatible wrapper provided)inferAlleleClusters() has new parameters but maintains backward compatibilityDEPENDENCIES:
igraph, stringdist, cluster, apeComplexHeatmap, dplyr, ggtreedplyr (replaced with data.table operations)MINOR CHANGES:
Author and Maintainer fieldstestthat (edition 3)BUG FIXES:
dplyr::between() callsdplyr::bind_rows() callsinferGenotypeAllele to simplify genotype by asc annotation.genotype_confidence.The confidence is calculated as the Z score of the allele count, repertoire depth, and the allele absolute threshold.
download_zenodo_files.download_zenodo_files.download_zenodo_files.