Skip to main content

ClockCytePy

A Python port of ClockCyteR.spatial — spatiotemporal and network analysis of circadian rhythms in organotypic suprachiasmatic nucleus (SCN) slices.

Nothing here is new science. ClockCytePy reproduces the published R analysis (Ferrari et al. 2026, Advanced Science, doi 10.1002/advs.75427) in Python, validated number-for-number against the toy dataset that ships with the original package.

It ports two trees: the public ClockCyteR.spatial v0.1.0, and Marco Ferrari's unpublished continuation of it. Neither is a superset of the other, so the port is a merge — see docs/port-plan/private-fork-inventory.md. Because that merge includes work that exists nowhere public, it is published with Marco's agreement and with him as co-author.

Scope

In scope — everything either tree of ClockCyteR.spatial does, starting from per-region intensity tables:

  • outlier removal, LOESS smoothing, polynomial detrending
  • FFT-NLLS rhythm fitting (period, phase, amplitude, RAE, AUC) per region
  • spatial maps and local coherence of every fitted parameter
  • correlation networks, Leiden clustering, node and cluster metrics
  • circular statistics, group comparisons, batch orchestration and reports
  • the whole-SCN Z-profile trace plot, and cross-slice aggregation, both from the unpublished fork

Out of scope — deliberately. Cell segmentation, tracking, drift correction, damping estimates, rhythmicity significance testing, anatomical core/shell priors and hierarchical statistics all live in Auto-Organotypic, upstream or downstream of this package. ClockCytePy is not the place to extend the method; it is the place to reproduce it.

Boundary

  images  ──►  Auto-Organotypic  ──►  per-region CSVs  ──►  ClockCytePy  ──►  per-cell tables
 (upstream: registration,      (the ClockCyteR       (this package)     (downstream:
  outline, traces)              _results format)                        Auto-Organotypic)

ClockCytePy imports nothing from Auto-Organotypic, and Auto-Organotypic imports nothing from ClockCytePy. They meet at a file format, never at a function call.

Install

pip install ClockCytePy                    # analysis only
pip install "ClockCytePy[plots]"           # + the 34 figure types
pip install "ClockCytePy[plots,repro]"     # + each figure carries the table it was drawn from

From a checkout, pip install -e . with the same extras. The import name is clockcytepy.

Needs Python 3.10+. No R at runtime, ever — R appears exactly once, by hand, to bake the validation fixtures.

The repro extra pulls in ReproFig, which draws nothing: it wraps the save, embedding the plotted CSV, the source-file hashes and the package version inside the image so a figure can be audited later. Everything below works without it, and the image is identical either way.

Use

from clockcytepy import (
    Params, Channel, index_files, analyze_project, ranges_calculation, generate_plots,
)

params = Params(
    channels={
        "Ch1": Channel(enabled=False, label="red_channel",      grid_file="Ch1_1_grid_vals.csv"),
        "Ch2": Channel(enabled=True,  label="Syn-Axon-GCaMP6s", grid_file="Ch2_2_grid_vals.csv"),
        "Ch3": Channel(enabled=False, label="Brightfield",      grid_file="Ch3_3_grid_vals.csv"),
    },
    coherence=True, normalize_phase=True, time_res=0.5,
    intervals={"interval1": (0, 72)}, time_window=True, pixel_fct=2.82,
    base_dir=base_dir,
)

files   = index_files(params.base_dir)
results = analyze_project(files, params)
params.plotting.ranges = ranges_calculation(params, results)
generate_plots(results, params)

Anyone holding the R script should recognise that line for line. Output filenames and folder layout match the R package's, so a ClockCytePy _results folder and a ClockCyteR one are interchangeable.

Status

Stages 01-10 complete. 355 tests pass — 150 parity tests against the frozen R fixtures, 81 for the renderers and standalone helpers, 46 for paths the reference run never reaches, and 78 independence checks.

Every quantity the R package reports is reproduced bit-exactly, with one exception — the offset column, which differs on one cell in 1199 and which nothing downstream reads. Full evidence in docs/parity-report.md.

I/O, preprocessing, rhythm fitting exact; cell membership identical
coherence, circular statistics exact
correlation network edge list identical, in order; node metrics exact
clustering cannot be exact — R is not reproducible against itself. See below
orchestration, summaries, plot ranges exact
plot data layer (8a) exact, including the fork's Z-profile path
plot renderers (8b) 30 of 34 types draw — the other four are dead branches in R. 249 of 249 files R writes are reproduced, name for name, across all three configurations; same data, ranges and colours, not pixels
standalone helpers all eight ported, including network_plot's six styles
cross-slice aggregation (10) done, validated to a lower standard by design

The finding worth knowing. cluster_leiden is stochastic and the R package sets no seed, so cluster assignments are not reproducible — two runs of the published code on the identical graph agree on as little as 52% of cells on the smallest slice. ClockCytePy samples the same distribution (it reproduces R's stored partition exactly on all three slices) and exposes a seed argument so a Python run can be made repeatable. It does not change the default, because that would change behaviour.

Four plot types build nothing — in the R source, and therefore here. period_variance, phase_variance and two_phases_rayleigh are empty switch branches that report success and then hand the saver R's base plot function; overlap_hetmap is disabled with if (FALSE). None is in a default list. They are reproduced as skips, with the reason recorded, rather than invented.

Seeing the figures

docs/figures/r-vs-python-figure-parity — a 28-frame review stack, ClockCyteR left and ClockCytePy right, one frame per plot type on slice L_1. preview.png is the first frame.

For Marco

docs/handoff-for-marco.md — the seeding decision, two questions the code could not settle, the attribution gate, and a full list of what was found and deliberately not fixed.

Plan and its corrections: docs/port-plan/00_overview.md, docs/port-plan/CORRECTIONS.md.

Release files for ClockCytePy 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ClockCytePy 0.1.0
File Size Uploaded
clockcytepy-0.1.0.tar.gz 76.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ClockCytePy 0.1.0
File Interpreter ABI Platform
clockcytepy-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 160.7 kB

Release files / clockcytepy-0.1.0.tar.gz

Download URL clockcytepy-0.1.0.tar.gz
Size 76.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c5081c3ed073aec59ccc0a1795a1e9a737eb14fa413391c68310dc836fd36d22
BLAKE2b-256 checksum
How to use checksums
7fca79349e70f6938b25df8ada63f78e9fce1bcdbf1c5c58d7ec7513647feb01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / clockcytepy-0.1.0-py3-none-any.whl

Download URL clockcytepy-0.1.0-py3-none-any.whl
Size 84.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ce9a349ff934b4fd3627b956c769320ba526f67838b51e915b144c0f6a49207
BLAKE2b-256 checksum
How to use checksums
8b41b9575867e164a02aecfe2cc0156d5cae2a9dbb873c59bddf95bf2fefa3e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page