From 7d0e5e60fe801ea3a28853b9e14fa9c20e5e6356 Mon Sep 17 00:00:00 2001 From: Mark Watkins Date: Tue, 12 Jul 2011 22:43:10 +1000 Subject: [PATCH] Weighted Average Fix --- Graphs/gSessionTime.cpp | 6 ++-- SleepLib/loader_plugins/prs1_loader.cpp | 46 ++++++++++++------------- SleepLib/machine_common.h | 5 ++- SleepLib/session.cpp | 12 +++---- daily.cpp | 36 +++++++++++++++++++ daily.h | 4 +-- docs/index.html | 2 +- 7 files changed, 74 insertions(+), 37 deletions(-) diff --git a/Graphs/gSessionTime.cpp b/Graphs/gSessionTime.cpp index 6eb3bf9f..a8e450ca 100644 --- a/Graphs/gSessionTime.cpp +++ b/Graphs/gSessionTime.cpp @@ -135,10 +135,10 @@ void gSessionTime::Plot(gGraphWindow & w,float scrx,float scry) GetTextExtent(str, textX, textY); if (!draw_xticks_instead && (textY+6count_events(CPAP_IAP)>0) { + //sess->summary[CPAP_Mode]!=MODE_ASV) sess->summary[CPAP_Mode]=MODE_BIPAP; + + sess->summary[BIPAP_PSAverage]=sess->weighted_avg_event_field(CPAP_PS,0); + sess->summary[BIPAP_PSMin]=sess->min_event_field(CPAP_PS,0); + sess->summary[BIPAP_PSMax]=sess->max_event_field(CPAP_PS,0); + if (sess->summary[CPAP_PressureReliefType].toInt()!=PR_NONE) { sess->summary[CPAP_PressureReliefType]=PR_BIFLEX; } @@ -340,6 +346,8 @@ int PRS1Loader::OpenMachine(Machine *m,QString path,Profile *profile) sess->summary[BIPAP_IAPMin]=sess->min_event_field(CPAP_IAP,0); sess->summary[BIPAP_IAPMax]=sess->max_event_field(CPAP_IAP,0); + + } else { sess->summary[CPAP_PressureMedian]=sess->avg_event_field(CPAP_Pressure,0); //sess->summary[CPAP_PressureAverage]=sess->weighted_avg_event_field(CPAP_Pressure,0); @@ -563,15 +571,24 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]/10.0; session->AddEvent(new Event(t,cpapcode, data,1)); break; + case 0x03: // BIPAP Pressure + data[0]=buffer[pos++]; + data[1]=buffer[pos++]; + data[0]/=10.0; + data[1]/=10.0; + session->AddEvent(new Event(t,CPAP_EAP, data, 1)); + session->AddEvent(new Event(t,CPAP_IAP, &data[1], 1)); + data[1]-=data[0]; + session->AddEvent(new Event(t,CPAP_PS, &data[1], 1)); + break; case 0x04: // Pressure Pulse data[0]=buffer[pos++]; session->AddEvent(new Event(t,cpapcode, data,1)); break; - - case 0x0a: // Hypopnea case 0x05: // RERA case 0x06: // Obstructive Apoanea case 0x07: // Clear Airway + case 0x0a: // Hypopnea case 0x0c: // Flow Limitation data[0]=buffer[pos++]; tt-=data[0]*1000; // Subtract Time Offset @@ -582,23 +599,9 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[1]=buffer[pos++]; session->AddEvent(new Event(tt,cpapcode,data,2)); break; - //case 0x08: // ASV Codes - //case 0x09: // ASV Codes - // data[0]=buffer[pos]; - // tt-=buffer[pos++]*1000; // Subtract Time Offset - // session->AddEvent(new Event(tt,cpapcode,data,1)); - // break; case 0x0d: // Vibratory Snore session->AddEvent(new Event(t,cpapcode, data,0)); break; - case 0x03: // BIPAP Pressure - data[0]=buffer[pos++]; - data[1]=buffer[pos++]; - data[0]/=10.0; - data[1]/=10.0; - session->AddEvent(new Event(t,CPAP_EAP, data, 1)); - session->AddEvent(new Event(t,CPAP_IAP, &data[1], 1)); - break; case 0x11: // Leak Rate data[0]=buffer[pos++]; data[1]=buffer[pos++]; @@ -609,13 +612,11 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 } break; case 0x0e: // Unknown - data[0]=buffer[pos++]; // << 8) | buffer[pos]; data[1]=buffer[pos++]; data[2]=buffer[pos++]; session->AddEvent(new Event(t,cpapcode, data, 3)); break; - case 0x10: // Unknown data[0]=buffer[pos++]; // << 8) | buffer[pos]; data[1]=buffer[pos++]; @@ -750,11 +751,6 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin session->AddEvent(new Event(t,CPAP_IAPLO,&data[1],1)); //correct data[2]=buffer[pos++]/10.0; // Hi IPAP session->AddEvent(new Event(t,CPAP_IAPHI,&data[2],1)); //correct - - // This may not be necessary.. Check: the average of IAPHI - average of IAPLO may equal the average of this. - data[2]-=data[1]; - session->AddEvent(new Event(t,CPAP_PS,&data[2],1)); //correct - data[3]=buffer[pos++];//Leak session->AddEvent(new Event(t,CPAP_Leak,&data[3],1)); // correct data[4]=buffer[pos++];//Breaths Per Minute @@ -770,9 +766,11 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin if (data[8]>0) { session->AddEvent(new Event(t,CPAP_VSnore,&data[8],1)); //correct } - data[9]=buffer[pos++]/10.0; // This is a pressure value + data[9]=buffer[pos++]/10.0; // EPAP session->AddEvent(new Event(t,CPAP_EAP,&data[9],1)); //correct + data[2]-=data[9]; // Pressure Support + session->AddEvent(new Event(t,CPAP_PS,&data[2],1)); //correct qDebug()<< d.toString("yyyy-MM-dd HH:mm:ss") << hex << session->session() << pos+15 << hex << int(code) << ": " << hex << int(data[0]) << " " << int(data[1]) << " " << int(data[2]) << " " << int(data[3]) << " " << int(data[4]) << " " << int(data[5])<< " " << int(data[6]) << " " << int(data[7]) << " " << int(data[8]) << " " << int(data[9]); break; case 0x03: // BIPAP Pressure diff --git a/SleepLib/machine_common.h b/SleepLib/machine_common.h index e100dd18..e847c7bf 100644 --- a/SleepLib/machine_common.h +++ b/SleepLib/machine_common.h @@ -45,7 +45,10 @@ enum MachineCode//:qint16 CPAP_LeakMedian,CPAP_LeakMinimum,CPAP_LeakMaximum,CPAP_LeakAverage,CPAP_Duration, CPAP_SnoreMinimum, CPAP_SnoreMaximum, CPAP_SnoreAverage, CPAP_SnoreMedian, - BIPAP_EAPAverage,BIPAP_IAPAverage,BIPAP_EAPMin,BIPAP_EAPMax,BIPAP_IAPMin,BIPAP_IAPMax,CPAP_BrokenSummary, + BIPAP_EAPAverage,BIPAP_IAPAverage,BIPAP_EAPMin,BIPAP_EAPMax,BIPAP_IAPMin,BIPAP_IAPMax, + BIPAP_PSAverage,BIPAP_PSMin, BIPAP_PSMax, + + CPAP_BrokenSummary, // PRS1 Specific Codes PRS1_PressurePulse=0x1000,PRS1_VSnore2, diff --git a/SleepLib/session.cpp b/SleepLib/session.cpp index ef284f22..728f262a 100644 --- a/SleepLib/session.cpp +++ b/SleepLib/session.cpp @@ -147,7 +147,7 @@ double Session::weighted_avg_event_field(MachineCode mc,int field) double mult; - if ((mc==CPAP_Pressure) || (mc==CPAP_EAP) || (mc==CPAP_IAP)) { + if ((mc==CPAP_Pressure) || (mc==CPAP_EAP) || (mc==CPAP_IAP) | (mc==CPAP_PS)) { mult=10.0; } else mult=10.0; @@ -175,21 +175,21 @@ double Session::weighted_avg_event_field(MachineCode mc,int field) lastval=val; } - qint64 total; + qint64 total=0; for (int i=0; i 0) { - s0=(vtime[i]/3600.0); + s0=vtime[i]; s1+=i*s0; s2+=s0; } } - - return (s1/total)/mult; + double j=double(s1)/double(total); + return j/mult; } void Session::AddEvent(Event * e) diff --git a/daily.cpp b/daily.cpp index d74e53d5..9cd83fee 100644 --- a/daily.cpp +++ b/daily.cpp @@ -188,6 +188,13 @@ Daily::Daily(QWidget *parent,QGLContext *context) : RR->AddLayer(new gLineChart(rr,Qt::gray,65536,false,false,true)); RR->setMinimumHeight(150); + AddCPAPData(ptb=new EventData(CPAP_PatientTriggeredBreaths )); + PTB=new gGraphWindow(gSplitter,tr("Patient Trig Breaths"),SF); + PTB->AddLayer(new gXAxis()); + PTB->AddLayer(new gYAxis()); + PTB->AddLayer(new gLineChart(ptb,Qt::gray,65536,false,false,true)); + PTB->setMinimumHeight(150); + AddOXIData(pulse=new EventData(OXI_Pulse,0,65536,true)); //pulse->ForceMinY(40); @@ -276,6 +283,8 @@ Daily::Daily(QWidget *parent,QGLContext *context) : FRW->LinkZoom(TV); FRW->LinkZoom(RR); FRW->LinkZoom(FLG); + FRW->LinkZoom(PTB); + SF->LinkZoom(FRW); SF->LinkZoom(MP); SF->LinkZoom(PRD); @@ -285,6 +294,8 @@ Daily::Daily(QWidget *parent,QGLContext *context) : SF->LinkZoom(TV); SF->LinkZoom(RR); SF->LinkZoom(FLG); + SF->LinkZoom(PTB); + PRD->LinkZoom(SF); PRD->LinkZoom(FRW); PRD->LinkZoom(MP); @@ -294,6 +305,18 @@ Daily::Daily(QWidget *parent,QGLContext *context) : PRD->LinkZoom(TV); PRD->LinkZoom(RR); PRD->LinkZoom(FLG); + PRD->LinkZoom(PTB); + + PTB->LinkZoom(SF); + PTB->LinkZoom(FRW); + PTB->LinkZoom(MP); + PTB->LinkZoom(LEAK); + PTB->LinkZoom(SNORE); + PTB->LinkZoom(MV); + PTB->LinkZoom(TV); + PTB->LinkZoom(RR); + PTB->LinkZoom(FLG); + PTB->LinkZoom(PRD); LEAK->LinkZoom(SF); LEAK->LinkZoom(FRW); @@ -304,6 +327,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : LEAK->LinkZoom(TV); LEAK->LinkZoom(RR); LEAK->LinkZoom(FLG); + LEAK->LinkZoom(PTB); SNORE->LinkZoom(SF); SNORE->LinkZoom(FRW); @@ -314,6 +338,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : SNORE->LinkZoom(TV); SNORE->LinkZoom(RR); SNORE->LinkZoom(FLG); + SNORE->LinkZoom(PTB); MV->LinkZoom(SF); MV->LinkZoom(FRW); @@ -324,6 +349,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : MV->LinkZoom(TV); MV->LinkZoom(RR); MV->LinkZoom(FLG); + MV->LinkZoom(PTB); TV->LinkZoom(SF); TV->LinkZoom(FRW); @@ -334,6 +360,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : TV->LinkZoom(MV); TV->LinkZoom(RR); TV->LinkZoom(FLG); + TV->LinkZoom(PTB); RR->LinkZoom(SF); RR->LinkZoom(FRW); @@ -344,6 +371,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : RR->LinkZoom(MV); RR->LinkZoom(TV); RR->LinkZoom(FLG); + RR->LinkZoom(PTB); FLG->LinkZoom(SF); FLG->LinkZoom(FRW); @@ -354,6 +382,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : FLG->LinkZoom(MV); FLG->LinkZoom(TV); FLG->LinkZoom(RR); + FLG->LinkZoom(PTB); MP->LinkZoom(SF); MP->LinkZoom(FRW); @@ -364,6 +393,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : MP->LinkZoom(MV); MP->LinkZoom(TV); MP->LinkZoom(RR); + MP->LinkZoom(PTB); gSplitter->addWidget(NoData); @@ -372,6 +402,7 @@ Daily::Daily(QWidget *parent,QGLContext *context) : AddGraph(MP); AddGraph(MV); AddGraph(TV); + AddGraph(PTB); AddGraph(RR); AddGraph(PRD); AddGraph(LEAK); @@ -664,6 +695,10 @@ void Daily::Load(QDate date) html+=("")+a.sprintf("%.2f",cpap->summary_weighted_avg(BIPAP_IAPAverage)); html+=("")+a.sprintf("%.2f",cpap->summary_max(BIPAP_IAPMax))+(""); + html+=(""+tr("PS:")+"")+a.sprintf("%.2f",cpap->summary_min(BIPAP_PSMin)); + html+=("")+a.sprintf("%.2f",cpap->summary_weighted_avg(BIPAP_PSAverage)); + html+=("")+a.sprintf("%.2f",cpap->summary_max(BIPAP_PSMax))+(""); + } html+=""+tr("Leak:"); html+=""+a.sprintf("%.2f",cpap->summary_min(CPAP_LeakMinimum)); @@ -713,6 +748,7 @@ void Daily::Load(QDate date) prd->isEmpty() && pressure_iap->isEmpty() ? PRD->hide() : PRD->show(); leak->isEmpty() ? LEAK->hide() : LEAK->show(); snore->isEmpty() ? SNORE->hide() : SNORE->show(); + ptb->isEmpty() ? PTB->hide() : PTB->show(); bool merge_oxi_graphs=true; if (!merge_oxi_graphs) { diff --git a/daily.h b/daily.h index eb1f9905..a0d269c1 100644 --- a/daily.h +++ b/daily.h @@ -58,10 +58,10 @@ private: void UpdateEventsTree(QTreeWidget * tree,Day *day); gPointData *tap,*tap_eap,*tap_iap,*g_ahi,*frw,*prd,*leak,*pressure_iap,*pressure_eap,*snore; - gPointData *pulse,*spo2,*rr,*mv,*tv,*mp,*flg; + gPointData *pulse,*spo2,*rr,*mv,*tv,*mp,*flg,*ptb; gFlagsGroup *fg; - gGraphWindow *PRD,*FRW,*G_AHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2,*SNORE,*RR,*MP,*MV,*TV,*FLG; + gGraphWindow *PRD,*FRW,*G_AHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2,*SNORE,*RR,*MP,*MV,*TV,*FLG,*PTB; list OXIData; list CPAPData; diff --git a/docs/index.html b/docs/index.html index f5227107..ceab6c86 100644 --- a/docs/index.html +++ b/docs/index.html @@ -12,7 +12,7 @@ p,a,td,body { font-size: 14px }

This software is designed to assist you in reviewing data for your CPAP Machine, Oximeter, and Sleep Stage monitors, as well as help you track general issues related to sleep health.

Currenly supports the following machines:

-
  • Philips Respironics System One (BIPAP and lower)
  • +
  • Philips Respironics System One (Including ASV models)
  • ResMed S9 models (AutoSet and lower)
  • Contec CMS50 Oximeters
  • Project Website: http://sleepyhead.sourceforge.net