McStas logo McStas - A neutron ray-trace simulation package ILL; PSI; ESS Niels Bohr Institute DTU Physics

McStas

About McStas
 Conditions of use
 Authors/Contacts
 Project funding

Download
 Components
 Other Downloads (share)

Mailing list

Search web/mailinglist

Documentation
 Wiki (GitHub)
 McStas manual
 Publications

Links

Report bugs (GitHub)

Code-repository (GitHub)


McStas: Polygon_ESS_butterfly_image

[ Identification | Description | Examples | Input parameters | Links ]

The Polygon_ESS_butterfly_image Instrument

Photograph the (wavelength, emission-time) region a chopper train leaves open to an ESS_butterfly source, and what the discs it describes then pass.

Identification

  • Site:
  • Author: Gregory Tucker
  • Origin: European Spallation Source ERIC
  • Date: 2026

Description

`Polygon_ESS_butterfly` hands its chopper train to chopper-lib, asks
`chopper_polygon_set_transmit_train` for the exact (inverse velocity, time) region a
neutron could pass through, and refuses to emit anything outside it. This instrument
makes that refusal visible: a monitor in front of the first disc records what was
emitted, in the two coordinates the region is drawn in, and a second monitor beyond the
last disc records what survived them, on the same axes.

The region is a union of convex polygons rather than a grid of bins, so it is not
quantised: the picture below has no resolution to choose and the acceptance it reports
is exact. `Masked_ESS_butterfly_image` is the same instrument over the grid version, and
the two are worth running side by side -- at any affordable bin size the grid is the
looser of the two, and says so by reporting a larger sampled fraction.

The source samples both coordinates uniformly -- `lambda = Lmin + range * rand01()`
and `t = rand01() * tmax_multiplier * ESS_SOURCE_DURATION` -- and carries the spectrum
in the ray weight instead. So the monitors' *N* channel is the region itself, one count
per surviving sample and no brightness in it, while *I* is that region under the
source's own spectrum. Read N to check the region and I to see what an instrument would
get.

Each disc draws a stripe. A disc `path` metres downstream is open around `delay`, so it
passes a ray emitted at `t` with inverse velocity `iv` when `t + path * iv` falls in an
opening: a band of slope `-path` in the image, one per opening per turn, half as thick
in time as `width / (360 nu)`. Two discs at different distances cross their stripes at
an angle, and the transmitted region is the patch they share.

The default train is the pair a real one is built around. The near disc turns a narrow
opening close to the source, so its stripe is thin and nearly flat: it says *when* a
neutron may leave. The far disc turns a wide opening thirty metres out, so its stripe
is thick but steep: it says *which wavelengths* may leave. What comes out is the ribbon
they share -- about 2 AA long and a millisecond thick, with the near disc's shallow
edges along it and the far disc's steep ones cutting it off.

Both delays are set from `lambda_0` and `t_0`, so both stripes pass through that point
by construction and the ribbon is centred on it. Move `t_0` and the pattern slides up
the frame; move `lambda_0` and it slides along the stripes.

mcstas-antlr Polygon_ESS_butterfly_image.instr
./Polygon_ESS_butterfly_image.out -n 2000000 lambda_0=3

Name a parameter even when it is the default one: given none at all, McCode prompts for
every one of them instead of running.

Three files come out of a run:

emission.L_U1     what the source emitted, wavelength across, emission time up
transmitted.L_U1  what the discs then passed, on those same axes
source.json       the region chopper-lib computed -- its polygons' vertices, its area,
the bands it covers and the acceptance -- a few hundred bytes, and
exact rather than sampled onto a mesh

Both monitors are `Monitor_nD` reading the same axis string, so the two images
subtract; and both plot the emission time, not the arrival time, which is what the
USERVAR carried down the beam is for. Without it the second picture would be the first
one sheared by the flight time and the pair could not be compared at all.

