mantid
mantid copied to clipboard
Unusual results of `SolidAngle`, probably affecting SANS reduction via `Q1D`
We have run into unexpected results by the SolidAngle
algorithm. Concretely for at least some instruments with horizontal tubes such as SANS2D and ZOOM. As you can see from the screenshots of the instrument view below, the computed solid angle has 2 maxima above and below the beam center. This is unexpected, since moving a horizontal cylinder up or down (i.e., perpendicular to the cylinder axis) should not make it appear larger.
Note that the figures are using SolidAngle(Method=GenericShape)
, which internally seems to call the same underlying function (IDetector::solidAngle()
) as Q1D
SANS reduction uses when enabling solid-angle correction. Solid-angle correction is enabled by default in Q1D
.
To reproduce:
- Load a file or IDF (using
LoadEmptyInstrument
). - Call
SolidAngle
with default settings (Method=GenericShape
). - Open the instrument view for the result.
SANS2D:
ZOOM:
LARMOR (looks ok?)
LOKI detector test @ LARMOR (does not show two maxima, but an odd shift we do not understand right now)
This is what LOQ looks like (the correction on the low-angle detector at 4m, in blue below, is negligible and flat, but more pronounced on the high-angle detector at 0.5m). But these are also individually pixelated detectors (a true multiwire gas detector and scintillator detector, respectively), not tube detectors.
This is in release 6.8.0 on W10/x64.
Two differences between SANS2D/ZOOM and LARMOR:
- On SANS2D/ZOOM the tubes are horizontal, on LARMOR they are vertical;
- How the detectors are 'built' in the respective IDF's are different: SANS2D/ZOOM take one approach, LARMOR takes another.
There is something off in the underlying code related to the horizontal and vertical orientation
If I rotate the SANS2D detector tubes and pixels in the IDF (by simply swapping x & y in the detector definitions) I see something sensible.
On another note.
The wide angle bank on Larmor doesn't look right either. The green stripes correspond to the centres of the 8 panels in the detector. I would expect a smooth function across the detector as a whole.
Just checked the direct geometry spectrometers:
- LET, Merlin, IN5, ARCS, CNCS, HYSPEC, Sequoia (all with vertical tubes) - ok
- MARI, IN4 (tubes at an angle, not vertical or horizontal) - funky stripes (like Larmor)
- Panther (vertical tubes) - maxima and minimas (like SANS2D)
- MAPS -
SolidAngle
errors (not sure why...)
Edit: Checked on Mantid 6.8 on Windows 10 using:
LoadEmptyInstrument(InstrumentName='mari', OutputWorkspace='inst')
SolidAngle(InputWorkspace='inst', OutputWorkspace='sa')
Can you add which versions of Mantid these errors are occuring on? We're finding it hard to replicate without that information
~~Loading the IDF for SANS2D directly results in the correct output. LARMOR and ZOOM were still broken. Have any changes been made to the SANS2D IDF recently?~~
This can be disregarded, the LoadEmptyInstrument
algorithm uses the ...Tubes.xml
definition for SANS2D.
LoadEmptyInstrument(InstrumentName='zoom', OutputWorkspace='inst')
SolidAngle(InputWorkspace='inst', OutputWorkspace='sa')
# LoadEmptyInstrument(Filename='/opt/mantidworkbenchnightly/instrument/SANS2D_Definition.xml', OutputWorkspace='aaaa')
LoadEmptyInstrument(Filename='/opt/mantidworkbenchnightly/instrument/SANS2D_Definition_Tubes.xml', OutputWorkspace='aaaa')
SolidAngle(InputWorkspace='aaaa', OutputWorkspace='bbbb')
Hi Caila, The direct load that you used was for the old SANS2D definition with the previous non-tube detector from about 10 years ago. You need to use SANS2D_tubes. This would be the one that is picked up automatically.
I’ve looked at this on windows with 6.7 and on IDAaaS with 6.8. The results are consistent. See below for the IDAaaS 6.8 versions.
Rob
I've just tried SANS2D_tubes in 6.8.0, 6.5.0 and 5.0.0 on W10/x64. The same (incorrect) output from each.
As far as I know the code in question is 10-15 years old. I would be surprised if it was touched recently.
Which is indeed my suspicion, @SimonHeybrock ...
We have managed to replicate the issue as far back as mantidplot v3.9.2. That is a long time for it to go unnoticed.
Hi Sarah, the correction is of the order of a few percent for SANS on the small angle detectors. It will be more for the wide angle. With the radial averaging that we use to produce IvsQ 1D data it is likely to have not produced a significant effect for the majority of measurements. For the wide angle bank on SANS2D I suspect that the other corrections we iterate over will also have helped smoothed things out. Richard Heenan and Sarah Rogers certainly looked at this in the early days of SANS2D although quite when Sarah can't remember. It is entirely possible that it is pre v4. We should look to correct this as we move towards a situation in which we are looking to provide more 2D data. There are a number of other questions that we will need to address in this process as well to do with error handling and binning. The polarisation EPIC may well incorporate quite a few of the issues as we look in further detail at what is required.
@rmdalgliesh Not sure I understand your argument, maybe you could explain in more detail?
the correction is of the order of a few percent for SANS on the small angle detectors. It will be more for the wide angle. With the radial averaging that we use to produce IvsQ 1D data it is likely to have not produced a significant effect for the majority of measurements.
The radial averaging does not change the observation above that the relative weight of pixels close/far from the beam center is altered. Doesn't this somehow affect the balance/weight of low-Q vs. high-Q?
Hi Simon, I'm not suggesting that this is something that should not be corrected as soon as reasonably possible. I'm was trying to point out (badly) that overall for SANS this a small perturbation in comparison to all of the other approximations that we make use of to generate the wavelength averaged data sets and that it is understandable that this has been missed. Given the accuracy to which we calibrate the instruments with standards on a routine basis (to a few %) and the number of assumptions we make about beam uniformity etc. there are also other areas in which we could make a lot of improvements in data correction in addition to this. The main reason we have chosen to not make the reduction more complex most of the time has been down to the need to maintain a reasonable data reduction speed. A SANS2D data set can take up to 1min to reduce to IvsQ in 1D already. This is a particular problem if you are trying to look at time dependent data.
Note that if one does the reduction properly, and use efficiency calibration with an incoherent sample, the solid angle algorithm has no effect (Data/SA)/(Incoherent/SA)=Data/Incoherent
I have a vague memory of there being an issue of solid angle not accounting of the occlusion of a pixel by its neighbors. I do not recall if this is properly accounted for in the various detector types.
It looks like what happens is that in order to calculate the solid angle for a tube, a cylinder is created with the appropriate geometry and then triangulated. The number of angular points used for the triangulation is hard-coded to 10. If the number of points is increased to e.g. 100, then the problem is fixed for SANS2D, ZOOM, and MARI. I'm not suggesting that this parameter is simply changed to 100, but that's where the problem is anyway.
I was puzzled by the fact that the error only appears in ZOOM and SANS2D when the tube / cylinder axis is along the x-direction (horizontal, perpendicular to the beam in Mantid convention) - and if you switch the orientation of the tube axis to be along y the error disappears. Likewise I found that if I switched the orientation of the tube axis in MERLIN from y to x, I see the same minima in the y=0 plane as in ZOOM.
Looking in the code I see it first constructs g_NSLICES
rectangular segments of the cylinder surface with z as the cylinder axis, rotates this into the actual desired axis; divides the rectangle into two triangles and uses an analytic formula to compute the solid angle subtended by the triangle at the sample position. It then keeps only positive solid angles, corresponding to triangles with face normals towards the sample position (so negative solid angles corresponds to segment on the "far" side of the cylinder from the sample position).
Checking the code I could find no error, except for a missing normalisation in computing the rotation axis to rotate the slices from a cylinder axis along z to the desired axis. However, this is not the cause of the bug as the axis for both SANS2D and ZOOM were already normalised in the IDF.
Interestingly, playing around I found two things:
- If you change
g_NSLICES
to9
(less than the default) the minima along the y=0 plane in the ZOOM and SANS2D calculation disappears but MARI, IN4 and LARMOR still have the stripes. - If you keep
g_NSLICES
at10
and change the construction axis within thecylinderSolidAngle
code from the z to the y axis (diff here) then the minima along y=0 also disappears for ZOOM and SANS2D - and MERLIN, LET etc still look ok (e.g. they didn't acquire a minimum along x=0). (Changing the construction axis from z to x does not help - this still gives the minimum along y=0 in ZOOM/SANS2D.)
This suggests that there is some sort of accidental alignment of the faces which we're using to approximate the surface of the cylinder. I eventually found that for g_NSLICES=10
there is an accidental coincidence of x and y values for one step and the next (specifically for angles 72 and 108 and 252 and 288 degrees):
Angle | 0 | 36.0000 | 72.0000 | 108.0000 | 144.0000 | 180.0000 | 216.0000 | 252.0000 | 288.0000 | 324.0000 | 360.0000 |
---|---|---|---|---|---|---|---|---|---|---|---|
cos | 0 | 0.5878 | 0.9511 | 0.9511 | 0.5878 | 0 | -0.5878 | -0.9511 | -0.9511 | -0.5878 | 0 |
sin | 1.0000 | 0.8090 | 0.3090 | -0.3090 | -0.8090 | -1.0000 | -0.8090 | -0.3090 | 0.3090 | 0.8090 | 1.0000 |
Now I think what happens is that for an x-aligned cylinder, under the original code which constructs it as z-aligned and then rotates it, the sin values rotates from the y to the z direction (beam direction), so that the segment appears "end-on" (exactly parallel) to the observer (sample position) so the solid angle for these segments is erroneously calculated to be vanishingly small. This effect only happens around y=0 because otherwise the non-zero y values causes a parallax so the triangles do not appear end-on any more. If, on the other hand we construct it as a y-aligned cylinder and rotate it to be x-aligned, then the sin values stays as the y axis so this segment appears perpendicular to the observer so has the maximum solid angle.
This accidental alignement also happens for g_NSLICES=6, 14, 18
and if this is set the same minumum around y=0 is seen for ZOOM/SANS2D.
The stripes seen in LARMOR is present even when g_NSLICES=100
and I think this is actually intrinsic - the LARMOR detector is defined as sets of flat packs of 8 tubes which means that the tubes in the centre of the pack are very slightly further from the sample position than the tubes on the edges, and so have very slightly smaller solid angle.
I think something similar (due to imperfect definition of the cylindrical geometry) is also behind the stripes seen on MARI. MARI's detector really are supposed to follow a cylindrical arc, and if g_NSLICES=100
then the stripes disappear... so I can only presume it's due to inaccuracies in the segmentation.
Anyway, all of this is to say that I think that the easiest solution is just to change g_NSLICES
to 100
. This does increase the run-time of the algorithm. For LET it increases it from about 0.2 to 0.3s on my laptop... so it might not matter in the grand scheme of things.
Alternatively, you can change g_NSLICES
to 11
and keep the same run time but still solve the issue for SANS2D and ZOOM.
There is logic in SolidAngle
for dealing with tubes analytically instead of triangulating, but only if both x-pixel-size
and y-pixel-size
are defined as instrument parameters.
With thanks to @dehoni, see:
https://www.sciencedirect.com/science/article/pii/S0168900216306714, Section 5.5
https://www.sciencedirect.com/science/article/pii/S0168900214013497?via%3Dihub, Section 4.2
It looks like this is working as it should then @smk78 ? If thats the case perhaps this issue could be closed? What do you think @SimonHeybrock ?
It looks like this is working as it should then @smk78 ? If thats the case perhaps this issue could be closed? What do you think @SimonHeybrock ?
I don't think so @sf1919 unless someone has implemented one of the changes suggested above. It reads as if a change needs to be made somewhere to correct the problem going forward.
I've got a PR that fixes this problem (#36581) by defaulting to 11 slices, but also adds the option to specify how many to use when calling SolidAngle
. It's not ready for review yet because I need to fix a bunch of tests where expected outputs have changed, but the actual implementation is finished. If any of you would like to try the fix and need a package build to do so then let me know.
Thanks @jclarkeSTFC I suspect that we should discuss with @cailafinn what we should be checking for the SANS code. I'm not sure we know enough about the underlying calls in the Q1D calls to make an informed decision on what to test. @cailafinn do you have any thoughts?
I'm not sure we know enough about the underlying calls in the Q1D calls to make an informed decision on what to test.
@rmdalgliesh I still need to do a bit more looking into it as the underlying algorithms predate my time working on mantid. Doing a bit of digging in the code documentation seems to suggest that it's mainly used for wide angle transmission corrections, but it may be used elsewhere.
@cailafinn OK, thanks for checking, we'll need to do some more digging. I think I understand why it might be used there but I would have thought it might come up elsewhere. It may be something we should wrap into the work on the polarisation EPIC. There are few other things we should check as part of that project too.
One option for getting the fix into 6.9 (code-freeze is this Friday) is that I change the default back to 10 slices in the PR, but also all the code is still there to call SolidAngle
with any number of slices. This way no results will change, but the fix is available whenever it's needed. Subsequently we can change the default value to e.g. 11 in a later release.
Hi @jclarkeSTFC this sounds like a sensible plan from the SANS point of view for the time being. We should determine how best to get the testing sorted as soon as possible in the next development cycle.
I'm closing this as it's been fixed by #36581