Skip to content

Call Circadian Workbench

Choose the entrance that matches the job. Think of these as different doors into the same laboratory: every door reaches the same registered scientific methods and returns the same numbers.

I want to... Use
analyse without writing code the desktop
ask one familiar question circadian ask
work in a notebook or another Python package circadian_workbench
connect another local application /api/v1
reach a specialised registered action cw.call(...)

Complete cohort and study management is intentionally reserved for a separately agreed workflow and is not described here.

Use the Python interface reference for every constructor and bound method. Use the complete action reference for every registered action, exact signature, argument, default, unit, and meaning.

The shared figure options describe themes, sizing and explicit per-figure colours.

No code: use the desktop

Open Circadian Workbench, load a recording, then choose the scientific question. The desktop shows only the reviewed non-cohort questions and keeps the original recording read-only.

circadian-workbench-desktop

One question: use the plain-English command

The command accepts a recording followed by a reviewed question or short name. It prints a readable answer unless --json is requested.

circadian --list-questions
circadian ask mouse01.awd "What is the period?"
circadian ask mouse01.awd period --json
circadian ask demo period

Questions are fixed reviewed aliases, not free-text artificial-intelligence interpretation. A misspelling returns close choices instead of guessing which analysis to run. Destructive actions are not available through this command.

A few Python lines: open a recording

The complete recording-to-figure path is:

import circadian_workbench as workbench

recording = workbench.open("mouse.awd")
result = recording.detrend(window_hours=24).compare_periods()
result.plot().save("periods.svg")

This saves .circadian-agent/periods.svg plus exact data, statistics, evidence and a replay producer. It never changes mouse.awd or starts a server. The processed samples flow directly into comparison; plotting uses the completed result. See complete runnable examples for numeric traces, channels and explicit setting overrides.

For a single estimate and a text answer:

import circadian_workbench as cw

recording = cw.open("mouse01.awd")
period = recording.period(method="lomb")

print(period.answer)
period.show()

Settings use scientific names and units. Unspecified settings retain the installed defaults, not those of the last run. Precedence is named method argument, then per-call settings, then settings explicitly bound to the recording, then the installed defaults. None means omitted; zero and False are explicit values. Supplying both settings and its compatibility spelling config is an error.

period = cw.open(
    "mouse01.awd",
    settings={"period_min_hours": 20, "period_max_hours": 28},
).period()

Numeric data: skip file construction

Elapsed hours and values can be passed directly. Circadian Workbench sorts the time grid, preserves missing values, and infers the sampling interval.

trace = cw.trace(hours, values, name="cell 17")
trace.period()
trace.compare_periods(["lomb", "chi_square"])
trace.detrend(method="running mean", window_hours=24)

For an array already extracted by Motion or Auto-Organotypic, the complete comparison-to-figure call is the same:

import circadian_workbench as workbench

recording = workbench.trace(
    hours,
    values,
    settings={"period_min_hours": 20, "period_max_hours": 28},
)
result = recording.compare_periods()
result.plot(theme="classic").save("periods.svg")

Supply your measured hours and values; the numeric example also provides a synthetic fixture. analysis.circadian.trace in Motion and auto_organotypic.rhythm.trace are the actual Workbench function, not copied implementations with separate defaults.

Use the input that describes the experiment:

cw.population(hours, {"cell 1": cell_1, "cell 2": cell_2}).synchrony()
cw.phases([5.8, 6.1, 6.3], period_hours=24).summary(label="regions")
cw.phases({"control": control_phases, "treated": treated_phases}).compare()
cw.channels(hours, {"PER2": per2, "BMAL1": bmal1}).compare()

population means several independent oscillators. channels means several measurements from the same subject.

Common recording analyses

Routine analyses have named calls and share the same settings argument:

recording.profile().series["mean"]
recording.daily_timing().tables["days"]
recording.bouts().tables["events"]
recording.spectrum(kind="power")
recording.wavelet(cycles=8)
recording.detrend("linear").instantaneous_phase()

The Python reference lists the full set, including onset fits, autocorrelation, nonparametric measures, peak alignment, phase angle, re-entrainment, masking, sleep, food anticipation, ultradian rhythms, splitting and channel comparison. is_rhythmic() uses the selected periodogram; rhythmicity(method="ejtk") uses the separate rank/template test on this one series. For correction across several series, use the registered rhythmicity action with all recordings.

For file-writing methods, root selects the output folder. The existing recording.actogram(output=...) spelling remains supported; supply either root or output, not both. Calendar-dependent analyses still require a real recording clock; a numeric trace is not silently assigned a meaningful date.

The result returned by every friendly call

Every call returns Result, so callers do not need a new output convention for each analysis.

Field Meaning
answer concise human-readable answer
data complete analysis result
table table when the result naturally has rows
files files created beneath the chosen output folder
warnings scientific qualifications and refusals
provenance software version, source fingerprint, complete effective_config for configurable actions, changed settings and processing history where applicable
run_record detached record of complete call inputs, effective settings, sources, seeds and software/code identity
script verified replay: checks the recorded environment and inputs, then the scientific result

Use result.show() for a person and result.as_dict() for strict JavaScript Object Notation (JSON). The raw registered-action envelope remains available as result.raw.

result.available_plots lists the supported views. result.plot() constructs a detached figure; figure.data gives its exact displayed table. Choose display options on that figure, for example result.plot(theme="classic", show_grid=False). figure.save("profile.pdf", root="my-figures") returns the actual path and all companion paths. Unsupported plots explain their absence rather than guessing which numeric array to draw. See figure options.

