Skip to content
PointillViz
PointillViz

© 2026 PointillViz

Conditional Contact Odds

by PointillViz community tools

How much one extra neighbour of type B changes the odds a cell is type A, holding every other type’s neighbour count fixed.

Verifiedv1.0.0
  • cell types
  • summary
  • cells
  • matrix
  • table
Conditional contact log-odds against marginal adjacency enrichment for 865 cell-type pairs, showing the pairs whose sign the conditioning reverses
Conditional contact log-odds against marginal adjacency enrichment for 865 cell-type pairs, showing the pairs whose sign the conditioning reversesArtwork from the tool’s bundle

Readme

Answers the question: Which group pairs remain associated after the complete composition of each cell’s neighbourhood is taken into account?

The tool is based on a softmax model that relates each cell’s group identity to the composition of its local neighbourhood. The probability that cell i belongs to group A is modeled as:

Neighbourhoods are defined by an undirected k-nearest-neighbour graph, and N(i,B) is the number of group-B neighbours connected to cell i. The model jointly estimates the group-specific offsets h(A) and the coefficients J(A,B) from the observed group labels. While h(A) accounts for the baseline tendency of a cell to belong to group A, the main quantities of interest are the coefficients J(A,B). They describe the association between groups A and B after the complete neighbourhood composition has been taken into account.

More precisely, while all other neighbour counts remain fixed, one additional B-neighbour changes the log-odds of group A versus group C by J(A,B)−J(C,B).

Map. Using the fitted softmax model above, each cell is colored by logP(z(i)=observed group|N(i)), the log probability assigned to its observed group, given its neighbourhood. Values closer to 0 indicate that the model assigns a high probability to the observed group, while more negative values indicate that the cell’s identity is unusual for its neighbourhood.

Matrix. Both axes list all groups, and each square shows the corresponding fitted coefficient J(A,B). The coefficients are centered to have a mean of zero, J′(A,B)=J(A,B)−mean(J). Positive values indicate stronger-than-average conditional association; negative values indicate weaker association or relative avoidance. The diagonal shows conditional self-association.

Table. Each row represents one group pair. Conditional log-odds is the centered J(A,B) value from the matrix. Marginal log2 obs/exp is the Cell-Type Co-occurrence score calculated on the same neighbour graph, without accounting for other groups. Contacts is the number of observed connections between the groups. Rank shift shows how the pair’s position changes when pairs are ranked by conditional association instead of ordinary co-occurrence. A positive value means that the pair ranks higher by conditional association, while a negative value means that it ranks lower.

Parameters

ParameterTypeDefaultWhat it does
Grouping columnfield categorical_field optional Selects the annotation used to define the groups.
Neighbours (k)k int, 4–30 15 Sets the number of nearest neighbours considered for each cell. Larger values include a broader neighbourhood but increase runtime.
Ridgelam float, 0.01–100 1 Controls how strongly coefficients are pulled toward zero. Higher values give more stable but more strongly smoothed estimates.
Minimum cells per levelmin_cells int, 10–5,000 100 Groups with fewer cells are not shown but remain included in the model.
Level ceilingmax_levels int, 4–100 80 Stops the analysis if the selected annotation contains more groups than this, limiting runtime and matrix size.
Convergencegtol float, 0.000001–0.01 0.0001 Sets when the model stops fitting. Smaller values require closer convergence but may take longer.

Outputs

  • summarywrites a summary
  • cellspaints the spatial view
  • matrixreturns a heatmap
  • tablereturns a table

Tool check

The nine gates this version passed when it was published.

Verified

Passed 9 of 9 gates

  1. bundle pass
  2. manifest pass
  3. entry pass
  4. imports pass, advisory
  5. fixture pass
  6. result pass
  7. determinism pass
  8. edge pass
  9. no_mutation pass
  1. bundle pass

    5 files, 21.3 kB packed and 72.0 kB unpacked, plugin.json at the root.

  2. manifest pass

    conditional-contact-odds 1.0.0 by PointillViz community tools; entry tool.py, outputs summary, cells, matrix, table, 120 s and 4096 MB budget.

  3. entry pass

    tool.py imported in 0.20 s and defines run(ds, params).

  4. imports advisory pass

    2 Python files, importing backend, numpy, potts_core, scipy, time; no network, subprocess, filesystem-write, dynamic-exec or environment use found.

  5. fixture pass

    ran on the 600-cell fixture in 0.48 s of its 120 s budget, returning summary, cells, table, matrix and 4 log lines.

  6. result pass

    returned the declared outputs: summary, cells, table, matrix.

  7. determinism pass

    two runs with identical parameters produced byte-identical results (14.2 kB of JSON).

  8. edge pass

    at the minimum corner (gtol=1e-06, k=4, lam=0.01, max_levels=4, min_cells=10) it refused in words rather than crashing: This annotation has 6 levels and the level ceiling is set to 4. Pick a coarser grouping. (Cost climbs steeply with the level count as well: on a 135k-cell section 73 levels took 26 s at k=15 and 146 levels took 108 s at k=30.) (code: too_many_levels); at the maximum corner (gtol=0.01, k=30, lam=100.0, max_levels=100, min_cells=5000) it refused in words rather than crashing: No pair of levels clears the display gate: 5,000 cells in each level and 100 observed contacts between them. The largest level here has 238 cells and the busiest pair has 2,598 contacts. Lower the minimum, or group the annotation more coarsely. (code: nothing_reportable).

  9. no_mutation pass

    the fixture dataset's 4 files are byte-identical after every run (plugin_cache/, where ds.knn caches, is excluded by design).

Passed every required gate when this version was published. That is a statement about the gates, not about whether the code is safe to run.

Versions

  1. v1.0.0 latest

More tools