mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-12 00:30:46 +00:00
User Flagging, take 1.. Note scanning for duplicates (ie. events already detected) is switched off for testing purposes
This commit is contained in:
parent
9566d23ae8
commit
ad739b5387
@ -127,7 +127,7 @@ EventDataType * FlowParser::applyFilters(EventDataType * data, int samples)
|
|||||||
{
|
{
|
||||||
EventDataType *in=NULL,*out=NULL;
|
EventDataType *in=NULL,*out=NULL;
|
||||||
if (m_filters.size()==0) {
|
if (m_filters.size()==0) {
|
||||||
qDebug() << "Trying to apply empty filter list in FlowParser..";
|
//qDebug() << "Trying to apply empty filter list in FlowParser..";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ EventDataType * FlowParser::applyFilters(EventDataType * data, int samples)
|
|||||||
in=data;
|
in=data;
|
||||||
out=m_buffers[0];
|
out=m_buffers[0];
|
||||||
if (in==out) {
|
if (in==out) {
|
||||||
qDebug() << "Error: If you need to use internal m_buffers as initial input, use the second one. No filters were applied";
|
//qDebug() << "Error: If you need to use internal m_buffers as initial input, use the second one. No filters were applied";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -219,13 +219,13 @@ void FlowParser::calcPeaks(EventDataType * input, int samples)
|
|||||||
double peakmax=flowstart, peakmin=flowstart;
|
double peakmax=flowstart, peakmin=flowstart;
|
||||||
|
|
||||||
time=lasttime=flowstart;
|
time=lasttime=flowstart;
|
||||||
|
breaths.clear();
|
||||||
|
|
||||||
// Estimate storage space needed using typical average breaths per minute.
|
// Estimate storage space needed using typical average breaths per minute.
|
||||||
m_minutes=double(m_flow->last() - m_flow->first()) / 60000.0;
|
m_minutes=double(m_flow->last() - m_flow->first()) / 60000.0;
|
||||||
const double avgbpm=20;
|
const double avgbpm=20;
|
||||||
int guestimate=m_minutes*avgbpm;
|
int guestimate=m_minutes*avgbpm;
|
||||||
breaths_lower.reserve(guestimate);
|
breaths.reserve(guestimate);
|
||||||
breaths_upper.reserve(guestimate);
|
|
||||||
|
|
||||||
// Prime min & max, and see which side of the zero line we are starting from.
|
// Prime min & max, and see which side of the zero line we are starting from.
|
||||||
c=input[0];
|
c=input[0];
|
||||||
@ -235,14 +235,12 @@ void FlowParser::calcPeaks(EventDataType * input, int samples)
|
|||||||
|
|
||||||
qint32 start=0,middle=0;//,end=0;
|
qint32 start=0,middle=0;//,end=0;
|
||||||
|
|
||||||
breaths.clear();
|
|
||||||
|
|
||||||
int sps=1000/m_rate;
|
int sps=1000/m_rate;
|
||||||
// For each samples, find the peak upper and lower breath components
|
// For each samples, find the peak upper and lower breath components
|
||||||
//bool dirty=false;
|
//bool dirty=false;
|
||||||
int len=0, lastk=0; //lastlen=0
|
int len=0, lastk=0; //lastlen=0
|
||||||
|
|
||||||
//EventList *uf1=m_session->AddEventList(CPAP_UserFlag1,EVL_Event);
|
|
||||||
//EventList *uf2=m_session->AddEventList(CPAP_UserFlag2,EVL_Event);
|
//EventList *uf2=m_session->AddEventList(CPAP_UserFlag2,EVL_Event);
|
||||||
|
|
||||||
qint64 sttime=time;//, ettime=time;
|
qint64 sttime=time;//, ettime=time;
|
||||||
@ -258,11 +256,12 @@ void FlowParser::calcPeaks(EventDataType * input, int samples)
|
|||||||
// This helps filter out dirty breaths..
|
// This helps filter out dirty breaths..
|
||||||
len=k-start;
|
len=k-start;
|
||||||
if ((max>3) && ((max-min) > 8) && (len>sps) && (middle > start)) {
|
if ((max>3) && ((max-min) > 8) && (len>sps) && (middle > start)) {
|
||||||
|
|
||||||
breaths.push_back(BreathPeak(min, max, start, peakmax, middle, peakmin, k));
|
breaths.push_back(BreathPeak(min, max, start, peakmax, middle, peakmin, k));
|
||||||
//EventDataType g0=(0-lastc) / (c-lastc);
|
//EventDataType g0=(0-lastc) / (c-lastc);
|
||||||
//double d=(m_rate*g0);
|
//double d=(m_rate*g0);
|
||||||
//double d1=flowstart+ (start*rate);
|
//double d1=flowstart+ (start*rate);
|
||||||
//double d2=flowstart+ (k*rate);
|
//double d2=peakmax;
|
||||||
|
|
||||||
//uf1->AddEvent(d1,0);
|
//uf1->AddEvent(d1,0);
|
||||||
//uf2->AddEvent(d2,0);
|
//uf2->AddEvent(d2,0);
|
||||||
@ -275,10 +274,11 @@ void FlowParser::calcPeaks(EventDataType * input, int samples)
|
|||||||
// Starting point of next breath cycle
|
// Starting point of next breath cycle
|
||||||
start=k;
|
start=k;
|
||||||
sttime=time;
|
sttime=time;
|
||||||
} //else {
|
}/* else {
|
||||||
// dirty=true;
|
if ((max <=3) || ((max-min) <= 8)) {
|
||||||
// lastc=-1;
|
start=k;
|
||||||
// }
|
}
|
||||||
|
}*/
|
||||||
} else if (c > max) {
|
} else if (c > max) {
|
||||||
// Update upper breath peak
|
// Update upper breath peak
|
||||||
max=c;
|
max=c;
|
||||||
@ -398,7 +398,7 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
EventDataType mv;
|
EventDataType mv;
|
||||||
if (calcMv) {
|
if (calcMv) {
|
||||||
MV=m_session->AddEventList(CPAP_MinuteVent,EVL_Event);
|
MV=m_session->AddEventList(CPAP_MinuteVent,EVL_Event);
|
||||||
MV->setGain(0.1);
|
MV->setGain(0.125);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventDataType sps=(1000.0/m_rate); // Samples Per Second
|
EventDataType sps=(1000.0/m_rate); // Samples Per Second
|
||||||
@ -465,7 +465,7 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
if (tv < mintv) mintv=tv;
|
if (tv < mintv) mintv=tv;
|
||||||
if (tv > maxtv) maxtv=tv;
|
if (tv > maxtv) maxtv=tv;
|
||||||
*tv_tptr++ = timeval;
|
*tv_tptr++ = timeval;
|
||||||
*tv_dptr++ = tv * 10.0;
|
*tv_dptr++ = tv / 20.0;
|
||||||
tv_count++;
|
tv_count++;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -507,14 +507,17 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
|
|
||||||
// Add manually.. (much quicker)
|
// Add manually.. (much quicker)
|
||||||
*rr_tptr++ = timeval;
|
*rr_tptr++ = timeval;
|
||||||
*rr_dptr++ = rr * 50.0;
|
|
||||||
|
// Use the same gains as ResMed..
|
||||||
|
|
||||||
|
*rr_dptr++ = rr * 5.0;
|
||||||
rr_count++;
|
rr_count++;
|
||||||
|
|
||||||
//rr->AddEvent(et,br * 50.0);
|
//rr->AddEvent(et,br * 50.0);
|
||||||
}
|
}
|
||||||
if (calcMv && calcResp && calcTv) {
|
if (calcMv && calcResp && calcTv) {
|
||||||
mv=(tv/1000.0) * rr;
|
mv=(tv/1000.0) * rr;
|
||||||
MV->AddEvent(et,mv * 10.0);
|
MV->AddEvent(et,mv * 8.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,7 +526,7 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (calcResp) {
|
if (calcResp) {
|
||||||
RR->setGain(0.02);
|
RR->setGain(0.2);
|
||||||
RR->setMin(minrr);
|
RR->setMin(minrr);
|
||||||
RR->setMax(maxrr);
|
RR->setMax(maxrr);
|
||||||
RR->setFirst(start);
|
RR->setFirst(start);
|
||||||
@ -535,7 +538,7 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (calcTv) {
|
if (calcTv) {
|
||||||
TV->setGain(0.1);
|
TV->setGain(20);
|
||||||
TV->setMin(mintv);
|
TV->setMin(mintv);
|
||||||
TV->setMax(maxtv);
|
TV->setMax(maxtv);
|
||||||
TV->setFirst(start);
|
TV->setFirst(start);
|
||||||
@ -544,355 +547,147 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FlowParser::flagEvents()
|
||||||
/*
|
|
||||||
// Support function for calcRespRate()
|
|
||||||
int filterFlow(Session *session, EventList *in, EventList *out, EventList *tv, EventList *mv, double rate)
|
|
||||||
{
|
{
|
||||||
int size=in->count();
|
int numbreaths=breaths.size();
|
||||||
int samples=size;
|
|
||||||
|
|
||||||
// Create two buffers for filter stages.
|
EventDataType val,mx,mn;
|
||||||
EventDataType *stage1=new EventDataType [samples];
|
QVector<EventDataType> br(numbreaths);
|
||||||
EventDataType *stage2=new EventDataType [samples];
|
|
||||||
|
|
||||||
QVector<EventDataType> med;
|
// QVector<qint64> bstart(numbreaths);
|
||||||
med.reserve(8);
|
// QVector<qint64> bend(numbreaths);
|
||||||
|
// QVector<EventDataType> bvalue(numbreaths);
|
||||||
|
|
||||||
EventDataType r,tmp;
|
double start=m_flow->first();
|
||||||
int cnt;
|
double sps=1000.0/m_rate;
|
||||||
|
double st,mt,et, dur;
|
||||||
EventDataType c;
|
qint64 len;
|
||||||
int i;
|
|
||||||
|
|
||||||
percentileFilter(in->rawData(), stage1, samples, 11, 0.5);
|
|
||||||
percentileFilter(stage1, stage2, samples, 7, 0.5);
|
|
||||||
|
|
||||||
|
|
||||||
qint64 time=in->first();
|
for (int i=0;i<numbreaths;i++) {
|
||||||
qint64 u1=0,u2=0,len,l1=0,l2=0;
|
// st=start+breaths[i].start * m_rate;
|
||||||
int z1=0,z2=0;
|
// et=start+breaths[i].end * m_rate;
|
||||||
EventDataType lastc=0,thresh=-1;
|
// bstart[i]=st;
|
||||||
QVector<int> breaths;
|
// bend[i]=et;
|
||||||
QVector<EventDataType> TV;
|
|
||||||
QVector<qint64> breaths_start;
|
|
||||||
QVector<qint64> breaths_min_peak;
|
|
||||||
QVector<EventDataType> breaths_min;
|
|
||||||
QVector<qint64> breaths_max_peak;
|
|
||||||
QVector<EventDataType> breaths_max;
|
|
||||||
|
|
||||||
EventDataType min=0,max=0;
|
val=breaths[i].max - breaths[i].min;
|
||||||
qint64 peakmin=0, peakmax=0;
|
//bvalue[i]=val;
|
||||||
double avgmax=0;
|
|
||||||
double avgmin=0;
|
|
||||||
for (i=0;i<size;i++) {
|
|
||||||
c=stage2[i];
|
|
||||||
|
|
||||||
if (c>thresh) {
|
br[i]=val;
|
||||||
// Crossing the zero line, going up
|
|
||||||
if (lastc<=thresh) {
|
|
||||||
u2=u1;
|
|
||||||
u1=time;
|
|
||||||
if (u2>0) {
|
|
||||||
z2=i;
|
|
||||||
len=qAbs(u2-u1);
|
|
||||||
if (tv) { // Tidal Volume Calculations
|
|
||||||
EventDataType t=0;
|
|
||||||
// looking at only half the waveform
|
|
||||||
for (int g=z1;g<z2;g++) {
|
|
||||||
tmp=-stage2[g];
|
|
||||||
t+=tmp;
|
|
||||||
}
|
|
||||||
TV.push_back(t);
|
|
||||||
}
|
|
||||||
// keep zero crossings points
|
|
||||||
breaths_start.push_back(time);
|
|
||||||
breaths.push_back(len);
|
|
||||||
|
|
||||||
// keep previously calculated negative peak
|
|
||||||
if (peakmin) {
|
|
||||||
breaths_min_peak.push_back(peakmin);
|
|
||||||
breaths_min.push_back(min);
|
|
||||||
avgmin+=min;
|
|
||||||
}
|
|
||||||
max=0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Find the positive peak
|
|
||||||
if (c>=max) {
|
|
||||||
max=c;
|
|
||||||
peakmax=time+rate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Crossing the zero line, going down
|
|
||||||
if (lastc>thresh) {
|
|
||||||
l2=l1;
|
|
||||||
l1=time;
|
|
||||||
if (l2>0) {
|
|
||||||
z1=i;
|
|
||||||
len=qAbs(l2-l1);
|
|
||||||
if (tv) {
|
|
||||||
// Average the other half of the breath to increase accuracy.
|
|
||||||
EventDataType t=0;
|
|
||||||
for (int g=z2;g<z1;g++) {
|
|
||||||
tmp=stage2[g];
|
|
||||||
t+=tmp;
|
|
||||||
}
|
|
||||||
int ts=TV.size()-2;
|
|
||||||
if (ts>=0) {
|
|
||||||
// TV[ts]=(TV[ts]+t)/2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// keep previously calculated positive peak
|
|
||||||
if (peakmax>0) {
|
|
||||||
breaths_max_peak.push_back(peakmax);
|
|
||||||
breaths_max.push_back(max);
|
|
||||||
avgmax+=max;
|
|
||||||
}
|
|
||||||
min=0;
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Find the negative peak
|
|
||||||
if (c<=min) {
|
|
||||||
min=c;
|
|
||||||
peakmin=time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
const EventDataType perc=0.95;
|
||||||
|
int idx=numbreaths*perc;
|
||||||
|
nth_element(br.begin(),br.begin()+idx,br.end());
|
||||||
|
|
||||||
}
|
EventDataType peak=*(br.begin()+idx);
|
||||||
lastc=c;
|
|
||||||
time+=rate;
|
|
||||||
}
|
|
||||||
if (!breaths.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
avgmax/=EventDataType(breaths_max.size());
|
EventDataType cutoffval=peak * (PROFILE.cpap->userFlowRestriction()/100.0);
|
||||||
avgmin/=EventDataType(breaths_min.size());
|
EventDataType duration=PROFILE.cpap->userEventDuration();
|
||||||
|
|
||||||
if ((breaths_max.size()>5) && (breaths_min.size()>5) && (p_profile->cpap->userEventFlagging())) {
|
QVector<qint64> good;
|
||||||
EventDataType maxperc,minperc;
|
EventList * uf1=NULL;
|
||||||
|
//EventList * uf2=m_session->AddEventList(CPAP_UserFlag2,EVL_Event);
|
||||||
|
// EventList * uf3=m_session->AddEventList(CPAP_UserFlag3,EVL_Event);
|
||||||
|
|
||||||
int n=breaths_max.size()*0.8;
|
double lastst=start, lastet=start;
|
||||||
if (n > breaths_max.size()-1) n-=1;
|
good.reserve(numbreaths);
|
||||||
nth_element(breaths_max.begin(),breaths_max.begin()+n,breaths_max.end());
|
bool bad=false;
|
||||||
maxperc=breaths_max[n];
|
int bs,bm,be;
|
||||||
|
for (int i=0;i<numbreaths;i++) {
|
||||||
|
bs=breaths[i].start;
|
||||||
|
bm=breaths[i].middle;
|
||||||
|
be=breaths[i].end;
|
||||||
|
|
||||||
n=breaths_min.size()*0.2;
|
mx=breaths[i].max;
|
||||||
if (n > breaths_min.size()-1) n-=1;
|
mn=breaths[i].min;
|
||||||
nth_element(breaths_min.begin(),breaths_min.begin()+n,breaths_min.end());
|
val=mx - mn;
|
||||||
minperc=breaths_min[n];
|
|
||||||
|
|
||||||
|
int i=bs;
|
||||||
QVector<qint64> goodb;
|
for (;i<bm;i++) {
|
||||||
|
if (qAbs(m_filtered[i]) > cutoffval) {
|
||||||
EventDataType restriction=p_profile->cpap->userFlowRestriction()/100.0;
|
bs=i;
|
||||||
|
|
||||||
// This is faster than vector access.
|
|
||||||
EventDataType *dptr=breaths_max.data();
|
|
||||||
qint64 * tptr=breaths_max_peak.data();
|
|
||||||
|
|
||||||
EventDataType restrict=maxperc * restriction;
|
|
||||||
|
|
||||||
// Knock out all the upper breath components above the flow restriction
|
|
||||||
for (int i=0;i<breaths_max.size();i++) {
|
|
||||||
max=*dptr++; //breaths_max[i];
|
|
||||||
time=*tptr++; //breaths_max_peak[i];
|
|
||||||
|
|
||||||
if ((time > 0) && (max > restrict)) {
|
|
||||||
goodb.push_back(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dptr=breaths_min.data();
|
|
||||||
tptr=breaths_min_peak.data();
|
|
||||||
|
|
||||||
restrict=minperc * restriction;
|
|
||||||
|
|
||||||
// Knock out all the lower breath components above the flow restriction
|
|
||||||
for (int i=0;i<breaths_min.size();i++) {
|
|
||||||
min=*dptr++; //breaths_min[i];
|
|
||||||
time=*tptr++; //breaths_min_peak[i];
|
|
||||||
if ((time > 0) && (min < restrict)) {
|
|
||||||
goodb.push_back(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EventList *uf=NULL;
|
|
||||||
|
|
||||||
if (goodb.size()>2) {
|
|
||||||
qint64 duration=p_profile->cpap->userEventDuration()*1000;
|
|
||||||
|
|
||||||
qSort(goodb);
|
|
||||||
|
|
||||||
tptr=goodb.data();
|
|
||||||
|
|
||||||
qint64 g0=*tptr++,g1;
|
|
||||||
|
|
||||||
EventDataType lf;
|
|
||||||
//
|
|
||||||
for (int i=1;i<goodb.size();i++) {
|
|
||||||
g1=*tptr++;
|
|
||||||
qint64 len=g1-g0;
|
|
||||||
if (len >= duration) {
|
|
||||||
time=g0 + (len/2);
|
|
||||||
if (!SearchApnea(session,time)) {
|
|
||||||
if (!uf) {
|
|
||||||
uf=new EventList(EVL_Event,1,0,0,0,0,true);
|
|
||||||
session->eventlist[CPAP_UserFlag1].push_back(uf);
|
|
||||||
}
|
|
||||||
lf=double(len)/1000.0;
|
|
||||||
if (lf>30) {
|
|
||||||
int i=5;
|
|
||||||
}
|
|
||||||
uf->AddEvent(time,lf,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g0=g1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qint64 window=60000;
|
|
||||||
qint64 t1=in->first()-window/2;
|
|
||||||
qint64 t2=in->first()+window/2;
|
|
||||||
qint64 t;
|
|
||||||
EventDataType br,q;
|
|
||||||
//int z=0;
|
|
||||||
int l;
|
|
||||||
|
|
||||||
QVector<int> breaths2;
|
|
||||||
QVector<qint64> breaths2_start;
|
|
||||||
|
|
||||||
QVector<EventDataType> TV2;
|
|
||||||
QVector<qint64> TV2_start;
|
|
||||||
|
|
||||||
int fir=0;//,fir2=0;
|
|
||||||
EventDataType T,L;
|
|
||||||
bool done=false;
|
|
||||||
do {
|
|
||||||
br=0;
|
|
||||||
bool first=true;
|
|
||||||
bool cont=false;
|
|
||||||
T=0;
|
|
||||||
L=0;
|
|
||||||
for (int i=fir;i<breaths.size();i++) {
|
|
||||||
t=breaths_start[i];
|
|
||||||
l=breaths[i];
|
|
||||||
if (t+l < t1) continue;
|
|
||||||
if (t > t2) break;
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
first=false;
|
|
||||||
fir=i;
|
|
||||||
}
|
|
||||||
//q=1; // 22:28pm
|
|
||||||
if (t<t1) {
|
|
||||||
// move to start of next breath
|
|
||||||
i++;
|
|
||||||
if (i>=breaths.size()) {
|
|
||||||
done=true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
t1=breaths_start[i];
|
|
||||||
t2=t1+window;
|
|
||||||
fir=i;
|
|
||||||
cont=true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//q=(t+l)-t1;
|
|
||||||
//br+=(1.0/double(l))*double(q);
|
|
||||||
|
|
||||||
} else if (t+l>t2) {
|
|
||||||
q=t2-t;
|
|
||||||
br+=(1.0/double(l))*double(q);
|
|
||||||
continue;
|
|
||||||
} else
|
|
||||||
br+=1.0;
|
|
||||||
|
|
||||||
T+=TV[i]/2.0;
|
|
||||||
L+=l/1000.0;
|
|
||||||
}
|
}
|
||||||
if (cont) continue;
|
i=be;
|
||||||
breaths2.push_back(br);
|
for (;i>bm;i--) {
|
||||||
breaths2_start.push_back(t1+window/2);
|
if (qAbs(m_filtered[i]) > cutoffval) {
|
||||||
//TV2_start.push_back(t2);
|
be=i;
|
||||||
TV2.push_back(T);
|
break;
|
||||||
//out->AddEvent(t,br);
|
|
||||||
//stage2[z++]=br;
|
|
||||||
|
|
||||||
t1+=window/2.0;
|
|
||||||
t2+=window/2.0;
|
|
||||||
} while (t2<in->last() && !done);
|
|
||||||
|
|
||||||
for (int i=2;i<breaths2.size()-2;i++) {
|
|
||||||
t=breaths2_start[i];
|
|
||||||
med.clear();
|
|
||||||
for (int j=0;j<5;j++) {
|
|
||||||
med.push_back(breaths2[i+j-2]);
|
|
||||||
}
|
|
||||||
qSort(med);
|
|
||||||
br=med[2];
|
|
||||||
if (out) out->AddEvent(t,br);
|
|
||||||
|
|
||||||
//t=TV2_start[i];
|
|
||||||
med.clear();
|
|
||||||
for (int j=0;j<5;j++) {
|
|
||||||
med.push_back(TV2[i+j-2]);
|
|
||||||
}
|
|
||||||
qSort(med);
|
|
||||||
tmp=med[3];
|
|
||||||
|
|
||||||
if (tv) tv->AddEvent(t,tmp);
|
|
||||||
|
|
||||||
if (mv) mv->AddEvent(t,(tmp*br)/1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] stage2;
|
|
||||||
delete [] stage1;
|
|
||||||
|
|
||||||
return out->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate RespiratoryRate graph
|
|
||||||
int calcRespRate(Session *session)
|
|
||||||
{
|
|
||||||
if (session->machine()->GetType()!=MT_CPAP) return 0;
|
|
||||||
if (session->machine()->GetClass()!=STR_MACH_PRS1) return 0;
|
|
||||||
if (!session->eventlist.contains(CPAP_FlowRate))
|
|
||||||
return 0; //need flow waveform
|
|
||||||
|
|
||||||
if (session->eventlist.contains(CPAP_RespRate))
|
|
||||||
return 0; // already exists?
|
|
||||||
|
|
||||||
EventList *flow, *rr=NULL, *tv=NULL, *mv=NULL;
|
|
||||||
|
|
||||||
if (!session->eventlist.contains(CPAP_TidalVolume)) {
|
|
||||||
tv=new EventList(EVL_Event);
|
|
||||||
} else tv=NULL;
|
|
||||||
if (!session->eventlist.contains(CPAP_MinuteVent)) {
|
|
||||||
mv=new EventList(EVL_Event);
|
|
||||||
} else mv=NULL;
|
|
||||||
if (!session->eventlist.contains(CPAP_RespRate)) {
|
|
||||||
rr=new EventList(EVL_Event);
|
|
||||||
} else rr=NULL;
|
|
||||||
|
|
||||||
if (!rr && !tv && !mv) return 0; // don't bother, but flagging won't run either..
|
|
||||||
if (rr) session->eventlist[CPAP_RespRate].push_back(rr);
|
|
||||||
if (tv) session->eventlist[CPAP_TidalVolume].push_back(tv);
|
|
||||||
if (mv) session->eventlist[CPAP_MinuteVent].push_back(mv);
|
|
||||||
|
|
||||||
int cnt=0;
|
|
||||||
for (int ws=0; ws < session->eventlist[CPAP_FlowRate].size(); ws++) {
|
|
||||||
flow=session->eventlist[CPAP_FlowRate][ws];
|
|
||||||
if (flow->count() > 5) {
|
|
||||||
cnt+=filterFlow(session, flow,rr,tv,mv,flow->rate());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cnt;
|
|
||||||
|
st=start + bs * m_rate;
|
||||||
|
mt=start + bm * m_rate;
|
||||||
|
et=start + be * m_rate;
|
||||||
|
|
||||||
|
len=st-lastet;
|
||||||
|
dur=len/1000.0;
|
||||||
|
if (dur>=duration) {
|
||||||
|
if (!uf1) {
|
||||||
|
uf1=m_session->AddEventList(CPAP_UserFlag1,EVL_Event);
|
||||||
|
}
|
||||||
|
uf1->AddEvent(st-len/2,dur);
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
// Uncomment to use UserFlags to show waveform crossover points
|
||||||
|
// Good for debugging this stuff. (Make sure to add the EventLists up above)
|
||||||
|
|
||||||
|
if (val > cutoffval) {
|
||||||
|
//uf2->AddEvent(st,0);
|
||||||
|
//uf2->AddEvent(mt,0);
|
||||||
|
//uf3->AddEvent(et,0);
|
||||||
|
lastet=et;
|
||||||
|
lastst=st;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
//EventList *uf1=NULL;
|
||||||
|
|
||||||
|
int lastbad=-1;
|
||||||
|
qint64 firstbad=0;
|
||||||
|
|
||||||
|
bool fr=false; // flow restriction
|
||||||
|
for (int i=0;i<numbreaths;i++) {
|
||||||
|
st=start+ breaths[i].start * m_rate;
|
||||||
|
et=start+ breaths[i].end * m_rate;
|
||||||
|
|
||||||
|
fr=false;
|
||||||
|
int j=i;
|
||||||
|
for (j=i;j<numbreaths;j++) {
|
||||||
|
mx=breaths[j].max;
|
||||||
|
mn=breaths[j].min;
|
||||||
|
val=mx-mn;
|
||||||
|
if (val > cutoffval)
|
||||||
|
break;
|
||||||
|
fr=true;
|
||||||
|
et=start + breaths[j].end * m_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (fr) {
|
||||||
|
i=j-1; // rewind
|
||||||
|
|
||||||
|
len=et-st;
|
||||||
|
dur=(len) / 1000.0;
|
||||||
|
|
||||||
|
if (dur >= duration) {
|
||||||
|
if (!uf1) {
|
||||||
|
uf1=m_session->AddEventList(CPAP_UserFlag1,EVL_Event);
|
||||||
|
}
|
||||||
|
uf1->AddEvent(et-(len/2),dur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void calcRespRate(Session *session, FlowParser * flowparser)
|
void calcRespRate(Session *session, FlowParser * flowparser)
|
||||||
{
|
{
|
||||||
@ -901,7 +696,7 @@ void calcRespRate(Session *session, FlowParser * flowparser)
|
|||||||
// if (session->machine()->GetClass()!=STR_MACH_PRS1) return;
|
// if (session->machine()->GetClass()!=STR_MACH_PRS1) return;
|
||||||
|
|
||||||
if (!session->eventlist.contains(CPAP_FlowRate)) {
|
if (!session->eventlist.contains(CPAP_FlowRate)) {
|
||||||
qDebug() << "calcRespRate called without FlowRate waveform available";
|
//qDebug() << "calcRespRate called without FlowRate waveform available";
|
||||||
return; //need flow waveform
|
return; //need flow waveform
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,7 +704,7 @@ void calcRespRate(Session *session, FlowParser * flowparser)
|
|||||||
if (!flowparser) {
|
if (!flowparser) {
|
||||||
flowparser=new FlowParser();
|
flowparser=new FlowParser();
|
||||||
trashfp=true;
|
trashfp=true;
|
||||||
qDebug() << "calcRespRate called without valid FlowParser object.. using a slow throw-away!";
|
//qDebug() << "calcRespRate called without valid FlowParser object.. using a slow throw-away!";
|
||||||
//return;
|
//return;
|
||||||
} else {
|
} else {
|
||||||
trashfp=false;
|
trashfp=false;
|
||||||
@ -954,12 +749,12 @@ void calcRespRate(Session *session, FlowParser * flowparser)
|
|||||||
//flowparser->addFilter(FilterPercentile,5,0.5);
|
//flowparser->addFilter(FilterPercentile,5,0.5);
|
||||||
//flowparser->addFilter(FilterXPass,0.5);
|
//flowparser->addFilter(FilterXPass,0.5);
|
||||||
EventList *flow;
|
EventList *flow;
|
||||||
int cnt=0;
|
|
||||||
for (int ws=0; ws < session->eventlist[CPAP_FlowRate].size(); ws++) {
|
for (int ws=0; ws < session->eventlist[CPAP_FlowRate].size(); ws++) {
|
||||||
flow=session->eventlist[CPAP_FlowRate][ws];
|
flow=session->eventlist[CPAP_FlowRate][ws];
|
||||||
if (flow->count() > 20) {
|
if (flow->count() > 20) {
|
||||||
flowparser->openFlow(session, flow);
|
flowparser->openFlow(session, flow);
|
||||||
flowparser->calc(calcResp, calcTv, calcTi ,calcTe, calcMv);
|
flowparser->calc(calcResp, calcTv, calcTi ,calcTe, calcMv);
|
||||||
|
flowparser->flagEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trashfp) {
|
if (trashfp) {
|
||||||
|
@ -105,6 +105,7 @@ public:
|
|||||||
|
|
||||||
// Minute vent needs Resp & TV calcs made here..
|
// Minute vent needs Resp & TV calcs made here..
|
||||||
void calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool calcMv);
|
void calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool calcMv);
|
||||||
|
void flagEvents();
|
||||||
|
|
||||||
/*void calcTidalVolume();
|
/*void calcTidalVolume();
|
||||||
void calcRespRate();
|
void calcRespRate();
|
||||||
@ -113,10 +114,7 @@ public:
|
|||||||
|
|
||||||
QList<Filter> m_filters;
|
QList<Filter> m_filters;
|
||||||
protected:
|
protected:
|
||||||
QVector<BreathPeak> breaths_lower;
|
|
||||||
QVector<BreathPeak> breaths_upper;
|
|
||||||
QVector<BreathPeak> breaths;
|
QVector<BreathPeak> breaths;
|
||||||
QList<BreathPeak> breatsh_good;
|
|
||||||
|
|
||||||
int m_samples;
|
int m_samples;
|
||||||
EventList * m_flow;
|
EventList * m_flow;
|
||||||
|
@ -184,7 +184,7 @@ EventDataType Day::percentile(ChannelID code,EventDataType percentile)
|
|||||||
// Can't assume this in any multi day calculations..
|
// Can't assume this in any multi day calculations..
|
||||||
if (lastgain>0) {
|
if (lastgain>0) {
|
||||||
if (gain!=lastgain) {
|
if (gain!=lastgain) {
|
||||||
qDebug() << "Gains differ across sessions :(";
|
qDebug() << "Gains differ across sessions: " << gain << lastgain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastgain=gain;
|
lastgain=gain;
|
||||||
|
@ -444,7 +444,7 @@ CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_
|
|||||||
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_FlowRate, CPAP_MaskPressure, CPAP_MaskPressureHi,
|
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_FlowRate, CPAP_MaskPressure, CPAP_MaskPressureHi,
|
||||||
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
|
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
|
||||||
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
|
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
|
||||||
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
|
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
|
||||||
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_PSMin, CPAP_PSMax, CPAP_Test1, CPAP_Test2;
|
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_PSMin, CPAP_PSMax, CPAP_Test1, CPAP_Test2;
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_
|
|||||||
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_FlowRate, CPAP_MaskPressure, CPAP_MaskPressureHi,
|
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_FlowRate, CPAP_MaskPressure, CPAP_MaskPressureHi,
|
||||||
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
|
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
|
||||||
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
|
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
|
||||||
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
|
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
|
||||||
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_PSMin, CPAP_PSMax, CPAP_Test1, CPAP_Test2;
|
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_PSMin, CPAP_PSMax, CPAP_Test1, CPAP_Test2;
|
||||||
|
|
||||||
extern ChannelID RMS9_E01, RMS9_E02, RMS9_EPR, RMS9_EPRSet, RMS9_SetPressure;
|
extern ChannelID RMS9_E01, RMS9_E02, RMS9_EPR, RMS9_EPRSet, RMS9_SetPressure;
|
||||||
|
@ -118,6 +118,7 @@ void init()
|
|||||||
|
|
||||||
CPAP_UserFlag1=schema::channel["UserFlag1"].id();
|
CPAP_UserFlag1=schema::channel["UserFlag1"].id();
|
||||||
CPAP_UserFlag2=schema::channel["UserFlag2"].id();
|
CPAP_UserFlag2=schema::channel["UserFlag2"].id();
|
||||||
|
CPAP_UserFlag3=schema::channel["UserFlag3"].id();
|
||||||
RMS9_E01=schema::channel["RMS9_E01"].id();
|
RMS9_E01=schema::channel["RMS9_E01"].id();
|
||||||
RMS9_E02=schema::channel["RMS9_E02"].id();
|
RMS9_E02=schema::channel["RMS9_E02"].id();
|
||||||
RMS9_EPR=schema::channel["EPR"].id();
|
RMS9_EPR=schema::channel["EPR"].id();
|
||||||
|
@ -710,7 +710,10 @@ void Session::UpdateSummaries()
|
|||||||
ChannelID id;
|
ChannelID id;
|
||||||
QHash<ChannelID,QVector<EventList *> >::iterator c;
|
QHash<ChannelID,QVector<EventList *> >::iterator c;
|
||||||
calcAHIGraph(this);
|
calcAHIGraph(this);
|
||||||
|
|
||||||
|
// Calculates RespRate and related waveforms (Tv, MV, Te, Ti) if missing
|
||||||
calcRespRate(this);
|
calcRespRate(this);
|
||||||
|
|
||||||
calcLeaks(this);
|
calcLeaks(this);
|
||||||
calcSPO2Drop(this);
|
calcSPO2Drop(this);
|
||||||
calcPulseChange(this);
|
calcPulseChange(this);
|
||||||
|
23
daily.cpp
23
daily.cpp
@ -157,6 +157,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
|||||||
if (PROFILE.cpap->userEventFlagging()) {
|
if (PROFILE.cpap->userEventFlagging()) {
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_UserFlag1,QColor("yellow"),tr("UF1"))));
|
fg->AddLayer((new gFlagsLine(CPAP_UserFlag1,QColor("yellow"),tr("UF1"))));
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_UserFlag2,QColor("green"),tr("UF2"))));
|
fg->AddLayer((new gFlagsLine(CPAP_UserFlag2,QColor("green"),tr("UF2"))));
|
||||||
|
fg->AddLayer((new gFlagsLine(CPAP_UserFlag3,QColor("brown"),tr("UF3"))));
|
||||||
}
|
}
|
||||||
//fg->AddLayer((new gFlagsLine(PRS1_0B,QColor("dark green"),tr("U0B"))));
|
//fg->AddLayer((new gFlagsLine(PRS1_0B,QColor("dark green"),tr("U0B"))));
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_VSnore2,QColor("red"),tr("VS2"))));
|
fg->AddLayer((new gFlagsLine(CPAP_VSnore2,QColor("red"),tr("VS2"))));
|
||||||
@ -195,6 +196,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
|||||||
if (PROFILE.cpap->userEventFlagging()) {
|
if (PROFILE.cpap->userEventFlagging()) {
|
||||||
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag1,QColor("yellow"),tr("U1"),FT_Bar)));
|
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag1,QColor("yellow"),tr("U1"),FT_Bar)));
|
||||||
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag2,QColor("orange"),tr("U2"),FT_Bar)));
|
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag2,QColor("orange"),tr("U2"),FT_Bar)));
|
||||||
|
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag3,QColor("brown"),tr("U3"),FT_Bar)));
|
||||||
}
|
}
|
||||||
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_SPO2Drop,QColor("red"),tr("O2"))));
|
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_SPO2Drop,QColor("red"),tr("O2"))));
|
||||||
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_PulseChange,QColor("blue"),tr("PC"),FT_Dot)));
|
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_PulseChange,QColor("blue"),tr("PC"),FT_Dot)));
|
||||||
@ -468,6 +470,7 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day)
|
|||||||
&& (code!=CPAP_RERA)
|
&& (code!=CPAP_RERA)
|
||||||
&& (code!=CPAP_UserFlag1)
|
&& (code!=CPAP_UserFlag1)
|
||||||
&& (code!=CPAP_UserFlag2)
|
&& (code!=CPAP_UserFlag2)
|
||||||
|
&& (code!=CPAP_UserFlag3)
|
||||||
&& (code!=CPAP_NRI)
|
&& (code!=CPAP_NRI)
|
||||||
&& (code!=CPAP_LeakFlag)
|
&& (code!=CPAP_LeakFlag)
|
||||||
&& (code!=CPAP_ExP)
|
&& (code!=CPAP_ExP)
|
||||||
@ -476,7 +479,7 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day)
|
|||||||
&& (code!=CPAP_VSnore2)
|
&& (code!=CPAP_VSnore2)
|
||||||
&& (code!=CPAP_VSnore)) continue;
|
&& (code!=CPAP_VSnore)) continue;
|
||||||
|
|
||||||
if (!userflags && ((code==CPAP_UserFlag1) || (code==CPAP_UserFlag2))) continue;
|
if (!userflags && ((code==CPAP_UserFlag1) || (code==CPAP_UserFlag2) || (code==CPAP_UserFlag3))) continue;
|
||||||
|
|
||||||
QTreeWidgetItem *mcr;
|
QTreeWidgetItem *mcr;
|
||||||
if (mcroot.find(code)==mcroot.end()) {
|
if (mcroot.find(code)==mcroot.end()) {
|
||||||
@ -826,6 +829,15 @@ void Daily::Load(QDate date)
|
|||||||
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5%</font></b></td></tr>\n")
|
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5%</font></b></td></tr>\n")
|
||||||
.arg("#80ff80").arg("black").arg(tr("PB/CSR")).arg(schema::channel[CPAP_CSR].description()).arg(csr,0,'f',2).arg(CPAP_CSR);
|
.arg("#80ff80").arg("black").arg(tr("PB/CSR")).arg(schema::channel[CPAP_CSR].description()).arg(csr,0,'f',2).arg(CPAP_CSR);
|
||||||
}
|
}
|
||||||
|
if (PROFILE.cpap->userEventFlagging()) {
|
||||||
|
EventDataType uf1=cpap->count(CPAP_UserFlag1) / cpap->hours();
|
||||||
|
if (uf1>0)
|
||||||
|
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5</font></b></td></tr>\n")
|
||||||
|
.arg("#e0e0e0").arg("black")
|
||||||
|
.arg(tr("User Flags"))
|
||||||
|
.arg(schema::channel[CPAP_UserFlag1].description())
|
||||||
|
.arg(uf1,0,'f',2).arg(CPAP_UserFlag1);
|
||||||
|
}
|
||||||
|
|
||||||
html+="</table></td>";
|
html+="</table></td>";
|
||||||
|
|
||||||
@ -844,15 +856,6 @@ void Daily::Load(QDate date)
|
|||||||
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info2 href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5</font></b></td></tr>\n")
|
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info2 href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5</font></b></td></tr>\n")
|
||||||
.arg("#ff4040").arg("black").arg(tr("VSnore2")).arg(schema::channel[CPAP_VSnore2].description()).arg(cpap->count(CPAP_VSnore2)/cpap->hours(),0,'f',2).arg(CPAP_VSnore2);
|
.arg("#ff4040").arg("black").arg(tr("VSnore2")).arg(schema::channel[CPAP_VSnore2].description()).arg(cpap->count(CPAP_VSnore2)/cpap->hours(),0,'f',2).arg(CPAP_VSnore2);
|
||||||
}
|
}
|
||||||
if (PROFILE.cpap->userEventFlagging()) {
|
|
||||||
EventDataType uf1=cpap->count(CPAP_UserFlag1) / cpap->hours();
|
|
||||||
if (uf1>0)
|
|
||||||
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a class=info2 href='event=%6'>%3<span>%4</span></a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%5</font></b></td></tr>\n")
|
|
||||||
.arg("#e0e0e0").arg("black")
|
|
||||||
.arg(tr("User Flags"))
|
|
||||||
.arg(schema::channel[CPAP_UserFlag1].description())
|
|
||||||
.arg(uf1,0,'f',2).arg(CPAP_UserFlag1);
|
|
||||||
}
|
|
||||||
html+="</table></td>";
|
html+="</table></td>";
|
||||||
} else if (cpap->machine->GetClass()==STR_MACH_Intellipap) {
|
} else if (cpap->machine->GetClass()==STR_MACH_Intellipap) {
|
||||||
html+="<td colspan=2 valign=top><table cellspacing=0 cellpadding=2 border=0 width='100%'>";
|
html+="<td colspan=2 valign=top><table cellspacing=0 cellpadding=2 border=0 width='100%'>";
|
||||||
|
@ -21,14 +21,17 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
|
|||||||
<channel id="0x100a" class="data" name="LeakFlag" details="Leak Event" label="L" unit="events/hour" color="dark blue"/>
|
<channel id="0x100a" class="data" name="LeakFlag" details="Leak Event" label="L" unit="events/hour" color="dark blue"/>
|
||||||
<channel id="0x100b" class="data" name="NRI" details="Non-Responding Event" label="NRI" unit="events/hour" color="orange"/>
|
<channel id="0x100b" class="data" name="NRI" details="Non-Responding Event" label="NRI" unit="events/hour" color="orange"/>
|
||||||
<channel id="0x100c" class="data" name="ExP" details="Exhale Puff" label="EP" unit="events/hour" color="dark magenta"/>
|
<channel id="0x100c" class="data" name="ExP" details="Exhale Puff" label="EP" unit="events/hour" color="dark magenta"/>
|
||||||
<channel id="0x101e" class="data" name="UserFlag1" details="User Flag (Custom Event)" label="UF1" unit="events/hour" color="dark cyan"/>
|
<channel id="0x101e" class="data" name="UserFlag1" details="User Flag #1" label="UF1" unit="events/hour" color="dark cyan"/>
|
||||||
<channel id="0x101f" class="data" name="UserFlag2" details="User Flag #2" label="UF2" unit="events/hour" color="dark cyan"/>
|
<channel id="0x101f" class="data" name="UserFlag2" details="User Flag #2" label="UF2" unit="events/hour" color="dark blue"/>
|
||||||
|
|
||||||
<channel id="0x1020" class="data" name="PressureMin" details="Min Therapy Pressure" label="Pressure" color="black"/>
|
<channel id="0x1020" class="data" name="PressureMin" details="Min Therapy Pressure" label="Pressure" color="black"/>
|
||||||
<channel id="0x1021" class="data" name="PressureMax" details="Max Therapy Pressure" label="Pressure" color="black"/>
|
<channel id="0x1021" class="data" name="PressureMax" details="Max Therapy Pressure" label="Pressure" color="black"/>
|
||||||
<channel id="0x1022" class="data" name="RampTime" details="Ramp Time" label="Ramp Time" color="black"/>
|
<channel id="0x1022" class="data" name="RampTime" details="Ramp Time" label="Ramp Time" color="black"/>
|
||||||
<channel id="0x1023" class="data" name="RampPressure" details="Ramp Starting Pressure" label="Ramp Pr." color="black"/>
|
<channel id="0x1023" class="data" name="RampPressure" details="Ramp Starting Pressure" label="Ramp Pr." color="black"/>
|
||||||
|
|
||||||
|
<channel id="0x1024" class="data" name="UserFlag3" details="User Flag #3" label="UF3" unit="events/hour" color="dark grey"/>
|
||||||
|
|
||||||
|
|
||||||
<channel id="0x1100" class="data" name="FlowRate" details="Flow Rate" label="Flow Rate" unit="L/min" color="black"/>
|
<channel id="0x1100" class="data" name="FlowRate" details="Flow Rate" label="Flow Rate" unit="L/min" color="black"/>
|
||||||
<channel id="0x1101" class="data" name="MaskPressure" details="Mask Pressure" label="Mask Pressure" unit="cmH20" color="blue"/>
|
<channel id="0x1101" class="data" name="MaskPressure" details="Mask Pressure" label="Mask Pressure" unit="cmH20" color="blue"/>
|
||||||
<channel id="0x1102" class="data" name="MaskPressureHi" details="Mask Pressure" label="Mask Pressure (Hi-Res)" unit="cmH20" color="blue" link="0x1101"/>
|
<channel id="0x1102" class="data" name="MaskPressureHi" details="Mask Pressure" label="Mask Pressure (Hi-Res)" unit="cmH20" color="blue" link="0x1101"/>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<li>Can print from both the Statistics & Help Browser pages.</li>
|
<li>Can print from both the Statistics & Help Browser pages.</li>
|
||||||
<li>Option to automatically maintain backup folder for ResMed users. (on by default)</li>
|
<li>Option to automatically maintain backup folder for ResMed users. (on by default)</li>
|
||||||
<li>Compression options to save disk space for SleepyHead data and backups.</li>
|
<li>Compression options to save disk space for SleepyHead data and backups.</li>
|
||||||
|
<li>Rewritten Flow Rate Calculations Module gives MinuteVent, RespiratoryRate, TidalVolume, Te & Ti to machines where it's missing, (provided Flow Waveform is available) and is much more accurate than before.</li>
|
||||||
<li>New Context cube to make empty pages more attractive.. Yes you can switch it off. No it doesn't take much resources.</li>
|
<li>New Context cube to make empty pages more attractive.. Yes you can switch it off. No it doesn't take much resources.</li>
|
||||||
<li>Plenty of other bug fixes, including more oximetry fixes.</li>
|
<li>Plenty of other bug fixes, including more oximetry fixes.</li>
|
||||||
</list></p>
|
</list></p>
|
||||||
|
@ -974,7 +974,7 @@ void MainWindow::on_summaryButton_clicked()
|
|||||||
"a:link,a:visited { color: inherit; text-decoration: none; }" //font-weight: normal;
|
"a:link,a:visited { color: inherit; text-decoration: none; }" //font-weight: normal;
|
||||||
"a:hover { background-color: inherit; color: white; text-decoration:none; font-weight: bold; }"
|
"a:hover { background-color: inherit; color: white; text-decoration:none; font-weight: bold; }"
|
||||||
"</style></head><body>";
|
"</style></head><body>";
|
||||||
recbox+="<table width=100% cellpadding=2 cellspacing=0>";
|
recbox+="<table width=100% cellpadding=1 cellspacing=0>";
|
||||||
int numdays=AHI.size();
|
int numdays=AHI.size();
|
||||||
if (numdays>1) {
|
if (numdays>1) {
|
||||||
int z=numdays/2;
|
int z=numdays/2;
|
||||||
@ -1044,7 +1044,7 @@ void MainWindow::on_summaryButton_clicked()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
||||||
.arg(tr("Best RX Setting"));
|
.arg(tr("Best RX Setting"));
|
||||||
recbox+=QString("<tr><td valign=top>Start<br/>End</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
recbox+=QString("<tr><td valign=top>Start<br/>End</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
||||||
.arg(tmpRX[ls]->first.toString(Qt::ISODate))
|
.arg(tmpRX[ls]->first.toString(Qt::ISODate))
|
||||||
@ -1080,7 +1080,7 @@ void MainWindow::on_summaryButton_clicked()
|
|||||||
modestr=tr("ST/ASV");
|
modestr=tr("ST/ASV");
|
||||||
}
|
}
|
||||||
|
|
||||||
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=0 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
||||||
.arg(tr("Worst RX Setting"));
|
.arg(tr("Worst RX Setting"));
|
||||||
recbox+=QString("<tr><td valign=top>Start<br/>End</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
recbox+=QString("<tr><td valign=top>Start<br/>End</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
||||||
.arg(tmpRX[0]->first.toString(Qt::ISODate))
|
.arg(tmpRX[0]->first.toString(Qt::ISODate))
|
||||||
|
Loading…
Reference in New Issue
Block a user