mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-08 20:20:44 +00:00
CMS50 Oximeter Loader and basic Graphs
This commit is contained in:
parent
314be4fbbc
commit
43e0f512b1
@ -73,6 +73,10 @@
|
||||
<Unit filename="../../src/graphs/graph.h" />
|
||||
<Unit filename="../../src/libs/sleeplib/binary_file.cpp" />
|
||||
<Unit filename="../../src/libs/sleeplib/binary_file.h" />
|
||||
<Unit filename="../../src/libs/sleeplib/loader_plugins/cms50_loader.cpp" />
|
||||
<Unit filename="../../src/libs/sleeplib/loader_plugins/cms50_loader.h" />
|
||||
<Unit filename="../../src/libs/sleeplib/loader_plugins/zeo_loader.cpp" />
|
||||
<Unit filename="../../src/libs/sleeplib/loader_plugins/zeo_loader.h" />
|
||||
<Unit filename="../../src/libs/sleeplib/machine.cpp" />
|
||||
<Unit filename="../../src/libs/sleeplib/machine.h" />
|
||||
<Unit filename="../../src/libs/sleeplib/machine_loader.cpp" />
|
||||
|
@ -8249,7 +8249,7 @@
|
||||
1307245704 /home/mark/projects/git/sleepyhead/src/SleepyHeadApp.h
|
||||
<wx/app.h>
|
||||
|
||||
1307245704 /home/mark/projects/git/sleepyhead/src/SleepyHeadMain.h
|
||||
1307291151 /home/mark/projects/git/sleepyhead/src/SleepyHeadMain.h
|
||||
<wx/listbox.h>
|
||||
<wx/treectrl.h>
|
||||
"SleepyHeadApp.h"
|
||||
@ -8257,7 +8257,7 @@
|
||||
"sleeplib/machine.h"
|
||||
"graphs/graph.h"
|
||||
|
||||
1307272411 /home/mark/projects/git/sleepyhead/src/libs/sleeplib/machine.h
|
||||
1307289735 /home/mark/projects/git/sleepyhead/src/libs/sleeplib/machine.h
|
||||
<wx/string.h>
|
||||
<wx/variant.h>
|
||||
<wx/dir.h>
|
||||
@ -8291,7 +8291,7 @@
|
||||
<map>
|
||||
"tinyxml/tinyxml.h"
|
||||
|
||||
1307245704 /home/mark/projects/git/sleepyhead/src/graphs/graph.h
|
||||
1307290670 /home/mark/projects/git/sleepyhead/src/graphs/graph.h
|
||||
<sleeplib/machine.h>
|
||||
<list>
|
||||
|
||||
@ -8312,7 +8312,7 @@
|
||||
"preferences.h"
|
||||
"tinyxml/tinyxml.h"
|
||||
|
||||
1307252474 source:/home/mark/projects/git/sleepyhead/src/SleepyHeadMain.cpp
|
||||
1307292874 source:/home/mark/projects/git/sleepyhead/src/SleepyHeadMain.cpp
|
||||
"wx_pch.h"
|
||||
"version.h"
|
||||
<wx/app.h>
|
||||
@ -8331,7 +8331,7 @@
|
||||
"sleeplib/profiles.h"
|
||||
"sleeplib/machine_loader.h"
|
||||
|
||||
1307245704 source:/home/mark/projects/git/sleepyhead/src/graphs/graph.cpp
|
||||
1307290767 source:/home/mark/projects/git/sleepyhead/src/graphs/graph.cpp
|
||||
<wx/settings.h>
|
||||
<wx/dcbuffer.h>
|
||||
<wx/log.h>
|
||||
@ -8346,7 +8346,7 @@
|
||||
<wx/ffile.h>
|
||||
<wx/utils.h>
|
||||
|
||||
1307245704 source:/home/mark/projects/git/sleepyhead/src/libs/sleeplib/machine.cpp
|
||||
1307289238 source:/home/mark/projects/git/sleepyhead/src/libs/sleeplib/machine.cpp
|
||||
<tr1/random>
|
||||
<wx/colour.h>
|
||||
<wx/log.h>
|
||||
@ -8409,14 +8409,20 @@
|
||||
"tinyxml.h"
|
||||
<windows.h>
|
||||
|
||||
1307274777 /home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/cms50_loader.h
|
||||
1307287644 /home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/cms50_loader.h
|
||||
"sleeplib/machine_loader.h"
|
||||
|
||||
1307275420 source:/home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/cms50_loader.cpp
|
||||
1307289931 source:/home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/cms50_loader.cpp
|
||||
<wx/log.h>
|
||||
<wx/progdlg.h>
|
||||
"cms50_loader.h"
|
||||
"sleeplib/machine.h"
|
||||
|
||||
1307275207 /home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/zeo_loader.h
|
||||
"sleeplib/machine_loader.h"
|
||||
|
||||
1307275410 source:/home/mark/projects/git/sleepyhead/src/libs/sleeplib/loader_plugins/zeo_loader.cpp
|
||||
<wx/log.h>
|
||||
"zeo_loader.h"
|
||||
"sleeplib/machine.h"
|
||||
|
||||
|
@ -2,12 +2,33 @@
|
||||
<CodeBlocks_layout_file>
|
||||
<ActiveTarget name="Debug" />
|
||||
<File name="../../src/SleepyHeadApp.cpp" open="1" top="0" tabpos="1">
|
||||
<Cursor position="781" topLine="0" />
|
||||
<Cursor position="781" topLine="2" />
|
||||
</File>
|
||||
<File name="../../src/SleepyHeadMain.cpp" open="1" top="1" tabpos="2">
|
||||
<Cursor position="5611" topLine="196" />
|
||||
<File name="../../src/SleepyHeadMain.cpp" open="1" top="0" tabpos="2">
|
||||
<Cursor position="35342" topLine="822" />
|
||||
</File>
|
||||
<File name="../../src/SleepyHeadMain.h" open="1" top="0" tabpos="3">
|
||||
<Cursor position="546" topLine="0" />
|
||||
<Cursor position="1968" topLine="43" />
|
||||
</File>
|
||||
<File name="../../src/graphs/graph.cpp" open="1" top="0" tabpos="8">
|
||||
<Cursor position="42531" topLine="1608" />
|
||||
</File>
|
||||
<File name="../../src/graphs/graph.h" open="1" top="0" tabpos="11">
|
||||
<Cursor position="15591" topLine="437" />
|
||||
</File>
|
||||
<File name="../../src/libs/sleeplib/loader_plugins/cms50_loader.cpp" open="1" top="1" tabpos="4">
|
||||
<Cursor position="4412" topLine="127" />
|
||||
</File>
|
||||
<File name="../../src/libs/sleeplib/loader_plugins/cms50_loader.h" open="1" top="0" tabpos="7">
|
||||
<Cursor position="579" topLine="0" />
|
||||
</File>
|
||||
<File name="../../src/libs/sleeplib/machine.cpp" open="1" top="0" tabpos="9">
|
||||
<Cursor position="25229" topLine="825" />
|
||||
</File>
|
||||
<File name="../../src/libs/sleeplib/machine.h" open="1" top="0" tabpos="5">
|
||||
<Cursor position="2133" topLine="25" />
|
||||
</File>
|
||||
<File name="../../src/libs/sleeplib/prs1_loader.cpp" open="1" top="0" tabpos="6">
|
||||
<Cursor position="23295" topLine="610" />
|
||||
</File>
|
||||
</CodeBlocks_layout_file>
|
||||
|
@ -541,9 +541,9 @@ Daily::Daily(wxWindow *win,Profile *p)
|
||||
this->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( Daily::OnEventTreeSelection), NULL, this);
|
||||
Notebook->AddPage(HTMLInfo,wxT("Details"),false,NULL);
|
||||
Notebook->AddPage(EventTree,wxT("Events"),false,NULL);
|
||||
AddData(tap_eap=new TAPData(CPAP_EAP));
|
||||
AddData(tap_iap=new TAPData(CPAP_IAP));
|
||||
AddData(tap=new TAPData(CPAP_Pressure));
|
||||
AddCPAPData(tap_eap=new TAPData(CPAP_EAP));
|
||||
AddCPAPData(tap_iap=new TAPData(CPAP_IAP));
|
||||
AddCPAPData(tap=new TAPData(CPAP_Pressure));
|
||||
|
||||
TAP=new gGraphWindow(ScrolledWindow,-1,wxT("Time@Pressure"),wxPoint(0,0), wxSize(600,60), wxNO_BORDER);
|
||||
TAP->SetMargins(20,15,5,50);
|
||||
@ -559,7 +559,7 @@ Daily::Daily(wxWindow *win,Profile *p)
|
||||
|
||||
G_AHI=new gGraphWindow(ScrolledWindow,-1,wxT("Event Breakdown"),wxPoint(0,0), wxSize(600,60), wxNO_BORDER);
|
||||
G_AHI->SetMargins(20,15,5,50);
|
||||
AddData(g_ahi=new AHIData());
|
||||
AddCPAPData(g_ahi=new AHIData());
|
||||
gCandleStick *l=new gCandleStick(g_ahi);
|
||||
l->AddName(wxT("H"));
|
||||
l->AddName(wxT("OA"));
|
||||
@ -576,37 +576,53 @@ Daily::Daily(wxWindow *win,Profile *p)
|
||||
l->color.push_back(wxGREEN2);
|
||||
G_AHI->AddLayer(l);
|
||||
|
||||
AddData(leakdata=new PressureData(CPAP_Leak,0));
|
||||
AddCPAPData(leakdata=new PressureData(CPAP_Leak,0));
|
||||
//leakdata->ForceMinY(0);
|
||||
//leakdata->ForceMaxY(120);
|
||||
|
||||
AddOXIData(pulse=new PressureData(OXI_Pulse,0,32768));
|
||||
pulse->ForceMinY(40);
|
||||
pulse->ForceMaxY(120);
|
||||
|
||||
PULSE=new gGraphWindow(ScrolledWindow,-1,wxT("Pulse"),wxPoint(0,0), wxSize(600,130), wxNO_BORDER);
|
||||
PULSE->AddLayer(new gLineChart(pulse,wxRED,32768,false,false,true));
|
||||
PULSE->AddLayer(new gXAxis(wxBLACK));
|
||||
|
||||
AddOXIData(spo2=new PressureData(OXI_SPO2,0,32768));
|
||||
spo2->ForceMinY(60);
|
||||
spo2->ForceMaxY(100);
|
||||
SPO2=new gGraphWindow(ScrolledWindow,-1,wxT("SpO2"),wxPoint(0,0), wxSize(600,130), wxNO_BORDER);
|
||||
SPO2->AddLayer(new gLineChart(spo2,wxBLUE,32768,false,false,true));
|
||||
SPO2->AddLayer(new gXAxis(wxBLACK));
|
||||
SPO2->LinkZoom(PULSE);
|
||||
PULSE->LinkZoom(SPO2);
|
||||
|
||||
LEAK=new gGraphWindow(ScrolledWindow,-1,wxT("Mask Leaks"),wxPoint(0,0), wxSize(600,130), wxNO_BORDER);
|
||||
LEAK->AddLayer(new gLineChart(leakdata,wxPURPLE,4096,false,false,true));
|
||||
LEAK->AddLayer(new gXAxis(wxBLACK));
|
||||
|
||||
AddData(pressure_iap=new PressureData(CPAP_IAP));
|
||||
AddData(pressure_eap=new PressureData(CPAP_EAP));
|
||||
AddData(prd=new PressureData(CPAP_Pressure));
|
||||
AddCPAPData(pressure_iap=new PressureData(CPAP_IAP));
|
||||
AddCPAPData(pressure_eap=new PressureData(CPAP_EAP));
|
||||
AddCPAPData(prd=new PressureData(CPAP_Pressure));
|
||||
PRD=new gGraphWindow(ScrolledWindow,-1,wxT("Pressure"),wxPoint(0,0), wxSize(600,130), wxNO_BORDER);
|
||||
PRD->AddLayer(new gLineChart(prd,wxDARK_GREEN,4096,false,false,true));
|
||||
PRD->AddLayer(new gLineChart(pressure_iap,wxBLUE,4096,false,true,true));
|
||||
PRD->AddLayer(new gLineChart(pressure_eap,wxRED,4096,false,true,true));
|
||||
PRD->AddLayer(new gXAxis(wxBLACK));
|
||||
|
||||
AddData(frw=new FlowData());
|
||||
AddCPAPData(frw=new FlowData());
|
||||
FRW=new gGraphWindow(ScrolledWindow,-1,wxT("Flow Rate"),wxPoint(0,0), wxSize(600,150), wxNO_BORDER);
|
||||
|
||||
AddData(flags[0]=new FlagData(CPAP_CSR,7,1,0));
|
||||
AddData(flags[1]=new FlagData(CPAP_ClearAirway,6));
|
||||
AddData(flags[2]=new FlagData(CPAP_Obstructive,5));
|
||||
AddData(flags[3]=new FlagData(CPAP_Hypopnea,4));
|
||||
AddData(flags[4]=new FlagData(CPAP_FlowLimit,3));
|
||||
AddData(flags[5]=new FlagData(CPAP_VSnore,2));
|
||||
AddData(flags[6]=new FlagData(CPAP_RERA,1));
|
||||
AddData(flags[7]=new FlagData(PRS1_PressurePulse,1));
|
||||
AddData(flags[8]=new FlagData(PRS1_VSnore2,1));
|
||||
AddData(flags[9]=new FlagData(PRS1_Unknown0E,1));
|
||||
AddCPAPData(flags[0]=new FlagData(CPAP_CSR,7,1,0));
|
||||
AddCPAPData(flags[1]=new FlagData(CPAP_ClearAirway,6));
|
||||
AddCPAPData(flags[2]=new FlagData(CPAP_Obstructive,5));
|
||||
AddCPAPData(flags[3]=new FlagData(CPAP_Hypopnea,4));
|
||||
AddCPAPData(flags[4]=new FlagData(CPAP_FlowLimit,3));
|
||||
AddCPAPData(flags[5]=new FlagData(CPAP_VSnore,2));
|
||||
AddCPAPData(flags[6]=new FlagData(CPAP_RERA,1));
|
||||
AddCPAPData(flags[7]=new FlagData(PRS1_PressurePulse,1));
|
||||
AddCPAPData(flags[8]=new FlagData(PRS1_VSnore2,1));
|
||||
AddCPAPData(flags[9]=new FlagData(PRS1_Unknown0E,1));
|
||||
|
||||
FRW->AddLayer(new gLineOverlayBar(flags[0],wxGREEN2,wxT("CSR")));
|
||||
FRW->AddLayer(new gLineChart(frw,wxBLACK,200000,true));
|
||||
@ -646,6 +662,8 @@ Daily::Daily(wxWindow *win,Profile *p)
|
||||
|
||||
fgSizer->Add(SF,1,wxEXPAND);
|
||||
fgSizer->Add(FRW,1,wxEXPAND);
|
||||
fgSizer->Add(PULSE,1,wxEXPAND);
|
||||
fgSizer->Add(SPO2,1,wxEXPAND);
|
||||
fgSizer->Add(PRD,1,wxEXPAND);
|
||||
fgSizer->Add(LEAK,1,wxEXPAND);
|
||||
fgSizer->Add(G_AHI,1,wxEXPAND);
|
||||
@ -704,18 +722,22 @@ void Daily::RefreshData()
|
||||
date-=wxTimeSpan::Days(1);
|
||||
|
||||
Day *d=NULL;
|
||||
Day *oxi=NULL;
|
||||
if (profile->daylist.find(date)!=profile->daylist.end()) {
|
||||
vector<Day *>::iterator di;
|
||||
for (di=profile->daylist[date].begin();di!=profile->daylist[date].end();di++) {
|
||||
if ((*di)->machine_type()==MT_CPAP) {
|
||||
if (!d && ((*di)->machine_type()==MT_CPAP)) {
|
||||
d=(*di);
|
||||
break;
|
||||
UpdateCPAPGraphs(d);
|
||||
}
|
||||
if ((*di)->machine_type()==MT_OXIMETER) {
|
||||
oxi=(*di);
|
||||
UpdateOXIGraphs(oxi);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGraphs(d);
|
||||
if (d) {
|
||||
CPAPMode mode=(CPAPMode)d->summary_max(CPAP_Mode);
|
||||
if (mode!=MODE_BIPAP) {
|
||||
@ -765,8 +787,6 @@ void Daily::RefreshData()
|
||||
EventTree->SortChildren(root);
|
||||
EventTree->Expand(root);
|
||||
|
||||
fgSizer->Layout();
|
||||
ScrolledWindow->FitInside();
|
||||
|
||||
PRTypes pr=(PRTypes)d->summary_max(CPAP_PressureReliefType);
|
||||
wxString epr=PressureReliefNames[pr]+wxString::Format(wxT(" x%i"),(int)d->summary_max(CPAP_PressureReliefSetting));
|
||||
@ -834,6 +854,25 @@ void Daily::RefreshData()
|
||||
|
||||
}
|
||||
html=html+wxT("<tr><td><b>")+_("Avg Leak")+wxT("</b></td><td>")+wxString::Format(wxT("%.2f"),d->summary_weighted_avg(CPAP_LeakAverage))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td> </td><td> </td></tr>\n");
|
||||
|
||||
if (oxi) {
|
||||
html=html+wxT("<tr><td colspan=2 align=center><i>")+_("Oximeter Information")+wxT("</i></td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("Pulse Avg")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_avg(OXI_PulseAverage))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("Pulse Min")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_min(OXI_PulseMin))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("Pulse Max")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_max(OXI_PulseMax))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("SpO2 Avg")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_avg(OXI_SPO2Average))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("SpO2 Min")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_min(OXI_SPO2Min))+wxT("</td></tr>\n");
|
||||
html=html+wxT("<tr><td><b>")+_("SpO2 Max")+wxT("</b></td><td>")+wxString::Format(wxT("%.1fcmH2O"),d->summary_max(OXI_SPO2Max))+wxT("</td></tr>\n");
|
||||
PULSE->Show(true);
|
||||
SPO2->Show(true);
|
||||
} else {
|
||||
PULSE->Show(false);
|
||||
SPO2->Show(false);
|
||||
}
|
||||
fgSizer->Layout();
|
||||
// fgSizer->Layout();
|
||||
ScrolledWindow->FitInside();
|
||||
|
||||
html=html+wxT("<tr><td> </td><td> </td></tr>\n");
|
||||
|
||||
@ -906,18 +945,31 @@ void Daily::OnCalendarDay( wxCalendarEvent& event )
|
||||
}
|
||||
RefreshData();
|
||||
}
|
||||
void Daily::UpdateGraphs(Day *day)
|
||||
void Daily::UpdateCPAPGraphs(Day *day)
|
||||
{
|
||||
//if (!day) return;
|
||||
if (day) {
|
||||
day->OpenEvents();
|
||||
day->OpenWaveforms();
|
||||
}
|
||||
for (list<gPointData *>::iterator g=Data.begin();g!=Data.end();g++) {
|
||||
for (list<gPointData *>::iterator g=CPAPData.begin();g!=CPAPData.end();g++) {
|
||||
(*g)->Update(day);
|
||||
}
|
||||
};
|
||||
|
||||
void Daily::UpdateOXIGraphs(Day *day)
|
||||
{
|
||||
//if (!day) return;
|
||||
if (day) {
|
||||
day->OpenEvents();
|
||||
day->OpenWaveforms();
|
||||
}
|
||||
for (list<gPointData *>::iterator g=OXIData.begin();g!=OXIData.end();g++) {
|
||||
(*g)->Update(day);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Daily::OnCalendarMonth( wxCalendarEvent& event )
|
||||
{
|
||||
wxDateTime et=event.GetDate();
|
||||
|
@ -66,16 +66,20 @@ protected:
|
||||
virtual void OnSelectSession( wxCommandEvent& event );
|
||||
virtual void OnEventTreeSelection( wxTreeEvent& event );
|
||||
|
||||
void AddData(gPointData *d) { Data.push_back(d); };
|
||||
void UpdateGraphs(Day *day);
|
||||
void AddCPAPData(gPointData *d) { CPAPData.push_back(d); };
|
||||
void AddOXIData(gPointData *d) { OXIData.push_back(d); };
|
||||
void UpdateCPAPGraphs(Day *day);
|
||||
void UpdateOXIGraphs(Day *day);
|
||||
|
||||
bool foobar_datehack;
|
||||
gPointData *tap,*tap_eap,*tap_iap,*g_ahi,*frw,*prd,*leakdata,*pressure_iap,*pressure_eap;
|
||||
gPointData *pulse,*spo2;
|
||||
gPointData *flags[10];
|
||||
gGraphWindow *PRD,*FRW,*G_AHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP;
|
||||
gGraphWindow *PRD,*FRW,*G_AHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2;
|
||||
|
||||
Profile *profile;
|
||||
list<gPointData *> Data;
|
||||
list<gPointData *> OXIData;
|
||||
list<gPointData *> CPAPData;
|
||||
wxHtmlWindow *HTMLInfo;
|
||||
wxTreeCtrl *EventTree;
|
||||
|
||||
|
@ -1602,8 +1602,8 @@ void FlowData::Reload(Day *day)
|
||||
//graph->Refresh(false);
|
||||
}
|
||||
|
||||
PressureData::PressureData(MachineCode _code,int _field)
|
||||
:gPointData(1024),code(_code),field(_field)
|
||||
PressureData::PressureData(MachineCode _code,int _field,int _size)
|
||||
:gPointData(_size),code(_code),field(_field)
|
||||
{
|
||||
}
|
||||
PressureData::~PressureData()
|
||||
@ -1616,6 +1616,7 @@ void PressureData::Reload(Day *day)
|
||||
m_ready=false;
|
||||
return;
|
||||
}
|
||||
|
||||
min_x=day->first().GetMJD();
|
||||
max_x=day->last().GetMJD();
|
||||
assert(min_x<max_x);
|
||||
|
@ -468,7 +468,7 @@ public:
|
||||
class PressureData:public gPointData
|
||||
{
|
||||
public:
|
||||
PressureData(MachineCode _code,int _field=0);
|
||||
PressureData(MachineCode _code,int _field=0,int _size=4096);
|
||||
virtual ~PressureData();
|
||||
virtual void Reload(Day *day=NULL);
|
||||
protected:
|
||||
|
@ -6,9 +6,12 @@ License: GPL
|
||||
*/
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include "cms50_loader.h"
|
||||
#include "sleeplib/machine.h"
|
||||
|
||||
extern wxProgressDialog *loader_progress;
|
||||
|
||||
CMS50Loader::CMS50Loader()
|
||||
{
|
||||
//ctor
|
||||
@ -25,8 +28,154 @@ bool CMS50Loader::Open(wxString & path,Profile *profile)
|
||||
// Not sure whether to both supporting SpO2 files here, as the timestamps are utterly useless for overlay purposes.
|
||||
// May just ignore the crap and support my CMS50 logger
|
||||
|
||||
// Contains three files
|
||||
// Data Folder
|
||||
// SpO2 Review.ini
|
||||
// SpO2.ini
|
||||
|
||||
wxString tmp=path+wxFileName::GetPathSeparator()+wxT("Data");
|
||||
if ((wxFileExists(path+wxFileName::GetPathSeparator()+wxT("SpO2 Review.ini")))
|
||||
&& (wxFileExists(path+wxFileName::GetPathSeparator()+wxT("SpO2.ini")))
|
||||
&& (wxDirExists(tmp))) {
|
||||
// Their software
|
||||
|
||||
return OpenCMS50(tmp,profile);
|
||||
} else {
|
||||
// My Logger
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool CMS50Loader::OpenCMS50(wxString & path, Profile *profile)
|
||||
{
|
||||
wxDir dir;
|
||||
if (!dir.Open(path)) return false;
|
||||
list<wxString> files;
|
||||
|
||||
wxString filename,pathname;
|
||||
|
||||
bool cont=dir.GetFirst(&filename);
|
||||
|
||||
while (cont) {
|
||||
if (filename.EndsWith(wxT(".spoR"))) {
|
||||
pathname=path+wxFileName::GetPathSeparator()+filename;
|
||||
files.push_back(pathname);
|
||||
}
|
||||
cont=dir.GetNext(&filename);
|
||||
}
|
||||
int size=files.size();
|
||||
if (size==0) return false;
|
||||
|
||||
Machine *mach=CreateMachine(profile);
|
||||
int cnt=0;
|
||||
for (list<wxString>::iterator n=files.begin();n!=files.end();n++,++cnt) {
|
||||
if (loader_progress) loader_progress->Update((float(cnt)/float(size)*100.0));
|
||||
OpenSPORFile((*n),mach,profile);
|
||||
}
|
||||
mach->Save();
|
||||
return true;
|
||||
}
|
||||
bool CMS50Loader::OpenSPORFile(wxString path,Machine *mach,Profile *profile)
|
||||
{
|
||||
wxFFile f;
|
||||
unsigned char tmp[256];
|
||||
if (!f.Open(path,wxT("rb"))) return false;
|
||||
|
||||
wxString str=path.AfterLast(wxChar('_'));
|
||||
wxString id=str.BeforeFirst(wxChar('.'));
|
||||
wxDateTime dt;
|
||||
dt.ParseFormat(id,wxT("%Y%m%d%H%M"));
|
||||
|
||||
SessionID sessid=dt.GetTicks(); // Import date becomes session id
|
||||
|
||||
if (mach->SessionExists(sessid))
|
||||
return false; // Already imported
|
||||
|
||||
// Find everything after the last _
|
||||
short data_starts;
|
||||
short some_code;
|
||||
int num_records;
|
||||
short some_more_code;
|
||||
int br;
|
||||
|
||||
|
||||
|
||||
f.Read(tmp,2);
|
||||
data_starts=tmp[0] | (tmp[1] << 8);
|
||||
f.Read(tmp,2);
|
||||
some_code=tmp[0] | (tmp[1] << 8); // == 512
|
||||
f.Read(tmp,2);
|
||||
num_records=tmp[0] | (tmp[1] << 8);
|
||||
num_records <<= 1;
|
||||
|
||||
f.Read(tmp,2);
|
||||
some_more_code=tmp[0] | (tmp[1] << 8); // == 512
|
||||
|
||||
f.Read(tmp,16);
|
||||
|
||||
wxString datestr;
|
||||
for (int i=0;i<16;i+=2) {
|
||||
datestr=datestr+tmp[i];
|
||||
}
|
||||
wxDateTime date;
|
||||
date.ParseFormat(datestr,wxT("%m/%d/%y"));
|
||||
|
||||
|
||||
f.Seek(data_starts,wxFromStart);
|
||||
buffer=new char [num_records*2];
|
||||
br=f.Read(buffer,num_records);
|
||||
if (br!=num_records) {
|
||||
wxLogDebug(wxT("Short .spoR File: ")+path);
|
||||
}
|
||||
char last_pulse=buffer[0];
|
||||
char last_spo2=buffer[1];
|
||||
EventDataType data[2];
|
||||
wxDateTime last_pulse_time=date;
|
||||
wxDateTime last_spo2_time=date;
|
||||
data[0]=last_pulse;
|
||||
data[1]=last_spo2;
|
||||
|
||||
Session *sess=new Session(mach,sessid);
|
||||
sess->set_first(date);
|
||||
sess->AddEvent(new Event(date,OXI_Pulse,data,1));
|
||||
sess->AddEvent(new Event(date,OXI_SPO2,&data[1],1));
|
||||
//wxDateTime
|
||||
wxDateTime tt=date;
|
||||
for (int i=2;i<num_records;i+=2) {
|
||||
if (last_pulse!=buffer[i]) {
|
||||
data[0]=buffer[i];
|
||||
sess->AddEvent(new Event(tt,OXI_Pulse,data,1));
|
||||
}
|
||||
if (last_spo2!=buffer[i+1]) {
|
||||
data[1]=buffer[i+1];
|
||||
sess->AddEvent(new Event(tt,OXI_SPO2,&data[1],1));
|
||||
}
|
||||
last_pulse=buffer[i];
|
||||
last_spo2=buffer[i+1];
|
||||
tt+=wxTimeSpan::Seconds(1);
|
||||
}
|
||||
sess->AddEvent(new Event(tt,OXI_Pulse,data,1));
|
||||
sess->AddEvent(new Event(tt,OXI_SPO2,&data[1],1));
|
||||
|
||||
sess->set_last(tt);
|
||||
wxTimeSpan t=sess->last()-sess->first();
|
||||
|
||||
double hours=(t.GetSeconds().GetLo()/3600.0);
|
||||
sess->set_hours(hours);
|
||||
|
||||
sess->summary[OXI_PulseAverage]=sess->weighted_avg_event_field(OXI_Pulse,0);
|
||||
sess->summary[OXI_PulseMin]=sess->min_event_field(OXI_Pulse,0);
|
||||
sess->summary[OXI_PulseMax]=sess->max_event_field(OXI_Pulse,0);
|
||||
sess->summary[OXI_SPO2Average]=sess->weighted_avg_event_field(OXI_SPO2,0);
|
||||
sess->summary[OXI_SPO2Min]=sess->min_event_field(OXI_SPO2,0);
|
||||
sess->summary[OXI_SPO2Max]=sess->max_event_field(OXI_SPO2,0);
|
||||
|
||||
mach->AddSession(sess,profile);
|
||||
sess->SetChanged(true);
|
||||
delete buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
Machine *CMS50Loader::CreateMachine(Profile *profile)
|
||||
{
|
||||
if (!profile) { // shouldn't happen..
|
||||
|
@ -22,7 +22,11 @@ class CMS50Loader : public MachineLoader
|
||||
Machine *CreateMachine(Profile *profile);
|
||||
|
||||
protected:
|
||||
bool OpenCMS50(wxString & path, Profile *profile);
|
||||
bool OpenSPORFile(wxString path, Machine * machine,Profile *profile);
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
#endif // CMS50LOADER_H
|
||||
|
@ -907,7 +907,7 @@ void Session::AddEvent(Event * e)
|
||||
{
|
||||
events[e->code()].push_back(e);
|
||||
if (e->time()>s_last) s_last=e->time();
|
||||
// wxLogMessage(e->time().Format(wxT("%Y-%m-%d %H:%M:%S"))+wxString::Format(wxT(" %04i %02i "),e->code(),e->fields()));
|
||||
// wxLogMessage(e->time().Format(wxT("%Y-%m-%d %H:%M:%S"))+wxString::Format(wxT(" %04i %02i "),e->code(),e->fields()));
|
||||
}
|
||||
void Session::AddWaveform(Waveform *w)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ enum MachineCode//:wxInt16
|
||||
PRS1_SystemLockStatus, PRS1_SystemResistanceStatus, PRS1_SystemResistanceSetting, PRS1_HoseDiameter, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI,
|
||||
|
||||
// Oximeter Codes
|
||||
OXI_Pulse=0x2000, OXI_SpO2, OXI_Plethy, OXI_Signal2, OXI_SignalGood,
|
||||
OXI_Pulse=0x2000, OXI_SPO2, OXI_Plethy, OXI_Signal2, OXI_SignalGood, OXI_PulseAverage, OXI_PulseMin, OXI_PulseMax, OXI_SPO2Average, OXI_SPO2Min, OXI_SPO2Max,
|
||||
|
||||
ZEO_SleepStage=0x2800, ZEO_Waveform,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user