Skip to content
Snippets Groups Projects
Commit 0dc8455b authored by Campbell, Stuart's avatar Campbell, Stuart
Browse files

Actually writes some data now. refs #1420.

parent 7a6d2cd9
No related branches found
No related tags found
No related merge requests found
#include "MantidNexus/SaveNXSPE.h" #include "MantidNexus/SaveNXSPE.h"
#include "MantidAPI/FileProperty.h" #include "MantidAPI/FileProperty.h"
#include "MantidKernel/ConfigService.h" #include "MantidKernel/ConfigService.h"
#include "MantidAPI/WorkspaceValidators.h" #include "MantidAPI/WorkspaceValidators.h"
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidGeometry/Instrument/ObjComponent.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "Poco/Path.h" #include "Poco/Path.h"
namespace Mantid { namespace Mantid
namespace NeXus { {
namespace NeXus
// Register the algorithm into the algorithm factory {
DECLARE_ALGORITHM( SaveNXSPE)
// Register the algorithm into the algorithm factory
using namespace Kernel; DECLARE_ALGORITHM( SaveNXSPE)
using namespace API;
using namespace Kernel;
SaveNXSPE::SaveNXSPE() : using namespace API;
API::Algorithm() {
} const double SaveNXSPE::MASK_FLAG = -1e30;
const double SaveNXSPE::MASK_ERROR = 0.0;
/**
* Initialise the algorithm SaveNXSPE::SaveNXSPE() :
*/ API::Algorithm()
void SaveNXSPE::init() { {
}
std::vector<std::string> exts;
exts.push_back(".nxspe"); /**
* Initialise the algorithm
declareProperty(new API::FileProperty("Filename", "", FileProperty::Save, exts), */
"The name of the NXSPE file to write, as a full or relative path"); void
SaveNXSPE::init()
CompositeValidator<> * wsValidator = new CompositeValidator<> ; {
wsValidator->add(new API::WorkspaceUnitValidator<>("DeltaE"));
wsValidator->add(new API::CommonBinsValidator<>); std::vector < std::string > exts;
wsValidator->add(new API::HistogramValidator<>); exts.push_back(".nxspe");
declareProperty(new WorkspaceProperty<MatrixWorkspace> ("InputWorkspace", declareProperty(new API::FileProperty("Filename", "", FileProperty::Save,
"", Direction::Input, wsValidator), exts),
"Name of the workspace to be saved."); "The name of the NXSPE file to write, as a full or relative path");
}
CompositeValidator<> * wsValidator = new CompositeValidator<> ;
/** wsValidator->add(new API::WorkspaceUnitValidator<>("DeltaE"));
* Execute the algorithm wsValidator->add(new API::CommonBinsValidator<>);
*/ wsValidator->add(new API::HistogramValidator<>);
void SaveNXSPE::exec() {
using namespace Mantid::API; declareProperty(new WorkspaceProperty<MatrixWorkspace> ("InputWorkspace",
// Retrieve the input workspace "", Direction::Input, wsValidator),
const MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); "Name of the workspace to be saved.");
}
// Do the full check for common binning
if (!WorkspaceHelpers::commonBoundaries(inputWS)) { /**
g_log.error("The input workspace must have common bins"); * Execute the algorithm
throw std::invalid_argument("The input workspace must have common bins"); */
} void
SaveNXSPE::exec()
const int nHist = inputWS->getNumberHistograms(); {
this->nBins = inputWS->blocksize(); using namespace Mantid::API;
// Retrieve the filename from the properties // Constant for converting Radians to Degrees
this->filename = getPropertyValue("Filename"); const double rad2deg = 180.0 / M_PI;
// Create the file. // Retrieve the input workspace
::NeXus::File nxFile(this->filename, NXACC_CREATE5); const MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
// Make the top level entry (and open it) // Do the full check for common binning
nxFile.makeGroup(inputWS->getName(), "NXentry", true); if (!WorkspaceHelpers::commonBoundaries(inputWS))
{
// Create NXSPE_info g_log.error("The input workspace must have common bins");
nxFile.makeGroup("NXSPE_info", "NXcollection", true); throw std::invalid_argument(
"The input workspace must have common bins");
//TODO: Get and write Ei as "fixed_energy" }
//TODO: Get and write psi as "psi"
//TODO: Get and write ki/kf as "ki_over_kf_scaling" = 1/0 // Number of spectra
const int nHist = inputWS->getNumberHistograms();
nxFile.closeGroup(); // NXSPE_info // Number of energy bins
this->nBins = inputWS->blocksize();
// NXinstrument
nxFile.makeGroup("instrument", "NXinstrument", true); // Get a pointer to the sample
Geometry::IObjComponent_const_sptr sample = inputWS->getInstrument()->getSample();
// NXfermi_chopper
nxFile.makeGroup("fermi", "NXfermi_chopper", true); // Retrieve the filename from the properties
//TODO: Get and write Ei as "fixed_energy" this->filename = getPropertyValue("Filename");
nxFile.closeGroup(); // NXfermi_chopper
// Create the file.
nxFile.closeGroup(); // NXinstrument ::NeXus::File nxFile(this->filename, NXACC_CREATE5);
// NXsample // Make the top level entry (and open it)
nxFile.makeGroup("sample", "NXsample", true); nxFile.makeGroup(inputWS->getName(), "NXentry", true);
// TODO: Write sample info
nxFile.closeGroup(); // NXsample // Definition name and version
nxFile.writeData("definition", "NXSPE");
// Energy bins nxFile.openData("definition");
// Get the Energy Axis (X) of the first spectra (they are all the same - checked above) // Make Version 1.0 as we don't have all the metadata yet!
const MantidVec& X = inputWS->readX(0); nxFile.putAttr("version", "1.0");
nxFile.writeData("energy", X); nxFile.closeData();
// TODO: Data Array // Program name and version
// TODO: Error Array nxFile.writeData("program_name", "mantid");
// Polar Angles nxFile.openData("program_name");
// Polar Angle Width // TODO: Get the correct version number
// Azimuthal Angle nxFile.putAttr("version", "1.1");
// Azimuthal Angle Width nxFile.closeData();
nxFile.closeGroup(); // Top level NXentry // Create NXSPE_info
} nxFile.makeGroup("NXSPE_info", "NXcollection", true);
} // namespace NeXus //TODO: Get and write Ei as "fixed_energy"
//TODO: Get and write psi as "psi"
//TODO: Get and write ki/kf as "ki_over_kf_scaling" = 1/0
nxFile.closeGroup(); // NXSPE_info
// NXinstrument
nxFile.makeGroup("instrument", "NXinstrument", true);
// Write the instrument name
nxFile.writeData("name", inputWS->getInstrument()->getName());
// and the short name
nxFile.openData("name");
// TODO: Get the instrument short name
nxFile.putAttr("short_name", inputWS->getInstrument()->getName());
nxFile.closeData();
// NXfermi_chopper
nxFile.makeGroup("fermi", "NXfermi_chopper", true);
//TODO: Get and write Ei as "fixed_energy"
nxFile.closeGroup(); // NXfermi_chopper
nxFile.closeGroup(); // NXinstrument
// NXsample
nxFile.makeGroup("sample", "NXsample", true);
// TODO: Write sample info
nxFile.closeGroup(); // NXsample
// Make the NXdata group
nxFile.makeGroup("data", "NXdata", true);
// Energy bins
// Get the Energy Axis (X) of the first spectra (they are all the same - checked above)
const MantidVec& X = inputWS->readX(0);
nxFile.writeData("energy", X);
nxFile.openData("energy");
nxFile.putAttr("units", "meV");
nxFile.closeData();
// let's create some blank arrays in the nexus file
std::vector<double> azimuthal;
std::vector<double> polar;
std::vector<double> azimuthal_width;
std::vector<double> polar_width;
double delta_polar = 0.0;
double delta_azimuthal = 0.0;
double distance = 0.0;
std::vector<int> array_dims;
array_dims.push_back(nHist);
array_dims.push_back(nBins);
nxFile.makeData("data", ::NeXus::FLOAT64, array_dims, false);
nxFile.makeData("error", ::NeXus::FLOAT64, array_dims, false);
std::vector<int> slab_start;
std::vector<int> slab_size;
// What size slabs are we going to write...
slab_size.push_back(1);
slab_size.push_back(nBins);
// And let's start at the beginning
slab_start.push_back(0);
slab_start.push_back(0);
// Loop over spectra
for (size_t i = 0; i < static_cast<size_t> (nHist); i++)
{
// Check that we aren't writing a monitor...
if (!inputWS->getDetector(i)->isMonitor())
{
Geometry::IDetector_sptr det = inputWS->getDetector(i);
polar.push_back(inputWS->detectorTwoTheta(det) * rad2deg);
azimuthal.push_back(inputWS->getDetector(i)->getPhi() * rad2deg);
// Get Sample->Detector distance
distance = det->getDistance(*sample);
// Now let's work out the detector widths
// TODO: This is the historically wrong method...update it!
// Initialise to large values
double xmin = -1000.0;
double xmax = 1000.0;
double ymin = -1000.0;
double ymax = 1000.0;
double zmin = -1000.0;
double zmax = 1000.0;
// Get the bounding box
det->getBoundingBox(xmax, ymax, zmax, xmin, ymin, zmin);
double xsize = xmax - xmin;
double ysize = ymax - ymin;
delta_polar = atan2((ysize / 2.0), distance) * rad2deg;
delta_azimuthal = atan2((xsize / 2.0), distance) * rad2deg;
// Now write the widths...
polar_width.push_back(delta_polar);
azimuthal_width.push_back(delta_azimuthal);
if (!inputWS->getDetector(i)->isMasked())
{
// no masking...
// Open the data
nxFile.openData("data");
slab_start[0] = i;
nxFile.putSlab(const_cast<MantidVec&> (inputWS->readY(i)),
slab_start, slab_size);
// Close the data
nxFile.closeData();
// Open the error
nxFile.openData("error");
nxFile.putSlab(const_cast<MantidVec&> (inputWS->readE(i)),
slab_start, slab_size);
// Close the error
nxFile.closeData();
}
else
{
// Write a masked value...
}
}
}
// Write the Polar (2Theta) angles
nxFile.writeData("polar", polar);
// Write the Azimuthal (phi) angles
nxFile.writeData("azimuthal", azimuthal);
// Now the widths...
nxFile.writeData("polar_width", polar_width);
nxFile.writeData("azimuthal_width", azimuthal_width);
nxFile.closeGroup(); // NXdata
nxFile.closeGroup(); // Top level NXentry
}
} // namespace NeXus
} // namespace Mantid } // namespace Mantid
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment