Skip to content

Publish areaDetector statistics and ROI statistics as a bounded data logic - #25

Draft
coretl wants to merge 2 commits into
split/G3from
split/G4
Draft

coretl wants to merge 2 commits into
split/G3from
split/G4

Conversation

@coretl

@coretl coretl commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Last of six stacked draft PRs, based on #24. It adds the areaDetector statistics and ROI statistics time series as a bounded data logic, and makes the plugins' switches decide which statistics are published.

Supersedes bluesky#1408

What changes

  • Each statistic of an NDStatsIO has one name, that of its scalar signal (for example det-stats-total), whether it is published as a readable, as a stats time series or as an HDF NDAttribute. The highest of these that serves a scan suppresses the others, and the hint of the scalar stays (ADR 0027).
  • The plugin's EnableCallbacks and its compute_statistics/compute_centroid PVs decide which statistics are used. NDPluginBaseIO.get_enabled_params() returns the NDParams switched on; AreaDetector asks each plugin at the first prepare() after stage() through a DetectorSuppressLogic, leaves out of read(), describe() and hints the read signals of the ones that are off, and raises at a later prepare() if a plugin now answers differently.
  • adcore.TimeSeriesDataLogic and ADDataFactory.time_series(plugin) publish the time series of an NDStatsIO or NDROIStatIO as event pages, for a detector that writes no file. The plugin must be in the detector's plugins. EventPageDataProvider(refresh=) asks the plugin to post its arrays before a page is read.
  • ADDataFactory.hdf(ndattribute_sources=) lists plugins whose NDAttributes the HDF writer writes, replacing setup_ndstats_sum.
  • NDROIStatIO is a StandardReadable whose channels are registered as CHILD readables, named <plugin name>-<Name PV> at stage(), with unused channels left out. This changes the datakey of every ROI stat signal.
  • AreaDetector registers every plugin as a CHILD readable; opt one out with set_readable_format(plugin, None).
  • ADDataFactory is built with keywords only, with build replacing writer_cls, writer_suffix and writer_name. ADHDFDataLogic and ADMultipartDataLogic with always_enable=True switch their plugin on at stage().
  • ADHDFDataLogic caps its HDF chunk at 4 MiB (a first guess for GPFS, open to reviewers).
  • adcore.prepare_filter sets enable_filter to False for a single exposure.
  • New NDParam, NDStatsTimeSeriesIO (the TS: sub-plugin of NDStatsIO), NDROIStatTSControl and the ts_* array signals; ADR 0027 is new and ADR 0024 is marked partly superseded.

For Jakub Wlodek: the switches-decide behaviour described in #24 is completed here with the compute_* PVs and the suppression of the read signals that are off.

Breaking changes

setup_ndstats_sum is removed (list the stats plugin in ndattribute_sources, and det-sum becomes det-stats-total); TimeSeriesDataLogic and ADDataFactory.time_series take a plugin rather than making one and no longer write the plugin's EnableCallbacks or ComputeStatistics; a plugin used as a source must be in plugins; NDROIStatIO channel datakeys change. Listed in the CHANGELOG diff.

How to review

ADR 0027 and the how-to docs/how-to/implement-ad-detector.md give the user-facing picture. In code, start with epics/adcore/_io.py (NDParam, get_enabled_params), then epics/adcore/_data_logic.py and _detector.py. The use-case tests under tests/unit_tests/epics/adcore show each publication route.

Position in the stack

Top of the stack. Previous: #24

AI Disclaimer

The code and this description were generated with AI and reviewed/tweaked by the author.

Split cut G4 (bluesky#1367) of detector-rederive (d0872e185): the
StatsTimeSeriesDataLogic, the ADDataFactory.stats_time_series factory
and their tests (UC6, UC7, HDF plus time series, two stats plugins, the
adsim container tests). Together with the PRs below it and the next commit,
the tree is the tip merged with origin/main, less the deleted ADWriterFactory
shims.

Round 3 of the stats naming review folded in: here the plugin snapshot is
taken once at stage and also records NDArrayPort and ROIStat channel names
(the next commit replaces it with a suppress logic asked at the first
prepare, which does not check NDArrayPort), the plugins a trigger logic
holds are not recorded, plugins= are registered as readables, data
factories take plugins by reference, NDROIStatIO is a StandardReadable,
and the writers no longer write EnableCallbacks at prepare.

Assisted-by: Claude Opus 5.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant