Newer
Older
Ronald Fowler
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidNexus/LoadMuonNexus.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/FileValidator.h"
#include <cmath>
#include <boost/shared_ptr.hpp>
#include "MantidNexus/MuonNexusReader.h"
namespace Mantid
{
namespace NeXus
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadMuonNexus)
using namespace Kernel;
using namespace API;
// Initialise the logger
Logger& LoadMuonNexus::g_log = Logger::get("LoadMuonNexus");
/// Empty default constructor
LoadMuonNexus::LoadMuonNexus() :
Algorithm(), m_filename(), m_numberOfSpectra(0), m_numberOfPeriods(0),
m_list(false), m_interval(false), m_spec_list(), m_spec_min(0), m_spec_max(0)
{}
/// Initialisation method.
void LoadMuonNexus::init()
{
std::vector<std::string> exts;
exts.push_back("NXS");
exts.push_back("nxs");
declareProperty("Filename","",new FileValidator(exts));
declareProperty(new WorkspaceProperty<DataObjects::Workspace2D>("OutputWorkspace","",Direction::Output));
BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
mustBePositive->setLower(0);
declareProperty("spectrum_min",0, mustBePositive);
declareProperty("spectrum_max",0, mustBePositive->clone());
declareProperty(new ArrayProperty<int>("spectrum_list"));
}
/** Executes the algorithm. Reading in the file and creating and populating
* the output workspace
*
* @throw Exception::FileError If the Nexus file cannot be found/opened
* @throw std::invalid_argument If the optional properties are set to invalid values
*/
void LoadMuonNexus::exec()
{
// Retrieve the filename from the properties
m_filename = getPropertyValue("Filename");
MuonNexusReader nxload;
if (nxload.readFromFile(m_filename) != 0)
{
g_log.error("Unable to open file " + m_filename);
throw Exception::FileError("Unable to open File:" , m_filename);
}
// Read in the number of spectra in the Nexus file
m_numberOfSpectra = nxload.t_nsp1;
// Read the number of periods in this file
m_numberOfPeriods = nxload.t_nper;
// Need to extract the user-defined output workspace name
Property *ws = getProperty("OutputWorkspace");
std::string localWSName = ws->value();
//- // If multiperiod, will need to hold the Instrument, Sample & SpectraDetectorMap for copying
//- boost::shared_ptr<Instrument> instrument;
//- boost::shared_ptr<SpectraDetectorMap> specMap;
//- boost::shared_ptr<Sample> sample;
//-
Ronald Fowler
committed
// Call private method to validate the optional parameters, if set
checkOptionalProperties();
Ronald Fowler
committed
// Read the number of time channels (i.e. bins) from the Nexus file
const int channelsPerSpectrum = nxload.t_ntc1;
// Read in the time bin boundaries
const int lengthIn = channelsPerSpectrum + 1;
float* timeChannels = new float[lengthIn];
nxload.getTimeChannels(timeChannels, lengthIn);
// Put the read in array into a vector (inside a shared pointer)
boost::shared_ptr<std::vector<double> > timeChannelsVec
(new std::vector<double>(timeChannels, timeChannels + lengthIn));
// Create an array to hold the read-in data
int* spectrum = new int[lengthIn];
// Calculate the size of a workspace, given its number of periods & spectra to read
int total_specs;
Ronald Fowler
committed
if( m_interval || m_list)
{
total_specs = m_spec_list.size();
if (m_interval)
{
total_specs += (m_spec_max-m_spec_min+1);
m_spec_max += 1;
}
}
else
Ronald Fowler
committed
{
total_specs = m_numberOfSpectra;
// In this case want all the spectra, but zeroth spectrum is garbage so go from 1 to NSP1
// - IS THIS TRUE for NeXus??
m_spec_min = 0; // changed to 0 for NeXus, was 1 for Raw
m_spec_max = m_numberOfSpectra; // was +1?
}
// Loop over the number of periods in the Nexus file, putting each period in a separate workspace
for (int period = 0; period < m_numberOfPeriods; ++period) {
// 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));
// Set the unit on the workspace to TOF
localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
int counter = 0;
for (int i = m_spec_min; i < m_spec_max; ++i)
{
// Shift the histogram to read if we're not in the first period
int histToRead = i + period*total_specs;
loadData(timeChannelsVec,counter,histToRead,nxload,lengthIn-1,spectrum,localWorkspace ); // added -1 for NeXus
counter++;
}
Ronald Fowler
committed
// Read in the spectra in the optional list parameter, if set
if (m_list)
{
for(unsigned int i=0; i < m_spec_list.size(); ++i)
{
loadData(timeChannelsVec,counter,m_spec_list[i],nxload,lengthIn-1,spectrum, localWorkspace );
counter++;
}
}
// Just a sanity check
assert(counter == total_specs);
Ronald Fowler
committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
std::string outputWorkspace = "OutputWorkspace";
if (period == 0)
{
// Only run the sub-algorithms once
//- runLoadInstrument(localWorkspace );
//- runLoadMappingTable(localWorkspace );
//- runLoadLog(localWorkspace );
//- // Cache these for copying to workspaces for later periods
//- instrument = localWorkspace->getInstrument();
//- specMap = localWorkspace->getSpectraMap();
//- sample = localWorkspace->getSample();
//- }
//- 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";
//- // Copy the shared instrument, sample & spectramap onto the workspace for this period
//- localWorkspace->setInstrument(instrument);
//- localWorkspace->setSpectraMap(specMap);
//- localWorkspace->setSample(sample);
}
// Assign the result to the output workspace property
setProperty(outputWorkspace,localWorkspace);
} // loop over periods
// Clean up
delete[] timeChannels;
delete[] spectrum;
}
Ronald Fowler
committed
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/// Validates the optional 'spectra to read' properties, if they have been set
void LoadMuonNexus::checkOptionalProperties()
{
Property *specList = getProperty("spectrum_list");
m_list = !(specList->isDefault());
Property *specMax = getProperty("spectrum_max");
m_interval = !(specMax->isDefault());
// If a multiperiod dataset, ignore the optional parameters (if set) and print a warning
if ( m_numberOfPeriods > 1)
{
if ( m_list || m_interval )
{
m_list = false;
m_interval = false;
g_log.warning("Ignoring spectrum properties in this multiperiod dataset");
}
}
// Check validity of spectra list property, if set
if ( m_list )
{
m_list = true;
m_spec_list = getProperty("spectrum_list");
const int minlist = *min_element(m_spec_list.begin(),m_spec_list.end());
const int maxlist = *max_element(m_spec_list.begin(),m_spec_list.end());
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("spectrum_min");
m_spec_max = getProperty("spectrum_max");
if ( m_spec_max < m_spec_min || m_spec_max > m_numberOfSpectra )
{
g_log.error("Invalid Spectrum min/max properties");
throw std::invalid_argument("Inconsistent properties defined");
}
}
}
Ronald Fowler
committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/** Load in a single spectrum taken from a NeXus file
* @param tcbs The vector containing the time bin boundaries
* @param hist The workspace index
* @param i The spectrum number
* @param nxload A reference to the MuonNeXusReader object
* @param lengthIn The number of elements in a spectrum
* @param spectrum Pointer to the array into which the spectrum will be read
* @param localWorkspace A pointer to the workspace in which the data will be stored
*/
void LoadMuonNexus::loadData(const DataObjects::Histogram1D::RCtype::ptr_type& tcbs,int hist, int& i, MuonNexusReader& nxload, const int& lengthIn, int* spectrum, DataObjects::Workspace2D_sptr localWorkspace)
{
// Read in a spectrum
memcpy(spectrum, nxload.counts + i * lengthIn, lengthIn * sizeof(int));
// Put it into a vector, discarding the 1st entry, which is rubbish
// But note that the last (overflow) bin is kept
// For Nexus, not sure if above is the case, hence give all data for now
std::vector<double> v(spectrum, spectrum + lengthIn);
// Create and fill another vector for the errors, containing sqrt(count)
std::vector<double> e(lengthIn); // changed to remove -1 for nexus
std::transform(v.begin(), v.end(), e.begin(), dblSqrt);
// Populate the workspace. Loop starts from 1, hence i-1
localWorkspace->setData(hist, v, e);
localWorkspace->setX(hist, tcbs);
localWorkspace->setErrorHelper(hist,GaussianErrorHelper::Instance());
localWorkspace->getAxis(1)->spectraNo(hist)= i;
}
//- /// Run the sub-algorithm LoadInstrument (or LoadInstrumentFromNexus)
//- void LoadMuonNexus::runLoadInstrument(DataObjects::Workspace2D_sptr localWorkspace)
//- {
//- // Determine the search directory for XML instrument definition files (IDFs)
//- std::string directoryName = Kernel::ConfigService::Instance().getString("instrumentDefinition.directory");
//- if ( directoryName.empty() ) directoryName = "../Instrument"; // This is the assumed deployment directory for IDFs
//-
//- const int stripPath = m_filename.find_last_of("\\/");
//- std::string instrumentID = m_filename.substr(stripPath+1,3); // get the 1st 3 letters of filename part
//- // force ID to upper case
//- std::transform(instrumentID.begin(), instrumentID.end(), instrumentID.begin(), toupper);
//- std::string fullPathIDF = directoryName + "/" + instrumentID + "_Definition.xml";
//-
//- Algorithm_sptr loadInst = createSubAlgorithm("LoadInstrument");
//- loadInst->setPropertyValue("Filename", fullPathIDF);
//- loadInst->setProperty<Workspace_sptr>("Workspace",localWorkspace);
//-
//- // Now execute the sub-algorithm. Catch and log any error, but don't stop.
//- try
//- {
//- loadInst->execute();
//- }
//- catch (std::runtime_error& err)
//- {
//- g_log.information("Unable to successfully run LoadInstrument sub-algorithm");
//- }
//-
//- // If loading instrument definition file fails, run LoadInstrumentFromNexus instead
//- if ( ! loadInst->isExecuted() )
//- {
//- runLoadInstrumentFromNexus(localWorkspace);
//- }
//- }
//-
//- /// Run LoadInstrumentFromNexus as a sub-algorithm (only if loading from instrument definition file fails)
//- void LoadMuonNexus::runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr localWorkspace)
//- {
//- g_log.information() << "Instrument definition file not found. Attempt to load information about \n"
//- << "the instrument from raw data file.\n";
//-
//- Algorithm_sptr loadInst = createSubAlgorithm("LoadInstrumentFromNexus");
//- loadInst->setPropertyValue("Filename", m_filename);
//- // Set the workspace property to be the same one filled above
//- loadInst->setProperty<Workspace_sptr>("Workspace",localWorkspace);
//-
//- // Now execute the sub-algorithm. Catch and log any error, but don't stop.
//- try
//- {
//- loadInst->execute();
//- }
//- catch (std::runtime_error& err)
//- {
//- g_log.error("Unable to successfully run LoadInstrumentFromNexus sub-algorithm");
//- }
//-
//- if ( ! loadInst->isExecuted() ) g_log.error("No instrument definition loaded");
//- }
//-
//- /// Run the LoadMappingTable sub-algorithm to fill the SpectraToDetectorMap
//- void LoadMuonNexus::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.
//- Algorithm_sptr loadmap= createSubAlgorithm("LoadMappingTable");
//- loadmap->setPropertyValue("Filename", m_filename);
//- loadmap->setProperty<Workspace_sptr>("Workspace",localWorkspace);
//- try
//- {
//- loadmap->execute();
//- }
//- catch (std::runtime_error& err)
//- {
//- 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 LoadMuonNexus::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace)
//- {
//- Algorithm_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
//- loadLog->setProperty<Workspace_sptr>("Workspace",localWorkspace);
//-
//- // Now execute the sub-algorithm. Catch and log any error, but don't stop.
//- try
//- {
//- loadLog->execute();
//- }
//- catch (std::runtime_error& err)
//- {
//- g_log.error("Unable to successfully run LoadLog sub-algorithm");
//- }
//-
//- if ( ! loadLog->isExecuted() ) g_log.error("Unable to successfully run LoadLog sub-algorithm");
//- }
double LoadMuonNexus::dblSqrt(double in)
{
return sqrt(in);
}
} // namespace DataHandling
} // namespace Mantid