Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: bHIVE
Title: B-cell Hybrid Immune Variant Engine
Version: 0.99.5
Version: 0.99.6
Authors@R: c(
person(given = "Nick", family = "Borcherding", role = c("aut", "cre"), email = "ncborch@gmail.com"))
Description: The bHIVE package implements an Artificial Immune Network (AI-Net) algorithm for clustering and classification tasks. Inspired by biological immune systems, it employs clonal selection, mutation, and network suppression to analyze and model datasets. This package provides flexible functionality, including affinity metrics, mutation strategies, and hyperparameter tuning.
Expand Down
42 changes: 42 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
# bHIVE 0.99.6

## New Behavior
* **Unified engine.** `bHIVE()` is now a thin wrapper over the `AINet` R6
engine instead of a separate pure-R implementation. `swarmbHIVE()` and
`honeycombHIVE()` call `bHIVE()`, so they now inherit the C++ clonal-selection
and suppression backends, Lloyd consolidation, input scaling, target-K, and
all composable immunology modules. The old module-free R loop is retired. The
return value gains `antibodies_unscaled` and (from `bHIVE()`) a `model`
handle; the historical `antibodies` / `assignments` / `task` fields are
unchanged. `swarmbHIVE()` now forwards every grid column to `bHIVE()`, so any
`bHIVE`/`AINet` argument can be tuned, not just `nAntibodies`/`beta`/`epsilon`.

* **Input scaling.** `AINet$new()` and `bHIVE()` gain a `scale` argument
(`"none"`, `"zscore"`, `"robust"`, `"arcsinh"`). The transform is learned at
`fit()` and re-applied to new data at `predict()`. Because `epsilon`,
mutation scale, and every distance live in feature units, scaling makes the
same defaults behave consistently across datasets of different magnitude.
`arcsinh` (cofactor `scaleCofactor`, default 5) is the standard mass-cytometry
transform. `affinityParams$alpha = "auto"` sets the RBF/Laplace bandwidth by
the median heuristic (alpha = 1 / median pairwise squared distance).

* **Target-K clustering.** New `targetK` argument forces the clustering result
to exactly K clusters. Affinity maturation still discovers where prototypes
belong, but a seeded K-means refinement coerces the count: surviving
antibodies are agglomerated (if more than K) or split with k-means++ (if
fewer). This decouples the reported cluster count from the scale-sensitive
emergent suppression dynamics.

* **Scale-free suppression.** New `epsilonQuantile` argument recomputes the
suppression threshold each iteration as a quantile of pairwise antibody
distances, adapting to the repertoire's own spread instead of a fixed
feature-unit `epsilon`.

* **Rare-population protection.** New `coverageBoost` (with `coverageQuantile`)
seeds fresh antibodies among the worst-covered data points after maturation,
countering the clonal-selection bias toward dense regions that otherwise
leaves rare populations unrepresented. `honeycombHIVE()` gains
`smallClusterAction` (`"merge"`, `"keep"`, `"drop"`): small clusters are now
merged into the nearest prototype (no observations dropped) or kept as rare
prototypes by default, instead of being silently deleted.

# bHIVE 0.99.5

## Performance
Expand Down
287 changes: 285 additions & 2 deletions R/AINet.R

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion R/ImmuneAlgorithm.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,18 @@ ImmuneAlgorithm <- R6::R6Class(
newdata <- as.matrix(newdata)

task <- self$result$task
A <- self$repertoire$as_matrix()
# Prefer the reported prototypes (consolidated / forced-K centroids for
# clustering; pruned antibodies for classification) so test-time labels
# match the training partition. Fall back to the raw repertoire.
A <- self$result$antibodies %||% self$repertoire$as_matrix()
cfg <- self$config

# Apply the scaling learned at fit() so new data lives in the same space
# as the trained antibodies. No-op when scale = "none".
if (!is.null(cfg$scaling)) {
newdata <- .bhive_apply_scaling(newdata, cfg$scaling)
}

alpha <- cfg$affinityParams$alpha %||% 1
c_p <- cfg$affinityParams$c %||% 1
p_p <- cfg$affinityParams$p %||% 2
Expand Down
Loading
Loading