Start of Oximetry rework

This commit is contained in:
Mark Watkins 2011-07-30 00:58:44 +10:00
parent e3fdfcb313
commit 20a5fbd5e2
17 changed files with 279 additions and 281 deletions

View File

@ -11,8 +11,8 @@
#include "gLineChart.h"
#define EXTRA_ASSERTS 1
gLineChart::gLineChart(MachineCode code,QColor col,bool _square_plot)
:gLayer(code),m_square_plot(_square_plot)
gLineChart::gLineChart(MachineCode code,QColor col,bool square_plot, bool disable_accel)
:gLayer(code),m_square_plot(square_plot),m_disable_accel(disable_accel)
{
color.clear();
color.push_back(col);
@ -135,7 +135,8 @@ void gLineChart::Plot(gGraphWindow & w,float scrx,float scry)
for (unsigned n=0;n<evec.size();n++) { // for each segment
EventList & el=*evec[n];
accel=el.type()==EVL_Waveform; // Turn on acceleration if this is a waveform.
accel=!m_disable_accel && (el.type()==EVL_Waveform); // Turn on acceleration if this is a waveform.
square_plot=m_square_plot;
if (accel || num_points>500) { // Don't square plot if too many points or waveform
@ -166,7 +167,6 @@ void gLineChart::Plot(gGraphWindow & w,float scrx,float scry)
//assert(x1<x2);
}
}
if (accel) {
x1=el.time(1);
sr=el.rate(); // Time distance between samples

View File

@ -16,7 +16,7 @@
class gLineChart:public gLayer
{
public:
gLineChart(MachineCode code,const QColor col=QColor("black"), bool _square_plot=false);
gLineChart(MachineCode code,const QColor col=QColor("black"), bool square_plot=false,bool disable_accel=false);
virtual ~gLineChart();
virtual void Plot(gGraphWindow & w,float scrx,float scry);
@ -25,10 +25,12 @@ class gLineChart:public gLayer
bool GetSquarePlot() { return m_square_plot; }
void ReportEmpty(bool b) { m_report_empty=b; }
bool GetReportEmpty() { return m_report_empty; }
void setDisableAccel(bool b) { m_disable_accel=b; }
bool disableAccel() { return m_disable_accel; }
protected:
bool m_report_empty;
bool m_square_plot;
bool m_disable_accel;
};
#endif // GLINECHART_H

View File

@ -58,7 +58,8 @@ void gSegmentChart::Plot(gGraphWindow & w,float scrx,float scry)
glLineWidth(1.5);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float mult=float(width)/m_total;
float xmult=float(width)/float(m_total);
float ymult=float(height)/float(m_total);
float xp=w.GetLeftMargin();
@ -66,7 +67,17 @@ void gSegmentChart::Plot(gGraphWindow & w,float scrx,float scry)
int yoffset=height/2;
int data;
for (unsigned m=0;m<m_values.size();m++) {
unsigned size=m_values.size();
float line_step=float(width)/float(size-1);
bool line_first=true;
int line_last;
if (m_graph_type==GST_Line) {
w.qglColor(m_outline_color);
glBegin(GL_LINES);
}
for (unsigned m=0;m<size;m++) {
data=m_values[m];
/////////////////////////////////////////////////////////////////////////////////////
@ -117,7 +128,7 @@ void gSegmentChart::Plot(gGraphWindow & w,float scrx,float scry)
// CandleStick Chart
/////////////////////////////////////////////////////////////////////////////////////
} else if (m_graph_type==GST_CandleStick) {
float bw=mult*float(data);
float bw=xmult*float(data);
glBegin(GL_QUADS);
w.qglColor(m_gradient_color);
@ -145,9 +156,21 @@ void gSegmentChart::Plot(gGraphWindow & w,float scrx,float scry)
}
xp+=bw;
} else {
} else if (m_graph_type==GST_Line) {
float h=float(data)*ymult;
if (line_first) {
line_first=false;
} else {
glVertex2f(xp,line_last);
xp+=line_step;
glVertex2f(xp,h);
}
line_last=h;
}
}
if (m_graph_type==GST_Line) {
glEnd();
}
glDisable(GL_BLEND);
}

View File

