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
Steve Williams
committed
SaveNexusProcessed::SaveNexusProcessed() :
Algorithm(),
m_spec_list(), m_spec_max(unSetInt)
Ronald Fowler
committed
{
}
/** Initialisation method.
*
*/
void SaveNexusProcessed::init()
{
Steve Williams
committed
declareProperty(new WorkspaceProperty<MatrixWorkspace>("InputWorkspace","",Direction::Input),
"Name of the workspace to be saved");
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");
Steve Williams
committed
declareProperty("FileName","",new FileValidator(exts,false),
"The name of the Nexus file to write, as a full or relative\n"
"path");
Ronald Fowler
committed
// Declare optional parameters (title now optional, was mandatory)
Steve Williams
committed
declareProperty("Title", "", new NullValidator<std::string>,
"A title to describe the saved workspace");
BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
mustBePositive->setLower(0);
Steve Williams
committed
declareProperty("spectrum_min", 0, mustBePositive->clone(),
"Index number of first spectrum to read, only for single\n"
"period data. Not yet implemented");
declareProperty("spectrum_max", unSetInt, mustBePositive->clone(),
"Index of last spectrum to read, only for single period\n"
"data. Not yet implemented");
declareProperty(new ArrayProperty<int>("spectrum_list"),
"List of spectrum numbers to read, only for single period\n"
"data. Not yet implemented");
declareProperty("EntryNumber", 0, mustBePositive);
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");
Steve Williams
committed
m_spec_list = getProperty("spectrum_list");
m_spec_max = getProperty("spectrum_max");
m_list = !m_spec_list.empty();
m_interval = (m_spec_max != unSetInt);
if ( m_spec_max == unSetInt ) m_spec_max = 0;
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
Roman Tolchenov
committed
nexusFile->writeNexusParameterMap(m_inputWorkspace);
// 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