Newer
Older
Peterson, Peter
committed
#include "MantidDataHandling/LoadEventPreNeXus.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/EventList.h"
#include "MantidKernel/ArrayProperty.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
#include "MantidKernel/System.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/UnitFactory.h"
Peterson, Peter
committed
Peterson, Peter
committed
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(LoadEventPreNeXus)
using namespace Kernel;
using namespace API;
using namespace Geometry;
using boost::posix_time::ptime;
using boost::posix_time::time_duration;
using DataObjects::EventList;
using DataObjects::EventWorkspace;
using DataObjects::EventWorkspace_sptr;
using DataObjects::TofEvent;
using std::cout;
using std::endl;
using std::ifstream;
using std::runtime_error;
using std::stringstream;
using std::string;
using std::vector;
// constants for locating the parameters to use in execution
static const string EVENT_PARAM("EventFilename");
static const string PULSEID_PARAM("PulseidFilename");
static const string MAP_PARAM("MappingFilename");
Janik Zikovsky
committed
static const string INSTRUMENT_PARAM("InstrumentFilename");
static const string PID_PARAM("SpectrumList");
Janik Zikovsky
committed
static const string PAD_PIXELS_PARAM("PadEmptyPixels");
static const string OUT_PARAM("OutputWorkspace");
Janik Zikovsky
committed
static const size_t DEFAULT_BLOCK_SIZE = 1000000; // 100,000
/// All pixel ids with matching this mask are errors.
/// The maximum possible tof as native type
static const uint32_t MAX_TOF_UINT32 = std::numeric_limits<uint32_t>::max();
/// The difference in seconds between standard unix and gps epochs.
static const uint32_t EPOCH_DIFF = 631152000;
/// The epoch for GPS times.
static const ptime GPS_EPOCH(boost::gregorian::date(1990, 1, 1));
/// The epoch for Unix times.
static const ptime UNIX_EPOCH(boost::gregorian::date(1970, 1, 1));
/// The number of nanoseconds in a second.
static const uint32_t NANO_TO_SEC = 1000000000;
/// Conversion factor between 100 nanoseconds and 1 microsecond.
static const double TOF_CONVERSION = .1;
/// Conversion factor between picoColumbs and microAmp*hours
static const double CURRENT_CONVERSION = 1.e-6 / 3600.;
static size_t getBufferSize(const size_t num_items);
LoadEventPreNeXus::LoadEventPreNeXus() : Mantid::API::Algorithm()
{
this->eventfile = NULL;
}
Peterson, Peter
committed
Peterson, Peter
committed
{
Peterson, Peter
committed
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Initialize the algorithm */
this->g_log.setName("DataHandling::LoadEventPreNeXus");
Peterson, Peter
committed
this->declareProperty(new FileProperty(EVENT_PARAM, "", FileProperty::Load, "event.dat"),
"A preNeXus neutron event file");
Peterson, Peter
committed
this->declareProperty(new FileProperty(PULSEID_PARAM, "", FileProperty::OptionalLoad, "pulseid.dat"),
"A preNeXus pulseid file. Used only if specified.");
Peterson, Peter
committed
this->declareProperty(new FileProperty(MAP_PARAM, "", FileProperty::OptionalLoad, ".dat"),
"TS mapping file converting detector id to pixel id. Used only if specified.");
Peterson, Peter
committed
this->declareProperty(new FileProperty(INSTRUMENT_PARAM, "", FileProperty::OptionalLoad, "Definition.xml"),
Janik Zikovsky
committed
"Instrument Geometry file to load. Used only if specified.");
// which pixels to load
this->declareProperty(new ArrayProperty<int>(PID_PARAM),
"A list of individual spectra to read. Only used if set.");
Peterson, Peter
committed
Janik Zikovsky
committed
// Pad out empty pixels?
this->declareProperty(new PropertyWithValue<bool>(PAD_PIXELS_PARAM, false, Direction::Input) );
// "Set to True to pad empty pixels, loaded from the instrument geometry file. Nothing is done if no geometry file was specified.");
// the output workspace name
this->declareProperty(new WorkspaceProperty<EventWorkspace>(OUT_PARAM,"",Direction::Output));
Peterson, Peter
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Execute the algorithm */
Peterson, Peter
committed
void LoadEventPreNeXus::exec()
{
this->spectra_list = this->getProperty(PID_PARAM);
// load the mapping file
string mapping_filename = this->getPropertyValue(MAP_PARAM);
this->loadPixelMap(mapping_filename);
Peterson, Peter
committed
// open the pulseid file
string pulseid_filename = this->getPropertyValue(PULSEID_PARAM);
this->readPulseidFile(pulseid_filename);
Peterson, Peter
committed
// open the event file
string event_filename = this->getPropertyValue(EVENT_PARAM);
this->openEventFile(event_filename);
// prep the output workspace
EventWorkspace_sptr localWorkspace = EventWorkspace_sptr(new EventWorkspace());
Janik Zikovsky
committed
//Make sure to initialize.
// We can use dummy numbers for arguments, for event workspace it doesn't matter
localWorkspace->initialize(1,1,1);
Janik Zikovsky
committed
// Set the units
localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
localWorkspace->setYUnit("Counts");
// TODO localWorkspace->setTitle(title);
Janik Zikovsky
committed
// load the instrument geometry file
string instrument_filename = this->getPropertyValue(INSTRUMENT_PARAM);
//TODO: Auto-find the instrument file if not specified
if (instrument_filename.length() > 0)
this->runLoadInstrument(instrument_filename, localWorkspace);
Janik Zikovsky
committed
//Process the events into pixels
this->procEvents(localWorkspace);
Janik Zikovsky
committed
//std::cout << "LoadEventPreNeXus::procEvents() has completed.\n";
Janik Zikovsky
committed
Janik Zikovsky
committed
//Save output
Janik Zikovsky
committed
Janik Zikovsky
committed
//std::cout << "LoadEventPreNeXus::output Workspace property has been set.\n";
Peterson, Peter
committed
}
Janik Zikovsky
committed
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//-----------------------------------------------------------------------------
/** Load the instrument geometry File
* @param filename file to open.
* @param localWorkspace MatrixWorkspace in which to put the instrument geometry
*/
void LoadEventPreNeXus::runLoadInstrument(const std::string &filename, MatrixWorkspace_sptr localWorkspace)
{
IAlgorithm_sptr loadInst= createSubAlgorithm("LoadInstrument");
// Now execute the sub-algorithm. Catch and log any error, but don't stop.
bool executionSuccessful(true);
try
{
loadInst->setPropertyValue("Filename", filename);
loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", localWorkspace);
loadInst->execute();
} catch (std::invalid_argument& e)
{
stringstream msg;
msg << "Invalid argument to LoadInstrument sub-algorithm : " << e.what();
g_log.information(msg.str());
executionSuccessful = false;
} catch (std::runtime_error& e)
{
g_log.information("Unable to successfully run LoadInstrument sub-algorithm");
g_log.information(e.what());
executionSuccessful = false;
}
// If loading instrument definition file fails
if (!executionSuccessful)
{
g_log.error() << "Error loading Instrument definition file\n";
//TODO: Load some other way???
// g_log.information() << "Instrument definition file "
// << fullPathIDF << " not found. Attempt to load information about \n"
// << "the instrument from raw data file.\n";
// runLoadInstrumentFromRaw(fileName,localWorkspace);
}
else
{
Janik Zikovsky
committed
this->instrument_loaded_correctly = true;
Janik Zikovsky
committed
// m_monitordetectorList = loadInst->getProperty("MonitorList");
// std::vector<int>::const_iterator itr;
// for (itr = m_monitordetectorList.begin(); itr != m_monitordetectorList.end(); ++itr)
// {
// g_log.debug() << "Monitor detector id is " << (*itr) << std::endl;
// }
}
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Turn a pixel id into a "corrected" pixelid and period.
*
*/
void LoadEventPreNeXus::fixPixelId(PixelType &pixel, uint32_t &period) const
Janik Zikovsky
committed
if (!this->using_mapping_file) { // nothing to do here
period = 0;
return;
}
PixelType unmapped_pid = pixel % this->numpixel;
period = (pixel - unmapped_pid) / this->numpixel;
pixel = this->pixelmap[unmapped_pid];
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Process the event file properly.
* @param workspace EventWorkspace to write to.
*/
void LoadEventPreNeXus::procEvents(DataObjects::EventWorkspace_sptr & workspace)
{
// do the actual loading
this->num_error_events = 0;
this->num_good_events = 0;
size_t event_offset = 0;
size_t event_buffer_size = getBufferSize(this->num_events);
double shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION;
double longest_tof = 0.;
Janik Zikovsky
committed
//Initialize progress reporting.
Progress prog(this,0.0,1.0, this->num_events/event_buffer_size);
//Try to parallelize the code - commented out because it actually makes the code slower!
size_t frame_index = 0;
for (event_offset = 0; event_offset < this->num_events; event_offset += event_buffer_size)
//Variables are defined
DasEvent * event_buffer = new DasEvent[event_buffer_size];
DasEvent temp;
Janik Zikovsky
committed
uint32_t period;
size_t current_event_buffer_size;
//Local incremented variables
size_t my_errors = 0;
size_t my_events = 0;
current_event_buffer_size = event_buffer_size;
if (event_offset + current_event_buffer_size > this->num_events)
current_event_buffer_size = this->num_events - event_offset;
// read in the data
this->eventfile->read(reinterpret_cast<char *>(event_buffer),
current_event_buffer_size * sizeof(DasEvent));
for (size_t i = 0; i < current_event_buffer_size; i++) {
temp = *(event_buffer + i);
if ((temp.pid & ERROR_PID) == ERROR_PID) // marked as bad
{
Janik Zikovsky
committed
continue;
frame_index = this->getFrameIndex(event_offset + i, frame_index);
double tof = static_cast<double>(temp.tof) * TOF_CONVERSION;
Janik Zikovsky
committed
TofEvent event;
Janik Zikovsky
committed
event = TofEvent(tof, frame_index);
//Find the overall max/min tof
if (tof < shortest_tof)
shortest_tof = tof;
if (tof > longest_tof)
longest_tof = tof;
Janik Zikovsky
committed
Janik Zikovsky
committed
//Covert the pixel ID from DAS pixel to our pixel ID
this->fixPixelId(temp.pid, period);
Janik Zikovsky
committed
Janik Zikovsky
committed
//The addEventQuickly method does not clear the cache, making things slightly faster.
workspace->getEventList(temp.pid).addEventQuickly(event);
Peterson, Peter
committed
// TODO work with period
// TODO filter based on pixel ids
Janik Zikovsky
committed
//Fold back the counters into the main one
this->num_error_events += my_errors;
this->num_good_events += my_events;
delete event_buffer;
//Report progress
prog.report();
}
Janik Zikovsky
committed
//--------- Pad Empty Pixels -----------
if (this->getProperty(PAD_PIXELS_PARAM))
Janik Zikovsky
committed
{
Janik Zikovsky
committed
//We want to pad out empty pixels.
if (!this->instrument_loaded_correctly)
{
g_log.warning() << "Warning! Cannot pad empty pixels, since the instrument geometry did not load correctly or was not specified. Sorry!\n";
}
else
{
std::map<int, Geometry::IDetector_sptr> detector_map = workspace->getInstrument()->getDetectors();
std::map<int, Geometry::IDetector_sptr>::iterator it;
for (it = detector_map.begin(); it != detector_map.end(); it++)
{
//Go through each pixel in the map, but forget monitors.
if (!it->second->isMonitor())
{
// and simply get the event list. It will be created if it was not there already.
workspace->getEventList(it->first); //it->first is detector ID #
}
}
}
Janik Zikovsky
committed
}
Janik Zikovsky
committed
Janik Zikovsky
committed
// add the frame information to the event workspace
for (size_t i = 0; i < this->num_pulses; i++)
workspace->addTime(i, this->pulsetimes[i]);
this->setProtonCharge(workspace);
//finalize loading; this condenses the pixels into a 0-based, dense vector.
Janik Zikovsky
committed
workspace->doneLoadingData(1);
Janik Zikovsky
committed
//Now, create a default X-vector for histogramming, with just 2 bins.
Kernel::cow_ptr<MantidVec> axis;
MantidVec& xRef = axis.access();
xRef.resize(2);
xRef[0] = shortest_tof - 1; //Just to make sure the bins hold it all
xRef[1] = longest_tof + 1;
workspace->setAllX(axis);
Janik Zikovsky
committed
g_log.information() << "Read " << this->num_good_events << " events + "
<< this->num_error_events << " errors"
<< ". Shortest TOF: " << shortest_tof << " microsec; longest TOF: " << longest_tof << " microsec.";
Janik Zikovsky
committed
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
}
//-----------------------------------------------------------------------------
/** Parallel-version of the procedure to process the event file properly.
* @param workspace EventWorkspace to write to.
*/
void LoadEventPreNeXus::procEventsParallel(DataObjects::EventWorkspace_sptr & workspace)
{
std::cout << "--- procEventsParallel starting ----\n";
// do the actual loading
this->num_error_events = 0;
this->num_good_events = 0;
size_t event_offset = 0;
size_t event_buffer_size = getBufferSize(this->num_events);
double shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION;
double longest_tof = 0.;
//Initialize progress reporting.
Progress prog(this,0.0,1.0, this->num_events/event_buffer_size);
//Try to parallelize the code - commented out because it actually makes the code slower!
size_t frame_index = 0;
for (event_offset = 0; event_offset < this->num_events; event_offset += event_buffer_size)
{
//Variables are defined
DasEvent * event_buffer = new DasEvent[event_buffer_size];
DasEvent temp;
size_t current_event_buffer_size;
//Local incremented variables
size_t my_errors = 0;
size_t my_events = 0;
// adjust the buffer size
current_event_buffer_size = event_buffer_size;
if (event_offset + current_event_buffer_size > this->num_events)
current_event_buffer_size = this->num_events - event_offset;
// read in the data
std::cout << "--- Loading from File ----\n";
this->eventfile->read(reinterpret_cast<char *>(event_buffer),
current_event_buffer_size * sizeof(DasEvent));
//This is a map, with the DAS pixel ID as the index
typedef std::map<int, std::vector<DasTofType> > PixelMapType;
PixelMapType das_pixel_map;
std::cout << "--- Process (serially) the entire list of DAS events ----\n";
//--- Process (serially) the entire list of DAS events ----
for (size_t i=0; i < current_event_buffer_size; i++)
{
temp = *(event_buffer + i);
//Add this time of flight to this das pixelid entry.
das_pixel_map[temp.pid].push_back(temp.tof);
}
//# of unique DAS pixel IDs
PixelType num_unique_pixels = das_pixel_map.size();
std::cout << "# of unique pixels = " << num_unique_pixels << "\n";
//Will split in blocks of this size.
Janik Zikovsky
committed
//Size of block is 1/num_cpus, rounded up
PixelType block_size = (num_unique_pixels + (num_cpus-1)) / num_cpus;
std::cout << "--- Find out where the iterators need to be ----\n";
//--- Find out where the iterators need to be ----
PixelMapType::iterator it_counter;
Janik Zikovsky
committed
PixelMapType::iterator * start_map_it = new PixelMapType::iterator[num_cpus+1];
Janik Zikovsky
committed
start_map_it[0] = das_pixel_map.begin();
size_t counter = 0;
size_t block_counter = 0;
for (it_counter = das_pixel_map.begin(); it_counter != das_pixel_map.end(); it_counter++)
{
if ((counter % block_size) == 0)
{
//This is where you need to start iterating
start_map_it[block_counter] = it_counter;
//No need to iterate to the end
if (block_counter == num_cpus - 1)
break;
block_counter++;
}
counter++;
}
//The ending iterator
start_map_it[num_cpus] = das_pixel_map.end();
PARALLEL_FOR1(workspace)
for (int block_num=0; block_num < num_cpus; block_num++)
Janik Zikovsky
committed
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
{
std::cout << "Starting iterating through block " << block_num << "\n";
//Make an iterator into the map
PixelMapType::iterator it;
//Iterate through this chunk of the map
for (it = start_map_it[block_num]; it != start_map_it[block_num+1]; it++)
{
//Get the pixel id of it
PixelType pid = it->first;
//std::cout << "pixelid is " << pid << "\n";
//This is the vector of tof values
std::vector<DasTofType> tof_vector = das_pixel_map[pid];
std::vector<DasTofType>::iterator it2;
for (it2 = tof_vector.begin(); it2 != tof_vector.end(); it2++)
{
//The time of flight
DasTofType tof = *it2;
//Make a TofEvent here
TofEvent event = TofEvent(tof, frame_index);
//TODO: Fix the PID here
//Add it to the list
workspace->getEventList(pid).addEventQuickly(event);
}
}
}
Janik Zikovsky
committed
delete [] start_map_it;
Janik Zikovsky
committed
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
//
// // process the individual events
// for (size_t i = 0; i < current_event_buffer_size; i++) {
// temp = *(event_buffer + i);
//
// if ((temp.pid & ERROR_PID) == ERROR_PID) // marked as bad
// {
// my_errors++;
// continue;
// }
//
// // work with the good guys
// frame_index = this->getFrameIndex(event_offset + i, frame_index);
// double tof = static_cast<double>(temp.tof) * TOF_CONVERSION;
// TofEvent event;
// event = TofEvent(tof, frame_index);
//
// //Find the overall max/min tof
// if (tof < shortest_tof)
// shortest_tof = tof;
// if (tof > longest_tof)
// longest_tof = tof;
//
// //Covert the pixel ID from DAS pixel to our pixel ID
// this->fixPixelId(temp.pid, period);
//
// //Parallel: this critical block is almost certainly killing parallel efficiency.
// //workspace->getEventList(temp.pid) += event;
//
// //The addEventQuickly method does not clear the cache, making things slightly faster.
// workspace->getEventList(temp.pid).addEventQuickly(event);
//
// // TODO work with period
// // TODO filter based on pixel ids
// my_events++;
// }
//Fold back the counters into the main one
//PARALLEL_CRITICAL(num_error_events)
{
this->num_error_events += my_errors;
this->num_good_events += my_events;
delete event_buffer;
//Report progress
prog.report();
//PARALLEL_END_INTERUPT_REGION
//PARALLEL_CHECK_INTERUPT_REGION
/*
Janik Zikovsky
committed
//OK, you've done all the events; but if some pixels got no events, their
// EventList wasn't initialized.
std::vector<PixelType>::iterator pix;
for (pix = this->pixelmap.begin(); pix < this->pixelmap.end(); pix++)
{
//Go through each pixel in the map
// and simply get the event list. It will be created if empty.
workspace->getEventList(*pix);
}
Janik Zikovsky
committed
// add the frame information to the event workspace
for (size_t i = 0; i < this->num_pulses; i++)
workspace->addTime(i, this->pulsetimes[i]);
this->setProtonCharge(workspace);
Janik Zikovsky
committed
std::cout << "About to finalize with doneLoadingData()\n";
Janik Zikovsky
committed
//finalize loading; this condenses the pixels into a 0-based, dense vector.
workspace->doneLoadingData();
Janik Zikovsky
committed
//std::cout << "Shortest tof " << shortest_tof << " longest was " << longest_tof << "\n";
//Now, create a default X-vector for histogramming, with just 2 bins.
Kernel::cow_ptr<MantidVec> axis;
MantidVec& xRef = axis.access();
xRef.resize(2);
xRef[0] = shortest_tof - 1; //Just to make sure the bins hold it all
xRef[1] = longest_tof + 1;
workspace->setAllX(axis);
stringstream msg;
msg << "Read " << this->num_good_events << " events + "
<< this->num_error_events << " errors";
Janik Zikovsky
committed
msg << ". Shortest tof: " << shortest_tof << " microsec; longest tof: " << longest_tof << " microsec.";
Janik Zikovsky
committed
Janik Zikovsky
committed
static std::time_t to_time_t(ptime t)
{
if (t.is_special())
{
// TODO throw an exception
}
time_duration duration = t - UNIX_EPOCH;
return static_cast<std::time_t>(duration.total_seconds());
}
/**
* Add a sample environment log for the proton chage and set the scalar
* value on the sample.
*/
void LoadEventPreNeXus::setProtonCharge(DataObjects::EventWorkspace_sptr & workspace)
{
if (this->proton_charge.empty()) // nothing to do
return;
Gigg, Martyn Anthony
committed
Run& run = workspace->mutableRun();
run.setProtonCharge(this->proton_charge_tot);
TimeSeriesProperty<double>* log = new TimeSeriesProperty<double>("ProtonCharge");
size_t num = this->proton_charge.size();
for (size_t i = 0; i < num; i++)
log->addValue(to_time_t(this->pulsetimes[i]), this->proton_charge[i]);
/// TODO set the units for the log
Gigg, Martyn Anthony
committed
run.addLogData(log);
}
//-----------------------------------------------------------------------------
/**
* Determine the frame index from the event index.
* @param event_index The index of the event.
* @param last_frame_index Last frame found. This parameter reduces the
* search to be from the current point forward.
*/
size_t LoadEventPreNeXus::getFrameIndex(const std::size_t event_index, const std::size_t last_frame_index)
{
// if at the end of the file return the last frame_index
if (last_frame_index + 1 >= this->num_pulses)
return last_frame_index;
// search for the next frame that increases the event index
size_t next_frame_index = last_frame_index + 1;
Gigg, Martyn Anthony
committed
for ( ; next_frame_index < this->num_pulses - 1; next_frame_index++)
{
if (this->event_indices[next_frame_index] > this->event_indices[last_frame_index])
break;
}
// determine the frame index
if (this->event_indices[next_frame_index] <= event_index)
return next_frame_index;
else
return last_frame_index;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Get the size of a file as a multiple of a particular data type
* @tparam T type to load in the file
* @param handle Handle to the file stream
* */
static size_t getFileSize(ifstream * handle)
{
if (!handle) {
throw runtime_error("Cannot find the size of a file from a null handle");
}
// get the size of the file in bytes and reset the handle back to the beginning
handle->seekg(0, std::ios::end);
size_t filesize = handle->tellg();
handle->seekg(0, std::ios::beg);
// check the file is a compatible size
if (filesize % sizeof(T) != 0) {
stringstream msg;
msg << "File size is not compatible with data size ";
msg << filesize << "%" << sizeof(T) << "=";
msg << filesize % sizeof(T);
throw runtime_error(msg.str());
}
return filesize / sizeof(T);
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Get a buffer size for loading blocks of data.
* @param num_items
*/
static size_t getBufferSize(const size_t num_items)
{
if (num_items < DEFAULT_BLOCK_SIZE)
return num_items;
else
return DEFAULT_BLOCK_SIZE;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Load a pixel mapping file
* @param filename Path to file.
*/
void LoadEventPreNeXus::loadPixelMap(const std::string &filename)
Janik Zikovsky
committed
this->using_mapping_file = false;
this->pixelmap.clear();
// check that there is a mapping file
if (filename.empty()) {
this->g_log.information("NOT using a mapping file");
return;
}
// actually deal with the file
this->g_log.debug("Using mapping file \"" + filename + "\"");
ifstream * handle = new ifstream(filename.c_str(), std::ios::binary);
size_t file_size = getFileSize<PixelType>(handle);
Janik Zikovsky
committed
//std::cout << "file is " << file_size << std::endl;
size_t buffer_size = getBufferSize(file_size);
PixelType * buffer = new PixelType[buffer_size];
size_t obj_size = sizeof(PixelType);
while (offset < file_size) {
// read a section and put it into the object
handle->read(reinterpret_cast<char *>(buffer), buffer_size * obj_size);
this->pixelmap.insert(this->pixelmap.end(), buffer, (buffer + buffer_size));
offset += buffer_size;
// make sure not to read past EOF
if (offset + buffer_size > file_size)
{
buffer_size = file_size - offset;
}
}
Janik Zikovsky
committed
//Let's assume that the # of pixels in the instrument matches the mapping file length.
this->numpixel = file_size;
// cleanup
delete buffer;
handle->close();
delete handle;
Janik Zikovsky
committed
//If we got here, the mapping file was loaded correctly and we'll use it
this->using_mapping_file = true;
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Open an event file
* @param filename file to open.
*/
void LoadEventPreNeXus::openEventFile(const std::string &filename)
{
this->eventfile = new ifstream(filename.c_str(), std::ios::binary);
this->num_events = getFileSize<DasEvent>(this->eventfile);
stringstream msg;
msg << "Reading " << this->num_events << " event records";
this->g_log.information(msg.str());
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Get time with nanosecond resolution.
* @param sec seconds
* @param nano nanoseconds
*/
static ptime getTime(uint32_t sec, uint32_t nano)
{
// push the nanoseconds to be less than one second
if (nano / NANO_TO_SEC > 0)
{
sec = nano / NANO_TO_SEC;
nano = nano % NANO_TO_SEC;
}
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
return GPS_EPOCH + boost::posix_time::seconds(sec) + boost::posix_time::nanoseconds(nano);
return GPS_EPOCH + boost::posix_time::seconds(sec);
//-----------------------------------------------------------------------------
/** Read a pulse ID file
* @param filename file to load.
*/
void LoadEventPreNeXus::readPulseidFile(const std::string &filename)
Peterson, Peter
committed
this->proton_charge_tot = 0.;
// jump out early if there isn't a filename
if (filename.empty()) {
this->g_log.information("NOT using a pulseid file");
this->num_pulses = 0;
return;
}
// set up for reading
this->g_log.debug("Using pulseid file \"" + filename + "\"");
ifstream * handle = new ifstream(filename.c_str(), std::ios::binary);
this->num_pulses = getFileSize<Pulse>(handle);
size_t buffer_size = getBufferSize(this->num_pulses);
size_t offset = 0;
Pulse* buffer = new Pulse[buffer_size];
size_t obj_size = sizeof(Pulse);
double temp;
// go through the file
while (offset < this->num_pulses)
{
handle->read(reinterpret_cast<char *>(buffer), buffer_size * obj_size);
for (size_t i = 0; i < buffer_size; i++)
{
this->pulsetimes.push_back(getTime(buffer[i].seconds, buffer[i].nanoseconds));
this->event_indices.push_back(buffer[i].event_index);
Peterson, Peter
committed
temp = buffer[i].pCurrent; // * CURRENT_CONVERSION;
this->proton_charge.push_back(temp);
Peterson, Peter
committed
//std::cout << (offset + i) << " " << *(this->pulsetimes.rbegin()) << " " << *(this->proton_charge.rbegin())<< std::endl; // REMOVE
if (temp < 0.)
Peterson, Peter
committed
this->g_log.warning("Individiual proton charge < 0 being ignored");
else
Peterson, Peter
committed
this->proton_charge_tot += temp;
}
offset += buffer_size;
// make sure not to read past EOF
if (offset + buffer_size > this->num_pulses)
buffer_size = this->num_pulses - offset;
}
Peterson, Peter
committed
this->proton_charge_tot = this->proton_charge_tot * CURRENT_CONVERSION;
stringstream msg;
msg << "Total proton charge of " << this->proton_charge_tot << " microAmp*hours";
this->g_log.information(msg.str());
delete buffer;
handle->close();
delete handle;