Skip to content

topolow

2.1.0Package record

Force-Directed Euclidean Embedding of Dissimilarity Data

0packages depend
2.7Kdownloads / year
60.9%test coverage
13/13flavors OK

Overview

About

A robust implementation of Topolow algorithm. It embeds objects into a low-dimensional Euclidean space from a matrix of pairwise dissimilarities, even when the data do not satisfy metric or Euclidean axioms. The package is particularly well-suited for sparse, incomplete, and censored (thresholded) datasets such as antigenic relationships. The core is a physics-inspired, gradient-free optimization framework that models objects as particles in a physical system, where observed dissimilarities define spring rest lengths and unobserved pairs exert repulsive forces. The package also provides functions specific to antigenic mapping to transform cross-reactivity and binding affinity measurements into accurate spatial representations in a phenotype space. Key features include: * Robust Embedding from Sparse Data: Effectively creates complete and consistent maps (in optimal dimensions) even with high proportions of missing data (e.g., >95%). * Physics-Inspired Optimization: Models objects (e.g., antigens, landmarks) as particles connected by springs (for measured dissimilarities) and subject to repulsive forces (for missing dissimilarities), and simulates the physical system using laws of mechanics, reducing the need for complex gradient computations. * Automatic Dimensionality Detection: Employs a likelihood-based approach to determine the optimal number of dimensions for the embedding/map, avoiding distortions common in methods with fixed low dimensions. * Noise and Bias Reduction: Naturally mitigates experimental noise and bias through its network-based, error-dampening mechanism. * Antigenic Velocity Calculation (for antigenic data): Introduces and quantifies "antigenic velocity," a vector that describes the rate and direction of antigenic drift for each pathogen isolate. This can help identify cluster transitions and potential lineage replacements. * Broad Applicability: Analyzes data from various objects that their dissimilarity may be of interest, ranging from complex biological measurements such as continuous and relational phenotypes, antibody-antigen interactions, and protein folding to abstract concepts, such as customer perception of different brands. Methods are described in the context of bioinformatics applications in Arhami and Rohani (2025a) doi:10.1093/bioinformatics/btaf372, and mathematical proofs and Euclidean embedding details are in Arhami and Rohani (2025b) doi:10.48550/arXiv.2508.01733.

Changes in 2.1.0

Deprecations

  • create_diagnostic_plots() is deprecated in favor of plot_mcmc_diagnostics(), so that every plotting function shares the plot_* prefix. The old function still works and warns; it will be removed in version 3.0.0.
  • **Migration**: create_diagnostic_plots(...) --> plot_mcmc_diagnostics(...)
  • **Migration**: argument res --> dpi

New Features

Subsampling for Computational Efficiency

  • **Major Feature**: Added the optional opt_subsample parameter to key optimization functions, enabling efficient parameter optimization on large datasets while maintaining final embedding quality. Parameter optimization still works reliably with subsampling, because likelihoods of samples of the same size are comparable, allowing us to choose the optimal parameter values.
  • **New Functions**:
  • check_matrix_connectivity(): Validates that a dissimilarity matrix forms a connected graph
  • subsample_dissimilarity_matrix(): Creates random subsamples with automatic connectivity validation and adaptive size adjustment
Show all changes in 2.1.0Hide the rest of the changes in 2.1.0
  • sanity_check_subsample(): Validates subsample suitability for cross-validation
  • prune_sparse_matrix(): Prunes sparse dissimilarity matrices to a well-connected subset
  • plot_mcmc_diagnostics(): Replacement for create_diagnostic_plots() (see Deprecations)
  • plot_ll_improvement(), plot_performance_trace(): Diagnostics for the parameter search
  • plot_euclidify_diagnostics(), create_diagnostic_report(): Diagnostics for Euclidify() output
  • **Enhanced Functions**:
  • initial_parameter_optimization(): Now accepts opt_subsample parameter
  • run_adaptive_sampling(): Now accepts opt_subsample parameter
  • adaptive_MC_sampling(): Now accepts opt_subsample parameter (internal)
  • Euclidify(): Now accepts opt_subsample parameter

How Subsampling Works

When opt_subsample is specified:

1. Each parameter evaluation uses a random subsample of the specified size

2. Connectivity is automatically validated; disconnected subsamples are rejected

3. If connectivity fails, sample size needs to be increased

4. Different parameter evaluations use different subsamples for robustness

5. **Final embedding always uses the full dataset**

The opt_subsample parameter is optional (default: NULL = use full data).

Performance Benefits

  • Substantially reduces the cost of parameter optimization on large datasets (>500 points), since each evaluation embeds a subsample rather than the full matrix
  • Reduces memory usage proportional to subsample size
  • Parameters found on subsamples generalize well to full data

Recommendations

  • Datasets < 500 points: Use full data (opt_subsample = NULL)
  • Datasets > 500 points: Recommended opt_subsample = 200-500
  • Always ensure opt_subsample >= folds for reliable cross-validation

Epoch-Based Parameter Search

  • initial_parameter_optimization() gained an epochs argument (default: 1). With more than one epoch the search runs as a simple evolutionary strategy: 1. **Initialization**: start from the user-provided parameter ranges. 2. **Epoch loop**, for each epoch: a. Generate num_samples points by Latin hypercube sampling within the current ranges. b. If opt_subsample is set, each evaluation uses its own random subsample. c. Evaluate the parameter sets by cross-validation, in parallel batches. d. **Range update** (after every epoch but the last): sort by NLL, keep the top 50%, and set the next epoch's range to 0.75 * min(survivors) through 1.25 * max(survivors). This lets the search drift toward and zoom in on promising regions. 3. **Finalization**: log-transform the results of the final epoch for direct use with adaptive sampling.

Other changes

  • Package gridExtra is a required import now.

Bug Fixes

  • initial_parameter_optimization() (and therefore Euclidify()) could fail on Windows with invalid connection whenever the parameter search ran in more than one batch. A cluster shutdown handler was registered per batch, and all of them referred to the last cluster, so it was stopped repeatedly while the earlier clusters leaked. Each batch's cluster is now stopped as soon as that batch finishes. The failure was reliably triggered by max_cores = 2, which is the configuration used on CRAN check machines.
  • Conversion of matrices to numeric in R/adaptive_sampling.R is now handled by the package's extract_numeric_values() function.
  • run_adaptive_sampling() no longer sleeps for a fixed 1.5 seconds on every call. Two Sys.sleep() calls guarded file visibility on networked filesystems (NFS, Lustre); they now poll for the expected state instead, so the wait is effectively free on a local filesystem while networked ones still get up to 5 seconds. This removed about a second from every Euclidify() run and has no effect on results.

Documentation

  • Clarified that the *_range arguments of Euclidify() are a **starting range for the search, not a hard bound**. Initial sampling draws inside the range, but adaptive refinement samples from a kernel density estimate of the best parameter sets found so far, which can propose values outside it. So ndim_range = c(3, 6) does not guarantee a 3- to 6-dimensional result; only the sanity limits (for example 1 <= ndim <= 50) are enforced. This behaviour is unchanged from earlier versions and is now documented, in a new section of ?Euclidify. Use euclidean_embedding() with an explicit ndim when a hard cap is required.

Improvements

  • Enhanced connectivity checking using igraph
  • Better error messages for disconnected data
  • Adaptive strategies for handling sparse data
  • Comprehensive logging of subsampling operations
  • New diagnostic plots including MCMC exploration and parameter fit traces

C++ Backend for Core Optimization

  • **This is the first release of topolow containing compiled code.** The core optimization loop of euclidean_embedding() has been rewritten in C++ using Rcpp, which speeds up the embedding substantially, most visibly on larger matrices. The remaining R-level loops in that function were replaced with vectorized operations.
  • **New parameter for euclidean_embedding()**:
  • convergence_check_freq: How often, in iterations, to test for convergence (default: 3). Larger values reduce the bookkeeping overhead; smaller values stop more promptly.
  • **Implementation details**:
  • **COO format**: edge data is held as a coordinate list, which avoids the zero-dropping behaviour of sparse matrix classes
  • **Shuffled sweep order**: the sweep order is permuted each iteration with a C++ Mersenne Twister (std::mt19937), which is what lets the configuration escape local optima
  • **Immediate updates**: Gauss-Seidel style in-place position updates, as in the original R implementation
  • **Single-pass error calculation**: the MAE over active constraints is accumulated in one pass over the edge list at each convergence check
  • **Cache-friendly layout**: edge data is stored in contiguous arrays
  • **Pre-computed factors**: degree-based normalization factors are computed once, before the iteration begins
  • **Direct memory access**: the inner loop writes to the raw column-major position buffer
  • **Return value enhancement**: the convergence field of the returned topolow object now includes:
  • achieved: whether convergence was reached
  • error: final MAE on active constraints
  • final_k: final spring constant after cooling
  • **Dependencies**: added Rcpp to LinkingTo (compile-time only; no new runtime dependency). The backend is Rcpp-only and links no BLAS or LAPACK routines, so no src/Makevars is required on any platform.

Reproducibility and numerical equivalence

  • The algorithm, its force model, cooling schedule and convergence criterion are unchanged from 2.0.1. Results from this version are **statistically equivalent** to 2.0.1 but **not bit-identical**, for two reasons:
  • The sweep order is randomized by a C++ generator seeded from std::random_device, independent of R's RNG. set.seed() fixes the starting configuration (drawn with stats::runif()) but not the sweep order, so repeated runs differ slightly. The R implementation in 2.0.1 shuffled the sweep order in the same way.
  • The convergence MAE (result$convergence$error) is now accumulated in package code rather than by a BLAS routine, so it can differ in the last representable digit from earlier development builds. This is far below the run-to-run variation produced by the shuffle, and it makes the value consistent across platforms, which it previously was not. Embedded positions are unaffected.
  • See the new Reproducibility section of ?euclidean_embedding for what is and is not seeded, and for how to obtain a single canonical map.

