Merged from statistics_dialog

This commit is contained in:
Bjørn Erik Jensen 2017-11-16 11:43:24 +01:00
commit fba74f535f
15 changed files with 941 additions and 208 deletions

View File

@ -56,6 +56,9 @@ ${CEE_CURRENT_LIST_DIR}RicCommandFeature.h
${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.h
${CEE_CURRENT_LIST_DIR}RicReloadSummaryCaseFeature.h
${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.h
${CEE_CURRENT_LIST_DIR}RicGridStatisticsDialog.h
${CEE_CURRENT_LIST_DIR}RicShowGridStatisticsFeature.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
@ -122,6 +125,9 @@ ${CEE_CURRENT_LIST_DIR}RicCloseSourSimDataFeature.cpp
${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.cpp
${CEE_CURRENT_LIST_DIR}RicReloadSummaryCaseFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.cpp
${CEE_CURRENT_LIST_DIR}RicGridStatisticsDialog.cpp
${CEE_CURRENT_LIST_DIR}RicShowGridStatisticsFeature.cpp
)
@ -137,6 +143,7 @@ if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToMetricFeature.cpp
${CEE_CURRENT_LIST_DIR}RicConvertAllFractureTemplatesToFieldFeature.cpp
${CEE_CURRENT_LIST_DIR}RicFractureNameGenerator.cpp
${CEE_CURRENT_LIST_DIR}RicShowGridStaticticsFeature.cpp
)
endif()
@ -149,4 +156,8 @@ list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
list(APPEND QT_MOC_HEADERS
${CEE_CURRENT_LIST_DIR}RicGridStatisticsDialog.h
)
source_group( "CommandFeature" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake )

View File

@ -0,0 +1,215 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicGridStatisticsDialog.h"
#include "RiaApplication.h"
#include "RimEclipseView.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RiuMainPlotWindow.h"
#include "RiuSummaryQwtPlot.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QTextEdit>
#include <QDialogButtonBox>
#include <QPushButton>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_histogram.h>
#include <qwt_series_data.h>
#include <qwt_plot_marker.h>
#include <qwt_symbol.h>
#include <vector>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicGridStatisticsDialog::RicGridStatisticsDialog(QWidget* parent)
: QDialog(parent)
{
// Create widgets
m_label = new QLabel();
m_textEdit = new QTextEdit();
m_historgramPlot = new QwtPlot();
m_aggregatedPlot = new QwtPlot();
m_buttons = new QDialogButtonBox(QDialogButtonBox::Close);
// Connect to signal
connect(m_buttons, SIGNAL(rejected()), this, SLOT(slotDialogFinished()));
// Set widget properties
m_textEdit->setReadOnly(true);
RiuSummaryQwtPlot::setCommonPlotBehaviour(m_historgramPlot);
RiuSummaryQwtPlot::setCommonPlotBehaviour(m_aggregatedPlot);
// Define layout
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(m_label);
layout->addWidget(m_textEdit);
layout->addWidget(m_historgramPlot);
layout->addWidget(m_aggregatedPlot);
layout->addWidget(m_buttons);
setLayout(layout);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicGridStatisticsDialog::~RicGridStatisticsDialog()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::setLabel(const QString& labelText)
{
m_label->setText(labelText);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::setInfoText(RimEclipseView* eclipseView)
{
Rim3dOverlayInfoConfig* overlayInfo = eclipseView->overlayInfoConfig();
if (eclipseView && overlayInfo)
{
QString text;
text = overlayInfo->caseInfoText(eclipseView);
text += overlayInfo->resultInfoText(overlayInfo->histogramData(eclipseView), eclipseView);
m_textEdit->setText(text);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::setHistogramData(RimEclipseView* eclipseView)
{
deletePlotItems(m_historgramPlot);
deletePlotItems(m_aggregatedPlot);
Rim3dOverlayInfoConfig* overlayInfo = eclipseView->overlayInfoConfig();
if (eclipseView && overlayInfo)
{
auto hist = new QwtPlotHistogram("Histogram");
auto aggr = new QwtPlotCurve("Aggregated");
hist->setBrush(QBrush(QColor(Qt::darkYellow)));
hist->setZ(-1);
aggr->setStyle(QwtPlotCurve::Steps);
aggr->setCurveAttribute(QwtPlotCurve::Inverted);
Rim3dOverlayInfoConfig::HistogramData histogramData = overlayInfo->histogramData(eclipseView);
QVector<QwtIntervalSample> histSamples;
QVector<QPointF> aggrSamples;
double xStep = (histogramData.max - histogramData.min) / (*histogramData.histogram).size();
double xCurr = histogramData.min;
double aggrValue = 0.0;
for(size_t value : *histogramData.histogram)
{
double xNext = xCurr + xStep;
histSamples.push_back(QwtIntervalSample(value, xCurr, xNext));
aggrValue += value;
aggrSamples.push_back(QPointF(xCurr, aggrValue));
xCurr = xNext;
}
// Axis
m_historgramPlot->setAxisScale(QwtPlot::xBottom, histogramData.min, histogramData.max);
m_aggregatedPlot->setAxisScale(QwtPlot::xBottom, histogramData.min, histogramData.max);
// Samples
hist->setSamples(histSamples);
aggr->setSamples(aggrSamples);
hist->attach(m_historgramPlot);
aggr->attach(m_aggregatedPlot);
// Markers
setMarkers(histogramData, m_historgramPlot);
setMarkers(histogramData, m_aggregatedPlot);
// Refresh plot
m_historgramPlot->replot();
m_aggregatedPlot->replot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::deletePlotItems(QwtPlot* plot)
{
auto itemList = plot->itemList();
for (auto item : itemList)
{
if (dynamic_cast<QwtPlotMarker*>(item)
|| dynamic_cast<QwtPlotCurve*>(item)
|| dynamic_cast<QwtPlotHistogram*>(item))
{
item->detach();
delete item;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::setMarkers(const Rim3dOverlayInfoConfig::HistogramData& histData, QwtPlot* plot)
{
auto scale = plot->axisScaleDiv(QwtPlot::yLeft);
QwtPlotMarker* marker;
marker = createVerticalPlotMarker(Qt::red, histData.p10);
marker->attach(plot);
marker = createVerticalPlotMarker(Qt::red, histData.p90);
marker->attach(plot);
marker = createVerticalPlotMarker(Qt::blue, histData.mean);
marker->attach(plot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtPlotMarker* RicGridStatisticsDialog::createVerticalPlotMarker(const QColor& color, double xValue)
{
QwtPlotMarker* marker = new QwtPlotMarker();
marker->setXValue(xValue);
marker->setLineStyle(QwtPlotMarker::VLine);
marker->setLinePen(color, 2, Qt::SolidLine);
return marker;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::slotDialogFinished()
{
close();
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Rim3dOverlayInfoConfig.h"
#include <QDialog>
class QLabel;
class QTextEdit;
class QDialogButtonBox;
class QwtPlot;
class QwtPlotMarker;
class RimEclipseView;
//==================================================================================================
///
///
//==================================================================================================
class RicGridStatisticsDialog : public QDialog
{
Q_OBJECT
public:
RicGridStatisticsDialog(QWidget* parent);
~RicGridStatisticsDialog();
void setLabel(const QString& labelText);
void setInfoText(RimEclipseView* eclipseView);
void setHistogramData(RimEclipseView* eclipseView);
private:
void deletePlotItems(QwtPlot* plot);
static void setMarkers(const Rim3dOverlayInfoConfig::HistogramData& histData, QwtPlot* plot);
static QwtPlotMarker* createVerticalPlotMarker(const QColor& color, double xValue);
private slots:
void slotDialogFinished();
private:
QLabel* m_label;
QTextEdit* m_textEdit;
QwtPlot* m_historgramPlot;
QwtPlot* m_aggregatedPlot;
QDialogButtonBox* m_buttons;
};

View File

@ -0,0 +1,64 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicShowGridStatisticsFeature.h"
#include "RiaApplication.h"
#include "RicGridStatisticsDialog.h"
#include "RimProject.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimEclipseView.h"
#include "cafSelectionManagerTools.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicShowGridStatisticsFeature, "RicShowGridStatisticsFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicShowGridStatisticsFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowGridStatisticsFeature::onActionTriggered(bool isChecked)
{
auto eclipseView = caf::firstAncestorOfTypeFromSelectedObject<RimEclipseView*>();
if (eclipseView && eclipseView->overlayInfoConfig())
{
eclipseView->overlayInfoConfig()->showStatisticsInfoDialog();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowGridStatisticsFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Grid statistics");
actionToSetup->setIcon(QIcon(":/statistics.png")); // Todo: Change icon
}

View File

@ -0,0 +1,36 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
class RicGridStatisticsDialog;
//==================================================================================================
///
//==================================================================================================
class RicShowGridStatisticsFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
virtual bool isCommandEnabled() override;
virtual void onActionTriggered( bool isChecked ) override;
virtual void setupActionLook(QAction* actionToSetup) override;
};

View File

@ -20,6 +20,8 @@
#include "Rim3dOverlayInfoConfig.h"
#include "RicGridStatisticsDialog.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseNativeVisibleCellsStatCalc.h"
@ -102,6 +104,8 @@ Rim3dOverlayInfoConfig::Rim3dOverlayInfoConfig()
//m_statisticsCellRange.uiCapability()->setUiHidden(true);
m_isVisCellStatUpToDate = false;
m_gridStatisticsDialog = std::unique_ptr<RicGridStatisticsDialog>(new RicGridStatisticsDialog(nullptr));
}
//--------------------------------------------------------------------------------------------------
@ -156,6 +160,258 @@ void Rim3dOverlayInfoConfig::setPosition(cvf::Vec2ui position)
m_position = position;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rim3dOverlayInfoConfig::HistogramData Rim3dOverlayInfoConfig::histogramData(RimEclipseView* eclipseView)
{
HistogramData histData;
bool isResultsInfoRelevant = eclipseView->hasUserRequestedAnimation() && eclipseView->cellResult()->hasResult();
if (isResultsInfoRelevant)
{
size_t scalarIndex = eclipseView->cellResult()->scalarResultIndex();
if (scalarIndex != cvf::UNDEFINED_SIZE_T)
{
if (m_statisticsCellRange == ALL_CELLS)
{
if (m_statisticsTimeRange == ALL_TIMESTEPS)
{
eclipseView->currentGridCellResults()->minMaxCellScalarValues(scalarIndex, histData.min, histData.max);
eclipseView->currentGridCellResults()->p10p90CellScalarValues(scalarIndex, histData.p10, histData.p90);
eclipseView->currentGridCellResults()->meanCellScalarValues(scalarIndex, histData.mean);
eclipseView->currentGridCellResults()->sumCellScalarValues(scalarIndex, histData.sum);
histData.histogram = &(eclipseView->currentGridCellResults()->cellScalarValuesHistogram(scalarIndex));
}
else if (m_statisticsTimeRange == CURRENT_TIMESTEP)
{
int currentTimeStep = eclipseView->currentTimeStep();
if (eclipseView->cellResult()->hasStaticResult())
{
currentTimeStep = 0;
}
eclipseView->currentGridCellResults()->minMaxCellScalarValues(scalarIndex, currentTimeStep, histData.min, histData.max);
eclipseView->currentGridCellResults()->p10p90CellScalarValues(scalarIndex, currentTimeStep, histData.p10, histData.p90);
eclipseView->currentGridCellResults()->meanCellScalarValues(scalarIndex, currentTimeStep, histData.mean);
eclipseView->currentGridCellResults()->sumCellScalarValues(scalarIndex, currentTimeStep, histData.sum);
histData.histogram = &(eclipseView->currentGridCellResults()->cellScalarValuesHistogram(scalarIndex, currentTimeStep));
}
else
{
CVF_ASSERT(false);
}
}
else if (m_statisticsCellRange == VISIBLE_CELLS)
{
updateVisCellStatsIfNeeded();
if (m_statisticsTimeRange == ALL_TIMESTEPS)
{
// TODO: Only valid if we have no dynamic property filter
m_visibleCellStatistics->meanCellScalarValues(histData.mean);
m_visibleCellStatistics->minMaxCellScalarValues(histData.min, histData.max);
m_visibleCellStatistics->p10p90CellScalarValues(histData.p10, histData.p90);
m_visibleCellStatistics->sumCellScalarValues(histData.sum);
histData.histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram());
}
else if (m_statisticsTimeRange == CURRENT_TIMESTEP)
{
int currentTimeStep = eclipseView->currentTimeStep();
if (eclipseView->cellResult()->hasStaticResult())
{
currentTimeStep = 0;
}
m_visibleCellStatistics->meanCellScalarValues(currentTimeStep, histData.mean);
m_visibleCellStatistics->minMaxCellScalarValues(currentTimeStep, histData.min, histData.max);
m_visibleCellStatistics->p10p90CellScalarValues(currentTimeStep, histData.p10, histData.p90);
m_visibleCellStatistics->sumCellScalarValues(currentTimeStep, histData.sum);
m_visibleCellStatistics->mobileVolumeWeightedMean(currentTimeStep, histData.weightedMean);
histData.histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram(currentTimeStep));
}
}
}
else if (eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())
{
if (m_statisticsTimeRange == CURRENT_TIMESTEP || m_statisticsTimeRange == ALL_TIMESTEPS) // All timesteps is ignored
{
int currentTimeStep = eclipseView->currentTimeStep();
if (m_statisticsCellRange == ALL_CELLS)
{
RigFlowDiagResults* fldResults = eclipseView->cellResult()->flowDiagSolution()->flowDiagResults();
RigFlowDiagResultAddress resAddr = eclipseView->cellResult()->flowDiagResAddress();
fldResults->minMaxScalarValues(resAddr, currentTimeStep, &histData.min, &histData.max);
fldResults->p10p90ScalarValues(resAddr, currentTimeStep, &histData.p10, &histData.p90);
fldResults->meanScalarValue(resAddr, currentTimeStep, &histData.mean);
fldResults->sumScalarValue(resAddr, currentTimeStep, &histData.sum);
histData.histogram = &(fldResults->scalarValuesHistogram(resAddr, currentTimeStep));
}
else if (m_statisticsCellRange == VISIBLE_CELLS)
{
updateVisCellStatsIfNeeded();
m_visibleCellStatistics->meanCellScalarValues(currentTimeStep, histData.mean);
m_visibleCellStatistics->minMaxCellScalarValues(currentTimeStep, histData.min, histData.max);
m_visibleCellStatistics->p10p90CellScalarValues(currentTimeStep, histData.p10, histData.p90);
m_visibleCellStatistics->sumCellScalarValues(currentTimeStep, histData.sum);
m_visibleCellStatistics->mobileVolumeWeightedMean(currentTimeStep, histData.weightedMean);
histData.histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram(currentTimeStep));
}
}
}
}
return histData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString Rim3dOverlayInfoConfig::caseInfoText(RimEclipseView* eclipseView)
{
QString infoText;
if (showCaseInfo())
{
QString caseName;
QString totCellCount;
QString activeCellCountText;
QString fractureActiveCellCount;
QString iSize, jSize, kSize;
QString zScale;
if (eclipseView->mainGrid())
{
caseName = eclipseView->eclipseCase()->caseUserDescription();
totCellCount = QString::number(eclipseView->mainGrid()->globalCellArray().size());
size_t mxActCellCount = eclipseView->eclipseCase()->eclipseCaseData()->activeCellInfo(RiaDefines::MATRIX_MODEL)->reservoirActiveCellCount();
size_t frActCellCount = eclipseView->eclipseCase()->eclipseCaseData()->activeCellInfo(RiaDefines::FRACTURE_MODEL)->reservoirActiveCellCount();
if (frActCellCount > 0) activeCellCountText += "Matrix : ";
activeCellCountText += QString::number(mxActCellCount);
if (frActCellCount > 0) activeCellCountText += " Fracture : " + QString::number(frActCellCount);
iSize = QString::number(eclipseView->mainGrid()->cellCountI());
jSize = QString::number(eclipseView->mainGrid()->cellCountJ());
kSize = QString::number(eclipseView->mainGrid()->cellCountK());
zScale = QString::number(eclipseView->scaleZ());
}
infoText += QString(
"<p><b><center>-- %1 --</center></b><p> "
"<b>Cell count. Total:</b> %2 <b>Active:</b> %3 <br>"
"<b>Main Grid I,J,K:</b> %4, %5, %6 <b>Z-Scale:</b> %7<br>").arg(caseName, totCellCount, activeCellCountText, iSize, jSize, kSize, zScale);
}
return infoText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData, RimEclipseView* eclipseView)
{
QString infoText;
bool isResultsInfoRelevant = eclipseView->hasUserRequestedAnimation() && eclipseView->cellResult()->hasResult();
if (eclipseView->cellResult()->isTernarySaturationSelected())
{
QString propName = eclipseView->cellResult()->resultVariableUiShortName();
infoText += QString("<b>Cell Property:</b> %1 ").arg(propName);
}
if (isResultsInfoRelevant)
{
QString propName = eclipseView->cellResult()->resultVariableUiShortName();
QString timeRangeText = m_statisticsTimeRange().uiText();
if (eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())
{
timeRangeText = caf::AppEnum<StatisticsTimeRangeType>::uiText(CURRENT_TIMESTEP);
}
infoText += QString("<b>Cell Property:</b> %1 ").arg(propName);
infoText += QString("<br><b>Statistics:</b> ") + timeRangeText + " and " + m_statisticsCellRange().uiText();
infoText += QString("<table border=0 cellspacing=5 >"
"<tr> <td>Min</td> <td>P10</td> <td>Mean</td> <td>P90</td> <td>Max</td> <td>Sum</td> </tr>"
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
"</table>").arg(histData.min).arg(histData.p10).arg(histData.mean).arg(histData.p90).arg(histData.max).arg(histData.sum);
if (eclipseView->faultResultSettings()->hasValidCustomResult())
{
QString faultMapping;
bool isShowingGrid = eclipseView->faultCollection()->isGridVisualizationMode();
if (!isShowingGrid)
{
if (eclipseView->faultCollection()->faultResult() == RimFaultInViewCollection::FAULT_BACK_FACE_CULLING)
{
faultMapping = "Cells behind fault";
}
else if (eclipseView->faultCollection()->faultResult() == RimFaultInViewCollection::FAULT_FRONT_FACE_CULLING)
{
faultMapping = "Cells in front of fault";
}
else
{
faultMapping = "Cells in front and behind fault";
}
}
else
{
faultMapping = "Cells in front and behind fault";
}
infoText += QString("<b>Fault results: </b> %1<br>").arg(faultMapping);
infoText += QString("<b>Fault Property:</b> %1 <br>").arg(eclipseView->faultResultSettings()->customFaultResult()->resultVariableUiShortName());
}
}
if (eclipseView->hasUserRequestedAnimation() && eclipseView->cellEdgeResult()->hasResult())
{
double min, max;
QString cellEdgeName = eclipseView->cellEdgeResult()->resultVariableUiShortName();
eclipseView->cellEdgeResult()->minMaxCellEdgeValues(min, max);
infoText += QString("<b>Cell Edge Property:</b> %1 ").arg(cellEdgeName);
infoText += QString("<table border=0 cellspacing=5 >"
"<tr> <td>Min</td> <td></td> <td></td> <td></td> <td>Max</td> </tr>"
"<tr> <td>%1</td> <td></td> <td></td> <td></td> <td> %2</td></tr>"
"</table>").arg(min).arg(max);
}
if (showVolumeWeightedMean() && histData.weightedMean != HUGE_VAL)
{
infoText += QString("<b>Mobile Volume Weighted Mean:</b> %1").arg(histData.weightedMean);
}
return infoText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rim3dOverlayInfoConfig::showStatisticsInfoDialog()
{
auto eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p());
if (eclipseView)
{
m_gridStatisticsDialog->setLabel("Grid statistics");
m_gridStatisticsDialog->setInfoText(eclipseView);
m_gridStatisticsDialog->setHistogramData(eclipseView);
m_gridStatisticsDialog->resize(600, 800);
m_gridStatisticsDialog->show();
m_gridStatisticsDialog->raise();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -188,7 +444,14 @@ void Rim3dOverlayInfoConfig::update3DInfo()
}
RimEclipseView * reservoirView = dynamic_cast<RimEclipseView*>(m_viewDef.p());
if (reservoirView) updateEclipse3DInfo(reservoirView);
if (reservoirView)
{
updateEclipse3DInfo(reservoirView);
// Update statistics dialog
m_gridStatisticsDialog->setInfoText(reservoirView);
m_gridStatisticsDialog->setHistogramData(reservoirView);
}
RimGeoMechView * geoMechView = dynamic_cast<RimGeoMechView*>(m_viewDef.p());
if (geoMechView) updateGeoMech3DInfo(geoMechView);
}
@ -240,224 +503,24 @@ void Rim3dOverlayInfoConfig::setReservoirView(RimView* ownerReservoirView)
//--------------------------------------------------------------------------------------------------
void Rim3dOverlayInfoConfig::updateEclipse3DInfo(RimEclipseView * eclipseView)
{
double min = HUGE_VAL, max = HUGE_VAL;
double p10 = HUGE_VAL, p90 = HUGE_VAL;
double mean = HUGE_VAL;
double sum = 0.0;
HistogramData histData;
double weightedMean = HUGE_VAL;
const std::vector<size_t>* histogram = NULL;
bool isResultsInfoRelevant = eclipseView->hasUserRequestedAnimation() && eclipseView->cellResult()->hasResult();
if (showHistogram() || showResultInfo())
{
if (isResultsInfoRelevant)
{
size_t scalarIndex = eclipseView->cellResult()->scalarResultIndex();
if (scalarIndex != cvf::UNDEFINED_SIZE_T)
{
if (m_statisticsCellRange == ALL_CELLS)
{
if (m_statisticsTimeRange == ALL_TIMESTEPS)
{
eclipseView->currentGridCellResults()->minMaxCellScalarValues(scalarIndex, min, max);
eclipseView->currentGridCellResults()->p10p90CellScalarValues(scalarIndex, p10, p90);
eclipseView->currentGridCellResults()->meanCellScalarValues(scalarIndex, mean);
eclipseView->currentGridCellResults()->sumCellScalarValues(scalarIndex, sum);
histogram = &(eclipseView->currentGridCellResults()->cellScalarValuesHistogram(scalarIndex));
}
else if (m_statisticsTimeRange == CURRENT_TIMESTEP)
{
int currentTimeStep = eclipseView->currentTimeStep();
if (eclipseView->cellResult()->hasStaticResult())
{
currentTimeStep = 0;
}
eclipseView->currentGridCellResults()->minMaxCellScalarValues(scalarIndex, currentTimeStep, min, max);
eclipseView->currentGridCellResults()->p10p90CellScalarValues(scalarIndex, currentTimeStep, p10, p90);
eclipseView->currentGridCellResults()->meanCellScalarValues(scalarIndex, currentTimeStep, mean);
eclipseView->currentGridCellResults()->sumCellScalarValues(scalarIndex, currentTimeStep, sum);
histogram = &(eclipseView->currentGridCellResults()->cellScalarValuesHistogram(scalarIndex, currentTimeStep));
}
else
{
CVF_ASSERT(false);
}
}
else if (m_statisticsCellRange == VISIBLE_CELLS)
{
updateVisCellStatsIfNeeded();
if (m_statisticsTimeRange == ALL_TIMESTEPS)
{
// TODO: Only valid if we have no dynamic property filter
m_visibleCellStatistics->meanCellScalarValues(mean);
m_visibleCellStatistics->minMaxCellScalarValues(min, max);
m_visibleCellStatistics->p10p90CellScalarValues(p10, p90);
m_visibleCellStatistics->sumCellScalarValues(sum);
histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram());
}
else if (m_statisticsTimeRange == CURRENT_TIMESTEP)
{
int currentTimeStep = eclipseView->currentTimeStep();
if (eclipseView->cellResult()->hasStaticResult())
{
currentTimeStep = 0;
}
m_visibleCellStatistics->meanCellScalarValues(currentTimeStep, mean);
m_visibleCellStatistics->minMaxCellScalarValues(currentTimeStep, min, max);
m_visibleCellStatistics->p10p90CellScalarValues(currentTimeStep, p10, p90);
m_visibleCellStatistics->sumCellScalarValues(currentTimeStep, sum);
m_visibleCellStatistics->mobileVolumeWeightedMean(currentTimeStep, weightedMean);
histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram(currentTimeStep));
}
}
}
else if (eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())
{
if (m_statisticsTimeRange == CURRENT_TIMESTEP || m_statisticsTimeRange == ALL_TIMESTEPS) // All timesteps is ignored
{
int currentTimeStep = eclipseView->currentTimeStep();
if (m_statisticsCellRange == ALL_CELLS)
{
RigFlowDiagResults* fldResults = eclipseView->cellResult()->flowDiagSolution()->flowDiagResults();
RigFlowDiagResultAddress resAddr = eclipseView->cellResult()->flowDiagResAddress();
fldResults->minMaxScalarValues(resAddr, currentTimeStep, &min, &max);
fldResults->p10p90ScalarValues(resAddr, currentTimeStep, &p10, &p90);
fldResults->meanScalarValue(resAddr, currentTimeStep, &mean);
fldResults->sumScalarValue(resAddr, currentTimeStep, &sum);
histogram = &(fldResults->scalarValuesHistogram(resAddr, currentTimeStep));
}
else if (m_statisticsCellRange == VISIBLE_CELLS)
{
updateVisCellStatsIfNeeded();
m_visibleCellStatistics->meanCellScalarValues(currentTimeStep, mean);
m_visibleCellStatistics->minMaxCellScalarValues(currentTimeStep, min, max);
m_visibleCellStatistics->p10p90CellScalarValues(currentTimeStep, p10, p90);
m_visibleCellStatistics->sumCellScalarValues(currentTimeStep, sum);
m_visibleCellStatistics->mobileVolumeWeightedMean(currentTimeStep, weightedMean);
histogram = &(m_visibleCellStatistics->cellScalarValuesHistogram(currentTimeStep));
}
}
}
}
histData = histogramData(eclipseView);
}
QString infoText;
if (showCaseInfo())
{
QString caseName;
QString totCellCount;
QString activeCellCountText;
QString fractureActiveCellCount;
QString iSize, jSize, kSize;
QString zScale;
if (eclipseView->mainGrid())
{
caseName = eclipseView->eclipseCase()->caseUserDescription();
totCellCount = QString::number(eclipseView->mainGrid()->globalCellArray().size());
size_t mxActCellCount = eclipseView->eclipseCase()->eclipseCaseData()->activeCellInfo(RiaDefines::MATRIX_MODEL)->reservoirActiveCellCount();
size_t frActCellCount = eclipseView->eclipseCase()->eclipseCaseData()->activeCellInfo(RiaDefines::FRACTURE_MODEL)->reservoirActiveCellCount();
if (frActCellCount > 0) activeCellCountText += "Matrix : ";
activeCellCountText += QString::number(mxActCellCount);
if (frActCellCount > 0) activeCellCountText += " Fracture : " + QString::number(frActCellCount);
iSize = QString::number(eclipseView->mainGrid()->cellCountI());
jSize = QString::number(eclipseView->mainGrid()->cellCountJ());
kSize = QString::number(eclipseView->mainGrid()->cellCountK());
zScale = QString::number(eclipseView->scaleZ());
}
infoText += QString(
"<p><b><center>-- %1 --</center></b><p> "
"<b>Cell count. Total:</b> %2 <b>Active:</b> %3 <br>"
"<b>Main Grid I,J,K:</b> %4, %5, %6 <b>Z-Scale:</b> %7<br>").arg(caseName, totCellCount, activeCellCountText, iSize, jSize, kSize, zScale);
infoText = caseInfoText(eclipseView);
}
if (showResultInfo())
{
if (eclipseView->cellResult()->isTernarySaturationSelected())
{
QString propName = eclipseView->cellResult()->resultVariableUiShortName();
infoText += QString("<b>Cell Property:</b> %1 ").arg(propName);
}
if (isResultsInfoRelevant)
{
QString propName = eclipseView->cellResult()->resultVariableUiShortName();
QString timeRangeText = m_statisticsTimeRange().uiText();
if (eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())
{
timeRangeText = caf::AppEnum<StatisticsTimeRangeType>::uiText(CURRENT_TIMESTEP);
}
infoText += QString("<b>Cell Property:</b> %1 ").arg(propName);
infoText += QString("<br><b>Statistics:</b> ") + timeRangeText + " and " + m_statisticsCellRange().uiText();
infoText += QString("<table border=0 cellspacing=5 >"
"<tr> <td>Min</td> <td>P10</td> <td>Mean</td> <td>P90</td> <td>Max</td> <td>Sum</td> </tr>"
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
"</table>").arg(min).arg(p10).arg(mean).arg(p90).arg(max).arg(sum);
if (eclipseView->faultResultSettings()->hasValidCustomResult())
{
QString faultMapping;
bool isShowingGrid = eclipseView->faultCollection()->isGridVisualizationMode();
if (!isShowingGrid)
{
if (eclipseView->faultCollection()->faultResult() == RimFaultInViewCollection::FAULT_BACK_FACE_CULLING)
{
faultMapping = "Cells behind fault";
}
else if (eclipseView->faultCollection()->faultResult() == RimFaultInViewCollection::FAULT_FRONT_FACE_CULLING)
{
faultMapping = "Cells in front of fault";
}
else
{
faultMapping = "Cells in front and behind fault";
}
}
else
{
faultMapping = "Cells in front and behind fault";
}
infoText += QString("<b>Fault results: </b> %1<br>").arg(faultMapping);
infoText += QString("<b>Fault Property:</b> %1 <br>").arg(eclipseView->faultResultSettings()->customFaultResult()->resultVariableUiShortName());
}
}
if (eclipseView->hasUserRequestedAnimation() && eclipseView->cellEdgeResult()->hasResult())
{
double min, max;
QString cellEdgeName = eclipseView->cellEdgeResult()->resultVariableUiShortName();
eclipseView->cellEdgeResult()->minMaxCellEdgeValues(min, max);
infoText += QString("<b>Cell Edge Property:</b> %1 ").arg(cellEdgeName);
infoText += QString("<table border=0 cellspacing=5 >"
"<tr> <td>Min</td> <td></td> <td></td> <td></td> <td>Max</td> </tr>"
"<tr> <td>%1</td> <td></td> <td></td> <td></td> <td> %2</td></tr>"
"</table>").arg(min).arg(max);
}
if (showVolumeWeightedMean() && weightedMean != HUGE_VAL)
{
infoText += QString("<b>Mobile Volume Weighted Mean:</b> %1").arg(weightedMean);
}
infoText += resultInfoText(histData, eclipseView);
}
if (!infoText.isEmpty())
@ -467,11 +530,13 @@ void Rim3dOverlayInfoConfig::updateEclipse3DInfo(RimEclipseView * eclipseView)
if (showHistogram())
{
if (isResultsInfoRelevant && histogram)
bool isResultsInfoRelevant = eclipseView->hasUserRequestedAnimation() && eclipseView->cellResult()->hasResult();
if (isResultsInfoRelevant && histData.histogram)
{
eclipseView->viewer()->showHistogram(true);
eclipseView->viewer()->setHistogram(min, max, *histogram);
eclipseView->viewer()->setHistogramPercentiles(p10, p90, mean);
eclipseView->viewer()->setHistogram(histData.min, histData.max, *histData.histogram);
eclipseView->viewer()->setHistogramPercentiles(histData.p10, histData.p90, histData.mean);
}
}
}

View File

@ -27,11 +27,14 @@
#include "cvfObject.h"
#include "cvfVector2.h"
#include <cmath>
#include <memory>
class RimEclipseView;
class RimGeoMechView;
class RimView;
class RigStatisticsDataCache;
class RicGridStatisticsDialog;
//==================================================================================================
///
@ -41,6 +44,21 @@ class Rim3dOverlayInfoConfig : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
class HistogramData
{
public:
HistogramData() : min(HUGE_VAL), max(HUGE_VAL), p10(HUGE_VAL), p90(HUGE_VAL), mean(HUGE_VAL), weightedMean(HUGE_VAL), sum(0.0) {}
double min;
double max;
double p10;
double p90;
double mean;
double sum;
double weightedMean;
const std::vector<size_t>* histogram;
};
public:
Rim3dOverlayInfoConfig();
virtual ~Rim3dOverlayInfoConfig();
@ -51,6 +69,12 @@ public:
void setPosition(cvf::Vec2ui position);
HistogramData histogramData(RimEclipseView* eclipseView);
QString caseInfoText(RimEclipseView* eclipseView);
QString resultInfoText(const HistogramData& histData, RimEclipseView* eclipseView);
void showStatisticsInfoDialog();
enum StatisticsTimeRangeType
{
ALL_TIMESTEPS,
@ -92,4 +116,6 @@ private:
bool hasInvalidStatisticsCombination();
bool m_isVisCellStatUpToDate;
cvf::ref<RigStatisticsDataCache> m_visibleCellStatistics;
std::unique_ptr<RicGridStatisticsDialog> m_gridStatisticsDialog;
};

View File

@ -72,6 +72,7 @@
#include "RimRftPlotCollection.h"
#include "RimPltPlotCollection.h"
#include "RimWellLogFile.h"
#include "Rim3dOverlayInfoConfig.h"
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
#include "RimEllipseFractureTemplate.h"
@ -436,6 +437,10 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
{
commandIds << "RicShowFlowCharacteristicsPlotFeature";
}
else if (dynamic_cast<Rim3dOverlayInfoConfig*>(uiItem))
{
commandIds << "RicShowGridStatisticsFeature";
}
#ifdef USE_PROTOTYPE_FEATURE_FRACTURES
else if (dynamic_cast<RimSimWellFracture*>(uiItem))
{

View File

@ -970,6 +970,14 @@ void RimView::updateAnnotationItems()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rim3dOverlayInfoConfig* RimView::overlayInfoConfig() const
{
return m_overlayInfoConfig;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -175,6 +175,9 @@ public:
virtual RimCase* ownerCase() const = 0;
virtual caf::PdmFieldHandle* userDescriptionField() override { return &name; }
Rim3dOverlayInfoConfig* overlayInfoConfig() const;
protected:
void setDefaultView();

View File

@ -102,6 +102,7 @@
<file>SplitterH.png</file>
<file>SplitterV.png</file>
<file>calculator.png</file>
<file>statistics.png</file>
</qresource>
<qresource prefix="/Shader/">
<file>fs_CellFace.glsl</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

View File

@ -62,6 +62,7 @@ ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionEditor.h
${CEE_CURRENT_LIST_DIR}RiuSummaryVectorDescriptionMap.h
${CEE_CURRENT_LIST_DIR}RiuExpressionContextMenuManager.h
${CEE_CURRENT_LIST_DIR}RiuCalculationsContextMenuManager.h
${CEE_CURRENT_LIST_DIR}RiuGridStatisticsHistogramWidget.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -120,6 +121,7 @@ ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionEditor.cpp
${CEE_CURRENT_LIST_DIR}RiuSummaryVectorDescriptionMap.cpp
${CEE_CURRENT_LIST_DIR}RiuExpressionContextMenuManager.cpp
${CEE_CURRENT_LIST_DIR}RiuCalculationsContextMenuManager.cpp
${CEE_CURRENT_LIST_DIR}RiuGridStatisticsHistogramWidget.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,173 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuGridStatisticsHistogramWidget.h"
#include <QPainter>
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuGridStatisticsHistogramWidget::RiuGridStatisticsHistogramWidget(QWidget * parent /*= 0*/, Qt::WindowFlags f /*= 0*/):
QWidget(parent, f)
{
m_minPercentile = HUGE_VAL;
m_maxPercentile = HUGE_VAL;
m_mean = HUGE_VAL;
m_min = HUGE_VAL;
m_max = -HUGE_VAL;
m_maxHistogramCount = 0;
m_width = 0;
m_height = 0;
m_x = 0;
m_y = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridStatisticsHistogramWidget::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
this->draw(&painter, 0, 0, this->width()-1, this->height()-1);
}
void RiuGridStatisticsHistogramWidget::draw(QPainter *painter,int x, int y, int width, int height )
{
// Initialize variables
m_x = x; m_y = y; m_width = width; m_height = height;
QRect r1(x,y,width, height);
// Frame around it all;
QColor windowColor = palette().color(QPalette::Window);// QColor(144, 173, 208, 180);
QColor frameColor = palette().color(QPalette::WindowText);//QColor(220, 240, 255, 100);
QColor foregroundColor = palette().color(QPalette::Dark);// QColor(100, 141, 189);
//painter->fillRect(r1, windowColor);
painter->setPen(frameColor);
painter->drawRect(r1);
// Columns
painter->setPen(foregroundColor);
int yColBottom = yPosFromCount(0);
for ( size_t colIdx = 0; colIdx < m_histogramData.size(); ++colIdx)
{
size_t colCount = m_histogramData[colIdx];
int yColTop = yPosFromCount(colCount);
int xColStart = xPosFromColIdx(colIdx);
int xColEnd = xPosFromColIdx(colIdx+1);
// First line
painter->drawLine(xColStart, yColBottom, xColStart, yColTop);
// If we span more than one pixel with :
++xColStart;
for (;xColStart < xColEnd; ++xColStart )
{
painter->drawLine(xColStart, yColBottom, xColStart, yColTop);
}
}
// Vertical lines for percentiles
if (m_minPercentile != HUGE_VAL)
{
int xpos = xPosFromDomainValue(m_minPercentile);
painter->setPen(QColor(255, 0, 0, 200));
painter->drawLine(xpos, y+1, xpos, y + height -1);
}
// Vertical lines for percentiles
if (m_maxPercentile != HUGE_VAL)
{
int xpos = xPosFromDomainValue(m_maxPercentile);
painter->setPen(QColor(255, 0, 0, 200));
painter->drawLine(xpos, y+1, xpos, y + height -1);
}
// Vertical lines for percentiles
if (m_mean != HUGE_VAL)
{
int xpos = xPosFromDomainValue(m_mean);
painter->setPen(QColor(0, 0, 255, 200));
painter->drawLine(xpos, y+1, xpos, y + height -1);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridStatisticsHistogramWidget::setHistogramData(double min, double max, const std::vector<size_t>& histogram)
{
m_min = min;
m_max = max;
m_histogramData = histogram;
m_maxHistogramCount = 0;
for (size_t colIdx = 0; colIdx < m_histogramData.size(); ++colIdx)
{
if (m_maxHistogramCount < m_histogramData[colIdx]) m_maxHistogramCount = m_histogramData[colIdx] ;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridStatisticsHistogramWidget::setPercentiles(double pmin, double pmax)
{
m_minPercentile = pmin;
m_maxPercentile = pmax;
}
#define xBorder 1
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuGridStatisticsHistogramWidget::xPosFromColIdx(size_t colIdx)
{
return (int)(m_x + xBorder + (m_width - 2*xBorder) * colIdx/m_histogramData.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuGridStatisticsHistogramWidget::xPosFromDomainValue(double value)
{
double range = m_max - m_min;
return (range == 0.0) ? (int)(m_x + xBorder) : (int)(m_x + xBorder + (m_width - 2*xBorder) * (value - m_min)/(m_max - m_min));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuGridStatisticsHistogramWidget::yPosFromCount(size_t colHeight)
{
return (int)(m_y + m_height - 1 - (m_height - 3) * colHeight/m_maxHistogramCount);
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QWidget>
class QPaintEvent;
class QString;
class QStringList;
class RiuGridStatisticsHistogramWidget : public QWidget
{
public:
RiuGridStatisticsHistogramWidget( QWidget * parent = 0, Qt::WindowFlags f = 0);
void setHistogramData(double min, double max, const std::vector<size_t>& histogram);
void setPercentiles(double pmin, double pmax);
void setMean(double mean) {m_mean = mean;}
protected:
virtual void paintEvent(QPaintEvent* event);
private:
void draw(QPainter *painter,int x, int y, int width, int height );
int xPosFromColIdx(size_t colIdx);
int yPosFromCount(size_t colHeight);
int xPosFromDomainValue(double value);
std::vector<size_t> m_histogramData;
double m_max;
double m_min;
double m_minPercentile;
double m_maxPercentile;
double m_mean;
size_t m_maxHistogramCount;
double m_width;
double m_height;
double m_x;
double m_y;
};