Commit f05417a9 authored by Ricardo Leal's avatar Ricardo Leal
Browse files

Re #6771 cleaned up. new branch.

parent 219d2abf
......@@ -25,6 +25,7 @@ set ( SRC_FILES
src/LiveDataAlgorithm.cpp
src/Load.cpp
src/LoadAscii.cpp
src/LoadHelper.cpp
src/LoadCalFile.cpp
src/LoadCanSAS1D.cpp
src/LoadCanSAS1D2.cpp
......@@ -45,6 +46,7 @@ set ( SRC_FILES
src/LoadGSS.cpp
src/LoadIDFFromNexus.cpp
src/LoadILL.cpp
src/LoadILLSANS.cpp
src/LoadISISNexus.cpp
src/LoadISISNexus2.cpp
src/LoadInstrument.cpp
......@@ -176,6 +178,7 @@ set ( INC_FILES
inc/MantidDataHandling/LiveDataAlgorithm.h
inc/MantidDataHandling/Load.h
inc/MantidDataHandling/LoadAscii.h
inc/MantidDataHandling/LoadHelper.h
inc/MantidDataHandling/LoadCalFile.h
inc/MantidDataHandling/LoadCanSAS1D.h
inc/MantidDataHandling/LoadCanSAS1D2.h
......@@ -192,6 +195,7 @@ set ( INC_FILES
inc/MantidDataHandling/LoadGSS.h
inc/MantidDataHandling/LoadIDFFromNexus.h
inc/MantidDataHandling/LoadILL.h
inc/MantidDataHandling/LoadILLSANS.h
inc/MantidDataHandling/LoadISISNexus.h
inc/MantidDataHandling/LoadISISNexus2.h
inc/MantidDataHandling/LoadInstrument.h
......@@ -331,6 +335,7 @@ set ( TEST_FILES
LoadEventPreNexusTest.h
LoadFullprofResolutionTest.h
LoadGSSTest.h
LoadILLSANSTest.h
LoadILLTest.h
LoadISISNexusTest.h
LoadInstrumentFromRawTest.h
......
#ifndef MANTID_DATAHANDLING_LoadHelper_H_
#define MANTID_DATAHANDLING_LoadHelper_H_
#include "MantidKernel/System.h"
#include "MantidNexus/NexusClasses.h"
namespace Mantid {
namespace DataHandling {
/** LoadHelper : Auxiliary File for Loading Files
Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport LoadHelper {
public:
LoadHelper();
virtual ~LoadHelper();
std::string getInstrumentName(NeXus::NXEntry&);
std::string findInstrumentNexusPath(const NeXus::NXEntry&);
std::string getStringFromNexusPath(const NeXus::NXEntry&, const std::string&);
double getDoubleFromNexusPath(const NeXus::NXEntry&, const std::string&);
std::vector<double> getTimeBinningFromNexusPath(
const NeXus::NXEntry &, const std::string &);
static double calculateStandardError(double in) {return sqrt(in);}
double calculateEnergy(double);
private:
/// Reference to the logger class
Kernel::Logger& g_log;
};
} // namespace DataHandling
} // namespace Mantid
#endif /* MANTID_DATAHANDLING_LoadHelper_H_ */
......@@ -42,15 +42,7 @@ namespace DataHandling {
{
public:
/// Constructor
LoadILL() : API::IHDFFileLoader(), m_instrumentName(""),
m_wavelength(0), m_channelWidth(0)
{
supportedInstruments.push_back("IN4");
supportedInstruments.push_back("IN5");
supportedInstruments.push_back("IN6");
}
/// Virtual destructor
LoadILL(); /// Virtual destructor
virtual ~LoadILL() {
}
/// Algorithm's name
......@@ -88,6 +80,10 @@ namespace DataHandling {
NeXus::NXData loadNexusFileData(NeXus::NXEntry& entry);
void loadDataIntoTheWorkSpace(NeXus::NXEntry& entry);
double getL1();
double getL2(int detId=1);
double getInstrumentProperty(std::string);
double calculateEnergy(double);
double calculateTOF(double);
void runLoadInstrument();
......
#ifndef MANTID_DATAHANDLING_LOADILLSANS_H_
#define MANTID_DATAHANDLING_LOADILLSANS_H_
#include "MantidKernel/System.h"
#include "MantidAPI/IHDFFileLoader.h"
#include "MantidNexus/NexusClasses.h"
#include "MantidDataHandling/LoadHelper.h"
namespace Mantid {
namespace DataHandling {
/** LoadILLSANS
To date this only supports ILL D33 SANS-TOF instrument
Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
struct DetectorPosition {
double distanceSampleRear;
double distanceSampleBottomTop;
double distanceSampleRightLeft;
double shiftLeft;
double shiftRight;
double shiftUp;
double shiftDown;
};
std::ostream& operator<<(std::ostream &strm, const DetectorPosition &p) {
return strm << "DetectorPosition : " << "distanceSampleRear = "
<< p.distanceSampleRear << ", " << "distanceSampleBottomTop = "
<< p.distanceSampleBottomTop << ", " << "distanceSampleRightLeft = "
<< p.distanceSampleRightLeft << ", " << "shiftLeft = "
<< p.shiftLeft << ", " << "shiftRight = " << p.shiftRight << ", "
<< "shiftUp = " << p.shiftUp << ", " << "shiftDown = "
<< p.shiftDown << std::endl;
}
class DLLExport LoadILLSANS: public API::IHDFFileLoader {
public:
LoadILLSANS();
virtual ~LoadILLSANS();
virtual const std::string name() const;
virtual int version() const;
virtual const std::string category() const;
/// Returns a confidence value that this algorithm can load a file
int confidence(Kernel::HDFDescriptor & descriptor) const;
private:
virtual void initDocs();
void init();
void exec();
void setInstrumentName(const NeXus::NXEntry&, const std::string&);
DetectorPosition getDetectorPosition(const NeXus::NXEntry&,
const std::string &);
void initWorkSpace(NeXus::NXEntry&, const std::string&);
void createEmptyWorkspace(int, int);
size_t loadDataIntoWorkspaceFromHorizontalTubes(NeXus::NXInt &, const std::vector<double> &,
size_t);
size_t loadDataIntoWorkspaceFromVerticalTubes(NeXus::NXInt &, const std::vector<double> &,
size_t);
void runLoadInstrument();
void moveDetectors(const DetectorPosition&);
void moveDetectorDistance(double, const std::string&);
void moveDetectorHorizontal(double, const std::string&);
void moveDetectorVertical(double, const std::string&);
Kernel::V3D getComponentPosition(const std::string& componentName);
void loadMetaData(const NeXus::NXEntry &,const std::string &);
LoadHelper m_loader;
std::string m_instrumentName; ///< Name of the instrument
std::vector<std::string> supportedInstruments;
API::MatrixWorkspace_sptr m_localWorkspace;
std::vector<double> m_defaultBinning;
};
} // namespace DataHandling
} // namespace Mantid
#endif /* MANTID_DATAHANDLING_LOADILLSANS_H_ */
/*WIKI*
TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page.
*WIKI*/
#include "MantidDataHandling/LoadHelper.h"
namespace Mantid {
namespace DataHandling {
using namespace Kernel;
using namespace API;
LoadHelper::LoadHelper() :
g_log(Kernel::Logger::get("Algorithm")) {
}
LoadHelper::~LoadHelper() {
}
/**
* Finds the instrument name in the nexus file
*
* @param entry :: The Nexus entry
* @return instrument name
*/
std::string LoadHelper::getInstrumentName(NeXus::NXEntry& entry) {
// Old format: /entry0/IN5/name
// New format: /entry0/instrument/name
// Ugly way of getting Instrument Name
// Instrument name is in: entry0/<NXinstrument>/name
std::string instrumentName = "";
std::vector<NeXus::NXClassInfo> v = entry.groups();
for (auto it = v.begin(); it < v.end(); it++) {
if (it->nxclass == "NXinstrument") {
std::string nexusInstrumentEntryName = it->nxname;
std::string insNamePath = nexusInstrumentEntryName + "/name";
if (!entry.isValid(insNamePath))
throw std::runtime_error(
"Error reading the instrument name: " + insNamePath
+ " is not a valid path!");
instrumentName = entry.getString(insNamePath);
g_log.debug() << "Instrument Name: " << instrumentName
<< " in NxPath: " << insNamePath << std::endl;
break;
}
}
return instrumentName;
}
/**
* Finds the path for the instrument name in the nexus file
* Usually of the form: entry0/<NXinstrument class>/name
*/
std::string LoadHelper::findInstrumentNexusPath(
const NeXus::NXEntry &firstEntry) {
std::string insNamePath = "";
std::vector<NeXus::NXClassInfo> v = firstEntry.groups();
for (auto it = v.begin(); it < v.end(); it++) {
if (it->nxclass == "NXinstrument") {
insNamePath = it->nxname;
break;
}
}
return insNamePath;
}
std::string LoadHelper::getStringFromNexusPath(const NeXus::NXEntry &firstEntry,
const std::string &nexusPath) {
return firstEntry.getString(nexusPath);
}
double LoadHelper::getDoubleFromNexusPath(const NeXus::NXEntry &firstEntry,
const std::string &nexusPath) {
return firstEntry.getFloat(nexusPath);
}
/**
* Gets the time binning from a Nexus float array
* Adds an extra bin at the end
*/
std::vector<double> LoadHelper::getTimeBinningFromNexusPath(
const NeXus::NXEntry &firstEntry, const std::string &nexusPath) {
NeXus::NXFloat timeBinningNexus = firstEntry.openNXFloat(nexusPath);
timeBinningNexus.load();
size_t numberOfBins = static_cast<size_t>(timeBinningNexus.dim0()) + 1; // boundaries
float* timeBinning_p = &timeBinningNexus[0];
std::vector<double> timeBinning(numberOfBins);
timeBinning.assign(timeBinning_p, timeBinning_p + numberOfBins);
// calculate the extra bin at the end
timeBinning[numberOfBins - 1] = timeBinning[numberOfBins - 2]
+ timeBinning[1] - timeBinning[0];
return timeBinning;
}
/**
* Calculate Neutron Energy from wavelength: \f$ E = h^2 / 2m\lambda ^2 \f$
* @param wavelength :: wavelength in \f$ \AA \f$
* @return tof in seconds
*/
double LoadHelper::calculateEnergy(double wavelength) {
double e = (PhysicalConstants::h * PhysicalConstants::h)
/ (2 * PhysicalConstants::NeutronMass * wavelength * wavelength
* 1e-20) / PhysicalConstants::meV;
return e;
}
} // namespace DataHandling
} // namespace Mantid
......@@ -14,6 +14,7 @@
#include "MantidAPI/Progress.h"
#include "MantidAPI/RegisterFileLoader.h"
#include "MantidGeometry/Instrument.h"
#include "MantidKernel/EmptyValues.h"
#include "MantidKernel/UnitFactory.h"
#include <limits>
......@@ -41,6 +42,7 @@ namespace Mantid {
<< c.nxclass;
}
/// Sets documentation strings for this algorithm
void LoadILL::initDocs() {
this->setWikiSummary("Loads a ILL nexus file. ");
......@@ -67,6 +69,19 @@ namespace Mantid {
// Private member functions
//---------------------------------------------------
LoadILL::LoadILL() :
API::IHDFFileLoader() {
m_instrumentName = "";
m_wavelength = 0;
m_channelWidth = 0;
supportedInstruments.push_back("IN4");
supportedInstruments.push_back("IN5");
supportedInstruments.push_back("IN6");
}
/**
* Initialise the algorithm
*/
......@@ -93,11 +108,12 @@ namespace Mantid {
setInstrumentName(entry);
initInstrumentSpecific();
loadTimeDetails(entry);
initWorkSpace(entry);
runLoadInstrument(); // just to get IDF contents
initInstrumentSpecific();
loadDataIntoTheWorkSpace(entry);
loadRunDetails(entry);
......@@ -130,6 +146,8 @@ namespace Mantid {
for (auto it = v.begin(); it < v.end(); it++) {
if (it->nxclass == "NXinstrument") {
std::string insNamePath = it->nxname + "/name";
if ( !entry.isValid(insNamePath) )
throw std::runtime_error("Error reading the instrument name: " + insNamePath + " is not a valid path!");
instrumentName = entry.getString(insNamePath);
g_log.debug() << "Instrument Name: " << instrumentName
<< " in NxPath: " << insNamePath << std::endl;
......@@ -151,7 +169,8 @@ namespace Mantid {
m_instrumentName = getInstrumentName(entry);
if (m_instrumentName == "") {
std::string message("Cannot read the instrument name from the Nexus file!");
std::string message(
"Cannot read the instrument name from the Nexus file!");
g_log.error(message);
throw std::runtime_error(message);
}
......@@ -179,7 +198,8 @@ namespace Mantid {
m_numberOfHistograms = m_numberOfTubes * m_numberOfPixelsPerTube;
g_log.debug() << "NumberOfTubes: " << m_numberOfTubes << std::endl;
g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube << std::endl;
g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube
<< std::endl;
g_log.debug() << "NumberOfChannels: " << m_numberOfChannels << std::endl;
// Now create the output workspace
......@@ -199,27 +219,16 @@ namespace Mantid {
/**
* Function to do specific instrument stuff
* This is very ugly. We have to find a place where to put this
* I can't get this from the instrument parameters because it wasn't
* initilialised yet!
*
*/
void LoadILL::initInstrumentSpecific() {
if (std::string::npos != m_instrumentName.find("IN5")) {
m_l1 = 2.0;
m_l2 = 4.0;
}
else if (std::string::npos != m_instrumentName.find("IN6")) {
m_l1 = 2.0;
m_l2 = 2.48;
}
else if (std::string::npos != m_instrumentName.find("IN4")) {
m_l1 = 2.0;
m_l2 = 2.0;
m_l1 = getL1();
// this will be mainly for IN5 (flat PSD detector)
m_l2 = getInstrumentProperty("l2");
if ( m_l2 == EMPTY_DBL() ){
g_log.debug("Calculating L2 from the IDF.");
m_l2 = getL2();
}
else{
g_log.warning("initInstrumentSpecific : Couldn't find instrument: " + m_instrumentName);
}
}
/**
......@@ -228,7 +237,6 @@ namespace Mantid {
*/
void LoadILL::loadTimeDetails(NeXus::NXEntry& entry) {
m_wavelength = entry.getFloat("wavelength");
// Monitor can be monitor (IN5) or monitor1 (IN6)
......@@ -245,7 +253,8 @@ namespace Mantid {
m_monitorElasticPeakPosition = entry.getInt(monitorName + "/elasticpeak");
NXFloat time_of_flight_data = entry.openNXFloat(monitorName + "/time_of_flight");
NXFloat time_of_flight_data = entry.openNXFloat(
monitorName + "/time_of_flight");
time_of_flight_data.load();
// The entry "monitor/time_of_flight", has 3 fields:
......@@ -318,7 +327,7 @@ namespace Mantid {
//runDetails.addProperty<double>("wavelength", m_wavelength);
runDetails.addProperty("wavelength", wavelength);
double ei = calculateEnergy(m_wavelength);
runDetails.addProperty<double>("Ei", ei,true); //overwrite
runDetails.addProperty<double>("Ei", ei, true); //overwrite
//std::string ei_str = boost::lexical_cast<std::string>(ei);
//runDetails.addProperty("Ei", ei_str);
......@@ -371,7 +380,6 @@ namespace Mantid {
}
///**
// * Gets the experimental Elastic Peak Position in the dectector
// * as the value parsed from the nexus file might be wrong.
......@@ -452,7 +460,6 @@ namespace Mantid {
//get limits in the m_numberOfTubes
size_t tubesToRemove = m_numberOfTubes / 7;
std::vector<int> cumulatedSumOfSpectras(m_numberOfChannels, 0);
for (size_t i = tubesToRemove; i < m_numberOfTubes - tubesToRemove; i++) {
int* data_p = &data(static_cast<int>(i), static_cast<int>(j), 0);
......@@ -462,7 +469,8 @@ namespace Mantid {
cumulatedSumOfSpectras.begin(), cumulatedSumOfSpectras.begin(),
std::plus<int>());
}
auto it = std::max_element(cumulatedSumOfSpectras.begin(),cumulatedSumOfSpectras.end());
auto it = std::max_element(cumulatedSumOfSpectras.begin(),
cumulatedSumOfSpectras.end());
int calculatedDetectorElasticPeakPosition;
if (it == cumulatedSumOfSpectras.end()) {
......@@ -473,13 +481,15 @@ namespace Mantid {
} else {
//calculatedDetectorElasticPeakPosition = *it;
calculatedDetectorElasticPeakPosition = static_cast<int>(std::distance(cumulatedSumOfSpectras.begin(), it));
calculatedDetectorElasticPeakPosition = static_cast<int>(std::distance(
cumulatedSumOfSpectras.begin(), it));
if (calculatedDetectorElasticPeakPosition == 0) {
g_log.warning()
<< "Elastic peak position is ZERO Assuming the EPP in the Nexus file: "
<< m_monitorElasticPeakPosition << std::endl;
calculatedDetectorElasticPeakPosition = m_monitorElasticPeakPosition;
<< "Elastic peak position is ZERO Assuming the EPP in the Nexus file: "
<< m_monitorElasticPeakPosition << std::endl;
calculatedDetectorElasticPeakPosition =
m_monitorElasticPeakPosition;
} else {
g_log.debug() << "Calculated Detector EPP: "
......@@ -510,7 +520,8 @@ namespace Mantid {
int calculatedDetectorElasticPeakPosition = getDetectorElasticPeakPosition(
data);
double theoreticalElasticTOF = (calculateTOF(m_l1) + calculateTOF(m_l2)) * 1e6; //microsecs
double theoreticalElasticTOF = (calculateTOF(m_l1) + calculateTOF(m_l2))
* 1e6; //microsecs
// Calculate the real tof (t1+t2) put it in tof array
std::vector<double> detectorTofBins(m_numberOfChannels + 1);
......@@ -519,7 +530,7 @@ namespace Mantid {
+ m_channelWidth
* static_cast<double>(static_cast<int>(i)
- calculatedDetectorElasticPeakPosition)
- m_channelWidth / 2; // to make sure the bin is in the middle of the elastic peak
- m_channelWidth / 2; // to make sure the bin is in the middle of the elastic peak
}
//g_log.debug() << "Detector TOF bins: ";
......@@ -533,7 +544,8 @@ namespace Mantid {
<< std::endl;
// Assign calculated bins to first X axis
m_localWorkspace->dataX(0).assign(detectorTofBins.begin(),detectorTofBins.end());
m_localWorkspace->dataX(0).assign(detectorTofBins.begin(),
detectorTofBins.end());
Progress progress(this, 0, 1, m_numberOfTubes * m_numberOfPixelsPerTube);
size_t spec = 0;
......@@ -550,7 +562,8 @@ namespace Mantid {
// Assign Error
MantidVec& E = m_localWorkspace->dataE(spec);
std::transform(data_p, data_p + m_numberOfChannels, E.begin(), LoadILL::calculateError);
std::transform(data_p, data_p + m_numberOfChannels, E.begin(),
LoadILL::calculateError);
++spec;
progress.report();
......@@ -602,12 +615,50 @@ namespace Mantid {
* @return tof in seconds
*/
double LoadILL::calculateEnergy(double wavelength) {
double e = (PhysicalConstants::h * PhysicalConstants::h) /
(2 * PhysicalConstants::NeutronMass * wavelength*wavelength * 1e-20)/
PhysicalConstants::meV;
double e = (PhysicalConstants::h * PhysicalConstants::h)
/ (2 * PhysicalConstants::NeutronMass * wavelength * wavelength
* 1e-20) / PhysicalConstants::meV;
return e;
}
double LoadILL::getL1() {
Geometry::Instrument_const_sptr instrument =
m_localWorkspace->getInstrument();
Geometry::IObjComponent_const_sptr sample = instrument->getSample();
double l1 = instrument->getSource()->getDistance(*sample);
return l1;
}
double LoadILL::getL2(int detId) {
// Get a pointer to the instrument contained in the workspace
Geometry::Instrument_const_sptr instrument =
m_localWorkspace->getInstrument();
// Get the distance between the source and the sample (assume in metres)
Geometry::IObjComponent_const_sptr sample = instrument->getSample();
// Get the sample-detector distance for this detector (in metres)
double l2 = m_localWorkspace->getDetector(detId)->getPos().distance(
sample->getPos());
return l2;
}
/*
* Get instrument property as double
* @s - input property name
*
*/
double LoadILL::getInstrumentProperty(std::string s) {
std::vector<std::string> prop = m_localWorkspace->getInstrument()->getStringParameter(s);
if (prop.empty()) {
g_log.debug("Property <" + s + "> doesn't exist!");