Newer
Older
Ronald Fowler
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidNexus/LoadInstrumentFromNexus.h"
#include "MantidAPI/Instrument.h"
#include "MantidKernel/ConfigService.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidGeometry/Instrument/CompAssembly.h"
#include "MantidGeometry/Instrument/Component.h"
Ronald Fowler
committed
#include "MantidNexus/MuonNexusReader.h"
#include <fstream>
namespace Mantid
{
Russell Taylor
committed
namespace NeXus
Ronald Fowler
committed
{
DECLARE_ALGORITHM(LoadInstrumentFromNexus)
using namespace Kernel;
using namespace API;
/// Empty default constructor
LoadInstrumentFromNexus::LoadInstrumentFromNexus()
{}
/// Initialisation method.
void LoadInstrumentFromNexus::init()
{
// When used as a sub-algorithm the workspace name is not used - hence the "Anonymous" to satisfy the validator
Steve Williams
committed
declareProperty(
new WorkspaceProperty<MatrixWorkspace>("Workspace","Anonymous",Direction::InOut),
"The name of the workspace in which to attach the imported instrument" );
Gigg, Martyn Anthony
committed
Peterson, Peter
committed
declareProperty(new FileProperty("Filename", "", FileProperty::Load, ".nxs"),
Gigg, Martyn Anthony
committed
"The name (including its full or relative path) of the Nexus file to\n"
"attempt to load the instrument from. The file extension must either be\n"
".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()
{
// 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;
if (nxload.readFromFile(m_filename.c_str()) != 0)
{
g_log.error("Unable to open file " + m_filename);
throw Exception::FileError("Unable to open File:" , m_filename);
}
Sofia Antony
committed
progress(0.5);
Ronald Fowler
committed
// Get reference to Instrument and set its name
boost::shared_ptr<API::Instrument> instrument = localWorkspace->getBaseInstrument();
Ronald Fowler
committed
instrument->setName(nxload.getInstrumentName());
// 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());
instrument->add(samplepos);
instrument->markAsSamplePos(samplepos);
samplepos->setPos(0.0,0.0,0.0);
Geometry::ObjComponent *source = new Geometry::ObjComponent("Unknown",instrument.get());
instrument->add(source);
instrument->markAsSource(source);
double l1;
// If user has provided an L1, use that
if ( ! Kernel::ConfigService::Instance().getValue("instrument.L1", l1) )
{
// 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
if (l1 == 0) l1 = 10.0;
}
source->setPos(0.0,-1.0*l1,0.0);
Sofia Antony
committed
progress(1.0);
Ronald Fowler
committed
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// add detectors
/* **** Ignoring all this for the moment - the sample Nexus files do not contain most of these values
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)
for (int i = 0; i < numDetector; ++i)
{
// Create a new detector. Instrument will take ownership of pointer so no need to delete.
Geometry::Detector *detector = new Geometry::Detector("det",samplepos);
Geometry::V3D pos;
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
for (int j = 0; j < numMonitors; ++j)
{
const int detectorToMark = detID[monIndex[j]-1];
Geometry::Detector *det = dynamic_cast<Geometry::Detector*>(instrument->getDetector(detectorToMark));
det->markAsMonitor();
g_log.information() << "Detector with ID " << detectorToMark << " marked as a monitor." << std::endl;
}
// Information to the user about what info is extracted from nexus file
Ronald Fowler
committed
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";
*/
return;
}
Russell Taylor
committed
} // namespace NeXus
Ronald Fowler
committed
} // namespace Mantid