The same result also provides named views without changing those fields:

estimate = recording.period()
period = estimate.measurements["period_hours"]
print(period.value, period.unit, period.status)
comparison = recording.compare_periods()
comparison.tables["estimates"]  # column units are in .attrs["units"]
processed = recording.detrend(window_hours=24)
processed.series["processed"]  # .x, .y, .x_unit, .y_unit, .context

Measurement status distinguishes reported, not_reported (the method returned no value), and refused. An absent field is not added; zero stays zero. Units are None when not declared, not an invented unit. Error fields keep their original names and definitions in .context; they are not automatically converted into confidence intervals. Named series retain missing samples as None, the original clock and processing history. Each access returns a fresh view, so editing a table or its metadata cannot change the scientific result.

Views are mapped explicitly for the single-recording, phase, population, prediction and statistical actions. Full analyze and study_report bundles retain their mixed sub-results in .data; file, settings, catalogue and maintenance actions expose raw data and files rather than fabricated scientific measurements. Actogram layers and wavelet matrices remain in .data; matrices are not reduced to an arbitrary line series.

A package maintainer: use only the public front door

Dependent packages should import the package root and adapt the Result once at their boundary.

import circadian_workbench as cw

def estimate_cell_period(hours, values):
    return cw.trace(hours, values, name="cell").period("lomb").as_dict()

Use from circadian_workbench import statistics for the shared Hedges' g, variance guard, degenerate-data guard and p-value corrections. Modules such as circadian_workbench.analysis and circadian_workbench.period_methods are engine internals, not compatibility contracts.

A specialised action: use call

cw.call is the escape hatch for registered actions that do not need a dedicated convenience method.

result = cw.call(
    "temperature_compensation",
    temperature_points=[
        [20, 24.2, "slice 1"],
        [25, 24.0, "slice 1"],
        [30, 23.9, "slice 1"],
    ],
)

Use cw.ask("period", source="mouse01.awd") when the caller starts from one of the reviewed questions. It never guesses an action.

Another local application: use version 1 web calls

The local service exposes the same registry contract:

GET  /api/v1/actions?action=estimate_period
POST /api/v1/validate
POST /api/v1/call

The request body for validation and execution is:

{
  "action": "estimate_period",
  "params": {
    "recording": {"path": "mouse01.awd"},
    "method": "lomb"
  },
  "root": "my-results"
}

Every response includes api_version: "1" and the registered-action envelope. An output root is a relative folder beneath the service's configured output area; absolute paths and parent-folder escapes are refused. Existing unversioned desktop routes remain compatible.

Errors a caller can act on

Friendly Python calls raise typed readable errors:

  • WorkbenchInputError: change the supplied values, settings or file.
  • UnknownQuestionError: choose one of the suggested reviewed questions.
  • UnknownActionError: inspect the registered actions and correct the name.
  • ActionConfirmationRequired: a destructive machine action needs explicit confirmation.
  • WorkbenchBackendError: the engine failed rather than declining invalid input.

The versioned web interface returns the corresponding error_type in its envelope. Only backend_error means the application itself is broken.

Compatibility promise

Workbench owns circadian scientific methods, argument meanings and defaults. Motion and Auto-Organotypic consume the installed Workbench interface; their existing explicit settings remain their callers' choices, not alternative Workbench defaults. The registry covers the implemented scientific core; the browser's reviewed question list is only a subset. This does not claim every circadian method in the literature has been implemented or independently validated.

Workbench: scientific methods + shared argument definitions + figure builder
    |-- Python, commands and browser adapters
    |-- Motion: selected science inside measurement workflows
    `-- Auto-Organotypic: selected science inside slice workflows

cw.describe("compare_periods") exposes the action's referenced scientific settings with their defaults, units and constraints. cw.discover() lists registered capabilities. Each consumer's argument_group() returns fresh copies of the same definitions; changing help or a definition centrally does not require another independently maintained registry.

The new uniform trace(...) paths use Workbench defaults. Existing Motion measurement calls retain their explicit 2–48-hour search, 0.05 significance threshold, 24-hour linear detrending, 24-observation and three-cycle checks. Existing Auto-Organotypic wrappers retain their 15–40-hour search and 30-minute bins. Use identical explicit settings when comparing those legacy paths.

With fixed input data, settings, seeds and software versions, unrelated earlier calls do not select a different method or figure theme. Saved evidence records a call; it does not decide future defaults. Keep the input and recorded numerical and rendering environment for long-term replay. result.script verifies input fingerprints and the recorded environment before analysis, then checks the scientific result. A saved figure's standalone producer also verifies the complete declared figure. Mismatches are reported, never repaired by silently installing or switching software. Data in an already completed result are not recomputed by plotting; figure options cannot change the scientific answer. Editing the original settings dictionary or a returned view cannot rewrite the stored run record.

These checks establish reproducibility in the recorded environment, not bit-identical raster output across arbitrary operating systems or font engines. Preserve the original data and the recorded package versions/code, numerical execution conditions and fonts. Optional external ReproFig proof checks have their own supported-manifest requirements; a valid saved artifact alone is not a claim that every external proof mode has passed.

The shared architecture continues public application programming interface version 1, introduced in 0.7. The cw.open, cw.trace, cw.population, cw.phases, cw.channels, cw.ask, cw.call, Result, input contracts, public errors and circadian_workbench.statistics addresses remain supported. Migrated consumers require circadian-workbench>=0.8,<0.9; pin the exact installed version and retain the recorded environment for replay.

The action registry remains the machine source of truth. python scripts/update_circadian_references.py --check verifies that generated action documentation matches it.