mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-08 04:00:44 +00:00
Merge branch 'master' into add-backup-STR-file
This commit is contained in:
commit
4323577412
@ -21,10 +21,15 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<li>[new] Add the "peak flow" channel reported by pre-DreamStation ventilators.</li>
|
<li>[new] Add the "peak flow" channel reported by pre-DreamStation ventilators.</li>
|
||||||
<li>[new] Automatically detect and resolve graphics-related crashes on Windows.</li>
|
<li>[new] Automatically detect and resolve graphics-related crashes on Windows.</li>
|
||||||
|
<li>[new] Support AVAPS in the Overview pressure chart.</li>
|
||||||
|
<li>[fix] Fix missing bars in the Overview pressure chart for Philips Respironics devices.</li>
|
||||||
|
<li>[fix] Add missing Philips Respironics pressure channels to CSV export.</li>
|
||||||
|
<li>[fix] Fix zero Philips Respironics AHI in CSV session export.</li>
|
||||||
<li>[fix] Add support for the Bi-Flex lock setting on pre-DreamStation ventilators.</li>
|
<li>[fix] Add support for the Bi-Flex lock setting on pre-DreamStation ventilators.</li>
|
||||||
<li>[fix] Fix the pressure waveform scale for the BiPAP autoSV Advanced 30 (960T)</li>
|
<li>[fix] Fix the pressure waveform scale for the BiPAP autoSV Advanced 30 (960T)</li>
|
||||||
<li>[fix] Add support for rise time mode on DreamStation BiPAP devices (600X-700X).</li>
|
<li>[fix] Add support for rise time mode on DreamStation BiPAP devices (600X-700X).</li>
|
||||||
<li>[fix] Remove the ramp time and pressure settings when the ramp is disabled on pre-DreamStation devices.</li>
|
<li>[fix] Remove the ramp time and pressure settings when the ramp is disabled on pre-DreamStation devices.</li>
|
||||||
|
<li>[fix] Improve import of Philips Respironics oximetry data.</li>
|
||||||
<li>[fix] Fix occasional failure to save imported Viatom data.</li>
|
<li>[fix] Fix occasional failure to save imported Viatom data.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
|
239
oscar/Graphs/gPressureChart.cpp
Normal file
239
oscar/Graphs/gPressureChart.cpp
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/* gPressureChart Implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 The Oscar Team
|
||||||
|
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file COPYING in the main directory of the source code
|
||||||
|
* for more details. */
|
||||||
|
|
||||||
|
#include "gPressureChart.h"
|
||||||
|
|
||||||
|
gPressureChart::gPressureChart()
|
||||||
|
: gSummaryChart("Pressure", MT_CPAP)
|
||||||
|
{
|
||||||
|
addCalc(CPAP_Pressure, ST_SETMAX);
|
||||||
|
addCalc(CPAP_Pressure, ST_MID);
|
||||||
|
addCalc(CPAP_Pressure, ST_90P);
|
||||||
|
addCalc(CPAP_PressureMin, ST_SETMIN);
|
||||||
|
addCalc(CPAP_PressureMax, ST_SETMAX);
|
||||||
|
|
||||||
|
addCalc(CPAP_EPAP, ST_SETMAX);
|
||||||
|
addCalc(CPAP_IPAP, ST_SETMAX);
|
||||||
|
addCalc(CPAP_EPAPLo, ST_SETMAX);
|
||||||
|
addCalc(CPAP_IPAPHi, ST_SETMAX);
|
||||||
|
|
||||||
|
addCalc(CPAP_EPAP, ST_MID);
|
||||||
|
addCalc(CPAP_EPAP, ST_90P);
|
||||||
|
addCalc(CPAP_IPAP, ST_MID);
|
||||||
|
addCalc(CPAP_IPAP, ST_90P);
|
||||||
|
|
||||||
|
// PRS1 reports pressure adjustments instead of observed pressures on some machines
|
||||||
|
addCalc(CPAP_PressureSet, ST_MID);
|
||||||
|
addCalc(CPAP_PressureSet, ST_90P);
|
||||||
|
addCalc(CPAP_EPAPSet, ST_MID);
|
||||||
|
addCalc(CPAP_EPAPSet, ST_90P);
|
||||||
|
addCalc(CPAP_IPAPSet, ST_MID);
|
||||||
|
addCalc(CPAP_IPAPSet, ST_90P);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int gPressureChart::addCalc(ChannelID code, SummaryType type)
|
||||||
|
{
|
||||||
|
QColor color = schema::channel[code].defaultColor();
|
||||||
|
if (type == ST_90P) {
|
||||||
|
color = brighten(color, 1.33f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = gSummaryChart::addCalc(code, type, color);
|
||||||
|
|
||||||
|
// Save the code and type used to add this calculation so that getCalc()
|
||||||
|
// can retrieve it by code and type instead of by hard-coded index.
|
||||||
|
m_calcs[code][type] = index;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SummaryCalcItem* gPressureChart::getCalc(ChannelID code, SummaryType type)
|
||||||
|
{
|
||||||
|
return &calcitems[m_calcs[code][type]];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gPressureChart::afterDraw(QPainter &, gGraph &graph, QRectF rect)
|
||||||
|
{
|
||||||
|
QStringList presstr;
|
||||||
|
|
||||||
|
if (getCalc(CPAP_Pressure)->cnt > 0) {
|
||||||
|
presstr.append(channelRange(CPAP_Pressure, STR_TR_CPAP));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCalc(CPAP_PressureMin, ST_SETMIN)->cnt > 0) {
|
||||||
|
// TODO: If using machines from different manufacturers in an overview,
|
||||||
|
// the below may not accurately find the APAP pressure channel for all
|
||||||
|
// days; but it only affects the summary label at the top.
|
||||||
|
ChannelID pressure = CPAP_Pressure;
|
||||||
|
if (getCalc(CPAP_PressureSet, ST_MID)->cnt > 0) {
|
||||||
|
pressure = CPAP_PressureSet;
|
||||||
|
}
|
||||||
|
presstr.append(QString("%1 %2/%3/%4/%5").
|
||||||
|
arg(STR_TR_APAP).
|
||||||
|
arg(getCalc(CPAP_PressureMin, ST_SETMIN)->min,0,'f',1).
|
||||||
|
arg(getCalc(pressure, ST_MID)->mid(), 0, 'f', 1).
|
||||||
|
arg(getCalc(pressure, ST_90P)->mid(),0,'f',1).
|
||||||
|
arg(getCalc(CPAP_PressureMax, ST_SETMAX)->max, 0, 'f', 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCalc(CPAP_EPAP)->cnt > 0) {
|
||||||
|
// See CPAP_PressureSet note above.
|
||||||
|
ChannelID epap = CPAP_EPAP;
|
||||||
|
if (getCalc(CPAP_EPAPSet, ST_MID)->cnt > 0) {
|
||||||
|
epap = CPAP_EPAPSet;
|
||||||
|
}
|
||||||
|
presstr.append(channelRange(epap, STR_TR_EPAP));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCalc(CPAP_IPAP)->cnt > 0) {
|
||||||
|
// See CPAP_PressureSet note above.
|
||||||
|
ChannelID ipap = CPAP_IPAP;
|
||||||
|
if (getCalc(CPAP_IPAPSet, ST_MID)->cnt > 0) {
|
||||||
|
ipap = CPAP_IPAPSet;
|
||||||
|
}
|
||||||
|
presstr.append(channelRange(ipap, STR_TR_IPAP));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCalc(CPAP_EPAPLo)->cnt > 0) {
|
||||||
|
presstr.append(channelRange(CPAP_EPAPLo, STR_TR_EPAPLo));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCalc(CPAP_IPAPHi)->cnt > 0) {
|
||||||
|
presstr.append(channelRange(CPAP_IPAPHi, STR_TR_IPAPHi));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString txt = presstr.join(" ");
|
||||||
|
graph.renderText(txt, rect.left(), rect.top()-5*graph.printScaleY(), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString gPressureChart::channelRange(ChannelID code, const QString & label)
|
||||||
|
{
|
||||||
|
SummaryCalcItem* calc = getCalc(code);
|
||||||
|
return QString("%1 %2/%3/%4").
|
||||||
|
arg(label).
|
||||||
|
arg(calc->min, 0, 'f', 1).
|
||||||
|
arg(calc->mid(), 0, 'f', 1).
|
||||||
|
arg(calc->max, 0, 'f', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gPressureChart::addSlice(ChannelID code, SummaryType type)
|
||||||
|
{
|
||||||
|
float value = 0;
|
||||||
|
QString label;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ST_SETMIN:
|
||||||
|
value = m_day->settings_min(code);
|
||||||
|
label = schema::channel[code].label();
|
||||||
|
break;
|
||||||
|
case ST_SETMAX:
|
||||||
|
value = m_day->settings_max(code);
|
||||||
|
label = schema::channel[code].label();
|
||||||
|
break;
|
||||||
|
case ST_MID:
|
||||||
|
value = m_day->calcMiddle(code);
|
||||||
|
label = m_day->calcMiddleLabel(code);
|
||||||
|
break;
|
||||||
|
case ST_90P:
|
||||||
|
value = m_day->calcPercentile(code);
|
||||||
|
label = m_day->calcPercentileLabel(code);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning() << "Unsupported summary type in gPressureChart";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SummaryCalcItem* calc = getCalc(code, type);
|
||||||
|
float height = value - m_height;
|
||||||
|
|
||||||
|
m_slices->append(SummaryChartSlice(calc, value, height, label, calc->color));
|
||||||
|
m_height += height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gPressureChart::populate(Day * day, int idx)
|
||||||
|
{
|
||||||
|
CPAPMode mode = (CPAPMode)(int)qRound(day->settings_wavg(CPAP_Mode));
|
||||||
|
m_day = day;
|
||||||
|
m_slices = &cache[idx];
|
||||||
|
m_height = 0;
|
||||||
|
|
||||||
|
if (mode == MODE_CPAP) {
|
||||||
|
addSlice(CPAP_Pressure);
|
||||||
|
|
||||||
|
} else if (mode == MODE_APAP) {
|
||||||
|
addSlice(CPAP_PressureMin, ST_SETMIN);
|
||||||
|
if (!day->summaryOnly()) {
|
||||||
|
// Handle PRS1 pressure adjustments reported separately from average (EPAP) pressure
|
||||||
|
ChannelID pressure = CPAP_Pressure;
|
||||||
|
if (m_day->channelHasData(CPAP_PressureSet)) {
|
||||||
|
pressure = CPAP_PressureSet;
|
||||||
|
}
|
||||||
|
addSlice(pressure, ST_MID);
|
||||||
|
addSlice(pressure, ST_90P);
|
||||||
|
}
|
||||||
|
addSlice(CPAP_PressureMax, ST_SETMAX);
|
||||||
|
|
||||||
|
} else if (mode == MODE_BILEVEL_FIXED) {
|
||||||
|
addSlice(CPAP_EPAP);
|
||||||
|
addSlice(CPAP_IPAP);
|
||||||
|
|
||||||
|
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
|
||||||
|
addSlice(CPAP_EPAPLo);
|
||||||
|
if (!day->summaryOnly()) {
|
||||||
|
addSlice(CPAP_EPAP, ST_MID);
|
||||||
|
addSlice(CPAP_EPAP, ST_90P);
|
||||||
|
addSlice(CPAP_IPAP, ST_MID);
|
||||||
|
addSlice(CPAP_IPAP, ST_90P);
|
||||||
|
}
|
||||||
|
addSlice(CPAP_IPAPHi);
|
||||||
|
|
||||||
|
} else if ((mode == MODE_BILEVEL_AUTO_VARIABLE_PS) || (mode == MODE_ASV_VARIABLE_EPAP)) {
|
||||||
|
addSlice(CPAP_EPAPLo);
|
||||||
|
if (!day->summaryOnly()) {
|
||||||
|
// Handle PRS1 pressure adjustments when reported instead of observed pressures
|
||||||
|
ChannelID epap = CPAP_EPAP;
|
||||||
|
if (m_day->channelHasData(CPAP_EPAPSet)) {
|
||||||
|
epap = CPAP_EPAPSet;
|
||||||
|
}
|
||||||
|
ChannelID ipap = CPAP_IPAP;
|
||||||
|
if (m_day->channelHasData(CPAP_IPAPSet)) {
|
||||||
|
ipap = CPAP_IPAPSet;
|
||||||
|
}
|
||||||
|
addSlice(epap, ST_MID);
|
||||||
|
addSlice(epap, ST_90P);
|
||||||
|
addSlice(ipap, ST_MID);
|
||||||
|
addSlice(ipap, ST_90P);
|
||||||
|
}
|
||||||
|
addSlice(CPAP_IPAPHi);
|
||||||
|
|
||||||
|
} else if (mode == MODE_ASV) {
|
||||||
|
addSlice(CPAP_EPAP);
|
||||||
|
if (!day->summaryOnly()) {
|
||||||
|
addSlice(CPAP_IPAP, ST_MID);
|
||||||
|
addSlice(CPAP_IPAP, ST_90P);
|
||||||
|
}
|
||||||
|
addSlice(CPAP_IPAPHi);
|
||||||
|
|
||||||
|
} else if (mode == MODE_AVAPS) {
|
||||||
|
addSlice(CPAP_EPAP);
|
||||||
|
if (!day->summaryOnly()) {
|
||||||
|
addSlice(CPAP_IPAP, ST_MID);
|
||||||
|
addSlice(CPAP_IPAP, ST_90P);
|
||||||
|
}
|
||||||
|
addSlice(CPAP_IPAPHi);
|
||||||
|
}
|
||||||
|
}
|
61
oscar/Graphs/gPressureChart.h
Normal file
61
oscar/Graphs/gPressureChart.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* gPressureChart Header
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 The Oscar Team
|
||||||
|
* Copyright (C) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file COPYING in the main directory of the source code
|
||||||
|
* for more details. */
|
||||||
|
|
||||||
|
#ifndef GPRESSURECHART_H
|
||||||
|
#define GPRESSURECHART_H
|
||||||
|
|
||||||
|
#include "gSessionTimesChart.h"
|
||||||
|
|
||||||
|
class gPressureChart : public gSummaryChart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gPressureChart();
|
||||||
|
virtual ~gPressureChart() {}
|
||||||
|
|
||||||
|
virtual Layer * Clone() {
|
||||||
|
gPressureChart * sc = new gPressureChart();
|
||||||
|
gSummaryChart::CloneInto(sc);
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// virtual void preCalc();
|
||||||
|
virtual void customCalc(Day *day, QVector<SummaryChartSlice> &slices) {
|
||||||
|
int size = slices.size();
|
||||||
|
float hour = day->hours(m_machtype);
|
||||||
|
for (int i=0; i < size; ++i) {
|
||||||
|
SummaryChartSlice & slice = slices[i];
|
||||||
|
SummaryCalcItem * calc = slices[i].calc;
|
||||||
|
|
||||||
|
calc->update(slice.value, hour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void afterDraw(QPainter &, gGraph &, QRectF);
|
||||||
|
|
||||||
|
virtual void populate(Day * day, int idx);
|
||||||
|
|
||||||
|
virtual QString tooltipData(Day * day, int idx) {
|
||||||
|
return day->getCPAPModeStr() + "\n" + day->getPressureSettings() + gSummaryChart::tooltipData(day, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int addCalc(ChannelID code, SummaryType type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SummaryCalcItem* getCalc(ChannelID code, SummaryType type = ST_SETMAX);
|
||||||
|
QString channelRange(ChannelID code, const QString & label);
|
||||||
|
void addSlice(ChannelID code, SummaryType type = ST_SETMAX);
|
||||||
|
|
||||||
|
QHash<ChannelID,QHash<SummaryType,int>> m_calcs;
|
||||||
|
|
||||||
|
// State passed between populate() and addSlice():
|
||||||
|
Day* m_day;
|
||||||
|
QVector<SummaryChartSlice>* m_slices;
|
||||||
|
float m_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GPRESSURECHART_H
|
@ -1,5 +1,6 @@
|
|||||||
/* gSessionTimesChart Implementation
|
/* gSessionTimesChart Implementation
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2020 The Oscar Team
|
||||||
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
@ -101,6 +102,17 @@ void gSummaryChart::SetDay(Day *unused_day)
|
|||||||
//QMap<QDate, int> gSummaryChart::dayindex;
|
//QMap<QDate, int> gSummaryChart::dayindex;
|
||||||
//QList<Day *> gSummaryChart::daylist;
|
//QList<Day *> gSummaryChart::daylist;
|
||||||
|
|
||||||
|
int gSummaryChart::addCalc(ChannelID code, SummaryType type, QColor color)
|
||||||
|
{
|
||||||
|
calcitems.append(SummaryCalcItem(code, type, color));
|
||||||
|
return calcitems.size() - 1; // return the index of the newly appended calc
|
||||||
|
}
|
||||||
|
|
||||||
|
int gSummaryChart::addCalc(ChannelID code, SummaryType type)
|
||||||
|
{
|
||||||
|
return addCalc(code, type, schema::channel[code].defaultColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool gSummaryChart::keyPressEvent(QKeyEvent *event, gGraph *graph)
|
bool gSummaryChart::keyPressEvent(QKeyEvent *event, gGraph *graph)
|
||||||
{
|
{
|
||||||
@ -1288,199 +1300,3 @@ QString gAHIChart::tooltipData(Day *day, int idx)
|
|||||||
}
|
}
|
||||||
return QString("\n%1: %2").arg(STR_TR_AHI).arg(float(total) / hour,0,'f',2)+txt;
|
return QString("\n%1: %2").arg(STR_TR_AHI).arg(float(total) / hour,0,'f',2)+txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gPressureChart::gPressureChart()
|
|
||||||
:gSummaryChart("Pressure", MT_CPAP)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Do not reorder these!!! :P
|
|
||||||
addCalc(CPAP_Pressure, ST_SETMAX, schema::channel[CPAP_Pressure].defaultColor()); // 00
|
|
||||||
addCalc(CPAP_Pressure, ST_MID, schema::channel[CPAP_Pressure].defaultColor()); // 01
|
|
||||||
addCalc(CPAP_Pressure, ST_90P, brighten(schema::channel[CPAP_Pressure].defaultColor(), 1.33f)); // 02
|
|
||||||
addCalc(CPAP_PressureMin, ST_SETMIN, schema::channel[CPAP_PressureMin].defaultColor()); // 03
|
|
||||||
addCalc(CPAP_PressureMax, ST_SETMAX, schema::channel[CPAP_PressureMax].defaultColor()); // 04
|
|
||||||
|
|
||||||
addCalc(CPAP_EPAP, ST_SETMAX, schema::channel[CPAP_EPAP].defaultColor()); // 05
|
|
||||||
addCalc(CPAP_IPAP, ST_SETMAX, schema::channel[CPAP_IPAP].defaultColor()); // 06
|
|
||||||
addCalc(CPAP_EPAPLo, ST_SETMAX, schema::channel[CPAP_EPAPLo].defaultColor()); // 07
|
|
||||||
addCalc(CPAP_IPAPHi, ST_SETMAX, schema::channel[CPAP_IPAPHi].defaultColor()); // 08
|
|
||||||
|
|
||||||
addCalc(CPAP_EPAP, ST_MID, schema::channel[CPAP_EPAP].defaultColor()); // 09
|
|
||||||
addCalc(CPAP_EPAP, ST_90P, brighten(schema::channel[CPAP_EPAP].defaultColor(),1.33f)); // 10
|
|
||||||
addCalc(CPAP_IPAP, ST_MID, schema::channel[CPAP_IPAP].defaultColor()); // 11
|
|
||||||
addCalc(CPAP_IPAP, ST_90P, brighten(schema::channel[CPAP_IPAP].defaultColor(),1.33f)); // 12
|
|
||||||
}
|
|
||||||
|
|
||||||
void gPressureChart::afterDraw(QPainter &, gGraph &graph, QRectF rect)
|
|
||||||
{
|
|
||||||
int pressure_cnt = calcitems[0].cnt;
|
|
||||||
int pressuremin_cnt = calcitems[3].cnt;
|
|
||||||
int epap_cnt = calcitems[5].cnt;
|
|
||||||
int ipap_cnt = calcitems[6].cnt;
|
|
||||||
int ipaphi_cnt = calcitems[8].cnt;
|
|
||||||
int epaplo_cnt = calcitems[7].cnt;
|
|
||||||
|
|
||||||
QStringList presstr;
|
|
||||||
|
|
||||||
float mid = 0;
|
|
||||||
|
|
||||||
if (pressure_cnt > 0) {
|
|
||||||
mid = calcitems[0].mid();
|
|
||||||
presstr.append(QString("%1 %2/%3/%4").
|
|
||||||
arg(STR_TR_CPAP).
|
|
||||||
arg(calcitems[0].min,0,'f',1).
|
|
||||||
arg(mid, 0, 'f', 1).
|
|
||||||
arg(calcitems[0].max,0,'f',1));
|
|
||||||
}
|
|
||||||
if (pressuremin_cnt > 0) {
|
|
||||||
presstr.append(QString("%1 %2/%3/%4/%5").
|
|
||||||
arg(STR_TR_APAP).
|
|
||||||
arg(calcitems[3].min,0,'f',1).
|
|
||||||
arg(calcitems[1].mid(), 0, 'f', 1).
|
|
||||||
arg(calcitems[2].mid(),0,'f',1).
|
|
||||||
arg(calcitems[4].max, 0, 'f', 1));
|
|
||||||
|
|
||||||
}
|
|
||||||
if (epap_cnt > 0) {
|
|
||||||
presstr.append(QString("%1 %2/%3/%4").
|
|
||||||
arg(STR_TR_EPAP).
|
|
||||||
arg(calcitems[5].min,0,'f',1).
|
|
||||||
arg(calcitems[5].mid(), 0, 'f', 1).
|
|
||||||
arg(calcitems[5].max, 0, 'f', 1));
|
|
||||||
}
|
|
||||||
if (ipap_cnt > 0) {
|
|
||||||
presstr.append(QString("%1 %2/%3/%4").
|
|
||||||
arg(STR_TR_IPAP).
|
|
||||||
arg(calcitems[6].min,0,'f',1).
|
|
||||||
arg(calcitems[6].mid(), 0, 'f', 1).
|
|
||||||
arg(calcitems[6].max, 0, 'f', 1));
|
|
||||||
}
|
|
||||||
if (epaplo_cnt > 0) {
|
|
||||||
presstr.append(QString("%1 %2/%3/%4").
|
|
||||||
arg(STR_TR_EPAPLo).
|
|
||||||
arg(calcitems[7].min,0,'f',1).
|
|
||||||
arg(calcitems[7].mid(), 0, 'f', 1).
|
|
||||||
arg(calcitems[7].max, 0, 'f', 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ipaphi_cnt > 0) {
|
|
||||||
presstr.append(QString("%1 %2/%3/%4").
|
|
||||||
arg(STR_TR_IPAPHi).
|
|
||||||
arg(calcitems[8].min,0,'f',1).
|
|
||||||
arg(calcitems[8].mid(), 0, 'f', 1).
|
|
||||||
arg(calcitems[8].max, 0, 'f', 1));
|
|
||||||
}
|
|
||||||
QString txt = presstr.join(" ");
|
|
||||||
graph.renderText(txt, rect.left(), rect.top()-5*graph.printScaleY(), 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void gPressureChart::populate(Day * day, int idx)
|
|
||||||
{
|
|
||||||
float tmp;
|
|
||||||
CPAPMode mode = (CPAPMode)(int)qRound(day->settings_wavg(CPAP_Mode));
|
|
||||||
QVector<SummaryChartSlice> & slices = cache[idx];
|
|
||||||
|
|
||||||
if (mode == MODE_CPAP) {
|
|
||||||
float pr = day->settings_max(CPAP_Pressure);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[0], pr, pr, schema::channel[CPAP_Pressure].label(), calcitems[0].color));
|
|
||||||
} else if (mode == MODE_APAP) {
|
|
||||||
float min = day->settings_min(CPAP_PressureMin);
|
|
||||||
float max = day->settings_max(CPAP_PressureMax);
|
|
||||||
|
|
||||||
tmp = min;
|
|
||||||
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[3], min, min, schema::channel[CPAP_PressureMin].label(), calcitems[3].color));
|
|
||||||
if (!day->summaryOnly()) {
|
|
||||||
float med = day->calcMiddle(CPAP_Pressure);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[1], med, med - tmp, day->calcMiddleLabel(CPAP_Pressure), calcitems[1].color));
|
|
||||||
tmp += med - tmp;
|
|
||||||
|
|
||||||
float p90 = day->calcPercentile(CPAP_Pressure);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[2], p90, p90 - tmp, day->calcPercentileLabel(CPAP_Pressure), calcitems[2].color));
|
|
||||||
tmp += p90 - tmp;
|
|
||||||
}
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[4], max, max - tmp, schema::channel[CPAP_PressureMax].label(), calcitems[4].color));
|
|
||||||
|
|
||||||
} else if (mode == MODE_BILEVEL_FIXED) {
|
|
||||||
float epap = day->settings_max(CPAP_EPAP);
|
|
||||||
float ipap = day->settings_max(CPAP_IPAP);
|
|
||||||
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[5], epap, epap, schema::channel[CPAP_EPAP].label(), calcitems[5].color));
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[6], ipap, ipap - epap, schema::channel[CPAP_IPAP].label(), calcitems[6].color));
|
|
||||||
|
|
||||||
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
|
|
||||||
float epap = day->settings_max(CPAP_EPAPLo);
|
|
||||||
tmp = epap;
|
|
||||||
float ipap = day->settings_max(CPAP_IPAPHi);
|
|
||||||
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[7], epap, epap, schema::channel[CPAP_EPAPLo].label(), calcitems[7].color));
|
|
||||||
if (!day->summaryOnly()) {
|
|
||||||
|
|
||||||
float e50 = day->calcMiddle(CPAP_EPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[9], e50, e50 - tmp, day->calcMiddleLabel(CPAP_EPAP), calcitems[9].color));
|
|
||||||
tmp += e50 - tmp;
|
|
||||||
|
|
||||||
float e90 = day->calcPercentile(CPAP_EPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[10], e90, e90 - tmp, day->calcPercentileLabel(CPAP_EPAP), calcitems[10].color));
|
|
||||||
tmp += e90 - tmp;
|
|
||||||
|
|
||||||
float i50 = day->calcMiddle(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[11], i50, i50 - tmp, day->calcMiddleLabel(CPAP_IPAP), calcitems[11].color));
|
|
||||||
tmp += i50 - tmp;
|
|
||||||
|
|
||||||
float i90 = day->calcPercentile(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[12], i90, i90 - tmp, day->calcPercentileLabel(CPAP_IPAP), calcitems[12].color));
|
|
||||||
tmp += i90 - tmp;
|
|
||||||
}
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[8], ipap, ipap - tmp, schema::channel[CPAP_IPAPHi].label(), calcitems[8].color));
|
|
||||||
} else if ((mode == MODE_BILEVEL_AUTO_VARIABLE_PS) || (mode == MODE_ASV_VARIABLE_EPAP)) {
|
|
||||||
float epap = day->settings_max(CPAP_EPAPLo);
|
|
||||||
tmp = epap;
|
|
||||||
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[7], epap, epap, schema::channel[CPAP_EPAPLo].label(), calcitems[7].color));
|
|
||||||
if (!day->summaryOnly()) {
|
|
||||||
float e50 = day->calcMiddle(CPAP_EPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[9], e50, e50 - tmp, day->calcMiddleLabel(CPAP_EPAP), calcitems[9].color));
|
|
||||||
tmp += e50 - tmp;
|
|
||||||
|
|
||||||
float e90 = day->calcPercentile(CPAP_EPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[10], e90, e90 - tmp, day->calcPercentileLabel(CPAP_EPAP), calcitems[10].color));
|
|
||||||
tmp += e90 - tmp;
|
|
||||||
|
|
||||||
float i50 = day->calcMiddle(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[11], i50, i50 - tmp, day->calcMiddleLabel(CPAP_IPAP), calcitems[11].color));
|
|
||||||
tmp += i50 - tmp;
|
|
||||||
|
|
||||||
float i90 = day->calcPercentile(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[12], i90, i90 - tmp, day->calcPercentileLabel(CPAP_IPAP), calcitems[12].color));
|
|
||||||
tmp += i90 - tmp;
|
|
||||||
}
|
|
||||||
float ipap = day->settings_max(CPAP_IPAPHi);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[8], ipap, ipap - tmp, schema::channel[CPAP_IPAPHi].label(), calcitems[8].color));
|
|
||||||
} else if (mode == MODE_ASV) {
|
|
||||||
float epap = day->settings_max(CPAP_EPAP);
|
|
||||||
tmp = epap;
|
|
||||||
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[5], epap, epap, schema::channel[CPAP_EPAP].label(), calcitems[5].color));
|
|
||||||
if (!day->summaryOnly()) {
|
|
||||||
float i50 = day->calcMiddle(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[11], i50, i50 - tmp, day->calcMiddleLabel(CPAP_IPAP), calcitems[11].color));
|
|
||||||
tmp += i50 - tmp;
|
|
||||||
|
|
||||||
float i90 = day->calcPercentile(CPAP_IPAP);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[12], i90, i90 - tmp, day->calcPercentileLabel(CPAP_IPAP), calcitems[12].color));
|
|
||||||
tmp += i90 - tmp;
|
|
||||||
}
|
|
||||||
float ipap = day->settings_max(CPAP_IPAPHi);
|
|
||||||
slices.append(SummaryChartSlice(&calcitems[8], ipap, ipap - tmp, schema::channel[CPAP_IPAPHi].label(), calcitems[8].color));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//void gPressureChart::afterDraw(QPainter &painter, gGraph &graph, QRect rect)
|
|
||||||
//{
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* gSessionTimesChart Header
|
/* gSessionTimesChart Header
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2020 The Oscar Team
|
||||||
* Copyright (C) 2011-2018 Mark Watkins <mark@jedimark.net>
|
* Copyright (C) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
@ -188,13 +189,8 @@ public:
|
|||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int addCalc(ChannelID code, SummaryType type, QColor color);
|
||||||
void addCalc(ChannelID code, SummaryType type, QColor color) {
|
virtual int addCalc(ChannelID code, SummaryType type);
|
||||||
calcitems.append(SummaryCalcItem(code, type, color));
|
|
||||||
}
|
|
||||||
void addCalc(ChannelID code, SummaryType type) {
|
|
||||||
calcitems.append(SummaryCalcItem(code, type, schema::channel[code].defaultColor()));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Layer * Clone() {
|
virtual Layer * Clone() {
|
||||||
gSummaryChart * sc = new gSummaryChart(m_label, m_machtype);
|
gSummaryChart * sc = new gSummaryChart(m_label, m_machtype);
|
||||||
@ -429,37 +425,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class gPressureChart : public gSummaryChart
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
gPressureChart();
|
|
||||||
virtual ~gPressureChart() {}
|
|
||||||
|
|
||||||
virtual Layer * Clone() {
|
|
||||||
gPressureChart * sc = new gPressureChart();
|
|
||||||
gSummaryChart::CloneInto(sc);
|
|
||||||
return sc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual void preCalc();
|
|
||||||
virtual void customCalc(Day *day, QVector<SummaryChartSlice> &slices) {
|
|
||||||
int size = slices.size();
|
|
||||||
float hour = day->hours(m_machtype);
|
|
||||||
for (int i=0; i < size; ++i) {
|
|
||||||
SummaryChartSlice & slice = slices[i];
|
|
||||||
SummaryCalcItem * calc = slices[i].calc;
|
|
||||||
|
|
||||||
calc->update(slice.value, hour);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual void afterDraw(QPainter &, gGraph &, QRectF);
|
|
||||||
|
|
||||||
virtual void populate(Day * day, int idx);
|
|
||||||
|
|
||||||
virtual QString tooltipData(Day * day, int idx) {
|
|
||||||
return day->getCPAPModeStr() + "\n" + day->getPressureSettings() + gSummaryChart::tooltipData(day, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GSESSIONTIMESCHART_H
|
#endif // GSESSIONTIMESCHART_H
|
||||||
|
@ -982,12 +982,9 @@ void PRS1Loader::ScanFiles(const QStringList & paths, int sessionid_base, Machin
|
|||||||
// All samples exhibiting this behavior are DreamStations.
|
// All samples exhibiting this behavior are DreamStations.
|
||||||
task->m_wavefiles.append(fi.canonicalFilePath());
|
task->m_wavefiles.append(fi.canonicalFilePath());
|
||||||
} else if (ext == 6) {
|
} else if (ext == 6) {
|
||||||
if (!task->oxifile.isEmpty()) {
|
// Oximetry data can also be split into multiple files, see waveform
|
||||||
qDebug() << sid << "already has oximetry file" << relativePath(task->oxifile)
|
// comment above.
|
||||||
<< "skipping" << relativePath(fi.canonicalFilePath());
|
task->m_oxifiles.append(fi.canonicalFilePath());
|
||||||
continue;
|
|
||||||
}
|
|
||||||
task->oxifile = fi.canonicalFilePath();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -8152,7 +8149,7 @@ QList<PRS1DataChunk *> PRS1Import::CoalesceWaveformChunks(QList<PRS1DataChunk *>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PRS1Import::ParseOximetry()
|
void PRS1Import::ImportOximetry()
|
||||||
{
|
{
|
||||||
int size = oximetry.size();
|
int size = oximetry.size();
|
||||||
|
|
||||||
@ -8208,10 +8205,10 @@ void PRS1Import::ImportOximetryChannel(ChannelID channel, QByteArray & data, qui
|
|||||||
quint64 start_ti;
|
quint64 start_ti;
|
||||||
int start_i;
|
int start_i;
|
||||||
|
|
||||||
// Split eventlist on invalid values (255)
|
// Split eventlist on invalid values (254-255)
|
||||||
for (int i=0; i < data.size(); i++) {
|
for (int i=0; i < data.size(); i++) {
|
||||||
unsigned char value = raw[i];
|
unsigned char value = raw[i];
|
||||||
bool valid = (value != 255);
|
bool valid = (value < 254);
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (pending_samples == false) {
|
if (pending_samples == false) {
|
||||||
@ -8221,7 +8218,7 @@ void PRS1Import::ImportOximetryChannel(ChannelID channel, QByteArray & data, qui
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (channel == OXI_Pulse) {
|
if (channel == OXI_Pulse) {
|
||||||
if (value > 200) UNEXPECTED_VALUE(value, "<= 200 bpm");
|
if (value > 240) UNEXPECTED_VALUE(value, "<= 240 bpm");
|
||||||
} else {
|
} else {
|
||||||
if (value > 100) UNEXPECTED_VALUE(value, "<= 100%");
|
if (value > 100) UNEXPECTED_VALUE(value, "<= 100%");
|
||||||
}
|
}
|
||||||
@ -8245,7 +8242,7 @@ void PRS1Import::ImportOximetryChannel(ChannelID channel, QByteArray & data, qui
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PRS1Import::ParseWaveforms()
|
void PRS1Import::ImportWaveforms()
|
||||||
{
|
{
|
||||||
int size = waveforms.size();
|
int size = waveforms.size();
|
||||||
quint64 s1, s2;
|
quint64 s1, s2;
|
||||||
@ -8413,7 +8410,7 @@ bool PRS1Import::ParseSession(void)
|
|||||||
|
|
||||||
// If are no mask-on slices, then there's not any meaningful event or waveform data for the session.
|
// If are no mask-on slices, then there's not any meaningful event or waveform data for the session.
|
||||||
// If there's no no event or waveform data, mark this session as a summary.
|
// If there's no no event or waveform data, mark this session as a summary.
|
||||||
if (session->m_slices.count() == 0 || (m_event_chunks.count() == 0 && m_wavefiles.isEmpty() && oxifile.isEmpty())) {
|
if (session->m_slices.count() == 0 || (m_event_chunks.count() == 0 && m_wavefiles.isEmpty() && m_oxifiles.isEmpty())) {
|
||||||
session->setSummaryOnly(true);
|
session->setSummaryOnly(true);
|
||||||
save = true;
|
save = true;
|
||||||
break; // and skip the occasional fragmentary event or waveform data
|
break; // and skip the occasional fragmentary event or waveform data
|
||||||
@ -8430,14 +8427,18 @@ bool PRS1Import::ParseSession(void)
|
|||||||
|
|
||||||
if (!m_wavefiles.isEmpty()) {
|
if (!m_wavefiles.isEmpty()) {
|
||||||
// Parse .005 Waveform files
|
// Parse .005 Waveform files
|
||||||
|
waveforms = ReadWaveformData(m_wavefiles, "Waveform");
|
||||||
|
|
||||||
|
// Extract and import raw data into channels.
|
||||||
ImportWaveforms();
|
ImportWaveforms();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oxifile.isEmpty()) {
|
if (!m_oxifiles.isEmpty()) {
|
||||||
// Parse .006 Waveform file
|
// Parse .006 Waveform files
|
||||||
oximetry = loader->ParseFile(oxifile);
|
oximetry = ReadWaveformData(m_oxifiles, "Oximetry");
|
||||||
oximetry = CoalesceWaveformChunks(oximetry);
|
|
||||||
ParseOximetry();
|
// Extract and import raw data into channels.
|
||||||
|
ImportOximetry();
|
||||||
}
|
}
|
||||||
|
|
||||||
save = true;
|
save = true;
|
||||||
@ -8447,16 +8448,17 @@ bool PRS1Import::ParseSession(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PRS1Import::ImportWaveforms()
|
QList<PRS1DataChunk *> PRS1Import::ReadWaveformData(QList<QString> & files, const char* label)
|
||||||
{
|
{
|
||||||
QMap<qint64,PRS1DataChunk *> waveform_chunks;
|
QMap<qint64,PRS1DataChunk *> waveform_chunks;
|
||||||
|
QList<PRS1DataChunk *> result;
|
||||||
|
|
||||||
if (m_wavefiles.count() > 1) {
|
if (files.count() > 1) {
|
||||||
qDebug() << session->session() << "Waveform data split across multiple files";
|
qDebug() << session->session() << label << "data split across multiple files";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & f : m_wavefiles) {
|
for (auto & f : files) {
|
||||||
// Parse a single .005 Waveform file
|
// Parse a single .005 or .006 waveform file
|
||||||
QList<PRS1DataChunk *> file_chunks = loader->ParseFile(f);
|
QList<PRS1DataChunk *> file_chunks = loader->ParseFile(f);
|
||||||
for (auto & chunk : file_chunks) {
|
for (auto & chunk : file_chunks) {
|
||||||
PRS1DataChunk* previous = waveform_chunks[chunk->timestamp];
|
PRS1DataChunk* previous = waveform_chunks[chunk->timestamp];
|
||||||
@ -8471,21 +8473,12 @@ void PRS1Import::ImportWaveforms()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of pointers sorted by timestamp.
|
// Get the list of pointers sorted by timestamp.
|
||||||
waveforms = waveform_chunks.values();
|
result = waveform_chunks.values();
|
||||||
|
|
||||||
// Coalesce contiguous waveform chunks into larger chunks.
|
// Coalesce contiguous waveform chunks into larger chunks.
|
||||||
waveforms = CoalesceWaveformChunks(waveforms);
|
result = CoalesceWaveformChunks(result);
|
||||||
|
|
||||||
if (session->eventlist.contains(CPAP_FlowRate)) {
|
return result;
|
||||||
if (waveforms.size() > 0) {
|
|
||||||
// Delete anything called "Flow rate" picked up in the events file if real data is present
|
|
||||||
qWarning() << session->session() << "Deleting flow rate events due to flow rate waveform data";
|
|
||||||
session->destroyEvent(CPAP_FlowRate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract raw data into channels.
|
|
||||||
ParseWaveforms();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
QList<QString> m_wavefiles;
|
QList<QString> m_wavefiles;
|
||||||
QString oxifile;
|
QList<QString> m_oxifiles;
|
||||||
|
|
||||||
//! \brief Imports .000 files for bricks.
|
//! \brief Imports .000 files for bricks.
|
||||||
bool ImportCompliance();
|
bool ImportCompliance();
|
||||||
@ -306,17 +306,17 @@ public:
|
|||||||
//! \brief Imports the .002 event file(s).
|
//! \brief Imports the .002 event file(s).
|
||||||
bool ImportEvents();
|
bool ImportEvents();
|
||||||
|
|
||||||
//! \brief Imports the .005 event file(s).
|
//! \brief Reads the .005 or .006 waveform file(s).
|
||||||
void ImportWaveforms();
|
QList<PRS1DataChunk *> ReadWaveformData(QList<QString> & files, const char* label);
|
||||||
|
|
||||||
//! \brief Coalesce contiguous .005 or .006 waveform chunks from the file into larger chunks for import.
|
//! \brief Coalesce contiguous .005 or .006 waveform chunks from the file into larger chunks for import.
|
||||||
QList<PRS1DataChunk *> CoalesceWaveformChunks(QList<PRS1DataChunk *> & allchunks);
|
QList<PRS1DataChunk *> CoalesceWaveformChunks(QList<PRS1DataChunk *> & allchunks);
|
||||||
|
|
||||||
//! \brief Takes the parsed list of Flow/MaskPressure waveform chunks and adds them to the database
|
//! \brief Takes the parsed list of Flow/MaskPressure waveform chunks and adds them to the database
|
||||||
void ParseWaveforms();
|
void ImportWaveforms();
|
||||||
|
|
||||||
//! \brief Takes the parsed list of oximeter waveform chunks and adds them to the database.
|
//! \brief Takes the parsed list of oximeter waveform chunks and adds them to the database.
|
||||||
void ParseOximetry();
|
void ImportOximetry();
|
||||||
|
|
||||||
//! \brief Adds a single channel of continuous oximetry data to the database, splitting on any missing samples.
|
//! \brief Adds a single channel of continuous oximetry data to the database, splitting on any missing samples.
|
||||||
void ImportOximetryChannel(ChannelID channel, QByteArray & data, quint64 ti, qint64 dur);
|
void ImportOximetryChannel(ChannelID channel, QByteArray & data, quint64 ti, qint64 dur);
|
||||||
|
@ -194,6 +194,7 @@ class Session
|
|||||||
t += slice.end - slice.start;
|
t += slice.end - slice.start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
t = t / 3600000.0;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* ExportCSV module implementation
|
/* ExportCSV module implementation
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2020 The OSCAR Team
|
||||||
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
@ -180,24 +181,16 @@ void ExportCSV::on_exportButton_clicked()
|
|||||||
countlist.append(CPAP_UserFlag2);
|
countlist.append(CPAP_UserFlag2);
|
||||||
countlist.append(CPAP_PressurePulse);
|
countlist.append(CPAP_PressurePulse);
|
||||||
|
|
||||||
avglist.append(CPAP_Pressure);
|
QVector<ChannelID> statChannels = { CPAP_Pressure, CPAP_PressureSet, CPAP_IPAP, CPAP_IPAPSet, CPAP_EPAP, CPAP_EPAPSet, CPAP_FLG };
|
||||||
avglist.append(CPAP_IPAP);
|
for (auto & chan : statChannels) {
|
||||||
avglist.append(CPAP_EPAP);
|
avglist.append(chan);
|
||||||
avglist.append(CPAP_FLG); // Pholynyk, 25Aug2015, add ResMed Flow Limitation
|
p90list.append(chan);
|
||||||
|
maxlist.append(chan);
|
||||||
p90list.append(CPAP_Pressure);
|
}
|
||||||
p90list.append(CPAP_IPAP);
|
|
||||||
p90list.append(CPAP_EPAP);
|
|
||||||
p90list.append(CPAP_FLG);
|
|
||||||
|
|
||||||
float percentile=p_profile->general->prefCalcPercentile()/100.0; // Pholynyk, 18Aug2015
|
float percentile=p_profile->general->prefCalcPercentile()/100.0; // Pholynyk, 18Aug2015
|
||||||
EventDataType percent = percentile; // was 0.90F
|
EventDataType percent = percentile; // was 0.90F
|
||||||
|
|
||||||
maxlist.append(CPAP_Pressure); // Pholynyk, 18Aug2015, add maximums
|
|
||||||
maxlist.append(CPAP_IPAP);
|
|
||||||
maxlist.append(CPAP_EPAP);
|
|
||||||
maxlist.append(CPAP_FLG);
|
|
||||||
|
|
||||||
// Not sure this section should be translateable.. :-/
|
// Not sure this section should be translateable.. :-/
|
||||||
if (ui->rb1_details->isChecked()) {
|
if (ui->rb1_details->isChecked()) {
|
||||||
header = tr("DateTime") + sep + tr("Session") + sep + tr("Event") + sep + tr("Data/Duration");
|
header = tr("DateTime") + sep + tr("Session") + sep + tr("Event") + sep + tr("Data/Duration");
|
||||||
|
@ -305,6 +305,7 @@ SOURCES += \
|
|||||||
SleepLib/serialoximeter.cpp \
|
SleepLib/serialoximeter.cpp \
|
||||||
SleepLib/loader_plugins/md300w1_loader.cpp \
|
SleepLib/loader_plugins/md300w1_loader.cpp \
|
||||||
Graphs/gSessionTimesChart.cpp \
|
Graphs/gSessionTimesChart.cpp \
|
||||||
|
Graphs/gPressureChart.cpp \
|
||||||
logger.cpp \
|
logger.cpp \
|
||||||
SleepLib/machine_common.cpp \
|
SleepLib/machine_common.cpp \
|
||||||
SleepLib/loader_plugins/weinmann_loader.cpp \
|
SleepLib/loader_plugins/weinmann_loader.cpp \
|
||||||
@ -383,6 +384,7 @@ HEADERS += \
|
|||||||
SleepLib/serialoximeter.h \
|
SleepLib/serialoximeter.h \
|
||||||
SleepLib/loader_plugins/md300w1_loader.h \
|
SleepLib/loader_plugins/md300w1_loader.h \
|
||||||
Graphs/gSessionTimesChart.h \
|
Graphs/gSessionTimesChart.h \
|
||||||
|
Graphs/gPressureChart.h \
|
||||||
logger.h \
|
logger.h \
|
||||||
SleepLib/loader_plugins/weinmann_loader.h \
|
SleepLib/loader_plugins/weinmann_loader.h \
|
||||||
Graphs/gdailysummary.h \
|
Graphs/gdailysummary.h \
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Overview GUI Implementation
|
/* Overview GUI Implementation
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2020 The Oscar Team
|
||||||
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include "Graphs/gXAxis.h"
|
#include "Graphs/gXAxis.h"
|
||||||
#include "Graphs/gLineChart.h"
|
#include "Graphs/gLineChart.h"
|
||||||
#include "Graphs/gYAxis.h"
|
#include "Graphs/gYAxis.h"
|
||||||
|
#include "Graphs/gPressureChart.h"
|
||||||
#include "cprogressbar.h"
|
#include "cprogressbar.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user