From fa3d9c4fc2905219e5778d4e763bb5bdd0c1f1e3 Mon Sep 17 00:00:00 2001 From: Rebecca Cox Date: Fri, 8 Dec 2017 15:46:16 +0100 Subject: [PATCH] #2227 Well Formation: Add filter. Filter options not dynamic --- .../ProjectDataModel/RimWellLogTrack.cpp | 49 ++++- .../RigWellPathFormations.cpp | 202 ++++++++++++++++-- .../RigWellPathFormations.h | 35 ++- 3 files changed, 263 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp index 7a684baab5..21ffad7bd2 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp @@ -80,9 +80,22 @@ namespace caf void AppEnum< RimWellLogTrack::FormationSource >::setUp() { addItem(RimWellLogTrack::CASE, "CASE", "Case"); - addItem(RimWellLogTrack::WELL_PICK, "WELLPICK", "Well Pick"); + addItem(RimWellLogTrack::WELL_PICK, "WELL_PICK", "Well Pick"); + addItem(RimWellLogTrack::WELL_PICK_FILTER, "WELL_PICK_FILTER", "Well Pick Filter"); setDefault(RimWellLogTrack::CASE); } + + template<> + void AppEnum::setUp() + { + addItem(RigWellPathFormation::ALL, "ALL", "All"); + addItem(RigWellPathFormation::GROUP, "GROUP", "Group"); + addItem(RigWellPathFormation::LEVEL0, "LEVEL0", "Main"); + addItem(RigWellPathFormation::LEVEL1, "LEVEL1", "Level 1"); + addItem(RigWellPathFormation::LEVEL2, "LEVEL2", "Level 2"); + addItem(RigWellPathFormation::LEVEL3, "LEVEL3", "Level 3"); + setDefault(RigWellPathFormation::ALL); + } } @@ -125,6 +138,10 @@ RimWellLogTrack::RimWellLogTrack() CAF_PDM_InitFieldNoDefault(&m_formationCase, "FormationCase", "Formation Case", "", "", ""); m_formationCase.uiCapability()->setUiTreeChildrenHidden(true); + + CAF_PDM_InitFieldNoDefault(&m_formationLevel, "FormationLevel", "Formation Level", "", "", ""); + + CAF_PDM_InitField(&m_showformationFluids, "ShowFormationFluids", false, "Show Fluids", "", "", ""); } //-------------------------------------------------------------------------------------------------- @@ -285,6 +302,14 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField, loadDataAndUpdate(); } + else if (changedField == &m_formationLevel) + { + loadDataAndUpdate(); + } + else if (changedField == &m_showformationFluids) + { + loadDataAndUpdate(); + } } //-------------------------------------------------------------------------------------------------- @@ -302,7 +327,7 @@ QList RimWellLogTrack::calculateValueOptions(const caf:: { RimTools::wellPathOptionItems(&options); } - else if(m_formationSource == WELL_PICK) + else if(m_formationSource == WELL_PICK || m_formationSource == WELL_PICK_FILTER) { RimTools::wellPathWithFormationsOptionItems(&options); } @@ -740,6 +765,12 @@ void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& { formationGroup->add(&m_formationWellPath); } + else if (m_formationSource() == WELL_PICK_FILTER) + { + formationGroup->add(&m_formationWellPath); + formationGroup->add(&m_formationLevel); + formationGroup->add(&m_showformationFluids); + } uiOrderingForVisibleXRange(uiOrdering); @@ -1170,6 +1201,20 @@ void RimWellLogTrack::updateFormationNamesOnPlot() formations->measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(&formationNamesToPlot, &yValues); + m_annotationTool->attachWellPicks(this->viewer(), formationNamesToPlot, yValues); + } + else if (m_formationSource() == WELL_PICK_FILTER) + { + if (m_formationWellPath == nullptr) return; + if (plot->depthType() != RimWellLogPlot::MEASURED_DEPTH) return; + + std::vector yValues; + + const RigWellPathFormations* formations = m_formationWellPath->formationsGeometry(); + if (!formations) return; + + formations->measuredDepthAndFormationNamesUpToLevel(m_formationLevel(), &formationNamesToPlot, &yValues, m_showformationFluids()); + m_annotationTool->attachWellPicks(this->viewer(), formationNamesToPlot, yValues); } } diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathFormations.cpp b/ApplicationCode/ReservoirDataModel/RigWellPathFormations.cpp index b91336d2b2..8f3c65906b 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathFormations.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellPathFormations.cpp @@ -1,17 +1,17 @@ ///////////////////////////////////////////////////////////////////////////////// // // 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 +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// @@ -23,20 +23,32 @@ #include "cvfMath.h" //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -RigWellPathFormations::RigWellPathFormations(std::vector formations, const QString& filePath, const QString& key) +RigWellPathFormations::RigWellPathFormations(std::vector formations, const QString& filePath, + const QString& key) { - m_filePath = filePath; - m_keyInFile = key; + m_filePath = filePath; + m_keyInFile = key; m_formations = formations; + m_maxLevelDetected = RigWellPathFormation::ALL; + + for (RigWellPathFormation& formation : m_formations) + { + RigWellPathFormation::FormationLevel level = detectLevel(formation.formationName); + formation.level = level; + if (level > m_maxLevelDetected) + { + m_maxLevelDetected = level; + } + } } struct MeasuredDepthComp { bool operator()(const double& md1, const double& md2) const { - if (cvf::Math::abs(md1 - md2) < 1.0) + if (cvf::Math::abs(md1 - md2) < 0.1) { return false; } @@ -45,9 +57,10 @@ struct MeasuredDepthComp }; //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RigWellPathFormations::measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(std::vector* names, std::vector* measuredDepths) const +void RigWellPathFormations::measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(std::vector* names, + std::vector* measuredDepths) const { names->clear(); measuredDepths->clear(); @@ -75,16 +88,102 @@ void RigWellPathFormations::measuredDepthAndFormationNamesWithoutDuplicatesOnDep } } +struct NameAndMD +{ + NameAndMD(RigWellPathFormation::FormationLevel level, QString name, double md) : m_level(level), m_name(name), m_md(md) {} + NameAndMD() {} + RigWellPathFormation::FormationLevel m_level; + QString m_name; + double m_md; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellPathFormations::measuredDepthAndFormationNamesUpToLevel(RigWellPathFormation::FormationLevel level, + std::vector* names, + std::vector* measuredDepths, bool includeFluids) const +{ + names->clear(); + measuredDepths->clear(); + + if (level == RigWellPathFormation::ALL) + { + measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(names, measuredDepths); + return; + } + + std::map tempMakeVectorUniqueOnMeasuredDepth; + + for (RigWellPathFormation formation : m_formations) + { + if (formation.level == RigWellPathFormation::FLUIDS) + { + if (includeFluids) + { + tempMakeVectorUniqueOnMeasuredDepth[formation.mdTop] = + NameAndMD(formation.level, formation.formationName + " Top", formation.mdTop); + } + else continue; + } + + if (level < formation.level) continue; + + if (!tempMakeVectorUniqueOnMeasuredDepth.count(formation.mdTop) || + tempMakeVectorUniqueOnMeasuredDepth.at(formation.mdTop).m_level < formation.level) + { + tempMakeVectorUniqueOnMeasuredDepth[formation.mdTop] = + NameAndMD(formation.level, formation.formationName + " Top", formation.mdTop); + } + } + + for (RigWellPathFormation formation : m_formations) + { + if (formation.level == RigWellPathFormation::FLUIDS) + { + if (includeFluids) + { + tempMakeVectorUniqueOnMeasuredDepth[formation.mdTop] = + NameAndMD(formation.level, formation.formationName + " Base", formation.mdTop); + } + else continue; + } + + if (level < formation.level) continue; + + if (!tempMakeVectorUniqueOnMeasuredDepth.count(formation.mdBase) || + tempMakeVectorUniqueOnMeasuredDepth.at(formation.mdBase).m_level < formation.level) + { + tempMakeVectorUniqueOnMeasuredDepth[formation.mdBase] = + NameAndMD(formation.level, formation.formationName + " Base", formation.mdBase); + } + } + + for (auto it = tempMakeVectorUniqueOnMeasuredDepth.begin(); it != tempMakeVectorUniqueOnMeasuredDepth.end(); it++) + { + names->push_back(it->second.m_name); + measuredDepths->push_back(it->second.m_md); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- +RigWellPathFormation::FormationLevel RigWellPathFormations::maxFormationLevel() const +{ + return m_maxLevelDetected; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- QString RigWellPathFormations::filePath() const { return m_filePath; } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- QString RigWellPathFormations::keyInFile() const { @@ -92,9 +191,86 @@ QString RigWellPathFormations::keyInFile() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- size_t RigWellPathFormations::formationNamesCount() const { return m_formations.size(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigWellPathFormation::FormationLevel RigWellPathFormations::detectLevel(QString formationName) +{ + formationName = formationName.trimmed(); + + if (formationName == "OIL" || formationName == "GAS") + { + return RigWellPathFormation::FLUIDS; + } + + bool isGroupName = true; + for (QChar c : formationName) + { + if (c.isLower()) + { + isGroupName = false; + break; + } + } + if (isGroupName) + { + return RigWellPathFormation::GROUP; + } + + QStringList formationNameSplitted = formationName.split(" "); + + std::vector levelDesctiptorCandidates; + + for (QString word : formationNameSplitted) + { + for (const QChar& c : word) + { + if (c.isDigit()) + { + levelDesctiptorCandidates.push_back(word); + break; + } + } + } + if (levelDesctiptorCandidates.empty()) + { + return RigWellPathFormation::LEVEL0; + } + + if (levelDesctiptorCandidates.size() > 1) + { + for (auto it = levelDesctiptorCandidates.begin(); it != levelDesctiptorCandidates.end(); it++) + { + for (const QChar& c : *it) + { + if (c.isLetter()) + { + levelDesctiptorCandidates.erase(it); + } + } + } + } + if (levelDesctiptorCandidates.size() != 1) return RigWellPathFormation::ALL; + + QString levelDescriptor = levelDesctiptorCandidates[0]; + + int dotCount = levelDescriptor.count('.'); + + size_t level = dotCount + 1; + + switch (dotCount) + { + case 0: return RigWellPathFormation::LEVEL1; + case 1: return RigWellPathFormation::LEVEL2; + case 2: return RigWellPathFormation::LEVEL3; + default: break; + } + return RigWellPathFormation::ALL; +} diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathFormations.h b/ApplicationCode/ReservoirDataModel/RigWellPathFormations.h index 443db152bb..11ac386949 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathFormations.h +++ b/ApplicationCode/ReservoirDataModel/RigWellPathFormations.h @@ -29,30 +29,49 @@ struct RigWellPathFormation { - double mdTop; - double mdBase; - QString formationName; - size_t level = 0; -}; + enum FormationLevel + { + GROUP, + LEVEL0, + LEVEL1, + LEVEL2, + LEVEL3, + ALL, + FLUIDS + }; + double mdTop; + double mdBase; + QString formationName; + FormationLevel level; +}; class RigWellPathFormations : public cvf::Object { public: RigWellPathFormations(std::vector formations, const QString& filePath, const QString& key); - void measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(std::vector* names, std::vector* measuredDepths) const; + void measuredDepthAndFormationNamesWithoutDuplicatesOnDepth(std::vector* names, + std::vector* measuredDepths) const; - void measuredDepthAndFormationNamesForLevel(size_t level, std::vector* names, std::vector* measuredDepths) const; + void measuredDepthAndFormationNamesUpToLevel(RigWellPathFormation::FormationLevel level, std::vector* names, + std::vector* measuredDepths, bool includeFluids) const; + + RigWellPathFormation::FormationLevel maxFormationLevel() const; QString filePath() const; QString keyInFile() const; size_t formationNamesCount() const; +private: + RigWellPathFormation::FormationLevel detectLevel(QString formationName); + private: QString m_filePath; QString m_keyInFile; - + + RigWellPathFormation::FormationLevel m_maxLevelDetected; + std::vector m_formations; };