Interim commit - resmed_loader still needs work

This commit is contained in:
Phil Olynyk 2019-07-31 14:36:40 -04:00
parent 93b363465f
commit 531edc6ad2
4 changed files with 361 additions and 361 deletions

View File

@ -19,100 +19,104 @@
#include "edfparser.h" #include "edfparser.h"
EDFParser::EDFParser(QString name) EDFInfo::EDFInfo()
{ {
filesize = 0; filesize = 0;
datasize = 0; datasize = 0;
signalPtr = nullptr; signalPtr = nullptr;
hdrPtr = nullptr; hdrPtr = nullptr;
fileData.clear(); fileData = nullptr;
if (!name.isEmpty())
Open(name);
} }
EDFParser::~EDFParser()
EDFInfo::~EDFInfo()
{ {
for (auto & s : edfsignals) { for (auto & s : edfsignals) {
if (s.value) if (s.value)
delete [] s.value; delete [] s.value;
} }
// for (auto & a : annotations)
// delete a;
} }
bool EDFParser::Open(const QString & name) QByteArray * EDFInfo::Open(const QString & name)
{ {
if (hdrPtr != nullptr) { if (hdrPtr != nullptr) {
qWarning() << "EDFParser::Open() called with file already open " << name; qWarning() << "EDFInfo::Open() called with file already open " << name;
sleep(1); sleep(1);
return false; return nullptr;
} }
QFile fi(name); QFile fi(name);
if (!fi.open(QFile::ReadOnly)) { if (!fi.open(QFile::ReadOnly)) {
qDebug() << "EDFParser::Open() Couldn't open file " << name; qDebug() << "EDFInfo::Open() Couldn't open file " << name;
sleep(1); sleep(1);
return false; return nullptr;
} }
fileData = new QByteArray();
if (name.endsWith(STR_ext_gz)) { if (name.endsWith(STR_ext_gz)) {
fileData = gUncompress(fi.readAll()); // Open and decompress file *fileData = gUncompress(fi.readAll()); // Open and decompress file
} else { } else {
fileData = fi.readAll(); // Open and read uncompressed file *fileData = fi.readAll(); // Open and read uncompressed file
} }
fi.close(); fi.close();
if (fileData.size() <= EDFHeaderSize) { if (fileData->size() <= EDFHeaderSize) {
qDebug() << "EDFParser::Open() File too short " << name; delete fileData;
qDebug() << "EDFInfo::Open() File too short " << name;
sleep(1); sleep(1);
return false; return nullptr;
} }
hdrPtr = (EDFHeaderRaw *)fileData.constData();
signalPtr = (char *)fileData.constData() + EDFHeaderSize;
filename = name; filename = name;
filesize = fileData.size(); return fileData;
datasize = filesize - EDFHeaderSize;
pos = 0;
return true;
} }
bool EDFParser::Parse() bool EDFInfo::Parse(QByteArray * fileData )
{ {
bool ok; bool ok;
if (hdrPtr == nullptr) { if (fileData == nullptr) {
qWarning() << "EDFParser::Parse() called without valid EDF data " << filename; qWarning() << "EDFInfo::Parse() called without valid EDF data " << filename;
sleep(1); sleep(1);
return false; return false;
} }
hdrPtr = (EDFHeaderRaw *)(*fileData).constData();
signalPtr = (char *)(*fileData).constData() + EDFHeaderSize;
filesize = (*fileData).size();
datasize = filesize - EDFHeaderSize;
pos = 0;
eof = false; eof = false;
edfHdr.version = QString::fromLatin1(hdrPtr->version, 8).toLong(&ok); edfHdr.version = QString::fromLatin1(hdrPtr->version, 8).toLong(&ok);
if (!ok) { if (!ok) {
qWarning() << "EDFParser::Parser() Bad Version " << filename; qWarning() << "EDFInfo::Parse() Bad Version " << filename;
sleep(1); sleep(1);
return false; return false;
} }
//patientident=QString::fromLatin1(header.patientident,80); edfHdr.patientident=QString::fromLatin1(hdrPtr->patientident,80);
edfHdr.recordingident = QString::fromLatin1(hdrPtr->recordingident, 80); // Serial number is in here.. edfHdr.recordingident = QString::fromLatin1(hdrPtr->recordingident, 80); // Serial number is in here..
edfHdr.startdate_orig = QDateTime::fromString(QString::fromLatin1(hdrPtr->datetime, 16), "dd.MM.yyHH.mm.ss"); edfHdr.startdate_orig = QDateTime::fromString(QString::fromLatin1(hdrPtr->datetime, 16), "dd.MM.yyHH.mm.ss");
edfHdr.num_header_bytes = QString::fromLatin1(hdrPtr->num_header_bytes, 8).toLong(&ok); edfHdr.num_header_bytes = QString::fromLatin1(hdrPtr->num_header_bytes, 8).toLong(&ok);
if (!ok) { if (!ok) {
qWarning() << "EDFParser::Parde() Bad header byte count " << filename; qWarning() << "EDFInfo::Parse() Bad header byte count " << filename;
sleep(1); sleep(1);
return false; return false;
} }
edfHdr.reserved44=QString::fromLatin1(hdrPtr->reserved, 44); edfHdr.reserved44=QString::fromLatin1(hdrPtr->reserved, 44);
edfHdr.num_data_records = QString::fromLatin1(hdrPtr->num_data_records, 8).toLong(&ok); edfHdr.num_data_records = QString::fromLatin1(hdrPtr->num_data_records, 8).toLong(&ok);
if (!ok) { if (!ok) {
qWarning() << "EDFParser::Parse() Bad data record count " << filename; qWarning() << "EDFInfo::Parse() Bad data record count " << filename;
sleep(1); sleep(1);
return false; return false;
} }
edfHdr.duration_Seconds = QString::fromLatin1(hdrPtr->dur_data_records, 8).toDouble(&ok); edfHdr.duration_Seconds = QString::fromLatin1(hdrPtr->dur_data_records, 8).toDouble(&ok);
if (!ok) { if (!ok) {
qWarning() << "EDFParser::Parse() Bad duration " << filename; qWarning() << "EDFInfo::Parse() Bad duration " << filename;
sleep(1); sleep(1);
return false; return false;
} }
edfHdr.num_signals = QString::fromLatin1(hdrPtr->num_signals, 4).toLong(&ok); edfHdr.num_signals = QString::fromLatin1(hdrPtr->num_signals, 4).toLong(&ok);
if (!ok) { if (!ok) {
qWarning() << "EDFParser::Parse() Bad number of signals " << filename; qWarning() << "EDFInfo::Parse() Bad number of signals " << filename;
sleep(1); sleep(1);
return false; return false;
} }
@ -123,49 +127,49 @@ bool EDFParser::Parse()
// Now copy all the Signal descriptives into edfsignals // Now copy all the Signal descriptives into edfsignals
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.value = nullptr; sig.value = nullptr;
sig.label = Read(16); sig.label = ReadBytes(16);
signal_labels.push_back(sig.label); signal_labels.push_back(sig.label);
signalList[sig.label].push_back(&sig); signalList[sig.label].push_back(&sig);
if (eof) { if (eof) {
qWarning() << "EDFParser::Parse() Early end of file " << filename; qWarning() << "EDFInfo::Parse() Early end of file " << filename;
sleep(1); sleep(1);
return false; return false;
} }
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.transducer_type = Read(80); sig.transducer_type = ReadBytes(80);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.physical_dimension = Read(8); sig.physical_dimension = ReadBytes(8);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.physical_minimum = Read(8).toDouble(&ok); sig.physical_minimum = ReadBytes(8).toDouble(&ok);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.physical_maximum = Read(8).toDouble(&ok); sig.physical_maximum = ReadBytes(8).toDouble(&ok);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.digital_minimum = Read(8).toDouble(&ok); sig.digital_minimum = ReadBytes(8).toDouble(&ok);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.digital_maximum = Read(8).toDouble(&ok); sig.digital_maximum = ReadBytes(8).toDouble(&ok);
sig.gain = (sig.physical_maximum - sig.physical_minimum) / (sig.digital_maximum - sig.digital_minimum); sig.gain = (sig.physical_maximum - sig.physical_minimum) / (sig.digital_maximum - sig.digital_minimum);
sig.offset = 0; sig.offset = 0;
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.prefiltering = Read(80); sig.prefiltering = ReadBytes(80);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.nr = Read(8).toLong(&ok); sig.nr = ReadBytes(8).toLong(&ok);
} }
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
sig.reserved = Read(32); sig.reserved = ReadBytes(32);
} }
// could do it earlier, but it won't crash from > EOF Reads // could do it earlier, but it won't crash from > EOF Reads
if (eof) { if (eof) {
qWarning() << "EDFParser::Parse() Early end of file " << filename; qWarning() << "EDFInfo::Parse() Early end of file " << filename;
sleep(1); sleep(1);
return false; return false;
} }
@ -180,7 +184,7 @@ bool EDFParser::Parse()
if (allocsize > (datasize - pos)) { if (allocsize > (datasize - pos)) {
// Space required more than the remainder left to read, // Space required more than the remainder left to read,
// so abort and let the user clean up the corrupted file themselves // so abort and let the user clean up the corrupted file themselves
qWarning() << "EDFParser::Parse(): " << filename << " is too short!"; qWarning() << "EDFInfo::Parse(): " << filename << " is too short!";
sleep(1); sleep(1);
return false; return false;
} }
@ -197,6 +201,10 @@ bool EDFParser::Parse()
} }
for (int x = 0; x < edfHdr.num_data_records; x++) { for (int x = 0; x < edfHdr.num_data_records; x++) {
for (auto & sig : edfsignals) { for (auto & sig : edfsignals) {
if ( sig.label.contains("ANNOTATIONS") ) {
annotations.push_back(ReadAnnotations( (char *)&signalPtr[pos], sig.nr*2));
pos += sig.nr * 2;
} else { // it's got genuine 16-bit values
#ifdef Q_LITTLE_ENDIAN #ifdef Q_LITTLE_ENDIAN
// Intel x86, etc.. // Intel x86, etc..
memcpy((char *)&sig.value[sig.pos], (char *)&signalPtr[pos], sig.nr * 2); memcpy((char *)&sig.value[sig.pos], (char *)&signalPtr[pos], sig.nr * 2);
@ -211,47 +219,102 @@ bool EDFParser::Parse()
#endif #endif
} }
} }
// Now massage some stuff into OSCAR's layout
int snp = edfHdr.recordingident.indexOf("SRN=");
serialnumber.clear();
for (int i = snp + 4; i < edfHdr.recordingident.length(); i++) {
if (edfHdr.recordingident[i] == ' ') {
break;
} }
serialnumber += edfHdr.recordingident[i];
}
QDate d2 = edfHdr.startdate_orig.date();
if (d2.year() < 2000) {
d2.setDate(d2.year() + 100, d2.month(), d2.day());
edfHdr.startdate_orig.setDate(d2);
}
if (!edfHdr.startdate_orig.isValid()) {
qDebug() << "Invalid date time retreieved parsing EDF File " << filename;
sleep(1);
return false;
}
startdate = qint64(edfHdr.startdate_orig.toTime_t()) * 1000LL;
//startdate-=timezoneOffset();
if (startdate == 0) {
qDebug() << "Invalid startdate = 0 in EDF File " << filename;
sleep(1);
return false;
}
dur_data_record = (edfHdr.duration_Seconds * 1000.0L);
enddate = startdate + dur_data_record * qint64(edfHdr.num_data_records);
return true; return true;
} }
// Parse the EDF file to get the annotations out of it.
QVector<Annotation> * EDFInfo::ReadAnnotations(const char * data, int charLen)
{
QVector<Annotation> * annoVec = new QVector<Annotation>;
// Process event annotation record
long pos = 0;
double offset;
double duration;
while (pos < charLen) {
QString text;
bool sign, ok;
char c = data[pos];
if ((c != '+') && (c != '-')) // Annotaion must start with a +/- sign
break;
sign = (data[pos++] == '+');
text = "";
c = data[pos];
do { // collect the offset
text += c;
pos++;
c = data[pos];
} while ((c != AnnoSep) && (c != AnnoDurMark)); // a duration is optional
offset = text.toDouble(&ok);
if (!ok) {
qDebug() << "Faulty offset in annotation record ";
// sleep(1);
break;
}
if (!sign)
offset = -offset;
duration = -1.0; // This indicates no duration supplied
// First entry
if (data[pos] == AnnoDurMark) { // get duration.(preceded by decimal 21 byte)
pos++;
text = "";
do { // collect the duration
text += data[pos];
pos++;
} while ((data[pos] != AnnoSep) && (pos < charLen)); // separator code
duration = text.toDouble(&ok);
if (!ok) {
qDebug() << "Faulty duration in annotation record ";
// sleep(1);
break;
}
}
while ((data[pos] == AnnoSep) && (pos < charLen)) {
int textLen = 0;
pos++;
const char * textStart = &data[pos];
if (data[pos] == AnnoEnd)
break;
if (data[pos] == AnnoSep) {
pos++;
break;
}
do { // collect the annotation text
pos++; // officially UTF-8 is allowed here, so don't mangle it
textLen++;
} while ((data[pos] != AnnoSep) && (pos < charLen)); // separator code
text.fromUtf8(textStart, textLen);
annoVec->push_back( Annotation( offset, duration, text) );
if (pos >= charLen) {
qDebug() << "Short EDF Annotations record";
// sleep(1);
break;
}
}
while ((pos < charLen) && (data[pos] == AnnoEnd))
pos++;
if (pos >= charLen)
break;
}
return annoVec;
}
// Read a 16 bits integer // Read a 16 bits integer
qint16 EDFParser::Read16() qint16 EDFInfo::Read16()
{ {
if ((pos + 2) > datasize) { if ((pos + 2) > datasize) {
eof = true; eof = true;
@ -266,7 +329,7 @@ qint16 EDFParser::Read16()
return res; return res;
} }
QString EDFParser::Read(unsigned n) QString EDFInfo::ReadBytes(unsigned n)
{ {
if ((pos + long(n)) > datasize) { if ((pos + long(n)) > datasize) {
eof = true; eof = true;
@ -277,7 +340,7 @@ QString EDFParser::Read(unsigned n)
return buf.trimmed(); return buf.trimmed();
} }
EDFSignal *EDFParser::lookupLabel(const QString & name, int index) EDFSignal *EDFInfo::lookupLabel(const QString & name, int index)
{ {
auto it = signalList.find(name); auto it = signalList.find(name);
if (it == signalList.end()) if (it == signalList.end())

View File

@ -57,8 +57,8 @@ struct EDFHeaderQT {
long num_header_bytes; long num_header_bytes;
QString reserved44; QString reserved44;
long num_data_records; long num_data_records;
long duration_Seconds; double duration_Seconds;
long num_signals; int num_signals;
}; };
/*! \struct EDFSignal /*! \struct EDFSignal
@ -80,79 +80,87 @@ struct EDFSignal {
long nr; //! \brief Number of records long nr; //! \brief Number of records
QString reserved; //! \brief Reserved (usually blank) QString reserved; //! \brief Reserved (usually blank)
qint16 *value; //! \brief Pointer to the signals sample data qint16 *value; //! \brief Pointer to the signals sample data
int pos; //! \brief a non-EDF extra used internally to count the signal data int pos; //! \brief a non-EDF extra used internally to count the signal data
}; };
/*! \class Annotation
\author Phil Olynyk
\brief Hold the annotation text from an EDF file
*/
class Annotation
{
public:
Annotation() { duration = -1.0; };
Annotation( double off, double dur, QString tx ) {
offset = off;
duration = dur;
text = tx;
};
virtual ~Annotation() {};
/*! \class EDFParser double offset;
double duration;
QString text;
};
/*! \class EDFInfo
\author Phil Olynyk
\author Mark Watkins <mark@jedimark.net> \author Mark Watkins <mark@jedimark.net>
\brief Parse an EDF+ data file into a list of EDFSignal's \brief Parse an EDF+ data file into a list of EDFSignal's
\note More information on the EDF+ file format can be obtained from http://edfplus.info \note More information on the EDF+ file format can be obtained from http://edfplus.info
*/ */
class EDFParser class EDFInfo
{ {
public: public:
//! \brief Constructs an EDFParser object, opening the filename if one supplied //! \brief Constructs an EDFParser object, opening the filename if one supplied
EDFParser(QString filename = ""); EDFInfo();
~EDFParser(); virtual ~EDFInfo();
//! \brief Open the EDF+ file, and read it's header virtual QByteArray * Open(const QString & name); //! \brief Open the EDF+ file, and read it's header
bool Open(const QString & name);
//! \brief Parse the EDF+ file into the list of EDFSignals.. Must be call Open(..) first. virtual bool Parse(QByteArray * fileData); //! \brief Parse the EDF+ file into the EDFheaderQT. Must call Open(..) first.
bool Parse();
//! \brief Read n bytes of 8 bit data from the EDF+ data stream virtual EDFSignal *lookupLabel(const QString & name, int index=0); //! \brief Return a ptr to the i'th signal with that name
QString Read(unsigned n);
//! \brief Read 16 bit word of data from the EDF+ data stream virtual long GetNumSignals() { return edfHdr.num_signals; } //! \brief Returns the number of signals contained in this EDF file
qint16 Read16();
//! \brief Return a ptr to the i'th signal with the given name (if multiple signal with the same name(?!)) virtual long GetNumDataRecords() { return edfHdr.num_data_records; } //! \brief Returns the number of data records contained per signal.
EDFSignal *lookupLabel(const QString & name, int index=0);
//! \brief Returns the number of signals contained in this EDF file virtual double GetDuration() { return edfHdr.duration_Seconds; } //! \brief Returns the duration represented by this EDF file
long GetNumSignals() { return edfHdr.num_signals; }
//! \brief Returns the number of data records contained per signal. virtual QString GetPatient() { return edfHdr.patientident; } //! \brief Returns the patientid field from the EDF header
long GetNumDataRecords() { return edfHdr.num_data_records; }
//! \brief Returns the duration represented by this EDF file (in milliseconds)
qint64 GetDuration() { return dur_data_record; }
//! \brief Returns the patientid field from the EDF header
QString GetPatient() { return edfHdr.patientident; }
// The data members follow // The data members follow
//! \brief The header in a QT friendly form QString filename; //! \brief For debug and error messages
EDFHeaderQT edfHdr;
//! \brief Vector containing the list of EDFSignals contained in this edf file EDFHeaderQT edfHdr; //! \brief The header in a QT friendly form
QVector<EDFSignal> edfsignals;
//! \brief An by-name indexed into the EDFSignal data QVector<EDFSignal> edfsignals; //! \brief Holds the EDFSignals contained in this edf file
QStringList signal_labels;
//! \brief ResMed sometimes re-uses the SAME signal name QVector< QVector<Annotation> * > annotations; //! \brief Holds the Annotaions for this EDF file
QHash<QString, QList<EDFSignal *> > signalList;
//! \brief The following are computed from the edfHdr data QStringList signal_labels; //! \brief An by-name indexed into the EDFSignal data
QString serialnumber;
qint64 dur_data_record; QHash<QString, QList<EDFSignal *> > signalList; //! \brief ResMed sometimes re-uses the SAME signal name
qint64 startdate;
qint64 enddate;
// the following could be private // the following could be private
private:
QVector<Annotation> * ReadAnnotations( const char * data, int charLen ); //! \brief Create an Annotaion vector from the signal values
QString ReadBytes(unsigned n); //! \brief Read n bytes of 8 bit data from the EDF+ data stream
qint16 Read16(); //! \brief Read 16 bit word of data from the EDF+ data stream
//! \brief This is the array holding the EDF file data //! \brief This is the array holding the EDF file data
QByteArray fileData; QByteArray * fileData;
//! \brief The EDF+ files header structure, used as a place holder while processing the text data. //! \brief The EDF+ files header structure, used as a place holder while processing the text data.
EDFHeaderRaw *hdrPtr; EDFHeaderRaw *hdrPtr;
//! \brief This is the array of signal descriptors and values //! \brief This is the array of signal descriptors and values
char *signalPtr; char *signalPtr;
QString filename;
long filesize; long filesize;
long datasize; long datasize;
long pos; long pos;

View File

@ -59,11 +59,54 @@ const QString STR_ext_TGT = "tgt";
const QString STR_ext_CRC = "crc"; const QString STR_ext_CRC = "crc";
ResMedEDFParser::ResMedEDFParser(QString filename) :EDFParser(filename) { } ResMedEDFInfo::ResMedEDFInfo() :EDFInfo() { }
ResMedEDFParser::~ResMedEDFParser() { } ResMedEDFInfo::~ResMedEDFInfo() { }
bool ResMedEDFInfo::Parse(QByteArray * fileData ) // overrides and calls the super's Parse
{
EDFInfo::Parse( fileData );
// Now massage some stuff into OSCAR's layout
int snp = edfHdr.recordingident.indexOf("SRN=");
serialnumber.clear();
for (int i = snp + 4; i < edfHdr.recordingident.length(); i++) {
if (edfHdr.recordingident[i] == ' ') {
break;
}
serialnumber += edfHdr.recordingident[i];
}
QDate d2 = edfHdr.startdate_orig.date();
if (d2.year() < 2000) {
d2.setDate(d2.year() + 100, d2.month(), d2.day());
edfHdr.startdate_orig.setDate(d2);
}
if (!edfHdr.startdate_orig.isValid()) {
qDebug() << "Invalid date time retreieved parsing EDF File " << filename;
sleep(1);
return false;
}
startdate = qint64(edfHdr.startdate_orig.toTime_t()) * 1000LL;
//startdate-=timezoneOffset();
if (startdate == 0) {
qDebug() << "Invalid startdate = 0 in EDF File " << filename;
sleep(1);
return false;
}
dur_data_record = (edfHdr.duration_Seconds * 1000.0L);
enddate = startdate + dur_data_record * qint64(edfHdr.num_data_records);
return true;
}
// Looks up foreign language Signal names that match this channelID // Looks up foreign language Signal names that match this channelID
EDFSignal *ResMedEDFParser::lookupSignal(ChannelID ch) EDFSignal *ResMedEDFInfo::lookupSignal(ChannelID ch)
{ {
// Get list of all known foreign language names for this channel // Get list of all known foreign language names for this channel
auto channames = resmed_codes.find(ch); auto channames = resmed_codes.find(ch);
@ -113,7 +156,7 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
int totalRecs = 0; int totalRecs = 0;
for (auto it=STRmap.begin(), end=STRmap.end(); it != end; ++it) { for (auto it=STRmap.begin(), end=STRmap.end(); it != end; ++it) {
STRFile & file = it.value(); STRFile & file = it.value();
ResMedEDFParser & str = *file.edf; ResMedEDFInfo & str = *file.edf;
totalRecs += str.GetNumDataRecords(); totalRecs += str.GetNumDataRecords();
} }
@ -126,7 +169,7 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
for (auto it=STRmap.begin(), end=STRmap.end(); it != end; ++it) { for (auto it=STRmap.begin(), end=STRmap.end(); it != end; ++it) {
STRFile & file = it.value(); STRFile & file = it.value();
QString & strfile = file.filename; QString & strfile = file.filename;
ResMedEDFParser & str = *file.edf; ResMedEDFInfo & str = *file.edf;
QDate date = str.edfHdr.startdate_orig.date(); // each STR.edf record starts at 12 noon QDate date = str.edfHdr.startdate_orig.date(); // each STR.edf record starts at 12 noon
@ -569,7 +612,7 @@ ResmedLoader::ResmedLoader() {
m_type = MT_CPAP; m_type = MT_CPAP;
timeInTimeDelta = timeInLoadBRP = timeInLoadPLD = timeInLoadEVE = 0; timeInTimeDelta = timeInLoadBRP = timeInLoadPLD = timeInLoadEVE = 0;
timeInLoadCSL = timeInLoadSAD = timeInEDFParser = timeInEDFOpen = timeInAddWaveform = 0; timeInLoadCSL = timeInLoadSAD = timeInEDFInfo = timeInEDFOpen = timeInAddWaveform = 0;
} }
@ -675,8 +718,9 @@ EDFType lookupEDFType(const QString & text)
// Pretend to parse the EVE file to get the duration out of it. // Pretend to parse the EVE file to get the duration out of it.
int PeekAnnotations(const QString & path, quint32 &start, quint32 &end) int PeekAnnotations(const QString & path, quint32 &start, quint32 &end)
{ {
ResMedEDFParser edf(path); ResMedEDFInfo edf;
if (!edf.Parse()) QByteArray * fileData = edf.Open(path);
if (!edf.Parse(fileData))
return -1; return -1;
QString t; QString t;
@ -895,7 +939,7 @@ EDFduration getEDFDuration(const QString & filename)
// Have to get the actual duration of the EVE file by parsing the annotations. :( // Have to get the actual duration of the EVE file by parsing the annotations. :(
// Can we cache the stupid EDFParser file for later ??? // Can we cache the stupid EDFInfo file for later ???
int recs = PeekAnnotations(filename, st2, en2); int recs = PeekAnnotations(filename, st2, en2);
if (recs > 0) { if (recs > 0) {
@ -1764,8 +1808,9 @@ int ResmedLoader::Open(const QString & dirpath)
// Now place any of these files in the Backup folder sorted by the file date // Now place any of these files in the Backup folder sorted by the file date
for (auto & filename : strfiles) { for (auto & filename : strfiles) {
ResMedEDFParser * stredf = new ResMedEDFParser(filename); ResMedEDFInfo * stredf = new ResMedEDFInfo();
if ( ! stredf->Parse()) { QByteArray * fileData = stredf->Open(filename);
if ( ! stredf->Parse(fileData)) {
qDebug() << "Faulty STR file" << filename; qDebug() << "Faulty STR file" << filename;
delete stredf; delete stredf;
continue; continue;
@ -1838,8 +1883,9 @@ int ResmedLoader::Open(const QString & dirpath)
if (STRmap.contains(date)) if (STRmap.contains(date))
continue; continue;
ResMedEDFParser * stredf = new ResMedEDFParser(fi.canonicalFilePath()); ResMedEDFInfo * stredf = new ResMedEDFInfo();
if (!stredf->Parse()) { QByteArray * fileData = stredf->Open(fi.canonicalFilePath() );
if (!stredf->Parse(fileData)) {
qDebug() << "Faulty STR file" << filename; qDebug() << "Faulty STR file" << filename;
delete stredf; delete stredf;
continue; continue;
@ -2002,7 +2048,7 @@ int ResmedLoader::Open(const QString & dirpath)
qDebug() << "Total toTimeDelta function usage:" << totalbytes << "in" << double(totalns) / 1000000000.0 << "seconds"; qDebug() << "Total toTimeDelta function usage:" << totalbytes << "in" << double(totalns) / 1000000000.0 << "seconds";
qDebug() << "Total CPU time in EDF Open" << timeInEDFOpen; qDebug() << "Total CPU time in EDF Open" << timeInEDFOpen;
qDebug() << "Total CPU time in EDF Parser" << timeInEDFParser; qDebug() << "Total CPU time in EDF Parser" << timeInEDFInfo;
qDebug() << "Total CPU time in LoadBRP" << timeInLoadBRP; qDebug() << "Total CPU time in LoadBRP" << timeInLoadBRP;
qDebug() << "Total CPU time in LoadPLD" << timeInLoadPLD; qDebug() << "Total CPU time in LoadPLD" << timeInLoadPLD;
qDebug() << "Total CPU time in LoadSAD" << timeInLoadSAD; qDebug() << "Total CPU time in LoadSAD" << timeInLoadSAD;
@ -2013,10 +2059,10 @@ int ResmedLoader::Open(const QString & dirpath)
} }
#endif #endif
sessfiles.clear(); // sessfiles.clear();
strsess.clear(); // strsess.clear();
// strdate.clear();
strdate.clear();
channel_efficiency.clear(); channel_efficiency.clear();
channel_time.clear(); channel_time.clear();
@ -2098,14 +2144,15 @@ bool ResmedLoader::LoadCSL(Session *sess, const QString & path)
time.start(); time.start();
#endif #endif
ResMedEDFParser edf(path); ResMedEDFInfo edf;
QByteArray * fileData = edf.Open(path);
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfopentime = time.elapsed(); int edfopentime = time.elapsed();
time.start(); time.start();
#endif #endif
if (!edf.Parse()) if (!edf.Parse(fileData))
return false; return false;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
@ -2249,7 +2296,7 @@ bool ResmedLoader::LoadCSL(Session *sess, const QString & path)
timeMutex.lock(); timeMutex.lock();
timeInLoadCSL += time.elapsed(); timeInLoadCSL += time.elapsed();
timeInEDFOpen += edfopentime; timeInEDFOpen += edfopentime;
timeInEDFParser += edfparsetime; timeInEDFInfo += edfparsetime;
timeMutex.unlock(); timeMutex.unlock();
#endif #endif
@ -2262,12 +2309,13 @@ bool ResmedLoader::LoadEVE(Session *sess, const QString & path)
QTime time; QTime time;
time.start(); time.start();
#endif #endif
ResMedEDFParser edf(path); ResMedEDFInfo edf;
QByteArray * fileData = edf.Open(path);
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfopentime = time.elapsed(); int edfopentime = time.elapsed();
time.start(); time.start();
#endif #endif
if (!edf.Parse()) if (!edf.Parse(fileData))
return false; return false;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfparsetime = time.elapsed(); int edfparsetime = time.elapsed();
@ -2422,7 +2470,7 @@ bool ResmedLoader::LoadEVE(Session *sess, const QString & path)
timeMutex.lock(); timeMutex.lock();
timeInLoadEVE += time.elapsed(); timeInLoadEVE += time.elapsed();
timeInEDFOpen += edfopentime; timeInEDFOpen += edfopentime;
timeInEDFParser += edfparsetime; timeInEDFInfo += edfparsetime;
timeMutex.unlock(); timeMutex.unlock();
#endif #endif
@ -2435,12 +2483,13 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
QTime time; QTime time;
time.start(); time.start();
#endif #endif
ResMedEDFParser edf(path); ResMedEDFInfo edf;
QByteArray * fileData = edf.Open(path);
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfopentime = time.elapsed(); int edfopentime = time.elapsed();
time.start(); time.start();
#endif #endif
if (!edf.Parse()) if (!edf.Parse(fileData))
return false; return false;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfparsetime = time.elapsed(); int edfparsetime = time.elapsed();
@ -2450,7 +2499,7 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
sess->updateFirst(edf.startdate); sess->updateFirst(edf.startdate);
QTime time2; QTime time2;
qint64 duration = edf.GetNumDataRecords() * edf.GetDuration(); qint64 duration = edf.GetNumDataRecords() * edf.GetDurationMillis();
sess->updateLast(edf.startdate + duration); sess->updateLast(edf.startdate + duration);
for (auto & es : edf.edfsignals) { for (auto & es : edf.edfsignals) {
@ -2510,7 +2559,7 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
timeMutex.lock(); timeMutex.lock();
timeInLoadBRP += time.elapsed(); timeInLoadBRP += time.elapsed();
timeInEDFOpen += edfopentime; timeInEDFOpen += edfopentime;
timeInEDFParser += edfparsetime; timeInEDFInfo += edfparsetime;
timeInAddWaveform += AddWavetime; timeInAddWaveform += AddWavetime;
timeMutex.unlock(); timeMutex.unlock();
#endif #endif
@ -2519,7 +2568,7 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
} }
// Convert EDFSignal data to OSCAR's Time-Delta Event format // Convert EDFSignal data to OSCAR's Time-Delta Event format
void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &es, ChannelID code, void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFInfo &edf, EDFSignal &es, ChannelID code,
long recs, qint64 duration, EventDataType t_min, EventDataType t_max, bool square) long recs, qint64 duration, EventDataType t_min, EventDataType t_max, bool square)
{ {
if (t_min == t_max) { if (t_min == t_max) {
@ -2569,9 +2618,7 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
break; break;
} }
tt += rate; tt += rate;
} while (sptr < eptr); } while (sptr < eptr);
if (!el) if (!el)
@ -2585,13 +2632,11 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
tmp = EventDataType(last) * es.gain; tmp = EventDataType(last) * es.gain;
if ((tmp >= t_min) && (tmp <= t_max)) { if ((tmp >= t_min) && (tmp <= t_max)) {
if (tmp < min) { if (tmp < min)
min = tmp; min = tmp;
}
if (tmp > max) { if (tmp > max)
max = tmp; max = tmp;
}
el->AddEvent(tt, last); el->AddEvent(tt, last);
} else { } else {
@ -2601,22 +2646,18 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
el->setDimension(es.physical_dimension); el->setDimension(es.physical_dimension);
el = sess->AddEventList(code, EVL_Event, es.gain, es.offset, 0, 0); el = sess->AddEventList(code, EVL_Event, es.gain, es.offset, 0, 0);
} else { } else
el->clear(); // reuse the object el->clear(); // reuse the object
} }
} }
}
tmp = EventDataType(c) * es.gain; tmp = EventDataType(c) * es.gain;
if ((tmp >= t_min) && (tmp <= t_max)) { if ((tmp >= t_min) && (tmp <= t_max)) {
if (tmp < min) { if (tmp < min)
min = tmp; min = tmp;
} if (tmp > max)
if (tmp > max) {
max = tmp; max = tmp;
}
el->AddEvent(tt, c); el->AddEvent(tt, c);
} else { } else {
@ -2625,7 +2666,8 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
// Create and attach new EventList // Create and attach new EventList
el = sess->AddEventList(code, EVL_Event, es.gain, es.offset, 0, 0); el = sess->AddEventList(code, EVL_Event, es.gain, es.offset, 0, 0);
} else { el->clear(); } } else
el->clear();
} }
} }
@ -2636,9 +2678,8 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
tmp = EventDataType(c) * es.gain; tmp = EventDataType(c) * es.gain;
if ((tmp >= t_min) && (tmp <= t_max)) { if ((tmp >= t_min) && (tmp <= t_max))
el->AddEvent(tt, c); el->AddEvent(tt, c);
}
sess->setMin(code, min); sess->setMin(code, min);
sess->setMax(code, max); sess->setMax(code, max);
@ -2667,7 +2708,7 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
timeInTimeDelta += time.elapsed(); timeInTimeDelta += time.elapsed();
timeMutex.unlock(); timeMutex.unlock();
#endif #endif
} } // end ResMedLoader::ToTimeDelta
// Load SAD Oximetry Signals // Load SAD Oximetry Signals
bool ResmedLoader::LoadSAD(Session *sess, const QString & path) bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
@ -2677,14 +2718,15 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
time.start(); time.start();
#endif #endif
ResMedEDFParser edf(path); ResMedEDFInfo edf;
QByteArray * fileData = edf.Open(path);
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfopentime = time.elapsed(); int edfopentime = time.elapsed();
time.start(); time.start();
#endif #endif
if (!edf.Parse()) if (!edf.Parse(fileData))
return false; return false;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
@ -2693,7 +2735,7 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
#endif #endif
sess->updateFirst(edf.startdate); sess->updateFirst(edf.startdate);
qint64 duration = edf.GetNumDataRecords() * edf.GetDuration(); qint64 duration = edf.GetNumDataRecords() * edf.GetDurationMillis();
sess->updateLast(edf.startdate + duration); sess->updateLast(edf.startdate + duration);
for (auto & es : edf.edfsignals) { for (auto & es : edf.edfsignals) {
@ -2732,7 +2774,7 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
timeMutex.lock(); timeMutex.lock();
timeInLoadSAD += time.elapsed(); timeInLoadSAD += time.elapsed();
timeInEDFOpen += edfopentime; timeInEDFOpen += edfopentime;
timeInEDFParser += edfparsetime; timeInEDFInfo += edfparsetime;
timeMutex.unlock(); timeMutex.unlock();
#endif #endif
return true; return true;
@ -2745,12 +2787,13 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
QTime time; QTime time;
time.start(); time.start();
#endif #endif
ResMedEDFParser edf(path); ResMedEDFInfo edf;
QByteArray * fileData = edf.Open(path);
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfopentime = time.elapsed(); int edfopentime = time.elapsed();
time.start(); time.start();
#endif #endif
if (!edf.Parse()) if (!edf.Parse(fileData))
return false; return false;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
int edfparsetime = time.elapsed(); int edfparsetime = time.elapsed();
@ -2760,7 +2803,7 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
// Is it safe to assume the order does not change here? // Is it safe to assume the order does not change here?
enum PLDType { MaskPres = 0, TherapyPres, ExpPress, Leak, RR, Vt, Mv, SnoreIndex, FFLIndex, U1, U2 }; enum PLDType { MaskPres = 0, TherapyPres, ExpPress, Leak, RR, Vt, Mv, SnoreIndex, FFLIndex, U1, U2 };
qint64 duration = edf.GetNumDataRecords() * edf.GetDuration(); qint64 duration = edf.GetNumDataRecords() * edf.GetDurationMillis();
sess->updateFirst(edf.startdate); sess->updateFirst(edf.startdate);
sess->updateLast(edf.startdate + duration); sess->updateLast(edf.startdate + duration);
QString t; QString t;
@ -2896,7 +2939,7 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
timeMutex.lock(); timeMutex.lock();
timeInLoadPLD += time.elapsed(); timeInLoadPLD += time.elapsed();
timeInEDFOpen += edfopentime; timeInEDFOpen += edfopentime;
timeInEDFParser += edfparsetime; timeInEDFInfo += edfparsetime;
timeMutex.unlock(); timeMutex.unlock();
#endif #endif

View File

@ -30,18 +30,46 @@ EDFType lookupEDFType(const QString & text);
const QString resmed_class_name = STR_MACH_ResMed; const QString resmed_class_name = STR_MACH_ResMed;
class ResMedEDFParser:public EDFParser class ResMedEDFInfo : public EDFInfo
{ {
public: public:
ResMedEDFParser(QString filename = ""); ResMedEDFInfo();
~ResMedEDFParser(); ~ResMedEDFInfo();
virtual bool Parse(QByteArray * fileData) override; // overrides and calls the super's Parse
virtual qint64 GetDurationMillis() { return dur_data_record; } // overrides the super
EDFSignal *lookupSignal(ChannelID ch); EDFSignal *lookupSignal(ChannelID ch);
//! \brief The following are computed from the edfHdr data
QString serialnumber;
qint64 dur_data_record;
qint64 startdate;
qint64 enddate;
};
class EDFduration
{
public:
EDFduration() { start = end = 0; type = EDF_UNKNOWN; }
EDFduration(quint32 start, quint32 end, QString path) :
start(start), end(end), path(path) {}
quint32 start;
quint32 end;
QString path;
QString filename;
EDFType type;
}; };
class STRRecord
struct STRRecord
{ {
public:
STRRecord() { STRRecord() {
maskon.clear(); maskon.clear();
maskoff.clear(); maskoff.clear();
@ -125,82 +153,8 @@ struct STRRecord
date=QDate(); date=QDate();
} }
STRRecord(const STRRecord & copy) {
maskon = copy.maskon;
maskoff = copy.maskoff;
maskdur = copy.maskdur;
maskevents = copy.maskevents;
mode = copy.mode;
rms9_mode = copy.rms9_mode;
set_pressure = copy.set_pressure;
epap = copy.epap;
max_pressure = copy.max_pressure;
min_pressure = copy.min_pressure;
max_ps = copy.max_ps;
min_ps = copy.min_ps;
ps = copy.ps;
max_epap = copy.max_epap;
min_epap = copy.min_epap;
ipap = copy.ipap;
max_ipap = copy.max_ipap;
min_ipap = copy.min_ipap;
epr = copy.epr;
epr_level = copy.epr_level;
sessionid = copy.sessionid;
ahi = copy.ahi;
ai = copy.ai;
oai = copy.oai;
hi = copy.hi;
uai = copy.uai;
cai = copy.cai;
csr = copy.csr;
date = copy.date; // All the data members
leak50 = copy.leak50;
leak95 = copy.leak95;
leakmax = copy.leakmax;
rr50 = copy.rr50;
rr95 = copy.rr95;
rrmax = copy.rrmax;
mv50 = copy.mv50;
mv95 = copy.mv95;
mvmax = copy.mvmax;
ie50 = copy.ie50;
ie95 = copy.ie95;
iemax = copy.iemax;
tv50 = copy.tv50;
tv95 = copy.tv95;
tvmax = copy.tvmax;
mp50 = copy.mp50;
mp95 = copy.mp95;
mpmax = copy.mpmax;
tgtepap50 = copy.tgtepap50;
tgtepap95 = copy.tgtepap95;
tgtepapmax = copy.tgtepapmax;
tgtipap50 = copy.tgtipap50;
tgtipap95 = copy.tgtipap95;
tgtipapmax = copy.tgtipapmax;
s_EPREnable = copy.s_EPREnable;
s_EPR_ClinEnable = copy.s_EPREnable;
s_RampEnable = copy.s_RampEnable;
s_RampTime = copy.s_RampTime;
s_SmartStart = copy.s_SmartStart;
s_PtAccess = copy.s_PtAccess;
s_ABFilter = copy.s_ABFilter;
s_Mask = copy.s_Mask;
s_Tube = copy.s_Tube;
s_ClimateControl = copy.s_ClimateControl;
s_HumEnable = copy.s_HumEnable;
s_HumLevel = copy.s_HumLevel;
s_TempEnable = copy.s_TempEnable;
s_Temp = copy.s_Temp;
ramp_pressure = copy.ramp_pressure;
}
QVector<quint32> maskon; QVector<quint32> maskon;
QVector<quint32> maskoff; QVector<quint32> maskoff;
@ -279,47 +233,6 @@ struct STRRecord
class ResmedLoader; class ResmedLoader;
struct EDFGroup {
EDFGroup() { }
EDFGroup(QString &brp, QString &eve, QString &pld, QString &sad, QString &csl) {
BRP = brp;
EVE = eve;
CSL = csl;
PLD = pld;
SAD = sad;
}
EDFGroup(const EDFGroup & copy) {
BRP = copy.BRP;
EVE = copy.EVE;
CSL = copy.CSL;
PLD = copy.PLD;
SAD = copy.SAD;
}
QString BRP;
QString EVE;
QString CSL;
QString PLD;
QString SAD;
};
struct EDFduration {
EDFduration() { start = end = 0; type = EDF_UNKNOWN; }
EDFduration(const EDFduration & copy) {
path = copy.path;
start = copy.start;
end = copy.end;
type = copy.type;
filename = copy.filename;
}
EDFduration(quint32 start, quint32 end, QString path) :
start(start), end(end), path(path) {}
quint32 start;
quint32 end;
QString path;
QString filename;
EDFType type;
};
struct ResMedDay { struct ResMedDay {
QDate date; QDate date;
STRRecord str; STRRecord str;
@ -342,50 +255,19 @@ protected:
ResMedDay * resday; ResMedDay * resday;
}; };
struct STRFile { class STRFile
{
public:
STRFile() : STRFile() :
filename(QString()), edf(nullptr) {} filename(QString()), edf(nullptr) {}
STRFile(QString name, ResMedEDFParser *str) : STRFile(QString name, ResMedEDFInfo *str) :
filename(name), edf(str) {} filename(name), edf(str) {}
STRFile(const STRFile & copy) { virtual ~STRFile() {}
filename = copy.filename;
edf = copy.edf;
}
~STRFile() {
}
QString filename; QString filename;
ResMedEDFParser * edf; ResMedEDFInfo * edf;
}; };
/*class ResmedImport:public ImportTask
{
public:
ResmedImport(ResmedLoader * l, SessionID s, QHash<EDFType, QStringList> grp, Machine * m): loader(l), sessionid(s), files(grp), mach(m) {}
virtual ~ResmedImport() {}
virtual void run();
protected:
ResmedLoader * loader;
SessionID sessionid;
QHash<EDFType, QStringList> files;
Machine * mach;
};
class ResmedImportStage2:public ImportTask
{
public:
ResmedImportStage2(ResmedLoader * l, STRRecord r, Machine * m): loader(l), R(r), mach(m) {}
virtual ~ResmedImportStage2() {}
virtual void run();
protected:
ResmedLoader * loader;
STRRecord R;
Machine * mach;
}; */
/*! \class ResmedLoader /*! \class ResmedLoader
@ -416,7 +298,7 @@ class ResmedLoader : public CPAPLoader
virtual const QString &loaderName() { return resmed_class_name; } virtual const QString &loaderName() { return resmed_class_name; }
//! \brief Converts EDFSignal data to time delta packed EventList, and adds to Session //! \brief Converts EDFSignal data to time delta packed EventList, and adds to Session
void ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &es, ChannelID code, long recs, void ToTimeDelta(Session *sess, ResMedEDFInfo &edf, EDFSignal &es, ChannelID code, long recs,
qint64 duration, EventDataType min = 0, EventDataType max = 0, bool square = false); qint64 duration, EventDataType min = 0, EventDataType max = 0, bool square = false);
//! \brief Register the ResmedLoader with the list of other machine loaders //! \brief Register the ResmedLoader with the list of other machine loaders
@ -443,7 +325,8 @@ class ResmedLoader : public CPAPLoader
bool LoadPLD(Session *sess, const QString & path); bool LoadPLD(Session *sess, const QString & path);
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, 0, resmed_class_name, QObject::tr("ResMed"), QString(), QString(), QString(), QObject::tr("S9"), QDateTime::currentDateTime(), resmed_data_version); return MachineInfo(MT_CPAP, 0, resmed_class_name, QObject::tr("ResMed"), QString(),
QString(), QString(), QObject::tr("S9"), QDateTime::currentDateTime(), resmed_data_version);
} }
virtual void initChannels(); virtual void initChannels();
@ -463,17 +346,20 @@ class ResmedLoader : public CPAPLoader
volatile int sessionCount; volatile int sessionCount;
protected: protected:
//! \brief The STR.edf file is a unique edf file with many signals
void ParseSTR(Machine *, QMap<QDate, STRFile> &); void ParseSTR(Machine *, QMap<QDate, STRFile> &);
//! \brief Scan for new files to import, group into sessions and add to task que //! \brief Scan for new files to import, group into sessions and add to task que
int scanFiles(Machine * mach, const QString & datalog_path); int scanFiles(Machine * mach, const QString & datalog_path);
//! \brief Write a backup copy to the backup path
QString backup(const QString & file, const QString & backup_path); QString backup(const QString & file, const QString & backup_path);
QMap<SessionID, QStringList> sessfiles; // The data members
QMap<quint32, STRRecord> strsess; // QMap<SessionID, QStringList> sessfiles;
QMap<QDate, QList<STRRecord *> > strdate; // QMap<quint32, STRRecord> strsess;
// QMap<QDate, QList<STRRecord *> > strdate;
QMap<QDate, ResMedDay> resdayList; QMap<QDate, ResMedDay> resdayList;
#ifdef DEBUG_EFFICIENCY #ifdef DEBUG_EFFICIENCY
@ -485,7 +371,7 @@ protected:
volatile qint64 timeInLoadCSL; volatile qint64 timeInLoadCSL;
volatile qint64 timeInLoadSAD; volatile qint64 timeInLoadSAD;
volatile qint64 timeInEDFOpen; volatile qint64 timeInEDFOpen;
volatile qint64 timeInEDFParser; volatile qint64 timeInEDFInfo;
volatile qint64 timeInAddWaveform; volatile qint64 timeInAddWaveform;
volatile qint64 timeInTimeDelta; volatile qint64 timeInTimeDelta;
QMutex timeMutex; QMutex timeMutex;