mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-05 02:30:44 +00:00
AirCurve series detection (icon fix) and some cleanups
This commit is contained in:
parent
f69eda1101
commit
29581ebc88
@ -1066,10 +1066,16 @@ bool PRS1Import::ParseF5Events()
|
||||
session->updateLast(t);
|
||||
session->m_cnt.clear();
|
||||
session->m_cph.clear();
|
||||
session->settings[CPAP_IPAPLo] = session->Min(CPAP_IPAPLo);
|
||||
session->settings[CPAP_IPAPHi] = session->Max(CPAP_IPAPHi);
|
||||
session->settings[CPAP_PSMax] = session->Max(CPAP_IPAPHi) - session->Min(CPAP_EPAP);
|
||||
session->settings[CPAP_PSMin] = session->Min(CPAP_IPAPLo) - session->Min(CPAP_EPAP);
|
||||
|
||||
EventDataType minEpap = session->Min(CPAP_EPAP);
|
||||
EventDataType minIpapLo = session->Min(CPAP_IPAPLo);
|
||||
EventDataType maxIpapHi = session->Max(CPAP_IPAPHi);
|
||||
|
||||
session->settings[CPAP_IPAPLo] = minIpapLo;
|
||||
session->settings[CPAP_IPAPHi] = maxIpapHi;
|
||||
|
||||
session->settings[CPAP_PSMax] = maxIpapHi - minEpap;
|
||||
session->settings[CPAP_PSMin] = minIpapLo - minEpap;
|
||||
|
||||
session->m_valuesummary[CPAP_Pressure].clear();
|
||||
session->m_valuesummary.erase(session->m_valuesummary.find(CPAP_Pressure));
|
||||
@ -1164,7 +1170,6 @@ bool PRS1Import::ParseF0Events()
|
||||
EventDataType data[10];
|
||||
int cnt = 0;
|
||||
short delta;
|
||||
int tdata;
|
||||
int pos;
|
||||
qint64 t = qint64(event->timestamp) * 1000L, tt;
|
||||
|
||||
@ -1193,17 +1198,12 @@ bool PRS1Import::ParseF0Events()
|
||||
EventList *IPAP = nullptr;
|
||||
EventList *PS = nullptr;
|
||||
|
||||
EventList *Code15 = nullptr;
|
||||
|
||||
//session->AddEventList(CPAP_VSnore, EVL_Event);
|
||||
//EventList * VS=session->AddEventList(CPAP_Obstructive, EVL_Event);
|
||||
unsigned char lastcode3 = 0, lastcode2 = 0, lastcode = 0;
|
||||
int lastpos = 0, startpos = 0, lastpos2 = 0, lastpos3 = 0;
|
||||
|
||||
int size = event->m_data.size();
|
||||
|
||||
bool FV3 = (event->fileVersion == 3);
|
||||
// if (FV3) size -= 2;
|
||||
unsigned char * buffer = (unsigned char *)event->m_data.data();
|
||||
|
||||
CPAPMode mode = (CPAPMode) session->settings[CPAP_Mode].toInt();
|
||||
@ -1322,7 +1322,6 @@ bool PRS1Import::ParseF0Events()
|
||||
|
||||
case 0x04: // Pressure Pulse
|
||||
data[0] = buffer[pos++];
|
||||
//tt = t - (qint64(data[0]) * 1000L);
|
||||
|
||||
PP->AddEvent(t, data[0]);
|
||||
break;
|
||||
@ -1369,16 +1368,13 @@ bool PRS1Import::ParseF0Events()
|
||||
break;
|
||||
|
||||
case 0x0d: // Vibratory Snore
|
||||
// if (event->fileVersion == 3) {
|
||||
// } else {
|
||||
VS->AddEvent(t, 0);
|
||||
// }
|
||||
VS->AddEvent(t, 0);
|
||||
break;
|
||||
|
||||
case 0x0e: // Unknown
|
||||
data[0] = buffer[pos + 1] << 8 | buffer[pos];
|
||||
if (event->familyVersion >= 4) {
|
||||
// might not doublerize on older machines
|
||||
// might not doublerize on older machines?
|
||||
data[0] *= 2;
|
||||
}
|
||||
|
||||
@ -1386,23 +1382,8 @@ bool PRS1Import::ParseF0Events()
|
||||
data[1] = buffer[pos++];
|
||||
|
||||
tt = t - qint64(data[1]) * 1000L;
|
||||
//LL->AddEvent(tt, data[0]);
|
||||
Code[17]->AddEvent(t, data[0]);
|
||||
|
||||
|
||||
|
||||
// data[0] = ((char *)buffer)[pos++];
|
||||
// data[1] = buffer[pos++]; //(buffer[pos+1] << 8) | buffer[pos];
|
||||
// //data[0]/=10.0;
|
||||
// //pos+=2;
|
||||
// data[2] = buffer[pos++];
|
||||
|
||||
// tdata = unsigned(data[1]) << 8 | unsigned(data[0]);
|
||||
// Code[17]->AddEvent(t, tdata);
|
||||
//qDebug() << hex << data[0] << data[1] << data[2];
|
||||
//session->AddEvent(new Event(t,cpapcode, 0, data, 3));
|
||||
//tt-=data[1]*1000;
|
||||
//session->AddEvent(new Event(t,CPAP_PB, data, 2));
|
||||
break;
|
||||
|
||||
case 0x0f: // Cheyne Stokes Respiration
|
||||
@ -1416,6 +1397,7 @@ bool PRS1Import::ParseF0Events()
|
||||
tt = t - qint64(data[1]) * 1000L;
|
||||
PB->AddEvent(tt, data[0]);
|
||||
break;
|
||||
|
||||
case 0x10: // Large Leak
|
||||
data[0] = buffer[pos + 1] << 8 | buffer[pos];
|
||||
if (event->familyVersion >= 4) {
|
||||
@ -1440,11 +1422,16 @@ bool PRS1Import::ParseF0Events()
|
||||
VS2->AddEvent(t, data[1]);
|
||||
}
|
||||
|
||||
if (((event->family == 0) && (event->familyVersion >= 4)) || (event->fileVersion == 3)) {
|
||||
if ((event->family == 0) && (event->familyVersion >= 4)) {
|
||||
// EPAP / Flex Pressure
|
||||
data[0] = buffer[pos++];
|
||||
//if (!(EPAP = session->AddEventList(CPAP_EPAP, EVL_Event, 0.1F))) { return false; }
|
||||
//EPAP->AddEvent(t, data[0]);
|
||||
|
||||
// Perhaps this check is not necessary, as it will theoretically add extra resolution to pressure chart
|
||||
// for bipap models and above???
|
||||
if (mode <= MODE_BILEVEL_FIXED) {
|
||||
if (!(EPAP = session->AddEventList(CPAP_EPAP, EVL_Event, 0.1F))) { return false; }
|
||||
EPAP->AddEvent(t, data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1455,11 +1442,8 @@ bool PRS1Import::ParseF0Events()
|
||||
data[2] = buffer[pos + 1] << 8 | buffer[pos];
|
||||
pos += 2;
|
||||
|
||||
// if (!Code[24]) {
|
||||
// if (!(Code[24] = session->AddEventList(PRS1_12, EVL_Event))) { return false; }
|
||||
// }
|
||||
// Could end here, but I've seen data sets valid data after!!!
|
||||
|
||||
// Code[24]->AddEvent(t, data[0]);
|
||||
break;
|
||||
|
||||
case 0x14: // DreamStation Hypopnea
|
||||
@ -1468,20 +1452,10 @@ bool PRS1Import::ParseF0Events()
|
||||
HY->AddEvent(tt, data[0]);
|
||||
break;
|
||||
|
||||
case 0x15: // DreamStation Hypopnea // Also a hypopnea.. Hmmm. grouped together by encore.
|
||||
case 0x15: // DreamStation Hypopnea
|
||||
data[0] = buffer[pos++];
|
||||
tt = t - (qint64(data[0]) * 1000L);
|
||||
HY->AddEvent(tt, data[0]);
|
||||
|
||||
|
||||
// This will create an ugly overlay... :/
|
||||
// if (!Code15) {
|
||||
// Code15 = session->AddEventList(CPAP_Pressure, EVL_Event, 0.1F);
|
||||
|
||||
// if (!Code15) { return false; }
|
||||
// }
|
||||
// Code15->AddEvent(t, data[0]);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2552,6 +2526,7 @@ void PRS1Import::run()
|
||||
session->Store(mach->getDataPath());
|
||||
loader->saveMutex.unlock();
|
||||
|
||||
// Unload them from memory
|
||||
session->TrashEvents();
|
||||
}
|
||||
|
||||
@ -2787,7 +2762,8 @@ QList<PRS1DataChunk *> PRS1Loader::ParseFile(QString path)
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((chunk->ext == 5) || (chunk->ext == 6)){
|
||||
|
||||
if ((chunk->ext == 5) || (chunk->ext == 6)) { // if Flow/MaskPressure Waveform or OXI Waveform file
|
||||
if (lastchunk != nullptr) {
|
||||
|
||||
Q_ASSERT(lastchunk->sessionid == chunk->sessionid);
|
||||
|
@ -50,6 +50,8 @@ struct PRS1Waveform {
|
||||
};
|
||||
|
||||
|
||||
/*! \class PRS1DataChunk
|
||||
* \brief Representing a chunk of event/summary/waveform data after the header is parsed. */
|
||||
class PRS1DataChunk
|
||||
{
|
||||
friend class PRS1DataGroup;
|
||||
@ -87,7 +89,8 @@ public:
|
||||
|
||||
class PRS1Loader;
|
||||
|
||||
|
||||
/*! \class PRS1Import
|
||||
* \brief Contains the functions to parse a single session... multithreaded */
|
||||
class PRS1Import:public ImportTask
|
||||
{
|
||||
public:
|
||||
@ -101,9 +104,10 @@ public:
|
||||
delete compliance;
|
||||
delete summary;
|
||||
delete event;
|
||||
for (int i=0;i < waveforms.size(); ++i) {delete waveforms.at(i); }
|
||||
for (int i=0;i < waveforms.size(); ++i) { delete waveforms.at(i); }
|
||||
}
|
||||
|
||||
//! \brief PRS1Import thread starts execution here.
|
||||
virtual void run();
|
||||
|
||||
PRS1DataChunk * compliance;
|
||||
@ -115,27 +119,39 @@ public:
|
||||
QString wavefile;
|
||||
QString oxifile;
|
||||
|
||||
//! \brief As it says on the tin.. Parses .001 files for bricks.
|
||||
bool ParseCompliance();
|
||||
|
||||
//! \brief Figures out which Summary Parser to call, based on machine family/version and calls it.
|
||||
bool ParseSummary();
|
||||
|
||||
//! \brief Figures out which Event Parser to call, based on machine family/version and calls it.
|
||||
bool ParseEvents();
|
||||
|
||||
//! \brief Takes the parsed list of Flow/MaskPressure waveform chunks and adds them to the database
|
||||
bool ParseWaveforms();
|
||||
|
||||
//! \brief Takes the parsed list of oximeter waveform chunks and adds them to the database.
|
||||
bool ParseOximetery();
|
||||
|
||||
|
||||
//! \brief Summary parser for 50 series Family 0 CPAP/APAP models
|
||||
bool ParseSummaryF0();
|
||||
//! \brief Summary parser for 60 series Family 0 CPAP/APAP models
|
||||
bool ParseSummaryF0V4();
|
||||
//! \brief Summary parser for 1060 series AVAPS models
|
||||
bool ParseSummaryF3();
|
||||
//! \brief Summary parser for 50 series Family 0 BiPAP/AutoSV models
|
||||
bool ParseSummaryF5V0();
|
||||
//! \brief Summary parser for 60 series Family 0 BiPAP/AutoSV models
|
||||
bool ParseSummaryF5V1();
|
||||
//! \brief Summary parser for DreamStation series CPAP/APAP models
|
||||
bool ParseSummaryF0V6();
|
||||
|
||||
|
||||
//! \brief Parse a single data chunk from a .002 file containing event data for a standard system one machine
|
||||
bool ParseF0Events();
|
||||
|
||||
//! \brief Parse a single data chunk from a .002 file containing event data for a AVAPS 1060P machine
|
||||
bool ParseF3Events();
|
||||
|
||||
//! \brief Parse a single data chunk from a .002 file containing event data for a family 5 ASV machine (which has a different format)
|
||||
bool ParseF5Events();
|
||||
|
||||
@ -157,13 +173,16 @@ class PRS1Loader : public CPAPLoader
|
||||
PRS1Loader();
|
||||
virtual ~PRS1Loader();
|
||||
|
||||
//! \brief Examine path and return it back if it contains what looks to be a valid PRS1 SD card structure
|
||||
QString checkDir(const QString & path);
|
||||
bool PeekProperties(MachineInfo & info, QString path, Machine * mach = nullptr);
|
||||
|
||||
//! \brief Peek into PROP.TXT or properties.txt at given path, and use it to fill MachineInfo structure
|
||||
bool PeekProperties(MachineInfo & info, QString path, Machine * mach = nullptr);
|
||||
|
||||
//! \brief Detect if the given path contains a valid Folder structure
|
||||
virtual bool Detect(const QString & path);
|
||||
|
||||
//! \brief Wrapper for PeekProperties that creates the MachineInfo structure.
|
||||
virtual MachineInfo PeekInfo(const QString & path);
|
||||
|
||||
//! \brief Scans directory path for valid PRS1 signature
|
||||
@ -175,23 +194,30 @@ class PRS1Loader : public CPAPLoader
|
||||
//! \brief Return the loaderName, in this case "PRS1"
|
||||
virtual const QString &loaderName() { return prs1_class_name; }
|
||||
|
||||
//! \brief Parse a PRS1 summary/event/waveform file and break into invidivual session or waveform chunks
|
||||
QList<PRS1DataChunk *> ParseFile(QString path);
|
||||
|
||||
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.
|
||||
static void Register();
|
||||
|
||||
//! \brief Generate a generic MachineInfo structure, with basic PRS1 info to be expanded upon.
|
||||
virtual MachineInfo newInfo() {
|
||||
return MachineInfo(MT_CPAP, 0, prs1_class_name, QObject::tr("Philips Respironics"), QString(), QString(), QString(), QObject::tr("System One"), QDateTime::currentDateTime(), prs1_data_version);
|
||||
}
|
||||
|
||||
|
||||
virtual QString PresReliefLabel() { return QObject::tr(""); }
|
||||
//! \brief Returns the PRS1 specific code for Pressure Relief Mode
|
||||
virtual ChannelID PresReliefMode() { return PRS1_FlexMode; }
|
||||
//! \brief Returns the PRS1 specific code for Pressure Relief Setting
|
||||
virtual ChannelID PresReliefLevel() { return PRS1_FlexLevel; }
|
||||
|
||||
//! \brief Returns the PRS1 specific code for Humidifier Connected
|
||||
virtual ChannelID HumidifierConnected() { return PRS1_HumidStatus; }
|
||||
//! \brief Returns the PRS1 specific code for Humidifier Level
|
||||
virtual ChannelID HumidifierLevel() { return PRS1_HumidLevel; }
|
||||
|
||||
//! \brief Called at application init, to set up any custom PRS1 Channels
|
||||
void initChannels();
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ const QString STR_UnknownModel = "Resmed S9 ???";
|
||||
ChannelID RMS9_EPR, RMS9_EPRLevel, RMS9_Mode;
|
||||
|
||||
const QString STR_ResMed_AirSense10 = "AirSense 10";
|
||||
const QString STR_ResMed_AirCurve10= "AirCurve 10";
|
||||
const QString STR_ResMed_S9 = "S9";
|
||||
|
||||
|
||||
@ -983,12 +984,14 @@ ResmedLoader::ResmedLoader()
|
||||
{
|
||||
const QString RMS9_ICON = ":/icons/rms9.png";
|
||||
const QString RM10_ICON = ":/icons/airsense10.png";
|
||||
const QString RM10C_ICON = ":/icons/airsense10.png";
|
||||
|
||||
m_pixmaps[STR_ResMed_S9] = QPixmap(RMS9_ICON);
|
||||
m_pixmaps[STR_ResMed_AirSense10] = QPixmap(RM10_ICON);
|
||||
m_pixmap_paths[STR_ResMed_S9] = RMS9_ICON;
|
||||
m_pixmaps[STR_ResMed_AirSense10] = QPixmap(RM10_ICON);
|
||||
m_pixmap_paths[STR_ResMed_AirSense10] = RM10_ICON;
|
||||
|
||||
m_pixmaps[STR_ResMed_AirCurve10] = QPixmap(RM10_ICON);
|
||||
m_pixmap_paths[STR_ResMed_AirCurve10] = RM10_ICON;
|
||||
m_type = MT_CPAP;
|
||||
}
|
||||
ResmedLoader::~ResmedLoader()
|
||||
@ -1198,6 +1201,9 @@ MachineInfo ResmedLoader::PeekInfo(const QString & path)
|
||||
} else if (value.contains(STR_ResMed_AirSense10)) {
|
||||
value.replace(STR_ResMed_AirSense10, "");
|
||||
info.series = STR_ResMed_AirSense10;
|
||||
} else if (value.contains(STR_ResMed_AirCurve10)) {
|
||||
value.replace(STR_ResMed_AirCurve10, "");
|
||||
info.series = STR_ResMed_AirCurve10;
|
||||
}
|
||||
value.replace("(","");
|
||||
value.replace(")","");
|
||||
@ -1922,12 +1928,15 @@ int ResmedLoader::Open(QString path)
|
||||
|
||||
} else if (key == "PNA") { // Product Name
|
||||
value.replace("_"," ");
|
||||
if (value.contains("S9")) {
|
||||
value.replace("S9", "");
|
||||
info.series = "S9";
|
||||
} else if (value.contains("AirSense 10")) {
|
||||
value.replace("AirSense 10", "");
|
||||
info.series = "AirSense 10";
|
||||
if (value.contains(STR_ResMed_S9)) {
|
||||
value.replace(STR_ResMed_S9, "");
|
||||
info.series = STR_ResMed_S9;
|
||||
} else if (value.contains(STR_ResMed_AirSense10)) {
|
||||
value.replace(STR_ResMed_AirSense10, "");
|
||||
info.series = STR_ResMed_AirSense10;
|
||||
} else if (value.contains(STR_ResMed_AirCurve10)) {
|
||||
value.replace(STR_ResMed_AirCurve10, "");
|
||||
info.series = STR_ResMed_AirCurve10;
|
||||
}
|
||||
value.replace("(","");
|
||||
value.replace(")","");
|
||||
|
@ -121,7 +121,7 @@ void init()
|
||||
// Pressure Related Settings
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_Pressure = 0x110C, WAVEFORM, MT_CPAP, SESSION, "Pressure",
|
||||
STR_TR_Pressure, QObject::tr("Therapy Pressure"), STR_TR_Pressure,
|
||||
STR_UNIT_CMH2O, DEFAULT, QColor("dark green")));
|
||||
STR_UNIT_CMH2O, DEFAULT, QColor("red")));
|
||||
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_IPAP = 0x110D, WAVEFORM, MT_CPAP, SESSION, "IPAP",
|
||||
STR_TR_IPAP, QObject::tr("Inspiratory Pressure"), STR_TR_IPAP,
|
||||
|
Loading…
Reference in New Issue
Block a user