ResMed S9 import fix for German machines

This commit is contained in:
Mark Watkins 2011-11-25 22:13:35 +10:00
parent 54fd38bf96
commit 45cdd1d172
5 changed files with 88 additions and 47 deletions

View File

@ -60,7 +60,7 @@ void gLineChart::paint(gGraph & w,int left, int top, int width, int height)
if (!m_day) if (!m_day)
return; return;
if (!m_day->channelExists(m_code)) return; //if (!m_day->channelExists(m_code)) return;
if (width<0) if (width<0)
return; return;

View File

@ -24,6 +24,20 @@ extern QProgressBar *qprogress;
QHash<int,QString> RMS9ModelMap; QHash<int,QString> RMS9ModelMap;
QHash<ChannelID, QVector<QString> > resmed_codes; QHash<ChannelID, QVector<QString> > resmed_codes;
EDFSignal * EDFParser::lookupSignal(ChannelID ch)
{
QHash<ChannelID, QVector<QString> >::iterator ci;
QHash<QString,EDFSignal *>::iterator jj;
ci=resmed_codes.find(ch);
if (ci==resmed_codes.end()) return NULL;
for (int i=0;i<ci.value().size();i++) {
jj=lookup.find(ci.value()[i]);
if (jj==lookup.end()) continue;
return jj.value();
}
return NULL;
}
EDFParser::EDFParser(QString name) EDFParser::EDFParser(QString name)
{ {
buffer=NULL; buffer=NULL;
@ -384,6 +398,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
if (qprogress) qprogress->setValue(33.0+(float(++cnt)/float(size)*33.0)); if (qprogress) qprogress->setValue(33.0+(float(++cnt)/float(size)*33.0));
QApplication::processEvents(); QApplication::processEvents();
EDFSignal *sig;
if (!sess) continue; if (!sess) continue;
if (!sess->first()) { if (!sess->first()) {
delete sess; delete sess;
@ -394,20 +409,26 @@ int ResmedLoader::Open(QString & path,Profile *profile)
int dn=dif/86400000L; int dn=dif/86400000L;
if (dn<days) { if (dn<days) {
int mode; int mode;
if (stredf.lookup.contains("Mode")) sig=stredf.lookupSignal(CPAP_Mode);
mode=(*stredf.lookup["Mode"]).data[dn]; if (sig) {
else mode=0; mode=sig->data[dn];
} else mode=0;
// AutoSV machines don't have both fields // AutoSV machines don't have both fields
if (stredf.lookup.contains("EPR")) sig=stredf.lookupSignal("EPR");
sess->settings["EPR"]=(*stredf.lookup["EPR"]).data[dn]; if (sig) {
if (stredf.lookup.contains("EPRSet")) sess->settings["EPR"]=sig->data[dn];
sess->settings["EPRSet"]=(*stredf.lookup["EPR Level"]).data[dn]; }
sig=stredf.lookupSignal("EPRLevel");
if (sig) {
sess->settings["EPRSet"]=sig->data[dn];
}
EDFSignal *sig;
if (mode==0) { if (mode==0) {
sess->settings[CPAP_Mode]=MODE_CPAP; sess->settings[CPAP_Mode]=MODE_CPAP;
sig=stredf.lookup["Set Pressure"]; sig=stredf.lookupSignal("Set Pressure");
if (sig) {
EventDataType pressure=sig->data[dn]*sig->gain; EventDataType pressure=sig->data[dn]*sig->gain;
sess->settings[CPAP_Pressure]=pressure; sess->settings[CPAP_Pressure]=pressure;
sess->setWavg(CPAP_Pressure,pressure); sess->setWavg(CPAP_Pressure,pressure);
@ -415,16 +436,19 @@ int ResmedLoader::Open(QString & path,Profile *profile)
sess->set90p(CPAP_Pressure,pressure); sess->set90p(CPAP_Pressure,pressure);
sess->setMax(CPAP_Pressure,pressure); sess->setMax(CPAP_Pressure,pressure);
sess->setMin(CPAP_Pressure,pressure); sess->setMin(CPAP_Pressure,pressure);
}
} else { } else {
if (mode>5) { if (mode>5) {
sess->settings[CPAP_Mode]=MODE_BIPAP; sess->settings[CPAP_Mode]=MODE_BIPAP;
} else { } else {
sess->settings[CPAP_Mode]=MODE_APAP; sess->settings[CPAP_Mode]=MODE_APAP;
} }
sig=stredf.lookup["Min Pressure"];
sig=stredf.lookupSignal(CPAP_PressureMin);
if (sig) if (sig)
sess->setMin(CPAP_Pressure,sig->data[dn]*sig->gain); sess->setMin(CPAP_Pressure,sig->data[dn]*sig->gain);
sig=stredf.lookup["Max Pressure"];
sig=stredf.lookupSignal(CPAP_PressureMax);
if (sig) if (sig)
sess->setMax(CPAP_Pressure,sig->data[dn]*sig->gain); sess->setMax(CPAP_Pressure,sig->data[dn]*sig->gain);
} }
@ -643,7 +667,7 @@ bool ResmedLoader::LoadSAD(Session *sess,EDFParser &edf)
//qDebug() << "SAD:" << es.label << es.digital_maximum << es.digital_minimum << es.physical_maximum << es.physical_minimum; //qDebug() << "SAD:" << es.label << es.digital_maximum << es.digital_minimum << es.physical_maximum << es.physical_minimum;
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords(); long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
ChannelID code; ChannelID code;
if (edf.edfsignals[s]->label=="Pulse") { if (edf.edfsignals[s]->label.startsWith("Puls")) {
code=OXI_Pulse; code=OXI_Pulse;
} else if (edf.edfsignals[s]->label=="SpO2") { } else if (edf.edfsignals[s]->label=="SpO2") {
code=OXI_SPO2; code=OXI_SPO2;
@ -694,7 +718,7 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
if (es.label=="Snore Index") { if (es.label=="Snore Index") {
code=CPAP_Snore; code=CPAP_Snore;
a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (es.label=="Therapy Pres") { } else if (es.label.startsWith("Therapy Pres")) {
code=CPAP_Pressure; //TherapyPressure; code=CPAP_Pressure; //TherapyPressure;
a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (es.label=="Insp Pressure") { } else if (es.label=="Insp Pressure") {
@ -704,7 +728,7 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
} else if (es.label=="MV") { } else if (es.label=="MV") {
code=CPAP_MinuteVent; code=CPAP_MinuteVent;
a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (es.label=="RR") { } else if ((es.label=="RR") || (es.label=="AF")) {
code=CPAP_RespRate; code=CPAP_RespRate;
a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate);
a->AddWaveform(edf.startdate,es.data,recs,duration); a->AddWaveform(edf.startdate,es.data,recs,duration);
@ -713,7 +737,7 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
es.physical_maximum=es.physical_minimum=0; es.physical_maximum=es.physical_minimum=0;
es.gain*=1000.0; es.gain*=1000.0;
a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (es.label=="Leak") { } else if ((es.label=="Leak") || (es.label.startsWith("Leck"))) {
code=CPAP_Leak; code=CPAP_Leak;
es.gain*=60; es.gain*=60;
es.physical_dimension="L/M"; es.physical_dimension="L/M";
@ -803,8 +827,13 @@ void ResInitModelMap()
resmed_codes[CPAP_EPAP].push_back("Exp Press"); resmed_codes[CPAP_EPAP].push_back("Exp Press");
resmed_codes[CPAP_EPAP].push_back("Exp Pressure"); // vpap resmed_codes[CPAP_EPAP].push_back("Exp Pressure"); // vpap
resmed_codes[CPAP_Leak].push_back("Leak"); resmed_codes[CPAP_Leak].push_back("Leak");
resmed_codes[CPAP_Leak].push_back("Leck.");
resmed_codes[CPAP_RespRate].push_back("RR"); resmed_codes[CPAP_RespRate].push_back("RR");
resmed_codes[CPAP_RespRate].push_back("AF");
resmed_codes[CPAP_TidalVolume].push_back("Vt"); resmed_codes[CPAP_TidalVolume].push_back("Vt");
resmed_codes[CPAP_MinuteVent].push_back("MV"); resmed_codes[CPAP_MinuteVent].push_back("MV");
resmed_codes[CPAP_IE].push_back("I:E"); // vpap resmed_codes[CPAP_IE].push_back("I:E"); // vpap
@ -817,6 +846,7 @@ void ResInitModelMap()
// Sad (oximetry) // Sad (oximetry)
resmed_codes[OXI_Pulse].push_back("Pulse"); resmed_codes[OXI_Pulse].push_back("Pulse");
resmed_codes[OXI_Pulse].push_back("Puls");
resmed_codes[OXI_SPO2].push_back("SpO2"); resmed_codes[OXI_SPO2].push_back("SpO2");
// Event annotations // Event annotations
@ -825,6 +855,18 @@ void ResInitModelMap()
resmed_codes[CPAP_Apnea].push_back("Apnea"); resmed_codes[CPAP_Apnea].push_back("Apnea");
resmed_codes[CPAP_ClearAirway].push_back("Central apnea"); resmed_codes[CPAP_ClearAirway].push_back("Central apnea");
resmed_codes[CPAP_Mode].push_back("Mode");
resmed_codes[CPAP_Mode].push_back("Modus");
resmed_codes["Set Pressure"].push_back("Eingest. Druck");
resmed_codes["Set Pressure"].push_back("Set Pressure");
resmed_codes["EPR"].push_back("EPR");
resmed_codes["EPRLevel"].push_back("EPR Level");
resmed_codes["EPRLevel"].push_back("EPR-Stufe");
resmed_codes[CPAP_PressureMax].push_back("Max Pressure");
resmed_codes[CPAP_PressureMax].push_back("Max. Druck");
resmed_codes[CPAP_PressureMin].push_back("Min Pressure");
resmed_codes[CPAP_PressureMin].push_back("Min. Druck");
// STR.edf // STR.edf
} }

View File

@ -70,6 +70,7 @@ public:
QVector<EDFSignal *> edfsignals; QVector<EDFSignal *> edfsignals;
QHash<QString,EDFSignal *> lookup; QHash<QString,EDFSignal *> lookup;
EDFSignal * lookupSignal(ChannelID);
long GetNumSignals() { return num_signals; } long GetNumSignals() { return num_signals; }
long GetNumDataRecords() { return num_data_records; } long GetNumDataRecords() { return num_data_records; }

View File

@ -229,29 +229,29 @@ void SerialOximeter::compactToEvent(EventList *el)
EventList nel(EVL_Waveform); EventList nel(EVL_Waveform);
EventDataType t,lastt=el->data(0); EventDataType t,lastt=el->data(0);
qint64 ti=el->time(0); qint64 ti=el->time(0);
for (qint32 i=0;i<el->count();i++) { for (quint32 i=0;i<el->count();i++) {
t=el->data(i); t=el->data(i);
if (t!=lastt) { if (t!=lastt) {
nel.AddEvent(ti,lastt); nel.AddEvent(ti,lastt);
ti=el->time(i); ti=el->time(i);
nel.AddEvent(ti,t);
} }
lastt=t; lastt=t;
} }
nel.AddEvent(el->last(),t); nel.AddEvent(el->last(),t);
el->getData().clear(); el->getData().clear();
el->getTime().clear(); el->getTime().clear();
el->setCount(nel.count()); el->setCount(0);//nel.count());
el->getData()=nel.getData(); //el->getData()=nel.getData();
el->getTime()=nel.getTime(); //el->getTime()=nel.getTime();
/* for (int i=0;i<nel.count();i++) { for (int i=0;i<nel.count();i++) {
el->getData().push_back(nel.data(i)); el->getData().push_back(nel.data(i));
el->getTime().push_back(nel.g) el->getTime().push_back(nel.time(i));
}*/ }
/*double rate=double(el->duration())/double(el->count()); /*double rate=double(el->duration())/double(el->count());
el->setType(EVL_Waveform); el->setType(EVL_Waveform);
@ -265,24 +265,14 @@ void SerialOximeter::compactAll()
for (i=session->eventlist.begin();i!=session->eventlist.end();i++) { for (i=session->eventlist.begin();i!=session->eventlist.end();i++) {
for (int j=0;j<i.value().size();j++) { for (int j=0;j<i.value().size();j++) {
if (i.key()==OXI_Plethy) { if (i.key()==OXI_SPO2) {
compactToWaveform(i.value()[j]);
} else {
compactToEvent(i.value()[j]); compactToEvent(i.value()[j]);
} else {
compactToWaveform(i.value()[j]);
} }
} }
} }
} }
/*void SerialOximeter::addEvents(EventDataType pr,EventDataType o2, EventDataType pleth)
{
lasttime=qint64(QDateTime::currentDateTime().toTime_t())*1000L;
addPulse(lasttime,pr);
addSpO2(lasttime,o2);
addPlethy(lasttime,pleth);
session->set_last(lasttime);
//emit(dataChanged());
}*/
Session *SerialOximeter::createSession() Session *SerialOximeter::createSession()
{ {
@ -529,6 +519,13 @@ void CMS50Serial::onReadyRead()
} }
} }
} }
if (import_mode && waitf6 && (cntf6==0)) {
failcnt++;
if (failcnt>2) {
emit(importAborted());
return;
}
}
emit(dataChanged()); emit(dataChanged());
} }
@ -537,6 +534,7 @@ bool CMS50Serial::startImport()
import_mode=true; import_mode=true;
waitf6=true; waitf6=true;
cntf6=0; cntf6=0;
failcnt=0;
//QMessageBox::information(0,"!!!Important Notice!!!","This Oximetry import method does NOT allow syncing of Oximetry and CPAP data.\nIf you really wish to record your oximetry data and have sync, you have to use the Live View mode (click Start) with the Oximeter connected to a computer via USB cable all night..\nEven then it will be out a bit because of your CPAP machines realtime clock drifts.",QMessageBox::Ok); //QMessageBox::information(0,"!!!Important Notice!!!","This Oximetry import method does NOT allow syncing of Oximetry and CPAP data.\nIf you really wish to record your oximetry data and have sync, you have to use the Live View mode (click Start) with the Oximeter connected to a computer via USB cable all night..\nEven then it will be out a bit because of your CPAP machines realtime clock drifts.",QMessageBox::Ok);
if (!Open(QextSerialPort::EventDriven)) return false; if (!Open(QextSerialPort::EventDriven)) return false;
connect(this,SIGNAL(importProcess()),this,SLOT(on_import_process())); connect(this,SIGNAL(importProcess()),this,SLOT(on_import_process()));
@ -869,9 +867,9 @@ void Oximetry::import_finished()
void Oximetry::on_import_aborted() void Oximetry::on_import_aborted()
{ {
qDebug() << "Oximetry import failed";
import_finished(); import_finished();
} }
void Oximetry::on_import_complete(Session * session) void Oximetry::on_import_complete(Session * session)
{ {
qDebug() << "Oximetry import complete"; qDebug() << "Oximetry import complete";
@ -901,7 +899,6 @@ void Oximetry::on_import_complete(Session * session)
PULSE->SetMaxX(l); PULSE->SetMaxX(l);
SPO2->SetMaxX(l); SPO2->SetMaxX(l);
PLETHY->forceMinY(0); PLETHY->forceMinY(0);
PLETHY->forceMaxY(128); PLETHY->forceMaxY(128);
PULSE->forceMinY(30); PULSE->forceMinY(30);

View File

@ -120,6 +120,7 @@ protected:
virtual void onReadyRead(); virtual void onReadyRead();
bool waitf6; bool waitf6;
short cntf6; short cntf6;
short failcnt;
QByteArray data; QByteArray data;
QVector<QDateTime> f2time; QVector<QDateTime> f2time;