Newer
Older
Ronald Fowler
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadInstrumentFromNexus.h"
Russell Taylor
committed
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidGeometry/Instrument/CompAssembly.h"
#include "MantidGeometry/Instrument/Component.h"
#include "MantidNexus/MuonNexusReader.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/ConfigService.h"
#include "MantidAPI/FileProperty.h"
Ronald Fowler
committed
#include <fstream>
namespace Mantid {
namespace DataHandling {
Ronald Fowler
committed
DECLARE_ALGORITHM(LoadInstrumentFromNexus)
using namespace Kernel;
using namespace API;
Gigg, Martyn Anthony
committed
using Geometry::Instrument;
Ronald Fowler
committed
/// Empty default constructor
LoadInstrumentFromNexus::LoadInstrumentFromNexus() {}
Ronald Fowler
committed
/// Initialisation method.
void LoadInstrumentFromNexus::init() {
// When used as a Child Algorithm the workspace name is not used - hence the
// "Anonymous" to satisfy the validator
Steve Williams
committed
declareProperty(
make_unique<WorkspaceProperty<MatrixWorkspace>>("Workspace", "Anonymous",
Direction::InOut),
"The name of the workspace in which to attach the imported instrument");
Gigg, Martyn Anthony
committed
make_unique<FileProperty>("Filename", "", FileProperty::Load, ".nxs"),
"The name (including its full or relative path) of the Nexus file to "
"attempt to load the instrument from. The file extension must either be "
".nxs or .NXS");
Ronald Fowler
committed
}
/** Executes the algorithm. Reading in the file and creating and populating
* the output workspace
*
* @throw FileError Thrown if unable to parse XML file
*/
void LoadInstrumentFromNexus::exec() {
Ronald Fowler
committed
// Retrieve the filename from the properties
m_filename = getPropertyValue("Filename");
// Get the input workspace
Roman Tolchenov
committed
const MatrixWorkspace_sptr localWorkspace = getProperty("Workspace");
Ronald Fowler
committed
// open Nexus file
MuonNexusReader nxload;
nxload.readFromFile(m_filename);
Sofia Antony
committed
progress(0.5);
Russell Taylor
committed
// Create a new Instrument with the right name and add it to the workspace
Geometry::Instrument_sptr instrument(
new Geometry::Instrument(nxload.getInstrumentName()));
Russell Taylor
committed
localWorkspace->setInstrument(instrument);
Ronald Fowler
committed
// Add dummy source and samplepos to instrument
// The L2 and 2-theta values from nexus file assumed to be relative to sample
// position
Ronald Fowler
committed
Geometry::ObjComponent *samplepos =
new Geometry::ObjComponent("Unknown", instrument.get());
Ronald Fowler
committed
instrument->add(samplepos);
instrument->markAsSamplePos(samplepos);
Ronald Fowler
committed
Geometry::ObjComponent *source =
new Geometry::ObjComponent("Unknown", instrument.get());
Ronald Fowler
committed
instrument->add(source);
instrument->markAsSource(source);
Ronald Fowler
committed
// If user has provided an L1, use that
if (!Kernel::ConfigService::Instance().getValue("instrument.L1", l1)) {
Ronald Fowler
committed
// Otherwise try and get it from the nexus file - but not there at present!
// l1 = nxload.ivpb.i_l1;
// Default to 10 if the file doesn't have it set
Ronald Fowler
committed
}
source->setPos(0.0, -1.0 * l1, 0.0);
progress(1.0);
Ronald Fowler
committed
// add detectors
/* **** Ignoring all this for the moment - the sample Nexus files do not
contain most of these values
Ronald Fowler
committed
const int numDetector = nxload.i_det; // number of detectors
const int* const detID = nxload.udet; // detector IDs
const float* const r = nxload.len2; // distance from sample
const float* const angle = nxload.tthe; // angle between indicent beam and
direction from sample to detector (two-theta)
Ronald Fowler
committed
for (int i = 0; i < numDetector; ++i)
{
// Create a new detector. Instrument will take ownership of pointer so no
need to delete.
Ronald Fowler
committed
Geometry::Detector *detector = new Geometry::Detector("det",samplepos);
Gigg, Martyn Anthony
committed
Kernel::V3D pos;
Ronald Fowler
committed
pos.spherical(r[i], angle[i], 0.0);
detector->setPos(pos);
// set detector ID, add copy to instrument and mark it
detector->setID(detID[i]);
instrument->add(detector);
instrument->markAsDetector(detector);
}
// Now mark the up the monitors
const int numMonitors = nxload.i_mon; // The number of monitors
const int* const monIndex = nxload.mdet; // Index into the udet array for
each monitor
Ronald Fowler
committed
for (int j = 0; j < numMonitors; ++j)
{
const int detectorToMark = detID[monIndex[j]-1];
Geometry::Detector *det =
dynamic_cast<Geometry::Detector*>(instrument->getDetector(detectorToMark));
Ronald Fowler
committed
det->markAsMonitor();
g_log.information() << "Detector with ID " << detectorToMark << " marked as
Ronald Fowler
committed
}
// Information to the user about what info is extracted from nexus file
g_log.information() << "SamplePos component added with position set to
(0,0,0).\n"
<< "Detector components added with position coordinates assumed to be
relative to the position of the sample; \n"
<< "L2 and two-theta values were read from nexus file and used to set the r
and theta spherical coordinates; \n"
Ronald Fowler
committed
<< "the remaining spherical coordinate phi was set to zero.\n"
<< "Source component added with position set to (0,-" << l1 << ",0). In
standard configuration, with \n"
<< "the beam along y-axis pointing from source to sample, this implies the
source is " << l1 << "m in front \n"
<< "of the sample. This value can be changed via the 'instrument.l1'
configuration property.\n";
Ronald Fowler
committed
*/
return;
}
} // namespace DataHandling
Ronald Fowler
committed
} // namespace Mantid