Newer
Older
Ronald Fowler
committed
// SaveNexusProcessed
// @author Ronald Fowler, based on SaveNexus
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidNexus/SaveNexusProcessed.h"
Ronald Fowler
committed
#include "MantidNexus/NexusFileIO.h"
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/ConfigService.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/FileProperty.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;
/// 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("nx5");
Ronald Fowler
committed
exts.push_back("xml");
Gigg, Martyn Anthony
committed
declareProperty(new FileProperty("Filename", "", FileProperty::Save, exts),
"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);
declareProperty("WorkspaceIndexMin", 0, mustBePositive->clone(),
Steve Williams
committed
"Index number of first spectrum to read, only for single\n"
"period data. Not yet implemented");
declareProperty("WorkspaceIndexMax", unSetInt, mustBePositive->clone(),
Steve Williams
committed
"Index of last spectrum to read, only for single period\n"
"data. Not yet implemented");
declareProperty(new ArrayProperty<int>("WorkspaceIndexList"),
Steve Williams
committed
"List of spectrum numbers to read, only for single period\n"
"data. Not yet implemented");
Sofia Antony
committed
//declareProperty("EntryNumber", 0, mustBePositive);
declareProperty("Append",false,"Determines whether .nxs file needs to be\n"
"over written or appended");
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
Gigg, Martyn Anthony
committed
m_filename = getPropertyValue("Filename");
//m_entryname = getPropertyValue("EntryName");
Ronald Fowler
committed
m_title = getPropertyValue("Title");
m_inputWorkspace = getProperty("InputWorkspace");
Gigg, Martyn Anthony
committed
// If no title's been given, use the workspace title field
Russell Taylor
committed
if (m_title.empty()) m_title = m_inputWorkspace->getTitle();
Gigg, Martyn Anthony
committed
// If we don't want to append then remove the file if it already exists
bool append_to_file = getProperty("Append");
if( !append_to_file )
{
Poco::File file(m_filename);
if( file.exists() )
{
file.remove();
}
}
m_spec_list = getProperty("WorkspaceIndexList");
m_spec_max = getProperty("WorkspaceIndexMax");
Steve Williams
committed
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.");
Sofia Antony
committed
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);
}
Sofia Antony
committed
progress(0.2);
Sofia Antony
committed
if( nexusFile->writeNexusProcessedHeader( m_title ) != 0 )
{
g_log.error("Failed to write file");
throw Exception::FileError("Failed to write to file", m_filename);
}
Ronald Fowler
committed
Sofia Antony
committed
progress(0.3);
Roman Tolchenov
committed
// write instrument data, if present and writer enabled
IInstrument_const_sptr instrument = m_inputWorkspace->getInstrument();
nexusFile->writeNexusInstrument(instrument);
Sofia Antony
committed
Roman Tolchenov
committed
nexusFile->writeNexusParameterMap(m_inputWorkspace);
Sofia Antony
committed
progress(0.5);
// write XML source file name, if it exists - otherwise write "NoNameAvailable"
std::string instrumentName=instrument->getName();
if(instrumentName != "")
Ronald Fowler
committed
{
// force ID to upper case
std::transform(instrumentName.begin(), instrumentName.end(), instrumentName.begin(), toupper);
std::string instrumentXml(instrumentName+"_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.
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
Sofia Antony
committed
progress(0.7);
Sofia Antony
committed
// boost::shared_ptr<Mantid::API::Sample> sample=m_inputWorkspace->getSample();
if( nexusFile->writeNexusProcessedSample(m_inputWorkspace->sample().getName(), m_inputWorkspace->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 int numberOfHist = m_inputWorkspace->getNumberHistograms();
// check if all X() are in fact the same array
bool uniformSpectra= API::WorkspaceHelpers::commonBoundaries(m_inputWorkspace);
Roman Tolchenov
committed
std::vector<int> spec;
Russell Taylor
committed
if( m_interval )
Ronald Fowler
committed
{
m_spec_min = getProperty("WorkspaceIndexMin");
m_spec_max = getProperty("WorkspaceIndexMax");
Russell Taylor
committed
if ( m_spec_max < m_spec_min || m_spec_max > numberOfHist-1 )
{
g_log.error("Invalid WorkspaceIndex min/max properties");
Russell Taylor
committed
throw std::invalid_argument("Inconsistent properties defined");
}
Roman Tolchenov
committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
for(int i=m_spec_min;i<=m_spec_max;i++)
spec.push_back(i);
if (m_list)
{
for(size_t i=0;i<m_spec_list.size();i++)
{
int s = m_spec_list[i];
if ( s < 0 ) continue;
if (s < m_spec_min || s > m_spec_max)
spec.push_back(s);
}
}
}
else if (m_list)
{
m_spec_max=0;
m_spec_min=numberOfHist-1;
for(size_t i=0;i<m_spec_list.size();i++)
{
int s = m_spec_list[i];
if ( s < 0 ) continue;
spec.push_back(s);
if (s > m_spec_max) m_spec_max = s;
if (s < m_spec_min) m_spec_min = s;
}
}
else
{
m_spec_min=0;
m_spec_max=numberOfHist-1;
Roman Tolchenov
committed
for(int i=m_spec_min;i<=m_spec_max;i++)
spec.push_back(i);
Ronald Fowler
committed
}
Roman Tolchenov
committed
nexusFile->writeNexusProcessedData(m_inputWorkspace,uniformSpectra,spec);
nexusFile->writeNexusProcessedProcess(m_inputWorkspace);
Roman Tolchenov
committed
nexusFile->writeNexusProcessedSpectraMap(m_inputWorkspace, spec);
Russell Taylor
committed
nexusFile->closeNexusFile();
Sofia Antony
committed
progress(1.0);
delete nexusFile;
Ronald Fowler
committed
return;
}
Sofia Antony
committed
/** virtual method to set the non workspace properties for this algorithm
* @param alg pointer to the algorithm
* @param propertyName name of the property
* @param propertyValue value of the property
* @param perioidNum period number
*/
void SaveNexusProcessed::setOtherProperties(IAlgorithm* alg,const std::string& propertyName,const std::string& propertyValue,int perioidNum)
{
if(!propertyName.compare("Append"))
{ if(perioidNum!=1)
{ alg->setPropertyValue(propertyName,"1");
}
else alg->setPropertyValue(propertyName,propertyValue);
}
else
Algorithm::setOtherProperties(alg,propertyName,propertyValue,perioidNum);
Sofia Antony
committed
}
Ronald Fowler
committed
} // namespace NeXus
} // namespace Mantid