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 "MantidAPI/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>
Gigg, Martyn Anthony
committed
Ronald Fowler
committed
namespace Mantid
{
namespace NeXus
{
Gigg, Martyn Anthony
committed
using namespace Kernel;
using namespace API;
Janik Zikovsky
committed
using namespace DataObjects;
Gigg, Martyn Anthony
committed
using Geometry::IInstrument_const_sptr;
Ronald Fowler
committed
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(SaveNexusProcessed)
/// Empty default constructor
Steve Williams
committed
SaveNexusProcessed::SaveNexusProcessed() :
Algorithm(),
m_spec_list(), m_spec_max(Mantid::EMPTY_INT())
Ronald Fowler
committed
{
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
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;
Peterson, Peter
committed
exts.push_back(".nxs");
exts.push_back(".nx5");
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(),
"Index number of first spectrum to write, only for single\n"
"period data. Not yet implemented");
declareProperty("WorkspaceIndexMax", Mantid::EMPTY_INT(), mustBePositive->clone(),
"Index of last spectrum to write, only for single period\n"
"data. Not yet implemented");
declareProperty(new ArrayProperty<int>("WorkspaceIndexList"),
"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
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
/** Executes the algorithm.
Ronald Fowler
committed
*
* @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");
Janik Zikovsky
committed
m_eventWorkspace = boost::dynamic_pointer_cast<const EventWorkspace>(m_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();
Gigg, Martyn Anthony
committed
}
}
m_spec_list = getProperty("WorkspaceIndexList");
m_spec_max = getProperty("WorkspaceIndexMax");
Steve Williams
committed
m_list = !m_spec_list.empty();
m_interval = (m_spec_max != Mantid::EMPTY_INT());
if ( m_spec_max == Mantid::EMPTY_INT() ) m_spec_max = 0;
Steve Williams
committed
const std::string workspaceID = m_inputWorkspace->id();
Janik Zikovsky
committed
if ((workspaceID.find("Workspace2D") == std::string::npos) &&
!m_eventWorkspace)
throw Exception::NotImplementedError("SaveNexusProcessed passed invalid workspaces. Must be Workspace2D or EventWorkspace.");
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);
}
progress(0.2);
if( nexusFile->writeNexusProcessedHeader( m_title ) != 0 )
{
g_log.error("Failed to write file");
throw Exception::FileError("Failed to write to file", m_filename);
}
Sofia Antony
committed
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);
Roman Tolchenov
committed
nexusFile->writeNexusParameterMap(m_inputWorkspace);
progress(0.5);
Sofia Antony
committed
// 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)
Gigg, Martyn Anthony
committed
std::string directoryName = Kernel::ConfigService::Instance().getInstrumentDirectory();
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);
Gigg, Martyn Anthony
committed
if( nexusFile->writeNexusProcessedSample(m_inputWorkspace->sample().getName(), m_inputWorkspace->sample(),
m_inputWorkspace->run()) != 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
for(int i=m_spec_min;i<=m_spec_max;i++)
spec.push_back(i);
Roman Tolchenov
committed
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)
Roman Tolchenov
committed
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;
}
Roman Tolchenov
committed
}
else
{
m_spec_min=0;
m_spec_max=numberOfHist-1;
spec.reserve(1+m_spec_max-m_spec_min);
for(int i=m_spec_min;i<=m_spec_max;i++)
spec.push_back(i);
Ronald Fowler
committed
}
Janik Zikovsky
committed
// Write out the data (2D or event)
if (m_eventWorkspace)
nexusFile->writeNexusProcessedDataEvent(m_eventWorkspace);
else
nexusFile->writeNexusProcessedData2D(m_inputWorkspace,uniformSpectra,spec);
nexusFile->writeNexusProcessedProcess(m_inputWorkspace);
Michael Whitty
committed
// MW 27/10/10 - don't try and save the spectra-detector map if there isn't one
if ( m_inputWorkspace->getAxis(1)->isSpectra() )
{
nexusFile->writeNexusProcessedSpectraMap(m_inputWorkspace, spec);
}
Russell Taylor
committed
nexusFile->closeNexusFile();
progress(1.0);
delete nexusFile;
Ronald Fowler
committed
return;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
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);
}
Ronald Fowler
committed
} // namespace NeXus
} // namespace Mantid