Newer
Older
Janik Zikovsky
committed
/*WIKI*
The algorithm SaveNexus will write a Nexus data file from the named workspace.
The file name can be an absolute or relative path and should have the extension
.nxs, .nx5 or .xml.
Warning - using XML format can be extremely slow for large data sets and generate very large files.
Both the extensions nxs and nx5 will generate HDF5 files.
The optional parameters can be used to control which spectra are saved into the file (not yet implemented).
If spectrum_min and spectrum_max are given, then only that range to data will be loaded.
A Mantid Nexus file may contain several workspace entries each labelled with an integer starting at 1.
If the file already contains n workspaces, the new one will be labelled n+1.
In the future it may be possible to write other Nexus file types than the one supported by SaveNexusProcessed.
===Time series data===
TimeSeriesProperty data within the workspace will be saved as NXlog sections in the Nexus file.
Only floating point logs are stored and loaded at present.
Janik Zikovsky
committed
[[SaveNexusProcessed]]
*WIKI*/
// SaveNeXus
// @author Freddie Akeroyd, STFC ISIS Faility
// @author Ronald Fowler, STFC eScience. Modified to fit with SaveNexusProcessed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/SaveNexus.h"
#include "MantidDataObjects/Workspace2D.h"
Ronald Fowler
committed
#include "MantidKernel/ArrayProperty.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
#include "MantidKernel/BoundedValidator.h"
#include <cmath>
#include <boost/shared_ptr.hpp>
namespace Mantid
{
namespace DataHandling
Russell Taylor
committed
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(SaveNexus)
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void SaveNexus::initDocs()
{
this->setWikiSummary("The SaveNexus algorithm will write the given Mantid workspace to a NeXus file. SaveNexus currently just invokes [[SaveNexusProcessed]]. ");
this->setOptionalMessage("The SaveNexus algorithm will write the given Mantid workspace to a NeXus file. SaveNexus currently just invokes SaveNexusProcessed.");
Janik Zikovsky
committed
}
Russell Taylor
committed
using namespace Kernel;
using namespace API;
using namespace DataObjects;
Russell Taylor
committed
/// Empty default constructor
SaveNexus::SaveNexus() : Algorithm() {}
Russell Taylor
committed
/** Initialisation method.
*
*/
void SaveNexus::init()
{
Gigg, Martyn Anthony
committed
// Declare required parameters, filename with ext {.nx,.nx5,xml} and input workspac
declareProperty(new WorkspaceProperty<Workspace> ("InputWorkspace", "", Direction::Input),
"Name of the workspace to be saved");
Russell Taylor
committed
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");
Russell Taylor
committed
//
// Declare optional input parameters
// These are:
// Title - string to describe data
// EntryNumber - integer >0 to be used in entry name "mantid_workspace_<n>"
// Within a file the entries will be sequential from 1.
// This option should allow overwrite of existing entry,
// *not* addition of out-of-sequence entry numbers.
// spectrum_min, spectrum_max - range of "spectra" numbers to write
// spectrum_list list of spectra values to write
//
declareProperty("Title", "", boost::make_shared<NullValidator>() ,
Russell Taylor
committed
"A title to describe the saved workspace");
auto mustBePositive = boost::make_shared<BoundedValidator<int> >();
Russell Taylor
committed
mustBePositive->setLower(0);
// declareProperty("EntryNumber", Mantid::EMPTY_INT(), mustBePositive,
Russell Taylor
committed
// "(Not implemented yet) The index number of the workspace within the Nexus file\n"
// "(default leave unchanged)" );
declareProperty("WorkspaceIndexMin", 0, mustBePositive,
"Number of first WorkspaceIndex to read, only for single period data.\n"
Russell Taylor
committed
"Not yet implemented");
declareProperty("WorkspaceIndexMax", Mantid::EMPTY_INT(), mustBePositive,
"Number of last WorkspaceIndex to read, only for single period data.\n"
Russell Taylor
committed
"Not yet implemented.");
declareProperty(new ArrayProperty<int> ("WorkspaceIndexList"),
"List of WorkspaceIndex numbers to read, only for single period data.\n"
Russell Taylor
committed
"Not yet implemented");
declareProperty("Append", false, "Determines whether .nxs file needs to be\n"
"over written or appended");
// option which might be required in future - should be a choice e.g. MantidProcessed/Muon1
// declareProperty("Filetype","",new NullValidator<std::string>);
}
Russell Taylor
committed
Russell Taylor
committed
/** Execute the algorithm. Currently just calls SaveNexusProcessed but could
* call write other formats if support added
*
* @throw runtime_error Thrown if algorithm cannot execute
*/
void SaveNexus::exec()
{
// Retrieve the filename from the properties
m_filename = getPropertyValue("FileName");
m_inputWorkspace = getProperty("InputWorkspace");
Russell Taylor
committed
//retrieve the append property
Sofia Antony
committed
bool bAppend = getProperty("Append");
// if bAppend is default (false) overwrite (delete )the .nxs file
if (!bAppend)
{
Poco::File file(m_filename);
if (file.exists())
{ file.remove();
}
Russell Taylor
committed
}
Sofia Antony
committed
Russell Taylor
committed
m_filetype = "NexusProcessed";
Russell Taylor
committed
if (m_filetype == "NexusProcessed")
{
runSaveNexusProcessed();
}
else
{
throw Exception::NotImplementedError("SaveNexus passed invalid filetype.");
Russell Taylor
committed
return;
}
Sofia Antony
committed
/** virtual method to set the non workspace properties for this algorithm
Janik Zikovsky
committed
* @param alg :: pointer to the algorithm
* @param propertyName :: name of the property
* @param propertyValue :: value of the property
* @param perioidNum :: period number
Sofia Antony
committed
*/
void SaveNexus::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
}
Russell Taylor
committed
void SaveNexus::runSaveNexusProcessed()
{
IAlgorithm_sptr saveNexusPro = createChildAlgorithm("SaveNexusProcessed", 0.0, 1.0, true);
Russell Taylor
committed
// Pass through the same output filename
saveNexusPro->setPropertyValue("Filename", m_filename);
// Set the workspace property
std::string inputWorkspace = "InputWorkspace";
saveNexusPro->setProperty(inputWorkspace, m_inputWorkspace);
Russell Taylor
committed
//
std::vector<int> specList = getProperty("WorkspaceIndexList");
Russell Taylor
committed
if (!specList.empty())
saveNexusPro->setPropertyValue("WorkspaceIndexList", getPropertyValue("WorkspaceIndexList"));
Russell Taylor
committed
//
int specMax = getProperty("WorkspaceIndexMax");
if (specMax != Mantid::EMPTY_INT())
Ronald Fowler
committed
{
saveNexusPro->setPropertyValue("WorkspaceIndexMax", getPropertyValue("WorkspaceIndexMax"));
saveNexusPro->setPropertyValue("WorkspaceIndexMin", getPropertyValue("WorkspaceIndexMin"));
Russell Taylor
committed
}
std::string title = getProperty("Title");
if (!title.empty())
saveNexusPro->setPropertyValue("Title", getPropertyValue("Title"));
Sofia Antony
committed
Russell Taylor
committed
// Pass through the append property
saveNexusPro->setProperty<bool>("Append",getProperty("Append"));
// If we're tracking history, add the entry before we save it to file
if (trackingHistory())
{
m_history->setExecCount(Algorithm::g_execCount);
if (!isChild())
{
m_inputWorkspace->history().addHistory(m_history);
}
//this is a child algorithm, but we still want to keep the history.
else if (isRecordingHistoryForChild() && m_parentHistory)
{
m_parentHistory->addChildHistory(m_history);
}
}
// Now execute the Child Algorithm. Catch and log any error, but don't stop.
Russell Taylor
committed
try
{
saveNexusPro->execute();
} catch (std::runtime_error&)
{
g_log.error("Unable to successfully run SaveNexusprocessed Child Algorithm");
Ronald Fowler
committed
}
Russell Taylor
committed
if (!saveNexusPro->isExecuted())
g_log.error("Unable to successfully run SaveNexusProcessed Child Algorithm");
Russell Taylor
committed
//
progress(1);
}
} // namespace DataHandling
} // namespace Mantid