Newer
Older
#include <algorithm>
#include <functional>
#include <Poco/File.h>
Peterson, Peter
committed
#include <Poco/Path.h>
Peterson, Peter
committed
#include <set>
#include <boost/timer.hpp>
Peterson, Peter
committed
#include "MantidAPI/FileFinder.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/LoadAlgorithmFactory.h"
#include "MantidDataHandling/LoadEventPreNexus.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/EventList.h"
#include "MantidKernel/ArrayProperty.h"
Peterson, Peter
committed
#include "MantidKernel/FileValidator.h"
Janik Zikovsky
committed
#include "MantidKernel/DateAndTime.h"
Peterson, Peter
committed
#include "MantidKernel/Glob.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
Peterson, Peter
committed
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/BinaryFile.h"
#include "MantidKernel/System.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidDataHandling/LoadInstrumentHelper.h"
#include "MantidKernel/DateAndTime.h"
#include "MantidGeometry/IDetector.h"
Peterson, Peter
committed
Peterson, Peter
committed
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(LoadEventPreNexus)
DECLARE_LOADALGORITHM(LoadEventPreNexus)
Peterson, Peter
committed
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void LoadEventPreNexus::initDocs()
Janik Zikovsky
committed
{
this->setWikiSummary("Loads SNS raw neutron event data format and stores it in a [[workspace]] ([[EventWorkspace]] class). ");
this->setOptionalMessage("Loads SNS raw neutron event data format and stores it in a workspace (EventWorkspace class).");
}
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");
static const string PID_PARAM("SpectrumList");
static const string PARALLEL_PARAM("UseParallelProcessing");
static const string BLOCK_SIZE_PARAM("LoadingBlockSize");
static const string OUT_PARAM("OutputWorkspace");
Peterson, Peter
committed
static const string PULSE_EXT("pulseid.dat");
static const string EVENT_EXT("event.dat");
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();
/// 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.;
LoadEventPreNexus::LoadEventPreNexus() : Mantid::API::IDataFileChecker()
this->max_events = 0;
Peterson, Peter
committed
LoadEventPreNexus::~LoadEventPreNexus()
Peterson, Peter
committed
{
Janik Zikovsky
committed
if (this->eventfile)
Peterson, Peter
committed
Gigg, Martyn Anthony
committed
/**
* Returns the name of the property to be considered as the Filename for Load
* @returns A character string containing the file property's name
*/
const char * LoadEventPreNexus::filePropertyName() const
Gigg, Martyn Anthony
committed
{
return EVENT_PARAM.c_str();
}
/**
* Do a quick file type check by looking at the first 100 bytes of the file
* @param filePath :: path of the file including name.
* @param nread :: no.of bytes read
* @param header :: The first 100 bytes of the file as a union
* @return true if the given file is of type which can be loaded by this algorithm
*/
bool LoadEventPreNexus::quickFileCheck(const std::string& filePath,size_t,const file_header&)
Gigg, Martyn Anthony
committed
{
std::string ext = extension(filePath);
return (ext.rfind("dat") != std::string::npos);
}
/**
* Checks the file by opening it and reading few lines
* @param filePath :: name of the file inluding its path
* @return an integer value how much this algorithm can load the file
*/
int LoadEventPreNexus::fileCheck(const std::string& filePath)
Gigg, Martyn Anthony
committed
{
int confidence(0);
try
{
// If this looks like a binary file where the exact file length is a multiple
Gigg, Martyn Anthony
committed
// of the DasEvent struct then we're probably okay.
// NOTE: Putting this on the stack gives a segfault on Windows when for some reason
// the BinaryFile destructor is called twice! I'm sure there is something I don't understand there
// but heap allocation seems to work so go for that.
BinaryFile<DasEvent> *event_file = new BinaryFile<DasEvent>(filePath);
Gigg, Martyn Anthony
committed
confidence = 80;
Gigg, Martyn Anthony
committed
delete event_file;
Gigg, Martyn Anthony
committed
}
catch(std::runtime_error &)
{
Gigg, Martyn Anthony
committed
// This BinaryFile constructor throws if the file does not contain an
// exact multiple of the sizeof(DasEvent) objects.
Gigg, Martyn Anthony
committed
}
return confidence;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Initialize the algorithm */
void LoadEventPreNexus::init()
Peterson, Peter
committed
this->declareProperty(new FileProperty(EVENT_PARAM, "", FileProperty::Load, EVENT_EXT),
"A preNeXus neutron event file");
Peterson, Peter
committed
this->declareProperty(new FileProperty(PULSEID_PARAM, "", FileProperty::OptionalLoad, PULSE_EXT),
"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.");
// which pixels to load
Janik Zikovsky
committed
this->declareProperty(new ArrayProperty<int64_t>(PID_PARAM),
"A list of individual spectra (pixel IDs) to read. Only used if set.");
Peterson, Peter
committed
Peterson, Peter
committed
// how many events to process
this->declareProperty(new PropertyWithValue<int>("NumberOfEvents", 0, Direction::Input),
"Number of events to read from the file.");
#ifdef LOADEVENTPRENEXUS_ALLOW_PARALLEL
//Parallel processing
this->declareProperty(new PropertyWithValue<bool>(PARALLEL_PARAM, true, Direction::Input) );
//Loading block size
this->declareProperty(new PropertyWithValue<int>(BLOCK_SIZE_PARAM, 500000, Direction::Input) );
#endif
// the output workspace name
Gigg, Martyn Anthony
committed
this->declareProperty(new WorkspaceProperty<IEventWorkspace>(OUT_PARAM,"",Direction::Output));
Peterson, Peter
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
Janik Zikovsky
committed
static string generatePulseidName(string eventfile)
Peterson, Peter
committed
{
size_t start;
string ending;
// normal ending
ending = "neutron_event.dat";
start = eventfile.find(ending);
if (start != string::npos)
return eventfile.replace(start, ending.size(), "pulseid.dat");
// split up event files - yes this is copy and pasted code
ending = "neutron0_event.dat";
start = eventfile.find(ending);
if (start != string::npos)
return eventfile.replace(start, ending.size(), "pulseid0.dat");
ending = "neutron1_event.dat";
start = eventfile.find(ending);
if (start != string::npos)
return eventfile.replace(start, ending.size(), "pulseid1.dat");
return "";
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
Peterson, Peter
committed
static string generateMappingfileName(EventWorkspace_sptr &wksp)
{//
Peterson, Peter
committed
// get the name of the mapping file as set in the parameter files
Gigg, Martyn Anthony
committed
std::vector<string> temp = wksp->getInstrument()->getStringParameter("TS_mapping_file");
Peterson, Peter
committed
if (temp.empty())
return "";
string mapping = temp[0];
Peterson, Peter
committed
// Try to get it from the data directories
string dataversion = Mantid::API::FileFinder::Instance().getFullPath(mapping);
if (!dataversion.empty())
return dataversion;
// get a list of all proposal directories
Peterson, Peter
committed
string instrument = wksp->getInstrument()->getName();
Peterson, Peter
committed
Poco::File base("/SNS/" + instrument + "/");
Peterson, Peter
committed
if (!base.exists())
return "";
Peterson, Peter
committed
vector<string> dirs; // poco won't let me reuse temp
base.list(dirs);
// check all of the proposals for the mapping file in the canonical place
const string CAL("_CAL");
vector<string> files;
for (size_t i = 0; i < dirs.size(); ++i) {
if (dirs[i].compare(dirs[i].length() - CAL.length(), CAL.length(), CAL) == 0) {
if (Poco::File(base.path() + "/" + dirs[i] + "/calibrations/" + mapping).exists())
files.push_back(base.path() + "/" + dirs[i] + "/calibrations/" + mapping);
}
}
Peterson, Peter
committed
if (files.empty())
return "";
Peterson, Peter
committed
else if (files.size() == 1)
return files[0];
else // just assume that the last one is the right one, this should never be fired
return *(files.rbegin());
Peterson, Peter
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Execute the algorithm */
void LoadEventPreNexus::exec()
Peterson, Peter
committed
{
// what spectra (pixel ID's) to load
this->spectra_list = this->getProperty(PID_PARAM);
Peterson, Peter
committed
// the event file is needed in case the pulseid fileanme is empty
string event_filename = this->getPropertyValue(EVENT_PARAM);
Peterson, Peter
committed
bool throwError = true;
Peterson, Peter
committed
if (pulseid_filename.empty())
{
Janik Zikovsky
committed
pulseid_filename = generatePulseidName(event_filename);
Peterson, Peter
committed
if (!pulseid_filename.empty())
{
if (Poco::File(pulseid_filename).exists())
Peterson, Peter
committed
{
Peterson, Peter
committed
this->g_log.information() << "Found pulseid file " << pulseid_filename << std::endl;
Peterson, Peter
committed
throwError = false;
}
Peterson, Peter
committed
{
pulseid_filename = "";
Peterson, Peter
committed
}
Peterson, Peter
committed
}
Peterson, Peter
committed
this->readPulseidFile(pulseid_filename, throwError);
Peterson, Peter
committed
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
// Add the run_start property
// Use the first pulse as the run_start time.
if (pulsetimes.size() > 0)
{
// add the start of the run as a ISO8601 date/time string. The start = the first pulse.
// (this is used in LoadInstrumentHelper to find the right instrument file to use).
localWorkspace->mutableRun().addProperty("run_start", pulsetimes[0].to_ISO8601_string(), true );
}
//Get the instrument!
Peterson, Peter
committed
this->runLoadInstrument(event_filename, localWorkspace);
Janik Zikovsky
committed
Peterson, Peter
committed
// load the mapping file
string mapping_filename = this->getPropertyValue(MAP_PARAM);
Peterson, Peter
committed
if (mapping_filename.empty()) {
mapping_filename = generateMappingfileName(localWorkspace);
if (!mapping_filename.empty())
this->g_log.information() << "Found mapping file \"" << mapping_filename << "\"" << std::endl;
}
Peterson, Peter
committed
this->loadPixelMap(mapping_filename);
Janik Zikovsky
committed
//Process the events into pixels
this->procEvents(localWorkspace);
Janik Zikovsky
committed
//Save output
Gigg, Martyn Anthony
committed
this->setProperty<IEventWorkspace_sptr>(OUT_PARAM, localWorkspace);
// Clear any large vectors to free up memory.
this->pulsetimes.clear();
this->event_indices.clear();
this->proton_charge.clear();
this->spectraLoadMap.clear();
Peterson, Peter
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Load the instrument geometry File
Janik Zikovsky
committed
* @param eventfilename :: Used to pick the instrument.
* @param localWorkspace :: MatrixWorkspace in which to put the instrument geometry
Janik Zikovsky
committed
*/
void LoadEventPreNexus::runLoadInstrument(const std::string &eventfilename, MatrixWorkspace_sptr localWorkspace)
Janik Zikovsky
committed
{
Peterson, Peter
committed
// determine the instrument parameter file
string instrument = Poco::Path(eventfilename).getFileName();
size_t pos = instrument.rfind("_"); // get rid of 'event.dat'
pos = instrument.rfind("_", pos-1); // get rid of 'neutron'
pos = instrument.rfind("_", pos-1); // get rid of the run number
instrument = instrument.substr(0, pos);
// do the actual work
Janik Zikovsky
committed
IAlgorithm_sptr loadInst= createSubAlgorithm("LoadInstrument");
// Now execute the sub-algorithm. Catch and log any error, but don't stop.
Peterson, Peter
committed
loadInst->setPropertyValue("InstrumentName", instrument);
loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", localWorkspace);
loadInst->executeAsSubAlg();
Peterson, Peter
committed
Peterson, Peter
committed
// Populate the instrument parameters in this workspace - this works around a bug
localWorkspace->populateInstrumentParameters();
Janik Zikovsky
committed
}
Janik Zikovsky
committed
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];
}
//-----------------------------------------------------------------------------
/** Special function to reduce the number of loaded events.
*
*/
void LoadEventPreNexus::setMaxEventsToLoad(std::size_t max_events_to_load)
{
this->max_events = max_events_to_load;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Process the event file properly.
Janik Zikovsky
committed
* @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;
this->num_ignored_events = 0;
//Default values in the case of no parallel
parallelProcessing = false;
loadBlockSize = Mantid::Kernel::DEFAULT_BLOCK_SIZE;
shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION;
longest_tof = 0.;
Janik Zikovsky
committed
//Initialize progress reporting.
Progress prog(this,0.0,1.0,static_cast<int>(this->num_events/loadBlockSize));
Janik Zikovsky
committed
//Allocate the buffer
DasEvent * event_buffer = new DasEvent[loadBlockSize];
Janik Zikovsky
committed
Peterson, Peter
committed
// We want to pad out empty pixels.
Peterson, Peter
committed
detid2det_map detector_map;
workspace->getInstrument()->getDetectors(detector_map);
// determine maximum pixel id
detid2det_map::iterator it;
detid_t detid_max = 0; // seems like a safe lower bound
for (it = detector_map.begin(); it != detector_map.end(); it++)
if (it->first > detid_max)
detid_max = it->first;
Janik Zikovsky
committed
// Pad all the pixels
this->pixel_to_wkspindex.reserve(detid_max+1); //starting at zero up to and including detid_max
this->pixel_to_wkspindex.assign(detid_max+1, 0);
Peterson, Peter
committed
size_t workspaceIndex = 0;
for (it = detector_map.begin(); it != detector_map.end(); it++)
Peterson, Peter
committed
{
Peterson, Peter
committed
if (!it->second->isMonitor())
Peterson, Peter
committed
{
Peterson, Peter
committed
this->pixel_to_wkspindex[it->first] = workspaceIndex;
Janik Zikovsky
committed
EventList & spec = workspace->getOrAddEventList(workspaceIndex);
spec.addDetectorID(it->first);
// Match the spectrum number and detector ID
spec.setSpectrumNo(it->first);
Peterson, Peter
committed
workspaceIndex += 1;
Peterson, Peter
committed
}
}
Janik Zikovsky
committed
workspace->doneAddingEventLists();
Peterson, Peter
committed
//For slight speed up
loadOnlySomeSpectra = (this->spectra_list.size() > 0);
Janik Zikovsky
committed
//Turn the spectra list into a map, for speed of access
for (std::vector<int64_t>::iterator it = spectra_list.begin(); it != spectra_list.end(); it++)
spectraLoadMap[*it] = true;
while (eventfile->getOffset() < this->num_events)
{
//Offset into the file before loading this new block
size_t fileOffset = eventfile->getOffset();
Janik Zikovsky
committed
//Load a block into the buffer directly, up to loadBlockSize elements
size_t current_event_buffer_size = eventfile->loadBlock(event_buffer, loadBlockSize);
Janik Zikovsky
committed
//This processes the events
procEventsLinear(workspace, event_buffer, current_event_buffer_size, fileOffset);
Janik Zikovsky
committed
//Report progress
Doucet, Mathieu
committed
prog.report("Load Event PreNeXus");
Janik Zikovsky
committed
}
//Clean up the buffers
Janik Zikovsky
committed
delete [] event_buffer;
Peterson, Peter
committed
//finalize loading
workspace->doneAddingEventLists();
Peterson, Peter
committed
if(loadOnlySomeSpectra)
workspace->deleteEmptyLists();
Janik Zikovsky
committed
this->setProtonCharge(workspace);
//Make sure the MRU is cleared
workspace->clearMRU();
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);
Peterson, Peter
committed
this->pixel_to_wkspindex.clear();
Janik Zikovsky
committed
Janik Zikovsky
committed
g_log.information() << "Read " << this->num_good_events << " events + "
<< this->num_error_events << " errors"
Peterson, Peter
committed
<< ". Shortest TOF: " << shortest_tof << " microsec; longest TOF: "
<< longest_tof << " microsec." << std::endl;
Janik Zikovsky
committed
}
//-----------------------------------------------------------------------------
/** Linear-version of the procedure to process the event file properly.
Janik Zikovsky
committed
* @param workspace :: EventWorkspace to write to.
* @param event_buffer :: The buffer containing the DAS events
* @param current_event_buffer_size :: The length of the given DAS buffer
* @param fileOffset :: Value for an offset into the binary file
*/
void LoadEventPreNexus::procEventsLinear(DataObjects::EventWorkspace_sptr & workspace, DasEvent * event_buffer,
size_t current_event_buffer_size, size_t fileOffset)
{
DasEvent temp;
uint32_t period;
Janik Zikovsky
committed
//Starting pulse time
Gigg, Martyn Anthony
committed
DateAndTime pulsetime;
int64_t pulse_i = 0;
int64_t numPulses = static_cast<int64_t>(this->pulsetimes.size());
if (static_cast<int64_t>(event_indices.size()) < numPulses)
{
g_log.warning() << "Event_indices vector is smaller than the pulsetimes array.\n";
// process the individual events
for (size_t i = 0; i < current_event_buffer_size; i++)
{
temp = *(event_buffer + i);
PixelType pid = temp.pid;
if ((pid & ERROR_PID) == ERROR_PID) // marked as bad
{
this->num_error_events++;
continue;
}
//Covert the pixel ID from DAS pixel to our pixel ID
this->fixPixelId(pid, period);
//Now check if this pid we want to load.
if (loadOnlySomeSpectra)
{
Janik Zikovsky
committed
it = spectraLoadMap.find(pid);
if (it == spectraLoadMap.end())
{
//Pixel ID was not found, so the event is being ignored.
this->num_ignored_events++;
continue;
}
}
// work with the good guys
Janik Zikovsky
committed
Janik Zikovsky
committed
//Find the pulse time for this event index
if (pulse_i < numPulses-1)
{
//This is the total offset into the file
size_t total_i = i + fileOffset;
//Go through event_index until you find where the index increases to encompass the current index. Your pulse = the one before.
while (!((total_i >= event_indices[pulse_i]) && (total_i < event_indices[pulse_i+1])) )
{
Janik Zikovsky
committed
pulse_i++;
if (pulse_i >= (numPulses-1))
break;
}
//if (pulsetimes[pulse_i] != pulsetime) std::cout << pulse_i << " at " << pulsetimes[pulse_i] << "\n";
Janik Zikovsky
committed
//Save the pulse time at this index for creating those events
pulsetime = pulsetimes[pulse_i];
}
Janik Zikovsky
committed
double tof = static_cast<double>(temp.tof) * TOF_CONVERSION;
TofEvent event;
Janik Zikovsky
committed
event = TofEvent(tof, pulsetime);
//Find the overall max/min tof
if (tof < shortest_tof)
shortest_tof = tof;
if (tof > longest_tof)
longest_tof = tof;
//The addEventQuickly method does not clear the cache, making things slightly faster.
Peterson, Peter
committed
workspace->getEventList(this->pixel_to_wkspindex[pid]).addEventQuickly(event);
// TODO work with period
this->num_good_events++;
}//for each event
}
//-----------------------------------------------------------------------------
/// Comparator for sorting dasevent lists
bool intermediatePixelIDComp(IntermediateEvent x, IntermediateEvent y)
{
return (x.pid < y.pid);
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/**
Janik Zikovsky
committed
* Add a sample environment log for the proton chage (charge of the pulse in picoCoulombs)
Janik Zikovsky
committed
* and set the scalar value (total proton charge, microAmps*hours, on the sample)
*
Janik Zikovsky
committed
* @param workspace :: Event workspace to set the proton charge on
*/
void LoadEventPreNexus::setProtonCharge(DataObjects::EventWorkspace_sptr & workspace)
{
if (this->proton_charge.empty()) // nothing to do
Peterson, Peter
committed
return;
Janik Zikovsky
committed
Gigg, Martyn Anthony
committed
Run& run = workspace->mutableRun();
Janik Zikovsky
committed
//Add the proton charge entries.
Janik Zikovsky
committed
TimeSeriesProperty<double>* log = new TimeSeriesProperty<double>("proton_charge");
Janik Zikovsky
committed
log->setUnits("picoCoulombs");
size_t num = this->proton_charge.size();
for (size_t i = 0; i < num; i++)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
//Add the time and associated charge to the log
log->addValue(this->pulsetimes[i], this->proton_charge[i]);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
/// TODO set the units for the log
Gigg, Martyn Anthony
committed
run.addLogData(log);
Janik Zikovsky
committed
double integ = run.integrateProtonCharge();
//run.setProtonCharge(this->proton_charge_tot); //This is now redundant
this->g_log.information() << "Total proton charge of " << integ << " microAmp*hours found by integrating.\n";
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Load a pixel mapping file
Janik Zikovsky
committed
* @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 + "\"");
Janik Zikovsky
committed
//Open the file; will throw if there is any problem
BinaryFile<PixelType> pixelmapFile(filename);
PixelType max_pid = static_cast<PixelType>(pixelmapFile.getNumElements());
//Load all the data
pixelmapFile.loadAllInto( this->pixelmap );
Janik Zikovsky
committed
Janik Zikovsky
committed
//Check for funky file
if (std::find_if(pixelmap.begin(), pixelmap.end(), std::bind2nd(std::greater<PixelType>(), max_pid))
!= pixelmap.end())
{
this->g_log.warning("Pixel id in mapping file was out of bounds. Loading without mapping file");
this->numpixel = 0;
this->pixelmap.clear();
this->using_mapping_file = false;
Janik Zikovsky
committed
return;
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
//Let's assume that the # of pixels in the instrument matches the mapping file length.
this->numpixel = static_cast<uint32_t>(pixelmapFile.getNumElements());
Janik Zikovsky
committed
Janik Zikovsky
committed
//-----------------------------------------------------------------------------
/** Open an event file
Janik Zikovsky
committed
* @param filename :: file to open.
*/
void LoadEventPreNexus::openEventFile(const std::string &filename)
Janik Zikovsky
committed
//Open the file
this->eventfile = new BinaryFile<DasEvent>(filename);
this->num_events = eventfile->getNumElements();
Peterson, Peter
committed
// determine if we should truncate the event list by the parameter list
int numeventsparam = this->getProperty("NumberOfEvents");
if (numeventsparam > 0)
this->setMaxEventsToLoad(static_cast<size_t>(numeventsparam));
//Limit the # of events to load?
if (this->max_events > 0)
this->num_events = this->max_events;
Peterson, Peter
committed
Janik Zikovsky
committed
this->g_log.information()<< "Reading " << this->num_events << " event records\n";
//-----------------------------------------------------------------------------
/** Read a pulse ID file
Janik Zikovsky
committed
* @param filename :: file to load.
* @param throwError :: Flag to trigger error throwing instead of just logging
*/
void LoadEventPreNexus::readPulseidFile(const std::string &filename, const bool throwError)
Peterson, Peter
committed
this->proton_charge_tot = 0.;
Janik Zikovsky
committed
this->num_pulses = 0;
Peterson, Peter
committed
// jump out early if there isn't a filename
if (filename.empty()) {
this->g_log.information("NOT using a pulseid file");
return;
}
Peterson, Peter
committed
std::vector<Pulse> * pulses;
Janik Zikovsky
committed
//Open the file; will throw if there is any problem
Peterson, Peter
committed
try {
BinaryFile<Pulse> pulseFile(filename);
//Get the # of pulse
this->num_pulses = pulseFile.getNumElements();
this->g_log.information() << "Using pulseid file \"" << filename << "\", with " << num_pulses
<< " pulses.\n";
//Load all the data
pulses = pulseFile.loadAll();
} catch (runtime_error &e) {
if (throwError)
{
throw;
}
else
{
this->g_log.information() << "Encountered error in pulseidfile (ignoring file): " << e.what() << "\n";
return;
}
}
Janik Zikovsky
committed
double temp;
for (std::vector<Pulse>::iterator it = pulses->begin(); it != pulses->end(); it++)
{
Gigg, Martyn Anthony
committed
this->pulsetimes.push_back( DateAndTime( (int64_t) (*it).seconds, (int64_t) (*it).nanoseconds));
Janik Zikovsky
committed
this->event_indices.push_back((*it).event_index);
Janik Zikovsky
committed
temp = (*it).pCurrent;
Janik Zikovsky
committed
this->proton_charge.push_back(temp);
if (temp < 0.)
this->g_log.warning("Individiual proton charge < 0 being ignored");
else
this->proton_charge_tot += temp;
Janik Zikovsky
committed
Peterson, Peter
committed
this->proton_charge_tot = this->proton_charge_tot * CURRENT_CONVERSION;
Janik Zikovsky
committed
//Clear the vector
delete pulses;