Conversation
…q detector would use incorrect PVs for dataset description
|
Use cases still to support:
|
|
@olliesilvester, @coretl, @shihab-dls and I discussed how the Jungfrau would fit into this. The particularly hard thing on the jungfrau is pedestal mode. This is a mode for taking darks where you set a number of frames The conclusions of how we would do this were:
@coretl will do this refactor |
|
@claude only review |
|
Claude finished @coretl's task in 4m 0s —— View job Code Review CompleteI've reviewed Critical Issues
Architecture & Design
Code Quality
Potential Bugs
Suggestions
All inline comments have been added to specific locations. The refactor looks solid overall - the new composition-based architecture with separate arm/trigger/data logic is much cleaner than the previous inheritance-heavy approach. Tasks:
|
|
@jwlodek I've included the color mode things in here too |
jwlodek
left a comment
There was a problem hiding this comment.
Had a read through everything, overall I like it. It seems to me like a much more intuitive way of setting up customized detector setups than complex inheritance. Mentioned a few minor things in suggestions.
It could exist already, but is there a way to clear out the logics configured for a detector? I'd be interested to see if we could have a few sets of logics that we apply for different plans.
I will try and give it a test with some real hardware by the end of this week.
There isn't at the moment, the idea being that the detector subclasses with |
jwlodek
left a comment
There was a problem hiding this comment.
I had a chance to try this out today with a new detector I'm integrating. For the most part it was pretty straightforward. One thing I ran into is that it seems like I needed to prime the HDF plugin before an acquisition - the initial acquisition produced a chunk_shape of [1, 0, 0] which tiled refused to ingest. Looking through the code I don't think that should be the case, so I'll double check tomorrow - I'm writing the AD driver as I go so perhaps a bug there, didn't have a chance to check for sure.
While looking at the shape/chunk_shape code though, I noticed that we also need to handle plugins as shape sources, (and the CB plugin should be used for the ContAcqDetector), and I started to think about how to potentially handle non-color higher dimensional detectors like one that is on my plate to work on in the coming months.
| prefix: str, | ||
| path_provider: PathProvider, | ||
| writer_suffix: str | None, | ||
| driver: ADBaseIO, |
There was a problem hiding this comment.
| driver: ADBaseIO, | |
| array_io: NDArrayBaseIO, |
There was a problem hiding this comment.
We need to allow passing plugins here to use them as the source of the dataset size, name is just a suggestion, It can stay driver too.
There was a problem hiding this comment.
My expectation for those that use a plugin as a source of dataset size is that people would set writer=None, then construct the NDArrayDescription and writer themselves to add it on afterwards, otherwise this function is getting unwieldy
| description = NDArrayDescription( | ||
| shape_signals=[driver.array_size_y, driver.array_size_x], | ||
| data_type_signal=driver.data_type, | ||
| color_mode_signal=driver.color_mode, |
There was a problem hiding this comment.
| description = NDArrayDescription( | |
| shape_signals=[driver.array_size_y, driver.array_size_x], | |
| data_type_signal=driver.data_type, | |
| color_mode_signal=driver.color_mode, | |
| if isinstance(array_io, ADBaseIO): | |
| shape_signals = [array_io.array_size_y, array_io.array_size_y] | |
| else: | |
| shape_signals = [array_io.array_size0, array_io.array_size1, array_io.array_size2] | |
| description = NDArrayDescription( | |
| shape_signals=shape_signals, | |
| data_type_signal=array_io.data_type, | |
| color_mode_signal=array_io.color_mode, |
See above. We need to pass dims 0-2, since depending on whether the image is color or not, X/Y will be 0 and 1 or 1 and 2.
There was a problem hiding this comment.
I actually also have a case that I'm working on that is a detector that produces three dimensional monochrome data: essentially it's a 264x264 array, with each "pixel" actually being a spectrum: https://pndetector.de/products-applications/product/the-pncdd-color-x-ray-camera-cxc/ (so we end up with 1024 x 264 x 264 data)
As such I wonder if this shape describing logic should remain in a provider / describer style callable class that takes an NDArrayBaseIO as an argument at init returns the dataset description to allow for easy overrides - hard-coding the x/y signals seems a bit inflexible for such cases.
There was a problem hiding this comment.
Hmm, that's interesting, is there an array_size_z PV for the third dimension?
There was a problem hiding this comment.
Yup: https://github.com/areaDetector/ADCore/blob/72593ed7ed6407c58ae387c3e58cfa8a33217b54/ADApp/Db/NDArrayBase.template#L539-L544
We could put that in, then remove those from the shape that are zero?
Hmm, that shouldn't be the case, for all the detectors I've seen they populate
I've added a commit that looks at That just leaves things like ROI plugins, which I hoped people would instantiate by creating an ophyd-async/tests/unit_tests/epics/adcore/test_use_cases.py Lines 414 to 425 in 5fd906c Would this handle all your use cases? |
|
@jwlodek I've corrected the naming of the parameter in the |
678e3cc to
c519d9c
Compare
Summary
This PR is a major architectural refactor of
StandardDetectorthat replaces the inheritance-heavy design with a composition-based approach. Instead of usingDetectorControllerandDetectorWriter, it introduces three separate logic classes (DetectorTriggerLogic,DetectorArmLogic, andDetectorDataLogic) that can be mixed and matched to build detectors with different behaviors.The refactor also renames trigger types for clarity:
EDGE_TRIGGER→EXTERNAL_EDGECONSTANT_GATE/VARIABLE_GATE→EXTERNAL_LEVELThis change makes it significantly easier to support advanced use cases like:
Fixes #1006, fixes #948, fixes #991, fixes #1037, fixes #776, fixes #983, fixes #454
Implemented on top of #1158
Breaking Changes
All detector implementations need updating:
Detector Controller → Trigger Logic + Arm Logic
Detector Writer → Data Logic
TriggerInfo Updates
Complete SimDetector Example
Reading Stats Without Files
Multiple Data Streams