diff --git a/Graphs/gFooBar.cpp b/Graphs/gFooBar.cpp index 4900b9ef..b2bcdc63 100644 --- a/Graphs/gFooBar.cpp +++ b/Graphs/gFooBar.cpp @@ -7,7 +7,7 @@ #include "gFooBar.h" gShadowArea::gShadowArea(QColor shadow_color) -:Layer(EmptyChannel),m_shadow_color(shadow_color) +:Layer(""),m_shadow_color(shadow_color) { QColor col=Qt::blue; addGLBuf(quads=new GLBuffer(shadow_color,20,GL_QUADS)); @@ -46,7 +46,7 @@ void gShadowArea::paint(gGraph & w,int left, int top, int width, int height) } gFooBar::gFooBar(int offset,QColor handle_color,QColor line_color) -:Layer(EmptyChannel),m_offset(offset),m_handle_color(handle_color),m_line_color(line_color) +:Layer(""),m_offset(offset),m_handle_color(handle_color),m_line_color(line_color) { } gFooBar::~gFooBar() @@ -66,7 +66,7 @@ void gFooBar::paint(gGraph & w,int left, int top, int width, int height) int start_px=left; //int end_px=left+width; - float h=top; + //float h=top; /* glLineWidth(1); glBegin(GL_LINES); diff --git a/Graphs/gGraphView.cpp b/Graphs/gGraphView.cpp index e24d4659..80ef2ada 100644 --- a/Graphs/gGraphView.cpp +++ b/Graphs/gGraphView.cpp @@ -357,7 +357,7 @@ void Layer::drawGLBuf() void Layer::SetDay(Day * d) { - if (d && m_code!=EmptyChannel) { + if (d && !m_code.isEmpty()) { m_day=d; m_minx=d->first(m_code); m_maxx=d->last(m_code); @@ -382,7 +382,7 @@ void Layer::setLayout(LayerPosition position, short width, short height, short o } LayerGroup::LayerGroup() : - Layer(EmptyChannel) + Layer("") { } LayerGroup::~LayerGroup() diff --git a/Graphs/gLineChart.cpp b/Graphs/gLineChart.cpp index 29f35d62..087c621f 100644 --- a/Graphs/gLineChart.cpp +++ b/Graphs/gLineChart.cpp @@ -36,6 +36,8 @@ void gLineChart::paint(gGraph & w,int left, int top, int width, int height) if (!m_day) return; + if (!m_day->channelExists(m_code)) return; + if (width<0) return; diff --git a/Graphs/gSegmentChart.cpp b/Graphs/gSegmentChart.cpp index 81c0ffb2..f671cd1b 100644 --- a/Graphs/gSegmentChart.cpp +++ b/Graphs/gSegmentChart.cpp @@ -9,7 +9,7 @@ gSegmentChart::gSegmentChart(GraphSegmentType type,QColor gradient_color,QColor outline_color) -:Layer(EmptyChannel),m_graph_type(type),m_gradient_color(gradient_color),m_outline_color(outline_color) +:Layer(""),m_graph_type(type),m_gradient_color(gradient_color),m_outline_color(outline_color) { // m_gradient_color=QColor(200,200,200); m_empty=true; diff --git a/Graphs/gSessionTime.cpp b/Graphs/gSessionTime.cpp index 492748bd..137c8178 100644 --- a/Graphs/gSessionTime.cpp +++ b/Graphs/gSessionTime.cpp @@ -9,7 +9,7 @@ #include "gSessionTime.h" gTimeYAxis::gTimeYAxis(QColor col) - :gYAxis(EmptyChannel,col) + :gYAxis("",col) { } gTimeYAxis::~gTimeYAxis() diff --git a/Graphs/gSessionTime.h b/Graphs/gSessionTime.h index e47cc8c6..465cb7a3 100644 --- a/Graphs/gSessionTime.h +++ b/Graphs/gSessionTime.h @@ -23,7 +23,7 @@ public: class gSessionTime:public Layer { public: - gSessionTime(ChannelID=EmptyChannel,QColor col=QColor("blue"),Qt::Orientation o=Qt::Horizontal); + gSessionTime(ChannelID="",QColor col=QColor("blue"),Qt::Orientation o=Qt::Horizontal); virtual ~gSessionTime(); virtual void paint(gGraph & w,int left,int top, int width, int height); diff --git a/Graphs/gBarChart.cpp b/Graphs/gSummaryChart.cpp similarity index 99% rename from Graphs/gBarChart.cpp rename to Graphs/gSummaryChart.cpp index 2e75d914..5827d29d 100644 --- a/Graphs/gBarChart.cpp +++ b/Graphs/gSummaryChart.cpp @@ -8,11 +8,11 @@ #include #include #include "gYAxis.h" -#include "gBarChart.h" +#include "gSummaryChart.h" extern QLabel * qstatus2; SummaryChart::SummaryChart(Profile *p,QString label,GraphType type) -:Layer(EmptyChannel),m_profile(p),m_label(label),m_graphtype(type) +:Layer(""),m_profile(p),m_label(label),m_graphtype(type) { QColor color=Qt::black; addGLBuf(quads=new GLBuffer(color,20000,GL_QUADS)); @@ -311,7 +311,7 @@ void SummaryChart::paint(gGraph & w,int left, int top, int width, int height) int x,y; for (int j=0;j #include "gYAxis.h" -gYSpacer::gYSpacer(int spacer) :Layer(EmptyChannel) +gYSpacer::gYSpacer(int spacer) + :Layer("") { -}; +} gXGrid::gXGrid(QColor col) - :Layer(EmptyChannel) + :Layer("") { m_major_color=QColor(180,180,180,128); m_minor_color=QColor(220,220,220,128); diff --git a/Graphs/gYAxis.h b/Graphs/gYAxis.h index 9b38dc18..31b7ae53 100644 --- a/Graphs/gYAxis.h +++ b/Graphs/gYAxis.h @@ -39,7 +39,7 @@ protected: class gYAxis:public Layer { public: - gYAxis(ChannelID code=EmptyChannel,QColor col=QColor("black")); + gYAxis(ChannelID code="",QColor col=QColor("black")); virtual ~gYAxis(); virtual void paint(gGraph & w,int left,int top, int width, int height); void SetShowMinorLines(bool b) { m_show_minor_lines=b; } diff --git a/Resources.qrc b/Resources.qrc index 3d845e87..dc053c2b 100644 --- a/Resources.qrc +++ b/Resources.qrc @@ -16,5 +16,7 @@ icons/oximeter.png docs/0.0.gif docs/template_overview.sht + docs/schema.xml + docs/channels.xml diff --git a/SleepLib/day.cpp b/SleepLib/day.cpp index f687a2e8..ba26df07 100644 --- a/SleepLib/day.cpp +++ b/SleepLib/day.cpp @@ -300,7 +300,7 @@ EventDataType Day::max(ChannelID code) EventDataType Day::cph(ChannelID code) { EventDataType sum=0; - EventDataType h=0; + //EventDataType h=0; for (int i=0;im_cph.contains(code)) continue; sum+=sessions[i]->cph(code)*sessions[i]->hours(); @@ -334,12 +334,18 @@ int Day::count(ChannelID code) } bool Day::channelExists(ChannelID id) { - if (machine->hasChannel(id)) return true; - /*for (int i=0;ichannelExists(id)) - return true; - } */ - return false; + return machine->hasChannel(id); +} +bool Day::channelHasData(ChannelID id) +{ + bool r=false; + for (int i=0;ichannelExists(id)) { + r=true; + break; + } + } + return r; } void Day::OpenEvents() diff --git a/SleepLib/day.h b/SleepLib/day.h index ab7f9c80..6ff006d2 100644 --- a/SleepLib/day.h +++ b/SleepLib/day.h @@ -68,6 +68,7 @@ public: void OpenEvents(); QVector & getSessions() { return sessions; } bool channelExists(ChannelID id); + bool channelHasData(ChannelID id); protected: QVector sessions; qint64 d_first,d_last; diff --git a/SleepLib/event.cpp b/SleepLib/event.cpp index 2ee55e51..cb081358 100644 --- a/SleepLib/event.cpp +++ b/SleepLib/event.cpp @@ -7,8 +7,8 @@ #include #include "event.h" -EventList::EventList(ChannelID code,EventListType et,EventDataType gain, EventDataType offset, EventDataType min, EventDataType max,double rate) - :m_code(code),m_type(et),m_gain(gain),m_offset(offset),m_min(min),m_max(max),m_rate(rate) +EventList::EventList(EventListType et,EventDataType gain, EventDataType offset, EventDataType min, EventDataType max,double rate) + :m_type(et),m_gain(gain),m_offset(offset),m_min(min),m_max(max),m_rate(rate) { m_first=m_last=0; m_count=0; diff --git a/SleepLib/event.h b/SleepLib/event.h index 682aba62..722ba5f0 100644 --- a/SleepLib/event.h +++ b/SleepLib/event.h @@ -1,24 +1,23 @@ -/******************************************************************** +/* SleepLib Event Class Header Copyright (c)2011 Mark Watkins License: GPL -*********************************************************************/ +*/ #ifndef EVENT_H #define EVENT_H #include -#include "SleepLib/session.h" +//#include "SleepLib/session.h" #include "machine_common.h" - enum EventListType { EVL_Waveform, EVL_Event }; class EventList { friend class Session; public: - EventList(ChannelID code,EventListType et,EventDataType gain=1.0, EventDataType offset=0.0, EventDataType min=0.0, EventDataType max=0.0, double rate=0.0); + EventList(EventListType et,EventDataType gain=1.0, EventDataType offset=0.0, EventDataType min=0.0, EventDataType max=0.0, double rate=0.0); ~EventList(); void AddEvent(qint64 time, EventStoreType data); @@ -44,7 +43,7 @@ public: void setMin(EventDataType v) { m_min=v; } void setMax(EventDataType v) { m_max=v; } void setRate(EventDataType v) { m_rate=v; } - void setCode(ChannelID id) { m_code=id; } + //void setCode(ChannelID id) { m_code=id; } inline const EventDataType & min() { return m_min; } inline const EventDataType & max() { return m_max; } @@ -52,7 +51,7 @@ public: inline const EventDataType & offset() { return m_offset; } inline const EventDataType & rate() { return m_rate; } inline const EventListType & type() { return m_type; } - inline const ChannelID & code() { return m_code; } + //inline const ChannelID & code() { return m_code; } inline const bool & update_minmax() { return m_update_minmax; } QString dimension() { return m_dimension; } @@ -63,7 +62,7 @@ public: protected: QVector m_time; // 32bitalize this.. add offsets to m_first QVector m_data; - ChannelID m_code; + //ChannelID m_code; EventListType m_type; int m_count; diff --git a/SleepLib/loader_plugins/cms50_loader.cpp b/SleepLib/loader_plugins/cms50_loader.cpp index 381e5a36..43690c42 100644 --- a/SleepLib/loader_plugins/cms50_loader.cpp +++ b/SleepLib/loader_plugins/cms50_loader.cpp @@ -224,10 +224,9 @@ bool CMS50Loader::OpenSPORFile(QString path,Machine *mach,Profile *profile) Session *sess=new Session(mach,sessid); sess->updateFirst(starttime); - EventList *oxip=new EventList(OXI_Pulse,EVL_Event); - EventList *oxis=new EventList(OXI_SPO2,EVL_Event); - sess->eventlist[OXI_Pulse].push_back(oxip); - sess->eventlist[OXI_SPO2].push_back(oxis); + EventList *oxip=sess->AddEventList(OXI_Pulse,EVL_Event); + EventList *oxis=sess->AddEventList(OXI_SPO2,EVL_Event); + oxip->AddEvent(starttime,last_pulse); oxis->AddEvent(starttime,last_spo2); diff --git a/SleepLib/loader_plugins/prs1_loader.cpp b/SleepLib/loader_plugins/prs1_loader.cpp index 43bc316c..802b1ef0 100644 --- a/SleepLib/loader_plugins/prs1_loader.cpp +++ b/SleepLib/loader_plugins/prs1_loader.cpp @@ -15,6 +15,7 @@ License: GPL #include #include #include +#include "SleepLib/schema.h" #include "prs1_loader.h" #include "SleepLib/session.h" @@ -43,7 +44,6 @@ PRS1::PRS1(Profile *p,MachineID id):CPAP(p,id) properties["Brand"]="Philips Respironics"; properties["Model"]="System One"; - //SleepFlags= { CPAP_RERA, PRS1_VSnore2, CPAP_FlowLimit, CPAP_Hypopnea, CPAP_Obstructive, CPAP_ClearAirway, CPAP_CSR }; } PRS1::~PRS1() { @@ -313,20 +313,22 @@ int PRS1Loader::OpenMachine(Machine *m,QString path,Profile *profile) continue; } + if (sess->count(CPAP_IPAP)>0) { //sess->summaryCPAP_Mode]!=MODE_ASV) sess->settings[CPAP_Mode]=MODE_BIPAP; - if (sess->settings[PRS1_PressureReliefType].toInt()!=PR_NONE) { - sess->settings[PRS1_PressureReliefType]=PR_BIFLEX; + if (sess->settings[PRS1_FlexMode].toInt()!=PR_NONE) { + sess->settings[PRS1_FlexMode]=PR_BIFLEX; } + sess->setAvg(CPAP_Pressure,(sess->avg(CPAP_EPAP)+sess->avg(CPAP_IPAP))/2.0); sess->setWavg(CPAP_Pressure,(sess->wavg(CPAP_EPAP)+sess->wavg(CPAP_IPAP))/2.0); sess->setMin(CPAP_Pressure,sess->min(CPAP_EPAP)); sess->setMax(CPAP_Pressure,sess->max(CPAP_IPAP)); - sess->set90p(CPAP_Pressure,sess->p90(CPAP_IPAP)); - sess->p90(CPAP_EPAP); + sess->set90p(CPAP_Pressure,(sess->p90(CPAP_IPAP)+sess->p90(CPAP_EPAP))/2.0); + //sess->p90(CPAP_EPAP); //sess->p90(CPAP_IPAP); } else { sess->avg(CPAP_Pressure); @@ -336,20 +338,20 @@ int PRS1Loader::OpenMachine(Machine *m,QString path,Profile *profile) sess->max(CPAP_Pressure); sess->cph(CPAP_Pressure); - if (!sess->settings.contains(PRS1_PressureMin)) { + if (!sess->settings.contains(CPAP_PressureMin)) { sess->settings[CPAP_BrokenSummary]=true; //sess->set_last(sess->first()); if (sess->min(CPAP_Pressure)==sess->max(CPAP_Pressure)) { - sess->settings[CPAP_Mode]=MODE_CPAP; // no ramp + sess->settings["PRS1Mode"]=MODE_CPAP; // no ramp } else { - sess->settings[CPAP_Mode]=MODE_UNKNOWN; + sess->settings["PRS1Mode"]=MODE_UNKNOWN; } - sess->settings[PRS1_PressureReliefType]=PR_UNKNOWN; + //sess->Set("FlexMode",PR_UNKNOWN); } } if (sess->settings[CPAP_Mode]==MODE_CPAP) { - sess->settings[PRS1_PressureMax]=sess->settings[PRS1_PressureMin]; + sess->settings[CPAP_PressureMax]=sess->settings[CPAP_PressureMin]; } //Printf(sess->start().Format()+wxT(" avgsummary=%.3f avgmine=%.3f\n"),sess->summary[CPAP_PressureAverage].GetDouble(),sess->weighted_avg_event_field(CPAP_Pressure,0)); @@ -433,16 +435,16 @@ bool PRS1Loader::OpenSummary(Session *session,QString filename) session->set_first(date); double max; - session->settings[PRS1_PressureMin]=(EventDataType)buffer[0x03]/10.0; - session->settings[PRS1_PressureMax]=max=(EventDataType)buffer[0x04]/10.0; + session->settings[CPAP_PressureMin]=(EventDataType)buffer[0x03]/10.0; + session->settings[CPAP_PressureMax]=max=(EventDataType)buffer[0x04]/10.0; int offset=0; if (buffer[0x05]!=0) { // This is a time value for ASV stuff // non zero adds extra fields.. offset=4; } - session->settings[PRS1_RampTime]=(int)buffer[offset+0x06]; // Minutes. Convert to seconds/hours here? - session->settings[PRS1_RampPressure]=(EventDataType)buffer[offset+0x07]/10.0; + session->settings[CPAP_RampTime]=(int)buffer[offset+0x06]; // Minutes. Convert to seconds/hours here? + session->settings[CPAP_RampPressure]=(EventDataType)buffer[offset+0x07]/10.0; if (max>0) { // Ignoring bipap until I see some more data. session->settings[CPAP_Mode]=(int)MODE_APAP; @@ -451,21 +453,21 @@ bool PRS1Loader::OpenSummary(Session *session,QString filename) // This is incorrect.. if (buffer[offset+0x08] & 0x80) { // Flex Setting if (buffer[offset+0x08] & 0x08) { - if (max>0) session->settings[PRS1_PressureReliefType]=(int)PR_AFLEX; - else session->settings[PRS1_PressureReliefType]=(int)PR_CFLEXPLUS; - } else session->settings[PRS1_PressureReliefType]=(int)PR_CFLEX; - } else session->settings[PRS1_PressureReliefType]=(int)PR_NONE; + if (max>0) session->settings[PRS1_FlexMode]=(int)PR_AFLEX; + else session->settings[PRS1_FlexMode]=(int)PR_CFLEXPLUS; + } else session->settings[PRS1_FlexMode]=(int)PR_CFLEX; + } else session->settings[PRS1_FlexMode]=(int)PR_NONE; - session->settings[PRS1_PressureReliefSetting]=(int)buffer[offset+0x08] & 3; - session->settings[PRS1_HumidifierSetting]=(int)buffer[offset+0x09]&0x0f; - session->settings[PRS1_HumidifierStatus]=(buffer[offset+0x09]&0x80)==0x80; - session->settings[PRS1_SystemLockStatus]=(buffer[offset+0x0a]&0x80)==0x80; - session->settings[PRS1_SystemOneResistanceStatus]=(buffer[offset+0x0a]&0x40)==0x40; - session->settings[PRS1_SystemOneResistanceSetting]=(int)buffer[offset+0x0a]&7; - session->settings[PRS1_HoseDiameter]=(int)((buffer[offset+0x0a]&0x08)?15:22); - session->settings[PRS1_AutoOff]=(buffer[offset+0x0c]&0x10)==0x10; - session->settings[PRS1_MaskAlert]=(buffer[offset+0x0c]&0x08)==0x08; - session->settings[PRS1_ShowAHI]=(buffer[offset+0x0c]&0x04)==0x04; + session->settings["FlexSet"]=(int)buffer[offset+0x08] & 3; + session->settings["HumidSet"]=(int)buffer[offset+0x09]&0x0f; + session->settings["HumidStat"]=(buffer[offset+0x09]&0x80)==0x80; + session->settings["SysLock"]=(buffer[offset+0x0a]&0x80)==0x80; + session->settings["SysOneResistStat"]=(buffer[offset+0x0a]&0x40)==0x40; + session->settings["SysOneResistSet"]=(int)buffer[offset+0x0a]&7; + session->settings["HoseDiam"]=((buffer[offset+0x0a]&0x08)?"15mm":"22mm"); + session->settings["AutoOff"]=(buffer[offset+0x0c]&0x10)==0x10; + session->settings["MaskAlert"]=(buffer[offset+0x0c]&0x08)==0x08; + session->settings["ShowAHI"]=(buffer[offset+0x0c]&0x04)==0x04; unsigned duration=buffer[offset+0x14] | (buffer[0x15] << 8); //session->settings[CPAP_Duration]=(int)duration; @@ -476,13 +478,13 @@ bool PRS1Loader::OpenSummary(Session *session,QString filename) return false; session->set_last(date+qint64(duration)*1000L); - session->settings[PRS1_PressureMinAchieved]=buffer[offset+0x16]/10.0; - session->settings[PRS1_PressureMaxAchieved]=buffer[offset+0x17]/10.0; - session->settings[PRS1_PressureAvg]=buffer[offset+0x18]/10.0; - session->settings[PRS1_Pressure90]=buffer[offset+0x19]/10.0; + //session->settings[PRS1_PressureMinAchieved]=buffer[offset+0x16]/10.0; + //session->settings[PRS1_PressureMaxAchieved]=buffer[offset+0x17]/10.0; + //session->settings[PRS1_PressureAvg]=buffer[offset+0x18]/10.0; + //session->settings[PRS1_Pressure90]=buffer[offset+0x19]/10.0; if (max==0) { - session->settings[PRS1_PressureAvg]=session->settings[PRS1_PressureMin]; + // session->settings[PRS1_PressureAvg]=session->settings[PRS1_PressureMin]; } // Not using these because sometimes this summary is broken. @@ -500,13 +502,14 @@ bool PRS1Loader::OpenSummary(Session *session,QString filename) // v2 event parser. bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 timestamp) { - ChannelID Codes[]={ + /*ChannelID Codes[]={ PRS1_Unknown00, PRS1_Unknown01, CPAP_Pressure, CPAP_EPAP, CPAP_PressurePulse, CPAP_RERA, CPAP_Obstructive, CPAP_ClearAirway, PRS1_Unknown08, PRS1_Unknown09, CPAP_Hypopnea, PRS1_Unknown0B, CPAP_FlowLimit, CPAP_VSnore, PRS1_Unknown0E, CPAP_CSR, PRS1_Unknown10, CPAP_Leak, PRS1_Unknown12 }; - int ncodes=sizeof(Codes)/sizeof(ChannelID); + int ncodes=sizeof(Codes)/sizeof(ChannelID); */ + //QHash Code; EventList * Code[0x20]={NULL}; EventDataType data[10]; @@ -520,7 +523,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 short delta; while (pos=ncodes) { + if (code>0x12) { qDebug() << "Illegal PRS1 code " << hex << int(code) << " appeared at " << hex << pos+16; return false; } @@ -534,42 +537,31 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 cnt++; switch (code) { + case 0x00: // Unknown 00 if (!Code[0]) { - Code[0]=new EventList(PRS1_Unknown00,EVL_Event); - session->eventlist[PRS1_Unknown00].push_back(Code[0]); - session->machine()->registerChannel(PRS1_Unknown00); + if (!(Code[0]=session->AddEventList(PRS1_00,EVL_Event))) return false; } Code[0]->AddEvent(t,buffer[pos++]); break; case 0x01: // Unknown if (!Code[1]) { - Code[1]=new EventList(PRS1_Unknown01,EVL_Event); - session->eventlist[PRS1_Unknown01].push_back(Code[1]); - session->machine()->registerChannel(PRS1_Unknown01); + if (!(Code[1]=session->AddEventList(PRS1_01,EVL_Event))) return false; } Code[1]->AddEvent(t,0); break; case 0x02: // Pressure if (!Code[2]) { - Code[2]=new EventList(CPAP_Pressure,EVL_Event,0.1); - session->eventlist[CPAP_Pressure].push_back(Code[2]); - session->machine()->registerChannel(CPAP_Pressure); + Code[2]=session->AddEventList(CPAP_Pressure,EVL_Event,0.1); + if (!Code[2]) return false; } Code[2]->AddEvent(t,buffer[pos++]); break; case 0x03: // BIPAP Pressure if (!Code[3]) { - Code[3]=new EventList(CPAP_EPAP,EVL_Event,0.1); - session->eventlist[CPAP_EPAP].push_back(Code[3]); - Code[4]=new EventList(CPAP_IPAP,EVL_Event,0.1); - session->eventlist[CPAP_IPAP].push_back(Code[4]); - Code[5]=new EventList(CPAP_PressureSupport,EVL_Event,0.1); - session->eventlist[CPAP_PressureSupport].push_back(Code[5]); - session->machine()->registerChannel(CPAP_EPAP); - session->machine()->registerChannel(CPAP_IPAP); - session->machine()->registerChannel(CPAP_PressureSupport); - + if (!(Code[3]=session->AddEventList(CPAP_EPAP,EVL_Event,0.1))) return false; + if (!(Code[4]=session->AddEventList(CPAP_IPAP,EVL_Event,0.1))) return false; + if (!(Code[5]=session->AddEventList(CPAP_PS,EVL_Event,0.1))) return false; } Code[3]->AddEvent(t,data[0]=buffer[pos++]); Code[4]->AddEvent(t,data[1]=buffer[pos++]); @@ -577,9 +569,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 break; case 0x04: // Pressure Pulse if (!Code[6]) { - Code[6]=new EventList(CPAP_PressurePulse,EVL_Event); - session->eventlist[CPAP_PressurePulse].push_back(Code[6]); - session->machine()->registerChannel(CPAP_PressurePulse); + if (!(Code[6]=session->AddEventList(CPAP_PressurePulse,EVL_Event))) return false; } Code[6]->AddEvent(t,buffer[pos++]); //qDebug() << hex << data[0]; @@ -588,9 +578,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; tt=t-(qint64(data[0])*1000L); if (!Code[7]) { - Code[7]=new EventList(CPAP_RERA,EVL_Event); - session->eventlist[CPAP_RERA].push_back(Code[7]); - session->machine()->registerChannel(CPAP_RERA); + if (!(Code[7]=session->AddEventList(CPAP_RERA,EVL_Event))) return false; } Code[7]->AddEvent(tt,data[0]); break; @@ -599,9 +587,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; tt=t-(qint64(data[0])*1000L); if (!Code[8]) { - Code[8]=new EventList(CPAP_Obstructive,EVL_Event); - session->eventlist[CPAP_Obstructive].push_back(Code[8]); - session->machine()->registerChannel(CPAP_Obstructive); + if (!(Code[8]=session->AddEventList(CPAP_Obstructive,EVL_Event))) return false; } Code[8]->AddEvent(tt,data[0]); break; @@ -609,9 +595,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; tt=t-(qint64(data[0])*1000L); if (!Code[9]) { - Code[9]=new EventList(CPAP_ClearAirway,EVL_Event); - session->eventlist[CPAP_ClearAirway].push_back(Code[9]); - session->machine()->registerChannel(CPAP_ClearAirway); + if (!(Code[9]=session->AddEventList(CPAP_ClearAirway,EVL_Event))) return false; } Code[9]->AddEvent(tt,data[0]); break; @@ -619,9 +603,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; tt=t-(qint64(data[0])*1000L); if (!Code[10]) { - Code[10]=new EventList(CPAP_Hypopnea,EVL_Event); - session->eventlist[CPAP_Hypopnea].push_back(Code[10]); - session->machine()->registerChannel(CPAP_Hypopnea); + if (!(Code[10]=session->AddEventList(CPAP_Hypopnea,EVL_Event))) return false; } Code[10]->AddEvent(tt,data[0]); break; @@ -629,9 +611,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; tt=t-(qint64(data[0])*1000L); if (!Code[11]) { - Code[11]=new EventList(CPAP_FlowLimit,EVL_Event); - session->eventlist[CPAP_FlowLimit].push_back(Code[11]); - session->machine()->registerChannel(CPAP_FlowLimit); + if (!(Code[11]=session->AddEventList(CPAP_FlowLimit,EVL_Event))) return false; } Code[11]->AddEvent(tt,data[0]); break; @@ -640,18 +620,14 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; data[1]=buffer[pos++]; if (!Code[12]) { - Code[12]=new EventList(PRS1_Unknown0B,EVL_Event); - session->eventlist[PRS1_Unknown0B].push_back(Code[12]); - session->machine()->registerChannel(PRS1_Unknown0B); + if (!(Code[12]=session->AddEventList(PRS1_0B,EVL_Event))) return false; } // FIXME Code[12]->AddEvent(t,data[0]); break; case 0x0d: // Vibratory Snore if (!Code[13]) { - Code[13]=new EventList(CPAP_VSnore,EVL_Event); - session->eventlist[CPAP_VSnore].push_back(Code[13]); - session->machine()->registerChannel(CPAP_VSnore); + if (!(Code[13]=session->AddEventList(CPAP_VSnore,EVL_Event))) return false; } Code[13]->AddEvent(t,0); break; @@ -659,20 +635,14 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[0]=buffer[pos++]; data[1]=buffer[pos++]; if (!Code[14]) { - Code[14]=new EventList(CPAP_Leak,EVL_Event); - session->eventlist[CPAP_Leak].push_back(Code[14]); - Code[15]=new EventList(CPAP_Snore,EVL_Event); - session->eventlist[CPAP_Snore].push_back(Code[15]); - session->machine()->registerChannel(CPAP_Leak); - session->machine()->registerChannel(CPAP_Snore); + if (!(Code[14]=session->AddEventList(CPAP_Leak,EVL_Event))) return false; + if (!(Code[15]=session->AddEventList(CPAP_Snore,EVL_Event))) return false; } Code[14]->AddEvent(t,data[0]); Code[15]->AddEvent(t,data[1]); if (data[1]>0) { if (!Code[16]) { - Code[16]=new EventList(PRS1_VSnore2,EVL_Event); - session->eventlist[PRS1_VSnore2].push_back(Code[16]); - session->machine()->registerChannel(PRS1_VSnore2); + if (!(Code[16]=session->AddEventList(CPAP_VSnore2,EVL_Event))) return false; } Code[16]->AddEvent(t,data[1]); } @@ -685,9 +655,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[2]=buffer[pos++]; if (!Code[17]) { - Code[17]=new EventList(PRS1_Unknown0E,EVL_Event); - session->eventlist[PRS1_Unknown0E].push_back(Code[17]); - session->machine()->registerChannel(PRS1_Unknown0E); + if (!(Code[17]=session->AddEventList(PRS1_0E,EVL_Event))) return false; } Code[17]->AddEvent(t,data[0]); //qDebug() << hex << data[0] << data[1] << data[2]; @@ -700,9 +668,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[1]=buffer[pos++]; data[2]=buffer[pos++]; if (!Code[20]) { - Code[20]=new EventList(PRS1_Unknown10,EVL_Event); - session->eventlist[PRS1_Unknown10].push_back(Code[20]); - session->machine()->registerChannel(PRS1_Unknown10); + if (!(Code[20]=session->AddEventList(PRS1_10,EVL_Event))) return false; } Code[20]->AddEvent(t,data[0]); break; @@ -712,9 +678,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[1]=buffer[pos++]; tt=t-qint64(data[1])*1000L; if (!Code[23]) { - Code[23]=new EventList(CPAP_CSR,EVL_Event); - session->eventlist[CPAP_CSR].push_back(Code[23]); - session->machine()->registerChannel(CPAP_CSR); + if (!(Code[23]=session->AddEventList(CPAP_CSR,EVL_Event))) return false; } Code[23]->AddEvent(tt,data[0]); break; @@ -724,9 +688,7 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 data[2]=buffer[pos+1]<<8 | buffer[pos]; pos+=2; if (!Code[24]) { - Code[24]=new EventList(PRS1_Unknown12,EVL_Event); - session->eventlist[PRS1_Unknown12].push_back(Code[24]); - session->machine()->registerChannel(PRS1_Unknown12); + if (!(Code[24]=session->AddEventList(PRS1_12,EVL_Event))) return false; } Code[24]->AddEvent(t,data[0]); break; @@ -743,14 +705,14 @@ bool PRS1Loader::Parse002(Session *session,unsigned char *buffer,int size,qint64 bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qint64 timestamp) { - ChannelID Codes[]={ - PRS1_Unknown00, PRS1_Unknown01, CPAP_Pressure, CPAP_EPAP, CPAP_PressurePulse, CPAP_Obstructive, - CPAP_ClearAirway, CPAP_Hypopnea, PRS1_Unknown08, CPAP_FlowLimit, PRS1_Unknown0A, CPAP_CSR, - PRS1_Unknown0C, CPAP_VSnore, PRS1_Unknown0E, PRS1_Unknown0F, PRS1_Unknown10, - CPAP_Leak, PRS1_Unknown12 + QString Codes[]={ + PRS1_00, PRS1_01, CPAP_Pressure, CPAP_EPAP, CPAP_PressurePulse, CPAP_Obstructive, + CPAP_ClearAirway, CPAP_Hypopnea, PRS1_08, CPAP_FlowLimit, PRS1_0A, CPAP_CSR, + PRS1_0C, CPAP_VSnore, PRS1_0E, PRS1_0F, PRS1_10, + CPAP_Leak, PRS1_12 }; - int ncodes=sizeof(Codes)/sizeof(ChannelID); + int ncodes=sizeof(Codes)/sizeof(QString); EventList * Code[0x20]={NULL}; //for (int i=0;i<0x20;i++) Code[i]=NULL; @@ -780,7 +742,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin pos+=2; t+=qint64(delta)*1000L; } - ChannelID cpapcode=Codes[(int)code]; + QString cpapcode=Codes[(int)code]; //EventDataType PS; tt=t; cnt++; @@ -802,9 +764,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin break; case 0x01: // Unknown if (!Code[1]) { - Code[1]=new EventList(cpapcode,EVL_Event,0.1); - session->eventlist[cpapcode].push_back(Code[1]); - session->machine()->registerChannel(cpapcode); + if (!(Code[1]=session->AddEventList(cpapcode,EVL_Event,0.1))) return false; } Code[1]->AddEvent(t,0); break; @@ -812,18 +772,14 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin case 0x02: // Pressure data[0]=buffer[pos++]; if (!Code[2]) { - Code[2]=new EventList(cpapcode,EVL_Event,0.1); - session->eventlist[cpapcode].push_back(Code[2]); - session->machine()->registerChannel(cpapcode); + if (!(Code[2]=session->AddEventList(cpapcode,EVL_Event,0.1))) return false; } Code[2]->AddEvent(t,data[0]); break; case 0x04: // Pressure Pulse data[0]=buffer[pos++]; if (!Code[3]) { - Code[3]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[3]); - session->machine()->registerChannel(cpapcode); + if (!(Code[3]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[3]->AddEvent(t,data[0]); break; @@ -832,9 +788,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[4]) { - Code[4]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[4]); - session->machine()->registerChannel(cpapcode); + if (!(Code[4]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[4]->AddEvent(tt,data[0]); break; @@ -843,9 +797,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[5]) { - Code[5]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[5]); - session->machine()->registerChannel(cpapcode); + if (!(Code[5]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[5]->AddEvent(tt,data[0]); break; @@ -853,9 +805,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[6]) { - Code[6]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[6]); - session->machine()->registerChannel(cpapcode); + if (!(Code[6]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[6]->AddEvent(tt,data[0]); break; @@ -863,9 +813,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[10]) { - Code[10]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[10]); - session->machine()->registerChannel(cpapcode); + if (!(Code[10]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[10]->AddEvent(tt,data[0]); break; @@ -873,9 +821,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[11]) { - Code[11]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[11]); - session->machine()->registerChannel(cpapcode); + if (!(Code[11]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[11]->AddEvent(tt,data[0]); @@ -885,9 +831,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[7]) { - Code[7]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[7]); - session->machine()->registerChannel(cpapcode); + if (!(Code[7]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[7]->AddEvent(tt,data[0]); break; @@ -896,9 +840,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin data[0]=buffer[pos++]; tt-=qint64(data[0])*1000L; // Subtract Time Offset if (!Code[8]) { - Code[8]=new EventList(cpapcode,EVL_Event); - session->eventlist[cpapcode].push_back(Code[8]); - session->machine()->registerChannel(cpapcode); + if (!(Code[8]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[8]->AddEvent(tt,data[0]); break; @@ -913,59 +855,25 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin //tt-=delta; tt-=qint64(data[1])*1000L; if (!Code[9]) { - Code[9]=new EventList(cpapcode,EVL_Event,2.0); - session->eventlist[cpapcode].push_back(Code[9]); - session->machine()->registerChannel(cpapcode); + if (!(Code[9]=session->AddEventList(cpapcode,EVL_Event))) return false; } Code[9]->AddEvent(tt,data[0]); //session->AddEvent(new Event(tt,cpapcode, data[0], data, 2)); break; case 0x0d: // All the other ASV graph stuff. if (!Code[12]) { - Code[12]=new EventList(CPAP_IPAP,EVL_Event,0.1); - session->eventlist[CPAP_IPAP].push_back(Code[12]); - session->machine()->registerChannel(CPAP_IPAP); - - Code[13]=new EventList(CPAP_IPAP_Low,EVL_Event,0.1); - session->eventlist[CPAP_IPAP_Low].push_back(Code[13]); - session->machine()->registerChannel(CPAP_IPAP_Low); - - Code[14]=new EventList(CPAP_IPAP_High,EVL_Event,0.1); - session->eventlist[CPAP_IPAP_High].push_back(Code[14]); - session->machine()->registerChannel(CPAP_IPAP_High); - - Code[15]=new EventList(CPAP_Leak,EVL_Event); - session->eventlist[CPAP_Leak].push_back(Code[15]); - session->machine()->registerChannel(CPAP_Leak); - - Code[16]=new EventList(CPAP_RespiratoryRate,EVL_Event); - session->eventlist[CPAP_RespiratoryRate].push_back(Code[16]); - session->machine()->registerChannel(CPAP_RespiratoryRate); - - Code[17]=new EventList(CPAP_PatientTriggeredBreaths,EVL_Event); - session->eventlist[CPAP_PatientTriggeredBreaths].push_back(Code[17]); - session->machine()->registerChannel(CPAP_PatientTriggeredBreaths); - - Code[18]=new EventList(CPAP_MinuteVentilation,EVL_Event); - session->eventlist[CPAP_MinuteVentilation].push_back(Code[18]); - session->machine()->registerChannel(CPAP_MinuteVentilation); - - Code[19]=new EventList(CPAP_TidalVolume,EVL_Event,10.0); - session->eventlist[CPAP_TidalVolume].push_back(Code[19]); - session->machine()->registerChannel(CPAP_TidalVolume); - - Code[20]=new EventList(CPAP_Snore,EVL_Event); - session->eventlist[CPAP_Snore].push_back(Code[20]); - session->machine()->registerChannel(CPAP_Snore); - - Code[22]=new EventList(CPAP_EPAP,EVL_Event,0.1); - session->eventlist[CPAP_EPAP].push_back(Code[22]); - session->machine()->registerChannel(CPAP_EPAP); - - Code[23]=new EventList(CPAP_PressureSupport,EVL_Event,0.1); - session->eventlist[CPAP_PressureSupport].push_back(Code[23]); - session->machine()->registerChannel(CPAP_PressureSupport); + if (!(Code[12]=session->AddEventList("IPAP",EVL_Event))) return false; + if (!(Code[13]=session->AddEventList("IPAPLo",EVL_Event))) return false; + if (!(Code[14]=session->AddEventList("IPAPHi",EVL_Event))) return false; + if (!(Code[15]=session->AddEventList("Leak",EVL_Event))) return false; + if (!(Code[16]=session->AddEventList("RespRate",EVL_Event))) return false; + if (!(Code[17]=session->AddEventList("PTB",EVL_Event))) return false; + if (!(Code[18]=session->AddEventList("MinuteVent",EVL_Event))) return false; + if (!(Code[19]=session->AddEventList("TidalVolume",EVL_Event))) return false; + if (!(Code[20]=session->AddEventList("Snore",EVL_Event))) return false; + if (!(Code[22]=session->AddEventList("EPAP",EVL_Event))) return false; + if (!(Code[23]=session->AddEventList("PS",EVL_Event))) return false; } Code[12]->AddEvent(t,data[0]=buffer[pos++]); // IAP Code[13]->AddEvent(t,buffer[pos++]); // IAP Low @@ -978,9 +886,7 @@ bool PRS1Loader::Parse002ASV(Session *session,unsigned char *buffer,int size,qin Code[20]->AddEvent(t,data[2]=buffer[pos++]); // Snore if (data[2]>0) { if (!Code[21]) { - Code[21]=new EventList(CPAP_VSnore,EVL_Event); - session->eventlist[CPAP_VSnore].push_back(Code[21]); - session->machine()->registerChannel(CPAP_VSnore); + if (!(Code[21]=session->AddEventList("VSnore",EVL_Event))) return false; } Code[21]->AddEvent(t,0); //data[2]); // VSnore } @@ -1181,7 +1087,9 @@ bool PRS1Loader::OpenWaveforms(Session *session,QString filename) //EventList *FlowData=EventList(CPAP_FlowRate, EVL_Waveform,1,0,-128,128); //EventList *MaskData=EventList(CPAP_MaskPressure, EVL_Waveform,1,0,-128,128); - ChannelID wc[2]={CPAP_FlowRate,CPAP_MaskPressure}; + QString FlowRate="FlowRate"; + QString MaskPressure="MaskPressure"; + QString wc[2]={FlowRate,MaskPressure}; do { timestamp=m_buffer[pos+0xb] | m_buffer[pos+0xc] << 8 | m_buffer[pos+0xd] << 16 | m_buffer[pos+0x0e] << 24; register unsigned char sum8=0; @@ -1226,24 +1134,24 @@ bool PRS1Loader::OpenWaveforms(Session *session,QString filename) double rate=(double(wdur[i])*1000.0)/double(wlength[i]); double gain; if (i==1) gain=0.1; else gain=1; - EventList *a=new EventList(wc[i],EVL_Waveform,gain,0,0,0,rate); - session->machine()->registerChannel(wc[i]); + EventList *a=session->AddEventList(wc[i],EVL_Waveform,gain,0,0,0,rate); + //EventList *a=new EventList(wc[i],EVL_Waveform,gain,0,0,0,rate); + //session->machine()->registerChannel(wc[i]); if (whl[i].sample_format) a->AddWaveform(qint64(start)*1000L,(unsigned char *)waveform[i],wlength[i],qint64(wdur[i])*1000L); else { a->AddWaveform(qint64(start)*1000L,(char *)waveform[i],wlength[i],qint64(wdur[i])*1000L); } - if (wc[i]==CPAP_FlowRate) { + if (wc[i]==FlowRate) { a->setMax(120); a->setMin(-120); - } else if (wc[i]==CPAP_MaskPressure) { + } else if (wc[i]==MaskPressure) { /* int v=ceil(a->max()/5); a->setMax(v*5); v=floor(a->min()/5); a->setMin(v*5); */ } - session->eventlist[wc[i]].push_back(a); session->updateLast(start+(qint64(wdur[i])*1000L)); wlength[i]=0; wdur[i]=0; @@ -1281,20 +1189,18 @@ bool PRS1Loader::OpenWaveforms(Session *session,QString filename) double rate=(double(wdur[i])*1000.0)/double(wlength[i]); double gain; if (i==1) gain=0.1; else gain=1; - EventList *a=new EventList(wc[i],EVL_Waveform,gain,0,0,0,rate); - session->machine()->registerChannel(wc[i]); + EventList *a=session->AddEventList(wc[i],EVL_Waveform,gain,0,0,0,rate); if (whl[i].sample_format) a->AddWaveform(qint64(start)*1000L,(unsigned char *)waveform[i],wlength[i],qint64(wdur[i])*1000L); else { a->AddWaveform(qint64(start)*1000L,(char *)waveform[i],wlength[i],qint64(wdur[i])*1000L); } - if (wc[i]==CPAP_FlowRate) { + if (wc[i]==FlowRate) { a->setMax(120); a->setMin(-120); - } else if (wc[i]==CPAP_MaskPressure) { + } else if (wc[i]==MaskPressure) { } - session->eventlist[wc[i]].push_back(a); session->updateLast(start+qint64(wdur[i])*1000L); } return true; diff --git a/SleepLib/loader_plugins/resmed_loader.cpp b/SleepLib/loader_plugins/resmed_loader.cpp index be96a91a..bc2259b6 100644 --- a/SleepLib/loader_plugins/resmed_loader.cpp +++ b/SleepLib/loader_plugins/resmed_loader.cpp @@ -121,6 +121,7 @@ bool EDFParser::Parse() edfsignals.push_back(signal); signal->data=NULL; edfsignals[i]->label=Read(16); + lookup[edfsignals[i]->label]=signal; } for (int i=0;itransducer_type=Read(80); @@ -257,6 +258,29 @@ int ResmedLoader::Open(QString & path,Profile *profile) } } } + QString strfile=path+"/STR.edf"; + EDFParser stredf(strfile); + + if (!stredf.Parse()) { + qDebug() << "Faulty file" << strfile; + return 0; + } + + qint64 duration=stredf.GetNumDataRecords()*stredf.GetDuration(); + int days=duration/86400000L; + + QDateTime dt1=QDateTime::fromTime_t(stredf.startdate/1000L); + QDateTime dt2=QDateTime::fromTime_t(stredf.enddate/1000L); + QDate dd1=dt1.date(); + QDate dd2=dt2.date(); + for (int s=0;snr*stredf.GetNumDataRecords(); + + qDebug() << "STREDF:" << stredf.edfsignals[s]->label << recs; + } + + QDir dir(newpath); if ((!dir.exists() || !dir.isReadable())) @@ -324,6 +348,9 @@ int ResmedLoader::Open(QString & path,Profile *profile) if (edf.serialnumber!=i.value()) { qDebug() << "edf Serial number doesn't match Identification.tgt"; } + if (edf.serialnumber!=stredf.serialnumber) { + qDebug() << "edf Serial number doesn't match STR.edf!"; + } } else if (i.key()=="PNA") { m->properties["Model"]=i.value(); } else if (i.key()=="PCD") { @@ -363,14 +390,49 @@ int ResmedLoader::Open(QString & path,Profile *profile) continue; } else { sess->SetChanged(true); + qint64 dif=sess->first()-stredf.startdate; + int dn=dif/86400000L; + if (dnsettings["EPR"]=(*stredf.lookup["EPR"]).data[dn]; + sess->settings["EPRSet"]=(*stredf.lookup["EPR Level"]).data[dn]; + + EDFSignal *sig; + if (mode==0) { + sess->settings["PAPMode"]=MODE_CPAP; + //m->registerChannel(CPAP_EPAP,false); + //m->registerChannel("IPAP",false); + sig=stredf.lookup["Set Pressure"]; + EventDataType pressure=sig->data[dn]*sig->gain; + sess->settings[CPAP_Pressure]=pressure; + sess->setWavg(CPAP_Pressure,pressure); + sess->setAvg(CPAP_Pressure,pressure); + sess->set90p(CPAP_Pressure,pressure); + sess->setMax(CPAP_Pressure,pressure); + sess->setMin(CPAP_Pressure,pressure); + } else { + if (mode>5) { + sess->settings[CPAP_Mode]=MODE_BIPAP; + } else { + sess->settings[CPAP_Mode]=MODE_APAP; + } + sig=stredf.lookup["Min Pressure"]; + if (sig) + sess->setMin(CPAP_Pressure,sig->data[dn]*sig->gain); + sig=stredf.lookup["Max Pressure"]; + if (sig) + sess->setMax(CPAP_Pressure,sig->data[dn]*sig->gain); + } + + } m->AddSession(sess,profile); // Adding earlier than I really like here.. } - if (!done && sess) { - sess->settings[CPAP_Mode]=MODE_APAP; - } - } - m->Save(); + + if (m) { + m->Save(); + } if (qprogress) qprogress->setValue(100); qDebug() << "Total Events " << event_cnt; return 1; @@ -457,36 +519,24 @@ bool ResmedLoader::LoadEVE(Session *sess,EDFParser &edf) if (!t.isEmpty()) { //code=MC_UNKNOWN; if (t=="obstructive apnea") { - code=CPAP_Obstructive; if (!EL[0]) { - EL[0]=new EventList(code,EVL_Event); - sess->eventlist[code].push_back(EL[0]); - sess->machine()->registerChannel(code); - + if (!(EL[0]=sess->AddEventList(CPAP_Obstructive,EVL_Event))) return false; } EL[0]->AddEvent(tt,duration); } else if (t=="hypopnea") { - code=CPAP_Hypopnea; if (!EL[1]) { - EL[1]=new EventList(code,EVL_Event); - sess->eventlist[code].push_back(EL[1]); - sess->machine()->registerChannel(code); + if (!(EL[1]=sess->AddEventList(CPAP_Hypopnea,EVL_Event))) return false; } EL[1]->AddEvent(tt,duration+10); // Only Hyponea's Need the extra duration??? } else if (t=="apnea") { - code=CPAP_Apnea; if (!EL[2]) { - EL[2]=new EventList(code,EVL_Event); - sess->eventlist[code].push_back(EL[2]); - sess->machine()->registerChannel(code); + if (!(EL[2]=sess->AddEventList(CPAP_Apnea,EVL_Event))) return false; } EL[2]->AddEvent(tt,duration); } else if (t=="central apnea") { code=CPAP_ClearAirway; if (!EL[3]) { - EL[3]=new EventList(code,EVL_Event); - sess->eventlist[code].push_back(EL[3]); - sess->machine()->registerChannel(code); + if (!(EL[3]=sess->AddEventList(CPAP_ClearAirway,EVL_Event))) return false; } EL[3]->AddEvent(tt,duration); } else { @@ -529,9 +579,8 @@ bool ResmedLoader::LoadBRP(Session *sess,EDFParser &edf) } else if (edf.edfsignals[s]->label.startsWith("Mask Pres")) { code=CPAP_MaskPressure; sess->machine()->registerChannel(code); - } else if (es.label.startsWith("Resp Event")) { - code=CPAP_RespiratoryEvent; + code=CPAP_RespEvent; sess->machine()->registerChannel(code); } else { qDebug() << "Unobserved ResMed BRP Signal " << edf.edfsignals[s]->label; @@ -539,16 +588,12 @@ bool ResmedLoader::LoadBRP(Session *sess,EDFParser &edf) } double rate=double(duration)/double(recs); //es.gain=1; - EventList *a=new EventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); + EventList *a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a->setDimension(es.physical_dimension); a->AddWaveform(edf.startdate,es.data,recs,duration); - - if (code==CPAP_MaskPressure) { - } else if (code==CPAP_FlowRate) { - } sess->setMin(code,a->min()); sess->setMax(code,a->max()); - sess->eventlist[code].push_back(a); + //sess->eventlist[code].push_back(a); //delete edf.edfsignals[s]->data; //edf.edfsignals[s]->data=NULL; // so it doesn't get deleted when edf gets trashed. } @@ -562,15 +607,14 @@ EventList * ResmedLoader::ToTimeDelta(Session *sess,EDFParser &edf, EDFSignal & //sess->UpdateFirst(tt); EventDataType c,last; //if (gain==0) gain=1; - EventList *el=new EventList(code,EVL_Event,es.gain,es.offset,min,max); - sess->eventlist[code].push_back(el); + + EventList *el=sess->AddEventList(code,EVL_Event,es.gain,es.offset,min,max); int startpos=0; - /*if ((code==CPAP_Pressure) || (code==CPAP_IPAP) || (code==CPAP_EPAP) - || (code==CPAP_TherapyPressure)) { - startpos=0; + if ((code==CPAP_Pressure) || (code==CPAP_IPAP) || (code==CPAP_EPAP)) { + startpos=20; // Shave the first 20 seconds of pressure data tt+=rate*startpos; - }*/ + } for (int i=startpos;inr*edf.GetNumDataRecords(); ChannelID code; if (edf.edfsignals[s]->label=="Pulse") { - code=CPAP_Pulse; - sess->machine()->registerChannel(code); + code=OXI_Pulse; + //sess->machine()->registerChannel(code); } else if (edf.edfsignals[s]->label=="SpO2") { - code=CPAP_SPO2; - sess->machine()->registerChannel(code); + code=OXI_SPO2; + //sess->machine()->registerChannel(code); } else { qDebug() << "Unobserved ResMed SAD Signal " << edf.edfsignals[s]->label; continue; @@ -637,8 +681,8 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) // 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 }; - sess->updateFirst(edf.startdate); qint64 duration=edf.GetNumDataRecords()*edf.GetDuration(); + sess->updateFirst(edf.startdate); sess->updateLast(edf.startdate+duration); QString t; int emptycnt=0; @@ -649,6 +693,7 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) for (int s=0;ssetMax(1); //a->setMin(0); } else if (es.label=="Therapy Pres") { - code=CPAP_IPAP; //TherapyPressure; - sess->settings[CPAP_Mode]=MODE_APAP; + code=CPAP_Pressure; //TherapyPressure; + //sess->settings[CPAP_Mode]=MODE_APAP; //EventList *a=new EventList(code,EVL_Waveform,es.gain,es.offset,es.physical_minimum,es.physical_maximum,rate); //sess->eventlist[code].push_back(a); //a->AddWaveform(edf.startdate,es.data,recs,duration); @@ -675,15 +720,14 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) //a->AddWaveform(edf.startdate,es.data,recs,duration); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label=="MV") { - code=CPAP_MinuteVentilation; + code=CPAP_MinuteVent; //EventList *a=new EventList(code,EVL_Waveform,es.gain,es.offset,es.physical_minimum,es.physical_maximum,rate); //sess->eventlist[code].push_back(a); //a->AddWaveform(edf.startdate,es.data,recs,duration); a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label=="RR") { - code=CPAP_RespiratoryRate; - a=new EventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); - sess->eventlist[code].push_back(a); + code=CPAP_RespRate; + a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a->AddWaveform(edf.startdate,es.data,recs,duration); //ToTimeDelta(sess,edf,es, code,recs,duration); } else if (es.label=="Vt") { @@ -704,13 +748,13 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) //a->setMax(1); //a->setMin(0); } else if (es.label=="FFL Index") { - code=CPAP_FlowLimitGraph; + code=CPAP_FLG; //es.gain=1;//10.0; a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); //a->setMax(1); //a->setMin(0); } else if (es.label.startsWith("Mask Pres")) { - code=CPAP_Pressure; + code=CPAP_MaskPressure; //es.gain=1; a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label.startsWith("Exp Press")) { @@ -718,28 +762,25 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label.startsWith("I:E")) { code=CPAP_IE;//I:E; - a=new EventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); - sess->eventlist[code].push_back(a); + a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a->AddWaveform(edf.startdate,es.data,recs,duration); //a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label.startsWith("Ti")) { code=CPAP_Ti;//Ti; - a=new EventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); - sess->eventlist[code].push_back(a); + a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a->AddWaveform(edf.startdate,es.data,recs,duration); //a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label.startsWith("Te")) { code=CPAP_Te;//Te; - a=new EventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); - sess->eventlist[code].push_back(a); + a=sess->AddEventList(code,EVL_Waveform,es.gain,es.offset,0,0,rate); a->AddWaveform(edf.startdate,es.data,recs,duration); //a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0); } else if (es.label=="") { if (emptycnt==0) { - code=RMS9_Empty1; + code=RMS9_E01; a=ToTimeDelta(sess,edf,es, code,recs,duration); } else if (emptycnt==1) { - code=RMS9_Empty2; + code=RMS9_E02; a=ToTimeDelta(sess,edf,es, code,recs,duration); } else { qDebug() << "Unobserved Empty Signal " << es.label; @@ -750,7 +791,7 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf) a=NULL; } if (a) { - sess->machine()->registerChannel(code); + //sess->machine()->registerChannel(code); sess->setMin(code,a->min()); sess->setMax(code,a->max()); a->setDimension(es.physical_dimension); diff --git a/SleepLib/loader_plugins/resmed_loader.h b/SleepLib/loader_plugins/resmed_loader.h index 98217014..e9dd130b 100644 --- a/SleepLib/loader_plugins/resmed_loader.h +++ b/SleepLib/loader_plugins/resmed_loader.h @@ -69,11 +69,13 @@ public: qint16 Read16(); QVector edfsignals; + QHash lookup; long GetNumSignals() { return num_signals; } long GetNumDataRecords() { return num_data_records; } qint64 GetDuration() { return dur_data_record; } QString GetPatient() { return patientident; } + bool Parse(); char *buffer; EDFHeader header; diff --git a/SleepLib/machine.cpp b/SleepLib/machine.cpp index bdebf9ae..2eb58a31 100644 --- a/SleepLib/machine.cpp +++ b/SleepLib/machine.cpp @@ -16,291 +16,10 @@ #include "machine.h" #include "profiles.h" #include - -ChannelGroup CPAP_CODES; -ChannelGroup PRS1_CODES; -ChannelGroup RMS9_CODES; -ChannelGroup OXI_CODES; -ChannelGroup ZEO_CODES; -ChannelGroup JOURNAL_CODES; - - -ChannelID CPAP_Obstructive,CPAP_Hypopnea,CPAP_Apnea, CPAP_ClearAirway, CPAP_RERA, CPAP_FlowLimit, -CPAP_CSR, CPAP_VSnore, CPAP_PressurePulse, CPAP_Mode, CPAP_FlowRate, CPAP_MaskPressure, CPAP_Pressure, -CPAP_EPAP, CPAP_IPAP, CPAP_IPAP_Low, CPAP_IPAP_High, CPAP_PressureSupport, CPAP_Snore, CPAP_Leak, -CPAP_RespiratoryRate, CPAP_TidalVolume, CPAP_MinuteVentilation, CPAP_PatientTriggeredBreaths, -CPAP_FlowLimitGraph, CPAP_TherapyPressure, CPAP_ExpiratoryPressure, CPAP_AHI,CPAP_RespiratoryEvent, -CPAP_IE,CPAP_Ti,CPAP_Te, -CPAP_BrokenSummary,CPAP_BrokenWaveform, CPAP_Pulse, CPAP_SPO2, CPAP_Plethy; - -ChannelID RMS9_PressureReliefType, RMS9_PressureReliefSetting, RMS9_Empty1, RMS9_Empty2; -ChannelID PRS1_PressureMin,PRS1_PressureMax, PRS1_PressureMinAchieved, PRS1_PressureMaxAchieved, -PRS1_PressureAvg, PRS1_Pressure90, PRS1_RampTime, PRS1_RampPressure, PRS1_HumidifierStatus, -PRS1_HumidifierSetting, PRS1_PressureReliefType, PRS1_PressureReliefSetting, PRS1_SystemOneResistanceStatus, -PRS1_SystemOneResistanceSetting, PRS1_SystemLockStatus, PRS1_HoseDiameter, PRS1_AutoOff, PRS1_AutoOn, -PRS1_MaskAlert, PRS1_ShowAHI, PRS1_Unknown00, PRS1_Unknown01, PRS1_Unknown08, PRS1_Unknown09, -PRS1_Unknown0A, PRS1_Unknown0B, PRS1_Unknown0C, PRS1_Unknown0E, PRS1_Unknown0F, PRS1_Unknown10, -PRS1_Unknown12, PRS1_VSnore2; - -ChannelID OXI_Pulse, OXI_SPO2, OXI_Plethysomogram, OXI_PulseChange, OXI_SPO2Drop, OXI_Error, OXI_SignalError; -ChannelID ZEO_SleepStage, ZEO_Waveform; -ChannelID JOURNAL_Notes, JOURNAL_Weight; - -ChannelID ChannelGroup::Get(ChannelType ctype,QString description,QString label,QString lookup,QColor color) -{ - ChannelID id=m_first+m_pos; - if (++m_pos>=m_size) { - qCritical("Not enough slots allocated for channel group"); - abort(); - } - channel[id]=Channel(id,m_type,ctype,description,label,color); - m_channelsbytype[ctype][id]=channel_lookup[lookup]=m_channel[id]=&channel[id]; - - return id; -} -ChannelGroup::ChannelGroup() -{ - m_pos=0; m_first=0xf000, m_size=0x1000; -} -ChannelGroup::ChannelGroup(MachineType type, ChannelID first, ChannelID reserved) - :m_type(type),m_first(first),m_size(reserved) -{ - m_pos=0; -} - +#include "SleepLib/schema.h" extern QProgressBar * qprogress; -// Master Lists.. -QHash channel; -QHash channel_lookup; -QHash channel_group; - - -void InitMapsWithoutAwesomeInitializerLists() -{ - CPAP_CODES=ChannelGroup(MT_CPAP,0x1000,0x400); - PRS1_CODES=ChannelGroup(MT_CPAP,0x1400,0x200); - RMS9_CODES=ChannelGroup(MT_CPAP,0x1600,0x200); - OXI_CODES=ChannelGroup(MT_OXIMETER,0x2000,0x800); - ZEO_CODES=ChannelGroup(MT_SLEEPSTAGE,0x2800,0x800); - JOURNAL_CODES=ChannelGroup(MT_JOURNAL,0x3000,0x800); - - // ******************** IMPORTANT ******************** - // Add to the end of each group or be eaten by a Grue! - // ******************** IMPORTANT ******************** - - // Flagable Events - CPAP_Obstructive=CPAP_CODES.Get(CT_Event,QObject::tr("Obstructive Apnea"),QObject::tr("OA"),"OA"), - CPAP_Hypopnea=CPAP_CODES.Get(CT_Event,QObject::tr("Hypopnea"),QObject::tr("H"),"OA"), - CPAP_Apnea=CPAP_CODES.Get(CT_Event,QObject::tr("Unspecified Apnea"),QObject::tr("UA"),"UA"), - CPAP_ClearAirway=CPAP_CODES.Get(CT_Event,QObject::tr("Clear Airway Apnea"),QObject::tr("CA"),"CA"), - CPAP_RERA=CPAP_CODES.Get(CT_Event,QObject::tr("RERA"),QObject::tr("RE"),"RE"), - CPAP_FlowLimit=CPAP_CODES.Get(CT_Event,QObject::tr("Flow Limitation"),QObject::tr("FL"),"FL"), - CPAP_CSR=CPAP_CODES.Get(CT_Event,QObject::tr("Periodic Breathing"),QObject::tr("PB"),"PB"), - CPAP_VSnore=CPAP_CODES.Get(CT_Event,QObject::tr("Vibratory Snore"),QObject::tr("VS"),"VS"), - CPAP_PressurePulse=CPAP_CODES.Get(CT_Event,QObject::tr("Pressure Pulse"),QObject::tr("PP"),"PP"), - CPAP_Mode=CPAP_CODES.Get(CT_Lookup,QObject::tr("CPAP Mode"),QObject::tr("CPAPMode"),"CPAPMode"), - // Alternate names at the end of each section - - // Graphable Events & Waveforms - CPAP_FlowRate=CPAP_CODES.Get(CT_Graph,QObject::tr("Flow Rate Waveform"),QObject::tr("Flow Rate"),"FR"), - CPAP_MaskPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Mask Pressure"),QObject::tr("Mask Pressure"),"MP"), - CPAP_Pressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Pressure"),QObject::tr("Pressure"),"P"), - CPAP_EPAP=CPAP_CODES.Get(CT_Graph,QObject::tr("Expiratory Pressure"),QObject::tr("EPAP"),"EPAP"), - CPAP_IPAP=CPAP_CODES.Get(CT_Graph,QObject::tr("Inhalation Pressure"),QObject::tr("IPAP"),"IPAP"), - CPAP_IPAP_Low=CPAP_CODES.Get(CT_Graph,QObject::tr("IPAP Low"),QObject::tr("IPAP Low"),"IPAPL"), - CPAP_IPAP_High=CPAP_CODES.Get(CT_Graph,QObject::tr("IPAP Low"),QObject::tr("IPAP High"),"IPAPH"), - CPAP_PressureSupport=CPAP_CODES.Get(CT_Graph,QObject::tr("Pressure Support"),QObject::tr("Pressure Support"),"PS"), - CPAP_Snore=CPAP_CODES.Get(CT_Graph,QObject::tr("Snore"),QObject::tr("Snore"),"Snore"), - CPAP_Leak=CPAP_CODES.Get(CT_Graph,QObject::tr("Leak Rate"),QObject::tr("Leak"),"Leak"), - CPAP_RespiratoryRate=CPAP_CODES.Get(CT_Graph,QObject::tr("Respiratory Rate"),QObject::tr("Resp. Rate"),"RR"), - CPAP_TidalVolume=CPAP_CODES.Get(CT_Graph,QObject::tr("Tidal Volume"),QObject::tr("Tidal Volume"),"TV"), - CPAP_MinuteVentilation=CPAP_CODES.Get(CT_Graph,QObject::tr("Minute Ventilation"),QObject::tr("Minute Vent."),"MV"), - CPAP_PatientTriggeredBreaths=CPAP_CODES.Get(CT_Graph,QObject::tr("Patient Triggered Breaths"),QObject::tr("Patient Trig Breaths"),"PTB"), - CPAP_FlowLimitGraph=CPAP_CODES.Get(CT_Graph,QObject::tr("Flow Limitation Graph"),QObject::tr("Flow Limit."),"FLG"), - CPAP_TherapyPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Therapy Pressure"),QObject::tr("Therapy Pressure"),"TP"), - CPAP_ExpiratoryPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Expiratory Pressure"),QObject::tr("Expiratory Pressure"),"EXP"), - CPAP_RespiratoryEvent=CPAP_CODES.Get(CT_Graph,QObject::tr("Respiratory Event"),QObject::tr("Respiratory Event"),"RESPEv"), - CPAP_IE=CPAP_CODES.Get(CT_Graph,QObject::tr("I:E"),QObject::tr("I:E"),"IE"), - CPAP_Ti=CPAP_CODES.Get(CT_Graph,QObject::tr("Ti"),QObject::tr("Ti"),"Ti"), - CPAP_Te=CPAP_CODES.Get(CT_Graph,QObject::tr("Te"),QObject::tr("Te"),"Te"), - - - CPAP_AHI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Apnea-Hypopnea Index"),QObject::tr("AHI"),"AHI"), - /*CPAP_AI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Apnea Index"),QObject::tr("AI"),"AI"), - CPAP_HI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Hypopnea Index"),QObject::tr("HI"),"HI"), - CPAP_CAI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Central Apnea Index"),QObject::tr("CAI"),"CAI"), - CPAP_RAI=CPAP_CODES.Get(CT_Calculation,QObject::tr("RERA+AHI Index"),QObject::tr("RAI"),"RAI"), - CPAP_RI=CPAP_CODES.Get(CT_Calculation,QObject::tr("RERA Index"),QObject::tr("RI"),"RI"), - CPAP_FLI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Flow Limitation Index"),QObject::tr("FLI"),"FLI"), - CPAP_VSI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Vibratory Snore Index"),QObject::tr("VSI"),"VSI"), - CPAP_PBI=CPAP_CODES.Get(CT_Calculation,QObject::tr("% Night in Periodic Breathing"),QObject::tr("PBI"),"PBI"), */ - //CPAP_PressureReliefType=CPAP_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","PRType"), - //CPAP_PressureReliefSetting=CPAP_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Setting"),"","PRSet"), - CPAP_BrokenSummary=CPAP_CODES.Get(CT_Boolean,QObject::tr("Broken Summary"),QObject::tr(""),"BrokenSummary"), - CPAP_BrokenWaveform=CPAP_CODES.Get(CT_Boolean,QObject::tr("Broken Waveform"),QObject::tr(""),"BrokenWaveform"); - - - RMS9_PressureReliefType=RMS9_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","RMS9_PRType"), - RMS9_PressureReliefSetting=RMS9_CODES.Get(CT_Decimal,QObject::tr("Pressure Relief Setting"),"","RMS9_PRSet"), - RMS9_Empty1=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown Empty 1"),"","RMS9_UE1"), - RMS9_Empty2=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown Empty 2"),"","RMS9_UE2"), - - PRS1_PressureMin=PRS1_CODES.Get(CT_Decimal,QObject::tr("Minimum Pressure"),"","PRS1_MinPres"), - PRS1_PressureMax=PRS1_CODES.Get(CT_Decimal,QObject::tr("Maximum Pressure"),"","PRS1_MaxPres"), - PRS1_PressureMinAchieved=PRS1_CODES.Get(CT_Decimal,QObject::tr("Minimum Pressure Achieved"),"","PRS1_MinPresAch"), - PRS1_PressureMaxAchieved=PRS1_CODES.Get(CT_Decimal,QObject::tr("Maximum Pressure Achieved"),"","PRS1_MaxPresAch"), - PRS1_PressureAvg=PRS1_CODES.Get(CT_Decimal,QObject::tr("Average Pressure"),"","PRS1_AvgPres"), - PRS1_Pressure90=PRS1_CODES.Get(CT_Decimal,QObject::tr("90% Pressure"),"","PRS1_90Pres"), - PRS1_RampTime=PRS1_CODES.Get(CT_Timespan,QObject::tr("Ramp Time"),"","PRS1_RampTime"), - PRS1_RampPressure=PRS1_CODES.Get(CT_Decimal,QObject::tr("Ramp Pressure"),"","PRS1_RampPressure"), - PRS1_HumidifierStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("Humidifier Status"),"","PRS1_HumiStat"), - PRS1_HumidifierSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("Humidifier Setting"),"","PRS1_HumiSet"), - PRS1_PressureReliefType=PRS1_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","PRS1_PRType"), - PRS1_PressureReliefSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Setting"),"","PRS1_PRSet"), - PRS1_SystemOneResistanceStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("System-One Resistance Status"),"","PRS1_ResistStat"), - PRS1_SystemOneResistanceSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("System-One Resistance Setting"),"","PRS1_ResistSet"), - PRS1_SystemLockStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("System Lock Status"),"","PRS1_SysLockStat"), - PRS1_HoseDiameter=PRS1_CODES.Get(CT_Lookup,QObject::tr("Hose Diameter"),"","PRS1_HoseDiam"), - PRS1_AutoOff=PRS1_CODES.Get(CT_Boolean,QObject::tr("Auto Off"),"","PRS1_AutoOff"), - PRS1_AutoOn=PRS1_CODES.Get(CT_Boolean,QObject::tr("Auto On"),"","PRS1_AutoOn"), - PRS1_MaskAlert=PRS1_CODES.Get(CT_Boolean,QObject::tr("Mask Alert"),"","PRS1_MaskAlert"), - PRS1_ShowAHI=PRS1_CODES.Get(CT_Boolean,QObject::tr("Show AHI"),"","PRS1_ShowAHI"), - PRS1_Unknown00=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 00 Event"),QObject::tr("U00"),"PRS1_U00"), - PRS1_Unknown01=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 01 Event"),QObject::tr("U01"),"PRS1_U01"), - PRS1_Unknown08=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 08 Event"),QObject::tr("U08"),"PRS1_U08"), - PRS1_Unknown09=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 09 Event"),QObject::tr("U09"),"PRS1_U09"), - PRS1_Unknown0A=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0A Event"),QObject::tr("U0A"),"PRS1_U0A"), - PRS1_Unknown0B=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0B Event"),QObject::tr("U0B"),"PRS1_U0B"), - PRS1_Unknown0C=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0C Event"),QObject::tr("U0C"),"PRS1_U0C"), - PRS1_Unknown0E=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0E Event"),QObject::tr("U0E"),"PRS1_U0E"), - PRS1_Unknown0F=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0F Event"),QObject::tr("U0F"),"PRS1_U0F"), - PRS1_Unknown10=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 10 Event"),QObject::tr("U10"),"PRS1_U10"), - PRS1_Unknown12=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 12 Event"),QObject::tr("U12"),"PRS1_U12"), - PRS1_VSnore2=CPAP_CODES.Get(CT_Event,QObject::tr("Vibratory Snore (Type 2)"),QObject::tr("VS2"),"VS2"); - - // CPAP Integrated oximetery codes.. - CPAP_Pulse=CPAP_CODES.Get(CT_Graph,QObject::tr("Pulse Rate"),QObject::tr("Pulse"),"CPPR"); - CPAP_SPO2=CPAP_CODES.Get(CT_Graph,QObject::tr("SpO2"),QObject::tr("SpO2"),"CPSP"); - CPAP_Plethy=CPAP_CODES.Get(CT_Graph,QObject::tr("Plethysomagram"),QObject::tr("Plethysomagram"),"CPPL"); - - OXI_Pulse=OXI_CODES.Get(CT_Graph,QObject::tr("Pulse Rate"),QObject::tr("PR"),"PR"), - OXI_SPO2=OXI_CODES.Get(CT_Graph,QObject::tr("Oxygen Saturation"),QObject::tr("SPO2"),"SPO2"), - OXI_Plethysomogram=OXI_CODES.Get(CT_Graph,QObject::tr("Plethysomogram"),QObject::tr("PLE"),"PLE"), - - OXI_PulseChange=OXI_CODES.Get(CT_Event,QObject::tr("Pulse Change"),QObject::tr("PC"),"PC"), - OXI_SPO2Drop=OXI_CODES.Get(CT_Event,QObject::tr("Oxigen Saturation Drop"),QObject::tr("SD"),"SD"), - OXI_Error=OXI_CODES.Get(CT_Event,QObject::tr("Oximeter Error"),QObject::tr("ER1"),"ER1"), - OXI_SignalError=OXI_CODES.Get(CT_Event,QObject::tr("Oximeter Signal Error"),QObject::tr("ER2"),"ER2"); - - - ZEO_SleepStage=ZEO_CODES.Get(CT_Graph,QObject::tr("Sleep Stage"),QObject::tr("SS"),"SS"), - ZEO_Waveform=ZEO_CODES.Get(CT_Graph,QObject::tr("Brainwaves"),QObject::tr("BW"),"BW"); - - - - JOURNAL_Notes=JOURNAL_CODES.Get(CT_Text,"Journal/Notes","JN"), - JOURNAL_Weight=JOURNAL_CODES.Get(CT_Decimal,"Weight","W"); - - channel[CPAP_Mode].addOption("CPAP"); - channel[CPAP_Mode].addOption("Auto"); - channel[CPAP_Mode].addOption("BIPAP/VPAP"); - channel[CPAP_Mode].addOption("ASV"); - - channel[PRS1_HoseDiameter].addOption("22mm"); - channel[PRS1_HoseDiameter].addOption("15mm"); - channel[PRS1_HumidifierSetting].addOption("Off"); - channel[PRS1_HumidifierSetting].addOption("1"); - channel[PRS1_HumidifierSetting].addOption("2"); - channel[PRS1_HumidifierSetting].addOption("3"); - channel[PRS1_HumidifierSetting].addOption("4"); - channel[PRS1_HumidifierSetting].addOption("5"); - channel[PRS1_SystemOneResistanceSetting].addOption("x1"); - channel[PRS1_SystemOneResistanceSetting].addOption("x2"); - channel[PRS1_SystemOneResistanceSetting].addOption("x3"); - channel[PRS1_SystemOneResistanceSetting].addOption("x4"); - channel[PRS1_SystemOneResistanceSetting].addOption("x5"); - channel[PRS1_PressureReliefType].addOption("None"); - channel[PRS1_PressureReliefType].addOption("C-Flex"); - channel[PRS1_PressureReliefType].addOption("C-Flex+"); - channel[PRS1_PressureReliefType].addOption("A-Flex"); - channel[PRS1_PressureReliefType].addOption("Bi-Flex"); - channel[PRS1_PressureReliefType].addOption("Bi-Flex+"); - channel[PRS1_PressureReliefSetting].addOption("Off"); - channel[PRS1_PressureReliefSetting].addOption("1"); - channel[PRS1_PressureReliefSetting].addOption("2"); - channel[PRS1_PressureReliefSetting].addOption("3"); - channel[RMS9_PressureReliefType].addOption("None"); - channel[RMS9_PressureReliefType].addOption("EPR"); - channel[RMS9_PressureReliefSetting].addOption("0"); - channel[RMS9_PressureReliefSetting].addOption("0.5"); - channel[RMS9_PressureReliefSetting].addOption("1"); - channel[RMS9_PressureReliefSetting].addOption("1.5"); - channel[RMS9_PressureReliefSetting].addOption("2"); - channel[RMS9_PressureReliefSetting].addOption("2.5"); - channel[RMS9_PressureReliefSetting].addOption("3.0"); - - channel[ZEO_SleepStage].addOption("Unknown"); - channel[ZEO_SleepStage].addOption("Awake"); - channel[ZEO_SleepStage].addOption("REM"); - channel[ZEO_SleepStage].addOption("Light Sleep"); - channel[ZEO_SleepStage].addOption("Deep Sleep"); - -/* CPAPModeNames[MODE_UNKNOWN]=QObject::tr("Undetermined"); - CPAPModeNames[MODE_CPAP]=QObject::tr("CPAP"); - CPAPModeNames[MODE_APAP]=QObject::tr("Auto"); - CPAPModeNames[MODE_BIPAP]=QObject::tr("BIPAP"); - CPAPModeNames[MODE_ASV]=QObject::tr("ASV"); - - PressureReliefNames[PR_UNKNOWN]=QObject::tr("Undetermined"); - PressureReliefNames[PR_NONE]=QObject::tr("None"); - PressureReliefNames[PR_CFLEX]=QObject::tr("C-Flex"); - PressureReliefNames[PR_CFLEXPLUS]=QObject::tr("C-Flex+"); - PressureReliefNames[PR_AFLEX]=QObject::tr("A-Flex"); - PressureReliefNames[PR_BIFLEX]=QObject::tr("Bi-Flex"); - PressureReliefNames[PR_EPR]=QObject::tr("Exhalation Pressure Relief (EPR)"); - PressureReliefNames[PR_SMARTFLEX]=QObject::tr("SmartFlex"); - - DefaultMCShortNames[CPAP_Obstructive]=QObject::tr("OA"); - DefaultMCShortNames[CPAP_Apnea]=QObject::tr("A"); - DefaultMCShortNames[CPAP_Hypopnea]=QObject::tr("H"); - DefaultMCShortNames[CPAP_RERA]=QObject::tr("RE"); - DefaultMCShortNames[CPAP_ClearAirway]=QObject::tr("CA"); - DefaultMCShortNames[CPAP_CSR]=QObject::tr("CSR/PB"); - DefaultMCShortNames[CPAP_VSnore]=QObject::tr("VS"); - DefaultMCShortNames[PRS1_VSnore2]=QObject::tr("VS2"); - DefaultMCShortNames[CPAP_FlowLimit]=QObject::tr("FL"); - DefaultMCShortNames[CPAP_Pressure]=QObject::tr("P"); - DefaultMCShortNames[CPAP_Leak]=QObject::tr("LR"); - DefaultMCShortNames[CPAP_EAP]=QObject::tr("EPAP"); - DefaultMCShortNames[CPAP_IAP]=QObject::tr("IPAP"); - DefaultMCShortNames[PRS1_PressurePulse]=QObject::tr("PP"); - - DefaultMCLongNames[CPAP_Obstructive]=QObject::tr("Obstructive Apnea"); - DefaultMCLongNames[CPAP_Hypopnea]=QObject::tr("Hypopnea"); - DefaultMCLongNames[CPAP_Apnea]=QObject::tr("Apnea"); - DefaultMCLongNames[CPAP_RERA]=QObject::tr("RERA"); - DefaultMCLongNames[CPAP_ClearAirway]=QObject::tr("Clear Airway Apnea"); - DefaultMCLongNames[CPAP_CSR]=QObject::tr("Periodic Breathing"); - DefaultMCLongNames[CPAP_VSnore]=QObject::tr("Vibratory Snore"); // flags type - DefaultMCLongNames[CPAP_FlowLimit]=QObject::tr("Flow Limitation"); - DefaultMCLongNames[CPAP_Pressure]=QObject::tr("Pressure"); - DefaultMCLongNames[CPAP_Leak]=QObject::tr("Leak Rate"); - DefaultMCLongNames[CPAP_PS]=QObject::tr("Pressure Support"); - DefaultMCLongNames[CPAP_EAP]=QObject::tr("BIPAP EPAP"); - DefaultMCLongNames[CPAP_IAP]=QObject::tr("BIPAP IPAP"); - DefaultMCLongNames[CPAP_Snore]=QObject::tr("Vibratory Snore"); // Graph data - DefaultMCLongNames[PRS1_VSnore2]=QObject::tr("Vibratory Snore (Graph)"); - DefaultMCLongNames[PRS1_PressurePulse]=QObject::tr("Pressure Pulse"); - DefaultMCLongNames[PRS1_Unknown0E]=QObject::tr("Unknown 0E"); - DefaultMCLongNames[PRS1_Unknown00]=QObject::tr("Unknown 00"); - DefaultMCLongNames[PRS1_Unknown01]=QObject::tr("Unknown 01"); - DefaultMCLongNames[PRS1_Unknown0B]=QObject::tr("Unknown 0B"); - DefaultMCLongNames[PRS1_Unknown10]=QObject::tr("Unknown 10"); */ -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Machine Base-Class implmementation ////////////////////////////////////////////////////////////////////////////////////////// @@ -374,7 +93,7 @@ Day *Machine::AddSession(Session *s,Profile *p) sessionlist[s->session()]=s; // To make sure it get's saved later even if it's not wanted. - QDateTime d1,d2=QDateTime::fromTime_t(s->first()/1000); + QDateTime d2=QDateTime::fromTime_t(s->first()/1000); QDate date=d2.date(); QTime time=d2.time(); @@ -605,8 +324,9 @@ bool Machine::Save() QString fn=path+"/channels.dat"; QFile cf(fn); - if (cf.open(QIODevice::WriteOnly)) { - int i=4; + if (!cf.open(QIODevice::WriteOnly)) { + qDebug() << "Couldn't write.. Permissions? Hard disk crashing?"; + return false; } QDataStream out(&cf); out.setVersion(QDataStream::Qt_4_6); @@ -717,12 +437,6 @@ Session *Machine::popSaveList() CPAP::CPAP(Profile *p,MachineID id):Machine(p,id) { m_type=MT_CPAP; - - registerChannel(CPAP_Obstructive); - registerChannel(CPAP_Hypopnea); - registerChannel(CPAP_ClearAirway); - registerChannel(CPAP_Snore); - registerChannel(CPAP_Leak); } CPAP::~CPAP() @@ -735,9 +449,6 @@ CPAP::~CPAP() Oximeter::Oximeter(Profile *p,MachineID id):Machine(p,id) { m_type=MT_OXIMETER; - registerChannel(OXI_Pulse); - registerChannel(OXI_SPO2); - registerChannel(OXI_Plethysomogram); } Oximeter::~Oximeter() diff --git a/SleepLib/machine.h b/SleepLib/machine.h index 794f0ba2..e4c33595 100644 --- a/SleepLib/machine.h +++ b/SleepLib/machine.h @@ -91,8 +91,8 @@ public: const MachineID & id() { return m_id; } const QDate & FirstDay() { return firstday; } const QDate & LastDay() { return lastday; } - bool hasChannel(ChannelID id) { return m_channels.contains(id) && m_channels[id]; } - void registerChannel(ChannelID id,bool b=true) { m_channels[id]=b; } + bool hasChannel(QString id) { return m_channels.contains(id) && m_channels[id]; } + void registerChannel(QString id,bool b=true) { m_channels[id]=b; } protected: QDate firstday,lastday; @@ -104,7 +104,7 @@ protected: Profile *profile; bool changed; bool firstsession; - QHash m_channels; + QHash m_channels; }; class CPAP:public Machine diff --git a/SleepLib/machine_common.h b/SleepLib/machine_common.h index c7b1034e..83536e64 100644 --- a/SleepLib/machine_common.h +++ b/SleepLib/machine_common.h @@ -1,8 +1,8 @@ -/******************************************************************** +/* SleepLib Machine Loader Class Header Copyright (c)2011 Mark Watkins License: GPL -*********************************************************************/ +*/ #ifndef MACHINE_COMMON_H #define MACHINE_COMMON_H @@ -15,7 +15,7 @@ #include using namespace std; -typedef quint32 ChannelID; +typedef QString ChannelID; typedef long MachineID; typedef long SessionID; typedef float EventDataType; @@ -32,163 +32,7 @@ const quint16 dbversion=6; enum MachineType { MT_UNKNOWN=0,MT_CPAP,MT_OXIMETER,MT_SLEEPSTAGE,MT_JOURNAL }; -enum ChannelType { CT_Unknown=0, CT_Event, CT_Graph, CT_Text, CT_Decimal, CT_Integer, CT_Boolean, CT_DateTime, CT_Date, CT_Time, CT_Timespan, CT_Calculation, CT_Lookup }; - -class Channel -{ -protected: - ChannelID m_id; - MachineType m_mtype; - ChannelType m_ctype; - QString m_details; - QString m_label; - QColor m_color; - QVector m_option; - EventDataType m_min_value; - EventDataType m_max_value; -public: - Channel() - :m_id(0),m_mtype(MT_UNKNOWN), m_ctype(CT_Unknown), m_details(""), m_label(""),m_color(Qt::black) {} - Channel(ChannelID id, MachineType mtype, ChannelType ctype, QString details, QString label, QColor color) - :m_id(id),m_mtype(mtype),m_ctype(ctype),m_details(details),m_label(label),m_color(color) {} - ChannelID & id() { return m_id; } - MachineType & machinetype() { return m_mtype; } - ChannelType & channeltype() { return m_ctype; } - QString & details() { return m_details; } - QString & label() { return m_label; } - - EventDataType min() { return m_min_value; } // Min value allowed for this channel - EventDataType max() { return m_max_value; } // Max value allowed for this channel - void setMin(EventDataType v) { m_min_value=v; } - void setMax(EventDataType v) { m_max_value=v; } - - // add Option automatically sets the bounds - void addOption(QVariant v) { m_option.push_back(v); m_min_value=0; m_max_value=m_option.size(); } - int countOptions() { return m_option.count(); } - - QVariant & option(int i) { if (m_option.contains(i)) return m_option[i]; } - QVariant & operator [](int i) { if (m_option.contains(i)) return m_option[i]; } - - QString optionString(int i) { if (m_option.contains(i)) return m_option[i].toString(); else return ""; } - int optionInt(int i) { if (m_option.contains(i)) return m_option[i].toInt(); else return 0; } - EventDataType optionFloat(int i) { if (m_option.contains(i)) return m_option[i].toFloat(); else return 0; } -}; - -extern QHash channel; -extern QHash channel_lookup; - -struct ChannelGroup -{ -protected: - MachineType m_type; - ChannelID m_first; - ChannelID m_size; - ChannelID m_pos; - QHash m_channel; - QHash > m_channelsbytype; - QHash m_channel_lookup; -public: - ChannelID first() { return m_first; } - ChannelID count() { return m_pos; } - Channel & operator [](ChannelID id) { return *m_channel[id]; } - Channel & operator [](QString lookup) { return *m_channel_lookup[lookup]; } - QHash & operator [](ChannelType type) { return m_channelsbytype[type]; } - - ChannelID Get(ChannelType ctype,QString description="",QString label="",QString lookup="",QColor color=Qt::black); - ChannelGroup(); - ChannelGroup(MachineType type, ChannelID first, ChannelID reserved=0x200); -}; -extern QHash channel_group; - -extern ChannelGroup CPAP_CODES; -extern ChannelGroup PRS1_CODES; -extern ChannelGroup RMS9_CODES; -extern ChannelGroup JOURNAL_CODES; -extern ChannelGroup ZEO_CODES; -extern ChannelGroup OXI_CODES; - -// ******************** IMPORTANT ******************** -// Add to the end of each group or be eaten by a Grue! -// Increment this version number if you mess with this -// ******************** IMPORTANT ******************** -const quint32 ChannelVersionNumber=0; - -const ChannelID EmptyChannel=0; -extern ChannelID CPAP_Obstructive,CPAP_Hypopnea,CPAP_Apnea, CPAP_ClearAirway, CPAP_RERA, CPAP_FlowLimit, -CPAP_CSR, CPAP_VSnore, CPAP_PressurePulse, CPAP_Mode, CPAP_FlowRate, CPAP_MaskPressure, CPAP_Pressure, -CPAP_EPAP, CPAP_IPAP, CPAP_IPAP_Low, CPAP_IPAP_High, CPAP_PressureSupport, CPAP_Snore, CPAP_Leak, -CPAP_RespiratoryRate, CPAP_TidalVolume, CPAP_MinuteVentilation, CPAP_PatientTriggeredBreaths, -CPAP_FlowLimitGraph, CPAP_TherapyPressure, CPAP_ExpiratoryPressure, CPAP_AHI, CPAP_BrokenSummary, -CPAP_BrokenWaveform, CPAP_Pulse, CPAP_SPO2, CPAP_Plethy,CPAP_RespiratoryEvent,CPAP_IE,CPAP_Ti,CPAP_Te; - -extern ChannelID RMS9_PressureReliefType, RMS9_PressureReliefSetting, RMS9_Empty1, RMS9_Empty2; -extern ChannelID PRS1_PressureMin,PRS1_PressureMax, PRS1_PressureMinAchieved, PRS1_PressureMaxAchieved, -PRS1_PressureAvg, PRS1_Pressure90, PRS1_RampTime, PRS1_RampPressure, PRS1_HumidifierStatus, -PRS1_HumidifierSetting, PRS1_PressureReliefType, PRS1_PressureReliefSetting, PRS1_SystemOneResistanceStatus, -PRS1_SystemOneResistanceSetting, PRS1_SystemLockStatus, PRS1_HoseDiameter, PRS1_AutoOff, PRS1_AutoOn, -PRS1_MaskAlert, PRS1_ShowAHI, PRS1_Unknown00, PRS1_Unknown01, PRS1_Unknown08, PRS1_Unknown09, -PRS1_Unknown0A, PRS1_Unknown0B, PRS1_Unknown0C, PRS1_Unknown0E, PRS1_Unknown0F, PRS1_Unknown10, -PRS1_Unknown12, PRS1_VSnore2; - -extern ChannelID OXI_Pulse, OXI_SPO2, OXI_Plethysomogram, OXI_PulseChange, OXI_SPO2Drop, OXI_Error, OXI_SignalError; -extern ChannelID ZEO_SleepStage, ZEO_Waveform; -extern ChannelID JOURNAL_Notes, JOURNAL_Weight; - - - - - - -// Be cautious when extending these.. add to the end of each groups to preserve file formats. -/*enum ChannelID//:qint16 -{ - // General Event Codes - MC_UNKNOWN=0, - - CPAP_Obstructive, CPAP_Apnea, CPAP_Hypopnea, CPAP_ClearAirway, CPAP_RERA, CPAP_VSnore, CPAP_FlowLimit, - CPAP_Leak, CPAP_Pressure, CPAP_EAP, CPAP_IAP, CPAP_CSR, CPAP_FlowRate, CPAP_MaskPressure, - CPAP_Snore,CPAP_MinuteVentilation, CPAP_RespiratoryRate, CPAP_TidalVolume,CPAP_FlowLimitGraph, - CPAP_PatientTriggeredBreaths, CPAP_PS, CPAP_IAPLO, CPAP_IAPHI, - - // General CPAP Summary Information - CPAP_PressureMin=0x80, CPAP_PressureMax, CPAP_RampTime, CPAP_RampStartingPressure, CPAP_Mode, CPAP_PressureReliefType, - CPAP_PressureReliefSetting, CPAP_HumidifierSetting, CPAP_HumidifierStatus, CPAP_PressureMinAchieved, - CPAP_PressureMaxAchieved, CPAP_PressurePercentValue, CPAP_PressurePercentName, CPAP_PressureAverage, CPAP_PressureMedian, - CPAP_LeakMedian,CPAP_LeakMinimum,CPAP_LeakMaximum,CPAP_LeakAverage,CPAP_Duration, - CPAP_SnoreMinimum, CPAP_SnoreMaximum, CPAP_SnoreAverage, CPAP_SnoreMedian, CPAP_TherapyPressure, CPAP_ExpPressure, - - CPAP_Pressure90,CPAP_Leak90,CPAP_AI, CPAP_HI, CPAP_CAI, CPAP_AHI, CPAP_PBI, - - BIPAP_EAPAverage,BIPAP_IAPAverage,BIPAP_EAPMin,BIPAP_EAPMax,BIPAP_IAPMin,BIPAP_IAPMax, - BIPAP_PSAverage,BIPAP_PSMin, BIPAP_PSMax, BIPAP_PS90, BIPAP_EAP90, BIPAP_IAP90, - - CPAP_PTBMin, CPAP_PTBMax, CPAP_PTBAverage, CPAP_PTB90, - CPAP_RRMin, CPAP_RRMax, CPAP_RRAverage, CPAP_RR90, - CPAP_MVMin, CPAP_MVMax, CPAP_MVAverage, CPAP_MV90, - CPAP_TVMin, CPAP_TVMax, CPAP_TVAverage, CPAP_TV90, - - CPAP_BrokenSummary, CPAP_BrokenWaveform, - - // PRS1 Specific Codes - PRS1_PressurePulse=0x1000,PRS1_VSnore2, - PRS1_Unknown00, PRS1_Unknown01, PRS1_Unknown08, PRS1_Unknown09, PRS1_Unknown0B, PRS1_Unknown0E, PRS1_Unknown10, PRS1_Unknown12, - PRS1_SystemLockStatus, PRS1_SystemResistanceStatus, PRS1_SystemResistanceSetting, PRS1_HoseDiameter, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI, - - // ASV Unknown Codes - PRS1_Unknown0A,PRS1_Unknown0C, PRS1_Unknown0F, - - ResMed_Empty1, ResMed_Empty2, - - // Oximeter Codes - OXI_Pulse=0x2000, OXI_SPO2, OXI_Plethy, OXI_Signal2, OXI_SignalGood, OXI_PulseAverage, OXI_PulseMin, OXI_PulseMax, OXI_SPO2Average, OXI_SPO2Min, OXI_SPO2Max, - OXI_PulseChange, OXI_SPO2Change, - - ZEO_SleepStage=0x2800, ZEO_Waveform, - - GEN_Weight=0x3000, GEN_Notes, GEN_Glucose, GEN_Calories, GEN_Energy, GEN_Mood, GEN_Excercise, GEN_Reminder - -};*/ -void InitMapsWithoutAwesomeInitializerLists(); +//void InitMapsWithoutAwesomeInitializerLists(); enum CPAPMode//:short @@ -206,8 +50,65 @@ enum PRTypes//:short //extern map CPAPModeNames; // These are types supported by wxVariant class. To retain compatability, add to the end of this list only.. -enum MCDataType//:wxInt8 +enum MCDataType { MC_bool=0, MC_int, MC_long, MC_float, MC_double, MC_string, MC_datetime }; +const QString CPAP_IPAP="IPAP"; +const QString CPAP_EPAP="EPAP"; +const QString CPAP_Pressure="Pressure"; +const QString CPAP_PS="PS"; +const QString PRS1_FlexMode="FlexMode"; +const QString PRS1_FlexSet="FlexSet"; +const QString CPAP_Mode="PAPMode"; +const QString CPAP_BrokenSummary="BrokenSummary"; +const QString CPAP_PressureMin="PressureMin"; +const QString CPAP_PressureMax="PressureMin"; +const QString CPAP_RampTime="RampTime"; +const QString CPAP_RampPressure="RampPressure"; +const QString CPAP_Obstructive="Obstructive"; +const QString CPAP_Hypopnea="Hypopnea"; +const QString CPAP_ClearAirway="ClearAirway"; +const QString CPAP_Apnea="Apnea"; +const QString CPAP_CSR="CSR"; +const QString CPAP_VSnore="VSnore"; +const QString CPAP_VSnore2="VSnore2"; +const QString CPAP_RERA="RERA"; +const QString CPAP_PressurePulse="PressurePulse"; +const QString CPAP_FlowLimit="FlowLimit"; +const QString CPAP_FlowRate="FlowRate"; +const QString CPAP_MaskPressure="MaskPressure"; +const QString CPAP_MaskPressureHi="MaskPressureHi"; +const QString CPAP_RespEvent="RespEvent"; +const QString CPAP_Snore="Snore"; +const QString CPAP_MinuteVent="MinuteVent"; +const QString CPAP_RespRate="RespRate"; +const QString CPAP_TidalVolume="TidalVolume"; +const QString CPAP_PTB="PTB"; +const QString CPAP_Leak="Leak"; +const QString CPAP_FLG="FLG"; +const QString CPAP_IE="IE"; +const QString CPAP_Te="Te"; +const QString CPAP_Ti="Ti"; +const QString RMS9_E01="RMS9_E01"; +const QString RMS9_E02="RMS9_E02"; +const QString PRS1_00="PRS1_00"; +const QString PRS1_01="PRS1_01"; +const QString PRS1_08="PRS1_08"; +const QString PRS1_0A="PRS1_0A"; +const QString PRS1_0B="PRS1_0B"; +const QString PRS1_0C="PRS1_0C"; +const QString PRS1_0E="PRS1_0E"; +const QString PRS1_0F="PRS1_0F"; +const QString PRS1_10="PRS1_10"; +const QString PRS1_12="PRS1_12"; + +const QString OXI_Pulse="Pulse"; +const QString OXI_SPO2="SPO2"; +const QString OXI_PulseChange="PulseChange"; +const QString OXI_SPO2Drop="SPO2Drop"; +const QString OXI_Plethy="Plethy"; + +const QString CPAP_AHI="AHI"; + #endif // MACHINE_COMMON_H diff --git a/SleepLib/profiles.cpp b/SleepLib/profiles.cpp index 607cc255..a38986b4 100644 --- a/SleepLib/profiles.cpp +++ b/SleepLib/profiles.cpp @@ -358,8 +358,7 @@ Profile *Get() */ void Scan() { - InitMapsWithoutAwesomeInitializerLists(); - + //InitMapsWithoutAwesomeInitializerLists(); p_pref=new Preferences("Preferences"); p_layout=new Preferences("Layout"); diff --git a/SleepLib/schema.cpp b/SleepLib/schema.cpp new file mode 100644 index 00000000..603cfb1a --- /dev/null +++ b/SleepLib/schema.cpp @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include +#include "schema.h" + + + +namespace schema { + +ChannelList channel; +Channel EmptyChannel; + +QHash ChanTypes; +QHash DataTypes; +QHash Scopes; + +bool schema_initialized=false; + +void init() +{ + if (schema_initialized) return; + schema_initialized=true; + + EmptyChannel=Channel(0,DATA,DAY,"Empty","Empty Channel","Empty",""); + + ChanTypes["data"]=DATA; + //Types["waveform"]=WAVEFORM; + ChanTypes["setting"]=SETTING; + + Scopes["session"]=SESSION; + Scopes["day"]=DAY; + Scopes["machine"]=MACHINE; + Scopes["global"]=GLOBAL; + + DataTypes[""]=DEFAULT; + DataTypes["bool"]=BOOL; + DataTypes["double"]=DOUBLE; + DataTypes["integer"]=INTEGER; + DataTypes["string"]=STRING; + DataTypes["richtext"]=RICHTEXT; + DataTypes["date"]=DATE; + DataTypes["datetime"]=DATETIME; + DataTypes["time"]=TIME; + + schema::channel.Load(":/docs/channels.xml"); + +} + +Channel::Channel(int id, ChanType type, ScopeType scope, QString name, QString description, QString label, QString unit, DataType datatype, QColor color, int link): + m_id(id), + m_type(type), + m_scope(scope), + m_name(name), + m_description(description), + m_label(label), + m_unit(unit), + m_datatype(datatype), + m_defaultcolor(color), + m_link(link) +{ +} +bool Channel::isNull() +{ + return (this==&EmptyChannel); +} + +ChannelList::ChannelList() + :m_doctype("channels") +{ +} +ChannelList::~ChannelList() +{ + for (QHash::iterator i=channels.begin();i!=channels.end();i++) { + delete i.value(); + } +} +bool ChannelList::Load(QString filename) +{ + QDomDocument doc(m_doctype); + QFile file(filename); + qDebug() << "Opening " << filename; + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open" << filename; + return false; + } + QString errorMsg; + int errorLine; + if (!doc.setContent(&file,false,&errorMsg,&errorLine)) { + qWarning() << "Invalid XML Content in" << filename; + qWarning() << "Error line" << errorLine <<":" << errorMsg; + return false; + } + file.close(); + + + QDomElement root=doc.documentElement(); + if (root.tagName().toLower() != "channels") { + return false; + } + QString language=root.attribute("language","en"); + QString version=root.attribute("version",""); + + if (version.isEmpty()) { + qWarning() << "No Version Field in" << m_doctype << "Schema, assuming 1.0" << filename; + version="1.0"; + } + + qDebug() << "Processing xml file:" << m_doctype << language << version; + QDomNodeList grp=root.elementsByTagName("group"); + QDomNode node,n,ch; + QDomElement e; + + bool ok; + int id,linkid; + QString chantype,scopestr,typestr,name,group,idtxt,details,label,unit,datatypestr,defcolor,link; + ChanType type; + DataType datatype; + Channel *chan; + QColor color; + bool multi; + ScopeType scope; + int line; + for (int i=0;i0) { + if (channels.contains(linkid)) { + Channel *it=channels[id]; + chan->m_links.push_back(it); + } else { + qWarning() << "Linked channel must be defined first in" << filename <<"line" << line; + } + } + + // process children + while(!ch.isNull()) { + e=ch.toElement(); + QString sub=ch.nodeName().toLower(); + QString id2str,name2str; + int id2; + if (sub=="option") { + id2str=e.attribute("id"); + id2=id2str.toInt(&ok,10); + name2str=e.attribute("value"); + //qDebug() << sub << id2 << name2str; + chan->addOption(id2,name2str); + } else if (sub=="color") { + } + ch=ch.nextSibling(); + } + } + } + + return true; +} +bool ChannelList::Save(QString filename) +{ + return false; +} + +} + +typedef schema::Channel * ChannelID; diff --git a/SleepLib/schema.h b/SleepLib/schema.h new file mode 100644 index 00000000..1b949dc9 --- /dev/null +++ b/SleepLib/schema.h @@ -0,0 +1,93 @@ +#ifndef SCHEMA_H +#define SCHEMA_H + +#include +#include +#include +#include + +namespace schema { + +enum Function { + NONE=0, AVG, WAVG, MIN, MAX, SUM, CNT, P90, CPH, SPH, HOURS, SET +}; + +enum ChanType { + DATA=0, SETTING +}; + +enum DataType { + DEFAULT=0, INTEGER, BOOL, DOUBLE, STRING, RICHTEXT, DATE, TIME, DATETIME +}; +enum ScopeType { + GLOBAL=0, MACHINE, DAY, SESSION +}; +class Channel; +extern Channel EmptyChannel; + +// this is really a channel definition. +class Channel +{ +public: + Channel() { m_id=0; } + Channel(int id, ChanType type, ScopeType scope, QString name, QString description, QString label, QString unit,DataType datatype=DEFAULT, QColor=Qt::black, int link=0); + void addColor(Function f, QColor color) { m_colors[f]=color; } + void addOption(int i, QString option) { m_options[i]=option; } + + const int & id() { return m_id; } + const ChanType & type() { return m_type; } + const QString & name() { return m_name; } + const QString & description() { return m_description; } + const QString & label() { return m_label; } + QHash m_options; + QHash m_colors; + QList m_links; // better versions of this data type + bool isNull(); +protected: + int m_id; + ChanType m_type; + ScopeType m_scope; + QString m_name; + QString m_description; + QString m_label; + QString m_unit; + DataType m_datatype; + QColor m_defaultcolor; + + int m_link; +}; + +class ChannelList +{ +public: + ChannelList(); + virtual ~ChannelList(); + bool Load(QString filename); + bool Save(QString filename); + Channel & operator[](int i) { + if (channels.contains(i)) + return *channels[i]; + else + return EmptyChannel; + } + Channel & operator[](QString name) { + QString tmp=name.toLower(); + if (names.contains(tmp)) + return *names[tmp]; + else + return EmptyChannel; + } + + QHash channels; + QHash names; + QHash > groups; + QString m_doctype; +}; + +extern ChannelList channel; + +void init(); + +} // namespace + +#endif // SCHEMA_H diff --git a/SleepLib/session.cpp b/SleepLib/session.cpp index f757c8b4..7d709bbb 100644 --- a/SleepLib/session.cpp +++ b/SleepLib/session.cpp @@ -254,7 +254,7 @@ bool Session::StoreEvents(QString filename) QHash >::iterator i; for (i=eventlist.begin(); i!=eventlist.end(); i++) { - out << (qint16)i.key(); // ChannelID + out << i.key(); // ChannelID out << (qint16)i.value().size(); for (int j=0;j sizevec; QString dim; for (int i=0;i> t16; - code=(ChannelID)t16; + in >> code; mcorder.push_back(code); in >> size2; sizevec.push_back(size2); @@ -367,10 +366,10 @@ bool Session::LoadEvents(QString filename) in >> mn; in >> mx; in >> dim; - EventList *elist=new EventList(code,elt,gain,offset,mn,mx,rate); + EventList *elist=AddEventList(code,elt,gain,offset,mn,mx,rate); elist->setDimension(dim); - eventlist[code].push_back(elist); + //eventlist[code].push_back(elist); elist->m_count=evcount; elist->m_first=ts1; elist->m_last=ts2; @@ -411,7 +410,7 @@ void Session::UpdateSummaries() QHash >::iterator c; for (c=eventlist.begin();c!=eventlist.end();c++) { id=c.key(); - if ((channel[id].channeltype()==CT_Event) || (channel[id].channeltype()==CT_Graph)) { + if (schema::channel[id].type()==schema::DATA) { //sum(id); // avg calculates this and cnt. min(id); max(id); @@ -540,7 +539,7 @@ qint64 Session::last(ChannelID id) m_lastchan[id]=max; return max; } -bool Session::channelExists(ChannelID id) +/*bool Session::channelExists(ChannelID id) { if (s_events_loaded) { QHash >::iterator j=eventlist.find(id); @@ -552,7 +551,7 @@ bool Session::channelExists(ChannelID id) return false; } return true; -} +}*/ int Session::count(ChannelID id) { @@ -763,3 +762,15 @@ EventDataType Session::wavg(ChannelID id) return v; } +EventList * Session::AddEventList(QString chan, EventListType et,EventDataType gain,EventDataType offset,EventDataType min, EventDataType max,EventDataType rate) +{ + schema::Channel * channel=&schema::channel[chan]; + if (!channel) { + qWarning() << "Channel" << chan << "does not exist!"; + //return NULL; + } + EventList * el=new EventList(et,gain,offset,min,max,rate); + eventlist[chan].push_back(el); + s_machine->registerChannel(chan); + return el; +} diff --git a/SleepLib/session.h b/SleepLib/session.h index d89a2655..9e389b7a 100644 --- a/SleepLib/session.h +++ b/SleepLib/session.h @@ -13,8 +13,9 @@ #include #include "SleepLib/machine.h" +#include "SleepLib/schema.h" #include "SleepLib/event.h" -class EventList; +//class EventList; class Machine; const quint32 magic=0xC73216AB; @@ -117,7 +118,7 @@ public: EventDataType percentile(ChannelID id,EventDataType percentile); - bool channelExists(ChannelID id); + bool channelExists(QString name) { return (schema::channel.names.contains(name));} bool IsLoneSession() { return s_lonesession; } void SetLoneSession(bool b) { s_lonesession=b; } @@ -130,6 +131,7 @@ public: qint64 last(ChannelID code); void UpdateSummaries(); + EventList * AddEventList(QString chan, EventListType et, EventDataType gain=1.0, EventDataType offset=0.0, EventDataType min=0.0, EventDataType max=0.0, EventDataType rate=0.0); Machine * machine() { return s_machine; } protected: SessionID s_session; diff --git a/SleepyHeadQT.pro b/SleepyHeadQT.pro index a139db7b..425c2643 100644 --- a/SleepyHeadQT.pro +++ b/SleepyHeadQT.pro @@ -46,14 +46,15 @@ SOURCES += main.cpp\ Graphs/gYAxis.cpp \ Graphs/gFlagsLine.cpp \ Graphs/glcommon.cpp \ - Graphs/gBarChart.cpp \ Graphs/gSegmentChart.cpp \ Graphs/gSessionTime.cpp \ qextserialport/qextserialport.cpp \ preferencesdialog.cpp \ Graphs/gGraphView.cpp \ Graphs/gStatsLine.cpp \ - report.cpp + report.cpp \ + Graphs/gSummaryChart.cpp \ + SleepLib/schema.cpp unix:SOURCES += qextserialport/posix_qextserialport.cpp unix:!macx:SOURCES += qextserialport/qextserialenumerator_unix.cpp @@ -93,7 +94,6 @@ HEADERS += \ Graphs/gYAxis.h \ Graphs/gFlagsLine.h \ Graphs/glcommon.h \ - Graphs/gBarChart.h \ Graphs/gSegmentChart.h\ Graphs/gSessionTime.h \ SleepLib/loader_plugins/resmed_loader.h \ @@ -103,7 +103,9 @@ HEADERS += \ preferencesdialog.h \ Graphs/gGraphView.h \ Graphs/gStatsLine.h \ - report.h + report.h \ + Graphs/gSummaryChart.h \ + SleepLib/schema.h FORMS += \ @@ -120,4 +122,7 @@ RESOURCES += \ OTHER_FILES += \ docs/index.html \ docs/usage.html \ - docs/template_overview.sht + docs/template_overview.sht \ + docs/schema.xml \ + docs/graphs.xml \ + docs/channels.xml diff --git a/daily.cpp b/daily.cpp index 92e58ba3..c93d4789 100644 --- a/daily.cpp +++ b/daily.cpp @@ -125,11 +125,10 @@ Daily::Daily(QWidget *parent,Profile * _profile,gGraphView * shared, MainWindow FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Hypopnea,QColor("blue"),"H"))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_PressurePulse,QColor("red"),"PR",FT_Dot))); //FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Pressure,QColor("white"),"P",FT_Dot))); - FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_Unknown0B,QColor("blue"),"0B",FT_Dot))); - FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_Unknown10,QColor("orange"),"10",FT_Dot))); - FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_Unknown0E,QColor("dark red"),"0E",FT_Dot))); + FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_0B,QColor("blue"),"0B",FT_Dot))); + FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_10,QColor("orange"),"10",FT_Dot))); + FRW->AddLayer(AddCPAP(new gLineOverlayBar(PRS1_0E,QColor("dark red"),"0E",FT_Dot))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_RERA,QColor("gold"),"RE"))); - //FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Unknown0E,QColor("dark green"),"U0E"))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Apnea,QColor("dark green"),"A"))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_VSnore,QColor("red"),"VS"))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_FlowLimit,QColor("black"),"FL"))); @@ -160,24 +159,25 @@ Daily::Daily(QWidget *parent,Profile * _profile,gGraphView * shared, MainWindow PRD->AddLayer(AddCPAP(new gLineChart(CPAP_Pressure,QColor("dark green"),true))); PRD->AddLayer(AddCPAP(new gLineChart(CPAP_EPAP,Qt::blue,true))); PRD->AddLayer(AddCPAP(new gLineChart(CPAP_IPAP,Qt::red,true))); + LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_Leak,Qt::darkYellow,true))); SNORE->AddLayer(AddCPAP(new gLineChart(CPAP_Snore,Qt::darkGray,true))); - PTB->AddLayer(AddCPAP(new gLineChart(CPAP_PatientTriggeredBreaths,Qt::gray,true))); + PTB->AddLayer(AddCPAP(new gLineChart(CPAP_PTB,Qt::gray,true))); MP->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure,Qt::blue,false))); - RR->AddLayer(AddCPAP(new gLineChart(CPAP_RespiratoryRate,Qt::darkMagenta,true))); - MV->AddLayer(AddCPAP(new gLineChart(CPAP_MinuteVentilation,Qt::darkCyan,true))); + RR->AddLayer(AddCPAP(new gLineChart(CPAP_RespRate,Qt::darkMagenta,true))); + MV->AddLayer(AddCPAP(new gLineChart(CPAP_MinuteVent,Qt::darkCyan,true))); TV->AddLayer(AddCPAP(new gLineChart(CPAP_TidalVolume,Qt::magenta,true))); - FLG->AddLayer(AddCPAP(new gLineChart(CPAP_FlowLimitGraph,Qt::darkBlue,true))); + FLG->AddLayer(AddCPAP(new gLineChart(CPAP_FLG,Qt::darkBlue,true))); //RE->AddLayer(AddCPAP(new gLineChart(CPAP_RespiratoryEvent,Qt::magenta,true))); IE->AddLayer(AddCPAP(new gLineChart(CPAP_IE,Qt::darkRed,true))); TE->AddLayer(AddCPAP(new gLineChart(CPAP_Te,Qt::darkGreen,true))); TI->AddLayer(AddCPAP(new gLineChart(CPAP_Ti,Qt::darkBlue,true))); - INTPULSE->AddLayer(AddCPAP(new gLineChart(CPAP_Pulse,Qt::red,true))); - INTSPO2->AddLayer(AddCPAP(new gLineChart(CPAP_SPO2,Qt::blue,true))); + INTPULSE->AddLayer(AddCPAP(new gLineChart(OXI_Pulse,Qt::red,true))); + INTSPO2->AddLayer(AddCPAP(new gLineChart(OXI_SPO2,Qt::blue,true))); PULSE->AddLayer(AddOXI(new gLineChart(OXI_Pulse,Qt::red,true))); SPO2->AddLayer(AddOXI(new gLineChart(OXI_SPO2,Qt::blue,true))); - PLETHY->AddLayer(AddOXI(new gLineChart(OXI_Plethysomogram,Qt::darkBlue,false))); + PLETHY->AddLayer(AddOXI(new gLineChart(OXI_Plethy,Qt::darkBlue,false))); for (int i=0;iAddLayer(new gYAxis(),LayerLeft,gYAxis::Margin); @@ -607,7 +607,7 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day) if ((code!=CPAP_Obstructive) && (code!=CPAP_Hypopnea) && (code!=CPAP_Apnea) - && (code!=PRS1_Unknown0B) + && (code!=PRS1_0B) && (code!=CPAP_ClearAirway) && (code!=CPAP_CSR) && (code!=CPAP_RERA) @@ -618,9 +618,9 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day) if (mcroot.find(code)==mcroot.end()) { int cnt=day->count(code); total_events+=cnt; - QString st=channel[m.key()].details(); + QString st=schema::channel[m.key()].description(); if (st.isEmpty()) { - st="Fixme "+QString::number((int)code); + st="Fixme "+code; } st+=" ("+QString::number(cnt)+" event"+((cnt>1)?"s":"")+")"; QStringList l(st); @@ -772,13 +772,13 @@ void Daily::Load(QDate date) QString a; if (cpap) { mode=(CPAPMode)cpap->settings_max(CPAP_Mode); - pr=(PRTypes)cpap->settings_max(PRS1_PressureReliefType); + pr=(PRTypes)cpap->settings_max(PRS1_FlexMode); if (pr==PR_NONE) epr=tr(" No Pressure Relief"); else { - epr=channel[PRS1_PressureReliefSetting].optionString(pr)+QString(" x%1").arg((int)cpap->settings_max(PRS1_PressureReliefSetting)); + //epr=schema::channel[PRS1_FlexSet].optionString(pr)+QString(" x%1").arg((int)cpap->settings_max(PRS1_FlexSet)); } - modestr=channel[CPAP_Mode].optionString(mode); + modestr=schema::channel[CPAP_Mode].m_options[mode]; float ahi=(cpap->count(CPAP_Obstructive)+cpap->count(CPAP_Hypopnea)+cpap->count(CPAP_ClearAirway)+cpap->count(CPAP_Apnea))/cpap->hours(); float csr=(100.0/cpap->hours())*(cpap->sum(CPAP_CSR)/3600.0); @@ -870,24 +870,24 @@ void Daily::Load(QDate date) html+=(" MinAvg90%Max"); ChannelID chans[]={ - CPAP_Pressure,CPAP_EPAP,CPAP_IPAP,CPAP_PressureSupport,CPAP_PatientTriggeredBreaths, - CPAP_MinuteVentilation,CPAP_RespiratoryRate,CPAP_RespiratoryEvent,CPAP_FlowLimitGraph, + CPAP_Pressure,CPAP_EPAP,CPAP_IPAP,CPAP_PS,CPAP_PTB, + CPAP_MinuteVent,CPAP_RespRate,CPAP_RespEvent,CPAP_FLG, CPAP_Leak,CPAP_Snore,CPAP_IE,CPAP_Ti,CPAP_Te,CPAP_TidalVolume, - CPAP_Pulse,CPAP_SPO2,OXI_Pulse,OXI_SPO2 + OXI_Pulse,OXI_SPO2 }; int numchans=sizeof(chans)/sizeof(ChannelID); for (int i=0;ichannelExists(code)) { - html+=""+channel[code].label(); + if (cpap && cpap->channelHasData(code)) { + html+=""+schema::channel[code].label(); html+=""+a.sprintf("%.2f",cpap->min(code)); html+=""+a.sprintf("%.2f",cpap->wavg(code)); html+=""+a.sprintf("%.2f",cpap->p90(code)); html+=""+a.sprintf("%.2f",cpap->max(code)); html+=""; } - if (oxi && oxi->channelExists(code)) { - html+=""+channel[code].label(); + if (oxi && oxi->channelHasData(code)) { + html+=""+schema::channel[code].label(); html+=""+a.sprintf("%.2f",oxi->min(code)); html+=""+a.sprintf("%.2f",oxi->wavg(code)); html+=""+a.sprintf("%.2f",oxi->p90(code)); @@ -946,7 +946,7 @@ void Daily::Load(QDate date) for (QVector::iterator s=cpap->begin();s!=cpap->end();s++) { fd=QDateTime::fromTime_t((*s)->first()/1000L); ld=QDateTime::fromTime_t((*s)->last()/1000L); - QHash::iterator i=(*s)->settings.find(CPAP_BrokenWaveform); + QHash::iterator i=(*s)->settings.find("BrokenWaveform"); if ((i!=(*s)->settings.end()) && i.value().toBool()) corrupted_waveform=true; tmp.sprintf(("%08i"+fd.date().toString(Qt::SystemLocaleShortDate)+""+fd.toString("HH:mm ")+""+ld.toString("HH:mm")+"").toLatin1(),(*s)->session()); html+=tmp; @@ -960,16 +960,16 @@ void Daily::Load(QDate date) ui->webView->setHtml(html); - ui->JournalNotes->clear(); + /*ui->JournalNotes->clear(); Session *journal=GetJournalSession(date); if (journal) { ui->JournalNotes->setHtml(journal->settings[JOURNAL_Notes].toString()); - } + }*/ } void Daily::Unload(QDate date) { - Session *journal=GetJournalSession(date); + /*Session *journal=GetJournalSession(date); if (!ui->JournalNotes->toPlainText().isEmpty()) { QString jhtml=ui->JournalNotes->toHtml(); if (journal) { @@ -988,7 +988,7 @@ void Daily::Unload(QDate date) if (journal) { Machine *jm=profile->GetMachine(MT_JOURNAL); if (jm) jm->SaveSession(journal); - } + } */ UpdateCalendarDay(date); } diff --git a/daily.h b/daily.h index a1c21ef8..47ce2916 100644 --- a/daily.h +++ b/daily.h @@ -16,7 +16,7 @@ #include #include #include -#include "Graphs/gBarChart.h" +#include "Graphs/gSummaryChart.h" #include #include "mainwindow.h" diff --git a/docs/channels.xml b/docs/channels.xml new file mode 100644 index 00000000..1aaf1d92 --- /dev/null +++ b/docs/channels.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/graphs.xml b/docs/graphs.xml new file mode 100644 index 00000000..b56c5477 --- /dev/null +++ b/docs/graphs.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/schema.xml b/docs/schema.xml new file mode 100644 index 00000000..1a824e4f --- /dev/null +++ b/docs/schema.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main.cpp b/main.cpp index a0d43fcd..0d376ae2 100644 --- a/main.cpp +++ b/main.cpp @@ -10,7 +10,7 @@ #include #include - +#include "SleepLib/schema.h" #include "mainwindow.h" #include "SleepLib/profiles.h" @@ -45,6 +45,11 @@ void MyOutputHandler(QtMsgType type, const char *msg) { //loglock.unlock(); } +void initialize() +{ + schema::init(); +} + int main(int argc, char *argv[]) { #ifdef Q_WS_X11 @@ -52,8 +57,8 @@ int main(int argc, char *argv[]) #endif QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); QApplication a(argc, argv); - a.setApplicationName("SleepyHead"); + initialize(); /*int id=QFontDatabase::addApplicationFont(":/fonts/FreeSans.ttf"); QStringList ffam=QFontDatabase::applicationFontFamilies(id); diff --git a/mainwindow.cpp b/mainwindow.cpp index e7c54870..962db77a 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -20,6 +20,7 @@ #include "SleepLib/loader_plugins/zeo_loader.h" #include "SleepLib/loader_plugins/resmed_loader.h" #include "preferencesdialog.h" +#include "SleepLib/schema.h" #include "Graphs/glcommon.h" @@ -34,9 +35,10 @@ void MainWindow::Log(QString s) static QMutex loglock,strlock; static int start=QDateTime::currentDateTime().toTime_t(); static QStringList slist; - if (!loglock.tryLock()) { - return; - } + //if (!loglock.tryLock()) { + //return; + //} + loglock.lock(); strlock.lock(); QString tmp=QString("%1: %2").arg(QDateTime::currentDateTime().toTime_t()-start,5,10,QChar('0')).arg(s); @@ -150,6 +152,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(netmanager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); connect(ui->webView, SIGNAL(statusBarMessage(QString)), this, SLOT(updatestatusBarMessage(QString))); + } extern MainWindow *mainwin; MainWindow::~MainWindow() @@ -197,6 +200,12 @@ void MainWindow::Startup() if (overview) overview->ReloadGraphs(); qprogress->hide(); qstatus->setText(""); + schema::Channel & item=schema::channel["SysOneResistSet"]; + if (!item.isNull()) { + for (QHash::iterator i=item.m_options.begin();i!=item.m_options.end();i++) { + qDebug() << i.key() << i.value(); + } + } //qstatusbar->clearMessage(); } diff --git a/overview.cpp b/overview.cpp index fa55976a..2d8b3017 100644 --- a/overview.cpp +++ b/overview.cpp @@ -57,7 +57,7 @@ Overview::Overview(QWidget *parent,Profile * _profile,gGraphView * shared) : LK=new gGraph(GraphView,"Leaks",default_height,0); uc=new SummaryChart(profile,"Hours",GT_BAR); - uc->addSlice(EmptyChannel,QColor("green"),ST_HOURS); + uc->addSlice("",QColor("green"),ST_HOURS); UC->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin); gXAxis *gx=new gXAxis(); gx->setUtcFix(true); diff --git a/overview.h b/overview.h index 9ca3a43e..bcc5d675 100644 --- a/overview.h +++ b/overview.h @@ -13,7 +13,7 @@ #include #include "SleepLib/profiles.h" #include "Graphs/gGraphView.h" -#include "Graphs/gBarChart.h" +#include "Graphs/gSummaryChart.h" #include "report.h" namespace Ui { diff --git a/oximetry.cpp b/oximetry.cpp index 020a4516..a0a8be41 100644 --- a/oximetry.cpp +++ b/oximetry.cpp @@ -9,7 +9,7 @@ #include "SleepLib/loader_plugins/cms50_loader.h" #include "SleepLib/event.h" #include "Graphs/gXAxis.h" -#include "Graphs/gBarChart.h" +#include "Graphs/gSummaryChart.h" #include "Graphs/gLineChart.h" #include "Graphs/gYAxis.h" @@ -66,7 +66,7 @@ Oximetry::Oximetry(QWidget *parent,Profile * _profile,gGraphView * shared) : SPO2=new gGraph(GraphView,tr("SPO2"),120); foobar=new gShadowArea(); CONTROL->AddLayer(foobar); - Layer *cl=new gLineChart(OXI_Plethysomogram); + Layer *cl=new gLineChart(OXI_Plethy); CONTROL->AddLayer(cl); cl->SetDay(day); CONTROL->setBlockZoom(true); @@ -79,16 +79,13 @@ Oximetry::Oximetry(QWidget *parent,Profile * _profile,gGraphView * shared) : } // Create the Event Lists to store / import data - ev_plethy=new EventList(OXI_Plethysomogram,EVL_Waveform,1,0,0,0,1000.0/50.0); - session->eventlist[OXI_Plethysomogram].push_back(ev_plethy); + ev_plethy=session->AddEventList(OXI_Plethy,EVL_Waveform,1,0,0,0,1000.0/50.0); - ev_pulse=new EventList(OXI_Pulse,EVL_Event,1); - session->eventlist[OXI_Pulse].push_back(ev_pulse); + ev_pulse=session->AddEventList(OXI_Pulse,EVL_Event,1); - ev_spo2=new EventList(OXI_SPO2,EVL_Event,1); - session->eventlist[OXI_SPO2].push_back(ev_spo2); + ev_spo2=session->AddEventList(OXI_SPO2,EVL_Event,1); - plethy=new gLineChart(OXI_Plethysomogram,Qt::black,false,true); + plethy=new gLineChart(OXI_Plethy,Qt::black,false,true); plethy->SetDay(day); CONTROL->AddLayer(plethy); //new gLineChart(OXI_Plethysomogram)); @@ -290,7 +287,7 @@ void Oximetry::on_RunButton_toggled(bool checked) sess->eventlist[OXI_SPO2].push_back(ev_spo2); sess->eventlist[OXI_Pulse].push_back(ev_pulse); - sess->eventlist[OXI_Plethysomogram].push_back(ev_plethy); + sess->eventlist[OXI_Plethy].push_back(ev_plethy); //Session *sess=session; sess->SetSessionID(starttime/1000L); @@ -310,36 +307,31 @@ void Oximetry::on_RunButton_toggled(bool checked) sess->wavg(OXI_SPO2); sess->p90(OXI_SPO2); - sess->avg(OXI_Plethysomogram); - sess->wavg(OXI_Plethysomogram); - sess->p90(OXI_Plethysomogram); - sess->setMin(OXI_Plethysomogram,ev_plethy->min()); - sess->setMax(OXI_Plethysomogram,ev_plethy->max()); + sess->avg(OXI_Plethy); + sess->wavg(OXI_Plethy); + sess->p90(OXI_Plethy); + sess->setMin(OXI_Plethy,ev_plethy->min()); + sess->setMax(OXI_Plethy,ev_plethy->max()); - sess->setFirst(OXI_Plethysomogram,ev_plethy->first()); - sess->setLast(OXI_Plethysomogram,ev_plethy->last()); + sess->setFirst(OXI_Plethy,ev_plethy->first()); + sess->setLast(OXI_Plethy,ev_plethy->last()); sess->updateFirst(sess->first(OXI_Pulse)); sess->updateLast(sess->last(OXI_Pulse)); sess->updateFirst(sess->first(OXI_SPO2)); sess->updateLast(sess->last(OXI_SPO2)); - sess->updateFirst(sess->first(OXI_Plethysomogram)); - sess->updateLast(sess->last(OXI_Plethysomogram)); + sess->updateFirst(sess->first(OXI_Plethy)); + sess->updateLast(sess->last(OXI_Plethy)); sess->SetChanged(true); mach->AddSession(sess,profile); mach->Save(); - ev_plethy=new EventList(OXI_Plethysomogram,EVL_Waveform,1,0,0,0,1000.0/50.0); - session->eventlist[OXI_Plethysomogram].push_back(ev_plethy); + ev_plethy=session->AddEventList(OXI_Plethy,EVL_Waveform,1,0,0,0,1000.0/50.0); + ev_pulse=session->AddEventList(OXI_Pulse,EVL_Event,1); + ev_spo2=session->AddEventList(OXI_SPO2,EVL_Event,1); - ev_pulse=new EventList(OXI_Pulse,EVL_Event,1); - session->eventlist[OXI_Pulse].push_back(ev_pulse); - - ev_spo2=new EventList(OXI_SPO2,EVL_Event,1); - session->eventlist[OXI_SPO2].push_back(ev_spo2); - - session->setCount(OXI_Plethysomogram,0); + session->setCount(OXI_Plethy,0); session->setCount(OXI_Pulse,0); session->setCount(OXI_SPO2,0); @@ -367,7 +359,7 @@ void Oximetry::UpdatePlethy(qint8 d) if (d>ev_plethy->max()) ev_plethy->setMax(d); int i=ev_plethy->count()+1; ev_plethy->setCount(i); - session->setCount(OXI_Plethysomogram,i); // update the cache + session->setCount(OXI_Plethy,i); // update the cache //ev_plethy->AddEvent(lasttime,d); lasttime+=20; // 50 samples per second PLETHY->SetMinY(ev_plethy->min()); @@ -679,8 +671,7 @@ void Oximetry::on_ImportButton_clicked() int drop=max-min; if (drop>6) { if (!oxf1) { - oxf1=new EventList(OXI_PulseChange,EVL_Event); - session->eventlist[OXI_PulseChange].push_back(oxf1); + oxf1=session->AddEventList(OXI_PulseChange,EVL_Event); } oxf1->AddEvent(tt,drop); } @@ -696,15 +687,12 @@ void Oximetry::on_ImportButton_clicked() int drop=max-min; if (drop>4) { if (!oxf1) { - oxf2=new EventList(OXI_SPO2Drop,EVL_Event); - session->eventlist[OXI_SPO2Drop].push_back(oxf2); + oxf2=session->AddEventList(OXI_SPO2Drop,EVL_Event); } oxf2->AddEvent(tt,drop); } } - - ++rb_pos; rb_pos=rb_pos % rb_size; @@ -743,14 +731,11 @@ void Oximetry::on_ImportButton_clicked() day->AddSession(session); // As did these - ev_plethy=new EventList(OXI_Plethysomogram,EVL_Waveform,1,0,0,0,1000.0/50.0); - session->eventlist[OXI_Plethysomogram].push_back(ev_plethy); + ev_plethy=session->AddEventList(OXI_Plethy,EVL_Waveform,1,0,0,0,1000.0/50.0); - ev_pulse=new EventList(OXI_Pulse,EVL_Event,1); - session->eventlist[OXI_Pulse].push_back(ev_pulse); + ev_pulse=session->AddEventList(OXI_Pulse,EVL_Event,1); - ev_spo2=new EventList(OXI_SPO2,EVL_Event,1); - session->eventlist[OXI_SPO2].push_back(ev_spo2); + ev_spo2=session->AddEventList(OXI_SPO2,EVL_Event,1); } delete port; port=NULL; diff --git a/preferencesdialog.cpp b/preferencesdialog.cpp index d92beacf..6f1cadc2 100644 --- a/preferencesdialog.cpp +++ b/preferencesdialog.cpp @@ -84,11 +84,11 @@ PreferencesDialog::PreferencesDialog(QWidget *parent,Profile * _profile) : ui->eventTable->setColumnWidth(1,55); int row=0; QTableWidgetItem *item; - QHash::iterator ci; - for (ci=channel.begin();ci!=channel.end();ci++) { - if ((ci.value().channeltype()==CT_Event) || (ci.value().channeltype()==CT_Graph)) { + QHash::iterator ci; + for (ci=schema::channel.names.begin();ci!=schema::channel.names.end();ci++) { + if (ci.value()->type()==schema::DATA) { ui->eventTable->insertRow(row); - item=new QTableWidgetItem(ci.value().details()); + item=new QTableWidgetItem(ci.value()->description()); ui->eventTable->setItem(row,2,item); QCheckBox *c=new QCheckBox(ui->eventTable); c->setChecked(true);