Backward Compatibility

  • All existing code using euclidean_embedding() will work without modification
  • Default parameter values preserve the original algorithm's behavior
  • Output structure remains compatible with downstream functions (Euclidify(), parameter optimization, etc.)

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 6.1 min · r-oldrel-windows-x86_64
Status changes
  • OK13 OK2026-08-04
  • NOTE12 OK, 1 NOTE2026-08-01
  • OK13 OK2026-06-08
  • ERROR12 OK, 1 ERROR2026-06-07
  • OK14 OK2026-03-10
Advisories

none known

Documentation

In release 2.1.0
READMEYes · 1,519 wordsVignettesYes · 1 · dynamicNEWSYes · 67% structured · mentions 2.1.0Citation fileYes · cites a publicationWebsitenot declared in DESCRIPTION
Help pages
79 (19 internal)includes a package overview page
Examples that run
82%31 run in a plain check (1 of them under a condition) · 7 only when donttest examples are enabled (R CMD check --as-cran)
Exported functions with examples
71%
Documented parameters
95%
Return-value docs
98%
Help pages citing references
0%

Downloads

2.7K
CRAN downloads in the past year
Rank #10,890 · ~7/day · ~224/mo
Daily download trend is not available in this view yet.
44730 days
96590 days
2.7K1 year
Compare downloads with other packages →
Also on76 r2u2 autocran

Repository

6Stars
3Forks
0Open issues
0Open PRs
12Releases
263Commits
3Commit identities
antigenic-cartographyimputation-algorithmmultidimensional-scalingphenotype-predictioneuclidean-distancesnon-metric
263 commits · Last activity 2026-09-04 · 0% stars, 30d
Responsiveness
How these are sampled
PRs merged (all time)
not measured
Median days to close, 50 most recently updated closed issues
15
Median days to close, 50 most recently updated closed PRs
not measured

Stars over time

2025-09-09 · 42026-07-07 · 6
PracticesBeta

8 development-tooling and community-health practices detected across 6 families in the upstream repository

Checks run against github.com/omid-arhami/topolow on 2026-10-18.

Continuous integration (2)
GitHub ActionsR CMD check workflow

The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel

Coverage (1)
Coverage reporting
Reproducibility and dev environment (1)
data-raw/
CRAN release process (2)
cran-comments.mdCRAN-SUBMISSION
Show all practicesHide 2 practices
Research and citation (1)
JOSS paper
Git structural (1)
.gitattributes
How this is detected·Detection ruleset v3 (2026-09-26)
AI coding toolsBeta

This repository shows signs of AI coding tools.

  • Claude Codefirst seen 2026-09-02
    Seen in the repository: CLAUDE.md
    Named in .Rbuildignore: CLAUDE.md
How this is detected·Detection ruleset v4 (updated 2026-09-27)

Dependencies

Declared dependencies
31 external dependencies (excludes base and recommended)

Installing topolow adds 41 packages (23 with compiled code, 42 MB of source tarballs). Heaviest: stringi 11 MB, ggplot2 6.0 MB, data.table 5.7 MB.

Depends (1)
R >= 4.1.0
Imports (20)
LinkingTo (1)
Enhances (0)
none
Reverse dependencies
0direct
0indirect

Nothing depends on this yet.

Datasets

People & History

People (1)
Author, Maintainer since 1.0.0 (2025), Copyright holder
Releases (4)

Pick two releases to compare their code metrics.

  • 2.1.0Latest
    record
    2026-09-14 · current release · diff ↗ ·
    added 9 exports
    check_matrix_connectivity, create_diagnostic_report, plot_euclidify_diagnostics, plot_ll_improvement, plot_mcmc_diagnostics, plot_performance_trace, prune_sparse_matrix, sanity_check_subsample, subsample_dissimilarity_matrix
  • R
    R 4.6.0 released · 2026-04-24
  • 2.0.1
    record
    2025-08-31 · diff ↗
  • 2.0.0
    record
    2025-08-19 · diff ↗ ·
    removed 21 exports
    add_noise_bias, c25_claud, c25_old, c25_older, calculate_annual_distances, calculate_cumulative_distances, calculate_procrustes_difference, calculate_procrustes_significance, create_and_optimize_RACMACS_map, dist_to_titer_table, find_mode, generate_complex_data, generate_synthetic_datasets, generate_unique_string, increase_na_percentage, long_to_matrix, only_virus_vs_as, plot_distance_heatmap, prepare_heatmap_data, prune_distance_network, unweighted_kde
    added 6 exports
    Euclidify, euclidean_embedding, extract_numeric_values, list_to_matrix, table_to_matrix, titers_list_to_matrix
  • 1.0.0
    record
    2025-07-11
  • R
    R 4.5.0 released · 2025-04-11

Package metadata

First published
2025-07-11
Total releases
4 / 1 yrs
License
BSD_3_clause + file LICENSE OSI
Minimum R
≥ 4.1.0
Bundled data
333 KB / 5 files
Download size
1.3 MB

Cite

Cite this package

Run in R for the authors' entry:

citation("topolow")

The package provides a citation file, so citation() returns the authors' own entry.

It points to 10.1093/bioinformatics/btaf372, 10.48550/arxiv.2508.01733.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for topolow version 2.1.0 [Data set]. HJJB, LLC. Data release v2026-10-22. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-22, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy