Unverified Commit ef936ef3 authored by Gigg, Martyn Anthony's avatar Gigg, Martyn Anthony Committed by GitHub
Browse files

Merge pull request #30320 from mantidproject/26906_d11b_d22b_loader

Loader for D11B and D22B
parents 3d91ea20 7e6fb0c4
......@@ -59,18 +59,18 @@ private:
const std::string &);
void initWorkSpace(NeXus::NXEntry &, const std::string &);
void initWorkSpaceD11B(NeXus::NXEntry &, const std::string &);
void initWorkSpaceD22B(NeXus::NXEntry &, const std::string &);
void initWorkSpaceD33(NeXus::NXEntry &, const std::string &);
void initWorkSpaceD16(NeXus::NXEntry &, const std::string &);
void createEmptyWorkspace(const size_t, const size_t);
size_t loadDataIntoWorkspaceFromMonitors(NeXus::NXEntry &firstEntry,
size_t firstIndex = 0);
size_t loadDataIntoWorkspaceFromVerticalTubes(NeXus::NXInt &,
const std::vector<double> &,
size_t);
size_t loadDataFromMonitors(NeXus::NXEntry &firstEntry,
size_t firstIndex = 0);
size_t loadDataFromTubes(NeXus::NXInt &, const std::vector<double> &, size_t);
void runLoadInstrument();
void moveDetectorsD33(const DetectorPosition &);
void moveDetectorDistance(double, const std::string &);
void moveDetectorDistance(double distance, const std::string &componentName);
void moveDetectorHorizontal(double, const std::string &);
void moveDetectorVertical(double, const std::string &);
Kernel::V3D getComponentPosition(const std::string &componentName);
......
......@@ -147,6 +147,47 @@ void LoadILLSANS::exec() {
const double angle = firstEntry.getFloat(instrumentPath + "/Gamma/value");
placeD16(-angle, distance, "detector");
} else if (m_instrumentName == "D11B") {
initWorkSpaceD11B(firstEntry, instrumentPath);
progress.report("Loading the instrument " + m_instrumentName);
runLoadInstrument();
// we move the parent "detector" component, but since it is at (0,0,0), we
// need to find the distance it has to move and move it to this position
double finalDistance =
firstEntry.getFloat(instrumentPath + "/detector/det_calc") / 1000.;
V3D pos = getComponentPosition("detector_center");
double currentDistance = pos.Z();
moveDetectorDistance(finalDistance - currentDistance, "detector");
// L2 was put at "finalDistance - currentDistance", so we update it to the
// correct value
API::Run &runDetails = m_localWorkspace->mutableRun();
runDetails.addProperty<double>("L2", finalDistance, true);
} else if (m_instrumentName == "D22B") {
initWorkSpaceD22B(firstEntry, instrumentPath);
progress.report("Loading the instrument " + m_instrumentName);
runLoadInstrument();
// first we move the central detector
double distance =
firstEntry.getFloat(instrumentPath + "/Detector/det_calc");
moveDetectorDistance(distance, "detector");
double offset =
firstEntry.getFloat(instrumentPath + "/Detector/dtr_actual");
// TODO : check sign on actual data
moveDetectorHorizontal(-offset / 1000, "detector"); // mm to meter
// then the right one
distance = firstEntry.getFloat(instrumentPath + "/RightDetector/det_calc");
moveDetectorDistance(distance, "detector_right");
offset = firstEntry.getFloat(instrumentPath + "/RightDetector/dtr_actual");
moveDetectorHorizontal(-offset / 1000, "detector"); // mm to meter
} else {
initWorkSpace(firstEntry, instrumentPath);
progress.report("Loading the instrument " + m_instrumentName);
......@@ -186,6 +227,12 @@ void LoadILLSANS::setInstrumentName(const NeXus::NXEntry &firstEntry,
firstEntry, instrumentNamePath + "/name");
const auto inst = std::find(m_supportedInstruments.begin(),
m_supportedInstruments.end(), m_instrumentName);
if ((m_instrumentName == "D11" || m_instrumentName == "D22") &&
firstEntry.containsGroup("data1")) {
m_instrumentName += "B";
}
if (inst == m_supportedInstruments.end()) {
throw std::runtime_error(
"Instrument " + m_instrumentName +
......@@ -258,13 +305,78 @@ void LoadILLSANS::initWorkSpace(NeXus::NXEntry &firstEntry,
loadMetaData(firstEntry, instrumentPath);
size_t nextIndex;
nextIndex = loadDataIntoWorkspaceFromVerticalTubes(data, m_defaultBinning, 0);
nextIndex = loadDataIntoWorkspaceFromMonitors(firstEntry, nextIndex);
nextIndex = loadDataFromTubes(data, m_defaultBinning, 0);
nextIndex = loadDataFromMonitors(firstEntry, nextIndex);
if (data.dim1() == 128) {
m_resMode = "low";
}
}
/**
* @brief LoadILLSANS::initWorkSpaceD11B Load D11B data
* @param firstEntry
* @param instrumentPath
*/
void LoadILLSANS::initWorkSpaceD11B(NeXus::NXEntry &firstEntry,
const std::string &instrumentPath) {
g_log.debug("Fetching data...");
NXData data1 = firstEntry.openNXData("data1");
NXInt dataCenter = data1.openIntData();
dataCenter.load();
NXData data2 = firstEntry.openNXData("data2");
NXInt dataRight = data2.openIntData();
dataRight.load();
NXData data3 = firstEntry.openNXData("data3");
NXInt dataLeft = data3.openIntData();
dataLeft.load();
size_t numberOfHistograms =
static_cast<size_t>(dataCenter.dim0() * dataCenter.dim1() +
dataRight.dim0() * dataRight.dim1() +
dataLeft.dim0() * dataLeft.dim1()) +
N_MONITORS;
createEmptyWorkspace(numberOfHistograms, 1);
loadMetaData(firstEntry, instrumentPath);
size_t nextIndex;
nextIndex = loadDataFromTubes(dataCenter, m_defaultBinning, 0);
nextIndex = loadDataFromTubes(dataLeft, m_defaultBinning, nextIndex);
nextIndex = loadDataFromTubes(dataRight, m_defaultBinning, nextIndex);
nextIndex = loadDataFromMonitors(firstEntry, nextIndex);
}
/**
* @brief LoadILLSANS::initWorkSpaceD22B Load D22B data
* @param firstEntry
* @param instrumentPath
*/
void LoadILLSANS::initWorkSpaceD22B(NeXus::NXEntry &firstEntry,
const std::string &instrumentPath) {
g_log.debug("Fetching data...");
NXData data1 = firstEntry.openNXData("data1");
NXInt dataCenter = data1.openIntData();
dataCenter.load();
NXData data2 = firstEntry.openNXData("data2");
NXInt dataSide = data2.openIntData();
dataSide.load();
size_t numberOfHistograms =
static_cast<size_t>(dataCenter.dim0() * dataCenter.dim1() +
dataSide.dim0() * dataSide.dim1()) +
N_MONITORS;
createEmptyWorkspace(numberOfHistograms, 1);
loadMetaData(firstEntry, instrumentPath);
size_t nextIndex;
nextIndex = loadDataFromTubes(dataCenter, m_defaultBinning, 0);
nextIndex = loadDataFromTubes(dataSide, m_defaultBinning, nextIndex);
nextIndex = loadDataFromMonitors(firstEntry, nextIndex);
}
/**
* Loads data for D33
*/
......@@ -387,22 +499,16 @@ void LoadILLSANS::initWorkSpaceD33(NeXus::NXEntry &firstEntry,
g_log.debug("Loading the data into the workspace...");
size_t nextIndex =
loadDataIntoWorkspaceFromVerticalTubes(dataRear, binningRear, 0);
nextIndex = loadDataIntoWorkspaceFromVerticalTubes(dataRight, binningRight,
nextIndex);
nextIndex =
loadDataIntoWorkspaceFromVerticalTubes(dataLeft, binningLeft, nextIndex);
nextIndex =
loadDataIntoWorkspaceFromVerticalTubes(dataDown, binningDown, nextIndex);
nextIndex =
loadDataIntoWorkspaceFromVerticalTubes(dataUp, binningUp, nextIndex);
nextIndex = loadDataIntoWorkspaceFromMonitors(firstEntry, nextIndex);
size_t nextIndex = loadDataFromTubes(dataRear, binningRear, 0);
nextIndex = loadDataFromTubes(dataRight, binningRight, nextIndex);
nextIndex = loadDataFromTubes(dataLeft, binningLeft, nextIndex);
nextIndex = loadDataFromTubes(dataDown, binningDown, nextIndex);
nextIndex = loadDataFromTubes(dataUp, binningUp, nextIndex);
nextIndex = loadDataFromMonitors(firstEntry, nextIndex);
}
size_t
LoadILLSANS::loadDataIntoWorkspaceFromMonitors(NeXus::NXEntry &firstEntry,
size_t firstIndex) {
size_t LoadILLSANS::loadDataFromMonitors(NeXus::NXEntry &firstEntry,
size_t firstIndex) {
// let's find the monitors; should be monitor1 and monitor2
for (std::vector<NXClassInfo>::const_iterator it =
......@@ -442,9 +548,9 @@ LoadILLSANS::loadDataIntoWorkspaceFromMonitors(NeXus::NXEntry &firstEntry,
return firstIndex;
}
size_t LoadILLSANS::loadDataIntoWorkspaceFromVerticalTubes(
NeXus::NXInt &data, const std::vector<double> &timeBinning,
size_t firstIndex = 0) {
size_t LoadILLSANS::loadDataFromTubes(NeXus::NXInt &data,
const std::vector<double> &timeBinning,
size_t firstIndex = 0) {
// Workaround to get the number of tubes / pixels
int numberOfTubes;
......@@ -458,6 +564,7 @@ size_t LoadILLSANS::loadDataIntoWorkspaceFromVerticalTubes(
numberOfTubes = data.dim0();
histogramWidth = data.dim2();
}
const int numberOfPixelsPerTube = data.dim1();
const HistogramData::BinEdges binEdges(timeBinning);
......@@ -565,11 +672,13 @@ void LoadILLSANS::moveDetectorDistance(double distance,
V3D pos = getComponentPosition(componentName);
mover->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
mover->setProperty("ComponentName", componentName);
mover->setProperty("X", pos.X());
mover->setProperty("Y", pos.Y());
mover->setProperty("Z", distance);
mover->setProperty("RelativePosition", false);
mover->executeAsChildAlg();
g_log.debug() << "Moving component '" << componentName
<< "' to Z = " << distance << '\n';
API::Run &runDetails = m_localWorkspace->mutableRun();
......
......@@ -40,7 +40,9 @@ public:
LoadILLSANSTest() {
ConfigService::Instance().appendDataSearchSubDir("ILL/D11/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D11B/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D22/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D22B/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D33/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D16/");
ConfigService::Instance().setFacility("ILL");
......@@ -99,6 +101,52 @@ public:
checkTimeFormat(outputWS);
}
void test_D11B() {
LoadILLSANS alg;
alg.setChild(true);
alg.initialize();
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", "027194.nxs"))
TS_ASSERT_THROWS_NOTHING(
alg.setPropertyValue("OutputWorkspace", "__unused_for_child"))
TS_ASSERT_THROWS_NOTHING(alg.execute())
TS_ASSERT(alg.isExecuted())
MatrixWorkspace_const_sptr outputWS = alg.getProperty("OutputWorkspace");
TS_ASSERT(outputWS)
TS_ASSERT_EQUALS(outputWS->getNumberHistograms(),
192 * 256 + 2 * 32 * 256 + 2)
TS_ASSERT_EQUALS(outputWS->blocksize(), 1)
TS_ASSERT(outputWS->detectorInfo().isMonitor(192 * 256 + 2 * 32 * 256))
TS_ASSERT(outputWS->detectorInfo().isMonitor(192 * 256 + 2 * 32 * 256 + 1))
TS_ASSERT(outputWS->isHistogramData())
TS_ASSERT(!outputWS->isDistribution())
const auto &instrument = outputWS->getInstrument();
IComponent_const_sptr component =
instrument->getComponentByName("detector_center");
V3D pos = component->getPos();
TS_ASSERT_DELTA(pos.Z(), 8.9274824298, 1E-3)
component = instrument->getComponentByName("detector_left");
pos = component->getPos();
TS_ASSERT_DELTA(pos.Z(), 8.82248, 1E-5)
component = instrument->getComponentByName("detector_right");
pos = component->getPos();
TS_ASSERT_DELTA(pos.Z(), 8.82248, 1E-5)
const auto &xAxis = outputWS->x(0).rawData();
const auto &spec = outputWS->y(3630).rawData();
const auto &err = outputWS->e(3630).rawData();
TS_ASSERT_EQUALS(xAxis.size(), 2)
TS_ASSERT_DELTA(xAxis[0], 6.685, 1E-5)
TS_ASSERT_DELTA(xAxis[1], 7.315, 1E-5)
TS_ASSERT_EQUALS(spec[0], 246)
TS_ASSERT_DELTA(err[0], sqrt(246), 1E-5)
const auto unit = outputWS->getAxis(0)->unit()->unitID();
TS_ASSERT_EQUALS(unit, "Wavelength");
checkTimeFormat(outputWS);
}
void test_D22() {
LoadILLSANS alg;
alg.setChild(true);
......@@ -135,6 +183,47 @@ public:
checkTimeFormat(outputWS);
}
void test_d22B() {
LoadILLSANS alg;
alg.setChild(true);
alg.initialize();
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", "375508.nxs"))
TS_ASSERT_THROWS_NOTHING(
alg.setPropertyValue("OutputWorkspace", "__unused_for_child"))
TS_ASSERT_THROWS_NOTHING(alg.execute())
TS_ASSERT(alg.isExecuted())
MatrixWorkspace_const_sptr outputWS = alg.getProperty("OutputWorkspace");
TS_ASSERT(outputWS)
TS_ASSERT_EQUALS(outputWS->getNumberHistograms(), 128 * 256 + 96 * 256 + 2)
TS_ASSERT_EQUALS(outputWS->blocksize(), 1)
TS_ASSERT(outputWS->detectorInfo().isMonitor(128 * 256 + 96 * 256))
TS_ASSERT(outputWS->detectorInfo().isMonitor(128 * 256 + 96 * 256 + 1))
TS_ASSERT(outputWS->isHistogramData())
TS_ASSERT(!outputWS->isDistribution())
const auto &instrument = outputWS->getInstrument();
// TODO SET CORRECT COORDINATES
IComponent_const_sptr comp = instrument->getComponentByName("detector");
V3D pos = comp->getPos();
TS_ASSERT_DELTA(pos.Z(), 16.874, 1E-5)
comp = instrument->getComponentByName("detector_right");
pos = comp->getPos();
TS_ASSERT_DELTA(pos.Z(), 16.874, 1E-5)
const auto &xAxis = outputWS->x(0).rawData();
const auto &spec = outputWS->y(1280).rawData();
const auto &err = outputWS->e(1280).rawData();
TS_ASSERT_EQUALS(xAxis.size(), 2)
TS_ASSERT_DELTA(xAxis[0], 6.65, 1E-5)
TS_ASSERT_DELTA(xAxis[1], 7.35, 1E-5)
TS_ASSERT_EQUALS(spec[0], 10)
TS_ASSERT_DELTA(err[0], sqrt(10), 1E-5)
const auto unit = outputWS->getAxis(0)->unit()->unitID();
TS_ASSERT_EQUALS(unit, "Wavelength");
checkTimeFormat(outputWS);
}
void test_D16() {
LoadILLSANS alg;
alg.setChild(true);
......
......@@ -17,16 +17,17 @@ class MaskBTP(mantid.api.PythonAlgorithm):
"""
# list of supported instruments
INSTRUMENT_LIST = ['ARCS', 'BIOSANS', 'CG2', 'CG3', 'CHESS', 'CNCS', 'CORELLI', 'D11', 'D11lr', 'D16', 'D22',
'D22lr', 'D33', 'EQ-SANS', 'GPSANS', 'HYSPEC', 'MANDI', 'NOMAD',
'POWGEN', 'REF_M', 'SEQUOIA', 'SNAP', 'SXD', 'TOPAZ', 'WAND', 'WISH']
INSTRUMENT_LIST = ['ARCS', 'BIOSANS', 'CG2', 'CG3', 'CHESS', 'CNCS', 'CORELLI', 'D11', 'D11B', 'D11lr', 'D16',
'D22', 'D22B', 'D22lr', 'D33', 'EQ-SANS', 'GPSANS', 'HYSPEC', 'MANDI', 'NOMAD', 'POWGEN',
'REF_M', 'SEQUOIA', 'SNAP', 'SXD', 'TOPAZ', 'WAND', 'WISH']
instname = None
instrument = None
bankmin = defaultdict(lambda: 1, {'D33': 0, 'SEQUOIA': 23, 'TOPAZ': 10}) # default is one
bankmax = {'ARCS': 115, 'BIOSANS': 88, 'CG2': 48, 'CG3': 88, 'CHESS': 163, 'CNCS': 50, 'CORELLI': 91, 'D11': 1, 'D11lr': 1,
'D16': 1, 'D22': 1, 'D22lr': 1, 'D33': 4, 'EQ-SANS': 48, 'GPSANS': 48, 'HYSPEC': 20, 'MANDI': 59, 'NOMAD': 99,
'POWGEN': 300, 'REF_M': 1, 'SEQUOIA': 150, 'SNAP': 64, 'SXD': 11, 'TOPAZ': 59, 'WAND': 8, 'WISH': 10}
bankmax = {'ARCS': 115, 'BIOSANS': 88, 'CG2': 48, 'CG3': 88, 'CHESS': 163, 'CNCS': 50, 'CORELLI': 91, 'D11': 1,
'D11B': 3, 'D11lr': 1, 'D16': 1, 'D22': 1, 'D22B': 2, 'D22lr': 1, 'D33': 4, 'EQ-SANS': 48, 'GPSANS': 48,
'HYSPEC': 20, 'MANDI': 59, 'NOMAD': 99, 'POWGEN': 300, 'REF_M': 1, 'SEQUOIA': 150, 'SNAP': 64, 'SXD': 11,
'TOPAZ': 59, 'WAND': 8, 'WISH': 10}
def category(self):
""" Mantid required
......@@ -263,6 +264,10 @@ class MaskBTP(mantid.api.PythonAlgorithm):
banks = ["back_detector", "front_detector_top", "front_detector_right", "front_detector_bottom",
"front_detector_left"]
return banks[banknum]
elif self.instname == "D11B":
return ["detector_center", "detector_left", "detector_right"][banknum - 1]
elif self.instname == "D22B":
return ["detector", "detector_right"][banknum - 1]
elif self.instname in ["D11", "D11lr", "D22", "D22lr", "D16"]:
return "detector"
else:
......
......@@ -264,6 +264,21 @@ class MaskBTPTest(unittest.TestCase):
self.assertEquals(len(mask), 9*128)
self.checkConsistentMask(ws, mask)
def test_d22b(self):
ws = LoadEmptyInstrument(InstrumentName="D22B")
mask = MaskBTP(Workspace=ws, Bank="2")
self.assertEquals(len(mask), 256*96)
self.checkConsistentMask(ws, mask)
def test_d11b(self):
ws = LoadEmptyInstrument(InstrumentName="D11B")
mask = MaskBTP(Workspace=ws, Components="detector_right, detector_left")
self.assertEquals(len(mask), 256*32*2)
self.checkConsistentMask(ws, mask)
if __name__ == '__main__':
unittest.main()
e38f1cd76ab0db5a381434b195c55b67
8a4668039bb895376a804cd30162c8c0
......@@ -13,6 +13,7 @@ This loads the nexus files produced by the SANS instruments D11, D22, D33 at the
For D33, it supports both monochromatic and TOF modes.
This loader reads the detector positions from the nexus file and places the detectors accordingly.
For D11 and D22 it supports the nominal and low resolution modes (pixel splitting).
It also supports the newer version for these instruments.
The output is a histogram workspace with unit of wavelength (Angstrom).
It has a single bin for monochromatic, and many bins (ragged) for TOF mode for D33.
......
......@@ -28,6 +28,7 @@ Improvements
from the nexus file.
- With :ref:`SANSILLAutoProcess <algm-SANSILLAutoProcess>`, the output workspace will get its title from the nexus file.
- The Rectangle option for :ref:`SolidAngle <algm-SolidAngle>` is now supported for ILL's D22 and D33.
- Add loader and MaskBTP support for D11B and D22B.
Bugfixes
########
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment