Unverified Commit 46269c82 authored by Dominik Arominski's avatar Dominik Arominski Committed by GitHub
Browse files

Loading scan mode data for IN5, PANTHER, SHARP (#30783)

* Added support for IN5/PANTHER scan-mode to LoadILLDiffraction

* Added checks for the new ILL data scan type: NXill

* Added discriminator for IN5/PANTHER scan data to LoadILLTOF

* Added confidence tests for D1B, D7, and IN5 scan-mode

* Conforming with Clang formatting

* Added release notes

* Updated documentation with new IN5/PANTHER processing

* Fixed issue with monitor being last spectrum in IN5/PANTHER

* Added unit test for IN5/PANTHER scan data

* Changed confidence for IN5 scan mode, added numor for D16 LoadILLTest

* Avoid implicitely losing precision of long int

* Corrected doc-example for IN5 omega scan

* Ei log is now overriding to accommodate PANTHER property structure

* Added PANTHER scan test and reorganised IN5 tests

* Ensuring Clang formatting

* Added info about processing omega-scan mode by a separate loader

* Added support for SHARP data scan mode

* Updated docs with SHARP support information

* Added missing blank line at the end of bullet list

* Fixed empty line at the end of list

* Added a blank line at the end of empty bullet list

* Replaced checking individual spectrometer inst with isSpectrometer

* Added SHARP to doc information

* Added PANTHER omega scan loading test

* Added loading test for SHARP omega scan

* Added scan variable name to sample logs
parent 0e7329ee
......@@ -109,6 +109,7 @@ private:
API::MatrixWorkspace_sptr m_outWorkspace; ///< output workspace
bool m_useCalibratedData{false}; ///< whether to use the calibrated data in
///< the nexus (D2B only)
bool m_isSpectrometer{false};
};
} // namespace DataHandling
......
......@@ -184,9 +184,7 @@ void LoadHelper::recurseAndAddNexusFieldsToWsRun(NXhandle nxfileID, API::Run &ru
NXstatus getinfo_status;
if ((opengroup_status = NXopengroup(nxfileID, nxname, nxclass)) == NX_OK) {
if (std::string(nxclass) != "ILL_data_scan_vars") {
if (std::string(nxclass) != "ILL_data_scan_vars" && std::string(nxclass) != "NXill_data_scan_vars") {
// Go down to one level, if the group is known to nexus
std::string p_nxname(nxname); // current names can be useful for next level
std::string p_nxclass(nxclass);
......
......@@ -65,7 +65,10 @@ int LoadILLDiffraction::confidence(NexusDescriptor &descriptor) const {
// fields existent only at the ILL Diffraction
// the second one is to recognize D1B
if (descriptor.pathExists("/entry0/instrument/2theta") || descriptor.pathExists("/entry0/instrument/Canne")) {
// the third one is to recognize IN5/PANTHER/SHARP scan mode
if (descriptor.pathExists("/entry0/instrument/2theta") || descriptor.pathExists("/entry0/instrument/Canne") ||
(descriptor.pathExists("/entry0/data_scan") && descriptor.pathExists("/entry0/experiment_identifier") &&
descriptor.pathExists("/entry0/instrument/Detector"))) {
return 80;
} else {
return 0;
......@@ -87,8 +90,8 @@ const std::string LoadILLDiffraction::summary() const { return "Loads ILL diffra
/**
* Constructor
*/
LoadILLDiffraction::LoadILLDiffraction() : IFileLoader<NexusDescriptor>(), m_instNames({"D20", "D2B", "D1B"}) {}
LoadILLDiffraction::LoadILLDiffraction()
: IFileLoader<NexusDescriptor>(), m_instNames({"D20", "D2B", "D1B", "IN5", "PANTHER", "SHARP"}) {}
/**
* Initialize the algorithm's properties.
*/
......@@ -156,6 +159,9 @@ void LoadILLDiffraction::loadDataScan() {
NXRoot dataRoot(m_filename);
NXEntry firstEntry = dataRoot.openFirstEntry();
m_instName = firstEntry.getString("instrument/name");
if (m_instName == "IN5" || m_instName == "PANTHER" || m_instName == "SHARP") {
m_isSpectrometer = true;
}
m_startTime = DateAndTime(m_loadHelper.dateTimeInIsoFormat(firstEntry.getString("start_time")));
const std::string dataType = getPropertyValue("DataType");
const bool hasCalibratedData = containsCalibratedData(m_filename);
......@@ -186,7 +192,7 @@ void LoadILLDiffraction::loadDataScan() {
axis.load();
// read the starting two theta
double twoThetaValue;
double twoThetaValue = 0;
if (m_instName == "D1B") {
if (getPointerToProperty("TwoThetaOffset")->isDefault()) {
g_log.notice("A 2theta offset angle is necessary for D1B data.");
......@@ -194,7 +200,7 @@ void LoadILLDiffraction::loadDataScan() {
} else {
twoThetaValue = getProperty("TwoThetaOffset");
}
} else {
} else if (!m_isSpectrometer) {
std::string twoThetaPath = "instrument/2theta/value";
NXFloat twoTheta0 = firstEntry.openNXFloat(twoThetaPath);
twoTheta0.load();
......@@ -496,18 +502,26 @@ void LoadILLDiffraction::fillStaticInstrumentScan(const NXUInt &data, const NXDo
const std::vector<double> axis = getAxis(scan);
const std::vector<double> monitor = getMonitor(scan);
size_t monitorIndex = 0;
size_t startIndex = NUMBER_MONITORS;
if (m_isSpectrometer) {
startIndex = 0;
monitorIndex = m_numberDetectorsActual;
}
// Assign monitor counts
m_outWorkspace->mutableX(0) = axis;
m_outWorkspace->mutableY(0) = monitor;
std::transform(monitor.begin(), monitor.end(), m_outWorkspace->mutableE(0).begin(), [](double e) { return sqrt(e); });
m_outWorkspace->mutableX(monitorIndex) = axis;
m_outWorkspace->mutableY(monitorIndex) = monitor;
std::transform(monitor.begin(), monitor.end(), m_outWorkspace->mutableE(monitorIndex).begin(),
[](double e) { return sqrt(e); });
// Assign detector counts
PARALLEL_FOR_IF(Kernel::threadSafe(*m_outWorkspace))
for (int i = NUMBER_MONITORS; i < static_cast<int>(m_numberDetectorsActual + NUMBER_MONITORS); ++i) {
for (int i = static_cast<int>(startIndex); i < static_cast<int>(m_numberDetectorsActual + startIndex); ++i) {
auto &spectrum = m_outWorkspace->mutableY(i);
auto &errors = m_outWorkspace->mutableE(i);
const auto tubeNumber = (i - NUMBER_MONITORS) / m_sizeDim2;
auto pixelInTubeNumber = (i - NUMBER_MONITORS) % m_sizeDim2;
const auto tubeNumber = (i - startIndex) / m_sizeDim2;
auto pixelInTubeNumber = (i - startIndex) % m_sizeDim2;
if (m_instName == "D2B" && !m_useCalibratedData && tubeNumber % 2 == 1) {
pixelInTubeNumber = D2B_NUMBER_PIXELS_IN_TUBES - 1 - pixelInTubeNumber;
}
......@@ -521,9 +535,10 @@ void LoadILLDiffraction::fillStaticInstrumentScan(const NXUInt &data, const NXDo
// Link the instrument
loadStaticInstrument();
// Move to the starting 2theta
moveTwoThetaZero(twoTheta0);
if (!m_isSpectrometer) {
// Move to the starting 2theta
moveTwoThetaZero(twoTheta0);
}
}
/**
......@@ -565,6 +580,9 @@ void LoadILLDiffraction::fillDataScanMetaData(const NXDouble &scan) {
const std::string scanVarName = boost::algorithm::to_lower_copy(m_scanVar[i].name);
const std::string scanVarProp = boost::algorithm::to_lower_copy(m_scanVar[i].property);
const std::string propName = scanVarName + "." + scanVarProp;
if (m_scanVar[i].scanned == 1) {
mutableRun.addProperty("ScanVar", propName, true);
}
auto property = std::make_unique<TimeSeriesProperty<double>>(propName);
for (size_t j = 0; j < m_numberScanPoints; ++j) {
property->addValue(absoluteTimes[j], scan(static_cast<int>(i), static_cast<int>(j)));
......@@ -608,14 +626,14 @@ std::vector<double> LoadILLDiffraction::getScannedVaribleByPropertyName(const NX
* Returns the monitor spectrum
* @param scan : scan data
* @return monitor spectrum
* @throw std::runtime_error If there are no entries named Monitor1 or Monitor_1
* in the NeXus file
* @throw std::runtime_error If there are no entries named Monitor1 or
* Monitor_1, or monitor1 in the NeXus file
*/
std::vector<double> LoadILLDiffraction::getMonitor(const NXDouble &scan) const {
std::vector<double> monitor = {0.};
for (size_t i = 0; i < m_scanVar.size(); ++i) {
if ((m_scanVar[i].name == "Monitor1") || (m_scanVar[i].name == "Monitor_1")) {
if ((m_scanVar[i].name == "Monitor1") || (m_scanVar[i].name == "Monitor_1") || (m_scanVar[i].name == "monitor1")) {
monitor.assign(scan() + m_numberScanPoints * i, scan() + m_numberScanPoints * (i + 1));
return monitor;
}
......@@ -822,9 +840,8 @@ void LoadILLDiffraction::setSampleLogs() {
}
double lambda = run.getLogAsSingleValue("wavelength");
double eFixed = WAVE_TO_E / (lambda * lambda);
run.addLogData(new PropertyWithValue<double>("Ei", eFixed));
run.addLogData(std::make_unique<Kernel::PropertyWithValue<double>>(PropertyWithValue<double>("Ei", eFixed)), true);
run.addLogData(new PropertyWithValue<size_t>("NumberOfDetectors", m_numberDetectorsActual));
if (m_pixelHeight != 0.) {
run.addLogData(new PropertyWithValue<double>("PixelHeight", m_pixelHeight));
}
......
......@@ -48,6 +48,7 @@ int LoadILLTOF2::confidence(Kernel::NexusDescriptor &descriptor) const {
// LoadILLIndirect
&& !descriptor.pathExists("/entry0/instrument/VirtualChopper") // This one is for
// LoadILLReflectometry
&& !descriptor.pathExists("/entry0/data_scan") // This one is handled by LoadILLDiffraction
) {
return 80;
} else {
......
......@@ -36,6 +36,9 @@ public:
ConfigService::Instance().appendDataSearchSubDir("ILL/D20/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D2B/");
ConfigService::Instance().appendDataSearchSubDir("ILL/D1B/");
ConfigService::Instance().appendDataSearchSubDir("ILL/IN5/");
ConfigService::Instance().appendDataSearchSubDir("ILL/PANTHER/");
ConfigService::Instance().appendDataSearchSubDir("ILL/SHARP/");
}
void setUp() override {
......@@ -219,11 +222,15 @@ public:
}
const auto &run = outputWS->run();
TS_ASSERT(run.hasProperty("ScanType"))
TS_ASSERT(run.hasProperty("ScanVar"))
TS_ASSERT(outputWS->run().hasProperty("omega.position"))
TS_ASSERT(outputWS->run().hasProperty("detector.totalcount"))
TS_ASSERT(outputWS->run().hasProperty("acquisitionspy.time"))
TS_ASSERT(outputWS->run().hasProperty("samplesettings.sampletemp"))
TS_ASSERT(outputWS->run().hasProperty("magneticfield.field"))
const auto scanVar = run.getLogData("ScanVar");
TS_ASSERT_EQUALS(scanVar->value(), "omega.position")
const auto omega = run.getLogData("omega.position");
TS_ASSERT_EQUALS(omega->size(), 21)
const double steps = run.getLogAsSingleValue("ScanSteps");
......@@ -457,6 +464,9 @@ public:
TS_ASSERT(run.hasProperty("ScanType"));
const auto type = run.getLogData("ScanType");
TS_ASSERT_EQUALS(type->value(), "DetectorScan");
TS_ASSERT(run.hasProperty("ScanVar"));
const auto scanVar = run.getLogData("ScanVar");
TS_ASSERT_EQUALS(scanVar->value(), "2theta.position");
checkTimeFormat(outputWS);
}
......@@ -493,6 +503,192 @@ public:
checkTimeFormat(outputWS);
}
void test_IN5_omega_scan() {
// Tests the omega-scan case for IN5
LoadILLDiffraction alg;
// Don't put output in ADS by default
alg.setChild(true);
TS_ASSERT_THROWS_NOTHING(alg.initialize())
TS_ASSERT(alg.isInitialized())
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", "199857.nxs"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("OutputWorkspace", "_unused_for_child"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("DataType", "Raw"))
TS_ASSERT_THROWS_NOTHING(alg.execute())
TS_ASSERT(alg.isExecuted())
MatrixWorkspace_sptr outputWS = alg.getProperty("OutputWorkspace");
TS_ASSERT(outputWS)
TS_ASSERT_EQUALS(outputWS->getNumberHistograms(), 98305)
TS_ASSERT_EQUALS(outputWS->blocksize(), 17)
TS_ASSERT(outputWS->detectorInfo().isMonitor(98304))
TS_ASSERT(!outputWS->isHistogramData())
TS_ASSERT(!outputWS->isDistribution())
TS_ASSERT_DELTA(outputWS->x(0)[0], 276.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(0)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(0)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->x(65)[15], 279.75, 0.01)
TS_ASSERT_DELTA(outputWS->y(65)[15], 1.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(65)[15], 1.00, 0.01)
TS_ASSERT_DELTA(outputWS->x(98304)[0], 276.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(98304)[0], 2471.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(98304)[0], 49.71, 0.01)
TS_ASSERT_DELTA(outputWS->x(98304)[16], 280.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(98304)[16], 513.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(98304)[16], 22.65, 0.01)
const auto &run = outputWS->run();
TS_ASSERT(run.hasProperty("AcquisitionSpy.Time"))
TS_ASSERT(run.hasProperty("SampleSettings.SampleTemp"))
TS_ASSERT(run.hasProperty("ScanType"))
TS_ASSERT(run.hasProperty("ScanVar"))
TS_ASSERT(run.hasProperty("ResolutionMode"))
TS_ASSERT(run.hasProperty("Ei"))
const auto spy = run.getLogData("AcquisitionSpy.Time");
const auto sample = run.getLogData("SampleSettings.SampleTemp");
const auto scanType = run.getLogData("ScanType");
const auto scanVar = run.getLogData("ScanVar");
const auto ei = run.getLogAsSingleValue("wavelength");
TS_ASSERT_EQUALS(scanType->value(), "OtherScan")
TS_ASSERT_EQUALS(scanVar->value(), "samplerotation.position")
TS_ASSERT_EQUALS(spy->size(), 17)
TS_ASSERT_EQUALS(sample->size(), 17)
TS_ASSERT_DELTA(ei, 4.80, 0.01)
TS_ASSERT_EQUALS(outputWS->run().getProperty("Detector.calibration_file")->value(), "none")
checkTimeFormat(outputWS);
}
void test_PANTHER_omega_scan() {
// Tests the omega-scan case for PANTHER
LoadILLDiffraction alg;
// Don't put output in ADS by default
alg.setChild(true);
TS_ASSERT_THROWS_NOTHING(alg.initialize())
TS_ASSERT(alg.isInitialized())
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", "010578.nxs"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("OutputWorkspace", "_unused_for_child"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("DataType", "Raw"))
TS_ASSERT_THROWS_NOTHING(alg.execute())
TS_ASSERT(alg.isExecuted())
MatrixWorkspace_sptr outputWS = alg.getProperty("OutputWorkspace");
TS_ASSERT(outputWS)
TS_ASSERT_EQUALS(outputWS->getNumberHistograms(), 73729)
TS_ASSERT_EQUALS(outputWS->blocksize(), 16)
TS_ASSERT(outputWS->detectorInfo().isMonitor(73728))
TS_ASSERT(!outputWS->isHistogramData())
TS_ASSERT(!outputWS->isDistribution())
TS_ASSERT_DELTA(outputWS->x(0)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(0)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(0)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->x(65)[15], 30.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(65)[15], 3.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(65)[15], 1.73, 0.01)
TS_ASSERT_DELTA(outputWS->x(73728)[0], 0.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(73728)[0], 497.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(73728)[0], 22.29, 0.01)
TS_ASSERT_DELTA(outputWS->x(73728)[15], 30.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(73728)[15], 504.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(73728)[15], 22.45, 0.01)
const auto &run = outputWS->run();
TS_ASSERT(run.hasProperty("AcquisitionSpy.Time"))
TS_ASSERT(run.hasProperty("SampleSettings.SampleTemp"))
TS_ASSERT(run.hasProperty("ScanType"))
TS_ASSERT(run.hasProperty("ScanVar"))
TS_ASSERT(run.hasProperty("ResolutionMode"))
TS_ASSERT(run.hasProperty("Ei"))
const auto spy = run.getLogData("AcquisitionSpy.Time");
const auto sample = run.getLogData("SampleSettings.SampleTemp");
const auto scanType = run.getLogData("ScanType");
const auto scanVar = run.getLogData("ScanVar");
const auto ei = run.getLogAsSingleValue("wavelength");
TS_ASSERT_EQUALS(scanType->value(), "OtherScan")
TS_ASSERT_EQUALS(scanVar->value(), "d1t.position")
TS_ASSERT_EQUALS(spy->size(), 16)
TS_ASSERT_EQUALS(sample->size(), 16)
TS_ASSERT_DELTA(ei, 1.5288, 0.0001)
TS_ASSERT_EQUALS(outputWS->run().getProperty("Detector.calibration_file")->value(), "none")
checkTimeFormat(outputWS);
}
void test_SHARP_omega_scan() {
// Tests the omega-scan case for SHARP
LoadILLDiffraction alg;
// Don't put output in ADS by default
alg.setChild(true);
TS_ASSERT_THROWS_NOTHING(alg.initialize())
TS_ASSERT(alg.isInitialized())
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Filename", "000104.nxs"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("OutputWorkspace", "_unused_for_child"))
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("DataType", "Raw"))
TS_ASSERT_THROWS_NOTHING(alg.execute())
TS_ASSERT(alg.isExecuted())
MatrixWorkspace_sptr outputWS = alg.getProperty("OutputWorkspace");
TS_ASSERT(outputWS)
TS_ASSERT_EQUALS(outputWS->getNumberHistograms(), 61441)
TS_ASSERT_EQUALS(outputWS->blocksize(), 8)
TS_ASSERT(outputWS->detectorInfo().isMonitor(61440))
TS_ASSERT(!outputWS->isHistogramData())
TS_ASSERT(!outputWS->isDistribution())
TS_ASSERT_DELTA(outputWS->x(0)[0], 60.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(0)[0], 163.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(0)[0], 12.77, 0.01)
TS_ASSERT_DELTA(outputWS->x(65)[7], 62.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(65)[7], 222.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(65)[7], 14.90, 0.01)
TS_ASSERT_DELTA(outputWS->x(61440)[0], 60.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(61440)[0], 128.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(61440)[0], 11.31, 0.01)
TS_ASSERT_DELTA(outputWS->x(61440)[7], 62.00, 0.01)
TS_ASSERT_DELTA(outputWS->y(61440)[7], 128.00, 0.01)
TS_ASSERT_DELTA(outputWS->e(61440)[7], 11.31, 0.01)
const auto &run = outputWS->run();
TS_ASSERT(run.hasProperty("AcquisitionSpy.Time"))
TS_ASSERT(run.hasProperty("SampleSettings.SampleTemp"))
TS_ASSERT(run.hasProperty("ScanType"))
TS_ASSERT(run.hasProperty("ScanVar"))
TS_ASSERT(run.hasProperty("ResolutionMode"))
TS_ASSERT(run.hasProperty("Ei"))
const auto spy = run.getLogData("AcquisitionSpy.Time");
const auto sample = run.getLogData("SampleSettings.SampleTemp");
const auto scanType = run.getLogData("ScanType");
const auto scanVar = run.getLogData("ScanVar");
const auto ei = run.getLogAsSingleValue("wavelength");
TS_ASSERT_EQUALS(scanType->value(), "OtherScan")
TS_ASSERT_EQUALS(scanVar->value(), "updown.position")
TS_ASSERT_EQUALS(spy->size(), 8)
TS_ASSERT_EQUALS(sample->size(), 8)
TS_ASSERT_DELTA(ei, 5.12, 0.01)
TS_ASSERT_EQUALS(outputWS->run().getProperty("Detector.calibration_file")->value(), "none")
checkTimeFormat(outputWS);
}
private:
const double RAD_2_DEG = 180.0 / M_PI;
std::string m_oldFacility;
......
......@@ -51,7 +51,12 @@ public:
void test_LoadSANS_D22() { checkLoader("ILL/D22/192068", "LoadILLSANS"); }
void test_LoadSANS_D16() { checkLoader("ILL/D16/218356", "LoadILLSANS"); }
void test_LoadSANS_D16() {
checkLoader("ILL/D16/023583", "LoadILLSANS");
checkLoader("ILL/D16/218356", "LoadILLSANS");
}
void test_LoadDiffraction_D1B() { checkLoader("ILL/D1B/473432", "LoadILLDiffraction"); }
void test_LoadDiffraction_D2B() { checkLoader("ILL/D2B/535401", "LoadILLDiffraction"); }
......@@ -60,6 +65,14 @@ public:
checkLoader("ILL/D20/967087", "LoadILLDiffraction");
}
void test_loadDiffraction_IN5() { checkLoader("ILL/IN5/199857", "LoadILLDiffraction"); }
void test_loadDiffraction_PANTHER() { checkLoader("ILL/PANTHER/010578", "LoadILLDiffraction"); }
void test_loadDiffraction_SHARP() { checkLoader("ILL/SHARP/000104.nxs", "LoadILLDiffraction"); }
void test_LoadPolarizedDiffraction_D7() { checkLoader("ILL/D7/394458", "LoadILLPolarizedDiffraction"); }
void test_loadIndirect_IN16B() {
checkLoader("ILL/IN16B/090661", "LoadILLIndirect"); // one wing qens
checkLoader("ILL/IN16B/083072", "LoadILLIndirect"); // one wing efws
......
......@@ -235,7 +235,7 @@ void NexusDescriptor::walkFile(::NeXus::File &file, const std::string &rootPath,
const std::string &entryName = it->first;
const std::string &entryClass = it->second;
const std::string entryPath = std::string(rootPath).append("/").append(entryName);
if (entryClass == "SDS" || entryClass == "ILL_data_scan_vars") {
if (entryClass == "SDS" || entryClass == "ILL_data_scan_vars" || entryClass == "NXill_data_scan_vars") {
pmap.emplace(entryPath, entryClass);
} else if (entryClass == "CDF0.0") {
// Do nothing with this
......
701fcaacba8a50ac8c170e01ce7919e6
1406c11dcd19fb369c87df74d0763259
......@@ -11,9 +11,10 @@ Description
-----------
This is the loader for the raw `.nxs` files produced by the powder diffractometers at ILL.
Currently it supports the instruments D20, D1B and D2B.
Currently it supports the instruments D20, D1B and D2B, as well as IN5, PANTHER, and SHARP in the data scan mode.
The *TwoThetaOffset* parameter corresponding to the rotation of the detector is optional and only used for D1B. It is to be provided in degrees.
Loading D20
###########
......@@ -38,12 +39,12 @@ The loader is able to load the following scan configurations:
- **detector scan**, used always for D2B, and for D20 calibration runs, when the detector moves during the run. In this configuration the output is a *scanning workspace* containing one spectrum for each pixel at each time index. The x-axis is again a single point.
- **other scan**, e.g. omega scan for D20, which is another type of motor scan, but it is not the detector that moves, but the sample. In this case, the data in the raw file is organised just as for *detector scan*, but the output workspace is not a *scanning workspace*. It is a regular workspace with x-axis corresponding to the scanned variable, e.g. omega angle.
- **other scan**, e.g. omega scan for D20, IN5, PANTHER, and SHARP, which is another type of motor scan, but it is not the detector that moves, but the sample. In this case, the data in the raw file is organised just as for *detector scan*, but the output workspace is not a *scanning workspace*. It is a regular workspace with x-axis corresponding to the scanned variable, e.g. omega angle.
Logs
####
The loader creates time series logs for each of the scanned variable in the `.nxs` file.
The loader creates time series logs for each of the scanned variable in the `.nxs` file. The scanned variable name is added under `ScanVar` log.
D2B alignment
-------------
......@@ -118,6 +119,20 @@ Output:
The output has 1 bin (detector scan) and 1281 spectra
**Example - LoadILLDiffraction - IN5**
.. testcode:: LoadILLDiffractionIN5Example
ws = LoadILLDiffraction(Filename='ILL/IN5/199857.nxs')
print('The output has {0} bin (omega scan) and {1} spectra'.format(ws.blocksize(), ws.getNumberHistograms()))
Output:
.. testoutput:: LoadILLDiffractionIN5Example
The output has 17 bin (omega scan) and 98305 spectra
.. categories::
.. sourcelink::
......@@ -17,6 +17,8 @@ To date this algorithm only supports: IN4, IN5, IN6, PANTHER, and SHARP.
By default, this algorithm loads the data indexed by channels. To convert to time-of-flight, use the ConvertToTOF option.
This algorithm also supports diffraction mode. In this case, the unit of the output workspace will be wavelength instead of time-of-flight or channel.
The support for the omega scan measurement mode for IN5, PANTHER, and SHARP is **not** handled by this loader, but instead the data
is loaded with :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>`.
.. note::
The initial time-of-flight axis is set up using the 'time_of_flight' field in the NeXus file. Therefore the conversion from 'TOF' to 'DeltaE' may not give the correct zero-energy transfer.
......
......@@ -54,6 +54,7 @@ Bugfixes
- :ref:`SNSPowderReduction <algm-SNSPowderReduction>` has additional property, ``DeltaRagged``, which allows using :ref:`RebinRagged <algm-RebinRagged>` to bin each spectrum differently.
- Allow a different number of spectra for absorption correction division of PEARL data. This allows ``create_vanadium`` to work for a non-standard dataset.
- Saved filenames for summed empty workspaces now include spline properties to avoid long_mode confusion when focussing.
- Fix segmentation violation issues for ILL instruments D1B, D2B, and D20, caused by change of scanned data type
- The :ref:`ConvertUnits <algm-ConvertUnits>` algorithm has been extended to use a quadratic relationship between d spacing and TOF when doing conversions between these units. The diffractometer constants DIFA, DIFC and TZERO that determine the form of the quadratic can be loaded into a workspace using a new :ref:`ApplyDiffCal <algm-ApplyDiffCal>` algorithm. This functionality was previously only available in :ref:`AlignDetectors <algm-AlignDetectors>` which only performed the conversion in the direction TOF to d spacing. This change will ensure that the conversion of focussed datasets from d spacing back to TOF at the end of the ISIS powder diffraction data reduction is performed correctly.
......
......@@ -14,6 +14,8 @@ New
* Updated instrument geometry for CHESS
* Loading of SHARP TOF and single-channel data has been added to :ref:`LoadILLTOF <algm-LoadILLTOF-v2>`
* Loading of the omega-scan mode is supported for ILL instruments IN5, PANTHER, and SHARP via :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` loader
Improvements
......@@ -23,8 +25,11 @@ Improvements
MSlice
------
BugFixes
########
- Fixed bug that overwrote selection of background workspace when subtracting workspaces.
- Fixed runtime error when trying to delete workspace for the second time.
- Fix for colorcycle problem for multiple curves on one plot.
......
Supports Markdown
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