mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-14 09:40:45 +00:00
Merge PRS1 F5 event importers into ImportEventsF5V0123 since they're now identical.
No change in functionality.
This commit is contained in:
parent
86cc4fa210
commit
75fca0c951
@ -1689,7 +1689,7 @@ void PRS1DataChunk::AddEvent(PRS1ParsedEvent* const event)
|
|||||||
m_parsedData.push_back(event);
|
m_parsedData.push_back(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PRS1Import::ParseEventsF5V3()
|
bool PRS1Import::ImportEventsF5V0123()
|
||||||
{
|
{
|
||||||
float GAIN = PRS1PressureEvent::GAIN;
|
float GAIN = PRS1PressureEvent::GAIN;
|
||||||
if (event->familyVersion == 2 || event->familyVersion == 3) {
|
if (event->familyVersion == 2 || event->familyVersion == 3) {
|
||||||
@ -2038,196 +2038,6 @@ bool PRS1DataChunk::ParseEventsF5V3(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PRS1Import::ParseF5Events()
|
|
||||||
{
|
|
||||||
float GAIN = PRS1PressureEvent::GAIN;
|
|
||||||
if (event->familyVersion == 2 || event->familyVersion == 3) {
|
|
||||||
// F5V2 and F5V3 use a gain of 0.125 rather than 0.1 to allow for a maximum value of 30 cmH2O
|
|
||||||
GAIN = 0.125; // TODO: this should be parameterized somewhere more logical
|
|
||||||
}
|
|
||||||
|
|
||||||
// Required channels
|
|
||||||
EventList *CA = session->AddEventList(CPAP_ClearAirway, EVL_Event);
|
|
||||||
EventList *OA = session->AddEventList(CPAP_Obstructive, EVL_Event);
|
|
||||||
EventList *HY = session->AddEventList(CPAP_Hypopnea, EVL_Event);
|
|
||||||
|
|
||||||
EventList *FL = session->AddEventList(CPAP_FlowLimit, EVL_Event);
|
|
||||||
EventList *SNORE = session->AddEventList(CPAP_Snore, EVL_Event); // snore count statistic
|
|
||||||
EventList *VS = session->AddEventList(CPAP_VSnore, EVL_Event);
|
|
||||||
EventList *VS2 = session->AddEventList(CPAP_VSnore2, EVL_Event); // flags nonzero snore-count intervals on overview
|
|
||||||
// No RERA detection
|
|
||||||
|
|
||||||
EventList *PB = session->AddEventList(CPAP_PB, EVL_Event);
|
|
||||||
EventList *LL = session->AddEventList(CPAP_LargeLeak, EVL_Event);
|
|
||||||
EventList *TOTLEAK = session->AddEventList(CPAP_LeakTotal, EVL_Event);
|
|
||||||
EventList *LEAK = session->AddEventList(CPAP_Leak, EVL_Event); // TODO: calculated for F5V0, reported by F5V1 and higher
|
|
||||||
|
|
||||||
EventList *RR = session->AddEventList(CPAP_RespRate, EVL_Event);
|
|
||||||
EventList *TV = session->AddEventList(CPAP_TidalVolume, EVL_Event, 10.0F);
|
|
||||||
EventList *MV = session->AddEventList(CPAP_MinuteVent, EVL_Event);
|
|
||||||
EventList *PTB = session->AddEventList(CPAP_PTB, EVL_Event);
|
|
||||||
|
|
||||||
// TB could be on-demand
|
|
||||||
EventList *TB = session->AddEventList(PRS1_TimedBreath, EVL_Event, 0.1F); // TODO: a gain of 0.1 should affect display, but it doesn't
|
|
||||||
|
|
||||||
EventList *IPAP = session->AddEventList(CPAP_IPAP, EVL_Event, GAIN);
|
|
||||||
EventList *EPAP = session->AddEventList(CPAP_EPAP, EVL_Event, GAIN);
|
|
||||||
EventList *PS = session->AddEventList(CPAP_PS, EVL_Event, GAIN);
|
|
||||||
EventList *IPAPLo = session->AddEventList(CPAP_IPAPLo, EVL_Event, GAIN);
|
|
||||||
EventList *IPAPHi = session->AddEventList(CPAP_IPAPHi, EVL_Event, GAIN);
|
|
||||||
|
|
||||||
// On-demand channels
|
|
||||||
EventList *PP = nullptr;
|
|
||||||
|
|
||||||
EventDataType currentPressure=0;
|
|
||||||
|
|
||||||
// Unintentional leak calculation, see zMaskProfile:calcLeak in calcs.cpp for explanation
|
|
||||||
// Only needed for F5V0: F5V1 and later report it directly
|
|
||||||
bool calcLeaks = (event->familyVersion == 0) && p_profile->cpap->calculateUnintentionalLeaks();
|
|
||||||
EventDataType lpm4 = p_profile->cpap->custom4cmH2OLeaks();
|
|
||||||
EventDataType lpm20 = p_profile->cpap->custom20cmH2OLeaks();
|
|
||||||
EventDataType lpm = lpm20 - lpm4;
|
|
||||||
EventDataType ppm = lpm / 16.0;
|
|
||||||
|
|
||||||
qint64 duration;
|
|
||||||
qint64 t = qint64(event->timestamp) * 1000L;
|
|
||||||
session->updateFirst(t);
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
ok = event->ParseEvents();
|
|
||||||
|
|
||||||
for (int i=0; i < event->m_parsedData.count(); i++) {
|
|
||||||
PRS1ParsedEvent* e = event->m_parsedData.at(i);
|
|
||||||
t = qint64(event->timestamp + e->m_start) * 1000L;
|
|
||||||
|
|
||||||
switch (e->m_type) {
|
|
||||||
case PRS1EPAPSetEvent::TYPE:
|
|
||||||
// TODO: The below belong in average channels and then this should go into the EPAP adjustment channel.
|
|
||||||
break;
|
|
||||||
case PRS1IPAPAverageEvent::TYPE:
|
|
||||||
IPAP->AddEvent(t, e->m_value); // TODO: This belongs in an average channel rather than setting channel.
|
|
||||||
currentPressure = e->m_value;
|
|
||||||
break;
|
|
||||||
case PRS1IPAPLowEvent::TYPE:
|
|
||||||
IPAPLo->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1IPAPHighEvent::TYPE:
|
|
||||||
IPAPHi->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1EPAPAverageEvent::TYPE:
|
|
||||||
EPAP->AddEvent(t, e->m_value); // TODO: This belongs in an average channel rather than setting channel.
|
|
||||||
PS->AddEvent(t, currentPressure - e->m_value); // Pressure Support
|
|
||||||
break;
|
|
||||||
case PRS1TimedBreathEvent::TYPE:
|
|
||||||
// The duration appears to correspond to the length of the timed breath in seconds when multiplied by 0.1 (100ms)!
|
|
||||||
// TODO: consider changing parsers to use milliseconds for time, since it turns out there's at least one way
|
|
||||||
// they can express durations less than 1 second.
|
|
||||||
// TODO: consider allowing OSCAR to record millisecond durations so that the display will say "2.1" instead of "21" or "2".
|
|
||||||
duration = e->m_duration * 100L; // for now do this here rather than in parser, since parser events don't use milliseconds
|
|
||||||
TB->AddEvent(t - duration, e->m_duration * 0.1F); // TODO: a gain of 0.1 should render this unnecessary, but gain doesn't seem to work currently
|
|
||||||
break;
|
|
||||||
case PRS1ObstructiveApneaEvent::TYPE:
|
|
||||||
OA->AddEvent(t, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1ClearAirwayEvent::TYPE:
|
|
||||||
CA->AddEvent(t, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1HypopneaEvent::TYPE:
|
|
||||||
HY->AddEvent(t, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1FlowLimitationEvent::TYPE:
|
|
||||||
FL->AddEvent(t, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1PeriodicBreathingEvent::TYPE:
|
|
||||||
// TODO: The graphs silently treat the timestamp of a span as an end time rather than start (see gFlagsLine::paint).
|
|
||||||
// Decide whether to preserve that behavior or change it universally and update either this code or comment.
|
|
||||||
duration = e->m_duration * 1000L;
|
|
||||||
PB->AddEvent(t + duration, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1LargeLeakEvent::TYPE:
|
|
||||||
// TODO: see PB comment above.
|
|
||||||
duration = e->m_duration * 1000L;
|
|
||||||
LL->AddEvent(t + duration, e->m_duration);
|
|
||||||
break;
|
|
||||||
case PRS1TotalLeakEvent::TYPE:
|
|
||||||
TOTLEAK->AddEvent(t, e->m_value);
|
|
||||||
// TODO: decide whether to keep this here, shouldn't keep it here just because it's "quicker".
|
|
||||||
// TODO: compare this value for the reported value for F5V1 and higher?
|
|
||||||
// TODO: Fix this for 0.125 gain: it assumes 0.1 (dividing by 10.0)...
|
|
||||||
// Or omit, because F5V1 and above reports unintentional leak below.
|
|
||||||
if (calcLeaks) { // Much Quicker doing this here than the recalc method.
|
|
||||||
EventDataType leak = e->m_value;
|
|
||||||
leak -= (((currentPressure/10.0f) - 4.0) * ppm + lpm4);
|
|
||||||
if (leak < 0) leak = 0;
|
|
||||||
LEAK->AddEvent(t, leak);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PRS1LeakEvent::TYPE:
|
|
||||||
LEAK->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1SnoreEvent::TYPE: // snore count that shows up in flags but not waveform
|
|
||||||
// TODO: The numeric snore graph is the right way to present this information,
|
|
||||||
// but it needs to be shifted left 2 minutes, since it's not a starting value
|
|
||||||
// but a past statistic.
|
|
||||||
SNORE->AddEvent(t, e->m_value);
|
|
||||||
if (e->m_value > 0) {
|
|
||||||
// TODO: currently these get drawn on our waveforms, but they probably shouldn't,
|
|
||||||
// since they don't have a precise timestamp. They should continue to be drawn
|
|
||||||
// on the flags overview.
|
|
||||||
VS2->AddEvent(t, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PRS1VibratorySnoreEvent::TYPE: // real VS marker on waveform
|
|
||||||
// TODO: These don't need to be drawn separately on the flag overview, since
|
|
||||||
// they're presumably included in the overall snore count statistic. They should
|
|
||||||
// continue to be drawn on the waveform, due to their precise timestamp.
|
|
||||||
VS->AddEvent(t, 0);
|
|
||||||
break;
|
|
||||||
case PRS1RespiratoryRateEvent::TYPE:
|
|
||||||
RR->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1PatientTriggeredBreathsEvent::TYPE:
|
|
||||||
PTB->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1MinuteVentilationEvent::TYPE:
|
|
||||||
MV->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1TidalVolumeEvent::TYPE:
|
|
||||||
TV->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1PressurePulseEvent::TYPE: // Only seen in F5V3, not F5V2 or earlier
|
|
||||||
if (!PP) {
|
|
||||||
if (!(PP = session->AddEventList(CPAP_PressurePulse, EVL_Event))) { return false; }
|
|
||||||
}
|
|
||||||
PP->AddEvent(t, e->m_value);
|
|
||||||
break;
|
|
||||||
case PRS1UnknownDataEvent::TYPE:
|
|
||||||
// These will show up in chunk YAML and any user alerts will be driven
|
|
||||||
// by the parser.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
qWarning() << "Unknown PRS1 event type" << (int) e->m_type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the last event has a non-zero duration, t will not reflect the full duration of the chunk, so update it.
|
|
||||||
t = qint64(event->timestamp + event->duration) * 1000L;
|
|
||||||
session->updateLast(t);
|
|
||||||
session->m_cnt.clear();
|
|
||||||
session->m_cph.clear();
|
|
||||||
|
|
||||||
session->m_valuesummary[CPAP_Pressure].clear();
|
|
||||||
session->m_valuesummary.erase(session->m_valuesummary.find(CPAP_Pressure));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 950P is F5V0
|
// 950P is F5V0
|
||||||
bool PRS1DataChunk::ParseEventsF5V0(void)
|
bool PRS1DataChunk::ParseEventsF5V0(void)
|
||||||
{
|
{
|
||||||
@ -7148,11 +6958,7 @@ bool PRS1Import::ParseEvents()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (event->familyVersion == 3) {
|
res = this->ImportEventsF5V0123();
|
||||||
res = ParseEventsF5V3();
|
|
||||||
} else {
|
|
||||||
res = ParseF5Events();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qDebug() << "Unknown PRS1 familyVersion" << event->familyVersion;
|
qDebug() << "Unknown PRS1 familyVersion" << event->familyVersion;
|
||||||
|
@ -312,10 +312,8 @@ public:
|
|||||||
bool ParseEventsF3V3();
|
bool ParseEventsF3V3();
|
||||||
//! \brief Parse a single data chunk from a .002 file containing event data for a family 3 ventilator machine (family version 6)
|
//! \brief Parse a single data chunk from a .002 file containing event data for a family 3 ventilator machine (family version 6)
|
||||||
bool ParseEventsF3V6();
|
bool ParseEventsF3V6();
|
||||||
//! \brief Parse a single data chunk from a .002 file containing event data for a family 5 ASV machine (which has a different format)
|
//! \brief Import a single data chunk from a .002 file containing event data for a family 5 ASV family machine (family versions 0-3)
|
||||||
bool ParseF5Events();
|
bool ImportEventsF5V0123();
|
||||||
//! \brief Parse a single data chunk from a .002 file containing event data for a family 5 ASV family version 3 machine (which has a different format again)
|
|
||||||
bool ParseEventsF5V3();
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
Reference in New Issue
Block a user