Describe a chopper¶
A Chopper is speed, delay, beam, edges, path and aperture — the disc
described the way the NeXus NXdisk_chopper standard and McStas' CollectorDiskChopper
describe one, so the disc's own numbers go in unconverted.
One opening, centred on the beam¶
The common case, and what every BIFROST disc is:
from chopcal.lib import Chopper
# a single opening 170 degrees across, centred on the beam
disk = Chopper.centred(speed=196.0, delay=3.878e-3, width=170.0, path=6.342)
print(list(disk.edges)) # [-85.0, 85.0]
print(disk.beam) # 0.0: the zero mark is on the beam at `delay`
Chopper.centred writes beam = 0 and edges = [-width/2, +width/2]. That pair is
exactly what the single angle field meant before chopper-lib 4.0.0.
Several openings¶
Give the disc's own slit angles: two per opening, strictly increasing, opening edge first.
# the disk's own numbers, unconverted: two edges per opening, increasing
multi = Chopper(speed=14.0, delay=0.0, beam=12.5,
edges=[0.0, 10.0, 90.0, 105.0, 180.0, 195.0], path=8.53)
print(multi.openings) # [(0.0, 10.0), (90.0, 105.0), (180.0, 195.0)]
print(multi.opening) # 40.0 degrees of opening in total
beam is the angle from the disc's mark to where the beam crosses it, so the openings and
the beam crossing are described separately — there is no conversion to do.
An opening straddling the mark is written past 360, never wrapped:
# an opening straddling the zero mark is written past 360, never wrapped
straddling = Chopper(speed=14.0, edges=[350.0, 370.0], path=1.0)
print(straddling.opening) # 20.0
[350, 370], not [350, 10], so the pairs stay ordered and each width is a difference.
Negative angles are fine too: a single opening astride the mark reads better as
[-85, 85].
Two mistakes that are refused rather than computed
An odd number of edges, and edges that do not strictly increase. chopper-lib checks
neither: it divides the count by two, so an odd list silently drops its last edge, and
it reads unordered edges as negative widths. Both come back as a ValueError here.
After assigning to edges directly, call chopper.validate() — a plain attribute
cannot check itself.
The aperture¶
aperture is how wide the beam is on the disc, in degrees about its spindle.
beam_aperture works it out from the geometry:
from chopcal.lib import beam_aperture
# a 60 x 90 mm beam through a 98.46 mm slit on a 350 mm disk
aperture = beam_aperture(radius=0.350, slit_height=0.09846,
window_width=0.060, window_height=0.090)
print(f'{aperture:.4f} degrees')
slit_height is the radial extent of the opening cut in the disc — McStas DiskChopper's
yheight, which puts the beam centre at radius - yheight/2. The window is the beam
inside it, and is smaller.
The largest angle belongs to the window's inner corners, nearest the spindle, where a given width subtends the most angle. Taking the width over the beam-crossing radius instead misses the height entirely: 11.4° where the real figure is 13.4°.
That is the right width for where anything gets through, which is what Region.transmit
builds. For how likely a neutron is to get through, Region.transmit_weighted wants
beam_aperture(..., at='centre'), the angle at the beam centre. While an edge crosses the
window, the fraction of the beam it has passed grows linearly at the rate the centre sets;
see Weight the region by a source.
Leave aperture at 0 for a pencil beam, which is what every field but this one describes.
A parked disc¶
A disc that is not turning is open or shut for good, and the two mean opposite things: one parked open has no period and so constrains nothing, while one parked shut is a beam stop that empties the answer.
shut = Chopper(speed=0.0, beam=180.0, edges=[-10.0, 10.0], path=20.0)
print(shut.parked_is_open()) # False: a beam stop
An empty result does not say which happened. parked_is_open does. It ignores speed,
because a turning disc stands open once a period whatever its angles are.
Units, at a glance¶
| field | unit |
|---|---|
speed |
Hz, signed — negative turns the disc the other way |
delay |
s |
beam |
degrees from the disc's mark |
edges |
degrees from the disc's mark |
path |
m from the source |
aperture |
degrees |
chopper.quantities gives the same values as scipp variables with those units attached,
if scipp is installed. It is not a dependency and does not become one.