mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-05 10:40:42 +00:00
Optimize waveform/leak/pressure processing calcs, FPIcon cleanup
This commit is contained in:
parent
ae3fe507b1
commit
f0356ee99c
@ -223,7 +223,7 @@ void FlowParser::openFlow(Session *session, EventList *flow)
|
|||||||
EventStoreType *eptr = inraw + m_samples;
|
EventStoreType *eptr = inraw + m_samples;
|
||||||
|
|
||||||
// Convert from store type to floats..
|
// Convert from store type to floats..
|
||||||
for (; inraw < eptr; inraw++) {
|
for (; inraw < eptr; ++inraw) {
|
||||||
*buf++ = EventDataType(*inraw) * m_gain;
|
*buf++ = EventDataType(*inraw) * m_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,10 +437,19 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
|
|
||||||
qint32 timeval = 0; // Time relative to start
|
qint32 timeval = 0; // Time relative to start
|
||||||
|
|
||||||
for (idx = 0; idx < nm; idx++) {
|
|
||||||
bs = breaths[idx].start;
|
|
||||||
bm = breaths[idx].middle;
|
BreathPeak * bpstr = breaths.data();
|
||||||
be = breaths[idx].end;
|
BreathPeak * bpend = bpstr + nm;
|
||||||
|
for (BreathPeak * bp = bpstr; bp != bpend; ++bp) {
|
||||||
|
bs = bp->start;
|
||||||
|
bm = bp->middle;
|
||||||
|
be = bp->end;
|
||||||
|
|
||||||
|
// for (idx = 0; idx < nm; idx++) {
|
||||||
|
// bs = breaths[idx].start;
|
||||||
|
// bm = breaths[idx].middle;
|
||||||
|
// be = breaths[idx].end;
|
||||||
|
|
||||||
// Calculate start, middle and end time of this breath
|
// Calculate start, middle and end time of this breath
|
||||||
st = start + bs * m_rate;
|
st = start + bs * m_rate;
|
||||||
@ -524,9 +533,13 @@ void FlowParser::calc(bool calcResp, bool calcTv, bool calcTi, bool calcTe, bool
|
|||||||
//et2=et;
|
//et2=et;
|
||||||
|
|
||||||
// Step back through last minute and count breaths
|
// Step back through last minute and count breaths
|
||||||
for (int i = idx; i >= 0; i--) {
|
BreathPeak *bpstr1 = bpstr-1;
|
||||||
st2 = start + double(breaths[i].start) * m_rate;
|
for (BreathPeak *p = bp; p != bpstr1; --p) {
|
||||||
et2 = start + double(breaths[i].end) * m_rate;
|
st2 = start + double(p->start) * m_rate;
|
||||||
|
et2 = start + double(p->end) * m_rate;
|
||||||
|
// for (int i = idx; i >= 0; i--) {
|
||||||
|
// st2 = start + double(breaths[i].start) * m_rate;
|
||||||
|
// et2 = start + double(breaths[i].end) * m_rate;
|
||||||
|
|
||||||
if (et2 < stmin) {
|
if (et2 < stmin) {
|
||||||
break;
|
break;
|
||||||
@ -631,13 +644,21 @@ void FlowParser::flagEvents()
|
|||||||
|
|
||||||
bool allowDuplicates = PROFILE.cpap->userEventDuplicates();
|
bool allowDuplicates = PROFILE.cpap->userEventDuplicates();
|
||||||
|
|
||||||
for (int i = 0; i < numbreaths; i++) {
|
BreathPeak *bpstr = breaths.data();
|
||||||
mx = breaths[i].max;
|
BreathPeak *bpend = bpstr + numbreaths;
|
||||||
mn = breaths[i].min;
|
|
||||||
br.push_back(qAbs(mx));
|
for (BreathPeak *p = bpstr; p != bpend; ++p) {
|
||||||
br.push_back(qAbs(mn));
|
br.push_back(qAbs(p->max));
|
||||||
|
br.push_back(qAbs(p->min));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for (int i = 0; i < numbreaths; i++) {
|
||||||
|
// mx = breaths[i].max;
|
||||||
|
// mn = breaths[i].min;
|
||||||
|
// br.push_back(qAbs(mx));
|
||||||
|
// br.push_back(qAbs(mn));
|
||||||
|
// }
|
||||||
|
|
||||||
//EventList * uf2=m_session->AddEventList(CPAP_UserFlag2,EVL_Event);
|
//EventList * uf2=m_session->AddEventList(CPAP_UserFlag2,EVL_Event);
|
||||||
//EventList * uf3=m_session->AddEventList(CPAP_UserFlag3,EVL_Event);
|
//EventList * uf3=m_session->AddEventList(CPAP_UserFlag3,EVL_Event);
|
||||||
|
|
||||||
@ -651,13 +672,19 @@ void FlowParser::flagEvents()
|
|||||||
|
|
||||||
int bs, bm, be, bs1, bm1, be1;
|
int bs, bm, be, bs1, bm1, be1;
|
||||||
|
|
||||||
for (int i = 0; i < numbreaths; i++) {
|
for (BreathPeak *p = bpstr; p != bpend; ++p) {
|
||||||
bs = breaths[i].start;
|
bs = p->start;
|
||||||
bm = breaths[i].middle;
|
bm = p->middle;
|
||||||
be = breaths[i].end;
|
be = p->end;
|
||||||
|
mx = p->max;
|
||||||
|
mn = p->min;
|
||||||
|
// for (int i = 0; i < numbreaths; i++) {
|
||||||
|
// bs = breaths[i].start;
|
||||||
|
// bm = breaths[i].middle;
|
||||||
|
// be = breaths[i].end;
|
||||||
|
|
||||||
mx = breaths[i].max;
|
// mx = breaths[i].max;
|
||||||
mn = breaths[i].min;
|
// mn = breaths[i].min;
|
||||||
val = mx - mn;
|
val = mx - mn;
|
||||||
|
|
||||||
// if (qAbs(mx) > cutoffval) {
|
// if (qAbs(mx) > cutoffval) {
|
||||||
@ -779,8 +806,8 @@ void calcRespRate(Session *session, FlowParser *flowparser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QVector<EventList *> &list = session->eventlist[CPAP_RespRate];
|
QVector<EventList *> &list = session->eventlist[CPAP_RespRate];
|
||||||
|
int size = list.size();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < size; ++i) {
|
||||||
delete list[i];
|
delete list[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,7 +815,8 @@ void calcRespRate(Session *session, FlowParser *flowparser)
|
|||||||
|
|
||||||
QVector<EventList *> &list2 = session->eventlist[CPAP_TidalVolume];
|
QVector<EventList *> &list2 = session->eventlist[CPAP_TidalVolume];
|
||||||
|
|
||||||
for (int i = 0; i < list2.size(); i++) {
|
size = list2.size();
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
delete list2[i];
|
delete list2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,7 +824,8 @@ void calcRespRate(Session *session, FlowParser *flowparser)
|
|||||||
|
|
||||||
QVector<EventList *> &list3 = session->eventlist[CPAP_MinuteVent];
|
QVector<EventList *> &list3 = session->eventlist[CPAP_MinuteVent];
|
||||||
|
|
||||||
for (int i = 0; i < list3.size(); i++) {
|
size = list3.size();
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
delete list3[i];
|
delete list3[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,8 +842,11 @@ void calcRespRate(Session *session, FlowParser *flowparser)
|
|||||||
//flowparser->addFilter(FilterXPass,0.5);
|
//flowparser->addFilter(FilterXPass,0.5);
|
||||||
EventList *flow;
|
EventList *flow;
|
||||||
|
|
||||||
for (int ws = 0; ws < session->eventlist[CPAP_FlowRate].size(); ws++) {
|
QVector<EventList *> &EVL = session->eventlist[CPAP_FlowRate];
|
||||||
flow = session->eventlist[CPAP_FlowRate][ws];
|
int size = EVL.size();
|
||||||
|
|
||||||
|
for (int ws = 0; ws < size; ++ws) {
|
||||||
|
flow = EVL[ws];
|
||||||
|
|
||||||
if (flow->count() > 20) {
|
if (flow->count() > 20) {
|
||||||
flowparser->openFlow(session, flow);
|
flowparser->openFlow(session, flow);
|
||||||
@ -1157,23 +1189,26 @@ void zMaskProfile::scanPressure(Session *session)
|
|||||||
prescnt = session->count(CPAP_Pressure);
|
prescnt = session->count(CPAP_Pressure);
|
||||||
Pressure.reserve(prescnt);
|
Pressure.reserve(prescnt);
|
||||||
|
|
||||||
for (int j = 0; j < session->eventlist[CPAP_Pressure].size(); j++) {
|
// WTF IS THIS DOING??? WHY THE HECK DID I PUT AN INNER LOOP HERE??
|
||||||
QVector<EventList *> &el = session->eventlist[CPAP_Pressure];
|
QVector<EventList *> &EVL=session->eventlist[CPAP_Pressure];
|
||||||
|
int size = EVL.size();
|
||||||
|
for (int j = 0; j < size; ++j) {
|
||||||
|
scanPressureList(EVL[j]);
|
||||||
|
// QVector<EventList *> &el = session->eventlist[CPAP_Pressure];
|
||||||
|
|
||||||
for (int e = 0; e < el.size(); e++) {
|
// for (int e = 0; e < el.size(); e++) {
|
||||||
scanPressureList(el[e]);
|
// scanPressureList(el[e]);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
} else if (session->eventlist.contains(CPAP_IPAP)) {
|
} else if (session->eventlist.contains(CPAP_IPAP)) {
|
||||||
prescnt = session->count(CPAP_IPAP);
|
prescnt = session->count(CPAP_IPAP);
|
||||||
Pressure.reserve(prescnt);
|
Pressure.reserve(prescnt);
|
||||||
|
|
||||||
for (int j = 0; j < session->eventlist[CPAP_IPAP].size(); j++) {
|
QVector<EventList *> &EVL=session->eventlist[CPAP_IPAP];
|
||||||
QVector<EventList *> &el = session->eventlist[CPAP_IPAP];
|
int size = EVL.size();
|
||||||
|
|
||||||
for (int e = 0; e < el.size(); e++) {
|
for (int j = 0; j < size; ++j) {
|
||||||
scanPressureList(el[e]);
|
scanPressureList(EVL[j]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,6 +1230,12 @@ void zMaskProfile::scanLeakList(EventList *el)
|
|||||||
qint64 ti;
|
qint64 ti;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
|
int psize = Pressure.size();
|
||||||
|
if (psize == 0) return;
|
||||||
|
TimeValue *tvstr = Pressure.data();
|
||||||
|
TimeValue *tvend = tvstr + (psize - 1);
|
||||||
|
TimeValue *p1, *p2;
|
||||||
|
|
||||||
for (; dptr < eptr; dptr++) {
|
for (; dptr < eptr; dptr++) {
|
||||||
leak = *dptr;
|
leak = *dptr;
|
||||||
ti = start + *tptr++;
|
ti = start + *tptr++;
|
||||||
@ -1202,20 +1243,34 @@ void zMaskProfile::scanLeakList(EventList *el)
|
|||||||
found = false;
|
found = false;
|
||||||
pressure = Pressure[0].value;
|
pressure = Pressure[0].value;
|
||||||
|
|
||||||
if (Pressure.size() > 1) {
|
if (psize > 1) {
|
||||||
for (int i = 0; i < Pressure.size() - 1; i++) {
|
for (p1 = tvstr; p1 != tvend; ++p1) {
|
||||||
const TimeValue &p1 = Pressure[i];
|
p2 = p1+1;
|
||||||
const TimeValue &p2 = Pressure[i + 1];
|
|
||||||
|
|
||||||
if ((p2.time > ti) && (p1.time <= ti)) {
|
if ((p2->time > ti) && (p1->time <= ti)) {
|
||||||
pressure = p1.value;
|
pressure = p1->value;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else if (p2.time == ti) {
|
} else if (p2->time == ti) {
|
||||||
pressure = p2.value;
|
pressure = p2->value;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// for (int i = 0; i < Pressure.size() - 1; i++) {
|
||||||
|
// const TimeValue &p1 = Pressure[i];
|
||||||
|
// const TimeValue &p2 = Pressure[i + 1];
|
||||||
|
|
||||||
|
// if ((p2.time > ti) && (p1.time <= ti)) {
|
||||||
|
// pressure = p1.value;
|
||||||
|
// found = true;
|
||||||
|
// break;
|
||||||
|
// } else if (p2.time == ti) {
|
||||||
|
// pressure = p2.value;
|
||||||
|
// found = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
found = true;
|
found = true;
|
||||||
@ -1245,8 +1300,14 @@ void zMaskProfile::scanLeaks(Session *session)
|
|||||||
{
|
{
|
||||||
QVector<EventList *> &elv = session->eventlist[CPAP_LeakTotal];
|
QVector<EventList *> &elv = session->eventlist[CPAP_LeakTotal];
|
||||||
|
|
||||||
for (int i = 0; i < elv.size(); i++) {
|
int size=elv.size();
|
||||||
scanLeakList(elv[i]);
|
if (!size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QVector<EventList *>::iterator end = elv.end();
|
||||||
|
QVector<EventList *>::iterator it;
|
||||||
|
for (it = elv.begin(); it != end; ++it) {
|
||||||
|
scanLeakList(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void zMaskProfile::updatePressureMin()
|
void zMaskProfile::updatePressureMin()
|
||||||
@ -1266,14 +1327,19 @@ void zMaskProfile::updatePressureMin()
|
|||||||
|
|
||||||
int sum1, sum2, w1, w2, N, k;
|
int sum1, sum2, w1, w2, N, k;
|
||||||
|
|
||||||
for (it = pressureleaks.begin(); it != pressureleaks.end(); it++) {
|
|
||||||
|
QMap<EventStoreType, QMap<EventStoreType, quint32> >::iterator plend = pressureleaks.end();
|
||||||
|
|
||||||
|
QMap<EventStoreType, quint32>::iterator lmend;
|
||||||
|
for (it = pressureleaks.begin(); it != plend; it++) {
|
||||||
pressure = it.key();
|
pressure = it.key();
|
||||||
QMap<EventStoreType, quint32> &leakmap = it.value();
|
QMap<EventStoreType, quint32> &leakmap = it.value();
|
||||||
lks = leakmap.size();
|
lks = leakmap.size();
|
||||||
SN = 0;
|
SN = 0;
|
||||||
|
|
||||||
// First sum total counts of all leaks
|
// First sum total counts of all leaks
|
||||||
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != leakmap.end(); lit++) {
|
lmend = leakmap.end();
|
||||||
|
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != lmend; ++lit) {
|
||||||
SN += lit.value();
|
SN += lit.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1292,15 +1358,14 @@ void zMaskProfile::updatePressureMin()
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
double total = 0;
|
double total = 0;
|
||||||
|
|
||||||
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != leakmap.end();
|
// why do this effectively twice? and k = size
|
||||||
lit++, k++) {
|
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != lmend; ++lit, ++k) {
|
||||||
total += lit.value();
|
total += lit.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
pressuretotal[pressure] = total;
|
pressuretotal[pressure] = total;
|
||||||
|
|
||||||
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != leakmap.end();
|
for (QMap<EventStoreType, quint32>::iterator lit = leakmap.begin(); lit != lmend; ++lit, ++k) {
|
||||||
lit++, k++) {
|
|
||||||
//for (k=0;k < N;k++) {
|
//for (k=0;k < N;k++) {
|
||||||
v1 = lit.key();
|
v1 = lit.key();
|
||||||
w1 = lit.value();
|
w1 = lit.value();
|
||||||
@ -1379,8 +1444,13 @@ void zMaskProfile::updateProfile(Session *session)
|
|||||||
|
|
||||||
EventDataType maxcnt, maxval, lastval, lastcnt;
|
EventDataType maxcnt, maxval, lastval, lastcnt;
|
||||||
|
|
||||||
for (QMap<EventStoreType, QMap<EventStoreType, quint32> >::iterator it = pressureleaks.begin();
|
|
||||||
it != pressureleaks.end(); it++) {
|
QMap<EventStoreType, QMap<EventStoreType, quint32> >::iterator plend = pressureleaks.end();
|
||||||
|
QMap<EventStoreType, QMap<EventStoreType, quint32> >::iterator it = pressureleaks.begin();
|
||||||
|
|
||||||
|
QMap<EventStoreType, quint32>::iterator lit;
|
||||||
|
QMap<EventStoreType, quint32>::iterator lvend;
|
||||||
|
for (; it != plend; ++it) {
|
||||||
p = it.key();
|
p = it.key();
|
||||||
l = pressuremin[p];
|
l = pressuremin[p];
|
||||||
QMap<EventStoreType, quint32> &leakval = it.value();
|
QMap<EventStoreType, quint32> &leakval = it.value();
|
||||||
@ -1391,7 +1461,8 @@ void zMaskProfile::updateProfile(Session *session)
|
|||||||
|
|
||||||
maxcnt = 0, maxval = 0, lastval = 0, lastcnt = 0;
|
maxcnt = 0, maxval = 0, lastval = 0, lastcnt = 0;
|
||||||
|
|
||||||
for (QMap<EventStoreType, quint32>::iterator lit = leakval.begin(); lit != leakval.end(); lit++) {
|
lvend = leakval.end();
|
||||||
|
for (lit = leakval.begin(); lit != lvend; ++lit) {
|
||||||
cnt += lit.value();
|
cnt += lit.value();
|
||||||
|
|
||||||
if (lit.value() > maxcnt) {
|
if (lit.value() > maxcnt) {
|
||||||
@ -1418,7 +1489,7 @@ void zMaskProfile::updateProfile(Session *session)
|
|||||||
pressuremax[p] = lastval;
|
pressuremax[p] = lastval;
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for (QMap<EventStoreType, quint32>::iterator lit = leakval.begin(); lit != leakval.end(); lit++) {
|
for (lit = leakval.begin(); lit != lvend; lit++) {
|
||||||
tmp = lit.key() - mean;
|
tmp = lit.key() - mean;
|
||||||
sum += tmp * tmp;
|
sum += tmp * tmp;
|
||||||
}
|
}
|
||||||
@ -1435,16 +1506,16 @@ void zMaskProfile::updateProfile(Session *session)
|
|||||||
QMap<EventStoreType, EventDataType> pressureval2;
|
QMap<EventStoreType, EventDataType> pressureval2;
|
||||||
EventDataType max = 0, tmp2, tmp3;
|
EventDataType max = 0, tmp2, tmp3;
|
||||||
|
|
||||||
for (QMap<EventStoreType, EventDataType>::iterator it = pressuretotal.begin();
|
QMap<EventStoreType, EventDataType>::iterator ptit;
|
||||||
it != pressuretotal.end(); it++) {
|
QMap<EventStoreType, EventDataType>::iterator ptend = pressuretotal.end();
|
||||||
if (max < it.value()) { max = it.value(); }
|
for (ptit = pressuretotal.begin(); ptit != ptend; ++ptit) {
|
||||||
|
if (max < ptit.value()) { max = ptit.value(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (QMap<EventStoreType, EventDataType>::iterator it = pressuretotal.begin();
|
for (ptit = pressuretotal.begin(); ptit != pressuretotal.end(); ptit++) {
|
||||||
it != pressuretotal.end(); it++) {
|
p = ptit.key();
|
||||||
p = it.key();
|
|
||||||
tmp = pressurecount[p];
|
tmp = pressurecount[p];
|
||||||
tmp2 = it.value();
|
tmp2 = ptit.value();
|
||||||
|
|
||||||
tmp3 = (tmp / tmp2) * (tmp2 / max);
|
tmp3 = (tmp / tmp2) * (tmp2 / max);
|
||||||
|
|
||||||
@ -1546,8 +1617,18 @@ int calcLeaks(Session *session)
|
|||||||
|
|
||||||
EventList *leak = session->AddEventList(CPAP_Leak, EVL_Event, 1);
|
EventList *leak = session->AddEventList(CPAP_Leak, EVL_Event, 1);
|
||||||
|
|
||||||
for (int i = 0; i < session->eventlist[CPAP_LeakTotal].size(); i++) {
|
QVector<EventList *> & EVL = session->eventlist[CPAP_LeakTotal];
|
||||||
EventList &el = *session->eventlist[CPAP_LeakTotal][i];
|
int evlsize = EVL.size();
|
||||||
|
|
||||||
|
TimeValue *p2, *pstr, *pend;
|
||||||
|
|
||||||
|
// can this go out of the loop?
|
||||||
|
int mppressize = maskProfile->Pressure.size();
|
||||||
|
pstr = maskProfile->Pressure.data();
|
||||||
|
pend = maskProfile->Pressure.data()+(mppressize-1);
|
||||||
|
|
||||||
|
for (int i = 0; i < evlsize; ++i) {
|
||||||
|
EventList &el = *EVL[i];
|
||||||
EventDataType gain = el.gain(), tmp, val;
|
EventDataType gain = el.gain(), tmp, val;
|
||||||
int count = el.count();
|
int count = el.count();
|
||||||
EventStoreType *dptr = el.rawData();
|
EventStoreType *dptr = el.rawData();
|
||||||
@ -1560,28 +1641,41 @@ int calcLeaks(Session *session)
|
|||||||
|
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
for (; dptr < eptr; dptr++) {
|
for (; dptr < eptr; ++dptr) {
|
||||||
tmp = EventDataType(*dptr) * gain;
|
tmp = EventDataType(*dptr) * gain;
|
||||||
ti = start + *tptr++;
|
ti = start + *tptr++;
|
||||||
|
|
||||||
found = false;
|
found = false;
|
||||||
pressure = maskProfile->Pressure[0].value;
|
pressure = pstr->value;
|
||||||
|
|
||||||
for (int i = 0; i < maskProfile->Pressure.size() - 1; i++) {
|
for (TimeValue *p1 = pstr; p1 != pend; ++p1) {
|
||||||
const TimeValue &p1 = maskProfile->Pressure[i];
|
p2 = p1+1;
|
||||||
const TimeValue &p2 = maskProfile->Pressure[i + 1];
|
if ((p2->time > ti) && (p1->time <= ti)) {
|
||||||
|
pressure = p1->value;
|
||||||
if ((p2.time > ti) && (p1.time <= ti)) {
|
|
||||||
pressure = p1.value;
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else if (p2.time == ti) {
|
} else if (p2->time == ti) {
|
||||||
pressure = p2.value;
|
pressure = p2->value;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for (int i = 0; i < mppressize - 1; ++i) {
|
||||||
|
// const TimeValue &p1 = &maskProfile->Pressure[i];
|
||||||
|
// const TimeValue &p2 = maskProfile->Pressure[i + 1];
|
||||||
|
|
||||||
|
// if ((p2.time > ti) && (p1.time <= ti)) {
|
||||||
|
// pressure = p1.value;
|
||||||
|
// found = true;
|
||||||
|
// break;
|
||||||
|
// } else if (p2.time == ti) {
|
||||||
|
// pressure = p2.value;
|
||||||
|
// found = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
val = tmp - maskProfile->calcLeak(pressure);
|
val = tmp - maskProfile->calcLeak(pressure);
|
||||||
|
|
||||||
@ -1622,10 +1716,12 @@ int calcPulseChange(Session *session)
|
|||||||
|
|
||||||
int max;
|
int max;
|
||||||
|
|
||||||
for (int e = 0; e < it.value().size(); e++) {
|
int size = it.value().size();
|
||||||
|
for (int e = 0; e < size; ++e) {
|
||||||
EventList &el = *(it.value()[e]);
|
EventList &el = *(it.value()[e]);
|
||||||
|
|
||||||
for (unsigned i = 0; i < el.count(); i++) {
|
int elcount=el.count();
|
||||||
|
for (int i = 0; i < elcount; ++i) {
|
||||||
val = el.data(i);
|
val = el.data(i);
|
||||||
time = el.time(i);
|
time = el.time(i);
|
||||||
|
|
||||||
@ -1634,7 +1730,7 @@ int calcPulseChange(Session *session)
|
|||||||
lv = change;
|
lv = change;
|
||||||
max = 0;
|
max = 0;
|
||||||
|
|
||||||
for (unsigned j = i + 1; j < el.count(); j++) { // scan ahead in the window
|
for (int j = i + 1; j < elcount; ++j) { // scan ahead in the window
|
||||||
time2 = el.time(j);
|
time2 = el.time(j);
|
||||||
|
|
||||||
if (time2 > time + window) { break; }
|
if (time2 > time + window) { break; }
|
||||||
@ -1709,10 +1805,12 @@ int calcSPO2Drop(Session *session)
|
|||||||
// Calculate median baseline
|
// Calculate median baseline
|
||||||
QList<EventDataType> med;
|
QList<EventDataType> med;
|
||||||
|
|
||||||
for (int e = 0; e < it.value().size(); e++) {
|
int evsize = it.value().size();
|
||||||
|
for (int e = 0; e < evsize; ++e) {
|
||||||
EventList &el = *(it.value()[e]);
|
EventList &el = *(it.value()[e]);
|
||||||
|
|
||||||
for (unsigned i = 0; i < el.count(); i++) {
|
int elcount = el.count();
|
||||||
|
for (int i = 0; i < elcount; i++) {
|
||||||
val = el.data(i);
|
val = el.data(i);
|
||||||
time = el.time(i);
|
time = el.time(i);
|
||||||
|
|
||||||
@ -1746,10 +1844,11 @@ int calcSPO2Drop(Session *session)
|
|||||||
EventDataType current;
|
EventDataType current;
|
||||||
qDebug() << "Calculated baseline" << baseline;
|
qDebug() << "Calculated baseline" << baseline;
|
||||||
|
|
||||||
for (int e = 0; e < it.value().size(); e++) {
|
for (int e = 0; e < evsize; ++e) {
|
||||||
EventList &el = *(it.value()[e]);
|
EventList &el = *(it.value()[e]);
|
||||||
|
|
||||||
for (unsigned i = 0; i < el.count(); i++) {
|
int elcount = el.count();
|
||||||
|
for (int i = 0; i < elcount; ++i) {
|
||||||
current = el.data(i);
|
current = el.data(i);
|
||||||
|
|
||||||
if (!current) { continue; }
|
if (!current) { continue; }
|
||||||
@ -1785,7 +1884,7 @@ int calcSPO2Drop(Session *session)
|
|||||||
|
|
||||||
min = val;
|
min = val;
|
||||||
|
|
||||||
for (unsigned j = i; j < el.count(); j++) { // scan ahead in the window
|
for (int j = i; j < elcount; ++j) { // scan ahead in the window
|
||||||
time2 = el.time(j);
|
time2 = el.time(j);
|
||||||
//if (time2 > time+window) break;
|
//if (time2 > time+window) break;
|
||||||
val2 = el.data(j);
|
val2 = el.data(j);
|
||||||
|
@ -286,28 +286,97 @@ int FPIconLoader::OpenMachine(Machine *mach, QString &path, Profile *profile)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime FPIconLoader::readFPDateTime(quint8 *data)
|
// !\brief Convert F&P 32bit date format to 32bit UNIX Timestamp
|
||||||
|
quint32 convertDate(quint32 timestamp)
|
||||||
{
|
{
|
||||||
quint32 ts = (data[3] << 24) | (data[2] << 16) | ((data[1] << 8) | data[0]); // ^ 0xc00000;
|
quint8 day, month,hour, minute, second;
|
||||||
// 0x20a41b18
|
quint16 year;
|
||||||
|
|
||||||
quint8 day = ts & 0x1f; // 0X18 24
|
|
||||||
ts >>= 5; // 10520D8
|
day = timestamp & 0x1f;
|
||||||
quint8 month = ts & 0x0f; // 0X08 8
|
month = (timestamp >> 5) & 0x0f;
|
||||||
ts >>= 4; // 10520D
|
year = 2000 + ((timestamp >> 9) & 0x3f);
|
||||||
quint8 year = ts & 0x3f; // 0X0D 13
|
timestamp >>= 15;
|
||||||
ts >>= 6; // 4148
|
timestamp |= (timestamp >> 15) & 1;
|
||||||
quint8 second = ts & 0x3f; // 0X08 8
|
|
||||||
ts >>= 6; // 20A
|
// Okay, why did I swap the first and last bits of the time field?
|
||||||
quint8 minute = ts & 0x3f; // 0A 10
|
// What am I forgetting?? This seems to work properly like this
|
||||||
ts >>= 6; // 10
|
// Was I looking at older data that worked like this?
|
||||||
quint8 hour = ts & 0x1f; // 10 16
|
|
||||||
QDate date = QDate(2000 + year, month, day);
|
second = timestamp & 0x3f;
|
||||||
QTime time = QTime(hour, minute, second);
|
minute = (timestamp >> 6) & 0x3f;
|
||||||
QDateTime datetime = QDateTime(date, time, Qt::UTC);
|
hour = (timestamp >> 12) & 0x1f;
|
||||||
return datetime;
|
|
||||||
|
// in >> a1;
|
||||||
|
// in >> a2;
|
||||||
|
// t1 = a2 << 8 | a1;
|
||||||
|
|
||||||
|
// if (t1 == 0xfafe) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// day = t1 & 0x1f;
|
||||||
|
// month = (t1 >> 5) & 0x0f;
|
||||||
|
// year = 2000 + ((t1 >> 9) & 0x3f);
|
||||||
|
|
||||||
|
// in >> a1;
|
||||||
|
// in >> a2;
|
||||||
|
|
||||||
|
// ts = ((a2 << 8) | a1) << 1;
|
||||||
|
// ts |= (t1 >> 15) & 1;
|
||||||
|
|
||||||
|
// second = (ts & 0x3f);
|
||||||
|
// minute = (ts >> 6) & 0x3f;
|
||||||
|
// hour = (ts >> 12) & 0x1f;
|
||||||
|
QDateTime dt = QDateTime(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC);
|
||||||
|
|
||||||
|
return dt.toTime_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint32 convertFLWDate(quint32 timestamp)
|
||||||
|
{
|
||||||
|
quint8 day, month, hour, minute, second;
|
||||||
|
quint16 year;
|
||||||
|
|
||||||
|
day = timestamp & 0x1f;
|
||||||
|
month = (timestamp >> 5) & 0x0f;
|
||||||
|
year = 2000 + ((timestamp >> 9) & 0x3f);
|
||||||
|
timestamp >>= 15;
|
||||||
|
|
||||||
|
// Okay, why did I swap the first and last bits of the time field?
|
||||||
|
// What am I forgetting?? This seems to work properly like this
|
||||||
|
// Was I looking at older data that worked like this?
|
||||||
|
|
||||||
|
second = timestamp & 0x3f;
|
||||||
|
minute = (timestamp >> 6) & 0x3f;
|
||||||
|
hour = (timestamp >> 12) & 0x1f;
|
||||||
|
QDateTime dt = QDateTime(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC);
|
||||||
|
|
||||||
|
return dt.toTime_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
//QDateTime FPIconLoader::readFPDateTime(quint8 *data)
|
||||||
|
//{
|
||||||
|
// quint32 ts = (data[3] << 24) | (data[2] << 16) | ((data[1] << 8) | data[0]); // ^ 0xc00000;
|
||||||
|
// // 0x20a41b18
|
||||||
|
|
||||||
|
// quint8 day = ts & 0x1f; // 0X18 24
|
||||||
|
// ts >>= 5; // 10520D8
|
||||||
|
// quint8 month = ts & 0x0f; // 0X08 8
|
||||||
|
// ts >>= 4; // 10520D
|
||||||
|
// quint8 year = ts & 0x3f; // 0X0D 13
|
||||||
|
// ts >>= 6; // 4148
|
||||||
|
// quint8 second = ts & 0x3f; // 0X08 8
|
||||||
|
// ts >>= 6; // 20A
|
||||||
|
// quint8 minute = ts & 0x3f; // 0A 10
|
||||||
|
// ts >>= 6; // 10
|
||||||
|
// quint8 hour = ts & 0x1f; // 10 16
|
||||||
|
// QDate date = QDate(2000 + year, month, day);
|
||||||
|
// QTime time = QTime(hour, minute, second);
|
||||||
|
// QDateTime datetime = QDateTime(date, time, Qt::UTC);
|
||||||
|
// return datetime;
|
||||||
|
//}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*in >> a1;
|
*in >> a1;
|
||||||
in >> a2;
|
in >> a2;
|
||||||
@ -348,19 +417,13 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
{
|
{
|
||||||
Q_UNUSED(mach);
|
Q_UNUSED(mach);
|
||||||
Q_UNUSED(profile);
|
Q_UNUSED(profile);
|
||||||
QByteArray data;
|
|
||||||
quint16 t1;
|
|
||||||
quint32 ts;
|
quint32 ts;
|
||||||
double ti;
|
double ti;
|
||||||
|
|
||||||
EventList *flow = nullptr, * pressure = nullptr, *leak = nullptr;
|
EventList *flow = nullptr, * pressure = nullptr;
|
||||||
QDateTime datetime;
|
|
||||||
|
|
||||||
unsigned char *buf, *endbuf;
|
|
||||||
|
|
||||||
|
|
||||||
qDebug() << filename;
|
qDebug() << filename;
|
||||||
QByteArray header;
|
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
|
|
||||||
if (!file.open(QFile::ReadOnly)) {
|
if (!file.open(QFile::ReadOnly)) {
|
||||||
@ -368,19 +431,14 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
header = file.read(0x200);
|
QByteArray header = file.read(0x200);
|
||||||
|
|
||||||
if (header.size() != 0x200) {
|
if (header.size() != 0x200) {
|
||||||
qDebug() << "Short file" << filename;
|
qDebug() << "Short file" << filename;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char hsum = 0xff;
|
unsigned char hsum = 0x0;
|
||||||
|
for (int i = 0; i < 0x1ff; i++) { hsum ^= header[i]; }
|
||||||
for (int i = 0; i < 0x1ff; i++) {
|
|
||||||
hsum += header[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hsum != header[0x1ff]) {
|
if (hsum != header[0x1ff]) {
|
||||||
qDebug() << "Header checksum mismatch" << filename;
|
qDebug() << "Header checksum mismatch" << filename;
|
||||||
}
|
}
|
||||||
@ -399,41 +457,21 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fname.chop(4);
|
fname.chop(4);
|
||||||
QString num = fname.right(4);
|
// QString num = fname.right(4);
|
||||||
int filenum = num.toInt();
|
// int filenum = num.toInt();
|
||||||
|
|
||||||
data = file.readAll();
|
|
||||||
|
|
||||||
buf = (unsigned char *)data.data();
|
QByteArray buf = file.read(4);
|
||||||
endbuf = buf + data.size();
|
unsigned char * data = (unsigned char *)buf.data();
|
||||||
|
|
||||||
t1 = buf[1] << 8 | buf[0];
|
ts = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
|
||||||
|
|
||||||
if (t1 == 0xfafe) { // End of file marker..
|
if (ts == 0xffffffff)
|
||||||
qDebug() << "FaFE observed in" << filename;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
datetime = readFPDateTime(buf);
|
|
||||||
buf += 4;
|
|
||||||
|
|
||||||
|
|
||||||
QDate date;
|
|
||||||
QTime time;
|
|
||||||
|
|
||||||
if (!datetime.isValid()) {
|
|
||||||
qDebug() << "DateTime invalid in OpenFLW:" << filename;
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
date = datetime.date();
|
|
||||||
time = datetime.time();
|
|
||||||
ts = datetime.toTime_t();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ts = convertFLWDate(ts);
|
||||||
ti = qint64(ts) * 1000L;
|
ti = qint64(ts) * 1000L;
|
||||||
|
|
||||||
EventStoreType pbuf[256];
|
|
||||||
|
|
||||||
QMap<SessionID, Session *>::iterator sit = Sessions.find(ts);
|
QMap<SessionID, Session *>::iterator sit = Sessions.find(ts);
|
||||||
|
|
||||||
Session *sess;
|
Session *sess;
|
||||||
@ -442,8 +480,9 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
|
|
||||||
if (sit != Sessions.end()) {
|
if (sit != Sessions.end()) {
|
||||||
sess = sit.value();
|
sess = sit.value();
|
||||||
qDebug() << filenum << ":" << date << sess->session() << ":" << sess->hours() * 60.0;
|
// qDebug() << filenum << ":" << date << sess->session() << ":" << sess->hours() * 60.0;
|
||||||
} else {
|
} else {
|
||||||
|
// Create a session
|
||||||
qint64 k = -1;
|
qint64 k = -1;
|
||||||
Session *s1 = nullptr;
|
Session *s1 = nullptr;
|
||||||
sess = nullptr;
|
sess = nullptr;
|
||||||
@ -470,7 +509,7 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
sess->setFirst(CPAP_FlowRate, ti);
|
sess->setFirst(CPAP_FlowRate, ti);
|
||||||
sess->setFirst(CPAP_MaskPressure, ti);
|
sess->setFirst(CPAP_MaskPressure, ti);
|
||||||
newsess = true;
|
newsess = true;
|
||||||
qDebug() << filenum << ":" << date << "couldn't find matching session for" << ts;
|
// qDebug() << filenum << ":" << date << "couldn't find matching session for" << ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,72 +518,65 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
|
|
||||||
// F&P Overwrites this file, not appends to it.
|
// F&P Overwrites this file, not appends to it.
|
||||||
flow = new EventList(EVL_Waveform, 1.0F, 0, 0, 0, rate);
|
flow = new EventList(EVL_Waveform, 1.0F, 0, 0, 0, rate);
|
||||||
//leak=new EventList(EVL_Event,1.0,0,0,0,rate*double(samples_per_block)); // 1 per second
|
pressure = new EventList(EVL_Event, 0.01F, 0, 0, 0, rate * double(samples_per_block));
|
||||||
pressure = new EventList(EVL_Event, 0.01F, 0, 0, 0,
|
|
||||||
rate * double(samples_per_block)); // 1 per second
|
|
||||||
|
|
||||||
flow->setFirst(ti);
|
flow->setFirst(ti);
|
||||||
//leak->setFirst(ti);
|
|
||||||
pressure->setFirst(ti);
|
pressure->setFirst(ti);
|
||||||
|
|
||||||
qint16 pr;
|
quint16 endMarker;
|
||||||
quint16 lkaj;
|
quint8 offset; // offset from center for this block
|
||||||
|
quint16 pres; // mask pressure
|
||||||
|
|
||||||
|
qint16 tmp;
|
||||||
|
QByteArray block;
|
||||||
|
qint16 samples[samples_per_block];
|
||||||
|
|
||||||
EventDataType val;
|
EventDataType val;
|
||||||
qint16 tmp;
|
|
||||||
|
|
||||||
|
// Each block represents 1 second of data.. therefore Flow waveform is at 50hz, and Pressure is at 1hz
|
||||||
do {
|
do {
|
||||||
quint8 *p = buf;
|
block = file.read(105);
|
||||||
|
if (block.size() != 105) {
|
||||||
// Scan ahead looking for end of block, marked by ff ff
|
|
||||||
do {
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (p >= endbuf) {
|
|
||||||
delete flow;
|
|
||||||
delete leak;
|
|
||||||
delete pressure;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} while (!((p[0] == 0xff) && (p[1] == 0xff)));
|
|
||||||
|
|
||||||
// The Pressure and lkaj codes are before the end of block marker
|
|
||||||
p -= 3;
|
|
||||||
pr = p[1] << 8 | p[0];
|
|
||||||
lkaj = p[2];
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
pressure->AddEvent(ti, pr);
|
|
||||||
//leak->AddEvent(ti,lkaj);
|
|
||||||
|
|
||||||
do {
|
|
||||||
tmp = buf[1] << 8 | buf[0];
|
|
||||||
val = (EventDataType(tmp) / 100.0) - lkaj;
|
|
||||||
|
|
||||||
if (val < -128) { val = -128; }
|
|
||||||
else if (val > 128) { val = 128; }
|
|
||||||
|
|
||||||
buf += 2;
|
|
||||||
|
|
||||||
pbuf[i++] = val;
|
|
||||||
} while (buf < p);
|
|
||||||
|
|
||||||
flow->AddWaveform(ti, pbuf, i, rate);
|
|
||||||
ti += i * rate;
|
|
||||||
|
|
||||||
buf = p + 5;
|
|
||||||
|
|
||||||
if (buf >= endbuf) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (!((buf[0] == 0xff) && (buf[1] == 0x7f)));
|
data = (unsigned char *)block.data();
|
||||||
|
endMarker = data[1] << 8 | data[0];
|
||||||
|
if (endMarker == 0x7fff) {
|
||||||
|
// Reached end of file
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pres = data[101] << 8 | data[100];
|
||||||
|
|
||||||
|
offset = data[102];
|
||||||
|
|
||||||
|
pressure->AddEvent(ti, pres);
|
||||||
|
|
||||||
|
for (int i=0; i < samples_per_block; i++) {
|
||||||
|
tmp = ((char *)data)[(i<<1) + 1] << 8 | data[(i << 1)];
|
||||||
|
|
||||||
|
// Assuming Litres per hour, converting to litres per minute and applying offset?
|
||||||
|
// As in should be 60.0?
|
||||||
|
val = (EventDataType(tmp) / 100.0) - offset;
|
||||||
|
|
||||||
|
// if (val < -128) { val = -128; }
|
||||||
|
// else if (val > 128) { val = 128; }
|
||||||
|
|
||||||
|
samples[i]=val;
|
||||||
|
}
|
||||||
|
flow->AddWaveform(ti, samples, samples_per_block, rate);
|
||||||
|
|
||||||
|
endMarker = data[103] << 8 | data[104];
|
||||||
|
ti += samples_per_block * rate;
|
||||||
|
} while (endMarker == 0xffff);
|
||||||
|
|
||||||
|
if (endMarker != 0x7fff) {
|
||||||
|
qDebug() << fname << "waveform does not end with the corrent marker";
|
||||||
|
}
|
||||||
|
|
||||||
if (sess) {
|
if (sess) {
|
||||||
sess->setLast(CPAP_FlowRate, ti);
|
sess->setLast(CPAP_FlowRate, ti);
|
||||||
sess->setLast(CPAP_MaskPressure, ti);
|
sess->setLast(CPAP_MaskPressure, ti);
|
||||||
sess->eventlist[CPAP_FlowRate].push_back(flow);
|
sess->eventlist[CPAP_FlowRate].push_back(flow);
|
||||||
// sess->eventlist[CPAP_Leak].push_back(leak);
|
|
||||||
sess->eventlist[CPAP_MaskPressure].push_back(pressure);
|
sess->eventlist[CPAP_MaskPressure].push_back(pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,6 +587,7 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename, Profile *profile)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Open Summary file
|
// Open Summary file
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -620,32 +653,11 @@ bool FPIconLoader::OpenSummary(Machine *mach, QString filename, Profile *profile
|
|||||||
QDate date;
|
QDate date;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
in >> a1;
|
in >> ts;
|
||||||
in >> a2;
|
if (ts == 0xffffffff) break;
|
||||||
t1 = a2 << 8 | a1;
|
if ((ts & 0xfafe) == 0xfafe) break;
|
||||||
|
|
||||||
if (t1 == 0xfafe) {
|
ts = convertDate(ts);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
day = t1 & 0x1f;
|
|
||||||
month = (t1 >> 5) & 0x0f;
|
|
||||||
year = 2000 + ((t1 >> 9) & 0x3f);
|
|
||||||
|
|
||||||
in >> a1;
|
|
||||||
in >> a2;
|
|
||||||
|
|
||||||
ts = ((a2 << 8) | a1) << 1;
|
|
||||||
ts |= (t1 >> 15) & 1;
|
|
||||||
|
|
||||||
second = (ts & 0x3f);
|
|
||||||
minute = (ts >> 6) & 0x3f;
|
|
||||||
hour = (ts >> 12) & 0x1f;
|
|
||||||
|
|
||||||
datetime = QDateTime(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC);
|
|
||||||
|
|
||||||
date = datetime.date();
|
|
||||||
ts = datetime.toTime_t();
|
|
||||||
|
|
||||||
// the following two quite often match in value
|
// the following two quite often match in value
|
||||||
in >> a1; // 0x04 Run Time
|
in >> a1; // 0x04 Run Time
|
||||||
@ -733,8 +745,8 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate and test checksum
|
||||||
unsigned char hsum = 0;
|
unsigned char hsum = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 0x1ff; i++) {
|
for (int i = 0; i < 0x1ff; i++) {
|
||||||
hsum += header[i];
|
hsum += header[i];
|
||||||
}
|
}
|
||||||
@ -743,64 +755,29 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
qDebug() << "Header checksum mismatch" << filename;
|
qDebug() << "Header checksum mismatch" << filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray index;
|
QByteArray index = file.read(0x800);
|
||||||
index = file.read(0x800);
|
|
||||||
//long size=index.size(),pos=0;
|
|
||||||
QDataStream in(index);
|
QDataStream in(index);
|
||||||
|
|
||||||
in.setVersion(QDataStream::Qt_4_6);
|
in.setVersion(QDataStream::Qt_4_6);
|
||||||
in.setByteOrder(QDataStream::LittleEndian);
|
in.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint32 ts;
|
quint32 ts;
|
||||||
QDateTime datetime;
|
|
||||||
QDate date;
|
|
||||||
QTime time;
|
|
||||||
//FPDetIdx *idx=(FPDetIdx *)index.data();
|
|
||||||
|
|
||||||
|
|
||||||
QVector<quint32> times;
|
QVector<quint32> times;
|
||||||
QVector<quint16> start;
|
QVector<quint16> start;
|
||||||
QVector<quint8> records;
|
QVector<quint8> records;
|
||||||
|
|
||||||
quint16 t1;
|
|
||||||
quint16 strt;
|
quint16 strt;
|
||||||
quint8 recs, z1, z2;
|
quint8 recs;
|
||||||
|
|
||||||
int day, month, year, hour, minute, second;
|
|
||||||
|
|
||||||
int totalrecs = 0;
|
int totalrecs = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
in >> z1;
|
in >> ts;
|
||||||
in >> z2;
|
if (ts == 0xffffffff) break;
|
||||||
t1 = z2 << 8 | z1;
|
if ((ts & 0xfafe) == 0xfafe) break;
|
||||||
|
|
||||||
if (t1 == 0xfafe) {
|
ts = convertDate(ts);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
day = t1 & 0x1f;
|
|
||||||
month = (t1 >> 5) & 0x0f;
|
|
||||||
year = 2000 + ((t1 >> 9) & 0x3f);
|
|
||||||
|
|
||||||
in >> z1;
|
|
||||||
in >> z2;
|
|
||||||
//
|
|
||||||
|
|
||||||
ts = ((z2 << 8) | z1) << 1;
|
|
||||||
ts |= (t1 >> 15) & 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
second = (ts & 0x3f);
|
|
||||||
minute = (ts >> 6) & 0x3f;
|
|
||||||
hour = (ts >> 12) & 0x1f;
|
|
||||||
|
|
||||||
datetime = QDateTime(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC);
|
|
||||||
//datetime=datetime.toTimeSpec(Qt::UTC);
|
|
||||||
|
|
||||||
ts = datetime.toTime_t();
|
|
||||||
|
|
||||||
date = datetime.date();
|
|
||||||
time = datetime.time();
|
|
||||||
in >> strt;
|
in >> strt;
|
||||||
in >> recs;
|
in >> recs;
|
||||||
totalrecs += recs;
|
totalrecs += recs;
|
||||||
@ -816,13 +793,14 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
|
|
||||||
in.setVersion(QDataStream::Qt_4_6);
|
in.setVersion(QDataStream::Qt_4_6);
|
||||||
in.setByteOrder(QDataStream::BigEndian);
|
in.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
// 5 byte repeating patterns
|
// 5 byte repeating patterns
|
||||||
|
|
||||||
quint8 *data = (quint8 *)databytes.data();
|
quint8 *data = (quint8 *)databytes.data();
|
||||||
|
|
||||||
qint64 ti;
|
qint64 ti;
|
||||||
quint8 pressure, leak, a1, a2, a3;
|
quint8 pressure, leak, a1, a2, a3, a4;
|
||||||
quint8 sa1, sa2; // The two sense awake bits per 2 minutes
|
// quint8 sa1, sa2; // The two sense awake bits per 2 minutes
|
||||||
SessionID sessid;
|
SessionID sessid;
|
||||||
Session *sess;
|
Session *sess;
|
||||||
int idx;
|
int idx;
|
||||||
@ -834,7 +812,6 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
sess->really_set_first(ti);
|
sess->really_set_first(ti);
|
||||||
EventList *LK = sess->AddEventList(CPAP_LeakTotal, EVL_Event, 1);
|
EventList *LK = sess->AddEventList(CPAP_LeakTotal, EVL_Event, 1);
|
||||||
EventList *PR = sess->AddEventList(CPAP_Pressure, EVL_Event, 0.1F);
|
EventList *PR = sess->AddEventList(CPAP_Pressure, EVL_Event, 0.1F);
|
||||||
// EventList *FLG = sess->AddEventList(CPAP_FLG, EVL_Event);
|
|
||||||
EventList *OA = sess->AddEventList(CPAP_Obstructive, EVL_Event);
|
EventList *OA = sess->AddEventList(CPAP_Obstructive, EVL_Event);
|
||||||
EventList *H = sess->AddEventList(CPAP_Hypopnea, EVL_Event);
|
EventList *H = sess->AddEventList(CPAP_Hypopnea, EVL_Event);
|
||||||
EventList *FL = sess->AddEventList(CPAP_FlowLimit, EVL_Event);
|
EventList *FL = sess->AddEventList(CPAP_FlowLimit, EVL_Event);
|
||||||
@ -846,8 +823,8 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
idx = stidx * 15;
|
idx = stidx * 15;
|
||||||
|
|
||||||
quint8 bitmask;
|
quint8 bitmask;
|
||||||
for (int i = 0; i < rec; i++) {
|
for (int i = 0; i < rec; ++i) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
pressure = data[idx];
|
pressure = data[idx];
|
||||||
PR->AddEvent(ti, pressure);
|
PR->AddEvent(ti, pressure);
|
||||||
|
|
||||||
@ -858,17 +835,19 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename, Profile *profile)
|
|||||||
a2 = data[idx + 3]; // [0..5] Hypopnea, [6..7] Unknown
|
a2 = data[idx + 3]; // [0..5] Hypopnea, [6..7] Unknown
|
||||||
a3 = data[idx + 4]; // [0..5] Flow Limitation, [6..7] SensAwake bitflags, 1 per minute
|
a3 = data[idx + 4]; // [0..5] Flow Limitation, [6..7] SensAwake bitflags, 1 per minute
|
||||||
|
|
||||||
sa1 = (a3 >> 6) & 1; // Sense awake bit for first minutes
|
// Sure there isn't 6 SenseAwake bits?
|
||||||
sa2 = (a3 >> 7) & 1; // Sense awake bit for second minute
|
a4 = (a1 >> 6) << 4 | ((a2 >> 6) << 2) | (a3 >> 6);
|
||||||
|
|
||||||
if (sa1) { SA->AddEvent(ti, 1); }
|
// this does the same thing as behaviour
|
||||||
if (sa2) { SA->AddEvent(ti + 60000L, 1); }
|
//a4 = (a3 >> 7) << 3 | ((a3 >> 6)&1);
|
||||||
|
|
||||||
bitmask = 1;
|
bitmask = 1;
|
||||||
for (int k = 0; k < 6; k++) { // There are 6 flag sets per 2 minutes
|
for (int k = 0; k < 6; k++) { // There are 6 flag sets per 2 minutes
|
||||||
if (a1 & bitmask) { OA->AddEvent(ti, 1); }
|
if (a1 & bitmask) { OA->AddEvent(ti, 1); }
|
||||||
if (a2 & bitmask) { H->AddEvent(ti, 1); }
|
if (a2 & bitmask) { H->AddEvent(ti, 1); }
|
||||||
if (a3 & bitmask) { FL->AddEvent(ti, 1); }
|
if (a3 & bitmask) { FL->AddEvent(ti, 1); }
|
||||||
|
if (a4 & bitmask) { SA->AddEvent(ti, 1); }
|
||||||
|
|
||||||
bitmask <<= 1;
|
bitmask <<= 1;
|
||||||
ti += 20000L; // Increment 20 seconds
|
ti += 20000L; // Increment 20 seconds
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,8 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
|||||||
graphlist[schema::channel[CPAP_Snore].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_Snore, COLOR_Snore, true)));
|
graphlist[schema::channel[CPAP_Snore].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_Snore, COLOR_Snore, true)));
|
||||||
|
|
||||||
graphlist[schema::channel[CPAP_PTB].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_PTB, COLOR_PTB, square)));
|
graphlist[schema::channel[CPAP_PTB].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_PTB, COLOR_PTB, square)));
|
||||||
|
|
||||||
|
|
||||||
graphlist[schema::channel[CPAP_MaskPressure].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure, COLOR_MaskPressure, false)));
|
graphlist[schema::channel[CPAP_MaskPressure].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure, COLOR_MaskPressure, false)));
|
||||||
graphlist[schema::channel[CPAP_RespRate].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_RespRate, COLOR_RespRate, square)));
|
graphlist[schema::channel[CPAP_RespRate].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_RespRate, COLOR_RespRate, square)));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user