OSCAR-code/SleepLib/loader_plugins/resmed_loader.cpp

641 lines
22 KiB
C++
Raw Normal View History

2011-06-28 02:21:38 +00:00
/*
SleepLib ResMed Loader Implementation
Author: Mark Watkins <jedimark64@users.sourceforge.net>
License: GPL
*/
#include <QString>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QProgressBar>
2011-07-01 10:10:44 +00:00
#include <QDebug>
2011-06-30 10:56:22 +00:00
#include <math.h>
2011-06-28 02:21:38 +00:00
#include "resmed_loader.h"
#include "SleepLib/session.h"
extern QProgressBar *qprogress;
map<int,QString> RMS9ModelMap;
2011-06-29 14:19:38 +00:00
EDFParser::EDFParser(QString name)
{
buffer=NULL;
Open(name);
}
EDFParser::~EDFParser()
{
vector<EDFSignal *>::iterator s;
for (s=edfsignals.begin();s!=edfsignals.end();s++) {
if ((*s)->data) delete [] (*s)->data;
delete *s;
}
if (buffer) delete [] buffer;
}
2011-06-29 16:19:57 +00:00
qint16 EDFParser::Read16()
{
unsigned char *buf=(unsigned char *)buffer;
if (pos>=filesize) return 0;
qint16 res=*(qint16 *)&buf[pos];
//qint16 res=(buf[pos] ^128)<< 8 | buf[pos+1] ^ 128;
pos+=2;
return res;
}
2011-06-29 14:19:38 +00:00
QString EDFParser::Read(int si)
{
QString str;
if (pos>=filesize) return "";
for (int i=0;i<si;i++) {
str+=buffer[pos++];
}
return str.trimmed();
}
bool EDFParser::Parse()
{
bool ok;
QString temp,temp2;
version=QString::fromAscii(header.version,8).toLong(&ok);
2011-06-29 14:19:38 +00:00
if (!ok)
return false;
//patientident=QString::fromAscii(header.patientident,80);
2011-07-05 05:37:11 +00:00
recordingident=QString::fromAscii(header.recordingident,80); // Serial number is in here..
int snp=recordingident.indexOf("SRN=");
serialnumber.clear();
2011-07-05 05:37:11 +00:00
/*char * idx=index(header.recordingident,'=');
idx++;
for (int i=0;i<16;++i) {
if (*idx==0x20) break;
serialnumber+=*idx;
++idx;
2011-07-05 05:37:11 +00:00
} */
2011-07-05 05:37:11 +00:00
for (int i=snp+4;i<recordingident.length();i++) {
if (recordingident[i]==' ')
break;
serialnumber+=recordingident[i];
}
2011-07-03 06:10:45 +00:00
QDateTime startDate=QDateTime::fromString(QString::fromAscii(header.datetime,16),"dd.MM.yyHH.mm.ss");
QDate d2=startDate.date();
2011-06-29 16:19:57 +00:00
if (d2.year()<2000) {
d2.setYMD(d2.year()+100,d2.month(),d2.day());
startDate.setDate(d2);
2011-06-29 16:19:57 +00:00
}
if (!startDate.isValid()) {
2011-07-01 10:10:44 +00:00
qDebug() << "Invalid date time retreieved parsing EDF File " << filename;
2011-06-29 16:19:57 +00:00
return false;
}
startdate=startDate.toMSecsSinceEpoch();
2011-06-29 16:19:57 +00:00
2011-07-21 03:38:17 +00:00
//qDebug() << startDate.toString("yyyy-MM-dd HH:mm:ss");
2011-06-29 16:19:57 +00:00
num_header_bytes=QString::fromAscii(header.num_header_bytes,8).toLong(&ok);
2011-06-29 14:19:38 +00:00
if (!ok)
return false;
//reserved44=QString::fromAscii(header.reserved,44);
num_data_records=QString::fromAscii(header.num_data_records,8).toLong(&ok);
2011-06-29 14:19:38 +00:00
if (!ok)
return false;
dur_data_record=QString::fromAscii(header.dur_data_records,8).toDouble(&ok)*1000.0;
2011-06-29 14:19:38 +00:00
if (!ok)
return false;
num_signals=QString::fromAscii(header.num_signals,4).toLong(&ok);
2011-06-29 14:19:38 +00:00
if (!ok)
return false;
2011-07-03 02:43:50 +00:00
enddate=startdate+dur_data_record*qint64(num_data_records);
2011-07-03 03:53:09 +00:00
// if (dur_data_record==0)
// return false;
// this could be loaded quicker by transducer_type[signal] etc..
2011-06-29 14:19:38 +00:00
for (int i=0;i<num_signals;i++) {
EDFSignal *signal=new EDFSignal;
edfsignals.push_back(signal);
signal->data=NULL;
edfsignals[i]->label=Read(16);
}
for (int i=0;i<num_signals;i++) edfsignals[i]->transducer_type=Read(80);
for (int i=0;i<num_signals;i++) edfsignals[i]->physical_dimension=Read(8);
for (int i=0;i<num_signals;i++) edfsignals[i]->physical_minimum=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->physical_maximum=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->digital_minimum=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->digital_maximum=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->prefiltering=Read(80);
for (int i=0;i<num_signals;i++) edfsignals[i]->nr=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->reserved=Read(32);
2011-06-29 16:19:57 +00:00
// allocate the buffers
2011-06-29 14:19:38 +00:00
for (int i=0;i<num_signals;i++) {
//qDebug//cout << "Reading signal " << signals[i]->label << endl;
2011-06-29 16:19:57 +00:00
EDFSignal & sig=*edfsignals[i];
long recs=sig.nr * num_data_records;
if (num_data_records<0)
return false;
sig.data=new qint16 [recs];
sig.pos=0;
}
2011-06-29 14:19:38 +00:00
2011-06-29 16:19:57 +00:00
for (int x=0;x<num_data_records;x++) {
for (int i=0;i<num_signals;i++) {
EDFSignal & sig=*edfsignals[i];
2011-06-30 10:56:22 +00:00
memcpy((char *)&sig.data[sig.pos],(char *)&buffer[pos],sig.nr*2);
sig.pos+=sig.nr;
pos+=sig.nr*2;
// big endian will screw up without this..
2011-06-30 10:56:22 +00:00
/*for (int j=0;j<sig.nr;j++) {
2011-06-29 16:19:57 +00:00
qint16 t=Read16();
sig.data[sig.pos++]=t;
2011-06-30 10:56:22 +00:00
} */
2011-06-29 14:19:38 +00:00
}
}
2011-06-29 16:19:57 +00:00
2011-06-29 14:19:38 +00:00
return true;
}
bool EDFParser::Open(QString name)
{
QFile f(name);
if (!f.open(QIODevice::ReadOnly)) return false;
if (!f.isReadable()) return false;
filename=name;
filesize=f.size();
datasize=filesize-EDFHeaderSize;
if (datasize<0) return false;
f.read((char *)&header,EDFHeaderSize);
2011-07-01 10:10:44 +00:00
//qDebug() << "Opening " << name;
buffer=new char [datasize];
f.read(buffer,datasize);
2011-06-29 14:19:38 +00:00
f.close();
pos=0;
2011-06-29 16:19:57 +00:00
return true;
2011-06-29 14:19:38 +00:00
}
2011-06-28 02:21:38 +00:00
ResmedLoader::ResmedLoader()
{
}
ResmedLoader::~ResmedLoader()
{
}
Machine *ResmedLoader::CreateMachine(QString serial,Profile *profile)
{
if (!profile) return NULL;
2011-06-28 02:21:38 +00:00
vector<Machine *> ml=profile->GetMachines(MT_CPAP);
bool found=false;
for (vector<Machine *>::iterator i=ml.begin(); i!=ml.end(); i++) {
2011-06-29 14:19:38 +00:00
if (((*i)->GetClass()==resmed_class_name) && ((*i)->properties["Serial"]==serial)) {
2011-06-28 02:21:38 +00:00
ResmedList[serial]=*i; //static_cast<CPAP *>(*i);
found=true;
break;
}
}
if (found) return ResmedList[serial];
2011-07-01 10:10:44 +00:00
qDebug() << "Create ResMed Machine" << serial;
2011-06-28 02:21:38 +00:00
Machine *m=new CPAP(profile,0);
2011-06-29 14:19:38 +00:00
m->SetClass(resmed_class_name);
2011-06-28 02:21:38 +00:00
ResmedList[serial]=m;
profile->AddMachine(m);
m->properties["Serial"]=serial;
2011-06-29 14:19:38 +00:00
m->properties["Brand"]="ResMed";
2011-07-24 17:18:10 +00:00
QString a;
a.sprintf("%i",resmed_data_version);
m->properties["DataVersion"]=a;
2011-06-28 02:21:38 +00:00
return m;
}
long event_cnt=0;
2011-07-15 13:30:41 +00:00
int ResmedLoader::Open(QString & path,Profile *profile)
2011-06-28 02:21:38 +00:00
{
QString newpath;
QString dirtag="DATALOG";
if (path.endsWith("/"+dirtag)) {
2011-07-15 13:30:41 +00:00
return 0; // id10t user..
2011-06-29 19:06:49 +00:00
//newpath=path;
2011-06-28 02:21:38 +00:00
} else {
newpath=path+"/"+dirtag;
}
2011-06-29 19:06:49 +00:00
QString idfile=path+"/Identification.tgt";
QFile f(idfile);
map<QString,QString> idmap;
if (f.open(QIODevice::ReadOnly)) {
if (!f.isReadable())
2011-07-15 13:30:41 +00:00
return 0;
2011-06-30 10:56:22 +00:00
2011-06-29 19:06:49 +00:00
while (!f.atEnd()) {
QString line=f.readLine().trimmed();
QString key,value;
if (!line.isEmpty()) {
key=line.section(" ",0,0);
value=line.section(" ",1);
key=key.section("#",1);
idmap[key]=value;
}
}
}
2011-06-28 02:21:38 +00:00
QDir dir(newpath);
if ((!dir.exists() || !dir.isReadable()))
return 0;
2011-07-01 10:10:44 +00:00
qDebug() << "ResmedLoader::Open newpath=" << newpath;
2011-06-29 14:19:38 +00:00
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
2011-06-28 02:21:38 +00:00
dir.setSorting(QDir::Name);
QFileInfoList flist=dir.entryInfoList();
2011-06-29 14:19:38 +00:00
map<SessionID,vector<QString> > sessfiles;
2011-06-29 16:19:57 +00:00
2011-06-29 14:19:38 +00:00
QString ext,rest,datestr,s,codestr;
SessionID sessionid;
QDateTime date;
2011-06-30 10:56:22 +00:00
QString filename;
int size=flist.size();
for (int i=0;i<size;i++) {
2011-06-28 02:21:38 +00:00
QFileInfo fi=flist.at(i);
2011-06-30 10:56:22 +00:00
filename=fi.fileName();
2011-06-29 14:19:38 +00:00
ext=filename.section(".",1).toLower();
if (ext!="edf") continue;
2011-06-29 16:19:57 +00:00
2011-06-29 14:19:38 +00:00
rest=filename.section(".",0,0);
datestr=filename.section("_",0,1);
date=QDateTime::fromString(datestr,"yyyyMMdd_HHmmss");
sessionid=date.toTime_t();
// Resmed bugs up on the session filenames.. 1 second either way
if (sessfiles.find(sessionid)==sessfiles.end()) {
if (sessfiles.find(sessionid+1)!=sessfiles.end()) sessionid++;
if (sessfiles.find(sessionid-1)!=sessfiles.end()) sessionid--;
}
2011-06-29 14:19:38 +00:00
2011-06-29 16:19:57 +00:00
sessfiles[sessionid].push_back(fi.canonicalFilePath());
if (qprogress) qprogress->setValue((float(i+1)/float(size)*33.0));
2011-06-29 16:19:57 +00:00
}
2011-06-29 14:19:38 +00:00
2011-06-29 16:19:57 +00:00
Machine *m=NULL;
2011-06-30 10:56:22 +00:00
QString fn;
2011-07-03 03:53:09 +00:00
Session *sess;
int cnt=0;
size=sessfiles.size();
2011-06-29 16:19:57 +00:00
for (map<SessionID,vector<QString> >::iterator si=sessfiles.begin();si!=sessfiles.end();si++) {
sessionid=si->first;
2011-07-01 10:10:44 +00:00
//qDebug() << "Parsing Session " << sessionid;
2011-06-29 16:19:57 +00:00
bool done=false;
bool first=true;
2011-07-03 03:53:09 +00:00
sess=NULL;
for (size_t i=0;i<si->second.size();++i) {
2011-06-30 10:56:22 +00:00
fn=si->second[i].section("_",-1).toLower();
2011-06-29 16:19:57 +00:00
EDFParser edf(si->second[i]);
2011-07-01 10:10:44 +00:00
//qDebug() << "Parsing File " << i << " " << edf.filesize;
2011-06-29 16:19:57 +00:00
if (!edf.Parse())
continue;
if (first) { // First EDF file parsed, check if this data set is already imported
m=CreateMachine(edf.serialnumber,profile);
2011-06-29 19:06:49 +00:00
for (map<QString,QString>::iterator i=idmap.begin();i!=idmap.end();i++) {
if (i->first=="SRN") {
if (edf.serialnumber!=i->second) {
2011-07-01 10:10:44 +00:00
qDebug() << "edf Serial number doesn't match Identification.tgt";
2011-06-29 19:06:49 +00:00
}
} else if (i->first=="PNA") {
m->properties["Model"]=i->second;
} else if (i->first=="PCD") {
bool ok;
int j=i->second.toInt(&ok);
if (RMS9ModelMap.find(j)!=RMS9ModelMap.end()) {
m->properties["SubModel"]=RMS9ModelMap[j];
}
2011-06-29 19:06:49 +00:00
} else {
m->properties[i->first]=i->second;
}
}
2011-06-29 16:19:57 +00:00
if (m->SessionExists(sessionid)) {
done=true;
break;
}
sess=new Session(m,sessionid);
2011-07-03 03:53:09 +00:00
first=false;
2011-06-29 16:19:57 +00:00
}
if (!done) {
2011-07-01 10:10:44 +00:00
if (fn=="eve.edf") LoadEVE(sess,edf);
else if (fn=="pld.edf") LoadPLD(sess,edf);
else if (fn=="brp.edf") LoadBRP(sess,edf);
else if (fn=="sad.edf") LoadSAD(sess,edf);
2011-07-03 03:53:09 +00:00
//if (first) {
//first=false;
//}
2011-06-29 16:19:57 +00:00
}
2011-06-29 14:19:38 +00:00
}
2011-07-03 03:53:09 +00:00
if (qprogress) qprogress->setValue(33.0+(float(++cnt)/float(size)*33.0));
if (!sess) continue;
if (!sess->first()) {
delete sess;
continue;
} else {
sess->SetChanged(true);
m->AddSession(sess,profile); // Adding earlier than I really like here..
}
if (!done && sess) {
2011-06-30 09:37:24 +00:00
sess->summary[CPAP_PressureMedian]=sess->avg_event_field(CPAP_Pressure,0);
sess->summary[CPAP_PressureAverage]=sess->weighted_avg_event_field(CPAP_Pressure,0);
sess->summary[CPAP_PressureMinAchieved]=sess->min_event_field(CPAP_Pressure,0);
sess->summary[CPAP_PressureMaxAchieved]=sess->max_event_field(CPAP_Pressure,0);
sess->summary[CPAP_PressureMin]=sess->summary[CPAP_PressureMinAchieved];
sess->summary[CPAP_PressureMax]=sess->summary[CPAP_PressureMaxAchieved];
sess->summary[CPAP_LeakMinimum]=sess->min_event_field(CPAP_Leak,0);
sess->summary[CPAP_LeakMaximum]=sess->max_event_field(CPAP_Leak,0); // should be merged..
sess->summary[CPAP_LeakMedian]=sess->avg_event_field(CPAP_Leak,0);
sess->summary[CPAP_LeakAverage]=sess->weighted_avg_event_field(CPAP_Leak,0);
sess->summary[CPAP_Snore]=sess->sum_event_field(CPAP_Snore,0);
sess->summary[CPAP_SnoreMinimum]=sess->min_event_field(CPAP_Snore,0);
sess->summary[CPAP_SnoreMaximum]=sess->max_event_field(CPAP_Snore,0);
sess->summary[CPAP_SnoreMedian]=sess->avg_event_field(CPAP_Snore,0);
sess->summary[CPAP_SnoreAverage]=sess->weighted_avg_event_field(CPAP_Snore,0);
sess->summary[CPAP_Obstructive]=sess->count_events(CPAP_Obstructive);
sess->summary[CPAP_Hypopnea]=sess->count_events(CPAP_Hypopnea);
sess->summary[CPAP_ClearAirway]=sess->count_events(CPAP_ClearAirway);
sess->summary[CPAP_Mode]=MODE_APAP;
}
2011-06-28 02:21:38 +00:00
}
2011-07-02 16:10:20 +00:00
m->Save();
if (qprogress) qprogress->setValue(100);
qDebug() << "Total Events " << event_cnt;
2011-07-15 13:30:41 +00:00
return 1;
2011-06-28 02:21:38 +00:00
}
2011-07-01 10:10:44 +00:00
bool ResmedLoader::LoadEVE(Session *sess,EDFParser &edf)
2011-06-29 14:19:38 +00:00
{
QString t;
2011-06-30 10:56:22 +00:00
long recs;
double totaldur,duration;
char * data;
char c;
long pos;
bool sign,ok;
double d;
2011-07-02 15:48:55 +00:00
double tt;
2011-06-30 10:56:22 +00:00
EventDataType fields[3];
MachineCode code;
2011-07-01 10:10:44 +00:00
//Event *e;
totaldur=edf.GetNumDataRecords()*edf.GetDuration();
2011-07-03 03:53:09 +00:00
//sess->set_first(edf.startdate);
//if (edf.enddate>edf.startdate) sess->set_last(edf.enddate);
2011-06-29 14:19:38 +00:00
for (int s=0;s<edf.GetNumSignals();s++) {
2011-06-30 10:56:22 +00:00
recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords()*2;
2011-07-01 10:10:44 +00:00
//qDebug() << edf.edfsignals[s]->label << " " << t;
2011-06-30 10:56:22 +00:00
data=(char *)edf.edfsignals[s]->data;
pos=0;
tt=edf.startdate;
duration=0;
while (pos<recs) {
c=data[pos];
if ((c!='+') && (c!='-'))
break;
if (data[pos++]=='+') sign=true; else sign=false;
t="";
c=data[pos];
do {
t+=c;
pos++;
c=data[pos];
} while ((c!=20) && (c!=21)); // start code
d=t.toDouble(&ok);
if (!ok) {
2011-07-01 10:10:44 +00:00
qDebug() << "Faulty EDF EVE file " << edf.filename;
break;
}
if (!sign) d=-d;
2011-07-02 15:48:55 +00:00
tt=edf.startdate+(d*1000.0);
duration=0;
// First entry
if (data[pos]==21) {
pos++;
// get duration.
t="";
do {
t+=data[pos];
pos++;
} while ((data[pos]!=20) && (pos<recs)); // start code
2011-07-02 15:48:55 +00:00
duration=t.toDouble(&ok);
if (!ok) {
2011-07-01 10:10:44 +00:00
qDebug() << "Faulty EDF EVE file (at %" << pos << ") " << edf.filename;
break;
}
}
while ((data[pos]==20) && (pos<recs)) {
t="";
pos++;
if (data[pos]==0)
break;
if (data[pos]==20) {
pos++;
break;
}
do {
t+=tolower(data[pos++]);
} while ((data[pos]!=20) && (pos<recs)); // start code
if (!t.isEmpty()) {
2011-06-30 10:56:22 +00:00
code=MC_UNKNOWN;
if (t=="obstructive apnea") code=CPAP_Obstructive;
else if (t=="hypopnea") code=CPAP_Hypopnea;
2011-07-21 03:35:59 +00:00
else if (t=="apnea") code=CPAP_Apnea;
else if (t=="central apnea") code=CPAP_ClearAirway;
if (code!=MC_UNKNOWN) {
2011-07-03 02:43:50 +00:00
fields[0]=duration;
2011-06-30 10:56:22 +00:00
sess->AddEvent(new Event(tt,code,fields,1));
} else {
if (t!="recording starts") {
2011-07-01 10:10:44 +00:00
qDebug() << "Unknown ResMed annotation field: " << t;
}
}
}
if (pos>=recs) {
2011-07-01 10:10:44 +00:00
qDebug() << "Short EDF EVE file" << edf.filename;
break;
}
// pos++;
}
while ((data[pos]==0) && pos<recs) pos++;
if (pos>=recs) break;
}
// qDebug(data);
2011-06-29 14:19:38 +00:00
}
2011-07-01 10:10:44 +00:00
return true;
2011-06-29 14:19:38 +00:00
}
2011-07-01 10:10:44 +00:00
bool ResmedLoader::LoadBRP(Session *sess,EDFParser &edf)
2011-06-29 14:19:38 +00:00
{
2011-06-29 16:19:57 +00:00
QString t;
2011-07-03 02:43:50 +00:00
sess->set_first(edf.startdate);
sess->set_last(edf.enddate);
qint64 duration=edf.GetNumDataRecords()*edf.GetDuration();
2011-06-29 16:19:57 +00:00
for (int s=0;s<edf.GetNumSignals();s++) {
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
MachineCode code;
if (edf.edfsignals[s]->label=="Flow") code=CPAP_FlowRate;
2011-07-10 17:49:02 +00:00
else if (edf.edfsignals[s]->label=="Mask Pres") {
code=CPAP_MaskPressure;
2011-07-24 17:18:10 +00:00
//for (int i=0;i<recs;i++) edf.edfsignals[s]->data[i]/=50.0;
2011-07-10 17:49:02 +00:00
} else {
2011-07-01 10:10:44 +00:00
qDebug() << "Unknown Signal " << edf.edfsignals[s]->label;
continue;
}
2011-06-29 16:19:57 +00:00
Waveform *w=new Waveform(edf.startdate,code,edf.edfsignals[s]->data,recs,duration,edf.edfsignals[s]->digital_minimum,edf.edfsignals[s]->digital_maximum);
edf.edfsignals[s]->data=NULL; // so it doesn't get deleted when edf gets trashed.
sess->AddWaveform(w);
}
2011-07-01 10:10:44 +00:00
return true;
2011-06-29 14:19:38 +00:00
}
void ResmedLoader::ToTimeDelta(Session *sess,EDFParser &edf, qint16 *data, MachineCode code, long recs, qint64 duration,EventDataType divisor)
2011-06-29 20:30:23 +00:00
{
bool first=true;
double rate=(duration/recs); // milliseconds per record
2011-07-02 15:48:55 +00:00
double tt=edf.startdate;
2011-06-29 20:30:23 +00:00
EventDataType c,last;
for (int i=0;i<recs;i++) {
c=data[i]/divisor;
if (first) {
2011-07-03 02:43:50 +00:00
sess->AddEvent(new Event(tt,code,&c,1));
2011-06-29 20:30:23 +00:00
first=false;
} else {
if (last!=c) {
2011-07-03 02:43:50 +00:00
sess->AddEvent(new Event(tt,code,&c,1));
2011-06-29 20:30:23 +00:00
}
}
tt+=rate;
2011-06-29 20:30:23 +00:00
last=c;
}
2011-07-03 02:43:50 +00:00
sess->AddEvent(new Event(tt,code,&c,1)); // add one at the end..
2011-06-29 20:30:23 +00:00
}
2011-07-01 10:10:44 +00:00
bool ResmedLoader::LoadSAD(Session *sess,EDFParser &edf)
2011-06-29 14:19:38 +00:00
{
2011-07-01 10:10:44 +00:00
// Oximeter bull crap.. this oximeter is not reported of highly..
// nonetheless, the data is easy to access.
return true;
2011-06-29 14:19:38 +00:00
}
2011-06-29 20:30:23 +00:00
2011-07-01 10:10:44 +00:00
bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
2011-06-29 14:19:38 +00:00
{
2011-07-01 02:52:02 +00:00
// Is it save to assume the order does not change here?
enum PLDType { MaskPres=0, TherapyPres, ExpPress, Leak, RR, Vt, Mv, SnoreIndex, FFLIndex, U1, U2 };
2011-07-03 02:43:50 +00:00
sess->set_first(edf.startdate);
sess->set_last(edf.enddate);
qint64 duration=edf.GetNumDataRecords()*edf.GetDuration();
QString t;
2011-07-21 03:35:59 +00:00
int emptycnt=0;
for (int s=0;s<edf.GetNumSignals();s++) {
2011-06-29 20:30:23 +00:00
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
MachineCode code;
2011-07-01 02:52:02 +00:00
// if (s==TherapyPres) {
// for (int i=0;i<recs;i++) qDebug("%04i %i",i,edf.edfsignals[s]->data[i]);
// } else
2011-06-29 20:30:23 +00:00
if (edf.edfsignals[s]->label=="Snore Index") {
code=CPAP_Snore;
2011-07-01 10:10:44 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration);
2011-07-01 02:52:02 +00:00
} else if (edf.edfsignals[s]->label=="Therapy Pres") {
2011-06-29 20:30:23 +00:00
code=CPAP_Pressure;
2011-07-01 10:10:44 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,50.0); //50.0
2011-06-29 20:30:23 +00:00
} else if (edf.edfsignals[s]->label=="MV") {
code=CPAP_MinuteVentilation;
2011-07-10 16:20:51 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration);
//Waveform *w=new Waveform(edf.startdate,code,edf.edfsignals[s]->data,recs,duration,edf.edfsignals[s]->digital_minimum,edf.edfsignals[s]->digital_maximum);
//edf.edfsignals[s]->data=NULL; // so it doesn't get deleted when edf gets trashed.
//sess->AddWaveform(w);
2011-06-29 20:30:23 +00:00
} else if (edf.edfsignals[s]->label=="RR") {
code=CPAP_RespiratoryRate;
2011-07-10 16:20:51 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration);
//Waveform *w=new Waveform(edf.startdate,code,edf.edfsignals[s]->data,recs,duration,edf.edfsignals[s]->digital_minimum,edf.edfsignals[s]->digital_maximum);
//edf.edfsignals[s]->data=NULL; // so it doesn't get deleted when edf gets trashed.
//sess->AddWaveform(w);
2011-06-29 20:30:23 +00:00
} else if (edf.edfsignals[s]->label=="Vt") {
code=CPAP_TidalVolume;
2011-07-10 16:20:51 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration);
//Waveform *w=new Waveform(edf.startdate,code,edf.edfsignals[s]->data,recs,duration,edf.edfsignals[s]->digital_minimum,edf.edfsignals[s]->digital_maximum);
//edf.edfsignals[s]->data=NULL; // so it doesn't get deleted when edf gets trashed.
//sess->AddWaveform(w);
} else if (edf.edfsignals[s]->label=="Leak") {
2011-06-29 20:30:23 +00:00
code=CPAP_Leak;
2011-07-01 10:10:44 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,1.0);
2011-06-30 12:07:11 +00:00
} else if (edf.edfsignals[s]->label=="FFL Index") {
code=CPAP_FlowLimitGraph;
2011-07-01 10:10:44 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,1.0);
2011-07-21 03:35:59 +00:00
} else if (edf.edfsignals[s]->label=="Mask Pres") {
2011-07-21 03:36:25 +00:00
code=CPAP_MaskPressureEvt;
2011-07-21 03:35:59 +00:00
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,50.0);
} else if (edf.edfsignals[s]->label=="Exp Press") {
code=CPAP_ExpPressure;
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,50.0);
} else if (edf.edfsignals[s]->label=="") {
if (emptycnt==0) {
code=ResMed_Empty1;
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,1.0);
} else if (emptycnt==1) {
code=ResMed_Empty2;
ToTimeDelta(sess,edf,edf.edfsignals[s]->data, code,recs,duration,1.0);
} else {
qDebug() << "Unobserved Empty Signal " << edf.edfsignals[s]->label;
}
emptycnt++;
2011-06-30 09:37:24 +00:00
} else {
2011-07-21 03:35:59 +00:00
qDebug() << "Unobserved Signal " << edf.edfsignals[s]->label;
2011-06-29 20:30:23 +00:00
}
}
2011-07-01 10:10:44 +00:00
return true;
2011-06-29 14:19:38 +00:00
}
2011-06-28 02:21:38 +00:00
void ResInitModelMap()
{
// Courtesy Troy Schultz
RMS9ModelMap[36001]="ResMed S9 Escape";
RMS9ModelMap[36002]="ResMed S9 Escape Auto";
RMS9ModelMap[36003]="ResMed S9 Elite";
RMS9ModelMap[36004]="ResMed S9 VPAP S";
RMS9ModelMap[36005]="ResMed S9 AutoSet";
RMS9ModelMap[36006]="ResMed S9 VPAP Auto";
RMS9ModelMap[36007]="ResMed S9 VPAP Adapt";
RMS9ModelMap[36008]="ResMed S9 VPAP ST";
// S8 Series
RMS9ModelMap[33007]="ResMed S8 Escape";
RMS9ModelMap[33039]="ResMed S8 Elite II";
RMS9ModelMap[33051]="ResMed S8 Escape II";
RMS9ModelMap[33064]="ResMed S8 Escape II AutoSet";
RMS9ModelMap[33064]="ResMed S8 Escape II AutoSet";
RMS9ModelMap[33129]="ResMed S8 AutoSet II";
2011-06-28 02:21:38 +00:00
};
bool resmed_initialized=false;
void ResmedLoader::Register()
{
if (resmed_initialized) return;
2011-07-01 10:10:44 +00:00
qDebug() << "Registering ResmedLoader";
2011-06-28 02:21:38 +00:00
RegisterLoader(new ResmedLoader());
ResInitModelMap();
resmed_initialized=true;
}