Starting the wavelength-LUT workflow on DREAM fails on every batch. The job runs in livedata-timeseries@dream and raises from deep in the cascade:
File ".../ess/reduce/unwrap/lut.py", line 688, in compute_frame_sequence
time_open=ch.time_offset_open(...)
File ".../scippneutron/chopper/disk_chopper.py", line 583, in _source_phase_factor
ValueError: The chopper is out of phase with the source. The frequency must be
an integer multiple of the pulse frequency or vice versa.
pulse_frequency: 7 Hz
frequency: 5 Hz
This is not the dimension-label problem from #1298 (fixed by scipp/scippneutron#728).
The 5 Hz is the overlap chopper. Rotation-speed setpoints as the timeseries service received them on 2026-09-10:
| chopper |
setpoint |
| pulse_shaping_chopper1 |
7 Hz |
| pulse_shaping_chopper2 |
7 Hz |
| band_chopper |
14 Hz |
| overlap_chopper |
5 Hz |
| T0_chopper |
0 Hz, stepped 0 -> 1 -> 1.1 -> 2 -> 3 -> 4 -> 0 between 07:21Z and 08:05Z |
5 Hz cannot be phase-locked to a 14 Hz source, so no single lookup table exists for this configuration. The 7 Hz in the message is not a chopper: compute_frame_sequence uses (1/pulse_period)/(pulse_stride*2) as the rotation frequency, so with pulse_stride=1 only choppers at k*7 Hz or 7/k Hz are accepted.
Reproduced locally: feeding those five setpoints to the real DREAM LUT job gives the identical error; changing only the overlap chopper to 14 Hz makes it succeed. Everything on our side reads the values correctly, so this is an instrument-configuration observation rather than a defect in the reduction.
Worth checking whether DREAM-ChpSy1:Chop-OC-103:Spd_S really is carrying the value we think, and whether the instrument was simply mid-commissioning (the T0 ramping in the same window suggests it was).
Two adjacent things noticed while investigating, neither of them this issue:
- A chopper at 0 Hz is unguarded.
guess_pulse_stride_from_choppers explicitly skips zero-frequency choppers as inactive, but compute_frame_sequence chops with them, and DiskChopper.time_offset_open/_close at 0 Hz return [-inf, inf] and [-nan, inf]. A parked disc is not a chopper and probably should not enter the cascade.
- Rotation direction has only one possible source, and it is unverified. All five
Spd_S values observed above are positive. Whether the PV can be negative is not established here — five positive readings are not evidence that it carries no sign, and the original wording of this bullet claimed more than was measured.
What is established is where the sign would have to come from. The geometry artifact cannot supply it: in geometry-dream-no-shape-2026-09-07.nxs every NXdisk_chopper has rotation_speed and rotation_speed_setpoint as empty NXlog placeholders (value: array([], dtype=float64)), there is no phase field and no dedicated direction field. And it would be overwritten regardless — build_disk_choppers_provider assigns merged['rotation_speed_setpoint'] = latest[name, 'speed'] unconditionally, so the live stream is the sole source of the sign by construction.
The sign is load-bearing: scippneutron reads positive as anticlockwise and negative as clockwise seen from the source, DiskChopper.is_clockwise is frequency < 0, and it selects slit_begin vs slit_end for time_offset_open/_close. Since these groups carry no phase, from_nexus also derives phase = 2*pi*frequency*delay, so the sign flips the phase too. An unsigned speed would not merely mislabel direction, it would change the computed opening times.
So: if any DREAM chopper counter-rotates, the cascade models it as co-rotating. Settling it needs PV metadata (or the chopper group) confirming whether Spd_S is a signed magnitude, or an observation of a chopper known to counter-rotate.
Starting the wavelength-LUT workflow on DREAM fails on every batch. The job runs in
livedata-timeseries@dreamand raises from deep in the cascade:This is not the dimension-label problem from #1298 (fixed by scipp/scippneutron#728).
The 5 Hz is the overlap chopper. Rotation-speed setpoints as the timeseries service received them on 2026-09-10:
5 Hz cannot be phase-locked to a 14 Hz source, so no single lookup table exists for this configuration. The 7 Hz in the message is not a chopper:
compute_frame_sequenceuses(1/pulse_period)/(pulse_stride*2)as the rotation frequency, so withpulse_stride=1only choppers at k*7 Hz or 7/k Hz are accepted.Reproduced locally: feeding those five setpoints to the real DREAM LUT job gives the identical error; changing only the overlap chopper to 14 Hz makes it succeed. Everything on our side reads the values correctly, so this is an instrument-configuration observation rather than a defect in the reduction.
Worth checking whether
DREAM-ChpSy1:Chop-OC-103:Spd_Sreally is carrying the value we think, and whether the instrument was simply mid-commissioning (the T0 ramping in the same window suggests it was).Two adjacent things noticed while investigating, neither of them this issue:
guess_pulse_stride_from_choppersexplicitly skips zero-frequency choppers as inactive, butcompute_frame_sequencechops with them, andDiskChopper.time_offset_open/_closeat 0 Hz return[-inf, inf]and[-nan, inf]. A parked disc is not a chopper and probably should not enter the cascade.Spd_Svalues observed above are positive. Whether the PV can be negative is not established here — five positive readings are not evidence that it carries no sign, and the original wording of this bullet claimed more than was measured.What is established is where the sign would have to come from. The geometry artifact cannot supply it: in
geometry-dream-no-shape-2026-09-07.nxseveryNXdisk_chopperhasrotation_speedandrotation_speed_setpointas empty NXlog placeholders (value: array([], dtype=float64)), there is nophasefield and no dedicated direction field. And it would be overwritten regardless —build_disk_choppers_providerassignsmerged['rotation_speed_setpoint'] = latest[name, 'speed']unconditionally, so the live stream is the sole source of the sign by construction.The sign is load-bearing: scippneutron reads positive as anticlockwise and negative as clockwise seen from the source,
DiskChopper.is_clockwiseisfrequency < 0, and it selectsslit_beginvsslit_endfortime_offset_open/_close. Since these groups carry nophase,from_nexusalso derivesphase = 2*pi*frequency*delay, so the sign flips the phase too. An unsigned speed would not merely mislabel direction, it would change the computed opening times.So: if any DREAM chopper counter-rotates, the cascade models it as co-rotating. Settling it needs PV metadata (or the chopper group) confirming whether
Spd_Sis a signed magnitude, or an observation of a chopper known to counter-rotate.