Newer
Older
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/WorkspaceProperty.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidDataHandling/LoadSavuTomoConfig.h"
#include "MantidKernel/PropertyWithValue.h"
Federico Montesino Pouzols
committed
#include <nexus/NeXusException.hpp>
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the algorithm factory
using namespace Mantid::API;
* Standard Initialisation method. Declares properties.
*/
void LoadSavuTomoConfig::init() {
// Required input properties
const std::vector<std::string> exts{".nxs", ".nx5", ".xml"};
Kernel::make_unique<FileProperty>("Filename", "", FileProperty::Load,
exts),
"The name of the Nexus parameterization file to read, as a full "
"or relative path.");
declareProperty(Kernel::make_unique<WorkspaceProperty<ITableWorkspace>>(
"OutputWorkspace", "savuTomoConfig",
Kernel::Direction::Output, PropertyMode::Mandatory),
"The name of the workspace to be created as output of "
"the algorithm, a workspace with this name will be created "
"and stored in the Analysis Data Service.");
}
* Executes the algorithm: reads in the parameters file and creates
* and fills the output workspace
*
* @throw runtime_error Thrown if execution fails
*/
void LoadSavuTomoConfig::exec() {
progress(0, "Opening file...");
Federico Montesino Pouzols
committed
// Will throw an approriate exception if there is a problem with the
// properties
std::string fname = getPropertyValue("Filename");
std::string wsName = getPropertyValue("OutputWorkspace");
Federico Montesino Pouzols
committed
ITableWorkspace_sptr ws;
try {
// Do the real load. Throws exception if issues found
if (ws) {
setProperty("OutputWorkspace", ws);
}
g_log.error() << "Failed to load savu tomography reconstruction "
Federico Montesino Pouzols
committed
return;
}
progress(1.0, "Loading finished.");
}
Federico Montesino Pouzols
committed
/**
* Can it be openend in the expected format, and does it seem to have
* sensible contents?
*
* @param fname name of file
* @param f nexus file object, created if file is fine
*
* @return true if everything seems fine, false otherwise
*/
bool LoadSavuTomoConfig::checkOpenFile(std::string fname,
boost::shared_ptr<NeXus::File> &f) {
Federico Montesino Pouzols
committed
try {
f = boost::make_shared<NeXus::File>(fname);
Federico Montesino Pouzols
committed
if (f)
f->getEntries();
} catch (NeXus::Exception &e) {
Federico Montesino Pouzols
committed
g_log.error() << "Failed to open as a NeXus file: '" << fname
<< "', error description: " << e.what() << '\n';
Federico Montesino Pouzols
committed
return false;
}
return true;
}
/**
* Loads a tomography parameterization file into a newly created table
Federico Montesino Pouzols
committed
* workspace. The file must have the following syntax:
Federico Montesino Pouzols
committed
*
Federico Montesino Pouzols
committed
* @verbatim
<NXentry name="entry1">
<NXprocess name="processing">
<NXnote name="id">
<values id="ID VALUE" params="..." name="..." cite="...">
</values>
</NXnote>
</NXprocess>
</NXentry>
@endverbatim
*
Federico Montesino Pouzols
committed
* @param fname name of the parameterization file
* @param wsName name of workspace where to load the file data
*
* @return table workspace with parameters (plugins) found in the
* loaded file
*/
ITableWorkspace_sptr LoadSavuTomoConfig::loadFile(std::string &fname,
std::string &wsName) {
Federico Montesino Pouzols
committed
// Throws an exception if there is a problem with file access
// Mantid::NeXus::NXRoot root(fname);
boost::shared_ptr<NeXus::File> f;
Federico Montesino Pouzols
committed
if (!checkOpenFile(fname, f)) {
throw std::runtime_error(
"Failed to recognize this file as a NeXus file, cannot continue.");
}
ITableWorkspace_sptr ws = API::WorkspaceFactory::Instance().createTable();
Federico Montesino Pouzols
committed
if (!ws)
throw std::runtime_error("Could not create TableWorkspace for "
"workspace with name '" +
wsName + "'");
Federico Montesino Pouzols
committed
// init workspace
ws->setTitle("Table with tomography parameters from file " + fname);
Federico Montesino Pouzols
committed
ws->addColumn("str", "ID");
ws->addColumn("str", "Parameters");
Federico Montesino Pouzols
committed
ws->addColumn("str", "Name");
ws->addColumn("str", "Cite");
// a bit of file consistency check, check at least there's a
// 'entry1'
// it could be more strict and demand entries.size()==1
std::map<std::string, std::string> entries = f->getEntries();
std::string mainEntryName = "entry";
auto it = entries.find(mainEntryName);
Federico Montesino Pouzols
committed
if (entries.end() == it) {
throw std::runtime_error(
"Could not find the '" + mainEntryName +
"' "
"entry. Even though this file looks like a valid NeXus file, it is "
"not in the correct format for tomography reconstruction "
"parameterization files.");
Federico Montesino Pouzols
committed
}
// go through the input file plugin entries
f->openGroup(mainEntryName, "NXentry");
f->openGroup("process", "NXprocess");
Federico Montesino Pouzols
committed
size_t pluginsLen = f->getEntries().size();
for (size_t j = 0; j < pluginsLen; j++) {
Federico Montesino Pouzols
committed
API::TableRow table = ws->appendRow();
std::string entryIdx = std::to_string(j);
Federico Montesino Pouzols
committed
try {
f->openGroup(entryIdx, "NXnote");
Federico Montesino Pouzols
committed
// detailed NeXus error message and throw...
g_log.error() << "Failed to load plugin '" << j
<< "' from"
throw std::runtime_error(
"Could not load one or more plugin "
"entries from the tomographic reconstruction parameterization "
"file. Please check that the file is correct.");
Federico Montesino Pouzols
committed
}
// TODO: check final 'schema', get these 4 fields from the file
std::string id = "";
std::string params = "";
std::string name = "";
std::string cite = "";
try {
f->readData("data", params);
f->readData("id", id);
f->readData("name", name);
// cite not available for now
// f->readData("cite", cite);
// This might be extended to an NXcite group that would be included
// not here but inside an "intermediate" NXcollection group. That
// NXcite would have 4 arrays: description, doi, endnote, bibtex.
// But this is what we have so far.
cite = "Not available";
Federico Montesino Pouzols
committed
// permissive, just error message but carry on
g_log.warning()
<< "Failed to read some fields in tomographic "
"reconstruction plugin line. The file seems to be wrong. Error "
Federico Montesino Pouzols
committed
}
table << id << params << name << cite;
f->closeGroup();
progress(static_cast<double>(j) / static_cast<double>(pluginsLen));
Federico Montesino Pouzols
committed
}
f->close();
return ws;
}
} // namespace DataHandling
} // namespace Mantid