Newer
Older

Zhou, Wenduo
committed
#include "MantidDataHandling/LoadLogsForSNSPulsedMagnet.h"
#include "MantidAPI/FileProperty.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/BinaryFile.h"

Zhou, Wenduo
committed
#include "MantidKernel/ConfigService.h"
Federico Montesino Pouzols
committed
#include "MantidKernel/System.h"

Zhou, Wenduo
committed
#include <fstream>

Zhou, Wenduo
committed
#include <sstream>
Federico Montesino Pouzols
committed
#include <sys/stat.h>

Zhou, Wenduo
committed
Peterson, Peter
committed
using std::size_t;
using std::vector;

Zhou, Wenduo
committed
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(LoadLogsForSNSPulsedMagnet)
using namespace Mantid::Kernel;
using namespace Mantid::API;
//----------------------------------------------------------------------------------------------
/** Constructor
*/
LoadLogsForSNSPulsedMagnet::LoadLogsForSNSPulsedMagnet()
: m_delaytimefilename(""), m_pulseidfilename(""),
m_delayfileinoldformat(false), m_numpulses(0), m_numchoppers(0),
m_delaytimes(nullptr), m_pulseidseconds(), m_pulseidnanoseconds(), WS() {}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
LoadLogsForSNSPulsedMagnet::~LoadLogsForSNSPulsedMagnet() {
for (unsigned int i = 0; i < m_numpulses; i++)
delete[] m_delaytimes[i];
delete[] m_delaytimes;
}
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void LoadLogsForSNSPulsedMagnet::init() {
declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>(
"Workspace", "Anonymous", Direction::InOut),
"The name of the workspace in which to attach the pulsed "
"magnet log information.");
declareProperty(
make_unique<FileProperty>("DelayTimeFilename", "", FileProperty::Load,
".dat"),
"The name (including its full or relative path) of the log file to\n"
"attempt to load the pulsed magnet log. The file extension must either "
"be\n"
".dat or .DAT");
declareProperty(
make_unique<FileProperty>("PulseIDFilename", "", FileProperty::Load,
".dat"),
"The name (including its full or relative path) of the log file to\n"
"attempt to load the PulseID. The file extension must either be\n"
".dat or .DAT");
declareProperty(make_unique<PropertyWithValue<bool>>("OldFormat", false,
Direction::Input),
"Delay time file have an old format");
make_unique<PropertyWithValue<int64_t>>("NumberOfChoppers", 4,
Direction::Input),
"Number of choppers used in data acquisition. It is not required for "
"new format Delay time file.");
m_numpulses = 0;
m_numchoppers = 4;
m_delayfileinoldformat = false;
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void LoadLogsForSNSPulsedMagnet::exec() {
// 1. Retrieve the information from input data file (binary)
m_delaytimefilename = getPropertyValue("DelayTimeFileName");
m_pulseidfilename = getPropertyValue("PulseIDFileName");
m_delayfileinoldformat = getProperty("OldFormat");
if (m_delayfileinoldformat)
m_numchoppers = getProperty("NumberOfChoppers");
// 1 b) check input
if (m_numchoppers < 1) {
throw std::invalid_argument(
"Number of choppers cannot be smaller than 1. ");

Zhou, Wenduo
committed
}

Zhou, Wenduo
committed

Zhou, Wenduo
committed
g_log.information() << "Input Files: " << m_delaytimefilename << " , "

Zhou, Wenduo
committed
// 2. Parse delaytime file
ParseDelayTimeLogFile();

Zhou, Wenduo
committed
// 3. Parse pulse ID file
ParsePulseIDLogFile();

Zhou, Wenduo
committed
// 4. Integrate answer
addProperty();

Zhou, Wenduo
committed

Zhou, Wenduo
committed
void LoadLogsForSNSPulsedMagnet::ParseDelayTimeLogFile() {
char *logfilename = &m_delaytimefilename[0];

Zhou, Wenduo
committed
// 1. Determine length of file
struct stat results;
size_t filesize;
if (stat(logfilename, &results) == 0) {
filesize = static_cast<size_t>(results.st_size);
g_log.debug() << "File Size = " << filesize << "\n";
} else {
g_log.error() << "File Error! Cannot Read File Size"
<< "\n";

Zhou, Wenduo
committed
return;
}
// 2. Determine number of magnetic pulses
size_t numpulses;
if (m_delayfileinoldformat) {
numpulses = filesize / sizeof(double) / m_numchoppers;
} else {
numpulses = filesize / (4 + 4) / m_numchoppers;
}
g_log.debug() << "Number of Pulses = " << numpulses
<< " Old format = " << m_delayfileinoldformat << '\n';
auto delaytimes = new unsigned int *[numpulses];
for (unsigned int i = 0; i < numpulses; i++)
delaytimes[i] = new unsigned int[m_numchoppers];
// 4. Parse
std::ifstream logFile(logfilename, std::ios::in | std::ios::binary);
size_t index = 0;
unsigned int localdelaytimes[4];
for (size_t p = 0; p < numpulses; p++) {
for (size_t i = 0; i < static_cast<size_t>(m_numchoppers); i++) {
unsigned int chopperindex;
unsigned int delaytime;
double dtime;
if (m_delayfileinoldformat) {
// Old format
logFile.read(reinterpret_cast<char *>(&dtime), sizeof(double));
chopperindex = static_cast<unsigned int>(i + 1);
delaytime = static_cast<unsigned int>(dtime * 1000);
logFile.read(reinterpret_cast<char *>(&chopperindex),
sizeof(unsigned int));
logFile.read(reinterpret_cast<char *>(&delaytime),
sizeof(unsigned int));
}
if (delaytime != 0) {
g_log.debug() << "Pulse Index = " << index
<< " Chopper = " << chopperindex
<< " Delay Time = " << delaytime << '\n';
}
localdelaytimes[i] = delaytime;

Zhou, Wenduo
committed
}
// Load
for (int i = 0; i < 4; i++) {
delaytimes[p][i] = localdelaytimes[i];

Zhou, Wenduo
committed
}

Zhou, Wenduo
committed

Zhou, Wenduo
committed
}
logFile.close();
m_numpulses = numpulses;
m_delaytimes = delaytimes;

Zhou, Wenduo
committed
return;
}
#pragma pack(push, 4) // Make sure the structure is 16 bytes.
struct Pulse {
/// The number of nanoseconds since the seconds field. This is not necessarily
/// less than one second.
uint32_t nanoseconds;

Zhou, Wenduo
committed
/// The number of seconds since January 1, 1990.
uint32_t seconds;

Zhou, Wenduo
committed
/// The index of the first event for this pulse.
uint64_t event_index;

Zhou, Wenduo
committed
/// The proton charge for the pulse.
// cppcheck-suppress unusedStructMember
double pCurrent;
};
#pragma pack(pop)

Zhou, Wenduo
committed
void LoadLogsForSNSPulsedMagnet::ParsePulseIDLogFile() {
BinaryFile<Pulse> pulseFile(m_pulseidfilename);
this->m_numpulses = pulseFile.getNumElements();
pulses = pulseFile.loadAll();
this->m_pulseidseconds.push_back(pulse.seconds);
this->m_pulseidnanoseconds.push_back(pulse.nanoseconds);
}
}
void LoadLogsForSNSPulsedMagnet::addProperty() {
// DateAndTime epoc(int64_t(m_pulseidhighs[0]),
// int64_t(m_pulseidhighs[0]));
// create values to put into the property
// std::vector<double> times;
// std::vector<double> values;*/
auto property = new TimeSeriesProperty<double> *[4];
for (int i = 0; i < 4; i++) {
std::stringstream namess;
namess << "PulsedMagnetDelay" << i;
std::string tempname = namess.str();
property[i] = new TimeSeriesProperty<double>(tempname);
property[i]->setUnits("nanoseconds");

Zhou, Wenduo
committed
}
for (size_t pulse_index = 0; pulse_index < m_numpulses; pulse_index++) {
DateAndTime dt(static_cast<int32_t>(m_pulseidseconds[pulse_index]),
static_cast<int32_t>(m_pulseidnanoseconds[pulse_index]));
for (int i = 0; i < 4; i++) {
property[i]->addValue(dt,
static_cast<double>(m_delaytimes[pulse_index][i]));

Zhou, Wenduo
committed
}

Zhou, Wenduo
committed
for (int i = 0; i < 4; i++)
WS->mutableRun().addProperty(property[i], false);
g_log.debug() << "Integration is Over!\n";

Zhou, Wenduo
committed
// Clean memory
delete[] property;

Zhou, Wenduo
committed

Zhou, Wenduo
committed
} // namespace Mantid
} // namespace DataHandling