ResMed S9 Flow Rate Data

This commit is contained in:
Mark Watkins 2011-06-30 02:19:57 +10:00
parent c6c7cda0fc
commit b88ac87548
5 changed files with 117 additions and 67 deletions

View File

@ -43,7 +43,7 @@ void WaveData::Reload(Day *day)
Waveform *w=(*l); Waveform *w=(*l);
double st=w->start().toMSecsSinceEpoch()/86400000.0; double st=w->start().toMSecsSinceEpoch()/86400000.0;
double rate=(w->duration()/w->samples())/86400.0; double rate=(w->duration()/w->samples())/86400.0;
//qDebug("Waveform Chunk contains %i samples",w->samples()); qDebug("Waveform Chunk contains %i samples",w->samples());
for (int i=0;i<w->samples();i++) { for (int i=0;i<w->samples();i++) {
QPointD r(st,(*w)[i]); QPointD r(st,(*w)[i]);
st+=rate; st+=rate;
@ -377,6 +377,8 @@ void HistoryData::Reload(Day *day)
double y,lasty=0; double y,lasty=0;
min_y=max_y=0; min_y=max_y=0;
min_x=max_x=0; min_x=max_x=0;
if (real_min_x<0) return;
if (real_max_x<0) return;
for (double x=floor(real_min_x);x<=ceil(real_max_x);x++) { for (double x=floor(real_min_x);x<=ceil(real_max_x);x++) {
date=QDateTime::fromMSecsSinceEpoch(x*86400000.0L); date=QDateTime::fromMSecsSinceEpoch(x*86400000.0L);
date.setTime(QTime(0,0,0)); date.setTime(QTime(0,0,0));

View File

@ -26,11 +26,19 @@ EDFParser::~EDFParser()
vector<EDFSignal *>::iterator s; vector<EDFSignal *>::iterator s;
for (s=edfsignals.begin();s!=edfsignals.end();s++) { for (s=edfsignals.begin();s!=edfsignals.end();s++) {
if ((*s)->data) delete [] (*s)->data; if ((*s)->data) delete [] (*s)->data;
if ((*s)->adata) delete [] (*s)->adata;
delete *s; delete *s;
} }
if (buffer) delete [] buffer; if (buffer) delete [] buffer;
} }
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;
}
QString EDFParser::Read(int si) QString EDFParser::Read(int si)
{ {
QString str; QString str;
@ -59,7 +67,19 @@ bool EDFParser::Parse()
} }
temp=Read(8); temp=Read(8);
temp+=" "+Read(8); temp+=" "+Read(8);
startdate.fromString(temp,"dd.MM.yy HH.mm.ss"); startdate=QDateTime::fromString(temp,"dd.MM.yy HH.mm.ss");
QDate d2=startdate.date();
if (d2.year()<2000) {
d2.setYMD(d2.year()+100,d2.month(),d2.day());
startdate.setDate(d2);
}
if (!startdate.isValid()) {
qDebug(("Invalid date time retreieved parsing EDF File"+filename).toLatin1());
return false;
}
qDebug(startdate.toString("yyyy-MM-dd HH:mm:ss").toLatin1());
num_header_bytes=Read(8).toLong(&ok); num_header_bytes=Read(8).toLong(&ok);
if (!ok) if (!ok)
return false; return false;
@ -80,7 +100,6 @@ bool EDFParser::Parse()
EDFSignal *signal=new EDFSignal; EDFSignal *signal=new EDFSignal;
edfsignals.push_back(signal); edfsignals.push_back(signal);
signal->data=NULL; signal->data=NULL;
signal->adata=NULL;
edfsignals[i]->label=Read(16); edfsignals[i]->label=Read(16);
} }
@ -94,27 +113,28 @@ bool EDFParser::Parse()
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]->nr=Read(8).toLong(&ok);
for (int i=0;i<num_signals;i++) edfsignals[i]->reserved=Read(32); for (int i=0;i<num_signals;i++) edfsignals[i]->reserved=Read(32);
// allocate the buffers
for (int i=0;i<num_signals;i++) { for (int i=0;i<num_signals;i++) {
//qDebug//cout << "Reading signal " << signals[i]->label << endl; //qDebug//cout << "Reading signal " << signals[i]->label << endl;
if (edfsignals[i]->label!="EDF Annotations") { EDFSignal & sig=*edfsignals[i];
// Waveforms
edfsignals[i]->data=new qint16 [edfsignals[i]->nr];
for (int j=0;j<edfsignals[i]->nr;j++){
long t;
t=Read(2).toLong(&ok);
if (!ok)
return false;
edfsignals[i]->data[j]=t & 0xffff;
}
} else { // Annotation data.. long recs=sig.nr * num_data_records;
edfsignals[i]->adata=(char *) new char [edfsignals[i]->nr*2]; if (num_data_records<0)
//cout << signals[i]->nr << endl;; return false;
for (int j=0;j<edfsignals[i]->nr*2;j++) sig.data=new qint16 [recs];
edfsignals[i]->adata[j]=buffer[pos++]; sig.pos=0;
}
//cout << "Read Signal" << endl;
} }
for (int x=0;x<num_data_records;x++) {
for (int i=0;i<num_signals;i++) {
EDFSignal & sig=*edfsignals[i];
for (int j=0;j<sig.nr;j++) {
qint16 t=Read16();
sig.data[sig.pos++]=t;
}
}
}
return true; return true;
} }
bool EDFParser::Open(QString name) bool EDFParser::Open(QString name)
@ -124,10 +144,12 @@ bool EDFParser::Open(QString name)
if (!f.isReadable()) return false; if (!f.isReadable()) return false;
filename=name; filename=name;
filesize=f.size(); filesize=f.size();
qDebug(("Opening "+name).toLatin1());
buffer=new char [filesize]; buffer=new char [filesize];
f.read(buffer,filesize); f.read(buffer,filesize);
f.close(); f.close();
pos=0; pos=0;
return true;
} }
ResmedLoader::ResmedLoader() ResmedLoader::ResmedLoader()
@ -187,55 +209,60 @@ bool ResmedLoader::Open(QString & path,Profile *profile)
dir.setSorting(QDir::Name); dir.setSorting(QDir::Name);
QFileInfoList flist=dir.entryInfoList(); QFileInfoList flist=dir.entryInfoList();
map<SessionID,vector<QString> > sessfiles; map<SessionID,vector<QString> > sessfiles;
QString ext,rest,datestr,s,codestr; QString ext,rest,datestr,s,codestr;
SessionID sessionid; SessionID sessionid;
QDateTime date; QDateTime date;
map<SessionID,Session *> sessions;
Session *sess;
Machine *m;
for (int i=0;i<flist.size();i++) { for (int i=0;i<flist.size();i++) {
QFileInfo fi=flist.at(i); QFileInfo fi=flist.at(i);
QString filename=fi.fileName(); QString filename=fi.fileName();
ext=filename.section(".",1).toLower(); ext=filename.section(".",1).toLower();
if (ext!="edf") continue; if (ext!="edf") continue;
rest=filename.section(".",0,0); rest=filename.section(".",0,0);
datestr=filename.section("_",0,1); datestr=filename.section("_",0,1);
date=QDateTime::fromString(datestr,"yyyyMMdd_HHmmss"); date=QDateTime::fromString(datestr,"yyyyMMdd_HHmmss");
sessionid=date.toTime_t(); sessionid=date.toTime_t();
s.sprintf("%li",sessionid); sessfiles[sessionid].push_back(fi.canonicalFilePath());
codestr=rest.section("_",2).toUpper(); }
int code;
if (codestr=="EVE") code=0;
else if (codestr=="PLD") code=1;
else if (codestr=="BRP") code=2;
else if (codestr=="SAD") code=3;
else {
qDebug(("Unknown file EDF type"+filename).toLatin1());
continue;
}
qDebug(("Parsing "+filename).toLatin1());
EDFParser edf(fi.canonicalFilePath());
if (!edf.Parse()) continue;
Machine *m=CreateMachine(edf.serialnumber,profile); Machine *m=NULL;
if (sessions.find(sessionid)==sessions.end()) { Session *sess=NULL;
sessions[sessionid]=new Session(m,sessionid); for (map<SessionID,vector<QString> >::iterator si=sessfiles.begin();si!=sessfiles.end();si++) {
} sessionid=si->first;
qDebug("Parsing Session %li",sessionid);
bool done=false;
bool first=true;
for (int i=0;i<si->second.size();i++) {
QString fn=si->second[i].section("_",-1).toLower();
EDFParser edf(si->second[i]);
qDebug("Parsing File %i %i",i,edf.filesize);
sess=sessions[sessionid]; if (!edf.Parse())
sess->SetChanged(true); continue;
switch(code) {
case 0: LoadEVE(m,sess,edf); if (first) { // First EDF file parsed, check if this data set is already imported
break; m=CreateMachine(edf.serialnumber,profile);
case 1: LoadPLD(m,sess,edf); if (m->SessionExists(sessionid)) {
break; done=true;
case 2: LoadBRP(m,sess,edf); break;
break; }
case 3: LoadSAD(m,sess,edf); sess=new Session(m,sessionid);
break; }
if (!done) {
if (fn=="eve.edf") LoadEVE(m,sess,edf);
else if (fn=="pld.edf") LoadPLD(m,sess,edf);
else if (fn=="brp.edf") LoadBRP(m,sess,edf);
else if (fn=="sad.edf") LoadSAD(m,sess,edf);
}
if (first) {
sess->SetChanged(true);
m->AddSession(sess,profile); // Adding earlier than I really like here..
first=false;
}
} }
} }
return 0; return 0;
@ -244,14 +271,34 @@ bool ResmedLoader::LoadEVE(Machine *mach,Session *sess,EDFParser &edf)
{ {
QString t; QString t;
for (int s=0;s<edf.GetNumSignals();s++) { for (int s=0;s<edf.GetNumSignals();s++) {
t.sprintf("%i",edf.edfsignals[s]->nr); long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
double duration=edf.GetNumDataRecords()*edf.GetDuration();
duration/=3600.0;
t.sprintf("EVE: %li %.2f",recs,duration);
qDebug((edf.edfsignals[s]->label+" "+t).toLatin1()); qDebug((edf.edfsignals[s]->label+" "+t).toLatin1());
if (edf.edfsignals[s]->adata) { char * data=(char *)edf.edfsignals[s]->data;
}
} }
} }
bool ResmedLoader::LoadBRP(Machine *mach,Session *sess,EDFParser &edf) bool ResmedLoader::LoadBRP(Machine *mach,Session *sess,EDFParser &edf)
{ {
QString t;
for (int s=0;s<edf.GetNumSignals();s++) {
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
double duration=edf.GetNumDataRecords()*edf.GetDuration();
MachineCode code;
if (edf.edfsignals[s]->label=="Flow") code=CPAP_FlowRate;
else if (edf.edfsignals[s]->label=="Mask Pres") code=CPAP_MaskPressure;
sess->set_first(edf.startdate);
QDateTime e=edf.startdate.addSecs(duration);
sess->set_last(e);
//duration/=3600.0;
sess->set_hours(duration/3600.0);
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);
t.sprintf("BRP: %li %.2f",recs,duration);
qDebug((edf.edfsignals[s]->label+" "+t).toLatin1());
}
} }
bool ResmedLoader::LoadSAD(Machine *mach,Session *sess,EDFParser &edf) bool ResmedLoader::LoadSAD(Machine *mach,Session *sess,EDFParser &edf)
{ {

View File

@ -39,7 +39,7 @@ public:
long nr; long nr;
QString reserved; QString reserved;
qint16 * data; qint16 * data;
char *adata; int pos;
}; };
class EDFParser class EDFParser
@ -50,12 +50,13 @@ public:
bool Open(QString name); bool Open(QString name);
QString Read(int si); QString Read(int si);
qint16 Read16();
vector<EDFSignal *> edfsignals; vector<EDFSignal *> edfsignals;
long GetNumSignals() { return num_signals; }; long GetNumSignals() { return num_signals; };
long GetNumDataRecords() { return num_data_records; }; long GetNumDataRecords() { return num_data_records; };
long GetDuration() { return dur_data_record; }; double GetDuration() { return dur_data_record; };
QString GetPatient() { return patientident; }; QString GetPatient() { return patientident; };
bool Parse(); bool Parse();
char *buffer; char *buffer;

