Merge TableView and SelectionManager changes for #2609 Well Path

This commit is contained in:
Jacob Støren
2018-06-27 17:27:18 +02:00
75 changed files with 2407 additions and 394 deletions

View File

@@ -733,7 +733,7 @@ void RimWellPltPlot::addStackedCurve(const QString& curveName,
curve->setSymbol(RimSummaryCurveAppearanceCalculator::cycledSymbol(curveGroupId));
}
curve->setSymbolSkipDinstance(10);
curve->setSymbolSkipDistance(10);
plotTrack->addCurve(curve);
}
@@ -1018,11 +1018,11 @@ void RimWellPltPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup("Legend and Axis");
legendAndAxisGroup->setCollapsedByDefault(true);
m_wellLogPlot->uiOrderingForPlot(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForPlotSettings(*legendAndAxisGroup);
track->uiOrderingForVisibleXRange(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForVisibleDepthRange(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForDepthAxis(*legendAndAxisGroup);
}
uiOrdering.skipRemainingFields(true);

View File

@@ -781,11 +781,11 @@ void RimWellRftPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup("Legend and Axis");
legendAndAxisGroup->setCollapsedByDefault(true);
m_wellLogPlot->uiOrderingForPlot(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForPlotSettings(*legendAndAxisGroup);
track->uiOrderingForVisibleXRange(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForVisibleDepthRange(*legendAndAxisGroup);
m_wellLogPlot->uiOrderingForDepthAxis(*legendAndAxisGroup);
}
uiOrdering.skipRemainingFields(true);

View File

@@ -547,7 +547,7 @@ QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData, Ri
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>Min</td> <td>P90</td> <td>Mean</td> <td>P10</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);
@@ -650,7 +650,7 @@ QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData, Ri
infoText += QString("<br><b>Statistics:</b> ") + m_statisticsTimeRange().uiText() + " 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>Min</td> <td>P90</td> <td>Mean</td> <td>P10</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);
}

View File

@@ -488,6 +488,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicImportSummaryCasesFeature";
menuBuilder << "RicImportSummaryGroupFeature";
menuBuilder << "RicImportEnsembleFeature";
menuBuilder << "RicNewDerivedEnsembleFeature";
}
else if (dynamic_cast<RimSummaryCaseCollection*>(uiItem))
{
@@ -498,6 +499,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicImportEnsembleFeature";
menuBuilder.subMenuEnd();
menuBuilder.addSeparator();
menuBuilder << "RicNewDerivedEnsembleFeature";
menuBuilder << "RicNewSummaryPlotFeature";
menuBuilder << "RicNewSummaryCrossPlotFeature";
menuBuilder.addSeparator();
@@ -677,6 +679,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicShowPlotDataFeature";
menuBuilder << "RicShowTotalAllocationDataFeature";
menuBuilder << "RicNewDerivedEnsembleFeature";
menuBuilder << "RicNewSummaryPlotFeature";
menuBuilder << "RicNewSummaryCrossPlotFeature";
menuBuilder << "RicSummaryCurveSwitchAxisFeature";

View File

@@ -112,6 +112,8 @@ RimPlotCurve::RimPlotCurve()
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", "");
CAF_PDM_InitField(&m_symbolSize, "SymbolSize", 6, "Symbol Size", "", "", "");
CAF_PDM_InitField(&m_showErrorBars, "ShowErrorBars", true, "Show Error Bars", "", "", "");
m_qwtPlotCurve = new RiuRimQwtPlotCurve(this);
@@ -416,6 +418,9 @@ void RimPlotCurve::updateCurveAppearance()
case SYMBOL_XCROSS:
style = QwtSymbol::XCross;
break;
case SYMBOL_DOWN_TRIANGLE:
style = QwtSymbol::DTriangle;
break;
default:
break;
@@ -424,7 +429,7 @@ void RimPlotCurve::updateCurveAppearance()
// QwtPlotCurve will take ownership of the symbol
symbol = new RiuCurveQwtSymbol(style, m_symbolLabel);
symbol->setSize(6, 6);
symbol->setSize(m_symbolSize, m_symbolSize);
symbol->setColor(curveColor);
}
@@ -541,7 +546,7 @@ RimPlotCurve::PointSymbolEnum RimPlotCurve::symbol()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::setSymbolSkipDinstance(float distance)
void RimPlotCurve::setSymbolSkipDistance(float distance)
{
m_symbolSkipPixelDistance = distance;
}
@@ -554,6 +559,14 @@ void RimPlotCurve::setSymbolLabel(const QString& label)
m_symbolLabel = label;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::setSymbolSize(int sizeInPixels)
{
m_symbolSize = sizeInPixels;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -571,7 +584,7 @@ void RimPlotCurve::resetAppearance()
setLineThickness(2);
setLineStyle(STYLE_SOLID);
setSymbol(SYMBOL_NONE);
setSymbolSkipDinstance(10);
setSymbolSkipDistance(10);
}
//--------------------------------------------------------------------------------------------------

View File

@@ -53,7 +53,8 @@ public:
SYMBOL_DIAMOND,
SYMBOL_TRIANGLE,
SYMBOL_CROSS,
SYMBOL_XCROSS
SYMBOL_XCROSS,
SYMBOL_DOWN_TRIANGLE
};
enum CurveInterpolationEnum
@@ -80,8 +81,9 @@ public:
void setLineStyle(LineStyleEnum lineStyle);
void setSymbol(PointSymbolEnum symbolStyle);
PointSymbolEnum symbol();
void setSymbolSkipDinstance(float distance);
void setSymbolSkipDistance(float distance);
void setSymbolLabel(const QString& label);
void setSymbolSize(int sizeInPixels);
void setLineThickness(int thickness);
void resetAppearance();
@@ -133,6 +135,7 @@ protected:
caf::PdmField<QString> m_customCurveName;
caf::PdmField<bool> m_showLegend;
QString m_symbolLabel;
caf::PdmField<int> m_symbolSize;
caf::PdmField<bool> m_isUsingAutoName;
caf::PdmField<cvf::Color3f> m_curveColor;

View File

@@ -624,6 +624,15 @@ std::vector<RimSummaryCaseCollection*> RimProject::summaryGroups() const
return groups;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseMainCollection* RimProject::firstSummaryCaseMainCollection() const
{
if (oilFields.empty()) return nullptr;
return oilFields[0]->summaryCaseMainCollection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -48,6 +48,7 @@ class RimOilField;
class RimScriptCollection;
class RimSummaryCase;
class RimSummaryCaseCollection;
class RimSummaryCaseMainCollection;
class Rim3dView;
class RimGridView;
class RimViewLinker;
@@ -108,7 +109,8 @@ public:
std::vector<RimSummaryCase*> allSummaryCases() const;
std::vector<RimSummaryCaseCollection*> summaryGroups() const;
RimSummaryCaseMainCollection* firstSummaryCaseMainCollection() const;
void allVisibleViews(std::vector<Rim3dView*>& views);
void allVisibleGridViews(std::vector<RimGridView*>& views);
void allNotLinkedViews(std::vector<RimGridView*>& views);

View File

@@ -65,6 +65,23 @@ void RimViewWindow::removeMdiWindowFromMdiArea()
if ( m_windowController() ) m_windowController->removeWindowFromMDI();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimViewWindow::windowTitle()
{
if (this->userDescriptionField())
{
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
if (uiFieldHandle)
{
QVariant v = uiFieldHandle->uiValue();
return v.toString();
}
}
return QString("");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -168,15 +185,7 @@ void RimViewWindow::updateMdiWindowTitle()
{
if ( viewWidget() )
{
if ( this->userDescriptionField() )
{
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
if ( uiFieldHandle )
{
QVariant v = uiFieldHandle->uiValue();
viewWidget()->setWindowTitle(v.toString());
}
}
viewWidget()->setWindowTitle(windowTitle());
}
}

View File

@@ -69,6 +69,7 @@ protected:
///////// Interface for the Window controller
friend class RimMdiWindowController;
QString windowTitle();
virtual QWidget* createViewWidget(QWidget* mainWindowParent) = 0;
virtual void updateViewWidgetAfterCreation() {};
virtual void updateMdiWindowTitle(); // Has real default implementation

View File

@@ -33,6 +33,7 @@
#include "RiuWellLogPlot.h"
#include "RiuWellLogTrack.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cvfAssert.h"
#include <math.h>
@@ -70,16 +71,19 @@ RimWellLogPlot::RimWellLogPlot()
CAF_PDM_InitField(&m_userName, "PlotDescription", QString("Well Log Plot"),"Name", "", "", "");
caf::AppEnum< RimWellLogPlot::DepthTypeEnum > depthType = MEASURED_DEPTH;
CAF_PDM_InitField(&m_depthType, "DepthType", depthType, "Depth type", "", "", "");
CAF_PDM_InitField(&m_depthType, "DepthType", depthType, "Type", "", "", "");
caf::AppEnum< RiaDefines::DepthUnitType > depthUnit = RiaDefines::UNIT_METER;
CAF_PDM_InitField(&m_depthUnit, "DepthUnit", depthUnit, "Depth unit", "", "", "");
CAF_PDM_InitField(&m_depthUnit, "DepthUnit", depthUnit, "Unit", "", "", "");
CAF_PDM_InitField(&m_minVisibleDepth, "MinimumDepth", 0.0, "Min", "", "", "");
CAF_PDM_InitField(&m_maxVisibleDepth, "MaximumDepth", 1000.0, "Max", "", "", "");
CAF_PDM_InitField(&m_isAutoScaleDepthEnabled, "AutoScaleDepthEnabled", true, "Auto Scale", "", "", "");
m_isAutoScaleDepthEnabled.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_showTitleInPlot, "ShowTitleInPlot", false, "Show Title", "", "", "");
CAF_PDM_InitField(&m_showTrackLegends, "ShowTrackLegends", true, "Show Legends", "", "", "");
CAF_PDM_InitField(&m_trackLegendsHorizontal, "TrackLegendsHorizontal", false, "Legend Orientation", "", "", "");
m_trackLegendsHorizontal.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_tracks, "Tracks", "", "", "", "");
m_tracks.uiCapability()->setUiHidden(true);
@@ -113,6 +117,13 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
m_isAutoScaleDepthEnabled = false;
}
else if (changedField == &m_showTitleInPlot ||
changedField == &m_showTrackLegends ||
changedField == &m_trackLegendsHorizontal)
{
updateTracks();
if (m_viewer) m_viewer->updateChildrenLayout();
}
else if (changedField == &m_isAutoScaleDepthEnabled)
{
updateDepthZoom();
@@ -121,8 +132,7 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
{
updateMdiWindowTitle();
}
if ( changedField == &m_depthType )
else if ( changedField == &m_depthType )
{
RimWellAllocationPlot* wellAllocPlot;
firstAncestorOrThisOfType(wellAllocPlot);
@@ -134,18 +144,12 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
updateDepthZoom();
}
}
if ( changedField == &m_depthUnit)
else if ( changedField == &m_depthUnit)
{
updateTracks();
updateDepthZoom();
}
if ( changedField == &m_showTrackLegends)
{
updateTracks();
if (m_viewer) m_viewer->updateChildrenLayout();
}
RimWellRftPlot* rftPlot(nullptr);
this->firstAncestorOrThisOfType(rftPlot);
@@ -189,6 +193,11 @@ QList<caf::PdmOptionItemInfo> RimWellLogPlot::calculateValueOptions(const caf::P
options.push_back(caf::PdmOptionItemInfo(UnitAppEnum::uiText(RiaDefines::UNIT_METER), RiaDefines::UNIT_METER));
options.push_back(caf::PdmOptionItemInfo(UnitAppEnum::uiText(RiaDefines::UNIT_FEET), RiaDefines::UNIT_FEET));
}
else if (fieldNeedingOptions == &m_trackLegendsHorizontal)
{
options.push_back(caf::PdmOptionItemInfo("Vertical", false));
options.push_back(caf::PdmOptionItemInfo("Horizontal", true));
}
(*useOptionsOnly) = true;
return options;
@@ -556,23 +565,14 @@ bool RimWellLogPlot::isPltPlotChild() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogPlot::uiOrderingForVisibleDepthRange(caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Visible Depth Range");
gridGroup->add(&m_minVisibleDepth);
gridGroup->add(&m_maxVisibleDepth);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogPlot::uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering)
void RimWellLogPlot::uiOrderingForDepthAxis(caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Depth Axis");
RimWellRftPlot* rftp = rftPlot();
if (!(rftp || pltPlot()))
{
uiOrdering.add(&m_depthType);
gridGroup->add(&m_depthType);
}
RimWellAllocationPlot* wap;
@@ -580,10 +580,22 @@ void RimWellLogPlot::uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering)
if (!(wap || rftp))
{
uiOrdering.add(&m_depthUnit);
gridGroup->add(&m_depthUnit);
}
gridGroup->add(&m_minVisibleDepth);
gridGroup->add(&m_maxVisibleDepth);
}
uiOrdering.add(&m_showTrackLegends);
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogPlot::uiOrderingForPlotSettings(caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup("Title and Legends");
titleAndLegendsGroup->add(&m_showTitleInPlot);
titleAndLegendsGroup->add(&m_showTrackLegends);
titleAndLegendsGroup->add(&m_trackLegendsHorizontal);
}
//--------------------------------------------------------------------------------------------------
@@ -602,8 +614,8 @@ void RimWellLogPlot::depthZoomMinMax(double* minimumDepth, double* maximumDepth)
void RimWellLogPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_userName);
uiOrderingForPlot(uiOrdering);
uiOrderingForVisibleDepthRange(uiOrdering);
uiOrderingForDepthAxis(uiOrdering);
uiOrderingForPlotSettings(uiOrdering);
uiOrdering.skipRemainingFields(true);
}
@@ -615,8 +627,8 @@ void RimWellLogPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
void RimWellLogPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
updateTracks();
updatePlotTitle();
updateTracks();
}
//--------------------------------------------------------------------------------------------------
@@ -834,10 +846,18 @@ QString RimWellLogPlot::depthPlotTitle() const
return depthTitle;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogPlot::isPlotTitleVisible() const
{
return m_showTitleInPlot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogPlot::isTrackLegendsVisible() const
bool RimWellLogPlot::areTrackLegendsVisible() const
{
return m_showTrackLegends();
}
@@ -850,6 +870,14 @@ void RimWellLogPlot::setTrackLegendsVisible(bool doShow)
m_showTrackLegends = doShow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogPlot::areTrackLegendsHorizontal() const
{
return m_trackLegendsHorizontal;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -903,3 +931,14 @@ void RimWellLogPlot::updateDisabledDepthTypes()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogPlot::updatePlotTitle()
{
if (m_viewer)
{
m_viewer->setPlotTitle(this->windowTitle());
}
}

View File

@@ -70,8 +70,10 @@ public:
QString depthPlotTitle() const;
bool isTrackLegendsVisible() const;
bool isPlotTitleVisible() const;
bool areTrackLegendsVisible() const;
void setTrackLegendsVisible(bool doShow);
bool areTrackLegendsHorizontal() const;
void addTrack(RimWellLogTrack* track);
void insertTrack(RimWellLogTrack* track, size_t index);
@@ -109,8 +111,8 @@ public:
RimWellPltPlot* pltPlot() const;
bool isPltPlotChild() const;
void uiOrderingForVisibleDepthRange(caf::PdmUiOrdering& uiOrdering);
void uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering);
void uiOrderingForDepthAxis(caf::PdmUiOrdering& uiOrdering);
void uiOrderingForPlotSettings(caf::PdmUiOrdering& uiOrdering);
protected:
@@ -131,7 +133,7 @@ private:
void detachAllCurves();
void updateDisabledDepthTypes();
void updatePlotTitle();
public: // Needed by RiuWellAllocation Plot
// RimViewWindow overrides
@@ -150,7 +152,9 @@ private:
caf::PdmField<double> m_minVisibleDepth;
caf::PdmField<double> m_maxVisibleDepth;
caf::PdmField<bool> m_isAutoScaleDepthEnabled;
caf::PdmField<bool> m_showTitleInPlot;
caf::PdmField<bool> m_showTrackLegends;
caf::PdmField<bool> m_trackLegendsHorizontal;
double m_minAvailableDepth;
double m_maxAvailableDepth;

View File

@@ -104,6 +104,17 @@ namespace caf
addItem(RigWellPathFormations::LEVEL10, "LEVEL10", "Formation 10");
setDefault(RigWellPathFormations::ALL);
}
template<>
void AppEnum< RimWellLogTrack::WidthScaleFactor >::setUp()
{
addItem(RimWellLogTrack::EXTRA_NARROW_TRACK, "EXTRA_NARROW_TRACK", "Extra Narrow");
addItem(RimWellLogTrack::NARROW_TRACK, "NARROW_TRACK", "Narrow");
addItem(RimWellLogTrack::NORMAL_TRACK, "NORMAL_TRACK", "Normal");
addItem(RimWellLogTrack::WIDE_TRACK, "WIDE_TRACK", "Wide");
addItem(RimWellLogTrack::EXTRA_WIDE_TRACK, "EXTRA_WIDE_TRACK", "Extra wide");
setDefault(RimWellLogTrack::NORMAL_TRACK);
}
}
@@ -155,6 +166,8 @@ RimWellLogTrack::RimWellLogTrack()
CAF_PDM_InitField(&m_showformationFluids, "ShowFormationFluids", false, "Show Fluids", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_widthScaleFactor, "Width", "Track Width", "", "Set width of track. ", "");
m_formationsForCaseWithSimWellOnly = false;
}
@@ -221,19 +234,12 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
m_wellLogTrackPlotWidget->setVisible(m_show());
}
RimWellLogPlot* wellLogPlot;
this->firstAncestorOrThisOfType(wellLogPlot);
if (wellLogPlot)
{
wellLogPlot->calculateAvailableDepthRange();
wellLogPlot->updateDepthZoom();
RiuWellLogPlot* wellLogPlotViewer = dynamic_cast<RiuWellLogPlot*>(wellLogPlot->viewWidget());
if (wellLogPlotViewer)
{
wellLogPlotViewer->updateChildrenLayout();
}
}
updateParentPlotLayout();
}
else if (changedField == &m_widthScaleFactor)
{
updateParentPlotLayout();
}
else if (changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax)
{
@@ -241,6 +247,7 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
m_wellLogTrackPlotWidget->replot();
m_isAutoScaleXEnabled = false;
updateEditors();
updateParentPlotLayout();
}
else if (changedField == &m_isAutoScaleXEnabled)
{
@@ -357,6 +364,23 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateParentPlotLayout()
{
RimWellLogPlot* wellLogPlot;
this->firstAncestorOrThisOfType(wellLogPlot);
if (wellLogPlot)
{
RiuWellLogPlot* wellLogPlotViewer = dynamic_cast<RiuWellLogPlot*>(wellLogPlot->viewWidget());
if (wellLogPlotViewer)
{
wellLogPlotViewer->updateChildrenLayout();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -627,6 +651,33 @@ void RimWellLogTrack::setXAxisTitle(const QString& text)
m_xAxisTitle = text;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::depthPlotTitle() const
{
RimWellLogPlot* parent;
this->firstAncestorOrThisOfTypeAsserted(parent);
return parent->depthPlotTitle();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogTrack::widthScaleFactor() const
{
return static_cast<int>(m_widthScaleFactor());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setWidthScaleFactor(WidthScaleFactor scaleFactor)
{
m_widthScaleFactor = scaleFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -735,6 +786,8 @@ void RimWellLogTrack::calculateXZoomRangeAndUpdateQwt()
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::applyXZoomFromVisibleRange()
{
if (!m_wellLogTrackPlotWidget) return;
m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax);
m_wellLogTrackPlotWidget->replot();
}
@@ -851,7 +904,6 @@ RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve(const QwtPlotCurve* c
void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_userName);
caf::PdmUiGroup* formationGroup = uiOrdering.addNewGroup("Zonation/Formation Names");
formationGroup->add(&m_showFormations);
@@ -901,6 +953,9 @@ void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
uiOrderingForVisibleXRange(uiOrdering);
caf::PdmUiGroup* trackSettingsGroup = uiOrdering.addNewGroup("Track Settings");
trackSettingsGroup->add(&m_widthScaleFactor);
uiOrdering.skipRemainingFields(true);
}

View File

@@ -70,6 +70,7 @@ public:
enum TrajectoryType { WELL_PATH, SIMULATION_WELL };
enum FormationSource { CASE, WELL_PICK_FILTER };
enum WidthScaleFactor { EXTRA_NARROW_TRACK = 2, NARROW_TRACK = 3, NORMAL_TRACK = 4, WIDE_TRACK = 6, EXTRA_WIDE_TRACK = 8};
void setDescription(const QString& description);
bool isVisible();
@@ -78,9 +79,12 @@ public:
void takeOutCurve(RimWellLogCurve* curve);
void deleteAllCurves();
size_t curveIndex(RimWellLogCurve* curve);
size_t curveCount() { return curves.size(); }
void setXAxisTitle(const QString& text);
size_t curveIndex(RimWellLogCurve* curve);
size_t curveCount() { return curves.size(); }
void setXAxisTitle(const QString& text);
QString depthPlotTitle() const;
int widthScaleFactor() const;
void setWidthScaleFactor(WidthScaleFactor scaleFactor);
void setFormationWellPath(RimWellPath* wellPath);
void setFormationSimWellName(const QString& simWellName);
@@ -127,6 +131,7 @@ public:
private:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
void updateParentPlotLayout();
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
virtual caf::PdmFieldHandle* objectToggleField() override;
@@ -179,7 +184,7 @@ private:
caf::PdmField<int> m_formationBranchIndex;
caf::PdmField<caf::AppEnum<RigWellPathFormations::FormationLevel>> m_formationLevel;
caf::PdmField<bool> m_showformationFluids;
caf::PdmField<caf::AppEnum<WidthScaleFactor>> m_widthScaleFactor;
caf::PdmField<bool> m_formationBranchDetection;
bool m_formationsForCaseWithSimWellOnly;

View File

@@ -36,6 +36,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.h
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.h
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.h
)
set (SOURCE_GROUP_SOURCE_FILES
@@ -75,6 +77,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -86,7 +86,7 @@ void RifCalculatedSummaryCurveReader::buildMetaData()
for (RimSummaryCalculation* calc : m_calculationCollection->calculations())
{
m_allResultAddresses.push_back(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString()));
m_allResultAddresses.insert(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString()));
}
}

View File

@@ -0,0 +1,231 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimDerivedEnsembleCase.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RifDerivedEnsembleReader.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimSummaryPlotCollection.h"
#include "RimSummaryCaseCollection.h"
#include "cvfAssert.h"
#include <QFileInfo>
CAF_PDM_ABSTRACT_SOURCE_INIT(RimDerivedEnsembleCase, "RimDerivedEnsembleCase");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t> RimDerivedEnsembleCase::EMPTY_TIME_STEPS_VECTOR;
const std::vector<double> RimDerivedEnsembleCase::EMPTY_VALUES_VECTOR;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCase::RimDerivedEnsembleCase() : m_summaryCase1(nullptr), m_summaryCase2(nullptr)
{
CAF_PDM_InitObject("Summary Case",":/SummaryCase16x16.png","","");
CAF_PDM_InitFieldNoDefault(&m_summaryCase1, "SummaryCase1", "SummaryCase1", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_summaryCase2, "SummaryCase2", "SummaryCase2", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCase::~RimDerivedEnsembleCase()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::setInUse(bool inUse)
{
m_inUse = inUse;
if (!m_inUse)
{
m_summaryCase1 = nullptr;
m_summaryCase2 = nullptr;
m_data.clear();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCase::isInUse() const
{
return m_inUse;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2)
{
if (!sumCase1 || !sumCase2) return;
m_summaryCase1 = sumCase1;
m_summaryCase2 = sumCase2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCase::needsCalculation(const RifEclipseSummaryAddress& address) const
{
return m_data.count(address) == 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RimDerivedEnsembleCase::timeSteps(const RifEclipseSummaryAddress& address) const
{
if (m_data.count(address) == 0) return EMPTY_TIME_STEPS_VECTOR;
return m_data.at(address).first;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RimDerivedEnsembleCase::values(const RifEclipseSummaryAddress& address) const
{
if (m_data.count(address) == 0) return EMPTY_VALUES_VECTOR;
return m_data.at(address).second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address)
{
clearData(address);
RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr;
RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr;
if (!reader1 || !reader2 || !parentEnsemble()) return;
RiaTimeHistoryCurveMerger merger;
std::vector<double> values1;
std::vector<double> values2;
DerivedEnsembleOperator op = parentEnsemble()->op();
reader1->values(address, &values1);
reader2->values(address, &values2);
merger.addCurveData(values1, reader1->timeSteps(address));
merger.addCurveData(values2, reader2->timeSteps(address));
merger.computeInterpolatedValues();
std::vector<double>& allValues1 = merger.interpolatedCurveValuesForAllTimeSteps(0);
std::vector<double>& allValues2 = merger.interpolatedCurveValuesForAllTimeSteps(1);
size_t sampleCount = merger.allTimeSteps().size();
std::vector<double> calculatedValues;
calculatedValues.reserve(sampleCount);
for (size_t i = 0; i < sampleCount; i++)
{
if (op == DERIVED_ENSEMBLE_SUB)
{
calculatedValues.push_back(allValues1[i] - allValues2[i]);
}
else if (op == DERIVED_ENSEMBLE_ADD)
{
calculatedValues.push_back(allValues1[i] + allValues2[i]);
}
}
auto& dataItem = m_data[address];
dataItem.first = merger.allTimeSteps();
dataItem.second = calculatedValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimDerivedEnsembleCase::caseName()
{
auto case1Name = m_summaryCase1->caseName();
auto case2Name = m_summaryCase2->caseName();
if (case1Name == case2Name) return case1Name;
else return QString("%1/%2").arg(case1Name).arg(case2Name);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::createSummaryReaderInterface()
{
m_reader.reset(new RifDerivedEnsembleReader(this));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryReaderInterface* RimDerivedEnsembleCase::summaryReader()
{
return m_reader.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath)
{
// NOP
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection * RimDerivedEnsembleCase::parentEnsemble() const
{
RimDerivedEnsembleCaseCollection* ensemble;
firstAncestorOrThisOfType(ensemble);
return ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<time_t>, std::vector<double>> RimDerivedEnsembleCase::lookupCachedData(const RifEclipseSummaryAddress& address)
{
auto itr = m_data.find(address);
if (itr == m_data.end()) return std::make_pair(std::vector<time_t>(), std::vector<double>());
return itr->second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::clearData(const RifEclipseSummaryAddress& address)
{
m_data.erase(address);
}

View File

@@ -0,0 +1,83 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016 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 "RimSummaryCase.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include <memory>
class RifEclipseSummaryAddress;
class RifSummaryReaderInterface;
class RifDerivedEnsembleReader;
class RimDerivedEnsembleCaseCollection;
//==================================================================================================
///
//==================================================================================================
enum DerivedEnsembleOperator
{
DERIVED_ENSEMBLE_SUB,
DERIVED_ENSEMBLE_ADD
};
//==================================================================================================
//
//==================================================================================================
class RimDerivedEnsembleCase : public RimSummaryCase
{
CAF_PDM_HEADER_INIT;
static const std::vector<time_t> EMPTY_TIME_STEPS_VECTOR;
static const std::vector<double> EMPTY_VALUES_VECTOR;
public:
RimDerivedEnsembleCase();
~RimDerivedEnsembleCase();
void setInUse(bool inUse);
bool isInUse() const;
void setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2);
bool needsCalculation(const RifEclipseSummaryAddress& address) const;
const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& address) const;
const std::vector<double>& values(const RifEclipseSummaryAddress& address) const;
void calculate(const RifEclipseSummaryAddress& address);
virtual QString caseName() override;
virtual void createSummaryReaderInterface() override;
virtual RifSummaryReaderInterface* summaryReader() override;
virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) override;
RimDerivedEnsembleCaseCollection* parentEnsemble() const;
private:
std::pair<std::vector<time_t>, std::vector<double>> lookupCachedData(const RifEclipseSummaryAddress& address);
void clearData(const RifEclipseSummaryAddress& address);
std::unique_ptr<RifDerivedEnsembleReader> m_reader;
bool m_inUse;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase1;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase2;
std::map<RifEclipseSummaryAddress, std::pair<std::vector<time_t>, std::vector<double>>> m_data;
};

View File

@@ -0,0 +1,440 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaApplication.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimDerivedEnsembleCase.h"
#include "RimProject.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h"
#include "RifSummaryReaderInterface.h"
#include <cafPdmUiPushButtonEditor.h>
#include <cmath>
namespace caf
{
template<>
void caf::AppEnum<DerivedEnsembleOperator>::setUp()
{
addItem(DERIVED_ENSEMBLE_SUB, "Sub", "-");
addItem(DERIVED_ENSEMBLE_ADD, "Add", "+");
setDefault(DERIVED_ENSEMBLE_SUB);
}
}
CAF_PDM_SOURCE_INIT(RimDerivedEnsembleCaseCollection, "RimDerivedEnsembleCaseCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection::RimDerivedEnsembleCaseCollection()
{
CAF_PDM_InitObject("Derived Ensemble", ":/SummaryEnsemble16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_ensemble1, "Ensemble1", "Ensemble 1", "", "", "");
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
m_ensemble1.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_ensemble2, "Ensemble2", "Ensemble 2", "", "", "");
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
m_ensemble2.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_operator, "Operator", "Operator", "", "", "");
CAF_PDM_InitField(&m_swapEnsemblesButton, "SwapEnsembles", false, "SwapEnsembles", "", "", "");
m_swapEnsemblesButton.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName());
m_swapEnsemblesButton.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_swapEnsemblesButton.xmlCapability()->disableIO();
CAF_PDM_InitField(&m_caseCount, "CaseCount", 0, "Number of Cases", "", "", "");
m_caseCount.uiCapability()->setUiReadOnly(true);
// Do not show child cases
uiCapability()->setUiTreeChildrenHidden(true);
// Do not store child cases to project file
m_cases.xmlCapability()->disableIO();
setNameAsReadOnly();
setName("Derived Ensemble");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection::~RimDerivedEnsembleCaseCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setEnsemble1(RimSummaryCaseCollection* ensemble)
{
m_ensemble1 = ensemble;
updateAutoName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setEnsemble2(RimSummaryCaseCollection* ensemble)
{
m_ensemble2 = ensemble;
updateAutoName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCase*> RimDerivedEnsembleCaseCollection::allSummaryCases() const
{
std::vector<RimSummaryCase*> cases;
for (auto sumCase : allDerivedCases(true)) cases.push_back(sumCase);
return cases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimDerivedEnsembleCaseCollection::calculateUnionOfSummaryAddresses() const
{
std::set<RifEclipseSummaryAddress> addresses;
if (!m_ensemble1 || !m_ensemble2) return addresses;
addresses = m_ensemble1->calculateUnionOfSummaryAddresses();
auto addrs2 = m_ensemble2->calculateUnionOfSummaryAddresses();
addresses.insert(addrs2.begin(), addrs2.end());
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::updateDerivedEnsembleCases()
{
if (!m_ensemble1 || !m_ensemble2) return;
setAllCasesNotInUse();
const auto cases1 = m_ensemble1->allSummaryCases();
const auto cases2 = m_ensemble2->allSummaryCases();
for (auto& sumCase1 : cases1)
{
auto crp = sumCase1->caseRealizationParameters();
if (!crp) continue;
const auto& sumCase2 = findCaseByParametersHash(cases2, crp->parametersHash());
if (!sumCase2) continue;
auto derivedCase = firstCaseNotInUse();
derivedCase->createSummaryReaderInterface();
derivedCase->setSummaryCases(sumCase1, sumCase2);
derivedCase->setCaseRealizationParameters(crp);
derivedCase->setInUse(true);
}
// If other derived ensembles are referring to this ensemble, update their cases as well
for (auto referring : findReferringEnsembles())
{
referring->updateDerivedEnsembleCases();
}
deleteCasesNoInUse();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCaseCollection::hasCaseReference(const RimSummaryCase* sumCase) const
{
for (auto currCase : m_ensemble1->allSummaryCases())
{
if (currCase == sumCase) return true;
}
for (auto currCase : m_ensemble2->allSummaryCases())
{
if (currCase == sumCase) return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::onLoadDataAndUpdate()
{
updateDerivedEnsembleCases();
updateReferringCurveSets();
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimDerivedEnsembleCaseCollection::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_ensemble1 || fieldNeedingOptions == &m_ensemble2)
{
for (auto ensemble : allEnsembles())
{
if(ensemble != this) options.push_back(caf::PdmOptionItemInfo(ensemble->name(), ensemble));
}
}
else if (fieldNeedingOptions == &m_caseCount)
{
m_caseCount = (int)m_cases.size();
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimSummaryCaseCollection::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(&m_caseCount);
uiOrdering.add(&m_ensemble1);
uiOrdering.add(&m_operator);
uiOrdering.add(&m_ensemble2);
uiOrdering.add(&m_swapEnsemblesButton);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
bool doUpdate = false;
bool doUpdateCases = false;
bool doClearAllData = false;
if (changedField == &m_ensemble1 || changedField == &m_ensemble2)
{
doUpdate = true;
doUpdateCases = true;
}
else if (changedField == &m_operator)
{
doUpdate = true;
doUpdateCases = true;
}
else if (changedField == &m_swapEnsemblesButton)
{
m_swapEnsemblesButton = false;
auto temp = m_ensemble1();
m_ensemble1 = m_ensemble2();
m_ensemble2 = temp;
doUpdate = true;
doUpdateCases = true;
}
if (doUpdate)
{
updateAutoName();
//if (doClearAllData) clearAllData();
if (doUpdateCases)
{
updateDerivedEnsembleCases();
updateConnectedEditors();
}
updateReferringCurveSets();
// If other derived ensembles are referring to this ensemble, update their cases as well
for (auto refering : findReferringEnsembles())
{
refering->updateReferringCurveSets();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (field == &m_swapEnsemblesButton)
{
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>(attribute);
if (attrib)
{
attrib->m_buttonText = "Swap Ensembles";
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setAllCasesNotInUse()
{
for (auto derCase : allDerivedCases(true)) derCase->setInUse(false);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::deleteCasesNoInUse()
{
std::vector<RimDerivedEnsembleCase*> inactiveCases;
auto allCases = allDerivedCases(false);
std::copy_if(allCases.begin(), allCases.end(), std::back_inserter(inactiveCases), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
for (auto derCase : inactiveCases)
{
removeCase(derCase);
delete derCase;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCase* RimDerivedEnsembleCaseCollection::firstCaseNotInUse()
{
auto allCases = allDerivedCases(false);
auto itr = std::find_if(allCases.begin(), allCases.end(), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
if (itr != allCases.end())
{
return *itr;
}
// If no active case was found, add a new case to the collection
auto newCase = new RimDerivedEnsembleCase();
m_cases.push_back(newCase);
return newCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimDerivedEnsembleCase*> RimDerivedEnsembleCaseCollection::allDerivedCases(bool activeOnly) const
{
std::vector<RimDerivedEnsembleCase*> activeCases;
for (auto sumCase : RimSummaryCaseCollection::allSummaryCases())
{
auto derivedCase = dynamic_cast<RimDerivedEnsembleCase*>(sumCase);
if (derivedCase && (!activeOnly || derivedCase->isInUse()))
{
activeCases.push_back(derivedCase);
}
}
return activeCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::updateAutoName()
{
QString op = caf::AppEnum<DerivedEnsembleOperator>::uiText(m_operator());
auto derivedEnsemble1 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble1());
auto derivedEnsemble2 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble2());
bool isDerived1 = derivedEnsemble1 != nullptr;
bool isDerived2 = derivedEnsemble2 != nullptr;
QString name =
(isDerived1 ? "(" : "") +
(m_ensemble1 ? m_ensemble1->name() : "") +
(isDerived1 ? ")" : "") +
" " + op + " " +
(isDerived2 ? "(" : "") +
(m_ensemble2 ? m_ensemble2->name() : "") +
(isDerived2 ? ")" : "");
setName(name);
// If other derived ensembles are referring to this ensemble, update theirs name as well
for (auto refering : findReferringEnsembles())
{
refering->updateAutoName();
refering->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimDerivedEnsembleCaseCollection::findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const
{
for (auto sumCase : cases)
{
auto ensembleParameters = sumCase->caseRealizationParameters();
if (ensembleParameters && ensembleParameters->parametersHash() == hash) return sumCase;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimDerivedEnsembleCaseCollection*> RimDerivedEnsembleCaseCollection::findReferringEnsembles() const
{
std::vector<RimDerivedEnsembleCaseCollection*> referringEnsembles;
RimSummaryCaseMainCollection* mainColl;
firstAncestorOrThisOfType(mainColl);
if (mainColl)
{
for (auto group : mainColl->summaryCaseCollections())
{
auto derivedEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
if (derivedEnsemble)
{
if (derivedEnsemble->m_ensemble1() == this || derivedEnsemble->m_ensemble2() == this)
{
referringEnsembles.push_back(derivedEnsemble);
}
}
}
}
return referringEnsembles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCaseCollection*> RimDerivedEnsembleCaseCollection::allEnsembles() const
{
std::vector<RimSummaryCaseCollection*> ensembles;
auto project = RiaApplication::instance()->project();
for (auto group : project->summaryGroups())
{
if (group->isEnsemble()) ensembles.push_back(group);
}
return ensembles;
}

View File

@@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RifEclipseSummaryAddress.h"
#include "RimDerivedEnsembleCase.h"
#include "RimSummaryCaseCollection.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
#include "cafPdmObject.h"
#include "cafPdmProxyValueField.h"
#include <vector>
class RimSummaryCase;
//==================================================================================================
///
//==================================================================================================
class RimDerivedEnsembleCaseCollection : public RimSummaryCaseCollection
{
CAF_PDM_HEADER_INIT;
public:
RimDerivedEnsembleCaseCollection();
virtual ~RimDerivedEnsembleCaseCollection();
RimSummaryCaseCollection* ensemble1() const { return m_ensemble1; }
RimSummaryCaseCollection* ensemble2() const { return m_ensemble2; }
DerivedEnsembleOperator op() const { return m_operator(); }
void setEnsemble1(RimSummaryCaseCollection* ensemble);
void setEnsemble2(RimSummaryCaseCollection* ensemble);
virtual std::vector<RimSummaryCase*> allSummaryCases() const override;
virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const override;
void updateDerivedEnsembleCases();
bool hasCaseReference(const RimSummaryCase* sumCase) const;
virtual void onLoadDataAndUpdate() override;
private:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName,
caf::PdmUiEditorAttribute* attribute) override;
void setAllCasesNotInUse();
void deleteCasesNoInUse();
RimDerivedEnsembleCase* firstCaseNotInUse();
std::vector<RimDerivedEnsembleCase*> allDerivedCases(bool activeOnly) const;
void updateAutoName();
RimSummaryCase* findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const;
std::vector<RimDerivedEnsembleCaseCollection*> findReferringEnsembles() const;
private:
std::vector<RimSummaryCaseCollection*> allEnsembles() const;
private:
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble1;
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble2;
caf::PdmField<caf::AppEnum<DerivedEnsembleOperator>> m_operator;
caf::PdmField<bool> m_swapEnsemblesButton;
caf::PdmField<int> m_caseCount;
};

View File

@@ -25,6 +25,7 @@
class EnsembleParameter;
class RimEnsembleCurveSet;
class RimSummaryCase;
class RimSummaryPlot;
class RimEnsembleCurveFilterCollection;
//==================================================================================================

View File

@@ -148,26 +148,42 @@ void RimEnsembleCurveFilterCollection::defineUiOrdering(QString uiConfigName, ca
auto selEnsembleParam = filter->selectedEnsembleParameter();
if (selEnsembleParam.isNumeric())
{
if (!filter->isActive()) groupTitle = "DISABLED - ";
groupTitle += QString("%1. Min: %2, Max: %3")
.arg(filter->ensembleParameterName())
.arg(QString::number(filter->minValue()))
.arg(QString::number(filter->maxValue()));
groupTitle = filter->ensembleParameterName();
if (!filter->isActive())
{
groupTitle += " - [Disabled]";
}
else
{
groupTitle += QString(" [%2 .. %3]")
.arg(QString::number(filter->minValue()))
.arg(QString::number(filter->maxValue()));
}
}
else if (selEnsembleParam.isText())
{
if (!filter->isActive()) groupTitle = "DISABLED - ";
groupTitle += QString("%1. Categories: ")
.arg(filter->ensembleParameterName());
groupTitle = filter->ensembleParameterName();
bool first = true;
for (auto cat : filter->categories())
if (!filter->isActive())
{
if (!first) groupTitle += ", ";
groupTitle += cat;
first = false;
groupTitle += " - [Disabled]";
}
else
{
groupTitle += " { ";
bool first = true;
for (auto cat : filter->categories())
{
if (!first) groupTitle += ", ";
groupTitle += cat;
first = false;
}
groupTitle += " }";
}
}
caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroupWithKeyword(groupTitle, QString("EnsembleFilter_") + filter->filterId());
filter->defineUiOrdering(uiConfigName, *filterGroup);
}

View File

@@ -20,6 +20,7 @@
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RiaStatisticsTools.h"
#include "SummaryPlotCommands/RicSummaryCurveCreator.h"
@@ -29,6 +30,7 @@
#include "RigStatisticsMath.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveFilter.h"
#include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSetCollection.h"
@@ -66,6 +68,12 @@
//--------------------------------------------------------------------------------------------------
#define DOUBLE_INF std::numeric_limits<double>::infinity()
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
RimPlotCurve::PointSymbolEnum statisticsCurveSymbolFromAddress(const RifEclipseSummaryAddress& address);
int statisticsCurveSymbolSize(RimPlotCurve::PointSymbolEnum symbol);
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -168,6 +176,7 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
m_ensembleStatCase->createSummaryReaderInterface();
m_disableStatisticCurves = false;
m_isCurveSetFiltered = false;
}
//--------------------------------------------------------------------------------------------------
@@ -735,7 +744,7 @@ void RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses(QList<caf::PdmOpt
for (RimSummaryCase* summaryCase : summaryCaseGroup->allSummaryCases())
{
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
const std::vector<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::vector<RifEclipseSummaryAddress>();
const std::set<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::set<RifEclipseSummaryAddress>();
for (auto& addr : addrs)
{
@@ -930,6 +939,8 @@ void RimEnsembleCurveSet::updateEnsembleCurves()
m_yValuesSummaryFilter->updateFromAddress(addr->address());
if (plot->qwtPlot()) m_qwtPlotCurveForLegendText->attach(plot->qwtPlot());
m_isCurveSetFiltered = filteredCases.size() < group->allSummaryCases().size();
}
RimSummaryPlot* plot;
@@ -939,6 +950,7 @@ void RimEnsembleCurveSet::updateEnsembleCurves()
plot->qwtPlot()->updateLegend();
plot->qwtPlot()->replot();
plot->updateAxes();
plot->updatePlotInfoLabel();
}
}
updateCurveColors();
@@ -987,9 +999,17 @@ void RimEnsembleCurveSet::updateStatisticsCurves(bool calculate = true)
curve->setParentQwtPlotNoReplot(plot->qwtPlot());
m_curves.push_back(curve);
curve->setColor(m_statistics->color());
curve->setSymbol(RimPlotCurve::SYMBOL_ELLIPSE);
curve->setSymbolSkipDinstance(50);
curve->setSymbolLabel(QString::fromStdString(address.ensembleStatisticsQuantityName()));
curve->setColor(m_statistics->color());
auto symbol = statisticsCurveSymbolFromAddress(address);
curve->setSymbol(symbol);
curve->setSymbolSize(statisticsCurveSymbolSize(symbol));
curve->setSymbolSkipDistance(150);
if (m_statistics->showCurveLabels())
{
curve->setSymbolLabel(RiaStatisticsTools::replacePercentileByPValueText(
QString::fromStdString(address.ensembleStatisticsQuantityName())));
}
curve->setLineStyle(RimPlotCurve::STYLE_SOLID);
curve->setSummaryCaseY(m_ensembleStatCase.get());
curve->setSummaryAddressY(address);
@@ -1093,6 +1113,14 @@ void RimEnsembleCurveSet::disableStatisticCurves()
m_disableStatisticCurves = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleCurveSet::isFiltered() const
{
return m_isCurveSetFiltered;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -1212,3 +1240,27 @@ void RimEnsembleCurveSet::updateLegendMappingMode()
break;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPlotCurve::PointSymbolEnum statisticsCurveSymbolFromAddress(const RifEclipseSummaryAddress& address)
{
auto qName = QString::fromStdString(address.quantityName());
if (qName.contains(ENSEMBLE_STAT_P10_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_TRIANGLE;
if (qName.contains(ENSEMBLE_STAT_P90_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_DOWN_TRIANGLE;
if (qName.contains(ENSEMBLE_STAT_P50_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_DIAMOND;
return RimPlotCurve::SYMBOL_ELLIPSE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int statisticsCurveSymbolSize(RimPlotCurve::PointSymbolEnum symbol)
{
if (symbol == RimPlotCurve::SYMBOL_DIAMOND) return 8;
if (symbol == RimPlotCurve::SYMBOL_TRIANGLE) return 7;
if (symbol == RimPlotCurve::SYMBOL_DOWN_TRIANGLE) return 7;
return 6;
}

View File

@@ -108,6 +108,7 @@ public:
std::vector<RimSummaryCase*> filterEnsembleCases(const RimSummaryCaseCollection* ensemble);
void disableStatisticCurves();
bool isFiltered() const;
bool hasP10Data() const;
bool hasP50Data() const;
@@ -174,5 +175,6 @@ private:
std::unique_ptr<RimEnsembleStatisticsCase> m_ensembleStatCase;
bool m_disableStatisticCurves;
bool m_isCurveSetFiltered;
};

View File

@@ -38,10 +38,11 @@ RimEnsembleStatistics::RimEnsembleStatistics()
CAF_PDM_InitObject("Ensemble Curve Filter", ":/EnsembleCurveSet16x16.png", "", "");
CAF_PDM_InitField(&m_active, "Active", true, "Show statistics curves", "", "", "");
CAF_PDM_InitField(&m_showP10Curve, "ShowP10Curve", true, "P10", "", "", "");
CAF_PDM_InitField(&m_showP10Curve, "ShowP10Curve", true, "P90", "", "", ""); // Yes, P90
CAF_PDM_InitField(&m_showP50Curve, "ShowP50Curve", true, "P50", "", "", "");
CAF_PDM_InitField(&m_showP90Curve, "ShowP90Curve", true, "P90", "", "", "");
CAF_PDM_InitField(&m_showP90Curve, "ShowP90Curve", true, "P10", "", "", ""); // Yes, P10
CAF_PDM_InitField(&m_showMeanCurve, "ShowMeanCurve", true, "Mean", "", "", "");
CAF_PDM_InitField(&m_showCurveLabels, "ShowCurveLabels", true, "Show Curve Labels", "", "", "");
CAF_PDM_InitField(&m_color, "Color", cvf::Color3f(cvf::Color3::BLACK), "Color", "", "", "");
}
@@ -106,6 +107,7 @@ void RimEnsembleStatistics::fieldChangedByUi(const caf::PdmFieldHandle* changedF
changedField == &m_showP50Curve ||
changedField == &m_showP90Curve ||
changedField == &m_showMeanCurve ||
changedField == &m_showCurveLabels ||
changedField == &m_color)
{
auto curveSet = parentCurveSet();
@@ -125,20 +127,25 @@ void RimEnsembleStatistics::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd
auto curveSet = parentCurveSet();
uiOrdering.add(&m_active);
uiOrdering.add(&m_showCurveLabels);
uiOrdering.add(&m_color);
auto group = uiOrdering.addNewGroup("Curves");
group->add(&m_showP10Curve);
group->add(&m_showP50Curve);
group->add(&m_showP90Curve);
group->add(&m_showP50Curve);
group->add(&m_showMeanCurve);
group->add(&m_color);
group->add(&m_showP10Curve);
disableP10Curve(!m_active || !curveSet->hasP10Data());
disableP50Curve(!m_active || !curveSet->hasP50Data());
disableP90Curve(!m_active || !curveSet->hasP90Data());
disableMeanCurve(!m_active);
m_showCurveLabels.uiCapability()->setUiReadOnly(!m_active);
m_color.uiCapability()->setUiReadOnly(!m_active);
m_showP10Curve.uiCapability()->setUiName(curveSet->hasP10Data() ? "P90" : "P90 (Needs > 8 curves)");
m_showP90Curve.uiCapability()->setUiName(curveSet->hasP90Data() ? "P10" : "P10 (Needs > 8 curves)");
uiOrdering.skipRemainingFields(true);
}

View File

@@ -45,6 +45,7 @@ public:
bool showP50Curve() const { return m_showP50Curve; }
bool showP90Curve() const { return m_showP90Curve; }
bool showMeanCurve() const { return m_showMeanCurve; }
bool showCurveLabels() const { return m_showCurveLabels; }
cvf::Color3f color() const { return m_color; }
void disableP10Curve(bool disable);
@@ -64,6 +65,7 @@ private:
caf::PdmField<bool> m_showP50Curve;
caf::PdmField<bool> m_showP90Curve;
caf::PdmField<bool> m_showMeanCurve;
caf::PdmField<bool> m_showCurveLabels;
caf::PdmField<cvf::Color3f> m_color;

View File

@@ -18,6 +18,7 @@
#include "RimSummaryCaseCollection.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveSet.h"
#include "RimGridSummaryCase.h"
#include "RimProject.h"
@@ -68,13 +69,34 @@ void RimSummaryCaseCollection::removeCase(RimSummaryCase* summaryCase)
updateReferringCurveSets();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::deleteAllCases()
{
m_cases.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase)
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase, bool updateCurveSets)
{
m_cases.push_back(summaryCase);
updateReferringCurveSets();
// Update derived ensemble cases (if any)
std::vector<caf::PdmObjectHandle*> referringObjects;
objectsWithReferringPtrFields(referringObjects);
for (auto refObj : referringObjects)
{
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(refObj);
if (!derEnsemble) continue;
derEnsemble->updateDerivedEnsembleCases();
if (updateCurveSets) derEnsemble->updateReferringCurveSets();
}
if(updateCurveSets) updateReferringCurveSets();
}
//--------------------------------------------------------------------------------------------------
@@ -133,11 +155,9 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::calculateUnionOfSum
if ( !reader ) continue;
const std::vector<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
const std::set<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
addressUnion.insert(readerAddresses.begin(), readerAddresses.end());
}
return addressUnion;
}
@@ -234,6 +254,14 @@ EnsembleParameter RimSummaryCaseCollection::ensembleParameter(const QString& par
return eParam;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::loadDataAndUpdate()
{
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -242,10 +270,18 @@ caf::PdmFieldHandle* RimSummaryCaseCollection::userDescriptionField()
return &m_name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::onLoadDataAndUpdate()
{
// NOP
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::updateReferringCurveSets() const
void RimSummaryCaseCollection::updateReferringCurveSets()
{
// Update curve set referring to this group
std::vector<PdmObjectHandle*> referringObjects;
@@ -299,3 +335,20 @@ void RimSummaryCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* chang
updateIcon();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_name);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::setNameAsReadOnly()
{
m_name.uiCapability()->setUiReadOnly(true);
}

View File

@@ -65,26 +65,35 @@ public:
virtual ~RimSummaryCaseCollection();
void removeCase(RimSummaryCase* summaryCase);
void addCase(RimSummaryCase* summaryCase);
std::vector<RimSummaryCase*> allSummaryCases() const;
void deleteAllCases();
void addCase(RimSummaryCase* summaryCase, bool updateCurveSets = true);
virtual std::vector<RimSummaryCase*> allSummaryCases() const;
void setName(const QString& name);
QString name() const;
bool isEnsemble() const;
void setAsEnsemble(bool isEnsemble);
std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const;
virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const;
EnsembleParameter ensembleParameter(const QString& paramName) const;
void loadDataAndUpdate();
private:
caf::PdmFieldHandle* userDescriptionField() override;
void updateReferringCurveSets() const;
QString nameAndItemCount() const;
void updateIcon();
virtual void initAfterRead() override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
private:
protected:
virtual void onLoadDataAndUpdate();
void updateReferringCurveSets();
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void setNameAsReadOnly();
caf::PdmChildArrayField<RimSummaryCase*> m_cases;
private:
caf::PdmField<QString> m_name;
caf::PdmProxyValueField<QString> m_nameAndItemCount;
caf::PdmField<bool> m_isEnsemble;

View File

@@ -21,6 +21,7 @@
#include "RifSummaryCaseRestartSelector.h"
#include "RifCaseRealizationParametersReader.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEclipseResultCase.h"
#include "RimFileSummaryCase.h"
#include "RimGridSummaryCase.h"
@@ -201,19 +202,43 @@ void RimSummaryCaseMainCollection::addCase(RimSummaryCase* summaryCase)
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseMainCollection::removeCase(RimSummaryCase* summaryCase)
{
std::vector<RimDerivedEnsembleCaseCollection*> derivedEnsembles;
// Build a list of derived ensembles that must be updated after delete
for (auto group : summaryCaseCollections())
{
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
if (derEnsemble)
{
if (derEnsemble->hasCaseReference(summaryCase))
{
derivedEnsembles.push_back(derEnsemble);
}
}
}
m_cases.removeChildObject(summaryCase);
for (RimSummaryCaseCollection* summaryCaseCollection : m_caseCollections)
{
summaryCaseCollection->removeCase(summaryCase);
}
// Update derived ensemble cases (if any)
for (auto derEnsemble : derivedEnsembles)
{
derEnsemble->updateDerivedEnsembleCases();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& collectionName, bool isEnsemble)
RimSummaryCaseCollection* RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
const QString& collectionName,
bool isEnsemble,
std::function<RimSummaryCaseCollection* ()> allocator)
{
RimSummaryCaseCollection* summaryCaseCollection = new RimSummaryCaseCollection();
RimSummaryCaseCollection* summaryCaseCollection = allocator();
if(!collectionName.isEmpty()) summaryCaseCollection->setName(collectionName);
summaryCaseCollection->setAsEnsemble(isEnsemble);
@@ -235,6 +260,8 @@ void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*
}
m_caseCollections.push_back(summaryCaseCollection);
return summaryCaseCollection;
}
//--------------------------------------------------------------------------------------------------
@@ -330,6 +357,14 @@ void RimSummaryCaseMainCollection::loadSummaryCaseData(std::vector<RimSummaryCas
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection* RimSummaryCaseMainCollection::defaultAllocator()
{
return new RimSummaryCaseCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -21,6 +21,7 @@
#include "cafPdmObject.h"
#include <vector>
#include <functional>
class RimGridSummaryCase;
class RimSummaryCase;
@@ -56,7 +57,10 @@ public:
void addCase(RimSummaryCase* summaryCase);
void removeCase(RimSummaryCase* summaryCase);
void addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& coolectionName, bool isEnsemble);
RimSummaryCaseCollection* addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
const QString& coolectionName,
bool isEnsemble,
std::function<RimSummaryCaseCollection* ()> allocator = defaultAllocator);
void removeCaseCollection(RimSummaryCaseCollection* caseCollection);
void loadAllSummaryCaseData();
@@ -67,6 +71,7 @@ public:
private:
static void loadSummaryCaseData(std::vector<RimSummaryCase*> summaryCases);
static RimSummaryCaseCollection* defaultAllocator();
private:
caf::PdmChildArrayField<RimSummaryCase*> m_cases;

View File

@@ -593,7 +593,7 @@ void RimSummaryCurve::appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionI
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
if (reader)
{
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
const std::set<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
for (auto& address : allAddresses)
{

View File

@@ -18,6 +18,8 @@
#include "RimSummaryCurveAutoName.h"
#include "RiaStatisticsTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RimEnsembleCurveSet.h"
@@ -73,6 +75,11 @@ QString RimSummaryCurveAutoName::curveNameY(const RifEclipseSummaryAddress& summ
{
text += summaryAddress.quantityName();
if (summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS)
{
text = RiaStatisticsTools::replacePercentileByPValueText(QString::fromStdString(text)).toStdString();
}
if (m_unit && summaryCurve && !summaryCurve->unitNameY().empty())
{
text += "[" + summaryCurve->unitNameY() + "]";

View File

@@ -208,7 +208,11 @@ QString RimSummaryPlotYAxisFormatter::autoAxisTitle() const
RifEclipseSummaryAddress sumAddress;
std::string unitText;
if (m_axisProperties->plotAxisType() == RiaDefines::PLOT_AXIS_BOTTOM)
if (rimCurve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS)
{
continue;
}
else if (m_axisProperties->plotAxisType() == RiaDefines::PLOT_AXIS_BOTTOM)
{
sumAddress = rimCurve->summaryAddressX();
unitText = rimCurve->unitNameX();

View File

@@ -52,16 +52,23 @@
#include "qwt_legend.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_renderer.h"
#include "qwt_plot_textlabel.h"
#include <QDateTime>
#include <QString>
#include <QRectF>
#include <set>
#include <limits>
CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot");
//--------------------------------------------------------------------------------------------------
/// Internal constants
//--------------------------------------------------------------------------------------------------
#define DOUBLE_INF std::numeric_limits<double>::infinity()
//--------------------------------------------------------------------------------------------------
/// Internal types
//--------------------------------------------------------------------------------------------------
@@ -79,14 +86,39 @@ struct CurveData
std::vector<double> values;
};
class CurvesData
{
public:
CurvesData() : resamplePeriod(DateTimePeriod::NONE) {}
void clear()
{
resamplePeriod = DateTimePeriod::NONE;
caseNames.clear();
timeSteps.clear();
allCurveData.clear();
}
DateTimePeriod resamplePeriod;
std::vector<QString> caseNames;
std::vector<std::vector<time_t> > timeSteps;
std::vector<std::vector<CurveData>> allCurveData;
};
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportValues);
void populateSummaryCurvesData(std::vector<RimSummaryCurve*> curves, CurvesData* curvesData);
void populateTimeHistoryCurvesData(std::vector<RimGridTimeHistoryCurve*> curves, CurvesData* curvesData);
void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesData* curvesData);
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const CurvesData& inputCurvesData,
CurvesData* resultCurvesData);
void appendToExportDataForCase(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData);
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData);
//--------------------------------------------------------------------------------------------------
///
@@ -154,6 +186,8 @@ RimSummaryPlot::RimSummaryPlot()
m_isCrossPlot = false;
m_nameHelperAllCurves.reset(new RimSummaryPlotNameHelper);
setPlotInfoLabel("Filters Active");
}
//--------------------------------------------------------------------------------------------------
@@ -275,140 +309,44 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
QString out;
RiaTimeHistoryCurveResampler resampler;
out += description();
// Summary curves
// Summary and time history (from grid) curves
{
std::vector<RimSummaryCurve*> curves;
this->descendantsIncludingThisOfType(curves);
std::vector<QString> caseNames;
std::vector<std::vector<time_t> > timeSteps;
std::vector<std::vector<CurveData>> allCurveData;
// Vector containing cases - curves
CurvesData summaryCurvesData;
populateSummaryCurvesData(curves, &summaryCurvesData);
for (RimSummaryCurve* curve : curves)
{
if (!curve->isCurveVisible()) continue;
QString curveCaseName = curve->summaryCaseY()->caseName();
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
for (size_t i = 0; i < caseNames.size(); i++)
{
if (curveCaseName == caseNames[i]) casePosInList = i;
}
CurvesData timeHistoryCurvesData;
populateTimeHistoryCurvesData(m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData);
CurveData curveData = { curve->curveName(), curve->summaryAddressY(), curve->valuesY() };
std::vector<CurvesData> exportData(2);
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
caseNames.push_back(curveCaseName);
timeSteps.push_back(curve->timeStepsY());
allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
allCurveData[casePosInList].push_back(curveData);
}
}
// Summary data for export
prepareCaseCurvesForExport(resamplingPeriod,
ResampleAlgorithm::DATA_DECIDES,
summaryCurvesData,
&exportData[0]);
for (size_t i = 0; i < timeSteps.size(); i++) //cases
{
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
// Time history data for export
prepareCaseCurvesForExport(resamplingPeriod,
ResampleAlgorithm::PERIOD_END,
timeHistoryCurvesData,
&exportData[1]);
out += "\n\n";
out += "Case: " + caseNames[i];
out += "\n";
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::DATA_DECIDES, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
}
// Time history curves (from grid)
{
std::vector<QString> caseNames;
std::vector<std::vector<time_t> > timeSteps;
std::vector<std::vector<CurveData>> allCurveData;
// Vector containing cases - curves
for (RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves)
{
if (!curve->isCurveVisible()) continue;
QString curveCaseName = curve->caseName();
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
for (size_t i = 0; i < caseNames.size(); i++)
{
if (curveCaseName == caseNames[i]) casePosInList = i;
}
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
caseNames.push_back(curveCaseName);
timeSteps.push_back(curve->timeStepValues());
allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
allCurveData[casePosInList].push_back(curveData);
}
}
for (size_t i = 0; i < timeSteps.size(); i++) //cases
{
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
out += "\n\n";
out += "Case: " + caseNames[i];
out += "\n";
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::PERIOD_END, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
appendToExportData(out, exportData);
}
// Pasted observed data
{
std::vector<std::vector<time_t> > timeSteps;
std::vector<std::vector<CurveData>> allCurveData;
// Vector containing cases - curves
CurvesData asciiCurvesData;
populateAsciiDataCurvesData(m_asciiDataCurves.childObjects(), &asciiCurvesData);
for (RimAsciiDataCurve* curve : m_asciiDataCurves)
for (size_t i = 0; i < asciiCurvesData.timeSteps.size(); i++)
{
if (!curve->isCurveVisible()) continue;
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
timeSteps.push_back(curve->timeSteps());
allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
allCurveData[casePosInList].push_back(curveData);
}
}
for (size_t i = 0; i < timeSteps.size(); i++) //cases
{
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
out += "\n\n";
prepareCaseCurvesForExport(DateTimePeriod::NONE, ResampleAlgorithm::NONE, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
appendToExportDataForCase(out, asciiCurvesData.timeSteps[i], asciiCurvesData.allCurveData[i]);
}
}
@@ -535,6 +473,49 @@ void RimSummaryPlot::updateAll()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setPlotInfoLabel(const QString& label)
{
auto qwtText = QwtText(label);
qwtText.setRenderFlags(Qt::AlignBottom | Qt::AlignRight);
QFont font;
font.setBold(true);
qwtText.setFont(font);
m_plotInfoLabel.reset(new QwtPlotTextLabel());
m_plotInfoLabel->setText(qwtText);
m_plotInfoLabel->setMargin(30);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::showPlotInfoLabel(bool show)
{
if (show) m_plotInfoLabel->attach(m_qwtPlot);
else m_plotInfoLabel->detach();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updatePlotInfoLabel()
{
bool anyCurveSetFiltered = false;
for (auto group : m_ensembleCurveSetCollection->curveSets())
{
if (group->isFiltered())
{
anyCurveSetFiltered = true;
break;
}
}
showPlotInfoLabel(anyCurveSetFiltered);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -1647,48 +1628,167 @@ void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportCurveData)
void populateTimeHistoryCurvesData(std::vector<RimGridTimeHistoryCurve*> curves, CurvesData* curvesData)
{
RiaTimeHistoryCurveResampler resampler;
CVF_ASSERT(curvesData);
exportTimeSteps->clear();
exportCurveData->clear();
curvesData->caseNames.clear();
curvesData->timeSteps.clear();
curvesData->allCurveData.clear();
if (period != DateTimePeriod::NONE)
for (RimGridTimeHistoryCurve* curve : curves)
{
for (auto& curveDataItem : curveData)
if (!curve->isCurveVisible()) continue;
QString curveCaseName = curve->caseName();
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
for (size_t i = 0; i < curvesData->caseNames.size(); i++)
{
resampler.setCurveData(curveDataItem.values, timeSteps);
if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END)
{
resampler.resampleAndComputePeriodEndValues(period);
}
else
{
resampler.resampleAndComputeWeightedMeanValues(period);
}
auto cd = curveDataItem;
cd.values = resampler.resampledValues();
exportCurveData->push_back(cd);
if (curveCaseName == curvesData->caseNames[i]) casePosInList = i;
}
*exportTimeSteps = resampler.resampledTimeSteps();
}
else
{
*exportTimeSteps = timeSteps;
*exportCurveData = curveData;
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
curvesData->caseNames.push_back(curveCaseName);
curvesData->timeSteps.push_back(curve->timeStepValues());
curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
curvesData->allCurveData[casePosInList].push_back(curveData);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData)
void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesData* curvesData)
{
CVF_ASSERT(curvesData);
curvesData->caseNames.clear();
curvesData->timeSteps.clear();
curvesData->allCurveData.clear();
for (RimAsciiDataCurve* curve : curves)
{
if (!curve->isCurveVisible()) continue;
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
curvesData->caseNames.push_back("");
curvesData->timeSteps.push_back(curve->timeSteps());
curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
curvesData->allCurveData[casePosInList].push_back(curveData);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void populateSummaryCurvesData(std::vector<RimSummaryCurve*> curves, CurvesData* curvesData)
{
CVF_ASSERT(curvesData);
curvesData->caseNames.clear();
curvesData->timeSteps.clear();
curvesData->allCurveData.clear();
for (RimSummaryCurve* curve : curves)
{
if (!curve->isCurveVisible()) continue;
QString curveCaseName = curve->summaryCaseY()->caseName();
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
for (size_t i = 0; i < curvesData->caseNames.size(); i++)
{
if (curveCaseName == curvesData->caseNames[i]) casePosInList = i;
}
CurveData curveData = { curve->curveName(), curve->summaryAddressY(), curve->valuesY() };
if (casePosInList == cvf::UNDEFINED_SIZE_T)
{
curvesData->caseNames.push_back(curveCaseName);
curvesData->timeSteps.push_back(curve->timeStepsY());
curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData }));
}
else
{
curvesData->allCurveData[casePosInList].push_back(curveData);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const CurvesData& inputCurvesData,
CurvesData* resultCurvesData)
{
RiaTimeHistoryCurveResampler resampler;
resultCurvesData->clear();
if (period != DateTimePeriod::NONE)
{
for (int i = 0; i < inputCurvesData.caseNames.size(); i++)
{
// Shortcuts to input data
auto& caseName = inputCurvesData.caseNames[i];
auto& caseTimeSteps = inputCurvesData.timeSteps[i];
auto& caseCurveData = inputCurvesData.allCurveData[i];
// Prepare result data
resultCurvesData->resamplePeriod = period;
//resultCurvesData->resampleAlgorithm = algorithm;
resultCurvesData->caseNames.push_back(caseName);
resultCurvesData->allCurveData.push_back(std::vector<CurveData>());
for (auto& curveDataItem : caseCurveData)
{
resampler.setCurveData(curveDataItem.values, caseTimeSteps);
if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END)
{
resampler.resampleAndComputePeriodEndValues(period);
}
else
{
resampler.resampleAndComputeWeightedMeanValues(period);
}
auto cd = curveDataItem;
cd.values = resampler.resampledValues();
auto& currResultCurveDataList = resultCurvesData->allCurveData[i];
currResultCurveDataList.push_back(cd);
}
resultCurvesData->timeSteps.push_back(resampler.resampledTimeSteps());
}
}
else
{
*resultCurvesData = inputCurvesData;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void appendToExportDataForCase(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData)
{
for (size_t j = 0; j < timeSteps.size(); j++) //time steps & data points
{
@@ -1714,3 +1814,108 @@ void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, cons
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData)
{
CurvesData data = concatCurvesData(curvesData);
if (data.resamplePeriod != DateTimePeriod::NONE)
{
time_t minTimeStep = std::numeric_limits<time_t>::max();
time_t maxTimeStep = 0;
for (auto& timeSteps : data.timeSteps)
{
if (!timeSteps.empty())
{
if (timeSteps.front() < minTimeStep) minTimeStep = timeSteps.front();
if (timeSteps.back() > maxTimeStep) maxTimeStep = timeSteps.back();
}
}
auto allTimeSteps = RiaTimeHistoryCurveResampler::timeStepsFromTimeRange(data.resamplePeriod, minTimeStep, maxTimeStep);
out += "\n\n";
out += "Date and time";
for (size_t i = 0; i < data.caseNames.size(); i++)
{
for (size_t j = 0; j < data.allCurveData[i].size(); j++)
{
out += "\t" + data.allCurveData[i][j].name + " (" + data.caseNames[i] + ")";
}
}
out += "\n";
std::vector<int> currIndexes(data.caseNames.size());
for (auto& i : currIndexes) i = 0;
for (auto timeStep : allTimeSteps)
{
QString tt = QDateTime::fromTime_t(timeStep).toUTC().toString("yyyy-MM-dd hh:mm:ss ");
out += QDateTime::fromTime_t(timeStep).toUTC().toString("yyyy-MM-dd hh:mm:ss ");
for (size_t i = 0; i < data.caseNames.size(); i++) // cases
{
// Check is time step exists in curr case
int& currIndex = currIndexes[i];
bool timeStepExists = currIndex < data.timeSteps[i].size() && timeStep == data.timeSteps[i][currIndex];
for (size_t j = 0; j < data.allCurveData[i].size(); j++) // vectors
{
QString valueText;
if (timeStepExists)
{
valueText = QString::number(data.allCurveData[i][j].values[currIndex], 'g', 6);
}
else
{
valueText = QString::number(DOUBLE_INF);
}
out += "\t" + valueText;
}
if (timeStepExists && currIndex < data.timeSteps[i].size()) currIndex++;
}
out += "\n";
}
}
else
{
for (size_t i = 0; i < data.caseNames.size(); i++)
{
out += "\n\n";
out += "Case: " + data.caseNames[i];
out += "\n";
appendToExportDataForCase(out, data.timeSteps[i], data.allCurveData[i]);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData)
{
CVF_ASSERT(!curvesData.empty());
DateTimePeriod period = curvesData.front().resamplePeriod;
CurvesData resultCurvesData;
resultCurvesData.resamplePeriod = period;
for (auto curvesDataItem : curvesData)
{
if (curvesDataItem.caseNames.empty()) continue;
CVF_ASSERT(curvesDataItem.resamplePeriod == period);
resultCurvesData.caseNames.insert(resultCurvesData.caseNames.end(), curvesDataItem.caseNames.begin(), curvesDataItem.caseNames.end());
resultCurvesData.timeSteps.insert(resultCurvesData.timeSteps.end(), curvesDataItem.timeSteps.begin(), curvesDataItem.timeSteps.end());
resultCurvesData.allCurveData.insert(resultCurvesData.allCurveData.end(), curvesDataItem.allCurveData.begin(), curvesDataItem.allCurveData.end());
}
return resultCurvesData;
}

View File

@@ -28,6 +28,7 @@
#include "RimViewWindow.h"
#include "qwt_plot_textlabel.h"
#include <QPointer>
#include <set>
@@ -121,6 +122,10 @@ public:
void updateAll();
void setPlotInfoLabel(const QString& label);
void showPlotInfoLabel(bool show);
void updatePlotInfoLabel();
// RimViewWindow overrides
public:
virtual QWidget* createViewWidget(QWidget* mainWindowParent) override;
@@ -183,7 +188,7 @@ private:
caf::PdmChildField<RimSummaryTimeAxisProperties*> m_timeAxisProperties;
QPointer<RiuSummaryQwtPlot> m_qwtPlot;
std::unique_ptr<QwtPlotTextLabel> m_plotInfoLabel;
bool m_isCrossPlot;