Skip to content

[ESSREDUCE] Project chopper axle onto incident beam for flight distance#630

Open
SimonHeybrock wants to merge 2 commits into
mainfrom
chopper-distance-beam-projection
Open

[ESSREDUCE] Project chopper axle onto incident beam for flight distance#630
SimonHeybrock wants to merge 2 commits into
mainfrom
chopper-distance-beam-projection

Conversation

@SimonHeybrock

@SimonHeybrock SimonHeybrock commented Jun 9, 2026

Copy link
Copy Markdown
Member

Problem

The chopper-cascade wavelength LUT derives each chopper's flight distance from norm(axle_position - source_position). A disk chopper's axle sits above, below, or to the side of the beam by design, so this straight-line distance overestimates the actual beam-path length.

Usually the error is negligible, but for closely-spaced choppers a large transverse axle offset can reorder the cascade. Concrete case on DREAM: the pulse-shaping choppers PSC1 (axle 0.7 m off-beam, 6.145 m downstream) and PSC2 (on-beam, 6.155 m). Under the norm their distances become 6.185 m and 6.155 m, so PSC1 is sorted after PSC2 and applied last — or, when the LUT is evaluated over a narrow distance range around the choppers, never applied at all. The result is that PSC1's phase/delay has no effect on the table.

Fix

Compute the distance as the projection of the axle position onto the incident-beam direction. The neutron crosses the disk where the incident beam intersects it, so this is the correct flight distance. Assuming the incident beam runs along the z axis, the projection is simply the z-component of the offset from the source. This is consistent with the straight-line Ltotal used for detectors and monitors, which lie on the beam where the projection reduces to the norm, so on-axis choppers are unaffected and existing results are unchanged.

Taking the z-component (rather than a source-to-sample dot product) avoids needing a sample position as input, keeping the workflow API unchanged.

Tests

  • Unit test that an off-beam axle projects onto the beam.
  • Regression test that two closely-spaced choppers with one offset axle keep the correct cascade order (the DREAM PSC1/PSC2 situation).

Existing analytical and simulation LUT tests pass unchanged.

The chopper-cascade LUT derived each chopper's flight distance from
`norm(axle_position - source_position)`. A disk chopper's axle sits above
or below the beam by design, so that straight-line distance overestimates
the beam-path length. For closely-spaced choppers a large transverse axle
offset can even reorder the cascade: e.g. DREAM's pulse-shaping choppers
PSC1 (axle 0.7 m off-beam, 6.145 m downstream) and PSC2 (on-beam, 6.155 m)
swap order under the norm (6.185 m vs 6.155 m), so PSC1 is applied last
or, over a narrow distance range, never at all.

Compute the distance as the projection of the axle position onto the
incident-beam direction (source to sample) instead. This matches the
straight-line `Ltotal` used for detectors and monitors, where the
component lies on the beam and the projection reduces to the norm, so
on-axis choppers are unaffected.

This adds `sample_position` as an input to `compute_frame_sequence` and
`simulate_chopper_cascade_using_tof`; workflows built from NeXus already
provide it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the essreduce Issues for essreduce. label Jun 9, 2026
@github-actions github-actions Bot changed the title Project chopper axle onto incident beam for flight distance [ESSREDUCE] Project chopper axle onto incident beam for flight distance Jun 9, 2026
def simulate_chopper_cascade_using_tof(
choppers: DiskChoppers[RunType],
source_position: Position[snx.NXsource, RunType],
sample_position: Position[snx.NXsample, RunType],

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nvaytet Not sure about this, as it would require always having a sample-position. Alternative would be to simply default to beam=Z.

"""
source_position = source_position.to(unit=axle_position.unit)
incident_beam = sample_position.to(unit=axle_position.unit) - source_position
return sc.dot(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had assumed that for balancing purposes, choppers are always installed vertical?

In the case of a tilted guide, I think the dot product is not quite right, because the chopper disk goes vertically from its axle center towards the beam, instead of perpendicular to the beam?
Instead we may need to somehow use the gravity vector?

Image

We also need to make it work for the case where the chopper is neither above nor below the beam, but on the side (as is the case for one of the Dream choppers).

@SimonHeybrock SimonHeybrock Jun 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems to go beyond the immediate fix -- the old solution didn't handle curved guides either, did it? Or do you think it is worse than before?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the old solution didn't handle curved guides either, did it? Or do you think it is worse than before?

No and no. It's just a case I thought about when reading your use of the dot product.
I think we should either fix this additional case, or at least write a comment in the code and/or open an issue?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conclusion from in-person discussion: use the z-component, which also removes the need for having a sample position.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nvaytet Done, ready for review

Project the chopper axle onto the incident beam by taking the
z-component of the offset from the source, assuming the beam runs
along z. This keeps the correct cascade ordering for off-beam axles
without requiring a sample position as workflow input.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@SimonHeybrock SimonHeybrock marked this pull request as ready for review June 10, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

essreduce Issues for essreduce.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants