Releases: SpatialPathology/InSituPy
Release list
0.12.0b6
Release Notes - InSituPy 0.12.0b6
PyPI: pip install insitupy-spatial==0.12.0b6
Summary
Multi-unit-layer support for the napari viewer, several data-integrity fixes, and a fail-fast
guard against accidentally re-constructing an InSituData on top of an already-saved project.
New Features
- Multiple named spatial units layers -
InSituData.unitsnow holds a
MultiSpatialUnitsDatacontainer, so a sample can carry more than one units layer (e.g.
Visium spots and niches) viaadd_units(data, key=...);crop()now crops all of them. - napari viewer - units layer selector to switch between multiple unit keys; searchable
type-ahead on the cells/units key fields; "Show" buttons gated on a valid selection.
Bug Fixes
- Fixed
InSituData(path)silently fabricating a new UID on a saved-project path; now raisesInSituDataConstructorPathErrorpointing atInSituData.read(). - Fixed cells/units shifting relative to the image after crop-by-region (negative shape bounds weren't clamped).
- Fixed
build_table()/to_anndata()silently dropping a sample when two samples shared alabel_colvalue. - Hardened
autodetect_obs_namesmatching so it no longer truncates barcodes or fails onconcat_on_diskoutput. - Fixed
InSituExperimentsubsetting inconsistency:__getitem__/query()now always return a view, and.filters.apply()now actually deep-copies. - Fixed the napari transcript viewer's thread-race
IndexErrorand a point-size inconsistency. - Fixed a zoom-out border artifact on cells-as-points and Transcripts layers (napari 0.7 default).
- Fixed cell/nucleus label mis-coloring in the napari viewer after filtering without
sync(). - Fixed a hidden units layer staying hidden after re-selecting its key.
- Fixed two bugs in the units save/load path (missing attribute; mismatched on-disk format).
Breaking Changes
build_table()/to_anndata()unique-obs_namesshape unified: both methods now append the uid ("{name}-{uid}") instead ofin_memoryprepending a positional index.import_from_anndata'sstrip_uid_prefixparameter renamed toautodetect_obs_names(no deprecated alias).
Dependency Changes
- napari bumped to
>=0.7.0,<0.8.0. - Python floor raised to
>=3.12.0,<4.0(required byzarr>=3.2.1).
Internal
- Stopped tracking
.mcp.json; documented self-serve MCP client setup for contributors. - Revised the MCP Server tutorial; synced its Python version reference to 3.13.
Full Changelog: 0.12.0b5...0.12.0b6
0.12.0b5
Release Notes - InSituPy 0.12.0b5
PyPI: pip install insitupy-spatial==0.12.0b5
Summary
Color-system consistency release: a new layer-aware exp.colors API keeps plotting and the
napari viewer in sync, several color-rendering bugs are fixed, and a tifffile/zarr
incompatibility that broke lazy image reads is resolved.
New Features
exp.colors— layer-aware color store that writes through to every sample's.uns,
keepingsync_colors,pl.spatial,pl.cellular_composition, andshow()consistent.- napari viewer — Show-widget layers now reuse by display scope instead of by exact name.
pl.embedding/umap/pca/tsne— newpalette,vcenter,subplot_width/subplot_heightparameters.pl.spatial— newnan_colorparameter (matchespl.embedding).
Bug Fixes
- Continuous values in the napari "cells"/"nuclei" mode no longer misrender as a slow, categorical-style legend.
- Fixed
KeyErroron integer-category columns in points-mode color mapping. - Fixed duplicate napari layers accumulating on repeated "Show" calls, and reused layers staying hidden after recoloring.
- Fixed
pl.spatial/sync_colorscrashes on object columns mixing strings with NaN. - Fixed stale layout state (e.g. figsize) leaking across successive
pl.spatialcalls. - Fixed
tifffile/zarr3.2.x incompatibility that broke all lazy (aszarr=True) image reads. - Fixed
write_ome_tiff()silently writing non-OME TIFFs.
Dependency Changes
- tifffile pinned to
>=2026.5.2,<2027.0.0.
Internal
- Test suite cleanup: removed one obsolete test, collected two previously-uncollected smoke
suites, fixed two test/implementation mismatches. - Full suite verified green: 687 passed, 0 failed, 0 errors.
Full Changelog: 0.12.0b4...0.12.0b5
0.12.0b4
Release Notes — InSituPy 0.12.0b4
Date: 2026-06-25
PyPI: pip install insitupy-spatial==0.12.0b4
Previous release: 0.12.0b3
Summary
This release is centred on multi-sample analysis workflows. One of the main additions is a
flexible filter layer system (InSituExperiment filters): users can define named sample
subsets — including composite filters that combine multiple base filters with AND/OR logic —
and use them to scope any downstream analysis without modifying the underlying experiment.
Alongside filters, a new cross-sample table workflow (build_table() / .table[...] /
import_from_table()) enables concatenation of cell tables across all samples into a single
AnnData, with results writable back to individual samples and full support for multi-panel
experiments with differing gene sets. Experiment management gains three new methods —
replace(), remove(), and reload() — and each dataset now carries a stable UID that
persists across saves, reloads, and reorders, making filter and merge-back operations robust
to experiment restructuring.
On the analysis side, QC is redesigned around the new qc_summary() method, and the
embedding plots (umap, pca, tsne) gain highlight/dim parameters for
focus-on-subset visualisation, a layer parameter to plot from any AnnData layer, and several
rendering options. The save pipeline received its most thorough hardening to date: atomic
swaps, collect-then-raise error handling, and guards against path-less dataset corruption make
save/saveas reliable even after hard crashes.
New Features
Cross-sample table workflow
- Added
InSituExperiment.build_table()to concatenate cell tables across all samples into a single AnnData, with support for union or inner gene sets across panels. - Results are accessible via
.table[cells_layer](bracket accessor) and can be written back to samples withimport_from_table(). InSituExperimentView.tableworks on filtered subsets of the experiment.concat_on_diskoption builds the table by writing per-sample H5AD files and concatenating them, avoiding peak RAM for large experiments.- A
build_params.jsonsidecar tracks the parameters used to build each stored table.
QC redesign
- New
InSituExperiment.qc_summary()method returns a tidy DataFrame of per-sample QC metrics. calculate_mad_thresholdsmoved to the newinsitupy.experimentalsubmodule; theinsitupy.ppalias is deprecated with a warning.
Embedding plot enhancements (isp.pl.embedding / umap / pca / tsne)
highlightparameter: colour a subset of cells, grey out the rest.dimparameter: inverse ofhighlight— grey out the specified cells.- "Other" legend entry automatically added for dimmed/highlighted background points.
layerparameter: plot expression values from any AnnData layer (not just.X).render_mode="matplotlib"for matplotlib-native rendering as an alternative to datashader.point_edge_color,point_edge_width, andrasterizedparameters added.nan_colorparameter to control colour of NaN values in categorical columns.- Scanpy colour palette fallback for categories already coloured in
.uns.
Experiment management
InSituData.uid— each dataset now has a stable unique identifier that persists across saves and reloads.InSituExperiment.replace(uid, new_data)— replace a dataset in an experiment by UID.InSituExperiment.remove(uid)— remove a dataset from an experiment.InSituExperiment.reload()— reload all datasets from disk without re-reading the experiment.InSituData.read()now auto-loads all available modalities by default.
Filter layer improvements
- Composite filter layers that combine multiple base filters with AND/OR logic.
- Improved repr distinguishes base filters from composite filters.
Metadata utilities
InSituExperiment.update_metadata()andrename_metadata_column()for in-place metadata edits.unload()to release modality data from memory.concat(mode='move')now supported on subsetted experiments.from_config()accepts a DataFrame directly as metadata input.- Experiment metadata stored as
metadata.parquetinstead ofmetadata.csv(more robust, preserves dtypes).
napari interactive viewer
- New
GeometriesWidgetwith colour palettes and geometry registries for managing annotations in the viewer. - GeometriesWidget restructured: separate "Show" and "Add" panels, point size preservation.
- Auto-naming of new geometry layers.
- Single-layer regions: all region/annotation classes for a given key are merged into one napari layer, with a combined widget.
Shapes and geometry
ShapesDatagainsto_regions()/to_annotations()conversion methods.scale_factorsentinel default with a descriptiveValueErrorwhen not set.
Image registration
- Registration module refactored into a standalone
register_images_standalonefunction; theImageRegistrationclass is deprecated. raise_on_insufficient_matchesparameter added to control error vs. warning behaviour on low feature matches.
Save/load additions
InSituDatapartial save methods:save_geometries(),save_cells(),save_images().InSituDatagains conversion methods between modality types.
Repr improvements
InSituData.__repr__now shows the dataset UID.InSituExperiment.__repr__now shows loaded modality counts per dataset.
Bug Fixes
Save pipeline hardening (major)
saveas()now uses a true atomic swap: moves old data aside to a backup before renaming the staging directory in; restores the backup if the swap fails. Previously, a crash during the swap could destroy both old and new copies.InSituExperiment.save()now uses a collect-then-raise pattern: all datasets are attempted before raising, and aRuntimeErrorlists every failing UID. Experiment-level files are skipped on any failure.InSituExperiment.save()no longer corrupts a path-less dataset's_pathon failure; the pre-pass validates before assigning.- Path-less datasets (added via
.add()without a prior save) are auto-assigned a freedata-NNNslot and written viasaveas()on the firstsave()call. InSituExperimentView.save_filters()now merges filter masks back to parent samples by UID rather than positional index, preventing wrong-sample writes after a parent reorder.saveas()recovers an orphaned.__ispy_bak__backup left by a previous crash instead of silently deleting it.InSituExperimentViewsave methods no longer mutate the parent experiment's filter state.
Memory and I/O
- Prevented OOM when saving large lazy transcript datasets.
- Fixed a pandas 2.x Copy-on-Write
MemoryErrorin transcript cropping (_crop_transcriptsnow usesDataFrame.take()). - Fixed regions extending past image boundaries causing crop failures.
- Fixed empty rows appearing in
metadata.csvon Windows.
Interactive viewer
- Fixed
IndexErrorrace condition inTranscriptViewerWidget. - Fixed
.unscolour order being lost when switching to cells/labels display mode. - Fixed point annotation colour channel mismatch in geometry layers.
- Fixed stale-key and uid-guard issues in interactive widgets; added "(all)" key option.
- Fixed sync-order bug in geometry colour legend updates.
Other
- Fixed H&E image registration crash and memory leak in registration QC.
- Fixed circular import in
containers/io.py. - Fixed
MultiCellData.__getitem__raisingIndexErrorinstead ofKeyErrorfor missing layer names. - Fixed best image pyramid level selection in
quantify_signalwhen pixel sizes differ. - Corrected inverted
unload()string normalisation and leiden flavour handling.
Dependency Changes
- scipy pinned to
>=1.14,<1.17(1.17 introduced a breaking change). - zarr minimum bumped to
3.2.1. - Python minimum updated to
>=3.11.0(was>=3.10). - anndata added as an explicit dependency (
>=0.12.0).
Documentation
- New save/load tutorial (
docs/tutorials/00_io/) covering full and partial saves, reload patterns, and when to use each method. - New cross-sample table tutorial with architecture diagram.
- New filter workflow tutorial documenting base and composite filter layers.
- MCP server tutorial (
MCP_TUTORIAL.md) updated: Claude Code global config option added, ChatGPT section labelled as untested with feedback link, tool count corrected to 22,tools/mcp_server/README.mdrewritten withuvxas the recommended path.
Internal / Refactoring
- Geometry layers in napari migrated to the napari features API.
_concatenate_samplesand_transfer_to_samplesextracted as reusable helpers._clear_modalityhelper introduced, consolidating deleter and unload logic.- Transcript cropping intermediate code cleaned up after performance work.
- Ruff linting applied and violations fixed across the codebase.
- GitHub Actions release workflow now auto-detects pre-release tags (
a,b,rc) and marks the GitHub Release accordingly.
Full Changelog: 0.12.0b3...0.12.0b4
0.11.4
Bug fixes
isp.pl.embedding/umap/pca/tsne: fixed silent mis-coloring of NaN
cells in categorical obs columns.
When a categorical column contained missing values, datashader encoded them with
the sentinel code -1, which NumPy's negative indexing silently mapped to the last
category's color bucket. Affected cells therefore appeared in the wrong color with
no legend entry. The fix adds anan_colorparameter (defaultNone): with
nan_color=NoneNaN cells are excluded from the plot; withnan_color="lightgray"
(or any color string) they are shown in that color with a dedicated "NaN" legend
entry. The fix is applied consistently across all rendering backends (static
datashader, interactive datashader, plotly, jscatter).
Full Changelog: 0.11.3...0.11.4
0.11.3
Bug fixes
-
quantify_signal: fixed pixel size mismatch between image and segmentation mask.
When the image and the segmentation mask were stored at different physical resolutions
(e.g. a high-resolution IF image at 0.2125 µm/px paired with a ProSeg mask at 1 µm/px),
the function previously always used level-0 of both pyramids and then naively cropped them
to the same pixel count, causing physically misaligned pixel pairing and incorrect intensity
measurements. The function now selects the image pyramid level whose pixel size is closest
to the mask pixel size, and applies a small nearest-neighbour zoom to the mask to cover any
residual mismatch. This also reduces peak memory usage by avoiding loading the full-resolution
image when the mask has coarser resolution. -
Fixed hidden files causing errors during directory globbing.
Files whose names start with.(e.g..DS_Store) are now filtered out when scanning
directories for input files such as GeoJSON boundaries.
Internal
- Upgraded ReadTheDocs build environment to Python 3.13.
Full Changelog: 0.11.2...0.11.3
0.11.2
What's Changed
- fix: make image metadata JSON-serializable before writing to Zarr store (backport to main) by @jwrth in #432
Full Changelog: 0.11.1...0.11.2
0.12.0b3
Dependency fixes
- Pin pandas to
<3.0.0: pandas 3.0.0 (released January 2026) changed the default string backend to Arrow-backed arrays (ArrowStringArray), which anndata 0.12.x cannot serialize to HDF5, causing anIORegistryErrorwhen saving data viasaveas(). Added an explicitpandas (>=1.5.0,<3.0.0)constraint to prevent incompatible environments. Full pandas 3.0 support is expected once anndata 0.13.0 is released.
Full Changelog: 0.12.0b2...0.12.0b3
0.12.0b2
Bug fixes
- Square image handling in
scale_to_max_width: Fixed a crash when downscaling square images. The previous dimension computation usednp.argmax/np.argminto identify the long and short axes, which both return index 0 for a square image, leaving one dimension asNone. Replaced with a uniform scale factor approach that works correctly for all aspect ratios. (#307)
Internal refactoring
- Split the monolithic
insitupy/containers/dataclasses.pyinto individual sub-modules (cell_data.py,boundaries_data.py,multi_cell_data.py,shapes_data.py,image_data.py,spatial_units_data.py). This is a non-breaking internal change — the public API is unchanged. - Removed the legacy
insitupy/dataclasses/package and the backward-compatibility shim, which had been superseded by the new module layout. - Removed unused
insitupy/plotting/spatial_old.py.
Full Changelog: 0.12.0b1...0.12.0b2
0.12.0b1
What's Changed
This beta release is a major code quality and usability overhaul based on a systematic code review, alongside a new MCP server integration.
MCP Server
- Added
insitupy-mcpas auvx-installable entry point - Claude Desktop users can now activate InSituPy as an MCP server with a single config snippet - Expanded MCP tools: datasets guide, result types, interactive viewer guide, images API, SpatialData API
- MCP server now covers tests/ directory and includes
list_test_filestool
API Improvements
- Standardized parameter names across plotting, tools, and IO (
color→keys,save→savepath,slide_id→dataset_name, etc.) with deprecation aliases for backwards compatibility - Unified
annotation_tupleandregion_tupleparameter pattern verbosedefault changed toFalsein preprocessing functions- Added
.read()classmethods to all major data classes
Code Quality
- ~310 public symbols now have Google-style docstrings
- Replaced all
print()calls with proper logging (~160 across 50+ files) - Replaced all
assertstatements with proper exceptions - Fixed several crash bugs in
SpatialUnitsData.save(),ImageData.load/save() - Package structure:
dataclasses/renamed tocontainers/
Tests
- Added test suites for IO readers, image IO, preprocessing, tools, spatialdata conversion, and plotting smoke tests
- Removed/fixed broken legacy tests
Other
- Version now read from
importlib.metadatainstead of hardcoded string - Image registration QC improvements by @jwrth in #423
Full Changelog: 0.11.1...0.12.0b1