The edge of the emitted patch has no staircase on it. That is the difference from
`Masked_ESS_butterfly_image`, whose region is a grid of bins and whose edge is drawn at
whatever `iv_bin` and `t_bin` were set to -- a bin is kept when any part of it can pass,
so a bin wide enough for a stripe to slant across keeps the whole slant. Here the edges
of the patch are the disc edges, at the precision of a double, and `source.json` carries
their coordinates.

`spread` widens them, and only in time. A neutron in a guide travels further than the
straight line, by an amount that turns into `deviation * inverse_velocity` of arrival
time -- so it tilts the stripes' shallow edges apart without moving their steep ones.
`spread = 1e-4` is a realistic guide; `spread = 1e-2` makes it visible.

`noise = 1` turns the region off -- the component keeps an excluded ray when
`rand01() > noise_fraction`, which no draw satisfies at 1 -- so the same instrument
takes the before picture:

./Polygon_ESS_butterfly_image.out -n 2000000 noise=1

`redraw = 1` is the same region spent differently. Instead of absorbing a ray outside it
the source draws the ray again from inside, and multiplies every ray weight by the
fraction of the sampled plane the region covers -- exactly, here, since both areas are
known in closed form rather than counted in cells. The two runs

./Polygon_ESS_butterfly_image.out -n 2000000 do_region=0
./Polygon_ESS_butterfly_image.out -n 2000000 redraw=1

measure the same `transmitted_I` -- that is what the weight factor is for -- while the
second gets there with roughly `1/acceptance` times as many counts in it, because none of
its ncount was spent on rays born where the discs were shut. `emission` shows the
difference plainly: the first fills the frame, the second is the ribbon alone.

`emission` then fills the frame with the sampling the region is applied to, and
`transmitted` shows what the discs pass out of the whole frame, which is the ribbon the
region is a copy of.

The two are not the same measurement, and the second is not a test of the first. The
region asks when a chopper is open on the beam axis; a disc's opening is angular, so a
beam of any width crosses it at a spread of phases, and one that misses the axis by `d`
is early or late by `d / (2 pi (radius - yheight/2) nu)`. Here that is a fair fraction
of the near disc's opening, so `transmitted` is both narrower than `emission` -- rays
off the axis miss a window the region says is open -- and a little wider at each stripe
edge, since the same spread lets others through when the axis is shut. Widen the discs
and the two converge. Neither the region nor the mask is the right tool for asking what
a real disc passes; both are the right tool for deciding what a source need not bother
emitting.

Examples

(Test cases in bold)
  • Test: -y Detector: transmitted_I=1.96867e+08

Input parameters

Parameters in boldface are required; the others are optional.
NameUnitDescriptionDefault
lambda_minAAshortest wavelength the source samples, and the images' left edge1.0
lambda_maxAAlongest wavelength the source samples, and the images' right edge5.0
lambda_0AAthe wavelength the train is set for3.0
t_0sthe emission time the train is set for, at lambda_00.0043
near_pathmhow far the near disc is from the source2.0
near_nuHzits signed rotation frequency14
near_widthdegits single opening, centred on the disc's zero mark6
far_pathmhow far the far disc is; the two paths are the stripe slopes30.0
far_nuHzits signed rotation frequency14
far_widthdegits single opening, centred on the disc's zero mark60
noise1chance of keeping an excluded ray; 1 disables the region0
nL1wavelength bins in both images256
nt1emission time bins in both images256
disc_radiusmouter radius of both discs0.5
slit_heightmradial height of their openings, so the hub is the difference0.1
slit_widthmthe pre-chopper aperture width, otherwise the full opening is always allowed to pass neutrons0.1
spread1extra flight path available to a ray, as a fraction of each disc's own path0.0
do_region1a flag to allow turning off the source shaping, but not the region calculation1
redraw1draw an excluded ray again from inside the region instead of absorbing it0

Links


[ Identification | Description | Examples | Input parameters | Links ]

Generated for mcstas 3.9.2


Last Modified: Tuesday, 06-Oct-2026 21:19:12 CEST
Search website mailinglist archive GitHub repos