Newer
Older
Ronald Fowler
committed
// SaveNexusProcessed
// @author Ronald Fowler, based on SaveNexus
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidNexus/SaveNexusProcessed.h"
#include "MantidDataObjects/Workspace1D.h"
#include "MantidDataObjects/Workspace2D.h"
Ronald Fowler
committed
#include "MantidNexus/NexusFileIO.h"
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/ConfigService.h"
Ronald Fowler
committed
Gigg, Martyn Anthony
committed
#include "Poco/File.h"
Gigg, Martyn Anthony
committed
#include "Poco/Path.h"
Ronald Fowler
committed
#include <cmath>
#include <boost/shared_ptr.hpp>
namespace Mantid
{
namespace NeXus
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(SaveNexusProcessed)
using namespace Kernel;
using namespace API;
using namespace DataObjects;
Logger& SaveNexusProcessed::g_log = Logger::get("SaveNexusProcessed");
/// Empty default constructor
Laurent Chapon
committed
SaveNexusProcessed::SaveNexusProcessed():Algorithm()
Ronald Fowler
committed
{
}
/** Initialisation method.
*
*/
void SaveNexusProcessed::init()
{
Roman Tolchenov
committed
declareProperty(new WorkspaceProperty<MatrixWorkspace>("InputWorkspace","",Direction::Input));
Ronald Fowler
committed
// Declare required input parameters for algorithm
std::vector<std::string> exts;
exts.push_back("NXS");
exts.push_back("nxs");
exts.push_back("nx5");
exts.push_back("NX5");
Ronald Fowler
committed
exts.push_back("xml");
exts.push_back("XML");
declareProperty("FileName","",new FileValidator(exts,false));
Russell Taylor
committed
//declareProperty("FileName","",new MandatoryValidator<std::string>);
Ronald Fowler
committed
// Declare optional parameters (title now optional, was mandatory)
declareProperty("Title","",new NullValidator<std::string>);
BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
mustBePositive->setLower(0);
declareProperty("EntryNumber",0,mustBePositive);
declareProperty("spectrum_min",0, mustBePositive->clone());
declareProperty("spectrum_max",0, mustBePositive->clone());
declareProperty(new ArrayProperty<int>("spectrum_list"));
Ronald Fowler
committed
}
/** Executes the algorithm. Reading in the file and creating and populating
* the output workspace
*
* @throw runtime_error Thrown if algorithm cannot execute
*/
void SaveNexusProcessed::exec()
{
// Retrieve the filename from the properties
m_filename = getPropertyValue("FileName");
//m_entryname = getPropertyValue("EntryName");
Ronald Fowler
committed
m_title = getPropertyValue("Title");
m_inputWorkspace = getProperty("InputWorkspace");
Property *specList = getProperty("spectrum_list");
m_list = !(specList->isDefault());
Property *specMax = getProperty("spectrum_max");
m_interval = !(specMax->isDefault());
const std::string workspaceID = m_inputWorkspace->id();
Gigg, Martyn Anthony
committed
if (workspaceID.find("Workspace2D") == std::string::npos )
throw Exception::NotImplementedError("SaveNexusProcessed passed invalid workspaces.");
Ronald Fowler
committed
NexusFileIO *nexusFile= new NexusFileIO();
if( nexusFile->openNexusWrite( m_filename ) != 0 )
{
g_log.error("Failed to open file");
throw Exception::FileError("Failed to open file", m_filename);
}
if( nexusFile->writeNexusProcessedHeader( m_title ) != 0 )
Ronald Fowler
committed
{
g_log.error("Failed to write file");
throw Exception::FileError("Failed to write to file", m_filename);
}
Roman Tolchenov
committed
// write instrument data, if present and writer enabled
boost::shared_ptr<IInstrument> instrument = m_inputWorkspace->getInstrument();
nexusFile->writeNexusInstrument(instrument);
Ronald Fowler
committed
// write XML source file name, if it exists - otherwise write "NoNameAvailable"
std::string instrumentName=instrument->getName();
if(instrumentName != "")
Ronald Fowler
committed
{
std::string inst3Char = instrumentName.substr(0,3); // get the first 3 letters of the name
// force ID to upper case
std::transform(inst3Char.begin(), inst3Char.end(), inst3Char.begin(), toupper);
Matt Clarke
committed
std::string instrumentXml(inst3Char+"_Definition.xml");
// Determine the search directory for XML instrument definition files (IDFs)
std::string directoryName = Kernel::ConfigService::Instance().getString("instrumentDefinition.directory");
Gigg, Martyn Anthony
committed
if ( directoryName.empty() )
{
// This is the assumed deployment directory for IDFs, where we need to be relative to the
// directory of the executable, not the current working directory.
Gigg, Martyn Anthony
committed
directoryName = Poco::Path(Mantid::Kernel::ConfigService::Instance().getBaseDir()).resolve("../Instrument").toString();
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Poco::File file(directoryName+"/"+instrumentXml);
if(!file.exists())
instrumentXml="NoXmlFileFound";
std::string version("1"); // these should be read from xml file
std::string date("20081031");
nexusFile->writeNexusInstrumentXmlName(instrumentXml,date,version);
Ronald Fowler
committed
}
else
nexusFile->writeNexusInstrumentXmlName("NoNameAvailable","","");
Ronald Fowler
committed
boost::shared_ptr<Mantid::API::Sample> sample=m_inputWorkspace->getSample();
if( nexusFile->writeNexusProcessedSample( sample->getName(), sample) != 0 )
Ronald Fowler
committed
{
g_log.error("Failed to write NXsample");
throw Exception::FileError("Failed to write NXsample", m_filename);
Ronald Fowler
committed
}
const Workspace2D_sptr localworkspace = boost::dynamic_pointer_cast<Workspace2D>(m_inputWorkspace);
const int numberOfHist = localworkspace->getNumberHistograms();
// check if all X() are in fact the same array
bool uniformSpectra= API::WorkspaceHelpers::commonBoundaries(localworkspace);
Russell Taylor
committed
m_spec_min=0;
m_spec_max=numberOfHist-1;
Russell Taylor
committed
if( m_interval )
Ronald Fowler
committed
{
Russell Taylor
committed
m_spec_min = getProperty("spectrum_min");
m_spec_max = getProperty("spectrum_max");
if ( m_spec_max < m_spec_min || m_spec_max > numberOfHist-1 )
{
g_log.error("Invalid Spectrum min/max properties");
throw std::invalid_argument("Inconsistent properties defined");
}
Ronald Fowler
committed
}
nexusFile->writeNexusProcessedData(localworkspace,uniformSpectra,m_spec_min,m_spec_max);
nexusFile->writeNexusProcessedProcess(localworkspace);
Russell Taylor
committed
const SpectraDetectorMap& spectraMap=localworkspace->spectraMap();
Ronald Fowler
committed
nexusFile->writeNexusProcessedSpectraMap(spectraMap, m_spec_min, m_spec_max);
Russell Taylor
committed
nexusFile->closeNexusFile();
Ronald Fowler
committed
return;
}
} // namespace NeXus
} // namespace Mantid