Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadRaw2.h"
Russell Taylor
committed
#include "MantidDataHandling/ManagedRawFileWorkspace2D.h"
Gigg, Martyn Anthony
committed
#include "MantidDataHandling/LoadRawHelper.h"
#include "MantidDataObjects/Workspace2D.h"
Gigg, Martyn Anthony
committed
#include "MantidGeometry/Instrument/XMLlogfile.h"
Russell Taylor
committed
#include "MantidAPI/MemoryManager.h"
#include "MantidAPI/SpectraDetectorMap.h"
Roman Tolchenov
committed
#include "MantidAPI/Progress.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/ArrayProperty.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
Anders Markvardsen
committed
#include "MantidKernel/TimeSeriesProperty.h"
#include "LoadRaw/isisraw2.h"
Sofia Antony
committed
#include "MantidDataHandling/LoadLog.h"
#include <boost/shared_ptr.hpp>
Russell Taylor
committed
#include <cmath>
#include <cstdio> //Required for gcc 4.4
#include "MantidDataHandling/LoadInstrumentHelper.h"
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadRaw2)
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void LoadRaw2::initDocs()
{
this->setWikiSummary("Loads a data file in ISIS [[RAW_File | RAW]] format and stores it in a 2D [[workspace]] ([[Workspace2D]] class). ");
this->setOptionalMessage("Loads a data file in ISIS RAW format and stores it in a 2D workspace (Workspace2D class).");
}
using namespace Kernel;
using namespace API;
/// Constructor
Algorithm(), isisRaw(new ISISRAW2), m_filename(), m_numberOfSpectra(0), m_numberOfPeriods(0),
m_list(false), m_interval(false), m_spec_list(), m_spec_min(0), m_spec_max(Mantid::EMPTY_INT())
Roman Tolchenov
committed
{}
LoadRaw2::~LoadRaw2()
Roman Tolchenov
committed
{}
/// Initialisation method.
void LoadRaw2::init()
{
Gigg, Martyn Anthony
committed
// Extension checking is not case sensitive
Gigg, Martyn Anthony
committed
// MG 20/07/09: I've had to change these extensions so that the native Windows file dialog can recognise
// the file types correctly
std::vector<std::string> exts;
Peterson, Peter
committed
exts.push_back(".raw");
exts.push_back(".s*");
exts.push_back(".add");
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
Gigg, Martyn Anthony
committed
"The name of the RAW file to read, including its full or relative\n"
"path. (N.B. case sensitive if running on Linux).");
declareProperty(new WorkspaceProperty<DataObjects::Workspace2D>("OutputWorkspace","",Direction::Output),
Gigg, Martyn Anthony
committed
"The name of the workspace that will be created, filled with the\n"
"read-in data and stored in the Analysis Data Service. If the input\n"
"RAW file contains multiple periods higher periods will be stored in\n"
"separate workspaces called OutputWorkspace_PeriodNo.");
BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
mustBePositive->setLower(1);
Gigg, Martyn Anthony
committed
declareProperty("SpectrumMin",1, mustBePositive, "The index number of the first spectrum to read. Only used if\n"
"spectrum_max is set.");
declareProperty("SpectrumMax",Mantid::EMPTY_INT(), mustBePositive->clone(), "The number of the last spectrum to read. Only used if explicitly\n"
Gigg, Martyn Anthony
committed
"set.");
declareProperty(new ArrayProperty<specid_t>("SpectrumList"), "A comma-separated list of individual spectra to read. Only used if\n"
Gigg, Martyn Anthony
committed
"explicitly set.");
m_cache_options.push_back("If Slow");
Roman Tolchenov
committed
m_cache_options.push_back("Always");
m_cache_options.push_back("Never");
declareProperty("Cache","If Slow",new ListValidator(m_cache_options));
Roman Tolchenov
committed
}
/** Executes the algorithm. Reading in the file and creating and populating
* the output workspace
* @throw Exception::FileError If the RAW file cannot be found/opened
* @throw std::invalid_argument If the optional properties are set to invalid values
*/
void LoadRaw2::exec()
{
// Retrieve the filename from the properties
m_filename = getPropertyValue("Filename");
Gigg, Martyn Anthony
committed
LoadRawHelper *helper = new LoadRawHelper;
FILE* file = helper->openRawFile(m_filename);
isisRaw->ioRAW(file, true);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
std::string title(isisRaw->r_title, 80);
g_log.information("**** Run title: "+ title + "***");
// Read in the number of spectra in the RAW file
m_numberOfSpectra = isisRaw->t_nsp1;
// Read the number of periods in this file
m_numberOfPeriods = isisRaw->t_nper;
// Read the number of time channels (i.e. bins) from the RAW file
Roman Tolchenov
committed
const int channelsPerSpectrum = isisRaw->t_ntc1;
Roman Tolchenov
committed
const int lengthIn = channelsPerSpectrum + 1;
Roman Tolchenov
committed
// Call private method to validate the optional parameters, if set
checkOptionalProperties();
Gigg, Martyn Anthony
committed
std::vector<Kernel::Property*> period1logProp;
Roman Tolchenov
committed
// Calculate the size of a workspace, given its number of periods & spectra to read
Roman Tolchenov
committed
if( m_interval || m_list)
{
if (m_interval)
{
Roman Tolchenov
committed
m_spec_max += 1;
}
else
total_specs = 0;
if (m_list)
{
if (m_interval)
{
for(std::vector<specid_t>::iterator it=m_spec_list.begin();it!=m_spec_list.end();)
if (*it >= m_spec_min && *it <m_spec_max)
{
it = m_spec_list.erase(it);
}
else
it++;
}
if (m_spec_list.size() == 0) m_list = false;
total_specs += static_cast<specid_t>(m_spec_list.size());
Roman Tolchenov
committed
}
else
{
total_specs = m_numberOfSpectra;
// In this case want all the spectra, but zeroth spectrum is garbage so go from 1 to NSP1
m_spec_min = 1;
m_spec_max = m_numberOfSpectra + 1;
}
Roman Tolchenov
committed
// If there is not enough memory use ManagedRawFileWorkspace2D.
Gigg, Martyn Anthony
committed
if ( ConfigService::Instance().getString("ManagedRawFileWorkspace.DoNotUse") != "1" &&
m_numberOfPeriods == 1 && MemoryManager::Instance().goForManagedWorkspace(total_specs,lengthIn,channelsPerSpectrum) &&
Roman Tolchenov
committed
total_specs == m_numberOfSpectra)
Roman Tolchenov
committed
{
const std::string cache_option = getPropertyValue("Cache");
size_t option = find(m_cache_options.begin(),m_cache_options.end(),cache_option) - m_cache_options.begin();
DataObjects::Workspace2D_sptr localWorkspace =
DataObjects::Workspace2D_sptr(
new ManagedRawFileWorkspace2D(m_filename, static_cast<int>(option)));
progress(0.,"Reading raw file...");
helper->loadRunParameters(localWorkspace, isisRaw.get());
runLoadInstrument(localWorkspace );
runLoadMappingTable(localWorkspace );
runLoadLog(localWorkspace );
Property* log=createPeriodLog(1);
if(log)
{
localWorkspace->mutableRun().addLogData(log);
}
Gigg, Martyn Anthony
committed
localWorkspace->mutableRun().setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
for (int i = 0; i < m_numberOfSpectra; ++i)
localWorkspace->getAxis(1)->spectraNo(i)= i+1;
Anders Markvardsen
committed
localWorkspace->populateInstrumentParameters();
setProperty("OutputWorkspace",localWorkspace);
return;
Roman Tolchenov
committed
}
float* timeChannels = new float[lengthIn];
isisRaw->getTimeChannels(timeChannels, lengthIn);
// Put the read in array into a vector (inside a shared pointer)
Russell Taylor
committed
boost::shared_ptr<MantidVec> timeChannelsVec
(new MantidVec(timeChannels, timeChannels + lengthIn));
Roman Tolchenov
committed
// Need to extract the user-defined output workspace name
Property *ws = getProperty("OutputWorkspace");
Roman Tolchenov
committed
Progress pr(this,0.,1.,total_specs * m_numberOfPeriods);
Russell Taylor
committed
// Create the 2D workspace for the output
DataObjects::Workspace2D_sptr localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>
(WorkspaceFactory::Instance().create("Workspace2D",total_specs,lengthIn,lengthIn-1));
Russell Taylor
committed
localWorkspace->setTitle(title);
Russell Taylor
committed
localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
Gigg, Martyn Anthony
committed
// Run parameters
helper->loadRunParameters(localWorkspace, isisRaw.get());
delete helper;
helper = NULL;
// Loop over the number of periods in the raw file, putting each period in a separate workspace
for (int period = 0; period < m_numberOfPeriods; ++period) {
{
localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>
(WorkspaceFactory::Instance().create(localWorkspace));
}
int counter = 0;
for (int i = 1; i <= m_numberOfSpectra; ++i)
{
int histToRead = i + period*(m_numberOfSpectra+1);
(m_list && find(m_spec_list.begin(),m_spec_list.end(),i) != m_spec_list.end()))
{
// Copy the data into the workspace vector, discarding the 1st entry, which is rubbish
// But note that the last (overflow) bin is kept
MantidVec& Y = localWorkspace->dataY(counter);
Y.assign(isisRaw->dat1 + 1, isisRaw->dat1 + lengthIn);
// Fill the vector for the errors, containing sqrt(count)
MantidVec& E = localWorkspace->dataE(counter);
std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt);
// Set the X vector pointer and spectrum number
localWorkspace->setX(counter, timeChannelsVec);
localWorkspace->getAxis(1)->spectraNo(counter)= i;
// - no account taken of bin widths/units etc.
++counter;
Roman Tolchenov
committed
pr.report();
}
else
{
}
}
// Just a sanity check
assert(counter == total_specs);
std::string outputWorkspace = "OutputWorkspace";
if (period == 0)
{
// Only run the sub-algorithms once
runLoadInstrument(localWorkspace );
runLoadMappingTable(localWorkspace );
runLoadLog(localWorkspace );
Property* log=createPeriodLog(period+1);
if(log)
{
localWorkspace->mutableRun().addLogData(log);
}
// Set the total proton charge for this run
// (not sure how this works for multi_period files)
Gigg, Martyn Anthony
committed
localWorkspace->mutableRun().setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
}
else // We are working on a higher period of a multiperiod raw file
{
// Create a WorkspaceProperty for the new workspace of a higher period
// The workspace name given in the OutputWorkspace property has _periodNumber appended to it
// (for all but the first period, which has no suffix)
std::stringstream suffix;
suffix << (period+1);
outputWorkspace += suffix.str();
std::string WSName = localWSName + "_" + suffix.str();
declareProperty(new WorkspaceProperty<DataObjects::Workspace2D>(outputWorkspace,WSName,Direction::Output));
g_log.information() << "Workspace " << WSName << " created. \n";
Gigg, Martyn Anthony
committed
//remove previous period data
std::stringstream index;
index << (period);
std::string prevPeriod="PERIOD "+index.str();
localWorkspace->mutableRun().removeLogData(prevPeriod);
//add current period data
Property* log=createPeriodLog(period+1);
if(log)
{
localWorkspace->mutableRun().addLogData(log);
}
}
Anders Markvardsen
committed
// check if values stored in logfiles should be used to define parameters of the instrument
Anders Markvardsen
committed
localWorkspace->populateInstrumentParameters();
Anders Markvardsen
committed
// Assign the result to the output workspace property
setProperty(outputWorkspace,localWorkspace);
} // loop over periods
// Clean up
delete[] timeChannels;
//delete[] spectrum;
fclose(file);
}
/** Creates a TimeSeriesProperty<bool> showing times when a particular period was active.
Janik Zikovsky
committed
* @param period :: The data period
* @return the times when requested period was active
*/
Kernel::Property* LoadRaw2::createPeriodLog(int period)const
{
Kernel::TimeSeriesProperty<int>* periods = dynamic_cast< Kernel::TimeSeriesProperty<int>* >(m_perioids.get());
Gigg, Martyn Anthony
committed
if(!periods) return 0;
std::ostringstream ostr;
ostr<<period;
Kernel::TimeSeriesProperty<bool>* p = new Kernel::TimeSeriesProperty<bool> ("period "+ostr.str());
Janik Zikovsky
committed
std::map<Kernel::DateAndTime, int> pMap = periods->valueAsMap();
std::map<Kernel::DateAndTime, int>::const_iterator it = pMap.begin();
if (it->second != period)
p->addValue(it->first,false);
for(;it!=pMap.end();it++)
p->addValue(it->first, (it->second == period) );
return p;
Sofia Antony
committed
}
/// Validates the optional 'spectra to read' properties, if they have been set
void LoadRaw2::checkOptionalProperties()
{
Steve Williams
committed
//read in the settings passed to the algorithm
m_spec_list = getProperty("SpectrumList");
m_spec_max = getProperty("SpectrumMax");
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 = 1;
// Check validity of spectra list property, if set
if ( m_list )
{
m_list = true;
Roman Tolchenov
committed
if (m_spec_list.size() == 0)
{
Roman Tolchenov
committed
m_list = false;
}
else
{
const int64_t minlist = *min_element(m_spec_list.begin(),m_spec_list.end());
const int64_t maxlist = *max_element(m_spec_list.begin(),m_spec_list.end());
Roman Tolchenov
committed
if ( maxlist > m_numberOfSpectra || minlist <= 0)
{
g_log.error("Invalid list of spectra");
throw std::invalid_argument("Inconsistent properties defined");
}
}
// Check validity of spectra range, if set
if ( m_interval )
{
m_interval = true;
m_spec_min = getProperty("SpectrumMin");
if ( m_spec_max < m_spec_min || m_spec_max > m_numberOfSpectra )
{
g_log.error("Invalid Spectrum min/max properties");
}
}
}
/// Run the sub-algorithm LoadInstrument (or LoadInstrumentFromRaw)
void LoadRaw2::runLoadInstrument(DataObjects::Workspace2D_sptr localWorkspace)
{
// get instrument ID
Roman Tolchenov
committed
std::string instrumentID = isisRaw->i_inst; // get the instrument name
size_t i = instrumentID.find_first_of(' '); // cut trailing spaces
if (i != std::string::npos) instrumentID.erase(i);
Roman Tolchenov
committed
IAlgorithm_sptr loadInst = createSubAlgorithm("LoadInstrument");
Gigg, Martyn Anthony
committed
bool executionSuccessful(true);
try
{
loadInst->setPropertyValue("InstrumentName", instrumentID);
Gigg, Martyn Anthony
committed
loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", localWorkspace);
Gigg, Martyn Anthony
committed
loadInst->setProperty("RewriteSpectraMap", false);
loadInst->execute();
}
Gigg, Martyn Anthony
committed
catch( std::invalid_argument&)
{
g_log.information("Invalid argument to LoadInstrument sub-algorithm");
executionSuccessful = false;
}
{
g_log.information("Unable to successfully run LoadInstrument sub-algorithm");
Gigg, Martyn Anthony
committed
executionSuccessful = false;
}
// If loading instrument definition file fails, run LoadInstrumentFromRaw instead
Gigg, Martyn Anthony
committed
if( !executionSuccessful )
{
Anders Markvardsen
committed
g_log.information() << "Instrument definition file "
<< " not found. Attempt to load information about \n"
Anders Markvardsen
committed
<< "the instrument from raw data file.\n";
runLoadInstrumentFromRaw(localWorkspace);
}
}
/// Run LoadInstrumentFromRaw as a sub-algorithm (only if loading from instrument definition file fails)
void LoadRaw2::runLoadInstrumentFromRaw(DataObjects::Workspace2D_sptr localWorkspace)
{
IAlgorithm_sptr loadInst = createSubAlgorithm("LoadInstrumentFromRaw");
loadInst->setPropertyValue("Filename", m_filename);
// Set the workspace property to be the same one filled above
Roman Tolchenov
committed
loadInst->setProperty<MatrixWorkspace_sptr>("Workspace",localWorkspace);
// Now execute the sub-algorithm. Catch and log any error, but don't stop.
try
{
loadInst->execute();
}
{
g_log.error("Unable to successfully run LoadInstrumentFromRaw sub-algorithm");
}
if ( ! loadInst->isExecuted() ) g_log.error("No instrument definition loaded");
}
/// Run the LoadMappingTable sub-algorithm to fill the SpectraToDetectorMap
void LoadRaw2::runLoadMappingTable(DataObjects::Workspace2D_sptr localWorkspace)
{
// Now determine the spectra to detector map calling sub-algorithm LoadMappingTable
// There is a small penalty in re-opening the raw file but nothing major.
IAlgorithm_sptr loadmap= createSubAlgorithm("LoadMappingTable");
loadmap->setPropertyValue("Filename", m_filename);
Roman Tolchenov
committed
loadmap->setProperty<MatrixWorkspace_sptr>("Workspace",localWorkspace);
try
{
}
{
Gigg, Martyn Anthony
committed
g_log.error("Unable to successfully execute LoadMappingTable sub-algorithm");
}
if ( ! loadmap->isExecuted() ) g_log.error("LoadMappingTable sub-algorithm is not executed");
}
/// Run the LoadLog sub-algorithm
void LoadRaw2::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace, int period)
{
(void) period; // Avoid compiler warning
IAlgorithm_sptr loadLog = createSubAlgorithm("LoadLog");
// Pass through the same input filename
loadLog->setPropertyValue("Filename",m_filename);
// Set the workspace property to be the same one filled above
Roman Tolchenov
committed
loadLog->setProperty<MatrixWorkspace_sptr>("Workspace",localWorkspace);
Sofia Antony
committed
//loadLog->setProperty("Period",period);
// Now execute the sub-algorithm. Catch and log any error, but don't stop.
try
{
loadLog->execute();
}
{
g_log.error("Unable to successfully run LoadLog sub-algorithm");
}
if ( ! loadLog->isExecuted() ) g_log.error("Unable to successfully run LoadLog sub-algorithm");
Gigg, Martyn Anthony
committed
LoadLog* plog=dynamic_cast<LoadLog*>(loadLog.get());
if(plog) m_perioids=plog->getPeriodsProperty();
}
double LoadRaw2::dblSqrt(double in)
{
return sqrt(in);
}
Anders Markvardsen
committed
} // namespace DataHandling
} // namespace Mantid