Repository navigation
Releases: robert-mcdermott/situcraft
Release list
SituCraft 0.9.0
Wave 9 of the roadmap: agents and scripts. What a program can do with
SituCraft, and what it may not: an agent asks through typed tools and gets answers that name their
sources, a script runs the same steps from Python or R, and a recipe makes a result again without
a window. situcraft mcp makes SituCraft's 86 actions tools for an AI agent such as Claude Code,
working in the window you watch with the leave you give it; cells and transcripts are asked for by
a tree of conditions, never a query string; every agent's and script's call is logged; situcraft run makes a result's recipe on a server or a cluster's nodes, one bundle or a hundred; R and Python
packages make each action a function; and an agent benchmark grades agents against known answers.
The guide's Agents and scripts follows an agent through two sessions whose every number CI
checks. 0.9.0 keeps a Lung project with a filter of a tree and an enrichment's recipe, which every
later version must reopen and make again with the same ids.
Added
-
The MCP server (wave 9, slice 1).
situcraft mcpis a Model Context Protocol server for AI
agents such as Claude Code: JSON-RPC on stdin and stdout, MCP 2024-11-05 to 2025-11-25.- Its tools are the remote-control actions, under the same names and arguments, with MCP's
hints (read-only, destructive, reaching the network). - Read-only unless allowed. By default the agent is offered the tools that read and show.
--allow editsadds those that change the project,--allow computethose that run jobs,
--allow filesthose that read or write this computer's files by path or download an
example (--allow allfor every one). A call needing more leave than was given is refused
with the leave it needs, and some arguments ask for more (jobswithdo,open_paths
withadd,import_labelswith apath). - In your window, or one of its own. With SituCraft already running on the library with
remote control, the agent works in its window. Otherwisesitucraft mcpstarts SituCraft,
opens its window when a tool needs it, takes no script's actions meanwhile, and stops when
the agent's session ends. - Named in the history. Every change an agent or a script makes is labeled with its name in
the History drawer, and undoes as any other. - Long calls report progress and can be cancelled.
- Documented: docs/MCP.md (Claude Code, Claude Desktop, Cursor, Gemini CLI,
VS Code and Codex; what an agent may do; every tool by the leave it needs) and the guide's
AI agents page. - Validated: the protocol's edges, the leave of every tool and every refusal, the agent's
name reaching the window, files by path, cancellation and progress (never after the reply),
the real command's stdout carrying only the protocol, and attaching to a running SituCraft; in
the browser, an agent's changes named in the History drawer.
- Its tools are the remote-control actions, under the same names and arguments, with MCP's
-
Answers that name their sources (wave 9, slice 2). Three actions the program answers itself,
from the library and the results' folders, with or without a window:list_projects: the library's projects, the most recently changed first.describe_project: what a project holds without opening it: its datasets, every result
with its id, kind, method and the ids of what it was made from, the page's records, regions,
saved views, figures and decisions.get_result: a result's record (method, parameters, what it was made from, software,
job, findings, the projects holding it) and its numbers as tables, a page at a time: each
spatial question's (an enrichment's pairs, Ripley's curves, the bands across an edge, Moran's
I by gene…), a clustering's clusters, a label set's labels, a cohort comparison's tests and a
cohort summary's table, and its summary as the report shows it.- Pictures:
show_tissue,show_mapandfigurewithpicturealso give a picture of what
they show, drawn as a figure draws it (the tissue with its scale bar and legend, a map by
cluster or label, a figure), which an agent receives as an image. - A read-only agent sees maps:
show_mapnow needs no leave, and the window does not make a
map for an agent not given compute. - Validated: the tables against the numbers in the results' files, paging, a project's
results and records, the program answering a script and an agent with no window open; on the
development library, every kind of result read and two pictures looked at.
-
Asking which cells and transcripts (wave 9, slice 3). Questions put as a tree of conditions
in JSON, never a query string:all,anyandnotof conditions on a cell's QC numbers, its
count of a gene, its label, cluster or niche, its region or its distance from one, a box, or a
saved filter; on a transcript's gene, region, distance, cell and quality. SituCraft checks the
tree, refuses one it cannot read with the reason, and evaluates it over the dataset's columns.query_cells: the cells a tree keeps, counted, with the checksum a filter would record, a
page of them with the columns asked for, and how they divide among a label set's labels, a
clustering's clusters or a niches analysis's niches against all the cells.query_transcripts: the transcripts a tree keeps, counted by gene.summarize_region: a region's or box's area, its cells and their density, its labels
against the whole tissue, and the genes most abundant in it and most above the rest.- All three are answered by the program from the library, with or without a window, on the
segmentation asked for (by default the one promoted). - Saved as a filter:
save_filtertakes the same tree (where), and the cells it keeps
become a filter that clusterings, graphs and spatial analyses use, shown, compared and verified
in the QC view as any other. - Validated: every kind of condition against counts made directly from the bundle's
columns; 500 random trees against a reading of each one cell at a time; the 17 filters the
page saved on the Lung bundle (0.1.0 to 0.6.0) reproduced cell for cell by the program; on the
development library, questions about the Lung's tumor nest throughsitucraft mcp, and a
filter saved from a tree used by a graph and verified again.
-
Every call logged (wave 9, slice 4). Each call an agent or a script makes of SituCraft is a
line of the library's log (calls/YYYY-MM.jsonl), refusals and failures too.- What a line holds: when; who called and how (an agent through
situcraft mcp, with its
leave, or a script); the tool and its arguments; whether it was done, refused or failed, and
the sentence it answered; the records it added, changed or removed in the project; the ids
its answer named; and how long it took. - The Calls tab of the drawer (
⌘J) shows the log as calls arrive, the newest first:
searched by words, chosen by caller, tool and outcome, each call opening to its arguments and
what it changed, the records of the open project a click away. It exports as CSV or JSON
lines, and scripts read it at/api/calls. The log never leaves this computer. - An action's answer now says what it changed in the project (
changed). - One line for each call: an agent working in the window of a running SituCraft waits for
its page before sending a call, rather than sending it again. - Validated: every outcome a script's or an agent's call can have, logged once, in the
window's SituCraft or one attached to; long arguments cut short; the ids an answer names;
searching, paging across months and exporting; in the browser, the calls of a script and an
agent shown as they came, and a filter a call added opened from its line.
- What a line holds: when; who called and how (an agent through
-
Recipes, made again without a window (wave 9, slice 5). A result's recipe is every step from
its bundles to it: each the job that made it and its parameters, as readable JSON.- Writing one: the Recipe button in the Reports view's What made a result, or the
recipetool for agents and scripts. Nothing of your computer is in it: a bundle is named by
its role, another file by its name, and what an earlier step made by that step. situcraft run --recipe … --bundle … --out …makes it in a SituCraft of its own, so that
it runs on a cluster's nodes as on your computer. It writes the artifacts,run.json(the
inputs and outputs by SHA-256, each step, and why it stopped if it did not finish) and a
certificate thatsitucraft verifychecks. Exit status: 0 made, 1 a step failed, 2 it could
not run.- On the same bundle, the very same results, with the same ids and files. On another
bundle, the steps that are the program's alone (segmentations, clusters, maps, labels).
A step that carries cells the window chose (a filter's, each cell's label, a region's) is
made only on its own bundle, and the run says so before making anything. - The same files on any number of threads (
--threads) and on any processor; with
--clockthe same recipe gives the same certificate, byte for byte.--dry-runchecks a
recipe without making it. - Validated: recipes written and read back, with no path of the computer in them; made
again with the same ids and files and verified bysitucraft verify; the same files twice, on
one thread and on many, with the same certificate under a fixed clock; the files pinned as
made on arm64 and made again on x86-64; on another bundle, a map made and an enrichment
refused; every ...
- Writing one: the Recipe button in the Reports view's What made a result, or the
SituCraft 0.8.0
Wave 8 of the roadmap: figures and a provable record. What others can
check: figures with scale bars and legends, the methods text, the software and publications behind
a result, a certificate checked by making the result again, and a package that opens anywhere.
Added
-
Figures of the tissue (wave 8, slice 1). The Reports view, until now a placeholder, keeps
the project's figures.- A figure is a page of panels at a journal's column width (85, 114 or 174 mm) or a 16:9
slide, its text 7 pt by default and never below 6 pt, its panels lettered A, B, C in reading
order; previewed as it will print; listed in the project tree. - A tissue panel is a saved view drawn at the panel's size, its region a center and a width
in µm: the stains composited from their samples as the Viewer composites them, at 300 dpi; the
cells' full-resolution outlines and their fill (a label set, clusters, niches, or a number
such as the cell's area); the view's genes' transcripts as points; a scale bar of a round
length; and a legend of the stains, the genes and the labels drawn. Each panel says what it
shows in words. - Written as SVG or PDF (vector, the PDF's text in Helvetica) or PNG (300 dpi), each with the
figure's manifest inside: what each panel shows and was drawn from (the dataset by its
bundle's run and fingerprint, the saved view, the label set or clustering), what it drew, a
digest of its drawing, SituCraft's version and commit, and a fingerprint. The same figure
written at the same time is the same bytes in SVG and PDF. - Read back: a figure SituCraft wrote is compared with the project: whether its manifest is
as written, what changed since in each panel's view, dataset and artifacts, and whether each
panel draws the same now. - Remote control:
figure,write_figureandread_figure. - Validated: in Node, the drawing in SVG and PDF, the compositing of stains against hand
computed pixels, the scale bar's lengths, the layout and letters, and the manifest in every
format, its edits found; in the page, a figure of a saved view of the Lung written in every
format and read with the suite's own readers: the same bytes again, one manifest, the stains'
pixels the suite's own composite of the tiles' samples and the Viewer's within one level, the
scale bar its length, the cells and their fills and the transcripts the suite's own, no text
below 6 pt, the PDF's text the SVG's.
- A figure is a page of panels at a journal's column width (85, 114 or 174 mm) or a 16:9
-
Figures of results (wave 8, slice 2). A figure's panels can be plots of results beside the
tissue, drawn from the same numbers their views show, at the figure's text size and never below
6 pt.- A QC distribution of a dataset's cells (transcripts, all transcripts, area, nucleus area),
in the QC view's 40 bins, on a log scale if asked, with a filter's thresholds. - The cells' map (UMAP), colored by clusters or a label set; many clusters named on the map.
- A spatial answer: an enrichment's or nearest distances' heat map, a dot where a pair differs
from chance, or Moran's I's genes in a pattern as bars. - A cohort's comparison: its effects with their intervals (on a log scale for ratios), a
label's or statistic's units by group, a volcano with the strongest genes named, or a gene by
group; those found red. - More on the tissue: post-Xenium images placed by their alignment (through its deformation),
an H&E laid over at its opacity and immunofluorescence channels added; the dataset's regions
outlined and named; every fill the Viewer draws, certainties, limitations and the review
status among them; the scale bar dark over a light H&E. - Laid out in rows: the tissue panels of a row keep their images as tall as each other; a
plot with more rows than its panel holds at 6 pt says how many it left out. - The Reports view adds a panel of any kind and chooses what it draws; remote control's
figuretakespanelsandcolumns. - Validated: in Node, the charts' ticks, bars, forests on log axes, heat maps, volcanoes,
dots and maps, and an image composited (at its opacity, between its pixels, a channel added, a
deformation followed); in the page, a figure of the Lung's results (every histogram bar the
suite's own binning, every map point and cluster, every heat map square's color and dot, the
genes in a pattern in order), of the simulated cohort's comparisons (each estimate on the log
scale, the found red, a volcano point each gene, a dot each unit), and of the simulated tissue's
H&E (60 pixels the suite's own placing of the image through its deformation and transform, and
the Viewer's within four levels).
- A QC distribution of a dataset's cells (transcripts, all transcripts, area, nucleus area),
-
What made a result (wave 8, slice 3). The record of any result: an analysis, a comparison, a
summary, a label set, a clustering, a map, a graph, a segmentation, an alignment, a filter or a
figure.- Each step from the bundles to the result, in an order where each comes after the steps it
was made from: its method and version, its parameters and seeds, the software that ran it, the
decisions about it (a segmentation promoted, an alignment chosen) and the publications it
follows. A cohort's result reaches back through each sample's segmentation, clustering, labels,
graph and analyses, as the summary's job recorded them, and through the design. - The references in one place: every publication SituCraft cites (the methods' papers, the
starter marker sets' atlases, the science page's list), numbered as first cited, each with its
DOI; a marker set's or an import's own citation kept as written. - Shown in the Reports view, below the figures (choose a result, or What made it in the
inspector), and written as Markdown (the samples' same steps written once), JSON
(situcraft-record) or BibTeX. - Remote control:
record, andexportwithwhat: record. - The cohort summary's citation names the published muscat paper (Crowell et al. 2020) by its
title. - Validated: each DOI against a recorded copy of Crossref's record of it (its title,
journal, year, volume, first page and first author); every citation the program records, the
starter sets' atlases and the science page's references found in the list; in Node, the
steps' order, inputs, seeds and references of a sample's and a cohort's results; in the page,
the Lung enrichment's record (from the bundle through its segmentation, clustering, marker set,
labels and graph, the clustering's seed its parameters', the methods' and atlas's papers cited,
the same record in every format) and the simulated cohort's expression comparison's (eight of
each sample's steps, the design, the summary, every method's paper).
- Each step from the bundles to the result, in an order where each comes after the steps it
-
The methods text (wave 8, slice 4). A methods section written from the record of the whole
project, a dataset (and everything made of it) or a result.- Every kind of step said as what was done, in paragraphs by topic: the data and its check;
images and their alignments (and why one was chosen) and checks; regions; segmentations
(expanded, refined, imported, chosen after a comparison, with why) and comparisons; filters
and reviews; clusters, maps, marker sets and labels (from markers, a reference, imported,
curated, consensus); graphs and every spatial question; a cohort's design, summary and
comparisons, with what they found; figures; the software and its versions. - Each step's parameters and seed are said, and what it found; a step made the same way for
several sections, segmentations or regions is said once, naming each. - References numbered as first cited, each with its DOI.
- Shown in the Reports view (copied, or written as Markdown or BibTeX), in the Data view's
Methods (a dataset's) and by Its methods in the inspector. Remote control:methodstakes
resultorproject, andexportwrites any of them. - Each method's own citations: each spatial question now records its own papers, a graph
those of its kind, the clusters Reichardt and Bornholdt's resolution, automatic registration
Hooke and Jeeves's search, and niches across samples Goltsev's and k-means++'s. - Validated: in Node, a result's, a project's and a dataset's methods, each number their
records', numbered as first cited; in the page, the Lung enrichment's methods against its
records and written as Markdown, and the simulated cohort's expression comparison's and
project's.
- Every kind of step said as what was done, in paragraphs by topic: the data and its check;
-
Certificates (wave 8, slice 5). A certificate of a result, a dataset's results or the whole
project: a zip of what it rests on and what it reports.- What it holds: the bundles by their files' SHA-256; each step from them to the result, the
program's by its job, parameters and the SHA-256 of every file it wrote, the page's own by its
record's digest, a figure by its drawing's digests, each with the numbers it reports; the
project, the record and the methods. - Its fingerprint, the SHA-256 of what it certifies, names it; a README says what it proves,
howsitucraft verifychecks it, and what is not made again. - The same bytes for the same project: no time of its own, and no path of your computer
(a bundle's folder stood in for by its dataset, any other path by its file's name). - In the Reports view, What made a result is of a result, a dataset or the project, and
writes its Certificate; remote control:exportwithwhat: certificate, andrecord
of a dataset or the project. - Validated: in Node, each step's files or digest, no path, the same bytes...
- What it holds: the bundles by their files' SHA-256; each step from them to the result, the
SituCraft 0.7.0
Wave 7 of the roadmap: samples and cohorts. A study's sections in one
project, each a sample, compared with the sample or the subject, not the cell, as the unit.
Added
- Samples (wave 7, slice 1). A project of several sections, each a sample, in the Cohort
view.- Sections added together: bundles chosen at once, or a folder of them, added in one step
(Add all to the project, in the Data and Cohort views), each checked first. - Samples: each dataset is a sample, or its regions are instead (a tissue microarray's cores,
sections placed on one slide), named by their regions until named; a region removed leaves its
sample flagged and left out. The project tree lists the samples. - Fields: subject and condition, and any added, as text or numbers (a number field takes only
numbers; missing values stay empty, never zero); fields renamed, retyped and removed. The run,
slide, Xenium region, panel and software read from each bundle beside them; a dataset now
records its slide and its panel's design. - Tables: the samples written as CSV and read back (CSV or tab-separated), rows matched to
samples by name, new columns added as fields, what did not match said; a table naming a sample
twice, or a value that does not fit, refused with nothing changed. - Each sample's cells under its dataset's default segmentation, counted in its region, and a
region's area. - Remote control:
samples,set_samples;exportwritessamples. - Validated: fields, names, regions and tables by hand, the CSV read back byte for byte
(quotes, line breaks, every digit of a number, a zero); in the page, the Lung and Breast bundles
added together, fields written and read back, refusals changing nothing, two regions of the
Lung as samples, their cells the suite's own count by centroid, all kept with the project; every
earlier release's project opening with each dataset a sample.
- Sections added together: bundles chosen at once, or a folder of them, added in one step
- Simulated cohorts (wave 7, slice 2).
situcraft simulate --cohortmakes sections of subjects
in groups, each a simulated bundle, whose differences are known: for checking the comparisons of
groups to come.- The design: groups (the first the reference), subjects in each or paired subjects in every
group, and slides as batches (each holding every group), each slide detecting transcripts a
little more or less well. - Known effects in a group: a cell type's odds against each other type, in every domain or in
the domains another type leads (how much it mixes into them), and a gene's level in a type. - Variation as asked, from section to section: each type's weight and each gene's level in
each type, log-normally; a paired subject's sections sharing a part of it. The sections share
the panel and the domains' mixes, each with its own layout, cells and molecules. - The truth (
truth/cohort.json): the design, each effect with what the true cells show of
it (each section's value, the groups' difference and its standard error), and each section's
true cells by domain and type and transcripts;samples.csv, each sample's subject and
condition;situcraft-cohort.json, its parameters. - Presets:
standard(four subjects in each of two groups, on two slides, with three effects;
about 3 s and 64 MB),null(no effect) andpaired(four subjects before and after). - The start page's A simulated cohort, made in seconds and opened as a project of its eight
samples, each with its subject and condition and its slide and run read from its bundle. - Remote control:
open_examplewithcohort. - Validated: the same cohort from the same seed, byte for byte on arm64 and amd64; each
effect as the true cells show it within three standard errors of the fold asked over 24
sections, the null cohort's groups alike; a gene's fold exact in each section; the variation's
spread and a paired subject's correlation as asked; in the page, the cohort made and opened,
each sample with its subject, condition, slide and run, one panel in every section, the truth's
cells each bundle's own and every effect the suite's own from the truth's counts.
- The design: groups (the first the reference), subjects in each or paired subjects in every
- The design (wave 7, slice 3). Before any comparison of groups, the Cohort view's Design
names what replicates what.- The replicate unit (a field,
subjectby default), the groups compared (a field,
conditionby default) and their reference, contrasts (each group against the reference,
or others), covariates (any field, numbers as they are and text as factors, or the bundles'
run, slide and panel) and samples left out with their reasons. - Rows are units in groups, a unit's samples in one group (technical replicates) combined; a
unit in more than one group pairs them, and the units enter the model. - Said in words (what is compared, the units in each group, pairing, covariates, the degrees
of freedom left) and as a matrix in treatment coding, column for column patsy's. - Refused, saying why: a group of fewer than two units, a term confounded with another (its
columns combinations of those before), the groups confounded with a slide, run or panel, no
degrees of freedom left, regions of one section as separate units, and a covariate with two
values for one unit in a group. Uneven batches and few degrees of freedom are noted. - Saved as versions of a name, with the samples as they were and those left out; a saved
design whose samples have changed says so. The project tree lists Designs. - Remote control:
design. - Validated: unpaired, paired, partly paired, unbalanced, covariate, three-group and
technical-replicate designs and every refusal by hand; six designs' matrices against patsy
1.0.3's for the same formulas (validation/reference/designs/); in the page, the simulated
cohort's designs (adjusted for the slide, paired, refused when confounded or with a group of
one subject) and their versions kept with the project.
- The replicate unit (a field,
- Sample summaries (wave 7, slice 4). Every sample measured the same way, and the cohort table
of their numbers, in the Cohort view.- The same steps on every sample: each dataset's cells clustered with SituCraft's defaults and
labeled from one marker set (a starter resolved on the first and used for the rest), so that
every sample's labels have the same names; a graph of each sample's cells (a region sample's,
its region's) and the same questions asked of each with the same parameters (neighborhood
enrichment, nearest distances, Moran's I). A step made already is answered at once. - The cohort table, an artifact of kind
cohort-summary: each sample's cells by label
(counts, shares of its labeled cells, densities per mm² of its tissue, within its region for a
region sample; a label no cell carries counted as none), its niches' shares, its quality, its
graph's numbers, its answers' (an enrichment's ratios, nearest distances' medians, each gene's
Moran's I) and its pseudobulk (each label's transcripts gene by gene; a gene one panel lacks
left empty, never zero). Each number is traced to the artifact it came from. - Niches across the samples: each cell's window of its nearest labeled cells in its own
sample, the windows of every sample pooled and grouped by one k-means, so that a niche is the
same kind of place in every sample; each niche's defining labels listed. - Shown a family at a time, a sample a row, each number's tip naming its source; written as
CSV: the table (a row each number, with its source), the pseudobulk (a row each sample's
label, a column each gene) and the family shown. The project tree lists Summaries. - Remote control:
cohort_steps,summarize_samples(of every sample or those named),
cohort_table;exportwritescohort-tableandpseudobulk. - Validated: a sample's numbers worked by hand; the tables read back to the last digit; the
niches found across samples the same as each sample's own when there is one; in Go, a section
and a region of it summarized, every number against the cells and the other artifacts; in the
page, the simulated cohort's eight samples through the steps and summarized, every one of
1,280 numbers equal to the artifact's it came from, each sample's shares within 0.03 of its
true types', its tissue within 2% of the section, the pseudobulk's raised gene within 0.15 (log)
of the truth's, the niches found together near each sample's own (and for one sample alone,
exactly its own), every domain's leading type defining a niche.
- The same steps on every sample: each dataset's cells clustered with SituCraft's defaults and
- Cohort QC, batches and panels (wave 7, slice 5). Before any comparison, the samples side by
side, in the Cohort view.- Quality by sample: cells per mm², median transcripts and genes, transcripts per 100 µm²,
median cell and nucleus areas, the shares of cells with a nucleus and without a transcript,
beside each sample's slide, run and panel. A sample far out on one (a robust z-score of 3.5
from the median absolute deviation, as Iglewicz and Hoaglin's, and a difference that matters:
20% for a quantity, 5 points for a share) is flagged with the reason in words, never passed
or failed; leaving it out of the design asks for a reason the design keeps. - Batches: the numbers' medians by slide, run and panel; each batch's samples by the design's
groups, a group confounded with a batch said. Nothing is corrected unless the design adjusts
for the batch. - The pseudobulk's principal components over the genes every panel has (log2 counts per
million, ...
- Quality by sample: cells per mm², median transcripts and genes, transcripts per 100 µm²,
SituCraft 0.6.0
Wave 6 of the roadmap: niches and spatial statistics. How the tissue is
organized, asked of a segmentation's labeled cells: which cell types are neighbors, how far apart
they lie, which enter a region, what niches the tissue has and which genes follow space, each result
with the cells it comes from.
Added
- Cell graphs (wave 6, slice 1). The Spatial view builds a graph of which of a
segmentation's cells are neighbors, the first step of every spatial question.- Four definitions: the Delaunay triangulation of the cells' centers, its edges up to a
longest length (50 µm by default); each cell's k nearest (6), an edge when either cell is among
the other's k; the cells within a radius (20 µm); and contact, cells whose outlines touch in the
segmentation (or lie within a gap), with the boundary they share. - The cells: all of a segmentation's, a QC filter's or those in regions; cells a review
excluded from analyses are always left out, and the graph records how many. - Exact: the triangulation by exact geometric predicates, the same for any points, lattices
whose cells lie four on a circle included; every graph the same on any number of threads and on
any processor. - An artifact of kind
graph, named by what it is made from (asking again answers it): its
cells and edges with their lengths and shared boundaries, and what it holds: the neighbors a
cell, cells without one, its pieces, its edges' lengths, with histograms. - On the tissue: the Viewer's Graph draws the edges over the cells, close up; a cell's
inspector lists its neighbors with their distances and labels. Saved views keep the graph. The
project tree lists Graphs. - Remote control:
build_graph;show_tissuetakesgraph. - Validated: lattices worked by hand (each kind's degrees and lengths); the triangulation's
empty circumcircles and Euler's count of triangles on random, cocircular, collinear and
repeated points; radius and k-nearest graphs against an exhaustive search; contact on label
rasters drawn by hand; on both development bundles and the standard simulated tissue, the same
edges as SciPy 1.18 (Delaunay by Qhull, a k-d tree) and Squidpy 1.8 (spatial_neighbors),
edge for edge, lengths identical; in the page, a radius graph's edges those of an exhaustive
search, a region's graph over its cells, the edges drawn where they lie.
- Four definitions: the Delaunay triangulation of the cells' centers, its edges up to a
- Which cell types are neighbors (wave 6, slice 2). The Spatial view's Questions ask a
label set's cells (any set, any level) how they are arranged; each answer is an artifact of kind
spatial, named by what it is asked of.- Neighborhood enrichment over a graph: for each pair of labels, the neighbors between their
cells against the number expected if the labels were dealt to the same cells at random, the
expectation exact; z-scores and two-sided p-values from seeded permutations (1,000 by default),
adjusted by Benjamini and Hochberg's procedure over the pairs that can be tested. Optionally
dealt within regions, so that each keeps its composition; in a contact graph, counted by the
boundary shared, with the contact fractions. Shown as a heat map of the ratio (red more, blue
fewer, the significant marked), tables of the pairs most and least often neighbors, and each
label's neighbors by label. - Co-occurrence across distances: from one label's cells, how much likelier each label's are
within a distance (or since the distance before) than any cell's, as curves. - Every number's cells on the tissue: a pair's cells with a neighbor of the other label
highlighted, the edges between them drawn in color over the graph; a label's cells near
another's. - Remote control:
spatial_analysis;show_tissuetakescells_of. The project tree lists
Spatial analyses. - Validated: a checkerboard's enrichment, the permutations' mean against the exact
expectation (with and without regions), uniform p-values on randomly labeled cells, regions
that fix every label; co-occurrence worked by hand and against an exhaustive count; on both
development bundles and the standard simulated tissue, labeled by their clusters, every count
Squidpy 1.8.3's, every z-score within the two tools' permutation error (correlation above
0.999), and every co-occurrence ratio Squidpy's routine's in float64 (to 10⁻¹⁴; its float32
places 3 pairs of Lung and 1 of Breast on the other side of a distance); in the page, the
counts, expectation, a pair's cells and a co-occurrence ratio against the suite's own.
- Neighborhood enrichment over a graph: for each pair of labels, the neighbors between their
- How far apart, and at what scale (wave 6, slice 3). Two more questions in the Spatial view.
- Nearest distances: each label's cells' distance to the nearest cell of each label, up to a
reach (100 µm); each pair's median against the labels dealt again to the same cells (z,
two-sided p, Benjamini–Hochberg), and the distribution of the distances with chance's
envelope. A heat map, red where nearer than chance, and tables of the nearest and farthest. - Ripley's K and L, of each label and across each pair, in a window (the tissue, its cells'
footprint with narrow gaps closed and holes kept, or a drawn region), with Ripley's isotropic
edge correction computed exactly for any polygon; shown as L(r) − r against the envelope of the
labels dealt at random, with a global test over the radii; tables of the labels that gather and
those that keep apart. - Effect sizes first: among the significant pairs, tables and summaries rank by the size of
the effect (a ratio, or µm), not by z. - Remote control:
spatial_analysisasks both (distances,ripley, withreach,
window,closing,correction);show_tissue'scells_ofshows the cells within a
distance of each other. - Validated: a window's area, inside, edge distance and circle shares by hand and against
Ripley's closed form for rectangles (2,000 cases, to 10⁻⁹); K of complete spatial randomness
within 0.6% of πr² in a square and an L-shaped window (without a correction, 8% to 13% short at
100 µm); a Thomas process's K within 6%; nearest distances against an exhaustive search; labels
kept apart, drawn together and dealt at random; on both development bundles and the standard
simulated tissue, nearest distances SciPy's k-d tree's exactly, K without a correction
astropy's exactly, and the isotropic correction the same estimator computed independently to
10⁻⁸ (astropy's variant, weighing each pair by one circle, a median of 0.6% apart); in the page,
a pair's median nearest distance, K in a region and the cells within a radius against the
suite's own.
- Nearest distances: each label's cells' distance to the nearest cell of each label, up to a
- Regions measured (wave 6, slice 4). Two questions asked of drawn regions.
- Regions compared: each region's cells by label per mm² of the tissue within it (its glass
and holes not counted) and per labeled cell, with Garwood's and Wilson's intervals; the tissue
in none of the regions a row of its own; any two rows compared as ratios with exact conditional
and Koopman's intervals, shown as a forest plot. - Across a region's edge: each label's density in bands of distance from the edge (every
10 µm, 100 µm inside to 100 µm outside), each band's own tissue its denominator; the core, the
margin and around compared, saying which labels fill the region, stay out or gather at its
margin; a label's profile across the edge. - Areas exact: the tissue within each region or band found by squares split until uniform,
those crossed by an edge at the finest size split along it, to about 10⁻⁶. - Remote control:
spatial_analysisasks both (regions,boundary, withregionand
margin);show_tissue'scells_ofshows a label's cells in a region or a zone. - Validated: band areas of a square, a 64-sided polygon and a square in a pixel tissue
against their exact formulas (to 10⁻⁵, most to 10⁻⁷); uniformly placed cells' densities within
their intervals as often as they claim; labels placed by rule read as filling, staying out and
gathering at the margin; the intervals against SciPy's and statsmodels' (to 10⁻⁹); on both
development bundles and the standard simulated tissue, every region's and band's area Shapely's
(to 2 × 10⁻⁷ and 4 × 10⁻⁶) and every count its; the simulated tissue's own domains, as regions,
each found denser in its dominant type; in the page, the counts in a region and in each band and
the cells at a margin against the suite's own.
- Regions compared: each region's cells by label per mm² of the tissue within it (its glass
- Cellular neighborhoods (wave 6, slice 5). A question in the Spatial view, and a label set.
- Niches: each cell's neighborhood (its 10 nearest labeled cells, or those within a radius)
by its labels' shares, the cells grouped by k-means with k-means++ seeding, the best of 10
starts, into niches numbered by size; each niche's make-up against the tissue's (a heat map),
its defining labels and its leading genes; the niches found again from 4 other seeds and their
agreement stated (the adjusted Rand index). - Niches as labels: the Viewer fills cells by niche, and every other question can be asked
of niches. - Remote control:
spatial_analysisasksniches(neighborsorradius,niches,
starts,seeds);show_tissuetakesfill: nichesandcells_ofwith a niche. - The simulator's truth gives each cell its domain (
truth/cells.parquet'sdomain). - Validated: k-means against every partition of small sets (the optimum each time),
separated clusters found exactly, the same on any number of workers; each window against an
exhau...
- Niches: each cell's neighborhood (its 10 nearest labeled cells, or those within a radius)
SituCraft 0.5.0
Wave 5 of the roadmap: the pathology bridge. Post-Xenium H&E and
immunofluorescence images on the tissue, aligned and checked in µm; regions exchanged with QuPath;
cells and regions reviewed with their provenance.
Added
- Post-Xenium images (wave 5, slice 1). An H&E or immunofluorescence image of the section,
stained and scanned after the Xenium run, drawn on the tissue under the transcripts and cells.- The image: a pyramidal, tiled OME-TIFF, as Xenium Explorer requires: RGB, or channels of
8 or 16 bits; deflate, LZW, JPEG or JPEG 2000 tiles. Read where it lies, never copied, a tile
at a time; recorded as an artifact of the dataset with its SHA-256. - Its alignment: the transformation matrix or keypoints Xenium Explorer saves, found beside
the image when 10x named it, recorded as the first version of its alignment (slice 2). The
image is placed by an alignment, never by the pixel size its own metadata gives (on the
pathology fixture's immunofluorescence image, the Xenium image's, 3.5 times too small). - The Viewer lists each image with how it is placed (scale, turn, mirroring), shows it at its
opacity at any rotation or reflection, an immunofluorescence image's channels each with a
color, window and gamma as the stains have; saved views keep them. The project tree lists
Images. Remote control:add_image;show_tissuetakesimages. - XOA 1.0 bundles open: cells numbered rather than named, the count matrix's earlier layout,
and Parquet files whose footer's row count is wrong (as fastparquet 1.0 wrote them). - JPEG tiles in TIFFs, their shared tables and colors as libjpeg-turbo decodes them.
- Validated on the pathology fixture (the breast cancer section of Janesick et al. 2023, its
bundle's files and its H&E and immunofluorescence images, 2.8 GB): every level of both images
the pixels tifffile reads; the XOA 1.0.1 bundle's checks; its H&E drawn where its matrix puts
it.
- The image: a pyramidal, tiled OME-TIFF, as Xenium Explorer requires: RGB, or channels of
- Alignment by landmarks, kept as versions (wave 5, slice 2). An image can be added without an
alignment and placed by landmarks; every alignment of an image is a version, and one places it.- The Alignment view: the Xenium image and the post-Xenium image side by side. A landmark is
a place clicked on both; once three are placed, the fit predicts where the next one falls and
the other image goes there. Landmarks are dragged to move them. The fit, a similarity (move,
turn, one scale, a mirror) or an affine transform (also stretched and sheared), updates as they
change, with each landmark's residual and its leave-one-out error in µm (where it falls when
fitted from the others: the error to expect where no landmark is), and the image can be laid
over the stains as fitted. - Versions: each alignment is an artifact naming its source and destination coordinate
systems (the image's pixels, the dataset's µm), with its landmarks, fit and errors, who made
it, a note and the version it was made from. Which one places the image is a decision kept
with its reason. Any version is written as Xenium Explorer's transformation matrix or
keypoints, to load with the image there. - Simulated post-Xenium images:
situcraft simulate --post-xeniumalso makes an H&E
(hematoxylin and eosin by Beer–Lambert's law, their colors varied per section) and an
immunofluorescence image (DAPI and a membrane stain) of the simulated section, each moved by a
known transform and a smooth deformation, written as its truth. - Remote control:
align_image,use_transform,show_alignment;add_imagewithout an
alignment;exportwrites an alignment for Xenium Explorer. - Validated: fits worked by hand (residuals and leave-one-out errors of a square of
landmarks); known similarities and affine transforms recovered exactly from their landmarks;
the page's fits the program's bit for bit; 10x's matrices for the fixture's H&E and
immunofluorescence image are similarities, and keypoints made with them fit back to them; the
simulated images' nuclei, found in them, lie where their truth puts them (a median 0.03 µm off
on the H&E), and the leave-one-out error of landmarks on them is near their fit's true error;
in the page, an image placed by six landmarks clicked on both images is drawn where the fit
puts it.
- The Alignment view: the Xenium image and the post-Xenium image side by side. A landmark is
- Automatic registration (wave 5, slice 3). Align automatically in the Alignment view (and
register_image) aligns an image to the Xenium image by the nuclei, as a job: an H&E's
hematoxylin (color deconvolution) or an immunofluorescence image's nuclear stain against DAPI.- Its scale, turn and mirroring are found, whatever its metadata says: a sweep of scales, the
image as it is and mirrored, the turn from the log-polar form of its spectrum and the shift by
phase correlation, the best by normalized mutual information; then refined by mutual
information over a pyramid, and fitted (a similarity or an affine transform) to local matches
of patches over the tissue, those that disagree with the rest dropped. - A smooth deformation, when asked, for a section that stretched: B-splines fitted to what the
model leaves of the matches, as smooth as best predicts matches held out, never folding, and
kept only when it predicts them clearly better than the model alone. The Viewer draws a
deformed image as it is deformed. - Each result is a version of the image's alignment, with its matches (shown on both images),
its fit and what the search found, started from scratch or from another version. The same
images give the same version on any computer. - Validated: on the pathology fixture, without their alignments and with the immunofluorescence
image's metadata 3.5 times wrong, the H&E and the immunofluorescence image placed within 0.61 and
0.68 µm (root-mean-square) of 10x's alignment over the Xenium image; on simulated images, the
scale, turn and mirror found and the result within 0.2 µm of the truth where the image was not
deformed, and the deformation brings a deformed one from 0.9 µm to 0.2 µm and is refused where
there is none; the page draws a deformed image where the program's deformation puts its pixels.
- Its scale, turn and mirroring are found, whatever its metadata says: a sweep of scales, the
- Alignment checked in µm (wave 5, slice 4). The Alignment view's See and check shows any
version on the Xenium image, and measures where it is off.- Seen: over the stains at an opacity, as a checkerboard of the image and the stains (squares
of a size chosen), or flickering between them; with DAPI's edges (the nuclei's boundaries in
yellow) or the Xenium segmentation's nuclei over the image. - Measured: Measure where it is off checks a version over the whole section, as a job:
patches of DAPI where there is tissue, between those an automatic alignment matched, each
against the image as the version draws it; how far it is off in µm (median, 90th percentile,
most) and a bound of the matches' own error, below which an error may be theirs. Show where it
is off maps each patch's error as a colored square with an arrow. Each check is recorded as
an artifact of its version. Remote control:check_alignment;show_alignmentshows a
version as asked. - Validated: on a simulated H&E placed by its true transform without its deformation, each
patch's measured error within 0.15 µm of the true one, without bias (0.03 µm); in the page,
six landmarks' version measured 0.85 µm off (truly 0.89 µm), the automatic one 0.23 µm; the
checkerboard and DAPI's edges drawn as asked. On the pathology fixture, 10x's alignment of the
immunofluorescence image is off by 0.85 µm (median), 2.10 µm (90th percentile); the automatic
one with its deformation, 0.48 and 0.72 µm.
- Seen: over the stains at an opacity, as a checkerboard of the image and the stains (squares
- Regions (wave 5, slice 5). The Viewer's Regions draws areas on the tissue, over any layer
(the stains, an H&E, an immunofluorescence image).- Tools: a rectangle (drag), a polygon (click its corners; double-click or Enter closes it,
Backspace takes a corner back), freehand, and a brush that paints a region, or paints onto the
region chosen or erases from it (holes, and parts cut apart). The wheel still zooms and the space
bar pans while drawing. - Named and classed, with QuPath's classes and colors (Tumor, Stroma, Immune cells,
Necrosis, Other, Region*, Ignore*) or any other; each region's area and cells (those of the
segmentation drawn whose center lies in it); Choose its cells chooses them for the QC view,
the Viewer and the inspector. - Kept as versions in the project: renamed, reclassed, reshaped, removed and returned, each
change with who, when and why; any earlier version restored. - With QuPath: regions written and read as GeoJSON as QuPath writes and reads annotations
(from QuPath 0.2's layout to 0.4's), in µm, the Xenium image's pixels, or a post-Xenium image's
pixels through its alignment (a deformation too): drawn on the H&E in QuPath, they land on the
tissue here, and back. Detections and cells in a file are left out, and counted. - The brush paints at an eighth of its radius however large the region, and changes a region
only near its stroke. - Remote control:
draw_region,edit_region,regions,import_regions;exportwrites a
dataset's regions as GeoJSON. - Validated: in the page, each region's cells the same as an independent count (a winding
number over the cells' centers); regions drawn by hand where the pointer went; regions written
in the simulated H&E's pixels through its deformed alignment and read back with the s...
- Tools: a rectangle (drag), a polygon (click its corners; double-click or Enter closes it,
SituCraft 0.4.0
Wave 4 of the roadmap: cell identities with their evidence. Cells are
clustered, mapped and labeled from markers, imported tables or a reference, each label with its
confidence and evidence, reviewed and kept as versions; every result is an artifact of its
segmentation, so it can be made again on another and the two read against each other.
Added
-
Clusters (wave 4, slice 1). The Cell types view clusters a segmentation's cells by their
gene expression, as a job, and records the clustering as an artifact of that segmentation with
every parameter.- The steps, as the common single-cell workflow takes them: the cells with at least 10 gene
transcripts (or those a saved QC filter keeps), each cell's counts scaled to the median total
and log-transformed, each gene scaled, exact principal components (50), each cell's 15 nearest
neighbors weighted as UMAP's graph, and Leiden communities at a resolution, numbered by size.
The same seed gives the same clusters on any computer. - What it shows: each cluster's size and leading markers (the Wilcoxon rank-sum test against
the other cells, with log₂ fold changes and the shares expressing; exploratory, since cells
are not replicates), the components' share of the variance, and Show on the tissue: the
cells filled by cluster in the Viewer, with a legend. The Viewer's Fill by lists each
clustering of the segmentation drawn. - Remote control:
cluster_cells;show_tissuefills byclusters. - Validated against scanpy, leidenalg, umap-learn and scikit-learn on both development
bundles and the standard simulated tissue: the same principal components (variances within
1e-13), the same neighbors, modularity within leidenalg's range over ten seeds, markers' scores
identical to the rank-sum test with exact ties, and the same leading markers as scanpy. On the
simulated tissue the clusters agree with the true cell types (adjusted Rand index 0.95).
- The steps, as the common single-cell workflow takes them: the cells with at least 10 gene
-
The map and exploring clusters (wave 4, slice 2). Each clustering comes with a map of its
cells (UMAP, made at once as a job and kept as an artifact), beside the tissue in the Cell types
view.- Linked: the map and the tissue colored alike (by any clustering's clusters, a gene, the
cells' transcripts or area, or how faithfully the map keeps their neighbors), and one selection
on both: cells lassoed on either side, or chosen by cluster. Markers of the selection
compares any selection with the other cells. - Honest about distortion: every map's trustworthiness and each cell's neighborhood
precision and recall are measured, and the page says in plain words what the map can show. - Clusters named and merged: names are versions in the project (the clusters keep their
numbers); the same name merges clusters on the map, the tissue and the legends. A dot plot
of each cluster's leading markers. - The instrument's own clusters (graph-based, and k-means of 2 to 10) and map, read from the
bundle'sanalysis.tar.gzand added as a clustering whose markers SituCraft computes;
two clusterings compared by their cross-table and adjusted Rand index. - Remote control:
show_map,name_clusters,instrument_clusters. - Validated: the same map as umap-learn's of the same graph, by every measure within its
spread over five seeds (trustworthiness 0.737, 0.779 and 0.840 on Lung, Breast and the
simulated tissue); the trustworthiness recomputed independently from the places; the
instrument's clusters as the bundle's other copy of them holds them; the map's selection and
linking in the viewer suite.
- Linked: the map and the tissue colored alike (by any clustering's clusters, a gene, the
-
Labels from markers (wave 4, slice 3). Under a clustering, the Cell types view labels each
cell from a marker set, as a job, and records the labels as an artifact with the marker set they
came from.- Marker sets: a hierarchy of labels (class, lineage, subtype) and states, each with positive
and negative markers and the sources they come from. Starter sets for the Breast and Lung
panels, from published cell atlases; edited in the app as versions kept in the project; read
and saved as files. Genes the panel lacks are shown, and removed on request. - Scores and labels: each cell scored for each label against control genes of similar
expression, as scanpy'sscore_genesscores a gene list (Tirosh et al. 2016), its negative
markers counting against it; labels taken from the top of the hierarchy down when the best
leads the next by a margin, else the cell stays at the level above; confidence from the lead. - What it shows: each cluster's labels at each level as bars, names for the clusters from
them, each label's markers and control genes; the map, the tissue and the Viewer colored by the
labels, their confidence or a label's score. - Remote control:
label_cells;show_mapandshow_tissuecolor bylabels. - Validated against scanpy on both development bundles and the standard simulated tissue:
every label's control genes scanpy's, every cell's score within 3e-7. On the simulated tissue
97% of the cells take their true type.
- Marker sets: a hierarchy of labels (class, lineage, subtype) and states, each with positive
-
Imported labels (wave 4, slice 4). Labels made elsewhere are imported for a segmentation's
cells and kept as a label set with their source.- Read: CSV and TSV (gzipped or not), Parquet, an AnnData object's obs in Zarr (or a
SpatialData store's table), Xenium Explorer's cell groups with their colors, and the
instrument's own clusters. The columns of the cells' ids, their labels, a confidence and colors
are suggested by their usual names, and chosen before importing. - Matched by the cells' ids: a table naming cells the segmentation does not have is refused,
with how many (and the segmentation whose cells they are, when the dataset has it); cells the
table does not name are counted. - Shown as any label set: each cluster's labels for the clustering shown, names for the
clusters from them, the map, the tissue and the Viewer colored by them, a label's cells
selected. - Remote control:
import_labels. - Validated on files written by pandas, pyarrow and anndata, read exactly, and on both
development bundles: their graph-based clusters, imported as a table, every cell its cluster.
- Read: CSV and TSV (gzipped or not), Parquet, an AnnData object's obs in Zarr (or a
-
Label versions, evidence and review (wave 4, slice 5).
- Versions side by side: curated labels (a predicted set and a reviewer's changes, each with
its reason, who and when, appended) and consensus labels (a rule — unanimous, majority, in order
— over chosen sets, their labels mapped to common names), shown on the map, the tissue and the
Viewer like any label set; any two compared in a cross-table. - A cell's evidence: its label in every version; from markers, why it took its label and not
the next, or not the one its neighbors carry, gene by gene in the cell; its neighbors' labels in
the tissue and in expression; its counts and its segmentation's flags; its reviews. - The review queue: cells whose label their nearest cells rarely share, and cells of low
confidence, the most doubtful first; accept or relabel each, saying why. - Remote control:
review_labels,label_evidence,curate_labels,consensus_labels. - Validated on built sets (the consensus rules), and on planted mislabels: the queue finds 95%
of them on the Breast tissue and 75% on the simulated one, whose domains mix their types.
- Versions side by side: curated labels (a predicted set and a reviewer's changes, each with
-
Labels from a reference (wave 4, slice 6). Under a clustering, the Cell types view labels each
cell from a labeled single-cell reference, as a job, and records the labels as an artifact with
the reference as it was compared.- References: an AnnData object in Zarr (its labels in
obs, its counts or log-normalized
values inX,raw/Xor a layer), or a table of each label's mean expression (CSV, TSV or
Parquet, a row per label or per gene), its columns suggested and described before use: its
labels, how many of the panel's genes it has and which it lacks. An.h5adfile is read once
written as Zarr (anndata'swrite_zarr). - The method: each cell's Spearman correlation with each label's profile over the genes that
set the labels apart, then again over the leading labels' own genes until one is left (Aran et
al. 2019, as SingleR maps cells); the label taken by a margin, its lead the cell's confidence. - Its evidence: each round's correlations, and the genes higher in the cell's label's profile
and in the next's that the cell expresses; the review queue and versions treat these labels as
any others. situcraft simulate --reference Nwrites a reference of the simulated tissue's types beside
it.- Remote control:
reference_labels;label_evidenceanswers a reference's rounds. - Validated against SingleR on both development bundles (the Human Primary Cell Atlas's main
labels) and the simulated tissue: given the same profiles, every cell's correlations within
3 × 10⁻⁸ and the same label on 99.97% to 100% of the cells. On the simulated tissue 98.1% of the
cells take their true type.
- References: an AnnData object in Zarr (its labels in
-
Labels across segmentations (wave 4, slice 7). What the choice of segmentation changes in
the cells' labels.- Made again in one step: a clustering and its label sets from markers or a reference made
again on another segmentation with the same parameters, from the label sets' card. - The comparison workspace's Labels tab: a label set of each segmentation read through the
comparison: how many matched cells keep their label and which change, what split and ...
- Made again in one step: a clustering and its label sets from markers or a reference made
SituCraft 0.3.0
Wave 3 of the roadmap: SituCraft's own transcript-informed
segmentation, validated against simulated truth and independent reference outputs.
Added
-
Simulated tissues (wave 3, slice 1).
situcraft simulatemakes a tissue whose every cell,
nucleus and molecule is known, and writes it as a Xenium output bundle labelled simulated, with
the truth beside it (docs/FORMATS.md).- The tissue:
- cell types with their own sizes, shapes, densities and expression, in domains of different
composition; - nuclei, some outside the section;
- negative-binomial expression; molecules diffused (a few far), background and negative
controls, quality scores and depth.
- cell types with their own sizes, shapes, densities and expression, in domains of different
- The simulated instrument segments it by nucleus expansion. Its DAPI image is a tiled
OME-TIFF. - The truth (
truth/) imports into the simulated dataset as a Xenium Ranger bundle of the
same run, so any segmentation is scored against it with the comparison workspace. - Labelled simulated: SituCraft marks the bundle simulated in the Data view, the inspector
and the dataset list. Its methods paragraph says that the data were simulated and implies no
instrument. - Read by other tools as Xenium data: the counts are also written as the 10x Genomics
HDF5 matrix (cell_feature_matrix.h5, by SituCraft's own HDF5 writer).cells.zarr.zip
follows XOA 2's layout. spatialdata-io reads a simulated bundle with no warning. - Reproducible: the same parameters and seed give the same bundle, byte for byte, on any
computer. - Validated: goodness-of-fit tests show that the counts, places, displacements, quality
scores, background and cells follow the distributions they are drawn from.
- The tissue:
-
The model of SituCraft's transcript-informed segmentation (wave 3, slice 2), not yet in
the app: a voxel lattice; a Poisson likelihood with per-gene background; a mixture of
expression states with negative-binomial counts; log-normal cell volumes; and a prior from the
nuclei. Its parameters are drawn by exact conditional updates. Each update is checked against
its analytic posterior, and the whole sweep by Geweke's joint distribution test, with the same
result on any number of threads and any processor. The equations are in
research.md §3.2. -
The sampler of SituCraft's transcript-informed segmentation (wave 3, slice 3), not yet in
the app. It moves cells' boundaries voxel by voxel, keeping each cell whole and within a
perimeter bound, and repositions each transcript within its likely displacement. It runs in
parallel with the same result on any number of threads and any processor. It reports each
transcript's most probable cell with its probability. On a simulated tissue it puts 85.9% of
transcripts in their true cells, against 82.5% for the instrument's nucleus expansion, and its
cells overlap the true ones more (median IoU 0.663 against 0.622). Its moves are checked to keep
the posterior exactly (detailed balance on every state of small lattices). -
Transcript-informed segmentation in the app (wave 3, slice 4). Refine from the
transcripts in the Segmentation view redraws the cells from the transcripts as a job and
records the segmentation as an artifact. That artifact keeps each transcript's probability of
its cell, the run's diagnostics, and each layer's outlines when there are several. It is
compared with the instrument's segmentation at once, ready for review in the comparison
workspace.- The view shows whether the run settled (Geweke's diagnostic), how stable its assignments
are, and which cells it is least sure of: few transcripts, uncertain boundaries, no nucleus. - The workspace lists a chosen difference's flagged cells.
- The methods paragraph describes a refined segmentation.
- Remote control adds
refine_segmentation. - On a simulated tissue it puts 85.9% of transcripts in their true cells (the instrument's
expansion: 82.5%), with a median IoU of 0.678 (0.622).
- The view shows whether the run settled (Geweke's diagnostic), how stable its assignments
-
The segmentation studio (wave 3, slice 5). The Segmentation view sets up and runs a
refinement in six steps: Input, Compute, Model, Review, Run, Compare. Each step shows what the
run would do on this bundle and this computer.- What it covers: the whole tissue, its separate sections apart (each with a model of its
own), or chosen regions, typed in µm or the region last framed in the Viewer. Cells about a
region are held as the instrument drew them, so no cell is cut; the rest of the tissue keeps
the instrument's segmentation. The transcripts' quality is a setting (Q20 to start). - Presets: Balanced, Conservative boundary, Flexible morphology, Low memory, ROI pilot and
Expert. Each says what it is for, what it changes and what it risks, with its measured
accuracy on a simulated tissue; every setting says what it does and what it costs. Changing
one but the seed makes the settings Expert. - The ROI pilot refines a region twice with different seeds and reports how often the two
put transcripts in the same cell. On a simulated tissue it matched the whole tissue's run in
its region. - A preflight counts the transcripts modelled and those left out, the cells it starts from,
and what it covers. It estimates memory, disk and time against what the computer has, and
refuses a run that would not fit. On the Lung example its estimates were within 5% of the
memory a whole run took, 10% of the disk and 10% of the time. - Progress, a log and Stop while it runs. A failure (missing cells to start from, a
malformed bundle, memory, disk space, a region without cells) says what went wrong and what
to do, in the studio, the Jobs view and remote control. - Recipes: Save the recipe keeps a refinement's settings as readable JSON. Load a
recipe applies one. - Remote control adds
refinement_preflight;refine_segmentationtakes a preset, regions
or sections, the quality, a second seed and the threads.
- What it covers: the whole tissue, its separate sections apart (each with a model of its
-
situcraft refineruns a refinement in the terminal from a preset or a recipe, writing the
segmentation's files and its recipe to a new folder;--preflightsays what it would need. The
same recipe gives the same files, byte for byte, as the app. The folder imports into the app
(Import a segmentation, SituCraft segmentation). -
Validation against an independent reference (wave 3, slice 6). SituCraft's refinement is
compared with Proseg 3.2.0 (the publication's software) on both 2-FOV bundles and a simulated
tissue, with the comparison workspace's measures; the numbers are kept in
validation/reference/segmentation/and checked weekly.- On the simulated tissue SituCraft puts 84.7% of transcripts in their true cell, against
Proseg's 75.2% and the instrument's 82.2%, with outlines as close to the true ones (median IoU
0.719 against 0.727), and leaves a tenth as many of the cells' transcripts in no cell (0.13%
against 1.42%). - Every tolerance is met on the Breast bundle and the simulated tissue. Three differences on the
Lung bundle are explained in research.md. - The Breast bundle refines in 83 s and 279 MB on a laptop.
- On the simulated tissue SituCraft puts 84.7% of transcripts in their true cell, against
-
The background's calibration (wave 3, slice 7). The refinement's background has two parts:
false decodes, which fall on every codeword alike and which the panel's negative controls
measure, and each gene's ambient RNA. The false decodes are now measured, not guessed.- A benchmark on simulated truth at three background levels and each kind alone: the false
decodes are measured within a sixth of the truth; on the standard tissue twice as much of the
background is found as before, with the same accuracy. Of what SituCraft leaves in no cell,
55–72% truly is background (Proseg: 18%). - The diagnostics report the background: the shares the model's rates account for, false
decodes and ambient RNA, the negative controls that measured them, and the share left in no
cell (diagnostics.json; the studio's Background). - The limit, documented: inside cells, ambient RNA cannot be told from the cells' own
expression, so most of it stays counted in cells (research.md §3.2 and §9). On the real
bundles false decodes are under 0.1% of the transcripts, and results there hardly change.
- A benchmark on simulated truth at three background levels and each kind alone: the false
-
Segmentations on the tissue (wave 3, slice 8). The Viewer draws any of a dataset's
segmentations over its stains, chosen in its Cells layer: the instrument's, nucleus expansions,
refinements, imports. A Viewer opened afresh draws the dataset's default. The legend names the
segmentation drawn and says how it was made.- A refinement's uncertainty, shown: cells filled by their flagged limitations (few
transcripts, uncertain boundary, no nucleus), by their boundary certainty or by their
transcripts' mean probability; transcripts colored by their assignment's probability, close
up. Doubtful cells and transcripts are drawn bright, certain ones dark. - The inspector describes the segmentation's cell: the instrument's cell it came from, its
counts and top genes, and what its method flags. - Show on the tissue on each segmentation in the Segmentation view and the inspector, and on
an expansion's and a refinement's result. - Saved views and links keep the segmentation drawn, its cell and how transcripts are
colored. Remote control:show_tissuetakessegmentation, the new fills andcolor_by;
select_cellselects a...
- A refinement's uncertainty, shown: cells filled by their flagged limitations (few
SituCraft 0.2.0
Wave 2 of the roadmap: segmentations become artifacts to compare,
review and choose between, and to export. The instrument's segmentation is the first; SituCraft's
nucleus expansion the second; other tools' are imported. Any two are compared cell by cell, reviewed
on the tissue, and one promoted with its reason; any is exported in open formats, every file listed
by its SHA-256.
Added
- Remote control (wave 2, slice 1).
situcraft --remote-controllets programs on this
computer (scripts, notebooks, the documentation's screenshots) drive the open window, which
performs each action where you see it; what an action changes is in the history and can be
undone (docs/REMOTE-CONTROL.md).- 20 actions:
- the project: describe it; start or open a project; open bundles and archives by path;
add a dataset; open an example; take a tour; - the tissue: show a view; focus an item; show the tissue (place, zoom, stains, genes,
layers, a cell); select a cell; - saved views: save, open and remove them;
- QC: read the metrics; show a QC map; choose cells; save a filter;
- the record: the methods paragraph; write the project, an archive or the methods to a
file.
- the project: describe it; start or open a project; open bundles and archives by path;
- Finding SituCraft: scripts find it in
remote.json(its address and a token), and
/api/remote/toolslists the actions with their arguments' schemas. - Safety: it answers this computer only, and only the window opened from this run.
Opening paths and writing files also need the token, and a file is never written over an
existing one unless asked.
- 20 actions:
- Segmentations as artifacts (wave 2, slice 2).
- The artifact store (
<data dir>/artifacts): what jobs make and register, each with its
lineage (what it was made from, the job and its spec, the method and its version, the
software), the SHA-256 of every file, what its check found, and its state.- Outputs are written to a staging folder and checked before they become an artifact.
- An artifact is never changed; one whose check finds a fatal problem is kept as invalid, for
review, and never used.
- The instrument's segmentation of each dataset is registered as an artifact by a job, when
the dataset is added or a project reopens (so 0.1.0 projects get theirs). It records:- the bundle's files that make it (cells, boundaries, nuclei, transcript assignments, counts,
masks) by SHA-256, never copied; - the cells each method segmented, and the software that did it;
- the findings of the bundle's validation that bear on it.
- the bundle's files that make it (cells, boundaries, nuclei, transcript assignments, counts,
- Promotion: each dataset's default segmentation is promoted by a recorded decision with its
reason. The instrument's is promoted when it is the only one, and decisions are never removed. - The project tree lists the segmentations, the default marked; the inspector shows a
segmentation's lineage, files, findings and the decision that made it the default.
- The artifact store (
- Jobs that survive the program (wave 2, slice 2).
- Jobs are kept in
<data dir>/jobs. A job SituCraft stopped, or that was running when it
crashed, is shown as interrupted when it starts again, and can be resumed or discarded. - Resuming continues the work from where it stopped: a derived-data build keeps what it
finished. - Closing the window while a job runs asks first; if it is closed anyway, SituCraft keeps
running until the job ends (Ctrl+C stops it, and the job can be resumed). - The Jobs view: what runs and waits, what was interrupted, and what finished. Each job has
its state, progress, times and runs, its whole log and its spec, and Stop, Resume and Discard. - The status bar's job opens the Jobs view.
- Remote control gains
segmentationsandjobs(list, read, stop, resume, discard).
- Jobs are kept in
- Nucleus expansion (wave 2, slice 3). SituCraft's first segmentation of its own.
- The method: each nucleus grows into a cell of its own by up to a chosen distance (5 µm to
start), every pixel going to the nearest nucleus within it, by exact Euclidean distances. It
runs on every core in bands of rows, and gives the same cells however the work is split.
Transcripts belong to the cell holding the pixel they lie in; the counts are of gene
transcripts of quality 20 or more. Bundles without a nucleus mask have their nucleus polygons
drawn instead. - An artifact of its own: its cells, label raster, transcript assignments, counts and
outlines (docs/FORMATS.md), checked before it is recorded (geometry,
assignments, counts, metadata), with every parameter in its lineage. The same dataset and
distance give the same artifact. - Compared with the instrument's segmentation: pixels and transcripts in the same cell, in
another or in only one; cell areas; the assigned fractions; and what differs, described. - The Segmentation view: the dataset's segmentations side by side by their numbers;
Expand the nuclei, run as a job; the comparison. - Remote control gains
expand_nuclei(23 actions).
- The method: each nucleus grows into a cell of its own by up to a chosen distance (5 µm to
- Importing segmentations (wave 2, slice 4). Segmentations made by other tools, imported to
compare with the others:- SpatialData Zarr (format 2 or 3, as spatialdata and spatialdata-io write it): cells from
shapes or a label image, each transcript's cell from points, counts from the table; - Baysor's
segmentation.csvwith its polygons; - GeoJSON polygons, with or without a transcript table (CSV or Parquet);
- Xenium Ranger output bundles of the same run.
- Each is checked against the dataset: its coordinates' units, declared and never guessed (the
check says which units fit when the cells lie outside the image); the transcripts it names,
by id and position; an output bundle's run; its ids. It becomes a segmentation artifact of
SituCraft's own files, kept with the SHA-256 of every file read, and counted as every
segmentation is; one whose check finds a fatal problem is kept as invalid, for review. - Import a segmentation in the Segmentation view; the inspector shows the files imported.
- Remote control gains
import_segmentation(24 actions). - Readers: AnnData in Zarr; Zarr's sharding and text of varying length (as anndata 0.11 and
later write); GeoJSON and WKB polygons; CSV, TSV and Parquet tables.
- SpatialData Zarr (format 2 or 3, as spatialdata and spatialdata-io write it): cells from
- Comparing segmentations (wave 2, slice 5). Any two segmentations of a dataset compared,
cell by cell:- Which cells correspond: a shared nucleus, or at least half of one within the other (or, for
cells without outlines, of their transcripts). Each set of corresponding cells is a
difference: one-to-one, expanded, contracted, split, merged, rearranged, only in one, or
assignment-only. - Measures: each segmentation's cells, cells with a nucleus or several, assigned fraction,
transcripts per cell, areas, cells in pieces, job time and size; between the two, the pixels
that agree, the transcripts that changed cell (gained, lost, moved), the overlap (IoU) and how
far boundaries moved; and by regions of 50 µm. - Transcripts given to the wrong cell: spurious co-expression of gene pairs relative to
nuclei alone, after Jones et al. (2025), and the mutually exclusive co-expression rate of
Hartman and Satija (2024). - Compare two segmentations in the Segmentation view; each comparison is an artifact kept
with the project. Remote control gainscompare_segmentations(25 actions).
- Which cells correspond: a shared nucleus, or at least half of one within the other (or, for
- The comparison workspace (wave 2, slice 6). The Compare view shows a comparison's two
segmentations on the tissue:- side by side with one camera, overlaid in two colours, or in turns (flicker); cells
filled by the class of their difference; a disagreement map by 50 µm region; - the review queue: the differences ranked by reassigned transcripts, contamination (markers
of different lineages in one cell), disagreement or low counts, among the classes and
reassigned transcripts you keep; each opens where it lies, lit in both and described in the
inspector; cell matching lists them all; - decisions: promote one segmentation as the dataset's default, keep one for exploration, or
reject one, each with a reason and the comparison it rests on, appended and never removed; - the measures' header warns when a measure rests on little.
- Comparisons appear in the project tree. Remote control gains
show_comparisonand
decide_segmentation(27 actions).
- side by side with one camera, overlaid in two colours, or in turns (flicker); cells
- Exports (wave 2, slice 7). Export a segmentation, in the Segmentation view, writes any
of a dataset's segmentations into one folder, in the formats chosen:- SpatialData Zarr: the cells as a label image and as polygons, the transcripts as points
with their cells, and the counts as an AnnData table annotating the labels, laid out as the
spatialdata package writes a store, in µm; - AnnData Zarr: the counts with each cell's measures and centroid;
- Parquet and CSV: cells, transcripts with their cells, outlines and counts, in Xenium's
column names; - Matrix Market: the counts as Xenium and Cell Ranger write them;
- GeoJSON: each cell's outline as a polygon naming it;
- Xenium Ranger's inputs: the cells and the bundle's nuclei as label masks on the morphology
image's pixels, checked (their size, cells without pixels, transcripts assigned otherwise than
the mask holds, a dataset without nuclei, a zipped bundle), and theimport-segmentation
command, shown with a but...
- SpatialData Zarr: the cells as a label image and as polygons, the transcripts as points
SituCraft 0.1.0
SituCraft's first release, wave 1 of the roadmap: open a Xenium
output bundle, check it, and see the tissue, its transcripts and its cells at any zoom, with QC
linked to the tissue and a project that reopens exactly. Start with
Getting started: its example datasets download in a click, each with a
guided tour.
Added
- The program and its window (wave 1, slice 1).
- One self-contained program (
situcraft) for macOS, Linux and Windows, x64 and ARM64. - It serves its embedded web app on 127.0.0.1, port 8840 or the next free one up to 8859, and
opens it in a desktop window. - Its ports are clear of the sibling programs' (Proteoscope 8765–8814, CytoWeave 8770–8789,
MaveScape 8820–8839), and a test keeps them so. - A second launch hands its paths to the running SituCraft.
- The host and its security are adapted from MaveScape 0.8.0: a Host-header check against DNS
rebinding, a same-origin API, a Content-Security-Policy and cross-origin isolation. - The content-addressed library is adapted from MaveScape 0.8.0 too, and holds projects.
- One self-contained program (
- Items named on this computer.
- On the command line or through Open a bundle (a path), SituCraft recognizes:
- Xenium output bundles, by their folder, their
.zipor theirexperiment.xenium; - Zarr stores, OME-TIFF images, Parquet and CSV tables, GeoJSON polygons and project archives;
- folders of these, in natural order.
- Xenium output bundles, by their folder, their
- A bundle counts as one item: SituCraft never walks into it, serves it whole or copies it into
the library. - The items are listed under On this computer in the project tree. Reading bundles comes in
a later slice of this wave.
- On the command line or through Open a bundle (a path), SituCraft recognizes:
- The workbench shell.
- A view rail in the order of the work: Data, Viewer, QC, Segmentation, then Cell types,
Spatial, Cohort, Reports and Jobs. Each view says what it will do until it is built. - A start page with recent projects.
- The project tree, an inspector, and a bottom drawer with the project's history and the
session's log. - A status bar, the command palette (⌘K), undo and redo.
- Light and dark themes, and color-vision-friendly colors.
- Without its program, the page says how to start SituCraft: a web page alone cannot read data
where it lies on the computer.
- A view rail in the order of the work: Data, Viewer, QC, Segmentation, then Cell types,
- Every byte of a Xenium bundle (wave 1, slice 2). SituCraft's own readers, in Go's standard
library alone, for everything a Xenium output bundle stores:- Codecs: Zstandard (RFC 8878, with XXH64 checksums), LZ4 blocks, Snappy and Blosc (byte and
bit shuffling). - Parquet: flat schemas, every physical type, plain, dictionary, RLE, delta and
byte-stream-split encodings, data page versions 1 and 2, and Zstd, Snappy, gzip, LZ4 or no
compression. - Zarr: formats 2 and 3, in directories and zips, with Blosc, Zstd, zlib, gzip and LZ4
chunks, C and F order, both byte orders, fill values for chunks never written, CRC-32C and
transposition. - TIFF and BigTIFF: strips and tiles, SubIFD pyramids, deflate, LZW, PackBits and both
predictors, and OME-XML, including multi-file OME-TIFFs (Xenium's four morphology-focus
channels) and z-stacks. - JPEG 2000 (ITU-T T.800, Part 1): JP2 files and raw codestreams; every progression order,
code-block style, tiles and tile-parts, layers, precincts, packed headers and ROI; 5/3 and 9/7
wavelets with both component transforms; decoding at reduced resolution; code blocks decoded
in parallel with the same result on any number of cores. Wired into the TIFF reader for
Xenium's tiles (34712) and whole-slide images' (33003, 33005).
- Codecs: Zstandard (RFC 8878, with XXH64 checksums), LZ4 blocks, Snappy and Blosc (byte and
- Opening and checking a bundle (wave 1, slice 3).
- Opening: a Xenium output bundle opens by its folder, its
experiment.xeniumor its zip, on
the command line or by Open a bundle. SituCraft never writes to it. A zipped bundle's
compressed members are unpacked into the cache once. - What it describes: which software and version wrote the bundle and how far SituCraft reads
it (XOA 2.x supported, others best-effort, said so), and every file by role, required or
optional. - Checks, each finding fatal, a warning or a note, with its files, count, tissue region and
remedy:- files present and readable;
- images against the manifest;
- cells, transcripts, the matrix, cells.zarr and boundaries against one another;
- genes against the panel;
- polygon validity;
- free space for the cache.
- It also recomputes twelve of the run's own recorded metrics from the data.
- The Data view shows each bundle's facts, summary, findings and files.
- Add to project records a bundle with no fatal problem: its place, run identifiers,
summary, findings and a fingerprint of its files. - Reopening a project finds each dataset's bundle again and says whether it is the same,
changed, another run, or not found; Locate… reconnects a bundle that moved, once it is
shown to be the same run.
- Add to project records a bundle with no fatal problem: its place, run identifiers,
--cache-dirsets where derived data go.
- Opening: a Xenium output bundle opens by its folder, its
- Derived data, built once (wave 1, slice 4).
- What is built for each dataset of a project, on one grid of tiles shared with the
morphology image's pyramid:- image tiles of every channel at every zoom level, decoded once from the bundle's JPEG
2000; - a spatial index of the transcripts: each one in the tile holding it, grouped by gene,
with per-gene density grids for every coarser level; - cell and nucleus outlines in tiles, exact at full resolution and simplified for each
coarser level.
- image tiles of every channel at every zoom level, decoded once from the bundle's JPEG
- When: a dataset's derived data are built when it is added to a project, or when a project
reopens and finds it again. Both development bundles take 2 to 4 seconds and 222 MB together. - Built to be trusted and reused:
- entries are named for the contents of the files they come from, so a bundle that moves or
is zipped keeps them and a changed one gets new ones; - an unchanged bundle reopens without being read;
- an interrupted build resumes where it stopped, with the same result to the byte;
- a crash never leaves a half-built entry.
- entries are named for the contents of the files they come from, so a bundle that moves or
- The cache is kept within a size,
--cache-limit(10 GB by default), by removing what was
used least recently; it can be deleted at any time. - Jobs: long work runs in the program as a job with progress, a log and Stop. The page
follows it live and finds it again after a reload. - The Data view shows each dataset's derived data (what is built, the size, a running
build's progress, Build now, why the last build failed if it did) and what the cache
holds; the status bar and inspector show a running build. - Sizes are now shown in decimal units (1 GB is 10^9 bytes), as
--cache-limitreads them.
- What is built for each dataset of a project, on one grid of tiles shared with the
- The tissue viewer (wave 1, slice 5).
- The tissue at any zoom, drawn with WebGL2 from the derived data:
- the morphology channels, each with its own color, contrast window and gamma, every 16-bit
sample exactly as recorded; - transcripts of chosen genes, up to 16 in distinct colors, or all transcripts: as points up
close, and as each gene's density farther out; - cell and nucleus outlines, and cells filled by transcripts, area or segmentation method,
with a legend.
- the morphology channels, each with its own color, contrast window and gamma, every 16-bit
- Finding your way: pan and zoom by dragging, scrolling, pinching or the keyboard; a scale
bar, the position in µm, and a minimap of the whole tissue. - Finding genes by typing their names, with each one's count.
- Clicking a cell shows it in the inspector: its ID, position, areas, segmentation method,
transcripts and top genes. Clicking one of its genes shows that gene. - View the tissue in the Data view opens a dataset once its derived data are built.
- Tiles are served from the cache and kept by the browser, so a view you return to is drawn at
once.
- The tissue at any zoom, drawn with WebGL2 from the derived data:
- QC (wave 1, slice 6). A QC view of whether the run supports analysis, and where it does
not.- Run metrics explained: every metric the run recorded, with what it measures. For 20 of
them, SituCraft's own value from the bundle's data is shown beside it; the rest are shown as
recorded, with why. - QC maps over the tissue:
- per cell: transcripts, genes, area, nucleus area, transcript density, transcripts in the
nucleus, segmentation method and more; - per small region: the share of gene transcripts outside cells, the share below quality 20,
and negative-control density.
- per cell: transcripts, genes, area, nucleus area, transcript density, transcripts in the
- Plots: a histogram, box plots by segmentation method and a scatter plot. Dragging across
one chooses those cells, which the tissue shows (in the QC view and in the Viewer) and the
inspector summarizes. - Filters: conditions on the cells, their effects counted as you edit them. They are saved
as named versions in the project and compared, and never change the data. Each version
records which cells it keeps and is checked to keep them again when the project reopens. - The derived data's format changed (to count the groups of transcripts the maps need), so
datasets build their derived data once more.
- Run metrics explained: every metric the run recorded, with what it measures. For 20 of
- Saved views, the record and examples (wave 1, slice 7).
- Saved views: Save view in the Viewer or the QC view keeps what it shows: the place and
zoom (in µm, so the same tissue on any screen), the channels with their colors and windows,
the genes, the layers and cell fill, the selected cell, and the QC map and filter in use.
Channels and genes are kept by name, so a view survives its derived data being rebuilt. Views
are list...
- Saved views: Save view in the Viewer or the QC view keeps what it shows: the place and