mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
statistics: make confidence area and regression line opt-in
This is not perfect - the polygon of the confidence area is calculated even if it is not shown. Oh well. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
ff536e98fc
commit
ba259fb1d6
5 changed files with 57 additions and 21 deletions
|
@ -11,7 +11,8 @@ static const double regressionLineWidth = 2.0;
|
||||||
RegressionItem::RegressionItem(StatsView &view, regression_data reg,
|
RegressionItem::RegressionItem(StatsView &view, regression_data reg,
|
||||||
StatsAxis *xAxis, StatsAxis *yAxis) :
|
StatsAxis *xAxis, StatsAxis *yAxis) :
|
||||||
ChartPixmapItem(view, ChartZValue::ChartFeatures),
|
ChartPixmapItem(view, ChartZValue::ChartFeatures),
|
||||||
xAxis(xAxis), yAxis(yAxis), reg(reg)
|
xAxis(xAxis), yAxis(yAxis), reg(reg),
|
||||||
|
regression(true), confidence(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +20,16 @@ RegressionItem::~RegressionItem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegressionItem::setFeatures(bool regressionIn, bool confidenceIn)
|
||||||
|
{
|
||||||
|
if (regressionIn == regression && confidenceIn == confidence)
|
||||||
|
return;
|
||||||
|
regression = regressionIn;
|
||||||
|
confidence = confidenceIn;
|
||||||
|
updatePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this calculates the confidence area, even if it isn't shown. Might want to optimize this.
|
||||||
void RegressionItem::updatePosition()
|
void RegressionItem::updatePosition()
|
||||||
{
|
{
|
||||||
if (!xAxis || !yAxis)
|
if (!xAxis || !yAxis)
|
||||||
|
@ -74,14 +85,18 @@ void RegressionItem::updatePosition()
|
||||||
ChartPixmapItem::resize(QSizeF(screenMaxX - screenMinX, screenMaxY - screenMinY));
|
ChartPixmapItem::resize(QSizeF(screenMaxX - screenMinX, screenMaxY - screenMinY));
|
||||||
|
|
||||||
img->fill(Qt::transparent);
|
img->fill(Qt::transparent);
|
||||||
|
if (confidence) {
|
||||||
QColor col(regressionItemColor);
|
QColor col(regressionItemColor);
|
||||||
col.setAlphaF(reg.r2);
|
col.setAlphaF(reg.r2);
|
||||||
painter->setPen(Qt::NoPen);
|
painter->setPen(Qt::NoPen);
|
||||||
painter->setBrush(QBrush(col));
|
painter->setBrush(QBrush(col));
|
||||||
painter->drawPolygon(poly);
|
painter->drawPolygon(poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regression) {
|
||||||
painter->setPen(QPen(regressionItemColor, regressionLineWidth));
|
painter->setPen(QPen(regressionItemColor, regressionLineWidth));
|
||||||
painter->drawLine(QPointF(linePolygon[0]), QPointF(linePolygon[1]));
|
painter->drawLine(QPointF(linePolygon[0]), QPointF(linePolygon[1]));
|
||||||
|
}
|
||||||
|
|
||||||
ChartPixmapItem::setPos(offset);
|
ChartPixmapItem::setPos(offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ public:
|
||||||
RegressionItem(StatsView &view, regression_data data, StatsAxis *xAxis, StatsAxis *yAxis);
|
RegressionItem(StatsView &view, regression_data data, StatsAxis *xAxis, StatsAxis *yAxis);
|
||||||
~RegressionItem();
|
~RegressionItem();
|
||||||
void updatePosition();
|
void updatePosition();
|
||||||
|
void setFeatures(bool regression, bool confidence);
|
||||||
private:
|
private:
|
||||||
StatsAxis *xAxis, *yAxis;
|
StatsAxis *xAxis, *yAxis;
|
||||||
regression_data reg;
|
regression_data reg;
|
||||||
|
bool regression, confidence;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,6 +28,8 @@ static const int ChartFeatureLegend = 1 << 1;
|
||||||
static const int ChartFeatureMedian = 1 << 2;
|
static const int ChartFeatureMedian = 1 << 2;
|
||||||
static const int ChartFeatureMean = 1 << 3;
|
static const int ChartFeatureMean = 1 << 3;
|
||||||
static const int ChartFeatureQuartiles = 1 << 4;
|
static const int ChartFeatureQuartiles = 1 << 4;
|
||||||
|
static const int ChartFeatureRegression = 1 << 5;
|
||||||
|
static const int ChartFeatureConfidence = 1 << 6;
|
||||||
|
|
||||||
static const struct ChartTypeDesc {
|
static const struct ChartTypeDesc {
|
||||||
ChartType id;
|
ChartType id;
|
||||||
|
@ -45,7 +47,7 @@ static const struct ChartTypeDesc {
|
||||||
SupportedVariable::Numeric,
|
SupportedVariable::Numeric,
|
||||||
false, false, false,
|
false, false, false,
|
||||||
{ ChartSubType::Dots },
|
{ ChartSubType::Dots },
|
||||||
0
|
ChartFeatureRegression | ChartFeatureConfidence
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ChartType::HistogramCount,
|
ChartType::HistogramCount,
|
||||||
|
@ -161,6 +163,8 @@ StatsState::StatsState() :
|
||||||
median(false),
|
median(false),
|
||||||
mean(false),
|
mean(false),
|
||||||
quartiles(true),
|
quartiles(true),
|
||||||
|
regression(true),
|
||||||
|
confidence(true),
|
||||||
var1Binner(nullptr),
|
var1Binner(nullptr),
|
||||||
var2Binner(nullptr),
|
var2Binner(nullptr),
|
||||||
var2Operation(StatsOperation::Invalid)
|
var2Operation(StatsOperation::Invalid)
|
||||||
|
@ -353,19 +357,23 @@ static StatsState::VariableList createOperationsList(const StatsVariable *var, S
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<StatsState::Feature> createFeaturesList(int chartFeatures, bool labels, bool legend, bool median, bool mean, bool quartiles)
|
static std::vector<StatsState::Feature> createFeaturesList(int chartFeatures, const StatsState &state)
|
||||||
{
|
{
|
||||||
std::vector<StatsState::Feature> res;
|
std::vector<StatsState::Feature> res;
|
||||||
if (chartFeatures & ChartFeatureLabels)
|
if (chartFeatures & ChartFeatureLabels)
|
||||||
res.push_back({ StatsTranslations::tr("labels"), ChartFeatureLabels, labels });
|
res.push_back({ StatsTranslations::tr("labels"), ChartFeatureLabels, state.labels });
|
||||||
if (chartFeatures & ChartFeatureLegend)
|
if (chartFeatures & ChartFeatureLegend)
|
||||||
res.push_back({ StatsTranslations::tr("legend"), ChartFeatureLegend, legend });
|
res.push_back({ StatsTranslations::tr("legend"), ChartFeatureLegend, state.legend });
|
||||||
if (chartFeatures & ChartFeatureMedian)
|
if (chartFeatures & ChartFeatureMedian)
|
||||||
res.push_back({ StatsTranslations::tr("median"), ChartFeatureMedian, median });
|
res.push_back({ StatsTranslations::tr("median"), ChartFeatureMedian, state.median });
|
||||||
if (chartFeatures & ChartFeatureMean)
|
if (chartFeatures & ChartFeatureMean)
|
||||||
res.push_back({ StatsTranslations::tr("mean"), ChartFeatureMean, mean });
|
res.push_back({ StatsTranslations::tr("mean"), ChartFeatureMean, state.mean });
|
||||||
if (chartFeatures & ChartFeatureQuartiles)
|
if (chartFeatures & ChartFeatureQuartiles)
|
||||||
res.push_back({ StatsTranslations::tr("quartiles"), ChartFeatureQuartiles, quartiles });
|
res.push_back({ StatsTranslations::tr("quartiles"), ChartFeatureQuartiles, state.quartiles });
|
||||||
|
if (chartFeatures & ChartFeatureRegression)
|
||||||
|
res.push_back({ StatsTranslations::tr("linear regression"), ChartFeatureRegression, state.regression });
|
||||||
|
if (chartFeatures & ChartFeatureConfidence)
|
||||||
|
res.push_back({ StatsTranslations::tr("95% confidence area"), ChartFeatureConfidence, state.confidence });
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +389,7 @@ StatsState::UIState StatsState::getUIState() const
|
||||||
// Second variable can only be binned if first variable is binned.
|
// Second variable can only be binned if first variable is binned.
|
||||||
res.binners2 = createBinnerList(var2, var2Binner, var1Binner != nullptr, true);
|
res.binners2 = createBinnerList(var2, var2Binner, var1Binner != nullptr, true);
|
||||||
res.operations2 = createOperationsList(var2, var2Operation, var1Binner);
|
res.operations2 = createOperationsList(var2, var2Operation, var1Binner);
|
||||||
res.features = createFeaturesList(chartFeatures, labels, legend, median, mean, quartiles);
|
res.features = createFeaturesList(chartFeatures, *this);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +479,10 @@ void StatsState::featureChanged(int id, bool state)
|
||||||
mean = state;
|
mean = state;
|
||||||
else if (id == ChartFeatureQuartiles)
|
else if (id == ChartFeatureQuartiles)
|
||||||
quartiles = state;
|
quartiles = state;
|
||||||
|
else if (id == ChartFeatureRegression)
|
||||||
|
regression = state;
|
||||||
|
else if (id == ChartFeatureConfidence)
|
||||||
|
confidence = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the new chart-type from the current chart-type and a list of possible chart types.
|
// Creates the new chart-type from the current chart-type and a list of possible chart types.
|
||||||
|
|
|
@ -108,6 +108,8 @@ public:
|
||||||
bool median;
|
bool median;
|
||||||
bool mean;
|
bool mean;
|
||||||
bool quartiles;
|
bool quartiles;
|
||||||
|
bool regression;
|
||||||
|
bool confidence;
|
||||||
const StatsBinner *var1Binner; // nullptr: undefined
|
const StatsBinner *var1Binner; // nullptr: undefined
|
||||||
const StatsBinner *var2Binner; // nullptr: undefined
|
const StatsBinner *var2Binner; // nullptr: undefined
|
||||||
StatsOperation var2Operation;
|
StatsOperation var2Operation;
|
||||||
|
|
|
@ -460,6 +460,11 @@ void StatsView::updateFeatures()
|
||||||
if (medianMarker)
|
if (medianMarker)
|
||||||
medianMarker->setVisible(state.median);
|
medianMarker->setVisible(state.median);
|
||||||
|
|
||||||
|
if (regressionItem) {
|
||||||
|
regressionItem->setVisible(state.regression || state.confidence);
|
||||||
|
if (state.regression || state.confidence)
|
||||||
|
regressionItem->setFeatures(state.regression, state.confidence);
|
||||||
|
}
|
||||||
for (ChartItemPtr<QuartileMarker> &marker: quartileMarkers)
|
for (ChartItemPtr<QuartileMarker> &marker: quartileMarkers)
|
||||||
marker->setVisible(state.quartiles);
|
marker->setVisible(state.quartiles);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue