Skip to content

Commit d8a03d5

Browse files
authored
Merge pull request #700 from scipp/multi-pulse-chopper-cascade
Support multiple pulses in chopper cascade
2 parents be535bb + 65ac786 commit d8a03d5

2 files changed

Lines changed: 81 additions & 2 deletions

File tree

src/scippneutron/tof/chopper_cascade.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ def from_source_pulse(
298298
time_max: sc.Variable,
299299
wavelength_min: sc.Variable,
300300
wavelength_max: sc.Variable,
301+
npulses: int = 1,
302+
pulse_period: sc.Variable | None = None,
303+
distance: sc.Variable | None = None,
301304
):
302305
"""
303306
Initialize a frame sequence from min/max time and wavelength of a pulse.
@@ -311,10 +314,22 @@ def from_source_pulse(
311314
[wavelength_min, wavelength_min, wavelength_max, wavelength_max],
312315
dim='vertex',
313316
).to(unit='angstrom')
317+
318+
if npulses > 1:
319+
if pulse_period is None:
320+
raise ValueError('pulse_period must be provided if npulses > 1')
321+
pulse_period = pulse_period.to(unit='s')
322+
subframes = [
323+
Subframe(time=time + i * pulse_period, wavelength=wavelength)
324+
for i in range(npulses)
325+
]
326+
else:
327+
subframes = [Subframe(time=time, wavelength=wavelength)]
328+
314329
frames = [
315330
Frame(
316-
distance=sc.scalar(0, unit='m'),
317-
subframes=[Subframe(time=time, wavelength=wavelength)],
331+
distance=sc.scalar(0.0, unit='m') if distance is None else distance,
332+
subframes=subframes,
318333
)
319334
]
320335
return FrameSequence(frames)

tests/tof/chopper_cascade_test.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,3 +493,67 @@ def test_frame_sequence_getitem_by_distance_selects_correct_chopper(
493493
distance = sc.scalar(3.0, unit='m')
494494
result = frames[distance]
495495
assert_identical(result.bounds(), frames[2].propagate_to(distance).bounds())
496+
497+
498+
def test_frame_sequence_with_multiple_pulses():
499+
pulse_period = sc.scalar(1 / 14, unit='s')
500+
frames = chopper_cascade.FrameSequence.from_source_pulse(
501+
time_min=sc.scalar(0.0, unit='ms'),
502+
time_max=sc.scalar(1.0, unit='ms'),
503+
wavelength_min=sc.scalar(1.0, unit='angstrom'),
504+
wavelength_max=sc.scalar(10.0, unit='angstrom'),
505+
npulses=3,
506+
pulse_period=pulse_period,
507+
)
508+
assert len(frames) == 1
509+
assert len(frames[0].subframes) == 3
510+
expected_time = sc.array(dims=['vertex'], values=[0.0, 1.0, 1.0, 0.0], unit='ms')
511+
expected_wavelength = sc.array(
512+
dims=['vertex'], values=[1.0, 1.0, 10.0, 10.0], unit='angstrom'
513+
)
514+
515+
for i in range(3):
516+
expected_subframe = chopper_cascade.Subframe(
517+
time=expected_time + i * pulse_period.to(unit='ms'),
518+
wavelength=expected_wavelength,
519+
)
520+
assert frames[0].subframes[i] == expected_subframe
521+
522+
523+
def test_chop_frame_sequence_with_multiple_pulses():
524+
pulse_period = sc.scalar(1 / 14, unit='s')
525+
frames = chopper_cascade.FrameSequence.from_source_pulse(
526+
time_min=sc.scalar(0.0, unit='ms'),
527+
time_max=sc.scalar(1.0, unit='ms'),
528+
wavelength_min=sc.scalar(1.0, unit='angstrom'),
529+
wavelength_max=sc.scalar(10.0, unit='angstrom'),
530+
npulses=3,
531+
pulse_period=pulse_period,
532+
)
533+
534+
offset = sc.arange('pulse', 3) * pulse_period
535+
536+
chopper1 = chopper_cascade.Chopper(
537+
distance=sc.scalar(5, unit='m'),
538+
time_open=(sc.array(dims=['slit'], values=[0.002], unit='s') + offset).flatten(
539+
to='slit'
540+
),
541+
time_close=(sc.array(dims=['slit'], values=[0.006], unit='s') + offset).flatten(
542+
to='slit'
543+
),
544+
)
545+
chopper2 = chopper_cascade.Chopper(
546+
distance=sc.scalar(10, unit='m'),
547+
time_open=(
548+
sc.array(dims=['slit'], values=[0.007, 0.009], unit='s') + offset
549+
).flatten(to='slit'),
550+
time_close=(
551+
sc.array(dims=['slit'], values=[0.008, 0.010], unit='s') + offset
552+
).flatten(to='slit'),
553+
)
554+
555+
frames = frames.chop([chopper1, chopper2])
556+
557+
assert len(frames[0].subframes) == 3
558+
assert len(frames[1].subframes) == 3
559+
assert len(frames[2].subframes) == 6 # 3 from each slit of chopper2

0 commit comments

Comments
 (0)