#864 Moved summary files into separate folder

This commit is contained in:
Magne Sjaastad
2016-11-04 11:42:03 +01:00
parent 85b1d4a391
commit b38c1986aa
29 changed files with 51 additions and 26 deletions

View File

@@ -0,0 +1,47 @@
# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly
if (${CMAKE_VERSION} VERSION_GREATER "2.8.2")
set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/)
endif()
set (SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RimFileSummaryCase.h
${CEE_CURRENT_LIST_DIR}RimGridSummaryCase.h
${CEE_CURRENT_LIST_DIR}RimSummaryCase.h
${CEE_CURRENT_LIST_DIR}RimSummaryCaseCollection.h
${CEE_CURRENT_LIST_DIR}RimSummaryCurve.h
${CEE_CURRENT_LIST_DIR}RimSummaryCurveAppearanceCalculator.h
${CEE_CURRENT_LIST_DIR}RimSummaryCurveFilter.h
${CEE_CURRENT_LIST_DIR}RimSummaryCurvesCalculator.h
${CEE_CURRENT_LIST_DIR}RimSummaryFilter.h
${CEE_CURRENT_LIST_DIR}RimSummaryPlot.h
${CEE_CURRENT_LIST_DIR}RimSummaryPlotCollection.h
${CEE_CURRENT_LIST_DIR}RimSummaryTimeAxisProperties.h
${CEE_CURRENT_LIST_DIR}RimSummaryYAxisProperties.h
)
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RimFileSummaryCase.cpp
${CEE_CURRENT_LIST_DIR}RimGridSummaryCase.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCase.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCaseCollection.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCurve.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCurveAppearanceCalculator.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCurveFilter.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryCurvesCalculator.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryFilter.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryPlot.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryPlotCollection.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryTimeAxisProperties.cpp
${CEE_CURRENT_LIST_DIR}RimSummaryYAxisProperties.cpp
)
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)
list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
source_group( "ProjectDataModel\\Summary" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake )

View File