View File

@ -32,7 +32,7 @@ enum MachineCode//:qint16
{ {
// General Event Codes // General Event Codes
CPAP_Obstructive=0, CPAP_Hypopnea, CPAP_ClearAirway, CPAP_RERA, CPAP_VSnore, CPAP_FlowLimit, CPAP_Obstructive=0, CPAP_Hypopnea, CPAP_ClearAirway, CPAP_RERA, CPAP_VSnore, CPAP_FlowLimit,
CPAP_Leak, CPAP_Pressure, CPAP_EAP, CPAP_IAP, CPAP_CSR, CPAP_FlowRate, CPAP_Leak, CPAP_Pressure, CPAP_EAP, CPAP_IAP, CPAP_CSR, CPAP_FlowRate, CPAP_MaskPressure,
CPAP_BreathsPerMinute, CPAP_BreathsPerMinute,
// General CPAP Summary Information // General CPAP Summary Information

View File

@ -114,13 +114,13 @@ Daily::Daily(QWidget *parent,QGLContext *context) :
LEAK->setMinimumHeight(150); LEAK->setMinimumHeight(150);
AddCPAPData(frw=new WaveData(CPAP_FlowRate)); AddCPAPData(frw=new WaveData(CPAP_FlowRate,700000)); // Holy crap resmed stuff is huge..
AddGraph(FRW=new gGraphWindow(gSplitter,tr("Flow Rate"),SF)); AddGraph(FRW=new gGraphWindow(gSplitter,tr("Flow Rate"),SF));
//FRW->AddLayer(new gFooBar()); //FRW->AddLayer(new gFooBar());
FRW->AddLayer(new gYAxis()); FRW->AddLayer(new gYAxis());
FRW->AddLayer(new gXAxis()); FRW->AddLayer(new gXAxis());
FRW->AddLayer(new gLineOverlayBar(flags[0],QColor("light green"),"CSR")); FRW->AddLayer(new gLineOverlayBar(flags[0],QColor("light green"),"CSR"));
gLineChart *g=new gLineChart(frw,Qt::black,200000,true); gLineChart *g=new gLineChart(frw,Qt::black,700000,true);
g->ReportEmpty(true); g->ReportEmpty(true);
@ -203,12 +203,12 @@ Daily::Daily(QWidget *parent,QGLContext *context) :
l->AddName(tr("FL")); l->AddName(tr("FL"));
l->AddName(tr("CSR")); l->AddName(tr("CSR"));
l->color.clear(); l->color.clear();
l->color.push_back(QColor("blue")); l->color.push_back(QColor(0x40,0x40,0xff,0xff)); // blue
l->color.push_back(QColor(0x40,0xaf,0xbf,0xff)); //#40afbf l->color.push_back(QColor(0x40,0xaf,0xbf,0xff)); // aqua
l->color.push_back(QColor(0xb2,0x54,0xcd,0xff)); //b254cd; //wxPURPLE); l->color.push_back(QColor(0xb2,0x54,0xcd,0xff)); // purple
l->color.push_back(QColor("yellow")); l->color.push_back(QColor(0xff,0xff,0x80,0xff)); // yellow
l->color.push_back(QColor(0x40,0x40,0x40,255)); l->color.push_back(QColor(0x40,0x40,0x40,0xff)); // dark grey
l->color.push_back(QColor(0x60,0xff,0x60,0xff)); //80ff80 l->color.push_back(QColor(0x60,0xff,0x60,0xff)); // green
G_AHI->AddLayer(l); G_AHI->AddLayer(l);
G_AHI->SetGradientBackground(false); G_AHI->SetGradientBackground(false);
//G_AHI->setMaximumSize(2000,30); //G_AHI->setMaximumSize(2000,30);