Commit 4f1fa389 authored by David Fairbrother's avatar David Fairbrother
Browse files

Fix missing assignment op / copy ctor

Fixes instances with missing assignment operator or copy constructor.
These are dangerous cases with dynamic memory as it's not obvious what
will happen, but the compiler will try anyway.

In many cases we can simply switch to unique_ptr or disable the copy
when it makes sense. But one or two cases required additional thought.

This fixes several memory leaks or sources of corruption if the fields
fall out of sync
parent c821b9f4
...@@ -48,7 +48,7 @@ public: ...@@ -48,7 +48,7 @@ public:
virtual ~ImplicitFunctionParameter() = default; virtual ~ImplicitFunctionParameter() = default;
protected: protected:
bool m_isValid; bool m_isValid{false};
std::string parameterXMLTemplate(const std::string &valueXMLtext) const { std::string parameterXMLTemplate(const std::string &valueXMLtext) const {
using namespace Poco::XML; using namespace Poco::XML;
......
...@@ -28,20 +28,14 @@ public: ...@@ -28,20 +28,14 @@ public:
/// Constructor with vector of DateAndTime /// Constructor with vector of DateAndTime
BankPulseTimes(const std::vector<Mantid::Types::Core::DateAndTime> &times); BankPulseTimes(const std::vector<Mantid::Types::Core::DateAndTime> &times);
/// Destructor
~BankPulseTimes();
/// Equals /// Equals
bool equals(size_t otherNumPulse, const std::string &otherStartTime); bool equals(size_t otherNumPulse, const std::string &otherStartTime);
/// String describing the start time /// String describing the start time
std::string startTime; std::string startTime;
/// Size of the array of pulse times
size_t numPulses;
/// Array of the pulse times /// Array of the pulse times
Mantid::Types::Core::DateAndTime *pulseTimes; std::vector<Mantid::Types::Core::DateAndTime> pulseTimes;
/// Vector of period numbers corresponding to each pulse /// Vector of period numbers corresponding to each pulse
std::vector<int> periodNumbers; std::vector<int> periodNumbers;
......
...@@ -151,6 +151,10 @@ public: ...@@ -151,6 +151,10 @@ public:
FastReadOnlyFile(const char *filename); FastReadOnlyFile(const char *filename);
~FastReadOnlyFile(); ~FastReadOnlyFile();
// Prevent copying of a file handle
FastReadOnlyFile(const FastReadOnlyFile &) = delete;
FastReadOnlyFile &operator=(FastReadOnlyFile) = delete;
// properties // properties
void *handle() const; void *handle() const;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <nexus/NeXusFile.hpp> #include <nexus/NeXusFile.hpp>
#include <climits> #include <climits>
#include <memory>
namespace Mantid { namespace Mantid {
namespace DataHandling { namespace DataHandling {
...@@ -52,7 +53,7 @@ private: ...@@ -52,7 +53,7 @@ private:
/// Overwrites Algorithm method /// Overwrites Algorithm method
void exec() override; void exec() override;
ISISRAW2 m_isisRaw; std::unique_ptr<ISISRAW2> m_isisRaw;
NXhandle handle; NXhandle handle;
FILE *rawFile; FILE *rawFile;
std::vector<int> monitorData; std::vector<int> monitorData;
......
...@@ -39,32 +39,28 @@ BankPulseTimes::BankPulseTimes(::NeXus::File &file, const std::vector<int> &pNum ...@@ -39,32 +39,28 @@ BankPulseTimes::BankPulseTimes(::NeXus::File &file, const std::vector<int> &pNum
file.getData(seconds); file.getData(seconds);
file.closeData(); file.closeData();
// Now create the pulseTimes // Now create the pulseTimes
numPulses = seconds.size(); if (seconds.size() == 0)
if (numPulses == 0)
throw std::runtime_error("event_time_zero field has no data!"); throw std::runtime_error("event_time_zero field has no data!");
pulseTimes = new Mantid::Types::Core::DateAndTime[numPulses]; std::transform(seconds.cbegin(), seconds.cend(), std::back_inserter(pulseTimes),
for (size_t i = 0; i < numPulses; i++) [start](double seconds) { return start + seconds; });
pulseTimes[i] = start + seconds[i];
} else if (heldTimeZeroType == ::NeXus::UINT64) { } else if (heldTimeZeroType == ::NeXus::UINT64) {
std::vector<uint64_t> nanoseconds; std::vector<uint64_t> nanoseconds;
file.getData(nanoseconds); file.getData(nanoseconds);
file.closeData(); file.closeData();
// Now create the pulseTimes // Now create the pulseTimes
numPulses = nanoseconds.size(); if (nanoseconds.size() == 0)
if (numPulses == 0)
throw std::runtime_error("event_time_zero field has no data!"); throw std::runtime_error("event_time_zero field has no data!");
pulseTimes = new Mantid::Types::Core::DateAndTime[numPulses]; std::transform(nanoseconds.cbegin(), nanoseconds.cend(), std::back_inserter(pulseTimes),
for (size_t i = 0; i < numPulses; i++) [start](int64_t nanoseconds) { return start + nanoseconds; });
pulseTimes[i] = start + int64_t(nanoseconds[i]);
} else { } else {
throw std::invalid_argument("Unsupported type for event_time_zero"); throw std::invalid_argument("Unsupported type for event_time_zero");
} }
// Ensure that we always have a consistency between nPulses and // Ensure that we always have a consistency between nPulses and
// periodNumbers containers // periodNumbers containers
if (numPulses != pNumbers.size()) { if (pulseTimes.size() != pNumbers.size()) {
periodNumbers = std::vector<int>(numPulses, FirstPeriod); periodNumbers = std::vector<int>(pulseTimes.size(), FirstPeriod);
; ;
} }
} }
...@@ -75,19 +71,12 @@ BankPulseTimes::BankPulseTimes(::NeXus::File &file, const std::vector<int> &pNum ...@@ -75,19 +71,12 @@ BankPulseTimes::BankPulseTimes(::NeXus::File &file, const std::vector<int> &pNum
* @param times * @param times
*/ */
BankPulseTimes::BankPulseTimes(const std::vector<Mantid::Types::Core::DateAndTime> &times) { BankPulseTimes::BankPulseTimes(const std::vector<Mantid::Types::Core::DateAndTime> &times) {
numPulses = times.size(); if (times.size() == 0)
pulseTimes = nullptr;
if (numPulses == 0)
return; return;
pulseTimes = new Mantid::Types::Core::DateAndTime[numPulses];
periodNumbers = std::vector<int>(numPulses, FirstPeriod); // TODO we are fixing this at 1 period for all
for (size_t i = 0; i < numPulses; i++)
pulseTimes[i] = times[i];
}
//---------------------------------------------------------------------------------------------- pulseTimes = times;
/** Destructor */ periodNumbers = std::vector<int>(pulseTimes.size(), FirstPeriod); // TODO we are fixing this at 1 period for all
BankPulseTimes::~BankPulseTimes() { delete[] this->pulseTimes; } }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
/** Comparison. Is this bank's pulse times array the same as another one. /** Comparison. Is this bank's pulse times array the same as another one.
...@@ -99,5 +88,5 @@ BankPulseTimes::~BankPulseTimes() { delete[] this->pulseTimes; } ...@@ -99,5 +88,5 @@ BankPulseTimes::~BankPulseTimes() { delete[] this->pulseTimes; }
* reloaded. * reloaded.
*/ */
bool BankPulseTimes::equals(size_t otherNumPulse, const std::string &otherStartTime) { bool BankPulseTimes::equals(size_t otherNumPulse, const std::string &otherStartTime) {
return ((this->startTime == otherStartTime) && (this->numPulses == otherNumPulse)); return ((this->startTime == otherStartTime) && (this->pulseTimes.size() == otherNumPulse));
} }
...@@ -154,7 +154,7 @@ void EventAssignerFixedWavelength::addEventImpl(size_t id, int64_t pulse, double ...@@ -154,7 +154,7 @@ void EventAssignerFixedWavelength::addEventImpl(size_t id, int64_t pulse, double
m_eventVectors[id]->emplace_back(m_wavelength); m_eventVectors[id]->emplace_back(m_wavelength);
} }
// FastReadOnlyFile // ISISRawOnlyFile
#ifdef _WIN32 #ifdef _WIN32
FastReadOnlyFile::FastReadOnlyFile(const char *filename) { FastReadOnlyFile::FastReadOnlyFile(const char *filename) {
m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
......
...@@ -55,7 +55,7 @@ void LoadBankFromDiskTask::loadPulseTimes(::NeXus::File &file) { ...@@ -55,7 +55,7 @@ void LoadBankFromDiskTask::loadPulseTimes(::NeXus::File &file) {
return; return;
} }
std::string thisStartTime; std::string thisStartTime;
size_t thisNumPulses = 0; size_t thispulseTimes = 0;
// If the offset is not present, use Unix epoch // If the offset is not present, use Unix epoch
if (!file.hasAttr("offset")) { if (!file.hasAttr("offset")) {
thisStartTime = "1970-01-01T00:00:00Z"; thisStartTime = "1970-01-01T00:00:00Z";
...@@ -66,13 +66,13 @@ void LoadBankFromDiskTask::loadPulseTimes(::NeXus::File &file) { ...@@ -66,13 +66,13 @@ void LoadBankFromDiskTask::loadPulseTimes(::NeXus::File &file) {
} }
if (!file.getInfo().dims.empty()) if (!file.getInfo().dims.empty())
thisNumPulses = file.getInfo().dims[0]; thispulseTimes = file.getInfo().dims[0];
file.closeData(); file.closeData();
// Now, we look through existing ones to see if it is already loaded // Now, we look through existing ones to see if it is already loaded
// thisBankPulseTimes = NULL; // thisBankPulseTimes = NULL;
for (auto &bankPulseTime : m_loader.m_bankPulseTimes) { for (auto &bankPulseTime : m_loader.m_bankPulseTimes) {
if (bankPulseTime->equals(thisNumPulses, thisStartTime)) { if (bankPulseTime->equals(thispulseTimes, thisStartTime)) {
thisBankPulseTimes = bankPulseTime; thisBankPulseTimes = bankPulseTime;
return; return;
} }
...@@ -131,7 +131,7 @@ void LoadBankFromDiskTask::prepareEventId(::NeXus::File &file, int64_t &start_ev ...@@ -131,7 +131,7 @@ void LoadBankFromDiskTask::prepareEventId(::NeXus::File &file, int64_t &start_ev
stop_event = dim0; stop_event = dim0;
// Handle the time filtering by changing the start/end offsets. // Handle the time filtering by changing the start/end offsets.
for (size_t i = 0; i < thisBankPulseTimes->numPulses; i++) { for (size_t i = 0; i < thisBankPulseTimes->pulseTimes.size(); i++) {
if (thisBankPulseTimes->pulseTimes[i] >= m_loader.alg->filter_time_start) { if (thisBankPulseTimes->pulseTimes[i] >= m_loader.alg->filter_time_start) {
start_event = static_cast<int64_t>(event_index[i]); start_event = static_cast<int64_t>(event_index[i]);
break; // stop looking break; // stop looking
...@@ -150,7 +150,7 @@ void LoadBankFromDiskTask::prepareEventId(::NeXus::File &file, int64_t &start_ev ...@@ -150,7 +150,7 @@ void LoadBankFromDiskTask::prepareEventId(::NeXus::File &file, int64_t &start_ev
start_event = 0; start_event = 0;
stop_event = dim0; stop_event = dim0;
} else { } else {
for (size_t i = 0; i < thisBankPulseTimes->numPulses; i++) { for (size_t i = 0; i < thisBankPulseTimes->pulseTimes.size(); i++) {
if (thisBankPulseTimes->pulseTimes[i] > m_loader.alg->filter_time_stop) { if (thisBankPulseTimes->pulseTimes[i] > m_loader.alg->filter_time_stop) {
stop_event = event_index[i]; stop_event = event_index[i];
break; break;
...@@ -353,7 +353,7 @@ void LoadBankFromDiskTask::run() { ...@@ -353,7 +353,7 @@ void LoadBankFromDiskTask::run() {
// The event_index should be the same length as the pulse times from DAS // The event_index should be the same length as the pulse times from DAS
// logs. // logs.
if (event_index.size() != thisBankPulseTimes->numPulses) if (event_index.size() != thisBankPulseTimes->pulseTimes.size())
m_loader.alg->getLogger().warning() << "Bank " << entry_name m_loader.alg->getLogger().warning() << "Bank " << entry_name
<< " has a mismatch between the number of event_index entries " << " has a mismatch between the number of event_index entries "
"and the number of pulse times in event_time_zero.\n"; "and the number of pulse times in event_time_zero.\n";
......
...@@ -985,7 +985,7 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, const bool monitors) ...@@ -985,7 +985,7 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, const bool monitors)
filter_time_start = Types::Core::DateAndTime::minimum(); filter_time_start = Types::Core::DateAndTime::minimum();
filter_time_stop = Types::Core::DateAndTime::maximum(); filter_time_stop = Types::Core::DateAndTime::maximum();
if (m_allBanksPulseTimes->numPulses > 0) { if (m_allBanksPulseTimes->pulseTimes.size() > 0) {
// If not specified, use the limits of doubles. Otherwise, convert from // If not specified, use the limits of doubles. Otherwise, convert from
// seconds to absolute PulseTime // seconds to absolute PulseTime
if (filter_time_start_sec != EMPTY_DBL()) { if (filter_time_start_sec != EMPTY_DBL()) {
......
...@@ -353,6 +353,11 @@ public: ...@@ -353,6 +353,11 @@ public:
virtual ~ISISRAW(); virtual ~ISISRAW();
explicit ISISRAW(ISISCRPT_STRUCT *crpt); explicit ISISRAW(ISISCRPT_STRUCT *crpt);
ISISRAW(ISISCRPT_STRUCT *crpt, bool doUpdateFromCRPT); ISISRAW(ISISCRPT_STRUCT *crpt, bool doUpdateFromCRPT);
// Explicitly prevent copying with all the dynamic allocations
ISISRAW(const ISISRAW &) = delete;
ISISRAW &operator=(ISISRAW) = delete;
int updateFromCRPT(); int updateFromCRPT();
virtual int ioRAW(FILE *file, bool from_file, bool read_data = true); virtual int ioRAW(FILE *file, bool from_file, bool read_data = true);
......
...@@ -104,12 +104,12 @@ void ProcessBankData::run() { // override { ...@@ -104,12 +104,12 @@ void ProcessBankData::run() { // override {
// Default pulse time (if none are found) // Default pulse time (if none are found)
const bool pulsetimesincreasing = const bool pulsetimesincreasing =
std::is_sorted(thisBankPulseTimes->pulseTimes, thisBankPulseTimes->pulseTimes + thisBankPulseTimes->numPulses); std::is_sorted(thisBankPulseTimes->pulseTimes.cbegin(), thisBankPulseTimes->pulseTimes.cend());
if (!std::is_sorted(event_index->cbegin(), event_index->cend())) if (!std::is_sorted(event_index->cbegin(), event_index->cend()))
throw std::runtime_error("Event index is not sorted"); throw std::runtime_error("Event index is not sorted");
// And there are this many pulses // And there are this many pulses
const auto NUM_PULSES = thisBankPulseTimes->numPulses; const auto NUM_PULSES = thisBankPulseTimes->pulseTimes.size();
prog->report(entry_name + ": filling events"); prog->report(entry_name + ": filling events");
// Will we need to compress? // Will we need to compress?
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <fstream> #include <fstream>
#include <iterator> #include <iterator>
#include <map> #include <map>
#include <memory>
#include <sstream> #include <sstream>
namespace Mantid::DataHandling { namespace Mantid::DataHandling {
...@@ -40,8 +41,9 @@ using namespace API; ...@@ -40,8 +41,9 @@ using namespace API;
/// Empty default constructor /// Empty default constructor
SaveISISNexus::SaveISISNexus() SaveISISNexus::SaveISISNexus()
: Algorithm(), m_isisRaw(), handle(), rawFile(), nper(0), nsp(0), ntc(0), nmon(0), ndet(0), counts_link(), : Algorithm(), m_isisRaw(std::make_unique<ISISRAW2>()), handle(), rawFile(), nper(0), nsp(0), ntc(0), nmon(0),
period_index_link(), spectrum_index_link(), time_of_flight_link(), time_of_flight_raw_link() {} ndet(0), counts_link(), period_index_link(), spectrum_index_link(), time_of_flight_link(),
time_of_flight_raw_link() {}
/** Initialisation method. /** Initialisation method.
* *
...@@ -97,18 +99,18 @@ void SaveISISNexus::exec() { ...@@ -97,18 +99,18 @@ void SaveISISNexus::exec() {
// Retrieve the filename from the properties // Retrieve the filename from the properties
inputFilename = getPropertyValue("InputFileName"); inputFilename = getPropertyValue("InputFileName");
m_isisRaw = ISISRAW2(); m_isisRaw = std::make_unique<ISISRAW2>();
rawFile = fopen(inputFilename.c_str(), "rb"); rawFile = fopen(inputFilename.c_str(), "rb");
if (rawFile == nullptr) { if (rawFile == nullptr) {
throw Exception::FileError("Cannot open file ", inputFilename); throw Exception::FileError("Cannot open file ", inputFilename);
} }
m_isisRaw.ioRAW(rawFile, true); m_isisRaw->ioRAW(rawFile, true);
nper = m_isisRaw.t_nper; // number of periods nper = m_isisRaw->t_nper; // number of periods
nsp = m_isisRaw.t_nsp1; // number of spectra nsp = m_isisRaw->t_nsp1; // number of spectra
ntc = m_isisRaw.t_ntc1; // number of time channels ntc = m_isisRaw->t_ntc1; // number of time channels
nmon = m_isisRaw.i_mon; // number of monitors nmon = m_isisRaw->i_mon; // number of monitors
ndet = m_isisRaw.i_det; // number of detectors ndet = m_isisRaw->i_det; // number of detectors
std::string outputFilename = getPropertyValue("OutputFileName"); std::string outputFilename = getPropertyValue("OutputFileName");
...@@ -124,7 +126,7 @@ void SaveISISNexus::exec() { ...@@ -124,7 +126,7 @@ void SaveISISNexus::exec() {
write_isis_vms_compat(); write_isis_vms_compat();
saveString("beamline", " "); saveString("beamline", " ");
flt = static_cast<float>(m_isisRaw.rpb.r_dur); // could be wrong flt = static_cast<float>(m_isisRaw->rpb.r_dur); // could be wrong
saveFloatOpen("collection_time", &flt, 1); saveFloatOpen("collection_time", &flt, 1);
putAttr("units", "second"); putAttr("units", "second");
close(); close();
...@@ -139,32 +141,32 @@ void SaveISISNexus::exec() { ...@@ -139,32 +141,32 @@ void SaveISISNexus::exec() {
putAttr("url", "http://svn.isis.rl.ac.uk/instruments/ISISTOFRAW/?version=1.0"); putAttr("url", "http://svn.isis.rl.ac.uk/instruments/ISISTOFRAW/?version=1.0");
close(); close();
flt = static_cast<float>(m_isisRaw.rpb.r_dur); flt = static_cast<float>(m_isisRaw->rpb.r_dur);
saveFloatOpen("duration", &flt, 1); saveFloatOpen("duration", &flt, 1);
putAttr("units", "second"); putAttr("units", "second");
close(); close();
start_time_str.assign(m_isisRaw.hdr.hd_date, m_isisRaw.hdr.hd_date + 12); start_time_str.assign(m_isisRaw->hdr.hd_date, m_isisRaw->hdr.hd_date + 12);
toISO8601(start_time_str); toISO8601(start_time_str);
start_time_str += 'T'; start_time_str += 'T';
start_time_str += std::string(m_isisRaw.hdr.hd_time, m_isisRaw.hdr.hd_time + 8); start_time_str += std::string(m_isisRaw->hdr.hd_time, m_isisRaw->hdr.hd_time + 8);
saveCharOpen("start_time", &start_time_str[0], 19); saveCharOpen("start_time", &start_time_str[0], 19);
putAttr("units", "ISO8601"); putAttr("units", "ISO8601");
close(); close();
std::string str; std::string str;
str.assign(m_isisRaw.rpb.r_enddate, m_isisRaw.rpb.r_enddate + 12); str.assign(m_isisRaw->rpb.r_enddate, m_isisRaw->rpb.r_enddate + 12);
toISO8601(str); toISO8601(str);
str += 'T'; str += 'T';
str += std::string(m_isisRaw.rpb.r_endtime, m_isisRaw.rpb.r_endtime + 8); str += std::string(m_isisRaw->rpb.r_endtime, m_isisRaw->rpb.r_endtime + 8);
saveCharOpen("end_time", &str[0], 19); saveCharOpen("end_time", &str[0], 19);
putAttr("units", "ISO8601"); putAttr("units", "ISO8601");
close(); close();
saveChar("title", m_isisRaw.r_title, 80); saveChar("title", m_isisRaw->r_title, 80);
saveInt("good_frames", &m_isisRaw.rpb.r_goodfrm); saveInt("good_frames", &m_isisRaw->rpb.r_goodfrm);
std::string experiment_identifier = std::to_string(m_isisRaw.rpb.r_prop); std::string experiment_identifier = std::to_string(m_isisRaw->rpb.r_prop);
saveChar("experiment_identifier", &experiment_identifier[0], static_cast<int>(experiment_identifier.size())); saveChar("experiment_identifier", &experiment_identifier[0], static_cast<int>(experiment_identifier.size()));
int tmp_int(0); int tmp_int(0);
saveInt("measurement_first_run", &tmp_int); saveInt("measurement_first_run", &tmp_int);
...@@ -173,27 +175,27 @@ void SaveISISNexus::exec() { ...@@ -173,27 +175,27 @@ void SaveISISNexus::exec() {
saveString("measurement_subid", " "); saveString("measurement_subid", " ");
saveString("measurement_type", " "); saveString("measurement_type", " ");
saveCharOpen("name", &m_isisRaw.i_inst, 8); saveCharOpen("name", &m_isisRaw->i_inst, 8);
putAttr("short_name", m_isisRaw.hdr.inst_abrv, 3); putAttr("short_name", m_isisRaw->hdr.inst_abrv, 3);
close(); close();
logNotes(); logNotes();
saveString("program_name", "isisicp"); saveString("program_name", "isisicp");
saveFloatOpen("proton_charge", &m_isisRaw.rpb.r_gd_prtn_chrg, 1); saveFloatOpen("proton_charge", &m_isisRaw->rpb.r_gd_prtn_chrg, 1);
putAttr("units", "uamp.hour"); putAttr("units", "uamp.hour");
close(); close();
saveFloatOpen("proton_charge_raw", &m_isisRaw.rpb.r_tot_prtn_chrg, 1); saveFloatOpen("proton_charge_raw", &m_isisRaw->rpb.r_tot_prtn_chrg, 1);
putAttr("units", "uamp.hour"); putAttr("units", "uamp.hour");
close(); close();
saveInt("raw_frames", &m_isisRaw.rpb.r_rawfrm); saveInt("raw_frames", &m_isisRaw->rpb.r_rawfrm);
run_cycle(); run_cycle();
saveInt("run_number", &m_isisRaw.r_number); saveInt("run_number", &m_isisRaw->r_number);
// script_name // script_name
// seci_config // seci_config
...@@ -383,67 +385,67 @@ void SaveISISNexus::toISO8601(std::string &str) { ...@@ -383,67 +385,67 @@ void SaveISISNexus::toISO8601(std::string &str) {
void SaveISISNexus::write_isis_vms_compat() { void SaveISISNexus::write_isis_vms_compat() {
NXmakegroup(handle, "isis_vms_compat", "IXvms"); NXmakegroup(handle, "isis_vms_compat", "IXvms");
NXopengroup(handle, "isis_vms_compat", "IXvms"); NXopengroup(handle, "isis_vms_compat", "IXvms");
int ndet = m_isisRaw.i_det; int ndet = m_isisRaw->i_det;
int nmon = m_isisRaw.i_mon; int nmon = m_isisRaw->i_mon;
saveInt("ADD", &m_isisRaw.add, 9); saveInt("ADD", &m_isisRaw->add, 9);
saveInt("CODE", m_isisRaw.code, ndet); saveInt("CODE", m_isisRaw->code, ndet);
saveInt("CRAT", m_isisRaw.crat, ndet); saveInt("CRAT", m_isisRaw->crat, ndet);
write_rpb(); write_rpb();
write_spb(); write_spb();
write_vpb(); write_vpb();
saveInt("DAEP", &m_isisRaw.daep, 64); saveInt("DAEP", &m_isisRaw->daep, 64);
saveInt("DELT", m_isisRaw.delt, ndet); saveInt("DELT", m_isisRaw->delt, ndet);
saveInt("FORM", &m_isisRaw.data_format); saveInt("FORM", &m_isisRaw->data_format);
saveChar("HDR", &m_isisRaw.hdr, 80); saveChar("HDR", &m_isisRaw->hdr, 80);
saveFloat("LEN2", m_isisRaw.len2, ndet); saveFloat("LEN2", m_isisRaw->len2, ndet);
saveInt("MDET", m_isisRaw.mdet, nmon); saveInt("MDET", m_isisRaw->mdet, nmon);
saveInt("MODN", m_isisRaw.modn, ndet); saveInt("MODN", m_isisRaw->modn, ndet);
saveInt("MONP", m_isisRaw.monp, nmon); saveInt("MONP", m_isisRaw->monp, nmon);
saveInt("MPOS", m_isisRaw.mpos, ndet); saveInt("MPOS", m_isisRaw->mpos, ndet);
saveChar("NAME", m_isisRaw.i_inst, 8); saveChar("NAME", m_isisRaw->i_inst, 8);
saveInt("NDET", &ndet); saveInt("NDET", &ndet);
saveInt("NFPP", &m_isisRaw.t_nfpp); saveInt("NFPP", &m_isisRaw->t_nfpp);
saveInt("NMON", &nmon); saveInt("NMON", &nmon);
saveInt("NPER", &m_isisRaw.t_nper); saveInt("NPER", &m_isisRaw->t_nper);
saveInt("NSER", &m_isisRaw.e_nse); saveInt("NSER", &m_isisRaw->e_nse);
saveInt("NSP1", &m_isisRaw.t_nsp1); saveInt("NSP1", &m_isisRaw->t_nsp1);
saveInt("NTC1", &m_isisRaw.t_ntc1); saveInt("NTC1", &m_isisRaw->t_ntc1);
saveInt("NTRG", &m_isisRaw.t_ntrg); saveInt("NTRG", &m_isisRaw->t_ntrg);
saveInt("NUSE", &m_isisRaw.i_use); saveInt("NUSE", &m_isisRaw->i_use);
saveInt("PMAP", &m_isisRaw.t_pmap, 256); saveInt("PMAP", &m_isisRaw->t_pmap, 256);