Startings of AHI breakdown Barchart

This commit is contained in:
Mark Watkins 2011-09-02 15:13:07 +10:00
parent c96a80e237
commit 32a7a67878
10 changed files with 200 additions and 53 deletions

View File

@ -12,40 +12,149 @@ gBarChart::gBarChart(ChannelID code,QColor color,Qt::Orientation o)
:Layer(code),m_orientation(o) :Layer(code),m_orientation(o)
{ {
//Xaxis=new gXAxis(); //Xaxis=new gXAxis();
addGLBuf(quads=new GLBuffer(color,20,GL_QUADS)); addGLBuf(quads=new GLBuffer(color,20000,GL_QUADS));
//addGLBuf(lines=new GLBuffer(col,20,GL_LINES)); //addGLBuf(lines=new GLBuffer(col,20,GL_LINES));
quads->forceAntiAlias(true); quads->forceAntiAlias(true);
//lines->setAntiAlias(true); //lines->setAntiAlias(true);
//lines->setSize(2); //lines->setSize(2);
m_empty=true;
} }
gBarChart::~gBarChart() gBarChart::~gBarChart()
{ {
//delete Xaxis; //delete Xaxis;
} }
void gBarChart::SetDay(Day * day)
{
if (!m_profile) {
qWarning() << "Forgot to set profile for gBarChart dummy!";
m_day=NULL;
return;
}
Layer::SetDay(day);
//m_empty=true;
// if (!day) return;
m_empty=false;
/*for (int i=0;i<m_codes.size();i++) {
if (day->count(m_codes[i])>0) {
m_empty=false;
break;
}
} */
m_values.clear();
m_miny=9999999;
m_maxy=-9999999;
int dn;
EventDataType tmp,total;
ChannelID code;
for (QMap<QDate,QVector<Day *> >::iterator d=m_profile->daylist.begin();d!=m_profile->daylist.end();d++) {
dn=QDateTime(d.key(),QTime(0,0,0)).toTime_t()/86400;
total=0;
for (int j=0;j<m_codes.size();j++) {
code=m_codes[j];
for (int i=0;i<d.value().size();i++) {
Day *day=d.value()[i];
if (day->channelExists(code)) { // too many lookups happening here.. stop the crap..
tmp=day->count(code)/day->hours();
if (tmp>0) {
total+=tmp;
m_values[dn][code]=tmp;
break;
}
}
}
}
m_values[dn][EmptyChannel]=total;
if (total<m_miny) m_miny=total;
if (total>m_maxy) m_maxy=total;
}
m_fday=QDateTime(m_profile->FirstDay(),QTime(0,0,0)).toTime_t()/86400;
m_minx=qint64(QDateTime(m_profile->FirstDay(),QTime(0,0,0)).toTime_t())*1000L;
m_maxx=qint64(QDateTime(m_profile->LastDay(),QTime(23,59,59)).toTime_t())*1000L;
int i=0;
//set miny & maxy here.. how?
}
void gBarChart::paint(gGraph & w,int left, int top, int width, int height) void gBarChart::paint(gGraph & w,int left, int top, int width, int height)
{ {
if (!m_visible) return; if (!m_visible) return;
//if (!m_day) return;
GLBuffer *lines=w.lines();
QColor blk=Qt::black;
lines->add(left, top, left, top+height, blk);
lines->add(left, top+height, left+width,top+height, blk);
lines->add(left+width,top+height, left+width, top, blk);
lines->add(left+width, top, left, top, blk);
qint64 minx=w.min_x, maxx=w.max_x; qint64 minx=w.min_x, maxx=w.max_x;
//qint64 minx=m_minx, maxx=m_maxx;
qint64 xx=maxx - minx; qint64 xx=maxx - minx;
qint32 days=xx/86400000L; int days=xx/86400000L;
float barw=float(width)/float(days); /*int days=0;
for (QMap<int,QMap<ChannelID,EventDataType> >::iterator d=m_values.begin();d!=m_values.end();d++) {
qint64 t2,ts; qint64 ts=qint64(d.key())*86400000L;
int day;
for (QMap<QDate,QVector<Day *> >::iterator d=m_profile->daylist.begin();d!=m_profile->daylist.end();d++) {
t2=QDateTime(d.key(),QTime(0,0,0)).toTime_t();
ts=t2*1000L;
if (ts<minx) continue; if (ts<minx) continue;
if (ts>maxx) continue; // break; // out of order if I end up using a hash instead.?? if (ts>maxx) continue; // break; // out of order if I end up using a hash instead.??
day=t2/86400; days++;
float pos=float(day)*barw; }*/
//int days=m_values.size();
EventDataType yy=m_maxy-m_miny;
EventDataType ymult=float(height)/yy;
float barw=(float(width)/float(days));
qint64 ts;
float px=left;
float py;
EventDataType total;
int daynum=0;
float h,tmp;
for (qint64 Q=minx;Q<maxx;Q+=86400000L) {
int zd=Q/86400000L;
QHash<int,QMap<ChannelID,EventDataType> >::iterator d=m_values.find(zd);
if (d!=m_values.end()) {
ts=qint64(d.key())*86400000L;
if (ts<minx) continue;
if (ts>maxx) continue; // break; // out of order if I end up using a hash instead.??
ChannelID code;
total=d.value()[EmptyChannel];
py=top+height;
for (int j=0;j<m_codes.size();j++) {
code=m_codes[j];
QMap<ChannelID,EventDataType>::iterator g=d.value().find(code);
if (g!=d.value().end()) {
if (code==EmptyChannel) continue;
//look up it's color key
QColor col=m_colors[j];
QColor col2=Qt::white;
tmp=(g.value()/total);
h=tmp*(total*ymult); // height of chunk
quads->add(px,py,col);
quads->add(px,py-h,col);
quads->add(px+barw,py-h,col2);
quads->add(px+barw,py,col2);
lines->add(px,py,px,py-h,blk);
lines->add(px,py-h,px+barw,py-h,blk);
lines->add(px,py,px+barw,py,blk);
lines->add(px+barw,py,px+barw,py-h,blk);
py-=h;
}
}
}
px+=barw;
daynum++;
} }

View File

@ -14,12 +14,14 @@
class gBarChart:public Layer class gBarChart:public Layer
{ {
public: public:
gBarChart(ChannelID code=EmptyChannel,QColor col=QColor("blue"),Qt::Orientation o=Qt::Horizontal); gBarChart(ChannelID code=EmptyChannel,QColor color=QColor("blue"),Qt::Orientation o=Qt::Horizontal);
virtual ~gBarChart(); virtual ~gBarChart();
void setProfile(Profile *profile); void setProfile(Profile *profile) { m_profile=profile; }
virtual void paint(gGraph & w,int left, int top, int width, int height); virtual void paint(gGraph & w,int left, int top, int width, int height);
virtual void SetDay(Day * day);
virtual bool isEmpty() { return m_empty; }
void addSlice(ChannelID code, QColor color) { m_codes.push_back(code); m_colors.push_back(color); }
protected: protected:
Qt::Orientation m_orientation; Qt::Orientation m_orientation;
@ -30,10 +32,14 @@ class gBarChart:public Layer
//virtual const wxString & FormatX(double v) { static wxString t; t=wxString::Format(wxT("%.1f"),v); return t; }; //virtual const wxString & FormatX(double v) { static wxString t; t=wxString::Format(wxT("%.1f"),v); return t; };
virtual const QString & FormatY(double v) { static QString t; t.sprintf("%.1f",v); return t; } virtual const QString & FormatY(double v) { static QString t; t.sprintf("%.1f",v); return t; }
gXAxis *Xaxis; //gXAxis *Xaxis;
QVector<QColor> color; QVector<QColor> m_colors;
QVector<ChannelID> m_codes;
QHash<int,QMap<ChannelID,EventDataType> > m_values;
Profile * m_profile; Profile * m_profile;
GLBuffer *quads; GLBuffer *quads;
bool m_empty;
int m_fday;
}; };
#endif // GBARCHART_H #endif // GBARCHART_H

View File

@ -54,9 +54,9 @@ GLBuffer::GLBuffer(QColor color,int max,int type)
m_antialias=true; m_antialias=true;
m_forceantialias=false; m_forceantialias=false;
buffer=new GLshort [max+8]; buffer=new GLshort [max+8];
if (m_type==GL_LINES) { //if (m_type==GL_LINES) {
colors=new GLubyte[max*4+(8*4)]; colors=new GLubyte[max*4+(8*4)];
} else colors=NULL; //} else colors=NULL;
m_cnt=0; m_cnt=0;
m_colcnt=0; m_colcnt=0;
m_size=1; m_size=1;
@ -1288,7 +1288,7 @@ void gGraphView::paintGL()
threaded=true; threaded=true;
} else threaded=false; } else threaded=false;
// threaded=true; threaded=false;
for (int i=0;i<m_graphs.size();i++) { for (int i=0;i<m_graphs.size();i++) {
if (m_graphs[i]->isEmpty() || !m_graphs[i]->visible()) continue; if (m_graphs[i]->isEmpty() || !m_graphs[i]->visible()) continue;
numgraphs++; numgraphs++;

View File

@ -8,7 +8,7 @@
#include <QDebug> #include <QDebug>
#include "gXAxis.h" #include "gXAxis.h"
const int divisors[]={86400000,2880000,14400000,7200000,3600000,2700000,1800000,1200000,900000,600000,300000,120000,60000,45000,30000,20000,15000,10000,5000,2000,1000,100,50,10}; const int divisors[]={604800000,259200000, 172800000, 86400000,2880000,14400000,7200000,3600000,2700000,1800000,1200000,900000,600000,300000,120000,60000,45000,30000,20000,15000,10000,5000,2000,1000,100,50,10};
const int divcnt=sizeof(divisors)/sizeof(int); const int divcnt=sizeof(divisors)/sizeof(int);
gXAxis::gXAxis(QColor col,bool fadeout) gXAxis::gXAxis(QColor col,bool fadeout)
@ -60,24 +60,30 @@ void gXAxis::paint(gGraph & w,int left,int top, int width, int height)
QString fd,tmpstr; QString fd,tmpstr;
int divmax,dividx; int divmax,dividx;
int fitmode; int fitmode;
if (xx>86400000L) { // Day /*if (xx>2*86400000L) { // Day
fd="MMM 00:00";
dividx=0; dividx=0;
divmax=10; divmax=10;
//fitmode=-1;
fd="MMM dd";
} else */
if (xx>86400000L) { // Day
fd="MMM 00";
dividx=0;
divmax=12;
fitmode=0; fitmode=0;
} else if (xx>600000) { // Minutes } else if (xx>600000) { // Minutes
fd="00:00"; fd="00:00";
dividx=0; dividx=3;
divmax=18; divmax=21;
fitmode=1; fitmode=1;
} else if (xx>5000) { // Seconds } else if (xx>5000) { // Seconds
fd="00:00:00"; fd="00:00:00";
dividx=9; dividx=10;
divmax=20; divmax=21;
fitmode=2; fitmode=2;
} else { // Microseconds } else { // Microseconds
fd="00:00:00:000"; fd="00:00:00:000";
dividx=19; dividx=22;
divmax=divcnt; divmax=divcnt;
fitmode=3; fitmode=3;
} }
@ -146,9 +152,13 @@ void gXAxis::paint(gGraph & w,int left,int top, int width, int height)
int s=(j/1000L) % 60L; int s=(j/1000L) % 60L;
if (fitmode==0) { if (fitmode==0) {
static QString dow[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; int d=(j/1000);
int d=(j/86400000) % 7; QDateTime dt=QDateTime::fromTime_t(d);
tmpstr=QString("%1 %2:%3").arg(dow[d]).arg(h,2,10,QChar('0')).arg(m,2,10,QChar('0')); tmpstr=dt.toString("MMM dd");
//} else if (fitmode==0) {
// static QString dow[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
// int d=(j/86400000) % 7;
// tmpstr=QString("%1 %2:%3").arg(dow[d]).arg(h,2,10,QChar('0')).arg(m,2,10,QChar('0'));
} else if (fitmode==1) { // minute } else if (fitmode==1) { // minute
tmpstr=QString("%1:%2").arg(h,2,10,QChar('0')).arg(m,2,10,QChar('0')); tmpstr=QString("%1:%2").arg(h,2,10,QChar('0')).arg(m,2,10,QChar('0'));
} else if (fitmode==2) { // second } else if (fitmode==2) { // second

View File

@ -1,8 +1,8 @@
/******************************************************************** /*
SleepLib Day Class Implementation SleepLib Day Class Implementation
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net> Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL License: GPL
*********************************************************************/ */
#include "day.h" #include "day.h"

View File

@ -392,6 +392,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
}; };
for (unsigned i=0;i<sizeof(a)/sizeof(ChannelID);i++) { for (unsigned i=0;i<sizeof(a)/sizeof(ChannelID);i++) {
if (sess->eventlist.contains(a[i])) { if (sess->eventlist.contains(a[i])) {
sess->count(a[i]);
sess->min(a[i]); sess->min(a[i]);
sess->max(a[i]); sess->max(a[i]);
sess->avg(a[i]); sess->avg(a[i]);
@ -405,6 +406,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
}; };
for (unsigned i=0;i<sizeof(b)/sizeof(ChannelID);i++) { for (unsigned i=0;i<sizeof(b)/sizeof(ChannelID);i++) {
if (sess->eventlist.contains(b[i])) { if (sess->eventlist.contains(b[i])) {
sess->count(a[i]);
sess->min(b[i]); sess->min(b[i]);
sess->max(b[i]); sess->max(b[i]);
sess->avg(b[i]); sess->avg(b[i]);

View File

@ -530,9 +530,15 @@ qint64 Session::last(ChannelID id)
} }
bool Session::channelExists(ChannelID id) bool Session::channelExists(ChannelID id)
{ {
QHash<ChannelID,QVector<EventList *> >::iterator j=eventlist.find(id); if (s_events_loaded) {
if (j==eventlist.end()) QHash<ChannelID,QVector<EventList *> >::iterator j=eventlist.find(id);
return false; if (j==eventlist.end()) // eventlist not loaded.
return false;
} else {
QHash<ChannelID,int>::iterator q=m_cnt.find(id);
if (q==m_cnt.end())
return false;
}
return true; return true;
} }

View File

@ -25,7 +25,6 @@
#include "Graphs/gFooBar.h" #include "Graphs/gFooBar.h"
#include "Graphs/gXAxis.h" #include "Graphs/gXAxis.h"
#include "Graphs/gYAxis.h" #include "Graphs/gYAxis.h"
#include "Graphs/gBarChart.h"
#include "Graphs/gSegmentChart.h" #include "Graphs/gSegmentChart.h"
#include "Graphs/gStatsLine.h" #include "Graphs/gStatsLine.h"
@ -85,6 +84,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared, MainWindow *mw)
SF->AddLayer(AddCPAP(seg),LayerRight,100); */ SF->AddLayer(AddCPAP(seg),LayerRight,100); */
BC=new gGraph(GraphView,"AHI Chart",default_height,2);
FRW=new gGraph(GraphView,"Flow Rate",default_height); FRW=new gGraph(GraphView,"Flow Rate",default_height);
MP=new gGraph(GraphView,"Mask Pressure",default_height); MP=new gGraph(GraphView,"Mask Pressure",default_height);
PRD=new gGraph(GraphView,"Pressure",default_height); PRD=new gGraph(GraphView,"Pressure",default_height);
@ -105,6 +105,16 @@ Daily::Daily(QWidget *parent,gGraphView * shared, MainWindow *mw)
SPO2=new gGraph(GraphView,"SPO2",default_height,1); SPO2=new gGraph(GraphView,"SPO2",default_height,1);
PLETHY=new gGraph(GraphView,"Plethy",default_height,1); PLETHY=new gGraph(GraphView,"Plethy",default_height,1);
bc=new gBarChart();
bc->setProfile(profile);
bc->addSlice(CPAP_Hypopnea,QColor("blue"));
bc->addSlice(CPAP_Obstructive,QColor("#40c0ff"));
bc->addSlice(CPAP_ClearAirway,QColor("purple"));
BC->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
BC->AddLayer(new gXAxis(),LayerBottom,0,gXAxis::Margin);
BC->AddLayer(bc);
BC->AddLayer(new gXGrid());
gFlagsGroup *fg=new gFlagsGroup(); gFlagsGroup *fg=new gFlagsGroup();
fg->AddLayer((new gFlagsLine(CPAP_CSR,QColor("light green"),"CSR",false,FT_Span))); fg->AddLayer((new gFlagsLine(CPAP_CSR,QColor("light green"),"CSR",false,FT_Span)));
@ -757,6 +767,10 @@ void Daily::Load(QDate date)
UpdateCPAPGraphs(cpap); UpdateCPAPGraphs(cpap);
UpdateEventsTree(ui->treeWidget,cpap); UpdateEventsTree(ui->treeWidget,cpap);
bc->SetDay(NULL);
BC->MinX();
BC->MaxX();
GraphView->ResetBounds(); GraphView->ResetBounds();
//GraphView->ResetBounds(1); //GraphView->ResetBounds(1);

10
daily.h
View File

@ -16,16 +16,14 @@
#include <QLabel> #include <QLabel>
#include <QtOpenGL/QGLContext> #include <QtOpenGL/QGLContext>
#include <QScrollBar> #include <QScrollBar>
#include <QWebPluginFactory> #include "Graphs/gBarChart.h"
#include <SleepLib/profiles.h> #include <SleepLib/profiles.h>
//#include <Graphs/graphwindow.h>
#include "mainwindow.h" #include "mainwindow.h"
#include "Graphs/gGraphView.h" #include "Graphs/gGraphView.h"
//#include "Graphs/gSplitter.h"
#include "Graphs/gLineChart.h" #include "Graphs/gLineChart.h"
//#include "Graphs/gFlagsLine.h"
namespace Ui { namespace Ui {
class Daily; class Daily;
} }
@ -70,8 +68,9 @@ private:
gGraph *PRD,*FRW,*GAHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2, gGraph *PRD,*FRW,*GAHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2,
*SNORE,*RR,*MP,*MV,*TV,*FLG,*PTB,*OF,*INTPULSE,*INTSPO2, *THPR, *SNORE,*RR,*MP,*MV,*TV,*FLG,*PTB,*OF,*INTPULSE,*INTSPO2, *THPR,
*PLETHY,*TI,*TE, *RE, *IE; *PLETHY,*TI,*TE, *RE, *IE, *BC;
gBarChart *bc;
QList<Layer *> OXIData; QList<Layer *> OXIData;
QList<Layer *> CPAPData; QList<Layer *> CPAPData;
//QVector<gGraph *> Graphs; //QVector<gGraph *> Graphs;
@ -96,6 +95,7 @@ private:
gGraphView *GraphView; gGraphView *GraphView;
MyScrollBar *scrollbar; MyScrollBar *scrollbar;
QHBoxLayout *layout; QHBoxLayout *layout;
}; };
#endif // DAILY_H #endif // DAILY_H

View File

@ -118,16 +118,6 @@ MainWindow::MainWindow(QWidget *parent) :
if (!pref.Exists("AlwaysShowOverlayBars")) pref["AlwaysShowOverlayBars"]=true; if (!pref.Exists("AlwaysShowOverlayBars")) pref["AlwaysShowOverlayBars"]=true;
ui->actionOverlay_Bars->setChecked(pref["AlwaysShowOverlayBars"].toBool()); ui->actionOverlay_Bars->setChecked(pref["AlwaysShowOverlayBars"].toBool());
daily=new Daily(ui->tabWidget,NULL,this);
ui->tabWidget->insertTab(1,daily,tr("Daily"));
//overview=new Overview(ui->tabWidget,daily->SharedWidget());
//ui->tabWidget->insertTab(2,overview,tr("Overview"));
//oximetry=NULL;
//overview=NULL;
oximetry=new Oximetry(ui->tabWidget,daily->SharedWidget());
ui->tabWidget->insertTab(3,oximetry,tr("Oximetry"));
ui->tabWidget->setCurrentWidget(ui->welcome); ui->tabWidget->setCurrentWidget(ui->welcome);
} }
@ -162,6 +152,16 @@ void MainWindow::Startup()
profile=Profiles::Get(pref["Profile"].toString()); profile=Profiles::Get(pref["Profile"].toString());
profile->LoadMachineData(); profile->LoadMachineData();
daily=new Daily(ui->tabWidget,NULL,this);
ui->tabWidget->insertTab(1,daily,tr("Daily"));
//overview=new Overview(ui->tabWidget,daily->SharedWidget());
//ui->tabWidget->insertTab(2,overview,tr("Overview"));
//oximetry=NULL;
//overview=NULL;
oximetry=new Oximetry(ui->tabWidget,daily->SharedWidget());
ui->tabWidget->insertTab(3,oximetry,tr("Oximetry"));
if (daily) daily->ReloadGraphs(); if (daily) daily->ReloadGraphs();
/*if (overview) { /*if (overview) {