@@ -0,0 +1,74 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimFileSummaryCase.h"
#include "QFileInfo"
//==================================================================================================
//
//
//
//==================================================================================================
CAF_PDM_SOURCE_INIT(RimFileSummaryCase,"FileSummaryCase");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFileSummaryCase::RimFileSummaryCase()
{
CAF_PDM_InitFieldNoDefault(&m_summaryHeaderFilename, "SummaryHeaderFilename", "Summary Header File", "", "", "");
m_summaryHeaderFilename.uiCapability()->setUiReadOnly(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFileSummaryCase::~RimFileSummaryCase()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::setSummaryHeaderFilename(const QString& fileName)
{
m_summaryHeaderFilename = fileName;
this->updateAutoShortName();
this->updateTreeItemName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFileSummaryCase::summaryHeaderFilename() const
{
return m_summaryHeaderFilename();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFileSummaryCase::caseName() const
{
QFileInfo caseFileName(this->summaryHeaderFilename());
return caseFileName.completeBaseName();
}

View File

@@ -0,0 +1,44 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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"
//==================================================================================================
//
//
//
//==================================================================================================
class RimFileSummaryCase: public RimSummaryCase
{
CAF_PDM_HEADER_INIT;
public:
RimFileSummaryCase();
virtual ~RimFileSummaryCase();
void setSummaryHeaderFilename(const QString& fileName);
virtual QString summaryHeaderFilename() const override;
virtual QString caseName() const override;
private:
caf::PdmField<QString> m_summaryHeaderFilename;
};

View File

@@ -0,0 +1,93 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimGridSummaryCase.h"
#include "RigSummaryCaseData.h"
#include "RimEclipseCase.h"
#include <QFileInfo>
//==================================================================================================
//
//
//
//==================================================================================================
CAF_PDM_SOURCE_INIT(RimGridSummaryCase,"GridSummaryCase");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridSummaryCase::RimGridSummaryCase()
{
CAF_PDM_InitFieldNoDefault(&m_eclipseCase, "Associated3DCase", "Main View", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridSummaryCase::~RimGridSummaryCase()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridSummaryCase::setAssociatedEclipseCase(RimEclipseCase* eclipseCase)
{
m_eclipseCase = eclipseCase;
this->updateAutoShortName();
this->updateTreeItemName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RimGridSummaryCase::associatedEclipseCase()
{
return m_eclipseCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridSummaryCase::summaryHeaderFilename() const
{
if (!m_eclipseCase()) return QString();
QFileInfo gridFileInfo(m_eclipseCase()->gridFileName());
QString possibleSumHeaderFileName = gridFileInfo.path() +"/"+ gridFileInfo.completeBaseName() + ".SMSPEC";
return possibleSumHeaderFileName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridSummaryCase::caseName() const
{
if (!m_eclipseCase()) return QString();
return m_eclipseCase()->caseUserDescription();
}

View File

@@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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"
class RimEclipseCase;
//==================================================================================================
//
//
//
//==================================================================================================
class RimGridSummaryCase: public RimSummaryCase
{
CAF_PDM_HEADER_INIT;
public:
RimGridSummaryCase();
virtual ~RimGridSummaryCase();
void setAssociatedEclipseCase(RimEclipseCase* eclipseCase);
RimEclipseCase* associatedEclipseCase();
virtual QString summaryHeaderFilename() const override;
virtual QString caseName() const override;
private:
caf::PdmPtrField<RimEclipseCase*> m_eclipseCase;
};

View File

@@ -0,0 +1,149 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCase.h"
#include "RigSummaryCaseData.h"
#include "RimEclipseCase.h"
#include "RimSummaryCaseCollection.h"
#include <QFileInfo>
#include "RimProject.h"
#include "RimSummaryPlotCollection.h"
#include "RimMainPlotCollection.h"
CAF_PDM_ABSTRACT_SOURCE_INIT(RimSummaryCase,"SummaryCase");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase::RimSummaryCase()
{
CAF_PDM_InitObject("Summary Case",":/SummaryCase48x48.png","","");
CAF_PDM_InitField(&m_shortName, "ShortName", QString("Display Name"), "Display Name", "", "", "");
CAF_PDM_InitField(&m_useAutoShortName, "AutoShortyName", false, "Use Auto Display Name", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase::~RimSummaryCase()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::loadCase()
{
if (m_summaryCaseData.isNull()) m_summaryCaseData = new RigSummaryCaseData(this->summaryHeaderFilename());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigSummaryCaseData* RimSummaryCase::caseData()
{
return m_summaryCaseData.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (changedField == &m_useAutoShortName)
{
this->updateAutoShortName();
}
else if (changedField == &m_shortName)
{
updateTreeItemName();
}
RimProject* proj = NULL;
this->firstAncestorOrThisOfType(proj);
RimMainPlotCollection* mainPlotColl = proj->mainPlotCollection();
RimSummaryPlotCollection* summaryPlotColl = mainPlotColl->summaryPlotCollection();
summaryPlotColl->updateSummaryNameHasChanged();
updateOptionSensitivity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::updateOptionSensitivity()
{
m_shortName.uiCapability()->setUiReadOnly(m_useAutoShortName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::updateTreeItemName()
{
if (caseName() != shortName())
this->setUiName(caseName() + " (" + shortName() +")");
else
this->setUiName(caseName());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryCase::shortName() const
{
return m_shortName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::initAfterRead()
{
updateOptionSensitivity();
updateTreeItemName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCase::updateAutoShortName()
{
if(m_useAutoShortName)
{
RimSummaryCaseCollection* summaryCaseCollection = NULL;
this->firstAncestorOrThisOfType(summaryCaseCollection);
CVF_ASSERT(summaryCaseCollection);
m_shortName = summaryCaseCollection->uniqueShortNameForCase(this);
updateTreeItemName();
}
else if (m_shortName() == QString("Display Name"))
{
m_shortName = caseName();
updateTreeItemName();
}
}

View File

@@ -0,0 +1,63 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
#include "cafPdmField.h"
#include "cvfObject.h"
#include "cafPdmPtrField.h"
class RigSummaryCaseData;
//==================================================================================================
//
//
//
//==================================================================================================
class RimSummaryCase : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryCase();
virtual ~RimSummaryCase();
virtual QString summaryHeaderFilename() const = 0;
virtual QString caseName() const = 0;
QString shortName() const;
void updateAutoShortName();
void updateOptionSensitivity();
void loadCase();
RigSummaryCaseData* caseData();
protected:
void updateTreeItemName();
caf::PdmField<QString> m_shortName;
caf::PdmField<bool> m_useAutoShortName;
cvf::ref<RigSummaryCaseData> m_summaryCaseData;
private:
// Overridden PDM methods
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
virtual void initAfterRead() override;
};

View File

@@ -0,0 +1,212 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCaseCollection.h"
#include "RimSummaryCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimEclipseResultCase.h"
#include "RimGridSummaryCase.h"
#include "RifEclipseSummaryTools.h"
#include <QDir>
#include "RimFileSummaryCase.h"
CAF_PDM_SOURCE_INIT(RimSummaryCaseCollection,"SummaryCaseCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection::RimSummaryCaseCollection()
{
CAF_PDM_InitObject("Summary Cases",":/Cases16x16.png","","");
CAF_PDM_InitFieldNoDefault(&m_cases,"SummaryCases","","","","");
m_cases.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection::~RimSummaryCaseCollection()
{
m_cases.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::createSummaryCasesFromRelevantEclipseResultCases()
{
RimProject* proj = nullptr;
firstAncestorOrThisOfType(proj);
if (proj)
{
std::vector<RimCase*> all3DCases;
proj->allCases(all3DCases);
for (RimCase* aCase: all3DCases)
{
RimEclipseResultCase* eclResCase = dynamic_cast<RimEclipseResultCase*>(aCase);
if (eclResCase)
{
// If we have no summary case corresponding to this eclipse case,
// try to create one.
bool isFound = false;
for (size_t scIdx = 0; scIdx < m_cases.size(); ++scIdx)
{
RimGridSummaryCase* grdSumCase = dynamic_cast<RimGridSummaryCase*>(m_cases[scIdx]);
if (grdSumCase)
{
if (grdSumCase->associatedEclipseCase() == eclResCase)
{
isFound = true;
break;
}
}
}
if (!isFound)
{
// Create new GridSummaryCase
createAndAddSummaryCaseFromEclipseResultCase(eclResCase);
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimSummaryCaseCollection::summaryCase(size_t idx)
{
return m_cases[idx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimSummaryCaseCollection::summaryCaseCount()
{
return m_cases.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::loadAllSummaryCaseData()
{
for (RimSummaryCase* sumCase: m_cases)
{
if (sumCase) sumCase->loadCase();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimSummaryCaseCollection::createAndAddSummaryCaseFromEclipseResultCase(RimEclipseResultCase* eclResCase)
{
QString gridFileName = eclResCase->gridFileName();
if(RifEclipseSummaryTools::hasSummaryFiles(QDir::toNativeSeparators(gridFileName).toStdString()))
{
RimGridSummaryCase* newSumCase = new RimGridSummaryCase();
this->m_cases.push_back(newSumCase);
newSumCase->setAssociatedEclipseCase(eclResCase);
newSumCase->updateOptionSensitivity();
return newSumCase;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimSummaryCaseCollection::createAndAddSummaryCaseFromFileName(const QString& fileName)
{
RimFileSummaryCase* newSumCase = new RimFileSummaryCase();
this->m_cases.push_back(newSumCase);
newSumCase->setSummaryHeaderFilename(fileName);
newSumCase->updateOptionSensitivity();
return newSumCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryCaseCollection::uniqueShortNameForCase(RimSummaryCase* summaryCase)
{
std::set<QString> allAutoShortNames;
for (RimSummaryCase* sumCase : m_cases)
{
if (sumCase && sumCase != summaryCase)
{
allAutoShortNames.insert(sumCase->shortName());
}
}
bool foundUnique = false;
QString caseName = summaryCase->caseName();
QString shortName;
if (caseName.size() > 2)
{
QString candidate;
candidate += caseName[0];
for (int i = 1; i < caseName.size(); ++i )
{
if (allAutoShortNames.count(candidate + caseName[i]) == 0)
{
shortName = candidate + caseName[i];
foundUnique = true;
break;
}
}
}
else
{
shortName = caseName.left(2);
if(allAutoShortNames.count(shortName) == 0)
{
foundUnique = true;
}
}
QString candidate = shortName;
int autoNumber = 0;
while (!foundUnique)
{
candidate = shortName + QString::number(autoNumber++);
if(allAutoShortNames.count(candidate) == 0)
{
shortName = candidate;
foundUnique = true;
}
}
return shortName;
}

View File

@@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
class RimSummaryCase;
class RimEclipseResultCase;
class RimSummaryCaseCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryCaseCollection();
virtual ~RimSummaryCaseCollection();
RimSummaryCase* summaryCase(size_t idx);
size_t summaryCaseCount();
void createSummaryCasesFromRelevantEclipseResultCases();
RimSummaryCase* createAndAddSummaryCaseFromEclipseResultCase(RimEclipseResultCase* eclResCase);
RimSummaryCase* createAndAddSummaryCaseFromFileName(const QString& fileName);
void loadAllSummaryCaseData();
QString uniqueShortNameForCase(RimSummaryCase* summaryCase);
private:
caf::PdmChildArrayField<RimSummaryCase*> m_cases;
};

View File

@@ -0,0 +1,532 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCurve.h"
#include "RiaApplication.h"
#include "RifReaderEclipseSummary.h"
#include "RigSummaryCaseData.h"
#include "RimDefines.h"
#include "RimEclipseResultCase.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCurveFilter.h"
#include "RimSummaryFilter.h"
#include "RimSummaryPlot.h"
#include "RiuLineSegmentQwtPlotCurve.h"
#include "RiuSummaryQwtPlot.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "qwt_date.h"
CAF_PDM_SOURCE_INIT(RimSummaryAddress, "SummaryAddress");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryAddress::RimSummaryAddress()
{
CAF_PDM_InitFieldNoDefault(&m_category, "SummaryVarType", "Type", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_quantityName, "SummaryQuantityName", "Quantity", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_regionNumber, "SummaryRegion", "Region", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_regionNumber2, "SummaryRegion2", "Region2", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellGroupName, "SummaryWellGroup", "Group", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellName, "SummaryWell", "Well", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellSegmentNumber, "SummaryWellSegment", "Well Segment", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_lgrName, "SummaryLgr", "Grid", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_cellI, "SummaryCellI", "I", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_cellJ, "SummaryCellJ", "J", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_cellK, "SummaryCellK", "K", "", "", "");
m_category = RifEclipseSummaryAddress::SUMMARY_INVALID;
m_regionNumber = m_regionNumber2 = m_wellSegmentNumber = m_cellI = m_cellJ = m_cellK = -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryAddress::~RimSummaryAddress()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryAddress::setAddress(const RifEclipseSummaryAddress& addr)
{
m_category = addr.category();
m_quantityName = addr.quantityName().c_str();
m_regionNumber = addr.regionNumber();
m_regionNumber2 = addr.regionNumber2();
m_wellGroupName = addr.wellGroupName().c_str();
m_wellName = addr.wellName().c_str();
m_wellSegmentNumber = addr.wellSegmentNumber();
m_lgrName = addr.lgrName().c_str();
m_cellI = addr.cellI(); m_cellJ = addr.cellJ(); m_cellK = addr.cellK();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RimSummaryAddress::address()
{
return RifEclipseSummaryAddress( m_category(),
m_quantityName().toStdString(),
m_regionNumber(),
m_regionNumber2(),
m_wellGroupName().toStdString(),
m_wellName().toStdString(),
m_wellSegmentNumber(),
m_lgrName().toStdString(),
m_cellI(), m_cellJ(), m_cellK());
}
namespace caf
{
template<>
void caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>::setUp()
{
addItem(RifEclipseSummaryAddress::SUMMARY_FIELD, "SUMMARY_FIELD", "Field");
addItem(RifEclipseSummaryAddress::SUMMARY_AQUIFER, "SUMMARY_AQUIFER", "Aquifer");
addItem(RifEclipseSummaryAddress::SUMMARY_NETWORK, "SUMMARY_NETWORK", "Network");
addItem(RifEclipseSummaryAddress::SUMMARY_MISC, "SUMMARY_MISC", "Misc");
addItem(RifEclipseSummaryAddress::SUMMARY_REGION, "SUMMARY_REGION", "Region");
addItem(RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION, "SUMMARY_REGION_2_REGION", "Region-Region");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, "SUMMARY_WELL_GROUP", "Group");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL, "SUMMARY_WELL", "Well");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION, "SUMMARY_WELL_COMPLETION", "Completion");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR, "SUMMARY_WELL_COMPLETION_LGR", "Lgr-Completion");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL_LGR, "SUMMARY_WELL_LGR", "Lgr-Well");
addItem(RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT, "SUMMARY_SEGMENT", "Segment");
addItem(RifEclipseSummaryAddress::SUMMARY_BLOCK, "SUMMARY_BLOCK", "Block");
addItem(RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR, "SUMMARY_BLOCK_LGR", "Lgr-Block");
setDefault(RifEclipseSummaryAddress::SUMMARY_FIELD);
}
}
CAF_PDM_SOURCE_INIT(RimSummaryCurve, "SummaryCurve");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurve::RimSummaryCurve()
{
CAF_PDM_InitObject("Summary Curve", ":/SummaryCurve16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_summaryCase, "SummaryCase", "Case", "", "", "");
m_summaryCase.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_selectedVariableDisplayField, "SelectedVariableDisplayVar", "Vector", "", "", "");
m_selectedVariableDisplayField.xmlCapability()->setIOWritable(false);
m_selectedVariableDisplayField.xmlCapability()->setIOReadable(false);
m_selectedVariableDisplayField.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitFieldNoDefault(&m_summaryFilter, "VarListFilter", "Filter", "", "", "");
m_summaryFilter.xmlCapability()->setIOWritable(false);
m_summaryFilter.xmlCapability()->setIOReadable(false);
m_summaryFilter.uiCapability()->setUiTreeChildrenHidden(true);
m_summaryFilter.uiCapability()->setUiHidden(true);
m_summaryFilter = new RimSummaryFilter();
CAF_PDM_InitFieldNoDefault(&m_uiFilterResultSelection, "FilterResultSelection", "Filter Result", "", "", "");
m_uiFilterResultSelection.xmlCapability()->setIOWritable(false);
m_uiFilterResultSelection.xmlCapability()->setIOReadable(false);
m_uiFilterResultSelection.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_uiFilterResultSelection.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_uiFilterResultSelection.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_curveVariable, "SummaryAddress", "SummaryAddress", "", "", "");
m_curveVariable.uiCapability()->setUiHidden(true);
m_curveVariable.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_plotAxis, "PlotAxis", "Axis", "", "", "");
m_curveVariable = new RimSummaryAddress;
// Add some space before name to indicate these belong to the Auto Name field
CAF_PDM_InitField(&m_addCaseNameToCurveName, "AddCaseNameToCurveName", true, " Case Name", "", "", "");
m_symbolSkipPixelDistance = 10.0f;
m_curveThickness = 2;
updateOptionSensitivity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurve::~RimSummaryCurve()
{
delete m_curveVariable();
delete m_summaryFilter();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setSummaryCase(RimSummaryCase* sumCase)
{
m_summaryCase = sumCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimSummaryCurve::summaryCase()
{
return m_summaryCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setVariable(QString varName)
{
m_curveVariable->setAddress(RifEclipseSummaryAddress::fieldVarAddress(varName.toStdString()));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RimSummaryCurve::summaryAddress()
{
return m_curveVariable->address();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setSummaryAddress(const RifEclipseSummaryAddress& address)
{
m_curveVariable->setAddress(address);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RimSummaryCurve::unitName()
{
RifReaderEclipseSummary* reader = summaryReader();
if (reader) return reader->unitName(this->summaryAddress());
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimSummaryCurve::yPlotValues() const
{
std::vector<QDateTime> dateTimes;
std::vector<double> values;
this->curveData(&dateTimes, &values);
return values;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setPlotAxis(RimDefines::PlotAxis plotAxis)
{
m_plotAxis = plotAxis;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDefines::PlotAxis RimSummaryCurve::associatedPlotAxis() const
{
return m_plotAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSummaryCurve::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> optionList = this->RimPlotCurve::calculateValueOptions(fieldNeedingOptions,useOptionsOnly);
if (!optionList.isEmpty()) return optionList;
if (fieldNeedingOptions == &m_summaryCase)
{
RimProject* proj = RiaApplication::instance()->project();
std::vector<RimSummaryCase*> cases;
proj->allSummaryCases(cases);
for (size_t i = 0; i < cases.size(); i++)
{
RimSummaryCase* rimCase = cases[i];
optionList.push_back(caf::PdmOptionItemInfo(rimCase->caseName(), QVariant::fromValue(caf::PdmPointer<caf::PdmObjectHandle>(rimCase))));
}
if (optionList.size() > 0)
{
optionList.push_front(caf::PdmOptionItemInfo("None", QVariant::fromValue(caf::PdmPointer<caf::PdmObjectHandle>(NULL))));
}
}
else if(fieldNeedingOptions == &m_uiFilterResultSelection)
{
if(m_summaryCase)
{
RifReaderEclipseSummary* reader = summaryReader();
int addressCount = 0;
if(reader)
{
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
addressCount = static_cast<int>(allAddresses.size());
std::map<RifEclipseSummaryAddress, int> addrToIdxMap;
for(int i = 0; i <addressCount; i++)
{
if (!m_summaryFilter->isIncludedByFilter(allAddresses[i] )) continue;
addrToIdxMap[allAddresses[i]] = i;
}
for (const auto& addrIntPair: addrToIdxMap)
{
std::string name = addrIntPair.first.uiText();
QString s = QString::fromStdString(name);
optionList.push_back(caf::PdmOptionItemInfo(s, addrIntPair.second));
}
}
optionList.push_front(caf::PdmOptionItemInfo(RimDefines::undefinedResultName(), addressCount));
if(useOptionsOnly) *useOptionsOnly = true;
}
}
return optionList;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryCurve::createCurveAutoName()
{
QString generatedCurveName = QString::fromStdString( m_curveVariable->address().uiText()) + "["+ this->unitName().c_str() + "]";
if (m_addCaseNameToCurveName && m_summaryCase())
{
if (!generatedCurveName.isEmpty())
{
generatedCurveName += ", ";
}
generatedCurveName += m_summaryCase->shortName();
}
return generatedCurveName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::updateZoomInParentPlot()
{
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfType(plot);
plot->updateZoomInQwt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::onLoadDataAndUpdate()
{
this->RimPlotCurve::updateCurvePresentation();
m_selectedVariableDisplayField = QString::fromStdString(m_curveVariable->address().uiText());
if (isCurveVisible())
{
std::vector<QDateTime> dateTimes;
std::vector<double> values;
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfType(plot);
bool isLogCurve = plot->isLogarithmicScaleEnabled(this->associatedPlotAxis());
if(this->curveData(&dateTimes, &values))
{
m_qwtPlotCurve->setSamplesFromDateAndValues(dateTimes, values, isLogCurve);
}
else
{
m_qwtPlotCurve->setSamplesFromDateAndValues(std::vector<QDateTime>(), std::vector<double>(), isLogCurve);
}
updateZoomInParentPlot();
if (m_parentQwtPlot) m_parentQwtPlot->replot();
}
updateQwtPlotAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup("Summary Vector");
curveDataGroup->add(&m_summaryCase);
curveDataGroup->add(&m_selectedVariableDisplayField);
caf::PdmUiGroup* curveVarSelectionGroup = curveDataGroup->addNewGroup("Vector Selection");
m_summaryFilter->defineUiOrdering(uiConfigName, *curveVarSelectionGroup);
curveVarSelectionGroup->add(&m_uiFilterResultSelection);
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance");
appearanceGroup->add(&m_curveColor);
appearanceGroup->add(&m_curveThickness);
appearanceGroup->add(&m_pointSymbol);
appearanceGroup->add(&m_symbolSkipPixelDistance);
appearanceGroup->add(&m_lineStyle);
appearanceGroup->add(&m_curveName);
appearanceGroup->add(&m_isUsingAutoName);
if (m_isUsingAutoName)
{
appearanceGroup->add(&m_addCaseNameToCurveName);
}
uiOrdering.add(&m_plotAxis);
uiOrdering.setForgetRemainingFields(true); // For now.
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::updateQwtPlotAxis()
{
if (m_qwtPlotCurve)
{
if (this->associatedPlotAxis() == RimDefines::PLOT_AXIS_LEFT)
{
m_qwtPlotCurve->setYAxis(QwtPlot::yLeft);
}
else
{
m_qwtPlotCurve->setYAxis(QwtPlot::yRight);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
this->RimPlotCurve::fieldChangedByUi(changedField,oldValue,newValue);
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfType(plot);
CVF_ASSERT(plot);
if(changedField == &m_uiFilterResultSelection)
{
if (0 <= m_uiFilterResultSelection() && static_cast<size_t>(m_uiFilterResultSelection()) < summaryReader()->allResultAddresses().size())
{
m_curveVariable->setAddress(summaryReader()->allResultAddresses()[m_uiFilterResultSelection()]);
}
else
{
m_curveVariable->setAddress(RifEclipseSummaryAddress());
}
this->loadDataAndUpdate();
plot->updateAxes();
}
else if (&m_showCurve == changedField)
{
plot->updateAxes();
}
else if (changedField == &m_addCaseNameToCurveName)
{
this->uiCapability()->updateConnectedEditors();
updateCurveName();
}
else if (changedField == &m_plotAxis)
{
updateQwtPlotAxis();
plot->updateAxes();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseSummary* RimSummaryCurve::summaryReader() const
{
if (!m_summaryCase()) return nullptr;
if (!m_summaryCase->caseData()) return nullptr;
return m_summaryCase()->caseData()->summaryReader();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCurve::curveData(std::vector<QDateTime>* timeSteps, std::vector<double>* values) const
{
CVF_ASSERT(timeSteps && values);
RifReaderEclipseSummary* reader = summaryReader();
if (!reader) return false;
std::vector<time_t> times = reader->timeSteps();
*timeSteps = RifReaderEclipseSummary::fromTimeT(times);
if (!times.size()) return false;
RifEclipseSummaryAddress addr = m_curveVariable()->address();
return reader->values(addr, values);
}

View File

@@ -0,0 +1,121 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cafPdmPtrField.h"
#include "cafPdmChildField.h"
#include "RifEclipseSummaryAddress.h"
#include "RimDefines.h"
#include "RimPlotCurve.h"
#include "cafAppEnum.h"
class RifReaderEclipseSummary;
class RimSummaryCase;
class RimSummaryFilter;
class RiuLineSegmentQwtPlotCurve;
class RimSummaryAddress: public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryAddress();;
virtual ~RimSummaryAddress();
void setAddress(const RifEclipseSummaryAddress& addr);
RifEclipseSummaryAddress address();
private:
caf::PdmField<caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory> >
m_category;
caf::PdmField<QString> m_quantityName;
caf::PdmField<int> m_regionNumber;
caf::PdmField<int> m_regionNumber2;
caf::PdmField<QString> m_wellGroupName;
caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_wellSegmentNumber;
caf::PdmField<QString> m_lgrName;
caf::PdmField<int> m_cellI;
caf::PdmField<int> m_cellJ;
caf::PdmField<int> m_cellK;
};
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryCurve : public RimPlotCurve
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryCurve();
virtual ~RimSummaryCurve();
void setSummaryCase(RimSummaryCase* sumCase);
RimSummaryCase* summaryCase();
void setVariable(QString varName);
RifEclipseSummaryAddress summaryAddress();
void setSummaryAddress(const RifEclipseSummaryAddress& address);
std::string unitName();
std::vector<double> yPlotValues() const;
void setPlotAxis(RimDefines::PlotAxis plotAxis);
RimDefines::PlotAxis associatedPlotAxis() const;
void updateQwtPlotAxis();
protected:
// RimPlotCurve overrides
virtual QString createCurveAutoName() override;
virtual void updateZoomInParentPlot() override;
virtual void onLoadDataAndUpdate() override;
private:
RifReaderEclipseSummary* summaryReader() const;
bool curveData(std::vector<QDateTime>* timeSteps, std::vector<double>* values) const;
// Overridden PDM methods
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "");
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly);
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
private:
// Fields
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmChildField<RimSummaryAddress*> m_curveVariable;
caf::PdmField<QString> m_selectedVariableDisplayField;
caf::PdmField<bool> m_addCaseNameToCurveName;
caf::PdmField< caf::AppEnum< RimDefines::PlotAxis > > m_plotAxis;
// Filter fields
caf::PdmChildField<RimSummaryFilter*> m_summaryFilter;
caf::PdmField<int> m_uiFilterResultSelection;
};

View File

@@ -0,0 +1,468 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCurveAppearanceCalculator.h"
#include "RimSummaryCurve.h"
#include "cvfVector3.h"
#include <cmath>
namespace caf
{
template<>
void caf::AppEnum< RimSummaryCurveAppearanceCalculator::CurveAppearanceType >::setUp()
{
addItem(RimSummaryCurveAppearanceCalculator::NONE, "NONE", "None");
addItem(RimSummaryCurveAppearanceCalculator::COLOR, "COLOR", "Color");
addItem(RimSummaryCurveAppearanceCalculator::SYMBOL, "SYMBOL", "Symbols");
addItem(RimSummaryCurveAppearanceCalculator::LINE_STYLE, "LINE_STYLE", "Line Style");
addItem(RimSummaryCurveAppearanceCalculator::GRADIENT, "GRADIENT", "Gradient");
addItem(RimSummaryCurveAppearanceCalculator::LINE_THICKNESS, "LINE_THICKNESS", "Line Thickness");
setDefault(RimSummaryCurveAppearanceCalculator::NONE);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurveAppearanceCalculator::RimSummaryCurveAppearanceCalculator(const std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >& curveDefinitions)
{
for(const std::pair<RimSummaryCase*, RifEclipseSummaryAddress>& curveDef : curveDefinitions)
{
if(curveDef.first) m_caseToAppearanceIdxMap[curveDef.first] = -1;
if(!curveDef.second.wellName().empty()) m_welToAppearanceIdxMap[curveDef.second.wellName()] = -1;
if(!curveDef.second.wellGroupName().empty()) m_grpToAppearanceIdxMap[curveDef.second.wellGroupName()] = -1;
if(!(curveDef.second.regionNumber() == -1)) m_regToAppearanceIdxMap[curveDef.second.regionNumber()] = -1;
if(!curveDef.second.quantityName().empty())
{
std::string varname = curveDef.second.quantityName();
m_varToAppearanceIdxMap[varname] = -1;
// Indexes for sub color ranges
char secondChar = 0;
if(varname.size() > 1)
{
secondChar = varname[1];
if ( secondChar != 'W'
&& secondChar != 'O'
&& secondChar != 'G'
&& secondChar != 'V')
{
secondChar = 0; // Consider all others as one group for coloring
}
}
m_secondCharToVarToAppearanceIdxMap[secondChar][varname] = -1;
}
}
m_caseCount = m_caseToAppearanceIdxMap.size();
m_variableCount = m_varToAppearanceIdxMap .size();
m_wellCount = m_welToAppearanceIdxMap .size();
m_groupCount = m_grpToAppearanceIdxMap .size();
m_regionCount = m_regToAppearanceIdxMap .size();
// Select the default appearance type for each data "dimension"
m_caseAppearanceType = NONE;
m_varAppearanceType = NONE;
m_wellAppearanceType = NONE;
m_groupAppearanceType = NONE;
m_regionAppearanceType = NONE;
std::set<RimSummaryCurveAppearanceCalculator::CurveAppearanceType> unusedAppearTypes;
unusedAppearTypes.insert(COLOR);
unusedAppearTypes.insert(GRADIENT);
unusedAppearTypes.insert(LINE_STYLE);
unusedAppearTypes.insert(SYMBOL);
unusedAppearTypes.insert(LINE_THICKNESS);
m_dimensionCount = 0;
if(m_variableCount > 1) { m_varAppearanceType = *(unusedAppearTypes.begin()); unusedAppearTypes.erase(unusedAppearTypes.begin()); m_dimensionCount++; }
if(m_caseCount > 1) { m_caseAppearanceType = *(unusedAppearTypes.begin()); unusedAppearTypes.erase(unusedAppearTypes.begin()); m_dimensionCount++; }
if(m_wellCount > 1) { m_wellAppearanceType = *(unusedAppearTypes.begin()); unusedAppearTypes.erase(unusedAppearTypes.begin()); m_dimensionCount++; }
if(m_groupCount > 1) { m_groupAppearanceType = *(unusedAppearTypes.begin()); unusedAppearTypes.erase(unusedAppearTypes.begin()); m_dimensionCount++; }
if(m_regionCount > 1) { m_regionAppearanceType = *(unusedAppearTypes.begin()); unusedAppearTypes.erase(unusedAppearTypes.begin()); m_dimensionCount++; }
if (m_dimensionCount == 0) m_varAppearanceType = COLOR; // basically one curve
// Assign increasing indexes
{ int idx = 0; for(auto& pair : m_caseToAppearanceIdxMap) pair.second = idx++; }
{ int idx = 0; for(auto& pair : m_varToAppearanceIdxMap) pair.second = idx++; }
{ int idx = 0; for(auto& pair : m_welToAppearanceIdxMap) pair.second = idx++; }
{ int idx = 0; for(auto& pair : m_grpToAppearanceIdxMap) pair.second = idx++; }
{ int idx = 0; for(auto& pair : m_regToAppearanceIdxMap) pair.second = idx++; }
for (auto& charMapPair : m_secondCharToVarToAppearanceIdxMap)
{ int idx = 0; for(auto& pair : charMapPair.second) pair.second = idx++; }
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveAppearanceCalculator::assignDimensions( CurveAppearanceType caseAppearance,
CurveAppearanceType variAppearance,
CurveAppearanceType wellAppearance,
CurveAppearanceType gropAppearance,
CurveAppearanceType regiAppearance)
{
m_caseAppearanceType = caseAppearance;
m_varAppearanceType = variAppearance;
m_wellAppearanceType = wellAppearance;
m_groupAppearanceType = gropAppearance;
m_regionAppearanceType = regiAppearance;
// Update the dimensionCount
m_dimensionCount = 0;
if(m_caseAppearanceType != NONE) ++m_dimensionCount;
if(m_varAppearanceType != NONE) ++m_dimensionCount;
if(m_wellAppearanceType != NONE) ++m_dimensionCount;
if(m_groupAppearanceType != NONE) ++m_dimensionCount;
if(m_regionAppearanceType != NONE) ++m_dimensionCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveAppearanceCalculator::getDimensions(CurveAppearanceType* caseAppearance,
CurveAppearanceType* variAppearance,
CurveAppearanceType* wellAppearance,
CurveAppearanceType* gropAppearance,
CurveAppearanceType* regiAppearance) const
{
*caseAppearance = m_caseAppearanceType ;
*variAppearance = m_varAppearanceType ;
*wellAppearance = m_wellAppearanceType ;
*gropAppearance = m_groupAppearanceType ;
*regiAppearance = m_regionAppearanceType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveAppearanceCalculator::setupCurveLook(RimSummaryCurve* curve)
{
m_currentCurveBaseColor = cvf::Color3f(0, 0, 0);
m_currentCurveGradient = 0.0f;
int caseAppearanceIdx = m_caseToAppearanceIdxMap[curve->summaryCase()];
int varAppearanceIdx = m_varToAppearanceIdxMap[curve->summaryAddress().quantityName()];
int welAppearanceIdx = m_welToAppearanceIdxMap[curve->summaryAddress().wellName()];
int grpAppearanceIdx = m_grpToAppearanceIdxMap[curve->summaryAddress().wellGroupName()];
int regAppearanceIdx = m_regToAppearanceIdxMap[curve->summaryAddress().regionNumber()];
// Remove index for curves without value at the specific dimension
if(curve->summaryAddress().wellName().empty()) welAppearanceIdx = -1;
if(curve->summaryAddress().wellGroupName().empty()) grpAppearanceIdx = -1;
if(curve->summaryAddress().regionNumber() < 0) regAppearanceIdx = -1;
setOneCurveAppearance(m_caseAppearanceType, m_caseCount, caseAppearanceIdx, curve);
setOneCurveAppearance(m_wellAppearanceType, m_wellCount, welAppearanceIdx, curve);
setOneCurveAppearance(m_groupAppearanceType, m_groupCount, grpAppearanceIdx, curve);
setOneCurveAppearance(m_regionAppearanceType, m_regionCount, regAppearanceIdx, curve);
if (m_varAppearanceType == COLOR && m_secondCharToVarToAppearanceIdxMap.size() > 1)
{
int subColorIndex = -1;
char secondChar = 0;
std::string varname = curve->summaryAddress().quantityName();
if (varname.size() > 1) secondChar = varname[1];
subColorIndex = m_secondCharToVarToAppearanceIdxMap[secondChar][varname];
if (secondChar == 'W')
{
// Pick blue
m_currentCurveBaseColor = cycledBlueColor(subColorIndex);
}
else if (secondChar == 'O')
{
// Pick Green
m_currentCurveBaseColor = cycledGreenColor(subColorIndex);
}
else if (secondChar == 'G')
{
// Pick Red
m_currentCurveBaseColor = cycledRedColor(subColorIndex);
}
else if(secondChar == 'V')
{
// Pick Brown
m_currentCurveBaseColor = cycledBrownColor(subColorIndex);
}
else
{
m_currentCurveBaseColor = cycledNoneRGBBrColor(subColorIndex);
}
}
else
{
setOneCurveAppearance(m_varAppearanceType, m_variableCount, varAppearanceIdx, curve);
}
curve->setColor(gradeColor(m_currentCurveBaseColor, m_currentCurveGradient));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveAppearanceCalculator::setOneCurveAppearance(CurveAppearanceType appeaType, size_t totalCount, int appeaIdx, RimSummaryCurve* curve)
{
switch(appeaType)
{
case NONE:
break;
case COLOR:
m_currentCurveBaseColor = cycledPaletteColor(appeaIdx);
break;
case GRADIENT:
m_currentCurveGradient = gradient(totalCount, appeaIdx);
break;
case LINE_STYLE:
curve->setLineStyle(cycledLineStyle(appeaIdx));
break;
case SYMBOL:
curve->setSymbol(cycledSymbol(appeaIdx));
break;
case LINE_THICKNESS:
curve->setLineThickness(cycledLineThickness(appeaIdx));
break;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledPaletteColor(int colorIndex)
{
if (colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 15;
static const cvf::ubyte colorData[][3] =
{
{ 0, 112, 136 }, // Dark Green-Blue
{ 202, 0, 0 }, // Red
{ 78, 204, 0 }, // Clear Green
{ 236, 118, 0 }, // Orange
{ 0 , 0, 0 }, // Black
{ 56, 56, 255 }, // Vivid Blue
{ 248, 0, 170 }, // Magenta
{ 169, 2, 240 }, // Purple
{ 0, 221, 221 }, // Turquoise
{ 201, 168, 206 }, // Light Violet
{ 0, 205, 68 }, // Bluish Green
{ 236, 188, 0 }, // Mid Yellow
{ 51, 204, 255 }, // Bluer Turquoise
{ 164, 193, 0 }, // Mid Yellowish Green
{ 0, 143, 239 }, // Dark Light Blue
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledNoneRGBBrColor(int colorIndex)
{
if(colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 7;
static const cvf::ubyte colorData[][3] =
{
{ 236, 118, 0 }, // Orange
{ 0 , 0, 0 }, // Black
{ 248, 0, 170 }, // Magenta
{ 236, 188, 0 }, // Mid Yellow
{ 169, 2, 240 }, // Purple
{ 0, 221, 221 }, // Turquoise
{ 201, 168, 206 }, // Light Violet
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledGreenColor(int colorIndex)
{
if(colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 3;
static const cvf::ubyte colorData[][3] =
{
{ 78, 204, 0 }, // Clear Green
{ 164, 193, 0 }, // Mid Yellowish Green
{ 0, 205, 68 } // Bluish Green
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledBlueColor(int colorIndex)
{
if(colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 3;
static const cvf::ubyte colorData[][3] =
{
{ 56, 56, 255 }, // Vivid Blue
{ 0, 143, 239 }, // Dark Light Blue
{ 153, 153, 255 }, // Off Light Blue
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledRedColor(int colorIndex)
{
if(colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 3;
static const cvf::ubyte colorData[][3] =
{
{ 202, 0, 0 }, // Off Red
{ 255, 51, 51}, // Bright Red
{ 255, 102, 102 } // Light Red
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledBrownColor(int colorIndex)
{
if(colorIndex < 0) return cvf::Color3f::BLACK;
static const int colorCount = 3;
static const cvf::ubyte colorData[][3] =
{
{186, 101, 44},
{ 99, 53, 23 }, // Highway Brown
{ 103, 56, 24} // Dark Brown
};
int paletteIdx = colorIndex % colorCount;
cvf::Color3ub ubColor(colorData[paletteIdx][0], colorData[paletteIdx][1], colorData[paletteIdx][2]);
cvf::Color3f cvfColor(ubColor);
return cvfColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPlotCurve::LineStyleEnum RimSummaryCurveAppearanceCalculator::cycledLineStyle(int index)
{
if (index < 0) return RimPlotCurve::STYLE_SOLID;
return caf::AppEnum<RimPlotCurve::LineStyleEnum>::fromIndex(1 + (index % (caf::AppEnum<RimPlotCurve::LineStyleEnum>::size() - 1)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPlotCurve::PointSymbolEnum RimSummaryCurveAppearanceCalculator::cycledSymbol(int index)
{
if (index < 0) return RimPlotCurve::SYMBOL_NONE;
return caf::AppEnum<RimPlotCurve::PointSymbolEnum>::fromIndex(1 + (index % (caf::AppEnum<RimPlotCurve::PointSymbolEnum>::size() - 1)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSummaryCurveAppearanceCalculator::cycledLineThickness(int index)
{
static const int thicknessCount = 3;
static const int thicknesses[] ={ 1, 3, 5 };
if (index < 0) return 1;
return (thicknesses[(index) % 3]);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RimSummaryCurveAppearanceCalculator::gradient(size_t totalCount, int index)
{
if(totalCount == 1 || index < 0) return 0.0f;
const float darkLimit = -0.45f;
const float lightLimit = 0.7f;
float totalSpan = lightLimit - darkLimit;
float step = totalSpan / (totalCount -1);
return darkLimit + (index * step);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::gradeColor(const cvf::Color3f& color, float factor)
{
CVF_ASSERT(-1.0 <= factor && factor <= 1.0);
cvf::Vec3f orgC(color.r(), color.g(), color.b());
cvf::Vec3f targetC;
if(factor < 0)
{
targetC = cvf::Vec3f(0, 0, 0);
}
else
{
targetC = cvf::Vec3f(1, 1, 1);
}
cvf::Vec3f newColor = ((float)fabs(factor)) * (targetC - orgC) + orgC;
return cvf::Color3f(newColor[0], newColor[1], newColor[2]);
}

View File

@@ -0,0 +1,101 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cvfBase.h"
#include "cvfColor3.h"
#include <set>
#include "RifEclipseSummaryAddress.h"
#include "RimPlotCurve.h"
class RimSummaryCurve;
class RimSummaryCase;
class RimSummaryCurveAppearanceCalculator
{
public:
RimSummaryCurveAppearanceCalculator(const std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >& curveDefinitions);
enum CurveAppearanceType
{
NONE,
COLOR,
SYMBOL,
LINE_STYLE,
GRADIENT,
LINE_THICKNESS
};
void assignDimensions(CurveAppearanceType caseAppearance,
CurveAppearanceType variAppearance,
CurveAppearanceType wellAppearance,
CurveAppearanceType gropAppearance,
CurveAppearanceType regiAppearance);
void getDimensions(CurveAppearanceType* caseAppearance,
CurveAppearanceType* variAppearance,
CurveAppearanceType* wellAppearance,
CurveAppearanceType* gropAppearance,
CurveAppearanceType* regiAppearance) const;
void setupCurveLook(RimSummaryCurve* curve);
private:
void setOneCurveAppearance(CurveAppearanceType appeaType, size_t totalCount, int appeaIdx, RimSummaryCurve* curve);
cvf::Color3f cycledPaletteColor(int colorIndex);
cvf::Color3f cycledNoneRGBBrColor(int colorIndex);
cvf::Color3f cycledGreenColor(int colorIndex);
cvf::Color3f cycledBlueColor(int colorIndex);
cvf::Color3f cycledRedColor(int colorIndex);
cvf::Color3f cycledBrownColor(int colorIndex);
RimPlotCurve::LineStyleEnum cycledLineStyle(int index);
RimPlotCurve::PointSymbolEnum cycledSymbol(int index);
int cycledLineThickness(int index);
float gradient(size_t totalCount, int index);
cvf::Color3f gradeColor(const cvf::Color3f& color , float factor);
cvf::Color3f m_currentCurveBaseColor;
float m_currentCurveGradient;
size_t m_caseCount;
size_t m_variableCount;
size_t m_wellCount;
size_t m_groupCount;
size_t m_regionCount;
int m_dimensionCount;
CurveAppearanceType m_caseAppearanceType;
CurveAppearanceType m_varAppearanceType;
CurveAppearanceType m_wellAppearanceType;
CurveAppearanceType m_groupAppearanceType;
CurveAppearanceType m_regionAppearanceType;
std::map<RimSummaryCase*, int> m_caseToAppearanceIdxMap;
std::map<std::string , int> m_varToAppearanceIdxMap;
std::map<std::string , int> m_welToAppearanceIdxMap;
std::map<std::string , int> m_grpToAppearanceIdxMap;
std::map<int , int> m_regToAppearanceIdxMap;
std::map<char, std::map< std::string, int> > m_secondCharToVarToAppearanceIdxMap;
};

View File

@@ -0,0 +1,609 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCurveFilter.h"
#include "RiaApplication.h"
#include "RifReaderEclipseSummary.h"
#include "RigSummaryCaseData.h"
#include "RimDefines.h"
#include "RimEclipseResultCase.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveAppearanceCalculator.h"
#include "RimSummaryFilter.h"
#include "RimSummaryPlot.h"
#include "RimSummaryPlotCollection.h"
#include "RiuLineSegmentQwtPlotCurve.h"
#include "RiuSummaryQwtPlot.h"
#include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPushButtonEditor.h"
QTextStream& operator << (QTextStream& str, const std::vector<RifEclipseSummaryAddress>& sobj)
{
CVF_ASSERT(false);
return str;
}
QTextStream& operator >> (QTextStream& str, std::vector<RifEclipseSummaryAddress>& sobj)
{
CVF_ASSERT(false);
return str;
}
CAF_PDM_SOURCE_INIT(RimSummaryCurveFilter, "SummaryCurveFilter");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurveFilter::RimSummaryCurveFilter()
{
CAF_PDM_InitObject("Curve Filter", ":/SummaryCurveFilter16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_selectedSummaryCases, "SummaryCases", "Cases", "", "", "");
m_selectedSummaryCases.uiCapability()->setUiTreeChildrenHidden(true);
m_selectedSummaryCases.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_selectedSummaryCases.uiCapability()->setAutoAddingOptionFromValue(false);
m_selectedSummaryCases.xmlCapability()->setIOWritable(false);
m_selectedSummaryCases.xmlCapability()->setIOReadable(false);
m_selectedSummaryCases.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP);
CAF_PDM_InitFieldNoDefault(&m_summaryFilter, "VarListFilter", "Filter", "", "", "");
m_summaryFilter.uiCapability()->setUiTreeChildrenHidden(true);
m_summaryFilter.uiCapability()->setUiHidden(true);
m_summaryFilter = new RimSummaryFilter();
CAF_PDM_InitFieldNoDefault(&m_uiFilterResultMultiSelection, "FilterResultSelection", "Filter Result", "", "Ctrl-A : Select All", "");
m_uiFilterResultMultiSelection.xmlCapability()->setIOWritable(false);
m_uiFilterResultMultiSelection.xmlCapability()->setIOReadable(false);
m_uiFilterResultMultiSelection.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_uiFilterResultMultiSelection.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_uiFilterResultMultiSelection.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_curves, "FilteredCurves", "Filtered Curves", "", "", "");
m_curves.uiCapability()->setUiHidden(true);
m_curves.uiCapability()->setUiTreeChildrenHidden(false);
CAF_PDM_InitFieldNoDefault(&m_applyButtonField, "ApplySelection", "Apply", "", "", "");
m_applyButtonField.xmlCapability()->setIOWritable(false);
m_applyButtonField.xmlCapability()->setIOReadable(false);
m_applyButtonField = false;
m_applyButtonField.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName());
m_applyButtonField.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
CAF_PDM_InitField(&m_autoApplyFilterChanges, "AutoApplyFilterChanges", false, "Auto Apply Changes", "", "", "");
CAF_PDM_InitField(&m_showCurves, "IsActive", true, "Show Curves", "", "", "");
m_showCurves.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_useAutoAppearanceAssignment, "UseAutoAppearanceAssignment", true, "Auto", "", "", "" );
CAF_PDM_InitFieldNoDefault(&m_caseAppearanceType, "CaseAppearanceType", "Case", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_variableAppearanceType, "VariableAppearanceType", "Vector", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellAppearanceType, "WellAppearanceType", "Well", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_groupAppearanceType, "GroupAppearanceType", "Group", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_regionAppearanceType, "RegionAppearanceType", "Region", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_plotAxis, "PlotAxis", "Axis", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurveFilter::~RimSummaryCurveFilter()
{
delete m_summaryFilter();
m_curves.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::createCurves(RimSummaryCase* summaryCase, const QString& stringFilter)
{
if (summaryCase)
{
std::vector<RimSummaryCase*> selectedCases;
selectedCases.push_back(summaryCase);
m_summaryFilter->setCompleteVarStringFilter(stringFilter);
std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> > newCurveDefinitions;
createSetOfCasesAndResultAdresses(selectedCases, *m_summaryFilter, &newCurveDefinitions);
createCurvesFromCurveDefinitions(newCurveDefinitions);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSummaryCurveFilter::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> optionList;
if (fieldNeedingOptions == &m_selectedSummaryCases)
{
RimProject* proj = RiaApplication::instance()->project();
std::vector<RimSummaryCase*> cases;
proj->allSummaryCases(cases);
for (size_t i = 0; i < cases.size(); i++)
{
RimSummaryCase* rimCase = cases[i];
optionList.push_back(caf::PdmOptionItemInfo(rimCase->caseName(), QVariant::fromValue(caf::PdmPointer<caf::PdmObjectHandle>(rimCase))));
}
}
else if(fieldNeedingOptions == &m_uiFilterResultMultiSelection)
{
std::set<RifEclipseSummaryAddress> addrUnion = findPossibleSummaryAddresses();
for(const auto& address: addrUnion)
{
std::string name = address.uiText();
QString s = QString::fromStdString(name);
optionList.push_back(caf::PdmOptionItemInfo(s, QVariant::fromValue(address)));
}
}
if(useOptionsOnly) *useOptionsOnly = true;
return optionList;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup("Summary Vectors");
curveDataGroup->add(&m_selectedSummaryCases);
caf::PdmUiGroup* curveVarSelectionGroup = curveDataGroup->addNewGroup("Vector Selection");
m_summaryFilter->defineUiOrdering(uiConfigName, *curveVarSelectionGroup);
curveVarSelectionGroup->add(&m_uiFilterResultMultiSelection);
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance settings");
appearanceGroup->add(&m_useAutoAppearanceAssignment);
if(!m_useAutoAppearanceAssignment())
{
appearanceGroup->add(&m_caseAppearanceType);
appearanceGroup->add(&m_variableAppearanceType);
appearanceGroup->add(&m_wellAppearanceType);
appearanceGroup->add(&m_groupAppearanceType);
appearanceGroup->add(&m_regionAppearanceType);
}
// Set sensitivity
{
m_caseAppearanceType.uiCapability()->setUiReadOnly(m_useAutoAppearanceAssignment);
m_variableAppearanceType.uiCapability()->setUiReadOnly(m_useAutoAppearanceAssignment);
m_wellAppearanceType.uiCapability()->setUiReadOnly(m_useAutoAppearanceAssignment);
m_groupAppearanceType.uiCapability()->setUiReadOnly(m_useAutoAppearanceAssignment);
m_regionAppearanceType.uiCapability()->setUiReadOnly(m_useAutoAppearanceAssignment);
}
uiOrdering.add(&m_plotAxis);
uiOrdering.add(&m_autoApplyFilterChanges);
uiOrdering.add(&m_applyButtonField);
uiOrdering.setForgetRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if(changedField == &m_uiFilterResultMultiSelection)
{
if (m_autoApplyFilterChanges)
{
loadDataAndUpdatePlot();
}
}
else if (changedField == &m_applyButtonField)
{
m_applyButtonField = false;
loadDataAndUpdatePlot();
}
else if (changedField == &m_showCurves)
{
for(RimSummaryCurve* curve : m_curves)
{
curve->updateCurveVisibility();
}
if (m_parentQwtPlot) m_parentQwtPlot->replot();
}
else if (changedField == &m_plotAxis)
{
updatePlotAxisForCurves();
}
else if (changedField == &m_selectedSummaryCases)
{
if (newValue.toList().size() < 1)
{
if (m_selectionCache.size() > 0)
{
m_selectedSummaryCases.setValue(m_selectionCache);
}
}
else
{
m_selectionCache = m_selectedSummaryCases.value();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::loadDataAndUpdatePlot()
{
syncCurvesFromUiSelection();
loadDataAndUpdate();
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfType(plot);
plot->updateAxes();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::setParentQwtPlot(QwtPlot* plot)
{
m_parentQwtPlot = plot;
for (RimSummaryCurve* curve : m_curves)
{
curve->setParentQwtPlot(plot);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::detachQwtCurves()
{
for(RimSummaryCurve* curve : m_curves)
{
curve->detachQwtCurve();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurve* RimSummaryCurveFilter::findRimCurveFromQwtCurve(const QwtPlotCurve* qwtCurve) const
{
for(RimSummaryCurve* rimCurve: m_curves)
{
if(rimCurve->qwtPlotCurve() == qwtCurve)
{
return rimCurve;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::syncCurvesFromUiSelection()
{
// Create a search map containing whats supposed to be curves
std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> > newCurveDefinitions;
// Populate the newCurveDefinitions from the Gui
std::set<RifEclipseSummaryAddress> addrUnion = findPossibleSummaryAddresses();
for (RimSummaryCase* currentCase: m_selectedSummaryCases)
{
if (!currentCase || !currentCase->caseData() || !currentCase->caseData()->summaryReader()) continue;
RifReaderEclipseSummary* reader = currentCase->caseData()->summaryReader();
for(const RifEclipseSummaryAddress& addr: m_uiFilterResultMultiSelection.v())
{
if(!reader->hasAddress(addr)) continue;
if (addrUnion.count(addr) == 0 ) continue; // Wash the possible "old" ui selection with new filter
newCurveDefinitions.insert(std::make_pair(currentCase, addr));
}
}
m_curves.deleteAllChildObjects();
createCurvesFromCurveDefinitions(newCurveDefinitions);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::syncUiSelectionFromCurves()
{
// Create a search map containing whats supposed to be uiSelected
std::set<RimSummaryCase*> referredCases;
std::set<RifEclipseSummaryAddress> existingCurveDefinitions;
// Populate the existingCurveDefinitions from the existing curves
for(RimSummaryCurve* curve: m_curves)
{
existingCurveDefinitions.insert(curve->summaryAddress());
referredCases.insert(curve->summaryCase());
}
if (m_curves.size()) // Only sync the selected cases if we actually have some curves. To avoid user getting an empty variable list accidentally
{
m_selectedSummaryCases.clear();
for(RimSummaryCase* currCase: referredCases)
{
m_selectedSummaryCases.push_back(currCase);
}
}
m_uiFilterResultMultiSelection.v().clear();
for(const RifEclipseSummaryAddress& addr: existingCurveDefinitions)
{
m_uiFilterResultMultiSelection.v().push_back(addr);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute)
{
if(&m_applyButtonField == field)
{
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*> (attribute);
attrib->m_buttonText = "Apply" ;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::updatePlotAxisForCurves()
{
for (RimSummaryCurve* curve : m_curves)
{
curve->setPlotAxis(m_plotAxis());
curve->updateQwtPlotAxis();
}
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfType(plot);
plot->updateAxes();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::loadDataAndUpdate()
{
for (RimSummaryCurve* curve: m_curves)
{
curve->loadDataAndUpdate();
}
syncUiSelectionFromCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RimSummaryCurveFilter::unitNames()
{
std::set<std::string> unitNames;
for(RimSummaryCurve* curve: m_curves)
{
if (curve->isCurveVisible()) unitNames.insert( curve->unitName());
}
return unitNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::createSetOfCasesAndResultAdresses(
const std::vector<RimSummaryCase*>& cases,
const RimSummaryFilter& filter,
std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >* curveDefinitions) const
{
for (RimSummaryCase* currentCase : cases)
{
if (!currentCase || !currentCase->caseData() || !currentCase->caseData()->summaryReader()) continue;
RifReaderEclipseSummary* reader = currentCase->caseData()->summaryReader();
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
int addressCount = static_cast<int>(allAddresses.size());
for (int i = 0; i < addressCount; i++)
{
if (!filter.isIncludedByFilter(allAddresses[i])) continue;
curveDefinitions->insert(std::make_pair(currentCase, allAddresses[i]));
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::createCurvesFromCurveDefinitions(const std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >& curveDefinitions)
{
int colorIndex = 2;
int lineStyleIdx = -1;
RimSummaryCase* prevCase = nullptr;
RimPlotCurve::LineStyleEnum lineStyle = RimPlotCurve::STYLE_SOLID;
RimSummaryCurveAppearanceCalculator curveLookCalc(curveDefinitions);
if (!m_useAutoAppearanceAssignment())
{
curveLookCalc.assignDimensions( m_caseAppearanceType(),
m_variableAppearanceType(),
m_wellAppearanceType(),
m_groupAppearanceType(),
m_regionAppearanceType());
}
else
{
RimSummaryCurveAppearanceCalculator::CurveAppearanceType caseAppearance;
RimSummaryCurveAppearanceCalculator::CurveAppearanceType variAppearance;
RimSummaryCurveAppearanceCalculator::CurveAppearanceType wellAppearance;
RimSummaryCurveAppearanceCalculator::CurveAppearanceType gropAppearance;
RimSummaryCurveAppearanceCalculator::CurveAppearanceType regiAppearance;
curveLookCalc.getDimensions(&caseAppearance,
&variAppearance,
&wellAppearance,
&gropAppearance,
&regiAppearance);
m_caseAppearanceType = caseAppearance;
m_variableAppearanceType = variAppearance;
m_wellAppearanceType = wellAppearance;
m_groupAppearanceType = gropAppearance;
m_regionAppearanceType = regiAppearance;
}
for (auto& caseAddrPair : curveDefinitions)
{
RimSummaryCase* currentCase = caseAddrPair.first;
RimSummaryCurve* curve = new RimSummaryCurve();
curve->setParentQwtPlot(m_parentQwtPlot);
curve->setSummaryCase(currentCase);
curve->setSummaryAddress(caseAddrPair.second);
curve->setPlotAxis(m_plotAxis());
m_curves.push_back(curve);
curveLookCalc.setupCurveLook(curve);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::updateCaseNameHasChanged()
{
for (RimSummaryCurve* curve : m_curves)
{
curve->updateCurveName();
curve->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDefines::PlotAxis RimSummaryCurveFilter::associatedPlotAxis() const
{
return m_plotAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::setPlotAxis(RimDefines::PlotAxis plotAxis)
{
m_plotAxis = plotAxis;
updateConnectedEditors();
updatePlotAxisForCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveFilter::updateCompleteVariableStringFilterChanged()
{
if (m_autoApplyFilterChanges)
{
loadDataAndUpdatePlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCurveFilter::isCurvesVisible()
{
return m_showCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSummaryCurveFilter::objectToggleField()
{
return &m_showCurves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimSummaryCurveFilter::findPossibleSummaryAddresses()
{
std::set<RifEclipseSummaryAddress> addrUnion;
for(RimSummaryCase* currCase: m_selectedSummaryCases)
{
RifReaderEclipseSummary* reader = nullptr;
if(currCase && currCase->caseData()) reader = currCase->caseData()->summaryReader();
if(reader)
{
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
int addressCount = static_cast<int>(allAddresses.size());
for(int i = 0; i <addressCount; i++)
{
if(!m_summaryFilter->isIncludedByFilter(allAddresses[i])) continue;
addrUnion.insert(allAddresses[i]);
}
}
}
return addrUnion;
}

View File

@@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cafPdmPtrField.h"
#include "cafPdmChildField.h"
#include "cafPdmChildArrayField.h"
#include "cafAppEnum.h"
#include "cafPdmPtrArrayField.h"
#include "RifEclipseSummaryAddress.h"
#include "RimDefines.h"
#include "RimSummaryCurveAppearanceCalculator.h"
#include "qwt_plot.h"
class QwtPlot;
class QwtPlotCurve;
class RifReaderEclipseSummary;
class RimSummaryCase;
class RimSummaryCurve;
class RimSummaryFilter;
class RiuLineSegmentQwtPlotCurve;
#include <QPointer>
Q_DECLARE_METATYPE(RifEclipseSummaryAddress);
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryCurveFilter : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryCurveFilter();
virtual ~RimSummaryCurveFilter();
void createCurves(RimSummaryCase* summaryCase, const QString& stringFilter);
bool isCurvesVisible();
void loadDataAndUpdate();
void setParentQwtPlot(QwtPlot* plot);
void detachQwtCurves();
RimSummaryCurve* findRimCurveFromQwtCurve(const QwtPlotCurve* qwtCurve) const;
std::set<std::string> unitNames();
void updateCaseNameHasChanged();
RimDefines::PlotAxis associatedPlotAxis() const;
void setPlotAxis(RimDefines::PlotAxis plotAxis);
void updateCompleteVariableStringFilterChanged();
private:
void syncCurvesFromUiSelection();
void createCurvesFromCurveDefinitions(const std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >& curveDefinitions);
void syncUiSelectionFromCurves();
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddresses();
void createSetOfCasesAndResultAdresses(
const std::vector<RimSummaryCase*>& cases,
const RimSummaryFilter& filter,
std::set<std::pair<RimSummaryCase*, RifEclipseSummaryAddress> >* curveDefinitions) const;
// Overridden PDM methods
virtual caf::PdmFieldHandle* objectToggleField() override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly);
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) override;
void updatePlotAxisForCurves();
void loadDataAndUpdatePlot();
private:
QPointer<QwtPlot> m_parentQwtPlot;
// Fields
caf::PdmField<bool> m_showCurves;
caf::PdmPtrArrayField<RimSummaryCase*> m_selectedSummaryCases;
caf::PdmChildArrayField<RimSummaryCurve*> m_curves;
caf::PdmField< caf::AppEnum< RimDefines::PlotAxis > > m_plotAxis;
// Filter fields
caf::PdmChildField<RimSummaryFilter*> m_summaryFilter;
caf::PdmField<std::vector<RifEclipseSummaryAddress> >
m_uiFilterResultMultiSelection;
caf::PdmField<bool> m_autoApplyFilterChanges;
caf::PdmField<bool> m_applyButtonField;
caf::PdmField<bool> m_useAutoAppearanceAssignment;
typedef caf::AppEnum<RimSummaryCurveAppearanceCalculator::CurveAppearanceType> AppearanceTypeAppEnum;
caf::PdmField< AppearanceTypeAppEnum > m_caseAppearanceType;
caf::PdmField< AppearanceTypeAppEnum > m_variableAppearanceType;
caf::PdmField< AppearanceTypeAppEnum > m_wellAppearanceType;
caf::PdmField< AppearanceTypeAppEnum > m_groupAppearanceType;
caf::PdmField< AppearanceTypeAppEnum > m_regionAppearanceType;
std::vector< caf::PdmPointer<RimSummaryCase> > m_selectionCache;
};

View File

@@ -0,0 +1,290 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryCurvesCalculator.h"
#include "RigStatisticsCalculator.h"
#include "RimDefines.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveFilter.h"
#include "RimSummaryYAxisProperties.h"
#include "RiuSummaryQwtPlot.h"
#include "qwt_plot_curve.h"
#include "qwt_scale_draw.h"
#include "qwt_scale_engine.h"
#include <set>
#include <string>
#include <cmath>
//--------------------------------------------------------------------------------------------------
// e format as [-]9.9e[+|-]999
// E format as[-]9.9E[+| -]999
// f format as[-]9.9
// g use e or f format, whichever is the most concise
// G use E or f format, whichever is the most concise
//--------------------------------------------------------------------------------------------------
class DecimalScaleDraw : public QwtScaleDraw
{
public:
virtual QwtText label(double value) const override
{
if (qFuzzyCompare(value + 1.0, 1.0))
value = 0.0;
int precision = DecimalScaleDraw::calculatePrecision(value);
return QString::number(value, 'f', precision);
}
private:
static int calculatePrecision(double value)
{
double absVal = fabs(value);
const int numberOfDigits = 2;
if (1e-16 < absVal && absVal < 1.0e3)
{
int logVal = static_cast<int>(log10(absVal));
int numDigitsAfterPoint = abs(logVal - numberOfDigits);
return numDigitsAfterPoint;
}
else
{
return numberOfDigits;
}
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class ScientificScaleDraw : public QwtScaleDraw
{
public:
virtual QwtText label(double value) const override
{
if (qFuzzyCompare(value + 1.0, 1.0))
value = 0.0;
return QString::number(value, 'e', 2);
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurvesCalculator::RimSummaryCurvesCalculator(RimSummaryYAxisProperties* axisProperties,
const std::vector<RimSummaryCurve*>& curves,
const std::vector<RimSummaryCurveFilter*>& curveFilters)
: m_axisProperties(axisProperties),
m_singleCurves(curves),
m_curveFilters(curveFilters)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurvesCalculator::RimSummaryCurvesCalculator(RimSummaryYAxisProperties* axisProperties, const std::vector<RimSummaryCurve*>& curves)
: m_axisProperties(axisProperties),
m_singleCurves(curves)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurvesCalculator::applyPropertiesToPlot(RiuSummaryQwtPlot* m_qwtPlot)
{
if (!m_qwtPlot) return;
{
QString axisTitle = m_axisProperties->customTitle;
if (m_axisProperties->isAutoTitle) axisTitle = autoAxisTitle();
QwtText axisTitleY = m_qwtPlot->axisTitle(m_axisProperties->axis());
QFont axisTitleYFont = axisTitleY.font();
axisTitleYFont.setBold(true);
axisTitleYFont.setPixelSize(m_axisProperties->fontSize);
axisTitleY.setFont(axisTitleYFont);
axisTitleY.setText(axisTitle);
m_qwtPlot->setAxisTitle(m_axisProperties->axis(), axisTitleY);
}
{
QFont yAxisFont = m_qwtPlot->axisFont(m_axisProperties->axis());
yAxisFont.setBold(false);
yAxisFont.setPixelSize(m_axisProperties->fontSize);
m_qwtPlot->setAxisFont(m_axisProperties->axis(), yAxisFont);
}
{
if (m_axisProperties->numberFormat == RimSummaryYAxisProperties::NUMBER_FORMAT_AUTO)
{
m_qwtPlot->setAxisScaleDraw(m_axisProperties->axis(), new QwtScaleDraw);
}
else if (m_axisProperties->numberFormat == RimSummaryYAxisProperties::NUMBER_FORMAT_DECIMAL)
{
m_qwtPlot->setAxisScaleDraw(m_axisProperties->axis(), new DecimalScaleDraw);
}
else if (m_axisProperties->numberFormat == RimSummaryYAxisProperties::NUMBER_FORMAT_SCIENTIFIC)
{
m_qwtPlot->setAxisScaleDraw(m_axisProperties->axis(), new ScientificScaleDraw());
}
}
{
if (m_axisProperties->isLogarithmicScaleEnabled)
{
QwtLogScaleEngine* currentScaleEngine = dynamic_cast<QwtLogScaleEngine*>(m_qwtPlot->axisScaleEngine(m_axisProperties->axis()));
if (!currentScaleEngine)
{
m_qwtPlot->setAxisScaleEngine(m_axisProperties->axis(), new QwtLogScaleEngine);
m_qwtPlot->setAxisMaxMinor(m_axisProperties->axis(), 5);
}
}
else
{
QwtLinearScaleEngine* currentScaleEngine = dynamic_cast<QwtLinearScaleEngine*>(m_qwtPlot->axisScaleEngine(m_axisProperties->axis()));
if (!currentScaleEngine)
{
m_qwtPlot->setAxisScaleEngine(m_axisProperties->axis(), new QwtLinearScaleEngine);
m_qwtPlot->setAxisMaxMinor(m_axisProperties->axis(), 3);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryCurvesCalculator::autoAxisTitle() const
{
std::set<std::string> unitNames;
for (RimSummaryCurve* rimCurve : m_singleCurves)
{
if (rimCurve->isCurveVisible()) unitNames.insert(rimCurve->unitName());
}
for (RimSummaryCurveFilter* curveFilter : m_curveFilters)
{
std::set<std::string> filterUnitNames = curveFilter->unitNames();
unitNames.insert(filterUnitNames.begin(), filterUnitNames.end());
}
QString assembledYAxisText;
for (const std::string& unitName : unitNames)
{
assembledYAxisText += "[" + QString::fromStdString(unitName) + "] ";
}
return assembledYAxisText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurvesCalculator::computeYRange(double* min, double* max) const
{
double minValue = HUGE_VAL;
double maxValue = -HUGE_VAL;
for (RimSummaryCurve* curve : m_singleCurves)
{
double minCurveValue = HUGE_VAL;
double maxCurveValue = -HUGE_VAL;
if (curve->isCurveVisible() && curveValueRangeY(curve->qwtPlotCurve(), &minCurveValue, &maxCurveValue))
{
if (minCurveValue < minValue)
{
minValue = minCurveValue;
}
if (maxCurveValue > maxValue)
{
maxValue = maxCurveValue;
}
}
}
if (minValue == HUGE_VAL)
{
minValue = RimDefines::minimumDefaultValuePlot();
maxValue = RimDefines::maximumDefaultValuePlot();
}
if (m_axisProperties->isLogarithmicScaleEnabled)
{
// For logarithmic auto scaling, compute positive curve value closest to zero and use
// this value as the plot visible minimum
double pos = HUGE_VAL;
double neg = -HUGE_VAL;
for (RimSummaryCurve* curve : m_singleCurves)
{
if (curve->isCurveVisible())
{
RigStatisticsCalculator::posNegClosestToZero(curve->yPlotValues(), pos, neg);
}
}
if (pos != HUGE_VAL)
{
minValue = pos;
}
}
*min = minValue;
*max = maxValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCurvesCalculator::curveValueRangeY(const QwtPlotCurve* qwtCurve, double* min, double* max) const
{
if (!qwtCurve) return false;
if (qwtCurve->data()->size() < 1)
{
return false;
}
*min = qwtCurve->minYValue();
*max = qwtCurve->maxYValue();
return true;
}

View File

@@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <vector>
#include <QString>
class RimSummaryCurve;
class RimSummaryCurveFilter;
class RimSummaryYAxisProperties;
class RiuSummaryQwtPlot;
class QwtPlotCurve;
class RimSummaryCurvesCalculator
{
public:
RimSummaryCurvesCalculator(RimSummaryYAxisProperties* axisProperties,
const std::vector<RimSummaryCurve*>& curves,
const std::vector<RimSummaryCurveFilter*>& curveFilters);
RimSummaryCurvesCalculator(RimSummaryYAxisProperties* axisProperties,
const std::vector<RimSummaryCurve*>& curves);
void applyPropertiesToPlot(RiuSummaryQwtPlot* qwtPlot);
void computeYRange(double* min, double* max) const;
private:
QString autoAxisTitle() const;
bool curveValueRangeY(const QwtPlotCurve* qwtCurve, double* min, double* max) const;
private:
RimSummaryYAxisProperties* m_axisProperties;
std::vector<RimSummaryCurve*> m_singleCurves;
std::vector<RimSummaryCurveFilter*> m_curveFilters;
};

View File

@@ -0,0 +1,382 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryFilter.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveFilter.h"
namespace caf
{
template<>
void caf::AppEnum<RimSummaryFilter::SummaryFilterType>::setUp()
{
addItem(RimSummaryFilter::SUM_FILTER_VAR_STRING, "SUM_FILTER_VAR_STRING", "All");
addItem(RimSummaryFilter::SUM_FILTER_FIELD, "SUM_FILTER_FIELD", "Field");
addItem(RimSummaryFilter::SUM_FILTER_WELL, "SUM_FILTER_WELL", "Well");
addItem(RimSummaryFilter::SUM_FILTER_WELL_GROUP, "SUM_FILTER_WELL_GROUP", "Group");
addItem(RimSummaryFilter::SUM_FILTER_WELL_COMPLETION, "SUM_FILTER_WELL_COMPLETION", "Completion");
addItem(RimSummaryFilter::SUM_FILTER_WELL_SEGMENT, "SUM_FILTER_SEGMENT", "Segment");
addItem(RimSummaryFilter::SUM_FILTER_BLOCK, "SUM_FILTER_BLOCK", "Block");
addItem(RimSummaryFilter::SUM_FILTER_REGION, "SUM_FILTER_REGION", "Region");
addItem(RimSummaryFilter::SUM_FILTER_REGION_2_REGION, "SUM_FILTER_REGION_2_REGION", "Region-Region");
addItem(RimSummaryFilter::SUM_FILTER_WELL_LGR, "SUM_FILTER_WELL_LGR", "Lgr-Well");
addItem(RimSummaryFilter::SUM_FILTER_WELL_COMPLETION_LGR, "SUM_FILTER_WELL_COMPLETION_LGR", "Lgr-Completion");
addItem(RimSummaryFilter::SUM_FILTER_BLOCK_LGR, "SUM_FILTER_BLOCK_LGR", "Lgr-Block");
addItem(RimSummaryFilter::SUM_FILTER_MISC, "SUM_FILTER_MISC", "Misc");
addItem(RimSummaryFilter::SUM_FILTER_AQUIFER, "SUM_FILTER_AQUIFER", "Aquifer");
addItem(RimSummaryFilter::SUM_FILTER_NETWORK, "SUM_FILTER_NETWORK", "Network");
addItem(RimSummaryFilter::SUM_FILTER_ANY, "SUM_FILTER_ANY", "All (Advanced)");
setDefault(RimSummaryFilter::SUM_FILTER_VAR_STRING);
}
}
CAF_PDM_SOURCE_INIT(RimSummaryFilter, "SummaryFilterSettings");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryFilter::RimSummaryFilter()
{
CAF_PDM_InitObject("Summary Filter", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_filterType, "SummaryFilterType", "Search", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_completeVarStringFilter, "SummaryCompleteVarStringFilter", "Filter", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_filterQuantityName, "SummaryVarQuantityFilter", "Vector name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_regionNumberFilter, "SummaryRegionNumberFilter", "Region number", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_regionNumber2Filter, "SummaryRegionNumber2Filter", "2. Region number", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellGroupNameFilter, "SummaryWellGroupNameFilter", "Group name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellNameFilter, "SummaryWellNameFilter", "Well name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellSegmentNumberFilter, "SummaryWellSegmentNumberFilter", "Segment number", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_lgrNameFilter, "SummaryLgrNameFilter", "Lgr name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_cellIJKFilter, "SummaryCellIJKFilter", "I, J, K", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryFilter::~RimSummaryFilter()
{
}
bool isNumberMatch(QString numericalFilterString, int number)
{
if(numericalFilterString.isEmpty()) return true;
if (numericalFilterString.trimmed() == "*")
{
if(number >= 0) return true;
else return false;
}
// Todo: Ranges, and lists
int filterNumber = numericalFilterString.toInt();
return number == filterNumber;
}
bool isStringMatch(QString filterString, std::string value)
{
if(filterString.isEmpty()) return true;
if(filterString.trimmed() == "*")
{
if(!value.empty()) return true;
else return false;
}
QRegExp searcher(filterString, Qt::CaseInsensitive, QRegExp::WildcardUnix);
QString qstrValue = QString::fromStdString(value);
return searcher.exactMatch(qstrValue);
}
bool isIJKMatch(QString filterString, int cellI, int cellJ, int cellK)
{
if(filterString.isEmpty()) return true;
if(filterString.trimmed() == "*")
{
if(cellI >= 0 && cellJ >= 0 && cellK >= 0) return true;
else return false;
}
QString ijkString;
if(cellI >= 0 && cellJ >= 0 && cellK >= 0)
{
ijkString = QString::number(cellI) + ", " + QString::number(cellJ) + ", " + QString::number(cellK);
}
// Todo: Ranges, and lists
QRegExp searcher(filterString, Qt::CaseInsensitive, QRegExp::WildcardUnix);
return searcher.exactMatch(ijkString);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryFilter::isIncludedByFilter(const RifEclipseSummaryAddress& addr) const
{
if(!isSumVarTypeMatchingFilterType(m_filterType(), addr.category())) return false;
if(m_filterType() == SUM_FILTER_VAR_STRING)
{
return isStringMatch(m_completeVarStringFilter(), addr.uiText());
}
if(!isStringMatch(m_filterQuantityName(), addr.quantityName())) return false;
if(m_filterType() == SUM_FILTER_ANY)
{
return (isNumberMatch(m_regionNumberFilter(), addr.regionNumber())
&& isNumberMatch(m_regionNumber2Filter(), addr.regionNumber2())
&& isStringMatch(m_wellGroupNameFilter(), addr.wellGroupName())
&& isStringMatch(m_wellNameFilter(), addr.wellName())
&& isStringMatch(m_lgrNameFilter(), addr.lgrName())
&& isNumberMatch(m_wellSegmentNumberFilter(), addr.wellSegmentNumber())
&& isIJKMatch(m_cellIJKFilter(), addr.cellI(), addr.cellJ(), addr.cellK()));
}
switch(addr.category())
{
case RifEclipseSummaryAddress::SUMMARY_REGION:
{
return isNumberMatch(m_regionNumberFilter(), addr.regionNumber());
}
break;
case RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION:
{
return isNumberMatch(m_regionNumberFilter(), addr.regionNumber())
&& isNumberMatch(m_regionNumber2Filter(), addr.regionNumber2());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL_GROUP:
{
return isStringMatch(m_wellGroupNameFilter(), addr.wellGroupName());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL:
{
return isStringMatch(m_wellNameFilter(), addr.wellName());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION:
{
return isStringMatch(m_wellNameFilter(), addr.wellName())
&& isIJKMatch(m_cellIJKFilter(), addr.cellI(), addr.cellJ(), addr.cellK());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL_LGR:
{
return isStringMatch(m_wellNameFilter(), addr.wellName())
&& isStringMatch(m_lgrNameFilter(), addr.lgrName());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR:
{
return isStringMatch(m_wellNameFilter(), addr.wellName())
&& isStringMatch(m_lgrNameFilter(), addr.lgrName())
&& isIJKMatch(m_cellIJKFilter(), addr.cellI(), addr.cellJ(), addr.cellK());
}
break;
case RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT:
{
return isStringMatch(m_wellNameFilter(), addr.wellName())
&& isNumberMatch(m_wellSegmentNumberFilter(), addr.wellSegmentNumber());
}
break;
case RifEclipseSummaryAddress::SUMMARY_BLOCK:
{
return isIJKMatch(m_cellIJKFilter(), addr.cellI(), addr.cellJ(), addr.cellK());
}
break;
case RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR:
{
return isStringMatch(m_lgrNameFilter(), addr.lgrName())
&& isIJKMatch(m_cellIJKFilter(), addr.cellI(), addr.cellJ(), addr.cellK());
}
break;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryFilter::isSumVarTypeMatchingFilterType(SummaryFilterType sumFilterType, RifEclipseSummaryAddress::SummaryVarCategory sumVarType)
{
if(sumVarType == RifEclipseSummaryAddress::SUMMARY_INVALID) return false;
if(sumFilterType == SUM_FILTER_ANY || sumFilterType == SUM_FILTER_VAR_STRING) return true;
switch(sumVarType)
{
case RifEclipseSummaryAddress::SUMMARY_FIELD: { return (sumFilterType == SUM_FILTER_FIELD); } break;
case RifEclipseSummaryAddress::SUMMARY_AQUIFER: { return (sumFilterType == SUM_FILTER_AQUIFER); } break;
case RifEclipseSummaryAddress::SUMMARY_NETWORK: { return (sumFilterType == SUM_FILTER_NETWORK); } break;
case RifEclipseSummaryAddress::SUMMARY_MISC: { return (sumFilterType == SUM_FILTER_MISC); } break;
case RifEclipseSummaryAddress::SUMMARY_REGION: { return (sumFilterType == SUM_FILTER_REGION); } break;
case RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION: { return (sumFilterType == SUM_FILTER_REGION_2_REGION); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL_GROUP: { return (sumFilterType == SUM_FILTER_WELL_GROUP); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL: { return (sumFilterType == SUM_FILTER_WELL); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION: { return (sumFilterType == SUM_FILTER_WELL_COMPLETION); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL_LGR: { return (sumFilterType == SUM_FILTER_WELL_LGR); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR: { return (sumFilterType == SUM_FILTER_WELL_COMPLETION_LGR); } break;
case RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT: { return (sumFilterType == SUM_FILTER_WELL_SEGMENT); } break;
case RifEclipseSummaryAddress::SUMMARY_BLOCK: { return (sumFilterType == SUM_FILTER_BLOCK); } break;
case RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR: { return (sumFilterType == SUM_FILTER_BLOCK_LGR); } break;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_filterType);
caf::PdmUiGroup* curveVarFilterGroup = nullptr;
if(m_filterType() == SUM_FILTER_VAR_STRING)
{
uiOrdering.add(&m_completeVarStringFilter);
}
else
{
caf::PdmUiOrdering* curveVarFilterGroup = &uiOrdering;//uiOrdering.addNewGroup("Search Options");
curveVarFilterGroup->add(&m_filterQuantityName);
switch(m_filterType())
{
case SUM_FILTER_ANY:
{
curveVarFilterGroup->add(&m_wellNameFilter);
curveVarFilterGroup->add(&m_wellGroupNameFilter);
curveVarFilterGroup->add(&m_regionNumberFilter);
curveVarFilterGroup->add(&m_regionNumber2Filter);
curveVarFilterGroup->add(&m_wellSegmentNumberFilter);
curveVarFilterGroup->add(&m_lgrNameFilter);
curveVarFilterGroup->add(&m_cellIJKFilter);
}
break;
case SUM_FILTER_REGION:
{
curveVarFilterGroup->add(&m_regionNumberFilter);
}
break;
case SUM_FILTER_REGION_2_REGION:
{
curveVarFilterGroup->add(&m_regionNumberFilter);
curveVarFilterGroup->add(&m_regionNumber2Filter);
}
break;
case SUM_FILTER_WELL_GROUP:
{
curveVarFilterGroup->add(&m_wellGroupNameFilter);
}
break;
case SUM_FILTER_WELL:
{
curveVarFilterGroup->add(&m_wellNameFilter);
}
break;
case SUM_FILTER_WELL_COMPLETION:
{
curveVarFilterGroup->add(&m_wellNameFilter);
curveVarFilterGroup->add(&m_cellIJKFilter);
}
break;
case SUM_FILTER_WELL_LGR:
{
curveVarFilterGroup->add(&m_wellNameFilter);
curveVarFilterGroup->add(&m_lgrNameFilter);
}
break;
case SUM_FILTER_WELL_COMPLETION_LGR:
{
curveVarFilterGroup->add(&m_wellNameFilter);
curveVarFilterGroup->add(&m_lgrNameFilter);
curveVarFilterGroup->add(&m_cellIJKFilter);
}
break;
case SUM_FILTER_WELL_SEGMENT:
{
curveVarFilterGroup->add(&m_wellNameFilter);
curveVarFilterGroup->add(&m_wellSegmentNumberFilter);
}
break;
case SUM_FILTER_BLOCK:
{
curveVarFilterGroup->add(&m_cellIJKFilter);
}
break;
case SUM_FILTER_BLOCK_LGR:
{
curveVarFilterGroup->add(&m_lgrNameFilter);
curveVarFilterGroup->add(&m_cellIJKFilter);
}
break;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryFilter::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
caf::PdmObject* parent = dynamic_cast<caf::PdmObject*>(this->parentField()->ownerObject());
if (parent)
{
parent->updateConnectedEditors();
}
if (changedField == &m_completeVarStringFilter)
{
RimSummaryCurveFilter* curveFilter = nullptr;
this->firstAncestorOrThisOfType(curveFilter);
if (curveFilter)
{
curveFilter->updateCompleteVariableStringFilterChanged();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryFilter::setCompleteVarStringFilter(const QString& stringFilter)
{
m_filterType = SUM_FILTER_VAR_STRING;
m_completeVarStringFilter = stringFilter;
}

View File

@@ -0,0 +1,79 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "RifEclipseSummaryAddress.h"
class RimSummaryFilter: public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum SummaryFilterType
{
SUM_FILTER_VAR_STRING,
SUM_FILTER_ANY,
SUM_FILTER_FIELD,
SUM_FILTER_AQUIFER,
SUM_FILTER_NETWORK,
SUM_FILTER_MISC,
SUM_FILTER_REGION,
SUM_FILTER_REGION_2_REGION,
SUM_FILTER_WELL_GROUP,
SUM_FILTER_WELL,
SUM_FILTER_WELL_COMPLETION,
SUM_FILTER_WELL_COMPLETION_LGR,
SUM_FILTER_WELL_LGR,
SUM_FILTER_WELL_SEGMENT,
SUM_FILTER_BLOCK,
SUM_FILTER_BLOCK_LGR,
};
RimSummaryFilter();
virtual ~RimSummaryFilter();
bool isIncludedByFilter(const RifEclipseSummaryAddress& addr) const;
void setCompleteVarStringFilter(const QString& stringFilter);
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
private:
friend class RimSummaryCurve;
friend class RimSummaryCurveFilter;
static bool isSumVarTypeMatchingFilterType(SummaryFilterType sumFilterType, RifEclipseSummaryAddress::SummaryVarCategory sumVarType);
caf::PdmField<caf::AppEnum<SummaryFilterType> >
m_filterType;
caf::PdmField<QString> m_completeVarStringFilter;
caf::PdmField<QString> m_filterQuantityName;
caf::PdmField<QString> m_regionNumberFilter;
caf::PdmField<QString> m_regionNumber2Filter;
caf::PdmField<QString> m_wellGroupNameFilter;
caf::PdmField<QString> m_wellNameFilter;
caf::PdmField<QString> m_wellSegmentNumberFilter;
caf::PdmField<QString> m_lgrNameFilter;
caf::PdmField<QString> m_cellIJKFilter;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
};

View File

@@ -0,0 +1,665 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryPlot.h"
#include "RiaApplication.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveFilter.h"
#include "RimSummaryCurvesCalculator.h"
#include "RimSummaryPlotCollection.h"
#include "RimSummaryTimeAxisProperties.h"
#include "RimSummaryYAxisProperties.h"
#include "RiuMainPlotWindow.h"
#include "RiuSelectionColors.h"
#include "RiuSummaryQwtPlot.h"
#include "cvfBase.h"
#include "cvfColor3.h"
#include "cafPdmUiTreeOrdering.h"
#include <QDateTime>
#include <QRectF>
#include "qwt_plot_curve.h"
#include "qwt_plot_renderer.h"
CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryPlot::RimSummaryPlot()
{
CAF_PDM_InitObject("Summary Plot", ":/SummaryPlot16x16.png", "", "");
CAF_PDM_InitField(&m_showWindow, "ShowWindow", true, "Show Summary Plot", "", "", "");
m_showWindow.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&m_userName, "PlotDescription", QString("Summary Plot"), "Name", "", "", "");
CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_curveFilters, "SummaryCurveFilters", "", "", "", "");
m_curveFilters.uiCapability()->setUiTreeHidden(true);
CAF_PDM_InitFieldNoDefault(&m_curves, "SummaryCurves", "", "", "", "");
m_curves.uiCapability()->setUiTreeHidden(true);
CAF_PDM_InitFieldNoDefault(&m_leftYAxisProperties, "LeftYAxisProperties", "Left Y Axis", "", "", "");
m_leftYAxisProperties.uiCapability()->setUiTreeHidden(true);
m_leftYAxisPropertiesObject = std::unique_ptr<RimSummaryYAxisProperties>(new RimSummaryYAxisProperties);
m_leftYAxisPropertiesObject->setNameAndAxis("Left Y-Axis", QwtPlot::yLeft);
m_leftYAxisProperties = m_leftYAxisPropertiesObject.get();
CAF_PDM_InitFieldNoDefault(&m_rightYAxisProperties, "RightYAxisProperties", "Right Y Axis", "", "", "");
m_rightYAxisProperties.uiCapability()->setUiTreeHidden(true);
m_rightYAxisPropertiesObject = std::unique_ptr<RimSummaryYAxisProperties>(new RimSummaryYAxisProperties);
m_rightYAxisPropertiesObject->setNameAndAxis("Right Y-Axis", QwtPlot::yRight);
m_rightYAxisProperties = m_rightYAxisPropertiesObject.get();
CAF_PDM_InitFieldNoDefault(&m_timeAxisProperties, "TimeAxisProperties", "Time Axis", "", "", "");
m_timeAxisProperties.uiCapability()->setUiTreeHidden(true);
m_timeAxisPropertiesObject = std::unique_ptr<RimSummaryTimeAxisProperties>(new RimSummaryTimeAxisProperties);
m_timeAxisProperties = m_timeAxisPropertiesObject.get();
CAF_PDM_InitField(&m_isAutoZoom, "AutoZoom", true, "Auto Zoom", "", "", "");
m_isAutoZoom.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryPlot::~RimSummaryPlot()
{
if (RiaApplication::instance()->mainPlotWindow())
{
RiaApplication::instance()->mainPlotWindow()->removeViewer(m_qwtPlot);
}
deletePlotWidget();
m_curves.deleteAllChildObjects();
m_curveFilters.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::deletePlotWidget()
{
if (m_qwtPlot)
{
m_qwtPlot->deleteLater();
m_qwtPlot = NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateAxes()
{
updateAxis(RimDefines::PLOT_AXIS_LEFT);
updateAxis(RimDefines::PLOT_AXIS_RIGHT);
updateZoomInQwt();
updateTimeAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryPlot::isLogarithmicScaleEnabled(RimDefines::PlotAxis plotAxis) const
{
if (plotAxis == RimDefines::PLOT_AXIS_LEFT)
{
return m_leftYAxisProperties->isLogarithmicScaleEnabled();
}
else
{
return m_rightYAxisProperties->isLogarithmicScaleEnabled();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::selectAxisInPropertyEditor(int axis)
{
RiuMainPlotWindow* plotwindow = RiaApplication::instance()->getOrCreateAndShowMainPlotWindow();
if (axis == QwtPlot::yLeft)
{
plotwindow->selectAsCurrentItem(m_leftYAxisProperties);
}
else if (axis == QwtPlot::yRight)
{
plotwindow->selectAsCurrentItem(m_rightYAxisProperties);
}
else if (axis == QwtPlot::xBottom)
{
plotwindow->selectAsCurrentItem(this);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimSummaryPlot::viewWidget()
{
return m_qwtPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateAxis(RimDefines::PlotAxis plotAxis)
{
if (!m_qwtPlot) return;
std::vector<RimSummaryCurve*> curves = curvesForAxis(plotAxis);
std::vector<RimSummaryCurveFilter*> curveFiltersForAxis;
for (RimSummaryCurveFilter* cs : m_curveFilters)
{
if (cs->associatedPlotAxis() == plotAxis)
{
curveFiltersForAxis.push_back(cs);
}
}
QwtPlot::Axis qwtAxis = QwtPlot::yLeft;
RimSummaryYAxisProperties* yAxisProperties = nullptr;
if (plotAxis == RimDefines::PLOT_AXIS_LEFT)
{
qwtAxis = QwtPlot::yLeft;
yAxisProperties = m_leftYAxisProperties();
}
else
{
qwtAxis = QwtPlot::yRight;
yAxisProperties = m_rightYAxisProperties();
}
if (curves.size() > 0)
{
m_qwtPlot->enableAxis(qwtAxis, true);
RimSummaryCurvesCalculator calc(yAxisProperties, curves, curveFiltersForAxis);
calc.applyPropertiesToPlot(m_qwtPlot);
}
else
{
m_qwtPlot->enableAxis(qwtAxis, false);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCurve*> RimSummaryPlot::curvesForAxis(RimDefines::PlotAxis plotAxis) const
{
std::vector<RimSummaryCurve*> curves;
std::vector<RimSummaryCurve*> childCurves;
this->descendantsIncludingThisOfType(childCurves);
for (RimSummaryCurve* curve : childCurves)
{
if (curve->associatedPlotAxis() == plotAxis)
{
curves.push_back(curve);
}
}
return curves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateTimeAxis()
{
if (!m_qwtPlot) return;
{
QString axisTitle;
if (m_timeAxisProperties->showTitle) axisTitle = m_timeAxisProperties->title();
QwtText timeAxisTitle = m_qwtPlot->axisTitle(QwtPlot::xBottom);
QFont font = timeAxisTitle.font();
font.setBold(true);
font.setPixelSize(m_timeAxisProperties->fontSize);
timeAxisTitle.setFont(font);
timeAxisTitle.setText(axisTitle);
m_qwtPlot->setAxisTitle(QwtPlot::xBottom, timeAxisTitle);
}
{
QFont timeAxisFont = m_qwtPlot->axisFont(QwtPlot::xBottom);
timeAxisFont.setBold(false);
timeAxisFont.setPixelSize(m_timeAxisProperties->fontSize);
m_qwtPlot->setAxisFont(QwtPlot::xBottom, timeAxisFont);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::handleViewerDeletion()
{
m_showWindow = false;
if (m_qwtPlot)
{
detachAllCurves();
}
uiCapability()->updateUiIconFromToggleField();
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateCaseNameHasChanged()
{
for (RimSummaryCurve* curve : m_curves)
{
curve->updateCurveName();
curve->updateConnectedEditors();
}
for (RimSummaryCurveFilter* curveFilter : m_curveFilters)
{
curveFilter->updateCaseNameHasChanged();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setZoomWindow(const QwtInterval& leftAxis, const QwtInterval& rightAxis, const QwtInterval& timeAxis)
{
m_leftYAxisProperties->visibleRangeMax = leftAxis.maxValue();
m_leftYAxisProperties->visibleRangeMin = leftAxis.minValue();
m_leftYAxisProperties->updateConnectedEditors();
m_rightYAxisProperties->visibleRangeMax = rightAxis.maxValue();
m_rightYAxisProperties->visibleRangeMin = rightAxis.minValue();
m_rightYAxisProperties->updateConnectedEditors();
m_timeAxisProperties->setVisibleRangeMin(timeAxis.minValue());
m_timeAxisProperties->setVisibleRangeMax(timeAxis.maxValue());
m_timeAxisProperties->updateConnectedEditors();
disableAutoZoom();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::zoomAll()
{
if (m_qwtPlot)
{
m_qwtPlot->setAxisAutoScale(QwtPlot::xBottom, true);
if (m_leftYAxisProperties->isLogarithmicScaleEnabled)
{
std::vector<RimSummaryCurve*> curves = curvesForAxis(RimDefines::PLOT_AXIS_LEFT);
double min, max;
RimSummaryCurvesCalculator calc(m_leftYAxisProperties, curves);
calc.computeYRange(&min, &max);
m_qwtPlot->setAxisScale(m_leftYAxisProperties->axis(), min, max);
}
else
{
m_qwtPlot->setAxisAutoScale(QwtPlot::yLeft, true);
}
if (m_rightYAxisProperties->isLogarithmicScaleEnabled)
{
std::vector<RimSummaryCurve*> curves = curvesForAxis(RimDefines::PLOT_AXIS_RIGHT);
double min, max;
RimSummaryCurvesCalculator calc(m_rightYAxisProperties, curves);
calc.computeYRange(&min, &max);
m_qwtPlot->setAxisScale(m_rightYAxisProperties->axis(), min, max);
}
else
{
m_qwtPlot->setAxisAutoScale(QwtPlot::yRight, true);
}
m_qwtPlot->replot();
}
updateZoomFromQwt();
m_isAutoZoom = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::addCurve(RimSummaryCurve* curve)
{
if (curve)
{
m_curves.push_back(curve);
if (m_qwtPlot)
{
curve->setParentQwtPlot(m_qwtPlot);
this->updateAxes();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::addCurveFilter(RimSummaryCurveFilter* curveFilter)
{
if(curveFilter)
{
m_curveFilters.push_back(curveFilter);
if(m_qwtPlot)
{
curveFilter->setParentQwtPlot(m_qwtPlot);
this->updateAxes();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (changedField == &m_showWindow)
{
if (m_showWindow)
{
loadDataAndUpdate();
}
else
{
updateViewerWidget();
}
uiCapability()->updateUiIconFromToggleField();
}
else if (changedField == &m_userName ||
changedField == &m_showPlotTitle)
{
updateViewerWidgetWindowTitle();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setupBeforeSave()
{
if (m_qwtPlot && RiaApplication::instance()->mainPlotWindow())
{
this->setMdiWindowGeometry(RiaApplication::instance()->mainPlotWindow()->windowGeometryForViewer(m_qwtPlot));
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimSummaryPlot::snapshotWindowContent()
{
QImage image;
if (m_qwtPlot)
{
image = QImage(m_qwtPlot->size(), QImage::Format_ARGB32);
image.fill(QColor(Qt::white).rgb());
QPainter painter(&image);
QRectF rect(0, 0, m_qwtPlot->size().width(), m_qwtPlot->size().height());
QwtPlotRenderer plotRenderer;
plotRenderer.render(m_qwtPlot, &painter, rect);
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/)
{
uiTreeOrdering.add(&m_timeAxisProperties);
uiTreeOrdering.add(&m_leftYAxisProperties);
uiTreeOrdering.add(&m_rightYAxisProperties);
uiTreeOrdering.add(&m_curveFilters);
uiTreeOrdering.add(&m_curves);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::loadDataAndUpdate()
{
updateViewerWidget();
for (RimSummaryCurveFilter* curveFilter: m_curveFilters)
{
curveFilter->loadDataAndUpdate();
}
for (RimSummaryCurve* curve : m_curves)
{
curve->loadDataAndUpdate();
}
this->updateAxes();
updateZoomInQwt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateZoomInQwt()
{
if (!m_qwtPlot) return;
if (m_isAutoZoom)
{
zoomAll();
}
else
{
setZoomIntervalsInQwtPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setZoomIntervalsInQwtPlot()
{
QwtInterval left, right, time;
left.setMinValue(m_leftYAxisProperties->visibleRangeMin());
left.setMaxValue(m_leftYAxisProperties->visibleRangeMax());
right.setMinValue(m_rightYAxisProperties->visibleRangeMin());
right.setMaxValue(m_rightYAxisProperties->visibleRangeMax());
time.setMinValue(m_timeAxisProperties->visibleRangeMin());
time.setMaxValue(m_timeAxisProperties->visibleRangeMax());
m_qwtPlot->setZoomWindow(left, right, time);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateZoomFromQwt()
{
if (!m_qwtPlot) return;
QwtInterval left, right, time;
m_qwtPlot->currentVisibleWindow(&left, &right, &time);
setZoomWindow(left, right, time);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::disableAutoZoom()
{
m_isAutoZoom = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setDescription(const QString& description)
{
m_userName = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryPlot::description() const
{
return m_userName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateViewerWidget()
{
RiuMainPlotWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow();
if (!mainPlotWindow) return;
if (m_showWindow())
{
if (!m_qwtPlot)
{
m_qwtPlot = new RiuSummaryQwtPlot(this, mainPlotWindow);
for(RimSummaryCurveFilter* curveFilter: m_curveFilters)
{
curveFilter->setParentQwtPlot(m_qwtPlot);
}
for(RimSummaryCurve* curve : m_curves)
{
curve->setParentQwtPlot(m_qwtPlot);
}
mainPlotWindow->addViewer(m_qwtPlot, this->mdiWindowGeometry());
mainPlotWindow->setActiveViewer(m_qwtPlot);
}
updateViewerWidgetWindowTitle();
}
else
{
if (m_qwtPlot)
{
this->setMdiWindowGeometry(mainPlotWindow->windowGeometryForViewer(m_qwtPlot));
mainPlotWindow->removeViewer(m_qwtPlot);
detachAllCurves();
deletePlotWidget();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::updateViewerWidgetWindowTitle()
{
if (m_qwtPlot)
{
m_qwtPlot->setWindowTitle(m_userName);
if (m_showPlotTitle)
{
m_qwtPlot->setTitle(m_userName);
}
else
{
m_qwtPlot->setTitle("");
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::detachAllCurves()
{
for(RimSummaryCurveFilter* curveFilter: m_curveFilters)
{
curveFilter->detachQwtCurves();
}
for(RimSummaryCurve* curve : m_curves)
{
curve->detachQwtCurve();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurve* RimSummaryPlot::findRimCurveFromQwtCurve(const QwtPlotCurve* qwtCurve) const
{
for(RimSummaryCurve* rimCurve: m_curves)
{
if(rimCurve->qwtPlotCurve() == qwtCurve)
{
return rimCurve;
}
}
for (RimSummaryCurveFilter* curveFilter: m_curveFilters)
{
RimSummaryCurve* foundCurve = curveFilter->findRimCurveFromQwtCurve(qwtCurve);
if (foundCurve) return foundCurve;
}
return NULL;
}

View File

@@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmObject.h"
#include "cafPdmField.h"
#include "cafPdmChildArrayField.h"
#include "cafAppEnum.h"
#include "cafPdmChildField.h"
#include "RimDefines.h"
#include "RimViewWindow.h"
#include <QPointer>
#include <memory>
class RiuSummaryQwtPlot;
class RimSummaryCurve;
class RimSummaryCurveFilter;
class RimSummaryYAxisProperties;
class RimSummaryTimeAxisProperties;
class PdmUiTreeOrdering;
class QwtPlotCurve;
class QwtInterval;
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryPlot : public RimViewWindow
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryPlot();
virtual ~RimSummaryPlot();
void setDescription(const QString& description);
QString description() const;
void addCurve(RimSummaryCurve* curve);
void addCurveFilter(RimSummaryCurveFilter* curveFilter);
RimSummaryCurve* findRimCurveFromQwtCurve(const QwtPlotCurve* curve) const;
void loadDataAndUpdate();
void handleViewerDeletion();
void updateCaseNameHasChanged();
void updateAxes();
virtual void zoomAll() override;
void setZoomWindow(const QwtInterval& leftAxis,
const QwtInterval& rightAxis,
const QwtInterval& timeAxis);
void updateZoomInQwt();
void updateZoomFromQwt();
void disableAutoZoom();
bool isLogarithmicScaleEnabled(RimDefines::PlotAxis plotAxis) const;
void selectAxisInPropertyEditor(int axis);
virtual QWidget* viewWidget() override;
protected:
// Overridden PDM methods
virtual caf::PdmFieldHandle* objectToggleField() { return &m_showWindow; }
virtual caf::PdmFieldHandle* userDescriptionField() { return &m_userName; }
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void setupBeforeSave() override;
virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
virtual QImage snapshotWindowContent() override;
private:
void updateViewerWidget();
void updateViewerWidgetWindowTitle();
void detachAllCurves();
void deletePlotWidget();
void updateAxis(RimDefines::PlotAxis plotAxis);
std::vector<RimSummaryCurve*> curvesForAxis(RimDefines::PlotAxis plotAxis) const;
void updateTimeAxis();
void setZoomIntervalsInQwtPlot();
private:
caf::PdmField<bool> m_showWindow;
caf::PdmField<bool> m_showPlotTitle;
caf::PdmField<QString> m_userName;
caf::PdmChildArrayField<RimSummaryCurve*> m_curves;
caf::PdmChildArrayField<RimSummaryCurveFilter*> m_curveFilters;
caf::PdmField<bool> m_isAutoZoom;
caf::PdmChildField<RimSummaryYAxisProperties*> m_leftYAxisProperties;
caf::PdmChildField<RimSummaryYAxisProperties*> m_rightYAxisProperties;
caf::PdmChildField<RimSummaryTimeAxisProperties*> m_timeAxisProperties;
QPointer<RiuSummaryQwtPlot> m_qwtPlot;
// Internal objects managed by unique_ptr
std::unique_ptr<RimSummaryYAxisProperties> m_leftYAxisPropertiesObject;
std::unique_ptr<RimSummaryYAxisProperties> m_rightYAxisPropertiesObject;
std::unique_ptr<RimSummaryTimeAxisProperties> m_timeAxisPropertiesObject;
};

View File

@@ -0,0 +1,132 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryPlotCollection.h"
#include "RifEclipseSummaryTools.h"
#include "RifReaderEclipseSummary.h"
#include "RimEclipseResultCase.h"
#include "RimSummaryPlot.h"
#include "RimProject.h"
#include "RiuProjectPropertyView.h"
#include <QDockWidget>
#include "RiuMainWindow.h"
CAF_PDM_SOURCE_INIT(RimSummaryPlotCollection, "SummaryPlotCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryPlotCollection::RimSummaryPlotCollection()
{
CAF_PDM_InitObject("Summary Plots", ":/SummaryPlots16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_summaryPlots, "SummaryPlots", "Summary Plots", "", "", "");
m_summaryPlots.uiCapability()->setUiHidden(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryPlotCollection::~RimSummaryPlotCollection()
{
m_summaryPlots.deleteAllChildObjects();
for (auto it = m_summaryFileReaders.begin(); it != m_summaryFileReaders.end(); it++)
{
delete it->second;
}
m_summaryFileReaders.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseSummary* RimSummaryPlotCollection::getOrCreateSummaryFileReader(const QString& eclipseCaseFilePathBasename)
{
auto it = m_summaryFileReaders.find(eclipseCaseFilePathBasename);
if (it != m_summaryFileReaders.end())
{
return it->second;
}
else
{
return createSummaryFileReader(eclipseCaseFilePathBasename);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseSummary* RimSummaryPlotCollection::getOrCreateSummaryFileReader(const RimEclipseResultCase* eclipseCase)
{
if (!eclipseCase) return NULL;
QString caseName = eclipseCase->gridFileName();
QString caseNameWithNoExtension = caseName.remove(".egrid", Qt::CaseInsensitive);
QString caseNameAbsPath = caseNameWithNoExtension.replace("/", "\\");
return this->getOrCreateSummaryFileReader(caseNameAbsPath);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseSummary* RimSummaryPlotCollection::createSummaryFileReader(const QString& eclipseCaseFilePathBasename)
{
std::string headerFile;
bool isFormatted = false;
RifEclipseSummaryTools::findSummaryHeaderFile(eclipseCaseFilePathBasename.toStdString(), &headerFile, &isFormatted);
if (headerFile.empty()) return nullptr;
std::vector<std::string> dataFiles = RifEclipseSummaryTools::findSummaryDataFiles(eclipseCaseFilePathBasename.toStdString());
if (!dataFiles.size()) return nullptr;
RifReaderEclipseSummary* reader = new RifReaderEclipseSummary;
if (!reader->open(headerFile, dataFiles))
{
delete reader;
return nullptr;
}
else
{
m_summaryFileReaders.insert(std::make_pair(eclipseCaseFilePathBasename, reader));
return reader;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotCollection::updateSummaryNameHasChanged()
{
for (RimSummaryPlot* plot : m_summaryPlots)
{
plot->updateCaseNameHasChanged();
}
}

View File

@@ -0,0 +1,56 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <QPointer>
#include <QDockWidget>
class RimSummaryPlot;
class RicDropEnabledMainWindow;
class RifReaderEclipseSummary;
class RimEclipseResultCase;
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryPlotCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryPlotCollection();
virtual ~RimSummaryPlotCollection();
RifReaderEclipseSummary* getOrCreateSummaryFileReader(const RimEclipseResultCase* eclipseCase);
caf::PdmChildArrayField<RimSummaryPlot*> m_summaryPlots;
void updateSummaryNameHasChanged();
private:
RifReaderEclipseSummary* createSummaryFileReader(const QString& eclipseCaseFilePathBasename);
RifReaderEclipseSummary* getOrCreateSummaryFileReader(const QString& eclipseCaseFilePathBasename);
private:
// Map from path to case to summary file reader objects
std::map<QString, RifReaderEclipseSummary*> m_summaryFileReaders;
};

View File

@@ -0,0 +1,139 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryTimeAxisProperties.h"
#include "RimSummaryPlot.h"
#include "cafPdmUiLineEditor.h"
#include "qwt_date.h"
CAF_PDM_SOURCE_INIT(RimSummaryTimeAxisProperties, "SummaryTimeAxisProperties");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTimeAxisProperties::RimSummaryTimeAxisProperties()
{
CAF_PDM_InitObject("Time Axis", ":/SummaryPlot16x16.png", "", "");
CAF_PDM_InitField(&showTitle, "ShowTitle", false, "Show Title", "", "", "");
CAF_PDM_InitField(&title, "Title", QString("Time"), "Title", "", "", "");
CAF_PDM_InitField(&fontSize, "FontSize", 11, "Font Size", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_visibleRangeMax, "VisibleRangeMax", "Max", "", "", "");
m_visibleRangeMax.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_visibleRangeMin, "VisibleRangeMin", "Min", "", "", "");
m_visibleRangeMin.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSummaryTimeAxisProperties::visibleRangeMin() const
{
return QwtDate::toDouble(m_visibleRangeMin());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSummaryTimeAxisProperties::visibleRangeMax() const
{
return QwtDate::toDouble(m_visibleRangeMax());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTimeAxisProperties::setVisibleRangeMin(double value)
{
m_visibleRangeMin = QwtDate::toDateTime(value);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTimeAxisProperties::setVisibleRangeMax(double value)
{
m_visibleRangeMax = QwtDate::toDateTime(value);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSummaryTimeAxisProperties::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
*useOptionsOnly = true;
if (&fontSize == fieldNeedingOptions)
{
std::vector<int> fontSizes;
fontSizes.push_back(8);
fontSizes.push_back(10);
fontSizes.push_back(11);
fontSizes.push_back(12);
fontSizes.push_back(16);
fontSizes.push_back(24);
for (int value : fontSizes)
{
QString text = QString("%1").arg(value);
options.push_back(caf::PdmOptionItemInfo(text, value));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTimeAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimSummaryPlot* rimSummaryPlot = nullptr;
this->firstAncestorOrThisOfType(rimSummaryPlot);
if (changedField == &m_visibleRangeMax)
{
QDateTime test = newValue.toDateTime();
if (!test.isValid())
{
m_visibleRangeMax = oldValue.toDateTime();
}
rimSummaryPlot->disableAutoZoom();
}
else if (changedField == &m_visibleRangeMin)
{
QDateTime test = newValue.toDateTime();
if (!test.isValid())
{
m_visibleRangeMin = oldValue.toDateTime();
}
rimSummaryPlot->disableAutoZoom();
}
rimSummaryPlot->updateAxes();
}

View File

@@ -0,0 +1,58 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmObject.h"
#include "cafPdmField.h"
#include "cafPdmChildArrayField.h"
#include "cafAppEnum.h"
#include <QString>
#include <QDateTime>
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryTimeAxisProperties : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryTimeAxisProperties();
caf::PdmField<int> fontSize;
caf::PdmField<QString> title;
caf::PdmField<bool> showTitle;
double visibleRangeMin() const;
double visibleRangeMax() const;
void setVisibleRangeMin(double value);
void setVisibleRangeMax(double value);
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
//virtual caf::PdmFieldHandle* userDescriptionField() override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
private:
caf::PdmField<QDateTime> m_visibleRangeMin;
caf::PdmField<QDateTime> m_visibleRangeMax;
};

View File

@@ -0,0 +1,166 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryYAxisProperties.h"
#include "RimSummaryPlot.h"
#include "RimDefines.h"
namespace caf
{
template<>
void caf::AppEnum< RimSummaryYAxisProperties::NumberFormatType >::setUp()
{
addItem(RimSummaryYAxisProperties::NUMBER_FORMAT_AUTO, "NUMBER_FORMAT_AUTO", "Auto");
addItem(RimSummaryYAxisProperties::NUMBER_FORMAT_DECIMAL, "NUMBER_FORMAT_DECIMAL", "Decimal");
addItem(RimSummaryYAxisProperties::NUMBER_FORMAT_SCIENTIFIC,"NUMBER_FORMAT_SCIENTIFIC", "Scientific");
setDefault(RimSummaryYAxisProperties::NUMBER_FORMAT_AUTO);
}
}
CAF_PDM_SOURCE_INIT(RimSummaryYAxisProperties, "SummaryYAxisProperties");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryYAxisProperties::RimSummaryYAxisProperties()
{
CAF_PDM_InitObject("Y-Axis Properties", ":/SummaryPlot16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_name, "Name", "Name", "", "", "");
m_name.uiCapability()->setUiHidden(true);
CAF_PDM_InitField(&isAutoTitle, "AutoTitle", true, "Auto Title", "", "", "");
CAF_PDM_InitFieldNoDefault(&customTitle, "CustomTitle", "Title", "", "", "");
CAF_PDM_InitField(&fontSize, "FontSize", 11, "Font Size", "", "", "");
CAF_PDM_InitField(&visibleRangeMax, "VisibleRangeMax", RimDefines::maximumDefaultValuePlot(), "Max", "", "", "");
CAF_PDM_InitField(&visibleRangeMin, "VisibleRangeMin", RimDefines::minimumDefaultValuePlot(), "Min", "", "", "");
CAF_PDM_InitFieldNoDefault(&numberFormat, "NumberFormat", "Number Format", "", "", "");
CAF_PDM_InitField(&isLogarithmicScaleEnabled, "LogarithmicScale", false, "Logarithmic Scale", "", "", "");
updateOptionSensitivity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSummaryYAxisProperties::userDescriptionField()
{
return &m_name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSummaryYAxisProperties::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
*useOptionsOnly = true;
if (&fontSize == fieldNeedingOptions)
{
std::vector<int> fontSizes;
fontSizes.push_back(8);
fontSizes.push_back(10);
fontSizes.push_back(12);
fontSizes.push_back(16);
fontSizes.push_back(24);
for (int value : fontSizes)
{
QString text = QString("%1").arg(value);
options.push_back(caf::PdmOptionItemInfo(text, value));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryYAxisProperties::setNameAndAxis(const QString& name, QwtPlot::Axis axis)
{
m_name = name;
m_axis = axis;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtPlot::Axis RimSummaryYAxisProperties::axis() const
{
return m_axis;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryYAxisProperties::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimSummaryPlot* rimSummaryPlot = nullptr;
this->firstAncestorOrThisOfType(rimSummaryPlot);
if (changedField == &isAutoTitle)
{
updateOptionSensitivity();
}
else if (changedField == &visibleRangeMax)
{
if (visibleRangeMin > visibleRangeMax) visibleRangeMax = oldValue.toDouble();
rimSummaryPlot->disableAutoZoom();
}
else if (changedField == &visibleRangeMin)
{
if (visibleRangeMin > visibleRangeMax) visibleRangeMin = oldValue.toDouble();
rimSummaryPlot->disableAutoZoom();
}
if (changedField == &isLogarithmicScaleEnabled)
{
rimSummaryPlot->loadDataAndUpdate();
}
else
{
rimSummaryPlot->updateAxes();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryYAxisProperties::updateOptionSensitivity()
{
customTitle.uiCapability()->setUiReadOnly(isAutoTitle);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryYAxisProperties::initAfterRead()
{
updateOptionSensitivity();
}

View File

@@ -0,0 +1,77 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmObject.h"
#include "cafPdmField.h"
#include "cafPdmChildArrayField.h"
#include "cafAppEnum.h"
#include "qwt_plot.h"
#include <QString>
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryYAxisProperties : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum NumberFormatType
{
NUMBER_FORMAT_AUTO,
NUMBER_FORMAT_DECIMAL,
NUMBER_FORMAT_SCIENTIFIC
};
public:
RimSummaryYAxisProperties();
void setNameAndAxis(const QString& name, QwtPlot::Axis axis);
QwtPlot::Axis axis() const;
caf::PdmField<bool> isAutoTitle;
caf::PdmField<QString> customTitle;
caf::PdmField<int> fontSize;
caf::PdmField<double> visibleRangeMin;
caf::PdmField<double> visibleRangeMax;
caf::PdmField< caf::AppEnum< NumberFormatType > > numberFormat;
caf::PdmField<bool> isLogarithmicScaleEnabled;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual caf::PdmFieldHandle* userDescriptionField() override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
protected:
virtual void initAfterRead() override;
private:
void updateOptionSensitivity();
private:
caf::PdmField<QString> m_name;
QwtPlot::Axis m_axis;
};