Skip to content

Latest commit

 

History

History
83 lines (72 loc) · 5.45 KB

CHANGELOG.md

File metadata and controls

83 lines (72 loc) · 5.45 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • Anchor-point / distance-zone analysis of a latent dimension (interscale.tl.anchors, plotted by interscale.pl.anchor_plots): find_anchor_cells localises the foci a dimension is reading (per-sample tail quantile, then a spatial-coherence filter), anchor_signed_distance gives every cell a signed distance to the anchor border, anchor_zones cuts that into anchor core / near / far at the local component's reach (local_reach_um = num_layers x radius), and profile_by_distance / anchor_enrichment profile expression and composition against it. This is the evidence a global dimension carries a long-range interaction rather than a neighbourhood effect: every distance plot marks the local reach, past which no cell's neighbourhood extends.

  • Gene-wise (per-entry) masking for the node-level reconstruction task, alongside the existing whole-cell masking, selected by dataset.mask_strategy ("node" | "gene"). Under "gene" a Bernoulli subset of (cell, gene) entries is blanked in every cell and the loss and every regression metric are restricted to those entries. Registered as the node_reg_genemask task for legnini23 and melton25, with config_files/sweeps/mask_granularity_legnini.yaml running the granularity/rate ablation.

Changed

  • tl.masking.MASK_VALUE is now -1, was 0. Masked positions must be distinguishable from real measurements: ~62% of legnini23's log1p_norm entries are already exactly 0 and 648 of its cells are all-zero, so a zero fill made the corruption invisible under gene masking. Measured at gene rate 0.25 over 3 seeds, fill 0 scored val_concordance_corr 0.0696 ±0.0113 against -1's 0.0799 ±0.0046 — better on every seed, with 2.5x less run-to-run spread. A configurable fill (zero/sentinel/learned, including a trainable per-gene [MASK] token) was trialled and removed: the learnable token tied with the fixed -1 to three decimals, so the option carried no information. This also changes the cell-masking path, whose published runs used 0.
  • dataset.pct_mask_nodes and dataset.pct_mask_genes are replaced by a single dataset.mask_percentage (and GraphAnnDataModule/BaseModule take one mask_percentage argument). mask_strategy already says whether a masked unit is a cell or an entry, so a second rate was always the inert half of a pair — and setting the wrong one silently produced a run with no masking. GraphAnnDataModule.mask_rate and BaseModule.mask_rate are gone with it. Every config using pct_mask_nodes must be renamed, including saved wandb sweeps.
  • tl.masking.apply_mask takes mask_strategy explicitly instead of inferring it from whether the batch carries a gene_mask, and GlobalModule._process_batch_for_metrics gates on the strategy the same way. A stale gene_mask can no longer hijack a cell-masking run, so GraphAnnDataModule._clear_gene_mask is removed.
  • tl.masking.apply_mask and BaseModule._common_step_masking now return a third value, the entry mask; every _common_step returns a sixth value carrying it through to the training plan. GlobalModule._process_batch_for_metrics returns it as a third value. DualDecoderCombinedModule.compute_separate_losses takes it as an optional fifth argument.
  • LocalModule._common_step returned a 4-tuple where the training plan unpacked 5; it now matches the 6-tuple contract of the other modules.
  • requires-python is now >=3.12, was >=3.11, and the test matrix's lower rung moves with it. anndata, scanpy, squidpy and scvi-tools all require 3.12 already, so the 3.11 claim only told the resolver to back-solve to years-old releases of them on that interpreter — the "old and broken versions" of #59.
  • Dependency bounds were loosened (#59). scanpy no longer carries a <1.13 upper bound: the break was squidpy's, not scanpy's — squidpy <= 1.8.3 imports the private scanpy.plotting._tools, which the scanpy 1.13 plotting rewrite moved under scanpy.plotting.legacy, so import squidpy (and through it import interscale) raised ModuleNotFoundError on scanpy 1.13.0a2. squidpy's main branch already imports from either location, so [tool.uv.sources] takes squidpy from git until that fix is released, with the commit pinned in uv.lock. numpy stays uncapped and resolves to 2.x; its >=1.19 floor and scipy's >=1.7 are gone, since requires-python already excludes everything below their first cp312 wheels.
  • torch-cluster, torch-scatter and torch-sparse are no longer part of the resolution. They come from geome, which never imports them, and torch-geometric >= 2.3 covers what they provide; PyPI only carries their 2023 source distributions, which must be compiled against the installed torch. [[tool.uv.dependency-metadata]] restates geome's requirements without them, so the [tool.uv] extra-build-dependencies block and CI's torch-version-pinned UV_FIND_LINKS PyG wheel index are both gone. pip install interscale still pulls them in through geome — docs/installation.md now derives the PyG wheel index from the installed torch instead of naming a version.

[0.0.1]

initial release