///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015- Statoil ASA // Copyright (C) 2015- Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimWellLogTrack.h" #include "RiaApplication.h" #include "RigEclipseCaseData.h" #include "RigEclipseWellLogExtractor.h" #include "RigFemPartResultsCollection.h" #include "RigFemResultAddress.h" #include "RigFormationNames.h" #include "RigGeoMechCaseData.h" #include "RigGeoMechWellLogExtractor.h" #include "RigResultAccessorFactory.h" #include "RigSimWellData.h" #include "RigSimulationWellCenterLineCalculator.h" #include "RigSimulationWellCoordsAndMD.h" #include "RigStatisticsCalculator.h" #include "RigWellLogCurveData.h" #include "RigWellPath.h" #include "RimCase.h" #include "RimEclipseCase.h" #include "RimGeoMechCase.h" #include "RimMainPlotCollection.h" #include "RimProject.h" #include "RimTools.h" #include "RimWellFlowRateCurve.h" #include "RimWellLogCurve.h" #include "RimWellLogPlotCollection.h" #include "RimWellPath.h" #include "RimWellPltPlot.h" #include "RimWellRftPlot.h" #include "RiuMainWindow.h" #include "RiuPlotAnnotationTool.h" #include "RiuWellLogPlot.h" #include "RiuWellLogTrack.h" #include "cvfAssert.h" #include "qwt_scale_engine.h" #define RI_LOGPLOTTRACK_MINX_DEFAULT -10.0 #define RI_LOGPLOTTRACK_MAXX_DEFAULT 100.0 CAF_PDM_SOURCE_INIT(RimWellLogTrack, "WellLogPlotTrack"); namespace caf { template<> void AppEnum< RimWellLogTrack::TrajectoryType >::setUp() { addItem(RimWellLogTrack::WELL_PATH, "WELL_PATH", "Well Path"); addItem(RimWellLogTrack::SIMULATION_WELL, "SIMULATION_WELL", "Simulation Well"); setDefault(RimWellLogTrack::WELL_PATH); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellLogTrack::RimWellLogTrack() { CAF_PDM_InitObject("Track", ":/WellLogTrack16x16.png", "", ""); CAF_PDM_InitFieldNoDefault(&m_userName, "TrackDescription", "Name", "", "", ""); m_userName.uiCapability()->setUiReadOnly(true); CAF_PDM_InitField(&m_show, "Show", true, "Show track", "", "", ""); m_show.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&curves, "Curves", "", "", "", ""); curves.uiCapability()->setUiHidden(true); CAF_PDM_InitField(&m_visibleXRangeMin, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min", "", "", ""); CAF_PDM_InitField(&m_visibleXRangeMax, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max", "", "", ""); CAF_PDM_InitField(&m_isAutoScaleXEnabled, "AutoScaleX", true, "Auto Scale", "", "", ""); CAF_PDM_InitField(&m_isLogarithmicScaleEnabled, "LogarithmicScaleX", false, "Logarithmic Scale", "", "", ""); CAF_PDM_InitField(&m_showFormations, "ShowFormations", false, "Show Formations", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_formationTrajectoryType, "FormationTrajectoryType", "Trajectory", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_formationWellPath, "FormationWellPath", " ", "", "", ""); m_formationWellPath.uiCapability()->setUiTreeChildrenHidden(true); CAF_PDM_InitField(&m_formationSimWellName, "FormationSimulationWellName", QString("None"), " ", "", "", ""); CAF_PDM_InitField(&m_formationBranchIndex, "FormationBranchIndex", 0, " ", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_formationCase, "FormationCase", "Formation Case", "", "", ""); m_formationCase.uiCapability()->setUiTreeChildrenHidden(true); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellLogTrack::~RimWellLogTrack() { curves.deleteAllChildObjects(); if (m_wellLogTrackPlotWidget) { m_wellLogTrackPlotWidget->deleteLater(); m_wellLogTrackPlotWidget = nullptr; } clearGeneratedSimWellPaths(&m_generatedSimulationWellPathBranches); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setDescription(const QString& description) { m_userName = description; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::simWellOptionItems(QList* options, RimCase* rimCase) { CVF_ASSERT(options); if (!options) return; std::set sortedWellNames; RimEclipseCase* eclipseCase = dynamic_cast(rimCase); if (eclipseCase && eclipseCase->eclipseCaseData()) { sortedWellNames = eclipseCase->eclipseCaseData()->findSortedWellNames(); } QIcon simWellIcon(":/Well.png"); for (const QString& wname : sortedWellNames) { options->push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); } if (options->size() == 0) { options->push_front(caf::PdmOptionItemInfo("None", "None")); } } //-------------------------------------------------------------------------------------------------- /// Clean up existing generated well paths //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::clearGeneratedSimWellPaths(cvf::Collection* generatedSimulationWellPathBranches) { RimWellLogPlotCollection* wellLogCollection = nullptr; // Need to use this approach, and not firstAnchestor because the curve might not be inside the hierarchy when deleted. RimProject * proj = RiaApplication::instance()->project(); if (proj && proj->mainPlotCollection()) wellLogCollection = proj->mainPlotCollection()->wellLogPlotCollection(); if (!wellLogCollection) return; for (size_t wpIdx = 0; wpIdx < generatedSimulationWellPathBranches->size(); ++wpIdx) { wellLogCollection->removeExtractors(generatedSimulationWellPathBranches->at(wpIdx)); } generatedSimulationWellPathBranches->clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { if (changedField == &m_show) { if (m_wellLogTrackPlotWidget) { m_wellLogTrackPlotWidget->setVisible(m_show()); } RimWellLogPlot* wellLogPlot; this->firstAncestorOrThisOfType(wellLogPlot); if (wellLogPlot) { wellLogPlot->calculateAvailableDepthRange(); wellLogPlot->updateDepthZoom(); RiuWellLogPlot* wellLogPlotViewer = dynamic_cast(wellLogPlot->viewWidget()); if (wellLogPlotViewer) { wellLogPlotViewer->updateChildrenLayout(); } } } else if (changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax) { m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); m_wellLogTrackPlotWidget->replot(); m_isAutoScaleXEnabled = false; } else if (changedField == &m_isAutoScaleXEnabled) { if (m_isAutoScaleXEnabled()) { this->updateXZoom(); computeAndSetXRangeMinForLogarithmicScale(); if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->replot(); } } else if (changedField == &m_isLogarithmicScaleEnabled) { updateAxisScaleEngine(); this->updateXZoom(); computeAndSetXRangeMinForLogarithmicScale(); m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); m_wellLogTrackPlotWidget->replot(); } else if (changedField == &m_showFormations) { loadDataAndUpdate(); RimWellRftPlot* rftPlot(nullptr); firstAncestorOrThisOfType(rftPlot); if (rftPlot) { rftPlot->updateConnectedEditors(); } else { RimWellPltPlot* pltPlot(nullptr); firstAncestorOrThisOfType(pltPlot); if (pltPlot) { pltPlot->updateConnectedEditors(); } } } else if (changedField == &m_formationCase) { QList options; RimWellLogTrack::simWellOptionItems(&options, m_formationCase); if (options.isEmpty()) { m_formationSimWellName = QString("None"); } clearGeneratedSimWellPaths(&m_generatedSimulationWellPathBranches); loadDataAndUpdate(); } else if (changedField == &m_formationWellPath) { loadDataAndUpdate(); } else if (changedField == &m_formationSimWellName) { clearGeneratedSimWellPaths(&m_generatedSimulationWellPathBranches); loadDataAndUpdate(); } else if (changedField == &m_formationTrajectoryType) { clearGeneratedSimWellPaths(&m_generatedSimulationWellPathBranches); loadDataAndUpdate(); } else if (changedField == &m_formationBranchIndex) { loadDataAndUpdate(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RimWellLogTrack::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { QList options; if (options.size() > 0) return options; if (fieldNeedingOptions == &m_formationWellPath) { RimTools::wellPathOptionItems(&options); options.push_front(caf::PdmOptionItemInfo("None", nullptr)); } else if (fieldNeedingOptions == &m_formationCase) { RimTools::caseOptionItems(&options); options.push_front(caf::PdmOptionItemInfo("None", nullptr)); } else if (fieldNeedingOptions == &m_formationSimWellName) { RimWellLogTrack::simWellOptionItems(&options, m_formationCase); } else if (fieldNeedingOptions == &m_formationBranchIndex) { updateGeneratedSimulationWellpath(&m_generatedSimulationWellPathBranches, m_formationSimWellName(), m_formationCase); size_t branchCount = m_generatedSimulationWellPathBranches.size(); for (int bIdx = 0; bIdx < static_cast(branchCount); ++bIdx) { options.push_back(caf::PdmOptionItemInfo("Branch " + QString::number(bIdx + 1), QVariant::fromValue(bIdx))); } if (options.size() == 0) { options.push_front(caf::PdmOptionItemInfo("None", -1)); } } return options; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimWellLogTrack::objectToggleField() { return &m_show; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField() { return &m_userName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::addCurve(RimWellLogCurve* curve) { curves.push_back(curve); if (m_wellLogTrackPlotWidget) { curve->setParentQwtPlotAndReplot(m_wellLogTrackPlotWidget); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::insertCurve(RimWellLogCurve* curve, size_t index) { curves.insert(index, curve); // Todo: Mark curve data to use either TVD or MD if (m_wellLogTrackPlotWidget) { curve->setParentQwtPlotAndReplot(m_wellLogTrackPlotWidget); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::takeOutCurve(RimWellLogCurve* curve) { size_t index = curves.index(curve); if ( index < curves.size()) { curves[index]->detachQwtCurve(); curves.removeChildObject(curve); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::deleteAllCurves() { curves.deleteAllChildObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuWellLogTrack* RimWellLogTrack::viewer() { return m_wellLogTrackPlotWidget; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::availableDepthRange(double* minimumDepth, double* maximumDepth) { double minDepth = HUGE_VAL; double maxDepth = -HUGE_VAL; size_t curveCount = curves.size(); for (size_t cIdx = 0; cIdx < curveCount; cIdx++) { double minCurveDepth = HUGE_VAL; double maxCurveDepth = -HUGE_VAL; if (curves[cIdx]->isCurveVisible() && curves[cIdx]->depthRange(&minCurveDepth, &maxCurveDepth)) { if (minCurveDepth < minDepth) { minDepth = minCurveDepth; } if (maxCurveDepth > maxDepth) { maxDepth = maxCurveDepth; } } } *minimumDepth = minDepth; *maximumDepth = maxDepth; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::loadDataAndUpdate() { RimWellLogPlot* wellLogPlot; firstAncestorOrThisOfType(wellLogPlot); if (wellLogPlot && m_wellLogTrackPlotWidget) { m_wellLogTrackPlotWidget->setDepthTitle(wellLogPlot->depthPlotTitle()); m_wellLogTrackPlotWidget->setXTitle(m_xAxisTitle); } for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) { curves[cIdx]->loadDataAndUpdate(false); } if (m_showFormations) { setFormationFieldsUiReadOnly(false); } else { setFormationFieldsUiReadOnly(true); } if ( m_wellLogTrackPlotWidget ) { m_wellLogTrackPlotWidget->updateLegend(); this->updateAxisScaleEngine(); this->updateFormationNamesOnPlot(); this->updateXZoomAndParentPlotDepthZoom(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setAndUpdateWellPathFormationNamesData(RimCase* rimCase, RimWellPath* wellPath) { m_formationCase = rimCase; m_formationTrajectoryType = RimWellLogTrack::WELL_PATH; m_formationWellPath = wellPath; m_formationSimWellName = ""; m_formationBranchIndex = -1; updateConnectedEditors(); if (m_showFormations) { updateFormationNamesOnPlot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setAndUpdateSimWellFormationNamesData(RimCase* rimCase, QString simWellName, int branchIndex) { m_formationCase = rimCase; m_formationTrajectoryType = RimWellLogTrack::SIMULATION_WELL; m_formationWellPath = nullptr; m_formationSimWellName = simWellName; m_formationBranchIndex = branchIndex; updateConnectedEditors(); if (m_showFormations) { updateFormationNamesOnPlot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setXAxisTitle(const QString& text) { m_xAxisTitle = text; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setFormationBranchIndex(int branchIndex) { m_formationBranchIndex = branchIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RimWellLogTrack::formationBranchIndex() const { return m_formationBranchIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimCase* RimWellLogTrack::formationNamesCase() const { return m_formationCase(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::recreateViewer() { if (m_wellLogTrackPlotWidget == nullptr) { m_wellLogTrackPlotWidget = new RiuWellLogTrack(this); updateAxisScaleEngine(); for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) { curves[cIdx]->setParentQwtPlotNoReplot(this->m_wellLogTrackPlotWidget); } this->m_wellLogTrackPlotWidget->replot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::detachAllCurves() { for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) { curves[cIdx]->detachQwtCurve(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateXZoomAndParentPlotDepthZoom() { if (m_wellLogTrackPlotWidget) { RimWellLogPlot* wellLogPlot; firstAncestorOrThisOfType(wellLogPlot); if (wellLogPlot) { wellLogPlot->updateDepthZoom(); } updateXZoom(); m_wellLogTrackPlotWidget->replot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateXZoom() { std::map> stackCurveGroups = visibleStackedCurves(); for (const std::pair>& curveGroup : stackCurveGroups) { for (RimWellFlowRateCurve* stCurve : curveGroup.second) stCurve->updateStackedPlotData(); } if (!m_isAutoScaleXEnabled()) { m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); m_wellLogTrackPlotWidget->replot(); return; } double minValue = HUGE_VAL; double maxValue = -HUGE_VAL; for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) { double minCurveValue = HUGE_VAL; double maxCurveValue = -HUGE_VAL; if (curves[cIdx]->isCurveVisible() && curves[cIdx]->valueRange(&minCurveValue, &maxCurveValue)) { if (minCurveValue < minValue) { minValue = minCurveValue; } if (maxCurveValue > maxValue) { maxValue = maxCurveValue; } } } if (minValue == HUGE_VAL) { minValue = RI_LOGPLOTTRACK_MINX_DEFAULT; maxValue = RI_LOGPLOTTRACK_MAXX_DEFAULT; } m_visibleXRangeMin = minValue; m_visibleXRangeMax = maxValue; computeAndSetXRangeMinForLogarithmicScale(); if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setShowFormations(bool on) { m_showFormations = on; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve(const QwtPlotCurve* curve) const { for (size_t idx = 0; idx < curves.size(); idx++) { if (curves[idx]->qwtPlotCurve() == curve) { return curves[idx]; } } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateGeneratedSimulationWellpath(cvf::Collection* generatedSimulationWellPathBranches, const QString& simWellName, RimCase* rimCase) { if (generatedSimulationWellPathBranches->size()) return; // Already created. Nothing to do RimEclipseCase* eclipseCase = dynamic_cast(rimCase); if (!(!simWellName.isEmpty() && simWellName != QString("None") && eclipseCase && eclipseCase->eclipseCaseData())) { return; } RigEclipseCaseData* eclCaseData = eclipseCase->eclipseCaseData(); const RigSimWellData* simWellData = eclCaseData->findSimWellData(simWellName); if (!simWellData) return; std::vector< std::vector > pipeBranchesCLCoords; std::vector< std::vector > pipeBranchesCellIds; RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame(eclCaseData, simWellData, -1, true, true, pipeBranchesCLCoords, pipeBranchesCellIds); for (size_t brIdx = 0; brIdx < pipeBranchesCLCoords.size(); ++brIdx) { auto wellMdCalculator = RigSimulationWellCoordsAndMD(pipeBranchesCLCoords[brIdx]); // Todo, branch index cvf::ref newWellPath = new RigWellPath(); newWellPath->m_measuredDepths = wellMdCalculator.measuredDepths(); newWellPath->m_wellPathPoints = wellMdCalculator.wellPathPoints(); generatedSimulationWellPathBranches->push_back(newWellPath.p()); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { uiOrdering.add(&m_userName); caf::PdmUiGroup* formationGroup = uiOrdering.addNewGroup("Formation Names Properties"); formationGroup->add(&m_showFormations); formationGroup->add(&m_formationCase); formationGroup->add(&m_formationTrajectoryType); if (m_formationTrajectoryType() == WELL_PATH) { formationGroup->add(&m_formationWellPath); } else { updateGeneratedSimulationWellpath(&m_generatedSimulationWellPathBranches, m_formationSimWellName(), m_formationCase); formationGroup->add(&m_formationSimWellName); if (m_generatedSimulationWellPathBranches.size() > 1) { formationGroup->add(&m_formationBranchIndex); } } uiOrderingForVisibleXRange(uiOrdering); uiOrdering.skipRemainingFields(true); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimWellLogTrack::curveIndex(RimWellLogCurve* curve) { return curves.index(curve); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimWellLogTrack::isVisible() { return m_show; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateAxisScaleEngine() { if (m_isLogarithmicScaleEnabled) { m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLogScaleEngine); // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine); } else { m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLinearScaleEngine); // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::computeAndSetXRangeMinForLogarithmicScale() { if (m_isAutoScaleXEnabled && m_isLogarithmicScaleEnabled) { double pos = HUGE_VAL; double neg = -HUGE_VAL; for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) { if (curves[cIdx]->isCurveVisible() && curves[cIdx]->curveData()) { RigStatisticsCalculator::posNegClosestToZero(curves[cIdx]->curveData()->xPlotValues(), pos, neg); } } if (pos != HUGE_VAL) { m_visibleXRangeMin = pos; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setLogarithmicScale(bool enable) { m_isLogarithmicScaleEnabled = enable; updateAxisScaleEngine(); computeAndSetXRangeMinForLogarithmicScale(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RimWellLogTrack::visibleStackedCurves() { std::map> stackedCurves; for (RimWellLogCurve* curve: curves) { if (curve && curve->isCurveVisible() ) { RimWellFlowRateCurve* wfrCurve = dynamic_cast(curve); if (wfrCurve != nullptr) { stackedCurves[wfrCurve->groupId()].push_back(wfrCurve); } } } return stackedCurves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimWellLogTrack::description() { return m_userName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimWellLogTrack::curvesVector() { std::vector curvesVector; for (RimWellLogCurve* curve : curves) { curvesVector.push_back(curve); } return curvesVector; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::uiOrderingForShowFormationNamesAndCase(caf::PdmUiOrdering& uiOrdering) { caf::PdmUiGroup* formationGroup = uiOrdering.addNewGroup("Formation Names"); formationGroup->setCollapsedByDefault(true); formationGroup->add(&m_showFormations); formationGroup->add(&m_formationCase); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::uiOrderingForVisibleXRange(caf::PdmUiOrdering& uiOrdering) { caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Visible X Axis Range"); gridGroup->add(&m_isAutoScaleXEnabled); gridGroup->add(&m_isLogarithmicScaleEnabled); gridGroup->add(&m_visibleXRangeMin); gridGroup->add(&m_visibleXRangeMax); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigEclipseWellLogExtractor* RimWellLogTrack::createSimWellExtractor(RimWellLogPlotCollection* wellLogCollection, RimCase* rimCase, const QString& simWellName, int branchIndex) { if (!wellLogCollection) return nullptr; RimEclipseCase* eclipseCase = dynamic_cast(rimCase); RimProject* proj = RiaApplication::instance()->project(); std::vector wellPaths = proj->simulationWellBranches(simWellName); if (wellPaths.size() == 0) return nullptr; CVF_ASSERT(branchIndex < static_cast(wellPaths.size())); return (wellLogCollection->findOrCreateSimWellExtractor(simWellName, QString("Find or create sim well extractor"), wellPaths[branchIndex], eclipseCase->eclipseCaseData())); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigEclipseWellLogExtractor* RimWellLogTrack::createWellPathExtractor(RimWellLogPlotCollection* wellLogCollection, RimCase* rimCase, RimWellPath* wellPath) { if (!wellLogCollection) return nullptr; RimEclipseCase* eclipseCase = dynamic_cast(rimCase); return (wellLogCollection->findOrCreateExtractor(wellPath, eclipseCase)); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigGeoMechWellLogExtractor* RimWellLogTrack::createGeoMechExtractor(RimWellLogPlotCollection* wellLogCollection, RimCase* rimCase, RimWellPath* wellPath) { RimGeoMechCase* geomCase = dynamic_cast(rimCase); return (wellLogCollection->findOrCreateExtractor(wellPath, geomCase)); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- CurveSamplingPointData RimWellLogTrack::curveSamplingPointData(RigEclipseWellLogExtractor* extractor, RigResultAccessor* resultAccessor) { CurveSamplingPointData curveData; curveData.md = extractor->measuredDepth(); curveData.tvd = extractor->trueVerticalDepth(); extractor->curveData(resultAccessor, &curveData.data); return curveData; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- CurveSamplingPointData RimWellLogTrack::curveSamplingPointData(RigGeoMechWellLogExtractor* extractor, const RigFemResultAddress& resultAddress) { CurveSamplingPointData curveData; curveData.md = extractor->measuredDepth(); curveData.tvd = extractor->trueVerticalDepth(); extractor->curveData(resultAddress, 0, &curveData.data); return curveData; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimWellLogTrack::formationNameIndexToName(RimCase* rimCase, const std::vector& formationNameInidces) { std::vector availableFormationNames = RimWellLogTrack::formationNamesVector(rimCase); std::vector formationNames; for (int index : formationNameInidces) { formationNames.push_back(availableFormationNames[index]); } return formationNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::findFormationNamesToPlot(const CurveSamplingPointData& curveData, const std::vector& formationNamesVector, RimWellLogPlot::DepthTypeEnum depthType, std::vector* formationNamesToPlot, std::vector>* yValues) { if (formationNamesVector.empty()) return; std::vector formationNameIndicesFromCurve; for (double nameIdx : curveData.data) { formationNameIndicesFromCurve.push_back(round(nameIdx)); } if (formationNameIndicesFromCurve.empty()) return; std::vector depthVector; if (depthType == RimWellLogPlot::MEASURED_DEPTH || depthType == RimWellLogPlot::PSEUDO_LENGTH) { depthVector = curveData.md; } else if(depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH) { depthVector = curveData.tvd; } if (depthVector.empty()) return; double currentYStart = depthVector[0]; double prevNameIndex = formationNameIndicesFromCurve[0]; double currentNameIndex; for (size_t i = 1; i < formationNameIndicesFromCurve.size(); i++) { currentNameIndex = formationNameIndicesFromCurve[i]; if (currentNameIndex != prevNameIndex) { if (prevNameIndex < formationNamesVector.size()) { formationNamesToPlot->push_back(formationNamesVector[prevNameIndex]); yValues->push_back(std::make_pair(currentYStart, depthVector[i - 1])); } currentYStart = depthVector[i]; prevNameIndex = currentNameIndex; } } size_t lastIdx = formationNameIndicesFromCurve.size() - 1; formationNamesToPlot->push_back(formationNamesVector[formationNameIndicesFromCurve[lastIdx]]); yValues->push_back(std::make_pair(currentYStart, depthVector[lastIdx])); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimWellLogTrack::formationNamesVector(RimCase* rimCase) { RimEclipseCase* eclipseCase = dynamic_cast(rimCase); RimGeoMechCase* geoMechCase = dynamic_cast(rimCase); if (eclipseCase) { if (eclipseCase->eclipseCaseData()->activeFormationNames()) { return eclipseCase->eclipseCaseData()->activeFormationNames()->formationNames(); } } else if (geoMechCase) { if (geoMechCase->geoMechData()->femPartResults()->activeFormationNames()) { return geoMechCase->geoMechData()->femPartResults()->activeFormationNames()->formationNames(); } } return std::vector(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setFormationFieldsUiReadOnly(bool readOnly /*= true*/) { m_formationTrajectoryType.uiCapability()->setUiReadOnly(readOnly); m_formationSimWellName.uiCapability()->setUiReadOnly(readOnly); m_formationCase.uiCapability()->setUiReadOnly(readOnly); m_formationWellPath.uiCapability()->setUiReadOnly(readOnly); m_formationBranchIndex.uiCapability()->setUiReadOnly(readOnly); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateFormationNamesOnPlot() { removeFormationNames(); if (m_showFormations == false) return; if ((m_formationSimWellName == QString("None") && m_formationWellPath == nullptr) || m_formationCase == nullptr) return; if (m_annotationTool == nullptr) { m_annotationTool = std::unique_ptr(new RiuPlotAnnotationTool()); } RimMainPlotCollection* mainPlotCollection; this->firstAncestorOrThisOfTypeAsserted(mainPlotCollection); RimWellLogPlotCollection* wellLogCollection = mainPlotCollection->wellLogPlotCollection(); CurveSamplingPointData curveData; RigEclipseWellLogExtractor* eclWellLogExtractor; RigGeoMechWellLogExtractor* geoMechWellLogExtractor; if (m_formationTrajectoryType == SIMULATION_WELL) { eclWellLogExtractor = RimWellLogTrack::createSimWellExtractor(wellLogCollection, m_formationCase, m_formationSimWellName, m_formationBranchIndex); } else { eclWellLogExtractor = RimWellLogTrack::createWellPathExtractor(wellLogCollection, m_formationCase, m_formationWellPath); } if (eclWellLogExtractor) { RimEclipseCase* eclipseCase = dynamic_cast(m_formationCase()); cvf::ref resultAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCase->eclipseCaseData(), 0, RiaDefines::PorosityModelType::MATRIX_MODEL, 0, RiaDefines::activeFormationNamesResultName(), RiaDefines::FORMATION_NAMES); curveData = RimWellLogTrack::curveSamplingPointData(eclWellLogExtractor, resultAccessor.p()); } else { geoMechWellLogExtractor = RimWellLogTrack::createGeoMechExtractor(wellLogCollection, m_formationCase, m_formationWellPath); if (!geoMechWellLogExtractor) return; curveData = RimWellLogTrack::curveSamplingPointData(geoMechWellLogExtractor, RigFemResultAddress(RIG_FORMATION_NAMES, RiaDefines::activeFormationNamesResultName().toStdString(), "")); } RimWellLogPlot* plot; firstAncestorOrThisOfTypeAsserted(plot); std::vector formationNamesVector = RimWellLogTrack::formationNamesVector(m_formationCase); std::vector formationNamesToPlot; std::vector> yValues; RimWellLogTrack::findFormationNamesToPlot(curveData, formationNamesVector, plot->depthType(), &formationNamesToPlot, &yValues); m_annotationTool->attachFormationNames(this->viewer(), formationNamesToPlot, yValues); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::removeFormationNames() { if (m_annotationTool) { m_annotationTool->detachAllAnnotations(); } }