@ -3,7 +3,7 @@
#include "graphlayer.h"
enum GraphSegmentType { GST_Pie, GST_CandleStick };
enum GraphSegmentType { GST_Pie, GST_CandleStick, GST_Line };
class gSegmentChart : public gLayer
{

View File

@ -28,7 +28,10 @@ public:
virtual qint64 Maxx() { if (m_day) return m_day->last(); return m_maxx; }
virtual EventDataType Miny() { return m_miny; }
virtual EventDataType Maxy() { return m_maxy; }
virtual void setMinY(EventDataType val) { m_miny=val; }
virtual void setMaxY(EventDataType val) { m_maxy=val; }
virtual void setMinX(qint64 val) { m_minx=val; }
virtual void setMaxX(qint64 val) { m_maxx=val; }
virtual void setVisible(bool v) { m_visible=v; }
virtual bool isVisible() { return m_visible; }
virtual bool isEmpty();

View File

@ -45,7 +45,7 @@ gGraphWindow::gGraphWindow(QWidget *parent, const QString & title, QGLWidget * s
min_x=max_x=0;
}
gGraphWindow::gGraphWindow(QWidget *parent, const QString & title, QGLContext * context,Qt::WindowFlags f)
/*gGraphWindow::gGraphWindow(QWidget *parent, const QString & title, QGLContext * context,Qt::WindowFlags f)
: QGLWidget((QGLContext *)context, parent, 0, f )
{
gl_context=context;
@ -69,7 +69,7 @@ gGraphWindow::gGraphWindow(QWidget *parent, const QString & title, QGLContext *
//setAcceptDrops(true);
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
}
}*/
gGraphWindow::~gGraphWindow()
{

View File

@ -1,8 +1,8 @@
/********************************************************************
/*
gGraphWindow Headers
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*********************************************************************/
*/
#ifndef GRAPHWINDOW_H
#define GRAPHWINDOW_H
@ -26,7 +26,7 @@ class gGraphWindow : public QGLWidget
{
Q_OBJECT
public:
explicit gGraphWindow(QWidget *parent, const QString & title, QGLContext * context,Qt::WindowFlags f=0);
//explicit gGraphWindow(QWidget *parent, const QString & title, QGLContext * context,Qt::WindowFlags f=0);
explicit gGraphWindow(QWidget *parent, const QString & title, QGLWidget * shared,Qt::WindowFlags f=0);
virtual ~gGraphWindow();
@ -72,18 +72,12 @@ public:
inline int Height() { return m_scrY-m_marginTop-m_marginBottom; } // Height of ""...
void LinkZoom(gGraphWindow *g) { link_zoom.push_back(g); } // Linking graphs changes zoom behaviour..
//void LinkMove(gGraphWindow *g) { link_move.push_back(g); } // Linking graphs changes zoom behaviour..
virtual qint64 MinX();
virtual qint64 MaxX();
virtual EventDataType MinY();
virtual EventDataType MaxY();
/* virtual double RealMinX();
virtual double RealMaxX();
virtual double RealMinY();
virtual double RealMaxY();*/
virtual void SetMinX(qint64 v);
virtual void SetMaxX(qint64 v);
virtual void SetMinY(EventDataType v);
@ -125,20 +119,14 @@ public:
void Render(int scrx,int scry);
//virtual void Update();
//virtual void Update();
void AddLayer(gLayer *l);
//virtual void DataChanged(gLayer *layer);
qint64 max_x,min_x,max_y,min_y;
qint64 rmax_x,rmin_x,rmax_y,rmin_y;
void SetBlockZoom(bool b) { m_block_zoom=b; }
//void SetBlockMove(bool b) { m_block_move=b; }
bool BlockZoom() { return m_block_zoom; }
QGLContext *gl_context;
//FTFont *texfont;
void SetGradientBackground(bool b) { m_gradient_background=b; }
bool GradientBackground() { return m_gradient_background; }
bool isEmpty();
@ -150,9 +138,7 @@ public:
void initializeGL();
QSplitter *splitter;
list<gGraphWindow *>link_zoom;
//list<gGraphWindow *>link_move;
//bool m_block_move;
bool m_block_zoom;
bool m_drag_foobar;
bool m_dragGraph;

View File

@ -41,6 +41,8 @@ public:
qint64 first() { return d_first; }
qint64 last() { return d_last; }
void setFirst(qint64 val) { d_first=val; }
void setLast(qint64 val) { d_last=val; }
qint64 first(MachineCode code);
qint64 last(MachineCode code);
EventDataType min(MachineCode code);
@ -60,6 +62,7 @@ public:
Machine *machine;
void OpenEvents();
vector<Session *> & getSessions() { return sessions; }
protected:
vector<Session *> sessions;

View File

@ -1,8 +1,8 @@
/********************************************************************
/*
SleepLib Event Class Implementation
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*********************************************************************/
*/
#include <QDebug>
#include "event.h"
@ -73,7 +73,6 @@ void EventList::AddWaveform(qint64 start, qint16 * data, int recs, qint64 durati
qWarning() << "Attempted to add waveform without setting sample rate";
return;
}
// duration=recs*rate;
qint64 last=start+duration;
if (!m_first) {
m_first=start;

View File

@ -27,6 +27,8 @@ public:
void AddWaveform(qint64 start, char * data, int recs, qint64 duration);
inline const int & count() { return m_count; }
void setCount(int count) { m_count=count; }
inline EventStoreType raw(int i) { return m_data[i]; }
EventDataType data(int i);
@ -34,6 +36,8 @@ public:
inline const qint64 & first() { return m_first; }
inline const qint64 & last() { return m_last; }
inline qint64 duration() { return m_last-m_first; }
void setFirst(qint64 val) { m_first=val; }
void setLast(qint64 val) { m_last=val; }
void setGain(EventDataType v) { m_gain=v; }
void setOffset(EventDataType v) { m_offset=v; }
@ -48,10 +52,11 @@ public:
inline const EventListType & type() { return m_type; }
inline const MachineCode & code() { return m_code; }
inline const bool & update_minmax() { return m_update_minmax; }
vector<EventStoreType> & getData() { return m_data; }
vector<qint64> & getTime() { return m_time; }
protected:
vector<qint64> m_time;
vector<qint64> m_time; // 32bitalize this.. add offsets to m_first
vector<EventStoreType> m_data;
MachineCode m_code;
EventListType m_type;

View File

@ -31,7 +31,10 @@ SOURCES += main.cpp\
SleepLib/loader_plugins/cms50_loader.cpp \
SleepLib/loader_plugins/prs1_loader.cpp \
SleepLib/loader_plugins/zeo_loader.cpp \
SleepLib/loader_plugins/resmed_loader.cpp \
SleepLib/loader_plugins/sleep_database.cpp \
daily.cpp \
oximetry.cpp \
overview.cpp \
mainwindow.cpp \
SleepLib/event.cpp \
@ -51,12 +54,9 @@ SOURCES += main.cpp\
Graphs/gTitle.cpp \
Graphs/gCandleStick.cpp \
Graphs/gBarChart.cpp \
SleepLib/loader_plugins/resmed_loader.cpp \
SleepLib/loader_plugins/sleep_database.cpp \
Graphs/gSegmentChart.cpp \
Graphs/gSessionTime.cpp \
qextserialport/qextserialport.cpp \
oximetry.cpp \
Graphs/gSegmentChart.cpp
qextserialport/qextserialport.cpp
unix:SOURCES += qextserialport/posix_qextserialport.cpp
unix:!macx:SOURCES += qextserialport/qextserialenumerator_unix.cpp
@ -80,6 +80,7 @@ HEADERS += \
SleepLib/loader_plugins/cms50_loader.h \
SleepLib/loader_plugins/prs1_loader.h \
SleepLib/loader_plugins/zeo_loader.h \
oximetry.h \
daily.h \
overview.h \
mainwindow.h \
@ -99,14 +100,13 @@ HEADERS += \
Graphs/gTitle.h \
Graphs/gCandleStick.h \
Graphs/gBarChart.h \
Graphs/gSegmentChart.h\
Graphs/gSessionTime.h \
SleepLib/loader_plugins/resmed_loader.h \
SleepLib/loader_plugins/sleep_database.h \
Graphs/gSessionTime.h \
qextserialport/qextserialport_global.h \
qextserialport/qextserialport.h \
qextserialport/qextserialenumerator.h \
oximetry.h \
Graphs/gSegmentChart.h
qextserialport/qextserialenumerator.h
FORMS += \

View File

@ -29,6 +29,16 @@
const int min_height=100;
const int default_height=150;
MyScrollArea::MyScrollArea(Daily * parent)
{
}
MyScrollArea::~MyScrollArea()
{
}
void MyScrollArea::scrollContentsBy(int dx, int dy)
{
}
Daily::Daily(QWidget *parent,QGLWidget * shared) :
QWidget(parent),
ui(new Ui::Daily)
@ -42,12 +52,15 @@ Daily::Daily(QWidget *parent,QGLWidget * shared) :
exit(-1);
}
//scrollArea=new MyScrollArea(this);
gSplitter=new QSplitter(Qt::Vertical,ui->scrollArea);
gSplitter->setStyleSheet("QSplitter::handle { background-color: 'light grey'; }");
gSplitter->setHandleWidth(3);
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->scrollArea->setWidget(gSplitter);
//this->connect(ui->scrollArea,
//ui->graphSizer->addWidget(gSplitter);
ui->scrollArea->setAutoFillBackground(false);
gSplitter->setAutoFillBackground(false);
@ -196,26 +209,32 @@ Daily::Daily(QWidget *parent,QGLWidget * shared) :
// SPO2->hide();
PULSE->hide();
gSegmentChart *seg;
TAP_EAP->SetMargins(0,0,0,0);
TAP_EAP->AddLayer(AddCPAP(new gTAPGraph(CPAP_EAP)));
TAP_EAP->AddLayer(AddCPAP(seg=new gTAPGraph(CPAP_EAP)));
TAP_EAP->hide();
TAP_EAP->SetGradientBackground(false);
TAP_IAP->SetMargins(0,0,0,0);
TAP_IAP->AddLayer(AddCPAP(new gTAPGraph(CPAP_IAP)));
TAP_IAP->AddLayer(AddCPAP(seg=new gTAPGraph(CPAP_IAP)));
TAP_IAP->hide();
TAP_IAP->SetGradientBackground(false);
TAP->SetMargins(0,0,0,0);
TAP->AddLayer(AddCPAP(new gTAPGraph(CPAP_Pressure)));
TAP->AddLayer(AddCPAP(seg=new gTAPGraph(CPAP_Pressure,GST_Line)));
TAP->hide();
TAP->SetGradientBackground(false);
G_AHI->SetMargins(0,0,0,0);
gSegmentChart *l=new gSegmentChart(GST_Pie);
l->AddSlice(CPAP_Hypopnea,QColor(0x40,0x40,0xff,0xff),"H");
l->AddSlice(CPAP_Obstructive,QColor(0x40,0xaf,0xbf,0xff),"OA");
l->AddSlice(CPAP_ClearAirway,QColor(0xb2,0x54,0xcd,0xff),"CA");
l->AddSlice(CPAP_RERA,QColor(0xff,0xff,0x80,0xff),"RE");
l->AddSlice(CPAP_FlowLimit,QColor(0x40,0x40,0x40,0xff),"FL");
G_AHI->AddLayer(AddCPAP(l));
seg=new gSegmentChart(GST_Pie);
seg->AddSlice(CPAP_Hypopnea,QColor(0x40,0x40,0xff,0xff),"H");
seg->AddSlice(CPAP_Obstructive,QColor(0x40,0xaf,0xbf,0xff),"OA");
seg->AddSlice(CPAP_ClearAirway,QColor(0xb2,0x54,0xcd,0xff),"CA");
seg->AddSlice(CPAP_RERA,QColor(0xff,0xff,0x80,0xff),"RE");
seg->AddSlice(CPAP_FlowLimit,QColor(0x40,0x40,0x40,0xff),"FL");
G_AHI->AddLayer(AddCPAP(seg));
G_AHI->SetGradientBackground(false);
G_AHI->hide();
@ -449,7 +468,7 @@ void Daily::Load(QDate date)
"<table cellspacing=0 cellpadding=2 border=0 width='100%'>\n";
QString tmp;
const int gwwidth=240;
const int gwheight=25;
const int gwheight=100;
UpdateOXIGraphs(oxi);
UpdateCPAPGraphs(cpap);
UpdateEventsTree(ui->treeWidget,cpap);

14
daily.h
View File

@ -24,6 +24,18 @@ namespace Ui {
class Daily;
}
class Daily;
class MyScrollArea:public QScrollArea
{
public:
MyScrollArea(Daily * parent);
virtual ~MyScrollArea();
protected:
virtual void scrollContentsBy(int dx, int dy);
Daily *daily;
};
class Daily : public QWidget
{
Q_OBJECT
@ -83,7 +95,7 @@ private:
Ui::Daily *ui;
Profile *profile;
QDate previous_date;
QScrollArea *scrollArea;
MyScrollArea *scrollArea;
QSplitter *gSplitter;
QLabel *NoData;
QWidget *spacer;

View File

@ -19,8 +19,6 @@
#include "SleepLib/loader_plugins/resmed_loader.h"
#include "daily.h"
#include "overview.h"
#include "Graphs/glcommon.h"
QProgressBar *qprogress;
@ -119,8 +117,8 @@ MainWindow::MainWindow(QWidget *parent) :
//overview=new Overview(ui->tabWidget,daily->SharedWidget());
//ui->tabWidget->insertTab(2,overview,tr("Overview"));
//oximetry=new Oximetry(ui->tabWidget,daily->SharedWidget());
//ui->tabWidget->insertTab(3,oximetry,tr("Oximetry"));
oximetry=new Oximetry(ui->tabWidget,daily->SharedWidget());
ui->tabWidget->insertTab(3,oximetry,tr("Oximetry"));
ui->tabWidget->setCurrentWidget(ui->welcome);
@ -135,11 +133,11 @@ MainWindow::~MainWindow()
/*if (overview) {
overview->close();
delete overview;
}
} */
if (oximetry) {
oximetry->close();
delete oximetry;
}*/
}
DoneGraphs();
Profiles::Done();
mainwin=NULL;

View File

@ -82,7 +82,7 @@ private:
Ui::MainWindow *ui;
Daily * daily;
//Overview * overview;
//Oximetry * oximetry;
Oximetry * oximetry;
bool first_load;
Profile *profile;
};

View File

@ -2,10 +2,11 @@
#include <QProgressBar>
#include <QMessageBox>
/*#include "oximetry.h"
#include "oximetry.h"
#include "ui_oximetry.h"
#include "qextserialport/qextserialenumerator.h"
#include "SleepLib/loader_plugins/cms50_loader.h"
#include "SleepLib/event.h"
#include "Graphs/gXAxis.h"
#include "Graphs/gBarChart.h"
#include "Graphs/gLineChart.h"
@ -23,34 +24,48 @@ Oximetry::Oximetry(QWidget *parent,QGLWidget * shared) :
profile=Profiles::Get(prof);
if (!profile) {
qWarning("Couldn't get profile.. Have to abort!");
abort();
exit(-1);
}
mach=profile->GetMachine(MT_OXIMETER);
if (!mach) {
CMS50Loader *l=dynamic_cast<CMS50Loader *>(GetLoader("CMS50"));
if (l) {
mach=l->CreateMachine(profile);
}
qDebug() << "Create Oximeter device";
}
// Create dummy day & session for holding eventlists.
day=new Day(mach);
session=new Session(mach,0);
day->AddSession(session);
gSplitter=new QSplitter(Qt::Vertical,ui->scrollArea);
gSplitter->setStyleSheet("QSplitter::handle { background-color: 'dark grey'; }");
gSplitter->setHandleWidth(2);
ui->graphLayout->addWidget(gSplitter);
AddData(plethy=new WaveData(OXI_Plethy));
// Create the Event Lists to store / import data
ev_plethy=new EventList(OXI_Plethy,EVL_Event,1,0,0,0,1000.0/50.0);
session->eventlist[OXI_Plethy].push_back(ev_plethy);
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);
plethy=new gLineChart(OXI_Plethy,Qt::black,false,true);
AddGraph(PLETHY=new gGraphWindow(gSplitter,tr("Plethysomogram"),shared));
plethy->SetDay(day);
AddData(pulse=new EventData(OXI_Pulse));
AddGraph(PULSE=new gGraphWindow(gSplitter,tr("Pulse Rate"),PLETHY));
pulse=new gLineChart(OXI_Pulse,Qt::red,true);
AddGraph(PULSE=new gGraphWindow(gSplitter,tr("Pulse Rate"),shared));
pulse->SetDay(day);
AddData(spo2=new EventData(OXI_SPO2));
AddGraph(SPO2=new gGraphWindow(gSplitter,tr("SPO2"),PLETHY));
plethy->SetRealMaxY(128);
pulse->SetRealMaxY(130);
spo2->SetRealMaxY(100);
for (unsigned i=0;i<Data.size();i++) {
Data[i]->AddSegment(1000000);
Data[i]->np.push_back(0);
Data[i]->SetRealMinY(0);
Data[i]->SetMinY(0);
Data[i]->SetMaxY(Data[i]->RealMaxY());
}
spo2=new gLineChart(OXI_SPO2,Qt::blue,true);
AddGraph(SPO2=new gGraphWindow(gSplitter,tr("SPO2"),shared));
spo2->SetDay(day);
for (unsigned i=0;i<Graphs.size();i++) {
for (unsigned j=0;j<Graphs.size();j++) {
@ -63,17 +78,13 @@ Oximetry::Oximetry(QWidget *parent,QGLWidget * shared) :
gSplitter->addWidget(Graphs[i]);
}
SPO2->AddLayer(new gLineChart(spo2,Qt::blue,65536,false,false,false));
PULSE->AddLayer(new gLineChart(pulse,Qt::red,65536,false,false,false));
PLETHY->AddLayer(new gLineChart(plethy,Qt::black,65536,true,false,false));
PLETHY->AddLayer(plethy);
PULSE->AddLayer(pulse);
SPO2->AddLayer(spo2);
for (unsigned i=0;i<Graphs.size();i++) {
Graphs[i]->setMinimumHeight(150);
Graphs[i]->SetSplitter(gSplitter);
Graphs[i]->RealMinY();
Graphs[i]->RealMaxY();
Graphs[i]->MinY();
Graphs[i]->MaxY();
}
on_RefreshPortsButton_clicked();
@ -92,6 +103,8 @@ void Oximetry::on_RefreshPortsButton_clicked()
int z=0;
QString firstport;
bool current_found=false;
// Windows build mixes these up
#ifdef Q_WS_WIN32
#define qesPORTNAME portName
#else
@ -131,46 +144,40 @@ void Oximetry::on_RunButton_toggled(bool checked)
lasttime=0;
lastpulse=-1;
lastspo2=-1;
plethy->np[0]=0;
// Wipe any current data
ev_plethy->getData().clear();
ev_plethy->getTime().clear();
ev_plethy->setCount(0);
ev_pulse->getData().clear();
ev_pulse->getTime().clear();
ev_pulse->setCount(0);
ev_spo2->getData().clear();
ev_spo2->getTime().clear();
ev_spo2->setCount(0);
lasttime=QDateTime::currentMSecsSinceEpoch();
starttime=lasttime;
plethy->SetRealMinX(double(lasttime)/86400000.0);
plethy->SetRealMaxX(double(lasttime+60000)/86400000.0);
plethy->SetMinX(double(lasttime)/86400000.0);
plethy->SetMaxX(double(lasttime+30000)/86400000.0);
PLETHY->RealMinX();
PLETHY->RealMaxX();
PLETHY->MinX();
PLETHY->MaxX();
plethy->SetReady(true);
plethy->SetVC(1);
plethy->np[0]=0;
day->setFirst(lasttime);
day->setLast(lasttime+30000);
session->set_first(lasttime);
session->set_last(lasttime+30000);
ev_plethy->setFirst(lasttime);
ev_plethy->setLast(lasttime+3600000);
PLETHY->SetMinX(lasttime);
PLETHY->SetMaxX(lasttime+30000);
pulse->SetRealMinX(double(lasttime)/86400000.0);
pulse->SetRealMaxX(double(lasttime)/86400000.0+(1.0/24.0));
pulse->SetMinX(double(lasttime)/86400000.0);
pulse->SetMaxX(double(lasttime)/86400000.0+(1.0/24.0));
pulse->np[0]=0;
pulse->SetReady(true);
pulse->SetVC(1);
PULSE->RealMinX();
PULSE->RealMaxX();
PULSE->MinX();
PULSE->MaxX();
ev_pulse->setFirst(lasttime);
ev_pulse->setLast(lasttime+3600000);
PULSE->SetMinX(lasttime);
PULSE->SetMaxX(lasttime+30000);
spo2->SetRealMinX(double(lasttime)/86400000.0);
spo2->SetRealMaxX(double(lasttime)/86400000.0+(1.0/24.0));
spo2->SetMinX(double(lasttime)/86400000.0);
spo2->SetMaxX(double(lasttime)/86400000.0+(1.0/24.0));
spo2->np[0]=0;
spo2->SetReady(true);
spo2->SetVC(1);
SPO2->RealMinX();
SPO2->RealMaxX();
SPO2->MinX();
SPO2->MaxX();
ev_spo2->setFirst(lasttime);
ev_spo2->setLast(lasttime+3600000);
SPO2->SetMinX(lasttime);
SPO2->SetMaxX(lasttime+30000);
ui->RunButton->setText("&Stop");
ui->SerialPortsCombo->setEnabled(false);
@ -198,29 +205,18 @@ void Oximetry::on_RunButton_toggled(bool checked)
delete port;
port=NULL;
spo2->point[0][spo2->np[0]].setX(lasttime/86400000.0);
spo2->point[0][spo2->np[0]++].setY(lastspo2);
pulse->point[0][pulse->np[0]].setX(lasttime/86400000.0);
pulse->point[0][pulse->np[0]++].setY(lastpulse);
pulse->SetRealMaxX(plethy->RealMaxX());
spo2->SetRealMaxX(plethy->RealMaxX());
spo2->SetMinX(plethy->RealMinX());
spo2->SetMaxX(plethy->RealMaxX());
pulse->SetMinX(plethy->RealMinX());
pulse->SetMaxX(plethy->RealMaxX());
plethy->SetMinX(plethy->RealMinX());
PULSE->RealMaxX();
PULSE->MaxX();
PULSE->MinX();
SPO2->RealMaxX();
SPO2->MaxX();
SPO2->MinX();
PLETHY->MinX();
PLETHY->MaxX();
ev_spo2->setLast(lasttime);
ev_pulse->setLast(lasttime);
ev_plethy->setLast(lasttime);
day->setLast(lasttime);
session->set_last(lasttime);
SPO2->SetMinX(ev_spo2->first());
SPO2->SetMaxX(lasttime);
PULSE->SetMinX(ev_pulse->first());
PULSE->SetMaxX(lasttime);
PLETHY->SetMinX(ev_plethy->first());
PLETHY->SetMaxX(lasttime);
PLETHY->updateGL();
SPO2->updateGL();
@ -234,31 +230,40 @@ void Oximetry::on_SerialPortsCombo_activated(const QString &arg1)
}
void Oximetry::UpdatePlethy(qint8 d)
{
plethy->point[0][plethy->np[0]].setX(double(lasttime)/86400000.0);
plethy->point[0][plethy->np[0]++].setY(d);
lasttime+=20; // 50 samples per second?
plethy->SetRealMaxX(lasttime/86400000.0);
if (plethy->RealMaxX()-plethy->RealMinX()>(1.0/(24.0*120.0))) {
plethy->SetMinX(lasttime/86400000.0-(1.0/(24.0*120.0)));
plethy->SetMaxX(lasttime/86400000.0);
ev_plethy->AddEvent(lasttime,d);
lasttime+=20; // 50 samples per second
//ev_plethy->setLast(lasttime);
//if (plethy->RealMaxX()-plethy->RealMinX()>(1.0/(24.0*120.0))) {
// plethy->SetMinX(lasttime/86400000.0-(1.0/(24.0*120.0)));
// plethy->SetMaxX(lasttime/86400000.0);
//}
if (d==55) {
int i=0;
}
//plethy->setMinY(ev_plethy->min());
//plethy->setMaxY(ev_plethy->max());
//plethy->setMinY(ev_plethy->min());
//plethy->setMaxY(ev_plethy->max());
PLETHY->MinX();
PLETHY->MaxX();
PLETHY->RealMaxX();
pulse->SetRealMaxX(PLETHY->RealMaxX());
spo2->SetRealMaxX(PLETHY->RealMaxX());
PULSE->SetMinX(PLETHY->MinX());
SPO2->SetMinX(PLETHY->MinX());
PULSE->SetMaxX(PLETHY->MaxX());
SPO2->SetMaxX(PLETHY->MaxX());
if (plethy->np[0]>max_data_points) {
//TODO: Stop Serial recording..
// for now overwrite..
plethy->np[0]=0;
lasttime=0;
}
//PLETHY->updateGL(); // Move this to a timer.
//PLETHY->MinY();
//PLETHY->MaxY();
PLETHY->SetMinY(ev_plethy->min());
PLETHY->SetMaxY(ev_plethy->max());
PULSE->SetMinY(ev_pulse->min());
PULSE->SetMaxY(ev_pulse->max());
SPO2->SetMinY(ev_spo2->min());
SPO2->SetMaxY(ev_spo2->max());
//PLETHY->MaxY();
PLETHY->SetMaxX(lasttime);
PLETHY->SetMinX(lasttime-30000);
PULSE->SetMaxX(lasttime);
PULSE->SetMinX(lasttime-30000);
SPO2->SetMaxX(lasttime);
SPO2->SetMinX(lasttime-30000);
session->set_last(lasttime);
day->setLast(lasttime);
}
bool Oximetry::UpdatePulse(qint8 pul)
{
@ -268,35 +273,7 @@ bool Oximetry::UpdatePulse(qint8 pul)
// Can make the graph can skip them.
if (lastpulse!=pul)
{
pulse->point[0][pulse->np[0]].setX(double(lasttime)/86400000.0);
pulse->point[0][pulse->np[0]++].setY(pul);
if (pul!=0) {
if (pulse->MinY()==0) {
pulse->SetMinY((pul/10) * 10);
pulse->SetMaxY((pul/10+1) * 10);
PULSE->MinY();
PULSE->MaxY();
} else {
if (pul<pulse->MinY()) {
pulse->SetMinY((pul/10) * 10);
PULSE->MinY();
}
if (pul>pulse->MaxY()) {
pulse->SetMaxY((pul/10+1) * 10);
PULSE->MaxY();
}
}
}
// PULSE->updateGL();
if (pulse->np[0]>max_data_points) {
//TODO: Stop Serial recording..
// for now overwrite..
pulse->np[0]=0;
lasttime=0;
}
ev_pulse->AddEvent(lasttime,pul);
ret=true;
//qDebug() << "Pulse=" << int(bytes[0]);
}
@ -309,36 +286,7 @@ bool Oximetry::UpdateSPO2(qint8 sp)
if (lastspo2!=sp)
{
spo2->point[0][spo2->np[0]].setX(double(lasttime)/86400000.0);
spo2->point[0][spo2->np[0]++].setY(sp);
if (sp!=0) {
if (spo2->MinY()==0) {
spo2->SetMinY((sp/10) * 10);
spo2->SetMaxY((sp/10+1) * 10);
SPO2->MinY();
SPO2->MaxY();
} else {
if (sp<spo2->MinY()) {
spo2->SetMinY((sp/10) * 10);
SPO2->MinY();
}
if (sp>spo2->MaxY()) {
spo2->SetMaxY((sp/10+1) * 10);
SPO2->MaxY();
}
}
}
//SPO2->updateGL();
if (spo2->np[0]>max_data_points) {
//TODO: Stop Serial recording..
// for now overwrite..
spo2->np[0]=0;
lasttime=0;
}
ev_spo2->AddEvent(lasttime,sp);
ret=true;
//qDebug() << "SpO2=" << int(bytes[1]);
}
@ -361,6 +309,7 @@ void Oximetry::onReadyRead()
if (bytes[i]&0x80) {
EventDataType d=bytes[i+1] & 0x7f;
UpdatePlethy(d);
//qDebug() << d;
i+=3;
} else {
if (UpdatePulse(bytes[i])) redraw_pulse=true;
@ -374,27 +323,15 @@ void Oximetry::onReadyRead()
if (redraw_spo2)
SPO2->updateGL();
//if (bytes.size()==3) {
//} else if (bytes.size()==2) { // Data bytes in live mode
// Plethy data
//} else {
//qDebug() << "Got " << bytes.size() << " bytes";
//}
//QString aa=QString::number(bytes.size(),16)+"bytes: ";
//for (int i=0;i<bytes.size();i++) {
// aa+=" "+QString::number((unsigned char)bytes[i],16);
//}
//qDebug() << aa;
//lastsize=bytes.size();
}
void Oximetry::onDsrChanged(bool status)
void Oximetry::onDsrChanged(bool status) // Doesn't work for CMS50's
{
if (status)
qDebug() << "device was turned on";
else
qDebug() << "device was turned off";
}
extern QProgressBar *qprogress;
extern QLabel *qstatus;
@ -414,31 +351,16 @@ void Oximetry::on_ImportButton_clicked()
QMessageBox msgbox(QMessageBox::Information,"Importing","Please Wait",QMessageBox::NoButton,this);
msgbox.show();
Machine *mach=profile->GetMachine(MT_OXIMETER);
if (!mach) {
CMS50Loader *l=dynamic_cast<CMS50Loader *>(GetLoader("CMS50"));
if (l) {
mach=l->CreateMachine(profile);
}
qDebug() << "Needed to create Oximeter device";
}
const int rb_size=0x200;
static unsigned char b1[2]={0xf5,0xf5};
static unsigned char b2[3]={0xf6,0xf6,0xf6};
static unsigned char rb[rb_size];
//b1[0]=0xf5;
//b1[1]=0xf5;
//b2[0]=0xf6;
//b2[1]=0xf6;
//b2[2]=0xf6;
unsigned char * buffer=NULL;
ui->SerialPortsCombo->setEnabled(false);
ui->RunButton->setText("&Start");
ui->RunButton->setChecked(false);
// port->write((char *)b1,2);
// return;
if (port) {
port->close();
delete port;
@ -565,14 +487,16 @@ void Oximetry::on_ImportButton_clicked()
QDateTime date=QDateTime::currentDateTimeUtc();
SessionID sid=date.toTime_t();
Session *sess=new Session(mach,sid);
session->SetSessionID(sid);
qDebug() << "Read " << bytes << "Bytes";
qDebug() << "Creating session " << sid;
char pulse,spo2,lastpulse=-1,lastspo2=-1;
qint64 tt=sid-(bytes/3);
tt*=1000;
sess->set_first(tt);
session->set_first(tt);
ev_pulse->setFirst(tt);
ev_spo2->setFirst(tt);
EventDataType data;
unsigned i=0;
while (i<bytes) {
@ -584,12 +508,12 @@ void Oximetry::on_ImportButton_clicked()
spo2=buffer[i++];
if (pulse!=0 && pulse!=lastpulse) {
data=pulse;
sess->AddEvent(new Event(tt,OXI_Pulse,0,&data,1));
ev_pulse->AddEvent(tt,data);
//qDebug() << "Pulse: " << int(pulse);
}
if (spo2 != 0 && spo2!=lastspo2) {
data=spo2;
sess->AddEvent(new Event(tt,OXI_SPO2,0,&data,1));
ev_spo2->AddEvent(tt,data);
//qDebug() << "SpO2: " << int(spo2);
}
@ -597,22 +521,38 @@ void Oximetry::on_ImportButton_clicked()
lastspo2=spo2;
tt+=1000;
}
data=pulse;
sess->AddEvent(new Event(tt,OXI_Pulse,0,&data,1));
data=spo2;
sess->AddEvent(new Event(tt,OXI_SPO2,0,&data,1));
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_PulseAverage]=sess->weighted_avg_event_field(OXI_Pulse,0);
sess->summary[OXI_SPO2Min]=sess->min_event_field(OXI_SPO2,0);
sess->summary[OXI_SPO2Max]=sess->max_event_field(OXI_SPO2,0);
sess->summary[OXI_SPO2Average]=sess->weighted_avg_event_field(OXI_SPO2,0);
sess->SetChanged(true);
mach->AddSession(sess,profile);
ev_pulse->AddEvent(tt,pulse);
ev_spo2->AddEvent(tt,spo2);
session->summary[OXI_PulseMin]=ev_pulse->min();
session->summary[OXI_PulseMax]=ev_pulse->max();
session->summary[OXI_PulseAverage]=session->weighted_avg(OXI_Pulse);
session->summary[OXI_SPO2Min]=ev_spo2->min();
session->summary[OXI_SPO2Max]=ev_spo2->max();
session->summary[OXI_SPO2Average]=session->weighted_avg(OXI_SPO2);
session->SetChanged(true);
mach->AddSession(session,profile);
mach->Save();
// Output Pulse & SPO2 here..
delete [] buffer;
port->write((char *)b2,3);
// Need to create a new session as this one got pinched.
session=new Session(mach,0);
day->getSessions().clear();
day->AddSession(session);
// As did these
ev_plethy=new EventList(OXI_Plethy,EVL_Waveform,1,0,0,0,1.0/50.0);
session->eventlist[OXI_Plethy].push_back(ev_plethy);
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);
}
delete port;
port=NULL;
@ -621,4 +561,4 @@ void Oximetry::on_ImportButton_clicked()
ui->SerialPortsCombo->setEnabled(true);
qstatus->setText("Ready");
}
*/

View File

@ -1,6 +1,6 @@
#ifndef OXIMETRY_H
#define OXIMETRY_H
/*
#include <QWidget>
#include <QGLContext>
@ -8,8 +8,11 @@
#include <qextserialport/qextserialport.h>
#include "SleepLib/profiles.h"
#include "SleepLib/day.h"
#include "SleepLib/session.h"
#include "Graphs/graphwindow.h"
#include "Graphs/graphdata_custom.h"
#include "Graphs/gLineChart.h"
namespace Ui {
class Oximetry;
@ -26,13 +29,11 @@ public:
explicit Oximetry(QWidget *parent,QGLWidget * shared=NULL);
~Oximetry();
void AddData(gPointData *d) { Data.push_back(d); }
void AddGraph(gGraphWindow *w) { Graphs.push_back(w); }
void RedrawGraphs();
private slots:
void on_RefreshPortsButton_clicked();
void on_RunButton_toggled(bool checked);
void on_SerialPortsCombo_activated(const QString &arg1);
@ -46,20 +47,27 @@ private:
bool UpdateSPO2(qint8 spo2);
void UpdatePlethy(qint8 plethy);
Ui::Oximetry *ui;
Profile *profile;
QSplitter *gSplitter;
gPointData *pulse,*spo2,*plethy;
gLineChart *pulse,*spo2,*plethy;
gGraphWindow *PULSE,*SPO2,*PLETHY;
vector<gGraphWindow *> Graphs;
vector<gPointData *> Data;
vector<gLineChart *> Data;
QextSerialPort *port;
QString portname;
PORTMODE portmode;
qint64 lasttime,starttime;
int lastpulse, lastspo2;
Machine * mach;
Day * day;
Session * session;
EventList * ev_pulse;
EventList * ev_spo2;
EventList * ev_plethy;
};
*/
#endif // OXIMETRY_H