Refactor ensemble import dialog

* #9773 Refactor ensemble import dialog.
* #9773 Add support for ensemble import of StimPlan/Reveal summary data.
* #9773 Add method for finding min and max time steps.
* #9773 Add option for resampling to hour intervals.
* #9773 Add option for resampling to minute intervals.
* #9773 Ensemble statistics: determine sub-sampling period dynamically.
* Use RiaWeightedMeanCalculator for curve resampling.
* Add HOUR and MINUTE to date time app enum.
* #9773 Generate better ensembles for StimPlan summaries.
* #9773 Fix parameters.txt lookup for StimPlan summaries
* Refactor: Improve interface of RicImportSummaryCasesFreature::createSummaryCasesFromFiles

Co-authored-by: Magne Sjaastad <magne.sjaastad@ceetronsolutions.com>
This commit is contained in:
Kristian Bendiksen
2023-04-20 10:16:43 +02:00
committed by GitHub
parent 67264da0a8
commit ff209ad7c2
34 changed files with 960 additions and 434 deletions

View File

@@ -46,6 +46,8 @@ template <>
void caf::AppEnum<RiaDefines::DateTimePeriod>::setUp()
{
addItem( RiaDefines::DateTimePeriod::NONE, "NONE", "None" );
addItem( RiaDefines::DateTimePeriod::MINUTE, "MINUTE", "Minute" );
addItem( RiaDefines::DateTimePeriod::HOUR, "HOUR", "Hour" );
addItem( RiaDefines::DateTimePeriod::DAY, "DAY", "Day" );
addItem( RiaDefines::DateTimePeriod::WEEK, "WEEK", "Week" );
addItem( RiaDefines::DateTimePeriod::MONTH, "MONTH", "Month" );

View File

@@ -45,6 +45,8 @@ enum class TimeFormatComponents
enum class DateTimePeriod
{
NONE = -1,
MINUTE,
HOUR,
DAY,
WEEK,
MONTH,

View File

@@ -22,6 +22,13 @@
namespace RiaDefines
{
enum class FileType
{
SMSPEC,
REVEAL_SUMMARY,
STIMPLAN_SUMMARY
};
QString summaryField();
QString summaryAquifer();
QString summaryNetwork();

View File

@@ -133,6 +133,106 @@ std::vector<QStringList> RiaEnsembleNameTools::groupFilesByEnsemble( const QStri
return groupedByIteration;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<QString, QStringList> RiaEnsembleNameTools::groupFilesByStimPlanEnsemble( const QStringList& fileNames )
{
std::vector<QStringList> componentsForAllFilePaths;
for ( const auto& filePath : fileNames )
{
QStringList components = RiaFilePathTools::splitPathIntoComponents( filePath );
componentsForAllFilePaths.push_back( components );
}
auto mapping = findUniqueStimPlanEnsembleNames( fileNames, componentsForAllFilePaths );
std::set<QString> iterations;
for ( const auto& [name, iterFileNamePair] : mapping )
{
iterations.insert( iterFileNamePair.first );
}
std::map<QString, QStringList> groupedByIteration;
for ( const QString& groupIteration : iterations )
{
QStringList fileNamesFromIteration;
for ( const auto& [name, iterFileNamePair] : mapping )
{
QString iteration = iterFileNamePair.first;
QString fileName = iterFileNamePair.second;
if ( groupIteration == iteration )
{
fileNamesFromIteration << fileName;
}
}
groupedByIteration[groupIteration] = fileNamesFromIteration;
}
return groupedByIteration;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<QString, std::pair<QString, QString>>
RiaEnsembleNameTools::findUniqueStimPlanEnsembleNames( const QStringList& fileNames, const std::vector<QStringList>& fileNameComponents )
{
CAF_ASSERT( fileNames.size() == static_cast<int>( fileNameComponents.size() ) );
struct StimPlanComponents
{
QString realization;
QString iteration;
QString well;
QString fracture;
QString job;
QString fileName;
};
std::vector<StimPlanComponents> comps;
int i = 0;
for ( const auto& fileComponents : fileNameComponents )
{
int numComponents = fileComponents.size();
if ( numComponents >= 7 )
{
StimPlanComponents c;
c.fileName = fileNames[i];
c.fracture = fileComponents[numComponents - 2];
c.iteration = fileComponents[numComponents - 6];
c.realization = fileComponents[numComponents - 7];
QString wellJobComponent = fileComponents[numComponents - 3];
QStringList parts = wellJobComponent.split( "_" );
if ( parts.size() == 4 )
{
c.well = parts[0];
c.job = parts[3];
}
comps.push_back( c );
}
i++;
}
std::map<QString, std::pair<QString, QString>> mapping;
for ( const StimPlanComponents& c : comps )
{
QString key = QString( "%1, %2, %3, %4, %5" ).arg( c.iteration, c.realization, c.well, c.fracture, c.job );
QString iteration = QString( "%1, %2, %3, %4" ).arg( c.iteration, c.well, c.fracture, c.job );
mapping[key] = std::make_pair( iteration, c.fileName );
}
return mapping;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -49,7 +49,11 @@ public:
const std::map<QString, QStringList>& keyFileComponentsForAllFiles,
const QString& ensembleCaseName );
static std::vector<QStringList> groupFilesByEnsemble( const QStringList& fileNames, EnsembleGroupingMode groupingMode );
static std::vector<QStringList> groupFilesByEnsemble( const QStringList& fileNames, EnsembleGroupingMode groupingMode );
static std::map<QString, QStringList> groupFilesByStimPlanEnsemble( const QStringList& fileNames );
static std::map<QString, std::pair<QString, QString>>
findUniqueStimPlanEnsembleNames( const QStringList& fileNames, const std::vector<QStringList>& fileNameComponents );
static QString uniqueShortNameForEnsembleCase( RimSummaryCase* summaryCase );
static QString uniqueShortNameForSummaryCase( RimSummaryCase* summaryCase );

View File

@@ -21,6 +21,7 @@
#include <QDateTime>
#include <QLocale>
#include <QString>
#include <QTime>
#include "cafPdmUiItem.h"
@@ -32,6 +33,8 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const DateTimeSpan RiaQDateTimeTools::TIMESPAN_MINUTE = DateTimeSpan( 0, 0, 0, 0, 1 );
const DateTimeSpan RiaQDateTimeTools::TIMESPAN_HOUR = DateTimeSpan( 0, 0, 0, 1 );
const DateTimeSpan RiaQDateTimeTools::TIMESPAN_DAY = DateTimeSpan( 0, 0, 1 );
const DateTimeSpan RiaQDateTimeTools::TIMESPAN_WEEK = DateTimeSpan( 0, 0, 7 );
const DateTimeSpan RiaQDateTimeTools::TIMESPAN_MONTH = DateTimeSpan( 0, 1, 0 );
@@ -48,6 +51,22 @@ Qt::TimeSpec RiaQDateTimeTools::currentTimeSpec()
return Qt::UTC;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
quint64 RiaQDateTimeTools::secondsInMinute()
{
return 60;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
quint64 RiaQDateTimeTools::secondsInHour()
{
return 60 * 60;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -142,7 +161,12 @@ QDateTime RiaQDateTimeTools::addYears( const QDateTime& dt, double years )
//--------------------------------------------------------------------------------------------------
QDateTime RiaQDateTimeTools::addSpan( const QDateTime& dt, DateTimeSpan span )
{
return createUtcDateTime( dt ).addYears( span.years() ).addMonths( span.months() ).addDays( span.days() );
return createUtcDateTime( dt )
.addYears( span.years() )
.addMonths( span.months() )
.addDays( span.days() )
.addSecs( span.hours() * RiaQDateTimeTools::secondsInHour() )
.addSecs( span.minutes() * RiaQDateTimeTools::secondsInMinute() );
}
//--------------------------------------------------------------------------------------------------
@@ -150,7 +174,12 @@ QDateTime RiaQDateTimeTools::addSpan( const QDateTime& dt, DateTimeSpan span )
//--------------------------------------------------------------------------------------------------
QDateTime RiaQDateTimeTools::subtractSpan( const QDateTime& dt, DateTimeSpan span )
{
return createUtcDateTime( dt ).addYears( -span.years() ).addMonths( -span.months() ).addDays( -span.days() );
return createUtcDateTime( dt )
.addYears( -span.years() )
.addMonths( -span.months() )
.addDays( -span.days() )
.addSecs( -span.hours() * RiaQDateTimeTools::secondsInHour() )
.addSecs( -span.minutes() * RiaQDateTimeTools::secondsInMinute() );
}
//--------------------------------------------------------------------------------------------------
@@ -250,6 +279,10 @@ const DateTimeSpan RiaQDateTimeTools::timeSpan( RiaDefines::DateTimePeriod perio
{
switch ( period )
{
case RiaDefines::DateTimePeriod::MINUTE:
return TIMESPAN_MINUTE;
case RiaDefines::DateTimePeriod::HOUR:
return TIMESPAN_HOUR;
case RiaDefines::DateTimePeriod::DAY:
return TIMESPAN_DAY;
case RiaDefines::DateTimePeriod::WEEK:
@@ -274,13 +307,19 @@ const DateTimeSpan RiaQDateTimeTools::timeSpan( RiaDefines::DateTimePeriod perio
//--------------------------------------------------------------------------------------------------
QDateTime RiaQDateTimeTools::truncateTime( const QDateTime& dt, RiaDefines::DateTimePeriod period )
{
int y = dt.date().year();
int m = dt.date().month();
int d = dt.date().day();
int dow = dt.date().dayOfWeek();
int y = dt.date().year();
int m = dt.date().month();
int d = dt.date().day();
int dow = dt.date().dayOfWeek();
int h = dt.time().hour();
int minute = dt.time().minute();
switch ( period )
{
case RiaDefines::DateTimePeriod::MINUTE:
return createUtcDateTime( QDate( y, m, d ), QTime( h, minute, 0 ) );
case RiaDefines::DateTimePeriod::HOUR:
return createUtcDateTime( QDate( y, m, d ), QTime( h, 0, 0 ) );
case RiaDefines::DateTimePeriod::DAY:
return createUtcDateTime( QDate( y, m, d ) );
case RiaDefines::DateTimePeriod::WEEK:

View File

@@ -99,6 +99,8 @@ public:
getTimeStepsWithinSelectedRange( const std::vector<QDateTime>& timeSteps, const QDateTime& fromTimeStep, const QDateTime& toTimeStep );
private:
static const DateTimeSpan TIMESPAN_MINUTE;
static const DateTimeSpan TIMESPAN_HOUR;
static const DateTimeSpan TIMESPAN_DAY;
static const DateTimeSpan TIMESPAN_WEEK;
static const DateTimeSpan TIMESPAN_MONTH;
@@ -109,6 +111,8 @@ private:
static quint64 secondsInDay();
static quint64 secondsInYear();
static quint64 secondsInHour();
static quint64 secondsInMinute();
};
//==================================================================================================
@@ -121,23 +125,31 @@ public:
: m_years( 0 )
, m_months( 0 )
, m_days( 0 )
, m_hours( 0 )
, m_minutes( 0 )
{
}
DateTimeSpan( int years, int months, int days )
DateTimeSpan( int years, int months, int days, int hours = 0, int minutes = 0 )
: m_years( years )
, m_months( months )
, m_days( days )
, m_hours( hours )
, m_minutes( minutes )
{
}
int years() const { return m_years; }
int months() const { return m_months; }
int days() const { return m_days; }
int hours() const { return m_hours; }
int minutes() const { return m_minutes; }
bool isEmpty() { return m_years == 0 && m_months == 0 && m_days; }
bool isEmpty() { return m_years == 0 && m_months == 0 && m_days == 0 && m_hours == 0 && m_minutes == 0; }
private:
int m_years;
int m_months;
int m_days;
int m_hours;
int m_minutes;
};

View File

@@ -21,6 +21,7 @@
#include "RiaQDateTimeTools.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "RiaWeightedMeanCalculator.h"
#include <limits>
@@ -125,8 +126,6 @@ std::vector<time_t> RiaTimeHistoryCurveResampler::timeStepsFromTimeRange( RiaDef
//--------------------------------------------------------------------------------------------------
void RiaTimeHistoryCurveResampler::computeWeightedMeanValues( RiaDefines::DateTimePeriod period )
{
size_t origDataSize = m_originalValues.second.size();
size_t oi = 0;
const auto& origTimeSteps = m_originalValues.second;
const auto& origValues = m_originalValues.first;
@@ -138,15 +137,19 @@ void RiaTimeHistoryCurveResampler::computeWeightedMeanValues( RiaDefines::DateTi
computeResampledTimeSteps( period );
m_values.reserve( m_timeSteps.size() );
size_t origDataSize = origValues.size();
size_t oi = 0;
for ( size_t i = 0; i < m_timeSteps.size(); i++ )
{
double wMean = 0.0;
time_t periodStart =
i > 0 ? m_timeSteps[i - 1]
: RiaQDateTimeTools::subtractPeriod( RiaQDateTimeTools::fromTime_t( m_timeSteps[0] ), period ).toSecsSinceEpoch();
time_t periodEnd = m_timeSteps[i];
time_t periodLength = periodEnd - periodStart;
RiaWeightedMeanCalculator<double> calc;
while ( true )
{
time_t origTimeStep = 0;
@@ -169,7 +172,7 @@ void RiaTimeHistoryCurveResampler::computeWeightedMeanValues( RiaDefines::DateTi
{
if ( origTimeStep == m_timeSteps[i] )
{
wMean += origValue;
calc.addValueAndWeight( origValue, periodLength );
oi++;
break;
}
@@ -179,7 +182,7 @@ void RiaTimeHistoryCurveResampler::computeWeightedMeanValues( RiaDefines::DateTi
time_t startTime = oi > 0 ? std::max( origTimeSteps[oi - 1], periodStart ) : periodStart;
time_t endTime = std::min( origTimeStep, periodEnd );
wMean += origValue * ( endTime - startTime ) / periodLength;
calc.addValueAndWeight( origValue, endTime - startTime );
if ( origTimeStep > m_timeSteps[i] ) break;
if ( origTimeStep == m_timeSteps[i] )
@@ -190,7 +193,7 @@ void RiaTimeHistoryCurveResampler::computeWeightedMeanValues( RiaDefines::DateTi
oi++;
}
m_values.push_back( wMean );
m_values.push_back( calc.weightedMean() );
}
}

View File

@@ -130,12 +130,15 @@ std::pair<QStringList, RiaEnsembleNameTools::EnsembleGroupingMode>
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( pathCacheName );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList( ".xml" ) );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
{
RicRecursiveFileSearchDialog::FileType::STIMPLAN_FRACTURE,
} );
// Remember filters
m_pathFilter = result.pathFilter;

View File

@@ -49,12 +49,13 @@ void RicCreateGridCaseGroupFromFilesFeature::onActionTriggered( bool isChecked )
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( "INPUT_FILES" );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Create Grid Case Group",
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList( ".EGRID" ) );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Create Grid Case Group",
defaultDir,
m_pathFilter,
m_fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::EGRID } );
// Remember filters
m_pathFilter = result.pathFilter;

View File

@@ -52,13 +52,14 @@ void RicImportEclipseCasesFeature::onActionTriggered( bool isChecked )
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( "BINARY_GRID" );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Import Eclipse Cases",
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList() << ".EGRID"
<< ".GRID" );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Import Eclipse Cases",
defaultDir,
m_pathFilter,
m_fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::EGRID,
RicRecursiveFileSearchDialog::FileType::GRID } );
// Remember filters
m_pathFilter = result.pathFilter;

View File

@@ -55,12 +55,13 @@ void RicCreateEnsembleSurfaceFeature::openDialogAndExecuteCommand()
QString pathFilter( "*" );
QString fileNameFilter( "*" );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
QStringList( ".EGRID" ) );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::EGRID } );
if ( !result.ok || result.files.isEmpty() )
{

View File

@@ -71,13 +71,14 @@ void RicCreateEnsembleWellLogFeature::openDialogAndExecuteCommand()
QString pathFilter( "*" );
QString fileNameFilter( "*" );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
{ ".GRDECL", ".EGRID" } );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::GRDECL,
RicRecursiveFileSearchDialog::FileType::EGRID } );
if ( !result.ok || result.files.isEmpty() )
{
return;

View File

@@ -22,6 +22,7 @@
#include "RiaEnsembleNameTools.h"
#include "RiaFilePathTools.h"
#include "RiaPreferences.h"
#include "RiaSummaryDefines.h"
#include "RiaSummaryTools.h"
#include "RiaTextStringTools.h"
@@ -70,23 +71,37 @@ bool RicImportEnsembleFeature::isCommandEnabled()
void RicImportEnsembleFeature::onActionTriggered( bool isChecked )
{
QString pathCacheName = "ENSEMBLE_FILES";
auto [fileNames, ensembleGroupingMode] =
RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialogWithGrouping( "Import Ensemble", pathCacheName );
auto result = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialogWithGrouping( "Import Ensemble", pathCacheName );
QStringList fileNames = result.files;
RiaEnsembleNameTools::EnsembleGroupingMode ensembleGroupingMode = result.groupingMode;
RiaDefines::FileType fileType = RicRecursiveFileSearchDialog::mapSummaryFileType( result.fileType );
if ( fileNames.isEmpty() ) return;
if ( ensembleGroupingMode == RiaEnsembleNameTools::EnsembleGroupingMode::NONE )
{
bool useEnsembleNameDialog = true;
importSingleEnsemble( fileNames, useEnsembleNameDialog, ensembleGroupingMode );
importSingleEnsemble( fileNames, useEnsembleNameDialog, ensembleGroupingMode, fileType );
}
else
{
std::vector<QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByEnsemble( fileNames, ensembleGroupingMode );
for ( const QStringList& groupedFileNames : groupedByEnsemble )
if ( fileType == RiaDefines::FileType::STIMPLAN_SUMMARY )
{
bool useEnsembleNameDialog = false;
importSingleEnsemble( groupedFileNames, useEnsembleNameDialog, ensembleGroupingMode );
std::map<QString, QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByStimPlanEnsemble( fileNames );
for ( const auto& [ensembleName, groupedFileNames] : groupedByEnsemble )
{
bool useEnsembleNameDialog = false;
importSingleEnsemble( groupedFileNames, useEnsembleNameDialog, ensembleGroupingMode, fileType, ensembleName );
}
}
else
{
std::vector<QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByEnsemble( fileNames, ensembleGroupingMode );
for ( const QStringList& groupedFileNames : groupedByEnsemble )
{
bool useEnsembleNameDialog = false;
importSingleEnsemble( groupedFileNames, useEnsembleNameDialog, ensembleGroupingMode, fileType );
}
}
}
}
@@ -96,18 +111,21 @@ void RicImportEnsembleFeature::onActionTriggered( bool isChecked )
//--------------------------------------------------------------------------------------------------
void RicImportEnsembleFeature::importSingleEnsemble( const QStringList& fileNames,
bool useEnsembleNameDialog,
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode )
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode,
RiaDefines::FileType fileType,
const QString& defaultEnsembleName )
{
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( fileNames, groupingMode );
QString ensembleName = !defaultEnsembleName.isEmpty() ? defaultEnsembleName
: RiaEnsembleNameTools::findSuitableEnsembleName( fileNames, groupingMode );
if ( useEnsembleNameDialog ) ensembleName = askForEnsembleName( ensembleName );
if ( ensembleName.isEmpty() ) return;
std::vector<RimSummaryCase*> cases;
RicImportSummaryCasesFeature::createSummaryCasesFromFiles( fileNames, &cases, true );
RicImportSummaryCasesFeature::CreateConfig createConfig{ .fileType = fileType, .ensembleOrGroup = true, .allowDialogs = true };
auto [isOk, cases] = RicImportSummaryCasesFeature::createSummaryCasesFromFiles( fileNames, createConfig );
if ( cases.empty() ) return;
if ( !isOk || cases.empty() ) return;
RimSummaryCaseCollection* ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases( cases, ensembleName, true );
@@ -124,7 +142,7 @@ void RicImportEnsembleFeature::importSingleEnsemble( const QStringList&
std::vector<RimCase*> allCases;
RiaApplication::instance()->project()->allCases( allCases );
if ( allCases.size() == 0 )
if ( allCases.empty() )
{
RiuMainWindow::closeIfOpen();
}

View File

@@ -19,6 +19,7 @@
#pragma once
#include "RiaEnsembleNameTools.h"
#include "RiaSummaryDefines.h"
#include "cafCmdFeature.h"
@@ -41,5 +42,7 @@ protected:
static QString askForEnsembleName( const QString& suggestion );
static void importSingleEnsemble( const QStringList& fileNames,
bool useEnsembleNameDialog,
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode );
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode,
RiaDefines::FileType fileType,
const QString& defaultEnsembleName = QString() );
};

View File

@@ -188,13 +188,13 @@ std::pair<QStringList, RiaEnsembleNameTools::EnsembleGroupingMode>
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( pathCacheName );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList() << ".TS"
<< ".ts" );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::SURFACE } );
// Remember filters
m_pathFilter = result.pathFilter;

View File

@@ -138,13 +138,13 @@ std::pair<QStringList, RiaEnsembleNameTools::EnsembleGroupingMode>
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( pathCacheName );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList() << ".LAS"
<< ".las" );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::LAS } );
// Remember filters
m_pathFilter = result.pathFilter;

View File

@@ -353,8 +353,8 @@ bool RicImportGeneralDataFeature::openInputEclipseCaseFromFileNames( const QStri
//--------------------------------------------------------------------------------------------------
bool RicImportGeneralDataFeature::openSummaryCaseFromFileNames( const QStringList& fileNames, bool doCreateDefaultPlot )
{
std::vector<RimSummaryCase*> newCases;
if ( RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( fileNames, doCreateDefaultPlot, &newCases ) )
auto [isOk, newCases] = RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( fileNames, doCreateDefaultPlot );
if ( isOk )
{
RicImportSummaryCasesFeature::addCasesToGroupIfRelevant( newCases );
for ( const RimSummaryCase* newCase : newCases )

View File

@@ -18,6 +18,7 @@
#include "RicImportSummaryCasesFeature.h"
#include "RiaSummaryDefines.h"
#include "SummaryPlotCommands/RicNewSummaryCurveFeature.h"
#include "RiaGuiApplication.h"
@@ -73,12 +74,19 @@ bool RicImportSummaryCasesFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicImportSummaryCasesFeature::onActionTriggered( bool isChecked )
{
RiaGuiApplication* app = RiaGuiApplication::instance();
QString pathCacheName = "INPUT_FILES";
QStringList fileNames = runRecursiveSummaryCaseFileSearchDialog( "Import Summary Cases", pathCacheName );
RiaGuiApplication* app = RiaGuiApplication::instance();
QString pathCacheName = "INPUT_FILES";
auto result = runRecursiveSummaryCaseFileSearchDialog( "Import Summary Cases", pathCacheName );
QStringList fileNames = result.files;
RiaDefines::FileType fileType = RicRecursiveFileSearchDialog::mapSummaryFileType( result.fileType );
std::vector<RimSummaryCase*> cases;
if ( !fileNames.isEmpty() ) createSummaryCasesFromFiles( fileNames, &cases );
if ( !fileNames.isEmpty() )
{
CreateConfig createConfig{ .fileType = fileType, .ensembleOrGroup = false, .allowDialogs = true };
auto [isOk, cases] = createSummaryCasesFromFiles( fileNames, createConfig );
}
addSummaryCases( cases );
if ( !cases.empty() )
@@ -121,21 +129,21 @@ void RicImportSummaryCasesFeature::setupActionLook( QAction* actionToSetup )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( const QStringList& fileNames,
bool doCreateDefaultPlot,
std::vector<RimSummaryCase*>* newCases )
std::pair<bool, std::vector<RimSummaryCase*>> RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( const QStringList& fileNames,
bool doCreateDefaultPlot )
{
RiaGuiApplication* app = RiaGuiApplication::instance();
std::vector<RimSummaryCase*> temp;
std::vector<RimSummaryCase*>* cases = newCases ? newCases : &temp;
if ( createSummaryCasesFromFiles( fileNames, cases ) )
CreateConfig createConfig{ .fileType = RiaDefines::FileType::SMSPEC, .ensembleOrGroup = false, .allowDialogs = true };
auto [isOk, cases] = createSummaryCasesFromFiles( fileNames, createConfig );
if ( isOk )
{
addSummaryCases( *cases );
if ( !cases->empty() && doCreateDefaultPlot )
addSummaryCases( cases );
if ( !cases.empty() && doCreateDefaultPlot )
{
RimSummaryMultiPlot* plotToSelect = nullptr;
for ( auto sumCase : *cases )
for ( auto sumCase : cases )
{
plotToSelect = RicSummaryPlotBuilder::createAndAppendDefaultSummaryMultiPlot( { sumCase }, {} );
}
@@ -147,7 +155,7 @@ bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( const QStr
}
RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow();
if ( mainPlotWindow && !cases->empty() )
if ( mainPlotWindow && !cases.empty() )
{
mainPlotWindow->updateMultiPlotToolBar();
@@ -160,53 +168,64 @@ bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles( const QStr
RiuMainWindow::closeIfOpen();
}
}
return true;
return std::make_pair( true, cases );
}
return false;
return std::make_pair( false, cases );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicImportSummaryCasesFeature::createSummaryCasesFromFiles( const QStringList& fileNames,
std::vector<RimSummaryCase*>* newCases,
bool ensembleOrGroup,
bool allowDialogs )
std::pair<bool, std::vector<RimSummaryCase*>> RicImportSummaryCasesFeature::createSummaryCasesFromFiles( const QStringList& fileNames,
CreateConfig createConfig )
{
RiaApplication* app = RiaApplication::instance();
RimProject* proj = app->project();
RimSummaryCaseMainCollection* sumCaseColl = proj->activeOilField() ? proj->activeOilField()->summaryCaseMainCollection() : nullptr;
if ( newCases ) newCases->clear();
if ( !sumCaseColl ) return false;
std::vector<RimSummaryCase*> newCases;
RifSummaryCaseRestartSelector fileSelector;
if ( !sumCaseColl ) return std::make_pair( false, newCases );
if ( !RiaGuiApplication::isRunning() || !allowDialogs )
std::vector<RifSummaryCaseFileResultInfo> importFileInfos;
if ( createConfig.fileType == RiaDefines::FileType::SMSPEC )
{
fileSelector.showDialog( false );
RifSummaryCaseRestartSelector fileSelector;
if ( !RiaGuiApplication::isRunning() || !createConfig.allowDialogs )
{
fileSelector.showDialog( false );
}
fileSelector.setEnsembleOrGroupMode( createConfig.ensembleOrGroup );
fileSelector.determineFilesToImportFromSummaryFiles( fileNames );
importFileInfos = fileSelector.summaryFileInfos();
if ( fileSelector.foundErrors() )
{
QString errorMessage = fileSelector.createCombinedErrorMessage();
RiaLogging::error( errorMessage );
}
}
else
{
// No restart files for these file types: just copy to result info
for ( auto f : fileNames )
{
importFileInfos.push_back( RifSummaryCaseFileResultInfo( f, false, createConfig.fileType ) );
}
}
fileSelector.setEnsembleOrGroupMode( ensembleOrGroup );
fileSelector.determineFilesToImportFromSummaryFiles( fileNames );
std::vector<RifSummaryCaseFileResultInfo> importFileInfos = fileSelector.summaryFileInfos();
if ( !importFileInfos.empty() )
{
std::vector<RimSummaryCase*> sumCases = sumCaseColl->createSummaryCasesFromFileInfos( importFileInfos, true );
if ( newCases ) newCases->insert( newCases->end(), sumCases.begin(), sumCases.end() );
newCases.insert( newCases.end(), sumCases.begin(), sumCases.end() );
}
if ( fileSelector.foundErrors() )
{
QString errorMessage = fileSelector.createCombinedErrorMessage();
RiaLogging::error( errorMessage );
}
return true;
return std::make_pair( true, newCases );
}
//--------------------------------------------------------------------------------------------------
@@ -258,36 +277,36 @@ void RicImportSummaryCasesFeature::addCasesToGroupIfRelevant( const std::vector<
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<QStringList, RiaEnsembleNameTools::EnsembleGroupingMode>
RicRecursiveFileSearchDialogResult
RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialogWithGrouping( const QString& dialogTitle, const QString& pathCacheName )
{
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( pathCacheName );
RicRecursiveFileSearchDialogResult result = RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
dialogTitle,
defaultDir,
m_pathFilter,
m_fileNameFilter,
QStringList( ".SMSPEC" ) );
auto fileTypes = { RicRecursiveFileSearchDialog::FileType::SMSPEC,
RicRecursiveFileSearchDialog::FileType::REVEAL_SUMMARY,
RicRecursiveFileSearchDialog::FileType::STIMPLAN_SUMMARY };
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr, dialogTitle, defaultDir, m_pathFilter, m_fileNameFilter, fileTypes );
// Remember filters
m_pathFilter = result.pathFilter;
m_fileNameFilter = result.fileNameFilter;
if ( !result.ok ) return std::make_pair( QStringList(), RiaEnsembleNameTools::EnsembleGroupingMode::NONE );
if ( !result.ok ) return result;
// Remember the path to next time
app->setLastUsedDialogDirectory( pathCacheName, QFileInfo( result.rootDir ).absoluteFilePath() );
return std::make_pair( result.files, result.groupingMode );
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog( const QString& dialogTitle, const QString& pathCacheName )
RicRecursiveFileSearchDialogResult RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog( const QString& dialogTitle,
const QString& pathCacheName )
{
auto result = runRecursiveSummaryCaseFileSearchDialogWithGrouping( dialogTitle, pathCacheName );
return result.first;
return runRecursiveSummaryCaseFileSearchDialogWithGrouping( dialogTitle, pathCacheName );
}

View File

@@ -19,7 +19,9 @@
#pragma once
#include "RiaEnsembleNameTools.h"
#include "RiaSummaryDefines.h"
#include "RicRecursiveFileSearchDialog.h"
#include "cafCmdFeature.h"
#include <QString>
@@ -38,20 +40,26 @@ class RicImportSummaryCasesFeature : public caf::CmdFeature
public:
RicImportSummaryCasesFeature() {}
static bool createAndAddSummaryCasesFromFiles( const QStringList& fileName,
bool doCreateDefaultPlot,
std::vector<RimSummaryCase*>* newCases = nullptr );
static bool createSummaryCasesFromFiles( const QStringList& fileName,
std::vector<RimSummaryCase*>* newCases,
bool ensembleOrGroup = false,
bool allowDialogs = true );
static std::pair<bool, std::vector<RimSummaryCase*>> createAndAddSummaryCasesFromFiles( const QStringList& fileName,
bool doCreateDefaultPlot );
struct CreateConfig
{
RiaDefines::FileType fileType;
bool ensembleOrGroup;
bool allowDialogs;
};
static std::pair<bool, std::vector<RimSummaryCase*>> createSummaryCasesFromFiles( const QStringList& fileName, CreateConfig createConfig );
static void addSummaryCases( const std::vector<RimSummaryCase*>& cases );
static void addCasesToGroupIfRelevant( const std::vector<RimSummaryCase*>& cases );
static QStringList runRecursiveSummaryCaseFileSearchDialog( const QString& dialogTitle, const QString& pathCacheName );
static RicRecursiveFileSearchDialogResult runRecursiveSummaryCaseFileSearchDialog( const QString& dialogTitle,
const QString& pathCacheName );
static std::pair<QStringList, RiaEnsembleNameTools::EnsembleGroupingMode>
runRecursiveSummaryCaseFileSearchDialogWithGrouping( const QString& dialogTitle, const QString& pathCacheName );
static RicRecursiveFileSearchDialogResult runRecursiveSummaryCaseFileSearchDialogWithGrouping( const QString& dialogTitle,
const QString& pathCacheName );
protected:
bool isCommandEnabled() override;

View File

@@ -21,6 +21,7 @@
#include "RiaGuiApplication.h"
#include "RiaPreferences.h"
#include "RiaSummaryDefines.h"
#include "RicCreateSummaryCaseCollectionFeature.h"
#include "RicImportSummaryCasesFeature.h"
@@ -55,12 +56,14 @@ void RicImportSummaryGroupFeature::onActionTriggered( bool isChecked )
{
RiaGuiApplication* app = RiaGuiApplication::instance();
QString pathCacheName = "INPUT_FILES";
QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog( "Import Summary Case Group", pathCacheName );
auto result = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog( "Import Summary Case Group", pathCacheName );
QStringList fileNames = result.files;
if ( fileNames.isEmpty() ) return;
std::vector<RimSummaryCase*> cases;
RicImportSummaryCasesFeature::createSummaryCasesFromFiles( fileNames, &cases, true );
RiaDefines::FileType fileType = RicRecursiveFileSearchDialog::mapSummaryFileType( result.fileType );
RicImportSummaryCasesFeature::CreateConfig createConfig{ .fileType = fileType, .ensembleOrGroup = true, .allowDialogs = true };
auto [isOk, cases] = RicImportSummaryCasesFeature::createSummaryCasesFromFiles( fileNames, createConfig );
RicImportSummaryCasesFeature::addSummaryCases( cases );
RicCreateSummaryCaseCollectionFeature::groupSummaryCases( cases, "", false );

View File

@@ -25,6 +25,7 @@
#include "RiuFileDialogTools.h"
#include "RiuTools.h"
#include "opm/io/eclipse/EclUtil.hpp"
#include <QAbstractItemView>
#include <QAction>
@@ -58,25 +59,24 @@
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
static QStringList trimLeftStrings( const QStringList& strings, const QString& trimText );
static void sortStringsByLength( QStringList& strings, bool ascending = true );
static void sortStringsByLength( QStringList& strings, bool ascending = true );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog( QWidget* parent,
const QString& caption,
const QString& dir,
const QString& pathFilter,
const QString& fileNameFilter,
const QStringList& fileExtensions )
RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSearchDialog( QWidget* parent,
const QString& caption,
const QString& dir,
const QString& pathFilter,
const QString& fileNameFilter,
const std::vector<FileType>& fileTypes )
{
const QString filePathRegistryKey = QString( "RicRecursiveFileSearchDialog %1" ).arg( caption ).replace( " ", "_" );
const QString fileFilterRegistryKey = QString( "RicRecursiveFileSearchDialog file filter %1" ).arg( caption ).replace( " ", "_" );
const QString useRealizationStarRegistryKey = "RecursiveFileSearchDialog_use_realization";
QSettings settings;
RicRecursiveFileSearchDialog dialog( parent, fileExtensions );
RicRecursiveFileSearchDialog dialog( parent, fileTypes );
{
QSignalBlocker signalBlocker( dialog.m_pathFilterField );
QSignalBlocker signalBlocker2( dialog.m_ensembleGroupingMode );
@@ -89,8 +89,11 @@ RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSea
dialog.m_fileFilterField->addItem( fileNameFilter );
dialog.m_pathFilterField->addItem( QDir::toNativeSeparators( pathFilterText ) );
QString joined = fileExtensions.join( '|' );
dialog.m_fileExtensionsField->setText( joined );
for ( const auto& fileType : fileTypes )
{
QString item = QString( "%1 (%2)" ).arg( fileNameForType( fileType ) ).arg( fileExtensionForType( fileType ) );
dialog.m_fileTypeField->addItem( item, static_cast<int>( fileType ) );
}
dialog.m_fileFilterField->addItem( fileNameFilter );
@@ -107,7 +110,11 @@ RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSea
dialog.m_pathFilterField->setCurrentText( QDir::toNativeSeparators( pathFilterText ) );
dialog.m_pathFilterField->setEditable( true );
dialog.m_fileExtensions = trimLeftStrings( fileExtensions, "." );
if ( !fileTypes.empty() )
{
dialog.m_fileExtensions = QStringList( fileExtensionForType( fileTypes.front() ) );
dialog.m_fileType = fileTypes.front();
}
for ( const auto& s : caf::AppEnum<RiaEnsembleNameTools::EnsembleGroupingMode>::uiTexts() )
{
@@ -144,15 +151,16 @@ RicRecursiveFileSearchDialogResult RicRecursiveFileSearchDialog::runRecursiveSea
dialog.rootDirWithEndSeparator(),
dialog.pathFilterWithoutStartSeparator(),
dialog.fileNameFilter(),
dialog.fileType(),
dialog.ensembleGroupingMode() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, const QStringList& fileExtensions )
RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, const std::vector<FileType>& fileTypes )
: QDialog( parent, RiuTools::defaultDialogFlags() )
, m_incomingFileExtensions( fileExtensions )
, m_incomingFileTypes( fileTypes )
{
// Create widgets
m_browseButton = new QPushButton();
@@ -164,8 +172,10 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, con
m_pathFilterField = new QComboBox();
m_fileFilterLabel = new QLabel();
m_fileFilterField = new QComboBox();
m_fileExtensionsLabel = new QLabel();
m_fileExtensionsField = new QLineEdit();
m_fileTypeLabel = new QLabel();
m_fileTypeField = new QComboBox();
m_fileExtensionLabel = new QLabel();
m_fileExtensionField = new QLineEdit();
m_effectiveFilterLabel = new QLabel();
m_effectiveFilterContentLabel = new QLabel();
m_ensembleGroupingMode = new QComboBox();
@@ -183,7 +193,9 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, con
connect( m_fileFilterField, SIGNAL( currentTextChanged( const QString& ) ), this, SLOT( slotFileFilterChanged( const QString& ) ) );
connect( m_fileFilterField, SIGNAL( editTextChanged( const QString& ) ), this, SLOT( slotFileFilterChanged( const QString& ) ) );
connect( m_fileExtensionsField, SIGNAL( editingFinished() ), this, SLOT( slotFileExtensionsChanged() ) );
connect( m_fileTypeField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( slotFileTypeChanged( int ) ) );
connect( m_fileExtensionField, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotFileExtensionChanged( const QString& ) ) );
connect( m_fileListWidget,
SIGNAL( customContextMenuRequested( const QPoint& ) ),
@@ -200,7 +212,8 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, con
// Set widget properties
m_pathFilterLabel->setText( "Path pattern" );
m_fileFilterLabel->setText( "File pattern" );
m_fileExtensionsLabel->setText( "File Extensions" );
m_fileTypeLabel->setText( "File type" );
m_fileExtensionLabel->setText( "File extension" );
m_effectiveFilterLabel->setText( "Effective filter" );
m_searchRootLabel->setText( "Root" );
m_searchRootLabel->setVisible( false );
@@ -236,8 +249,12 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, con
inputGridLayout->addWidget( m_fileFilterField, row, 1, 1, 2 );
row++;
inputGridLayout->addWidget( m_fileExtensionsLabel, row, 0 );
inputGridLayout->addWidget( m_fileExtensionsField, row, 1, 1, 2 );
inputGridLayout->addWidget( m_fileTypeLabel, row, 0 );
inputGridLayout->addWidget( m_fileTypeField, row, 1, 1, 2 );
row++;
inputGridLayout->addWidget( m_fileExtensionLabel, row, 0 );
inputGridLayout->addWidget( m_fileExtensionField, row, 1, 1, 2 );
row++;
{
@@ -291,8 +308,8 @@ RicRecursiveFileSearchDialog::RicRecursiveFileSearchDialog( QWidget* parent, con
{
QString text = "Define the extension using \".EGRID|.GRDECL\"";
m_fileExtensionsLabel->setToolTip( text );
m_fileExtensionsField->setToolTip( text );
m_fileExtensionLabel->setToolTip( text );
m_fileExtensionField->setToolTip( text );
}
{
@@ -383,6 +400,14 @@ QStringList RicRecursiveFileSearchDialog::fileExtensions() const
return exts;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicRecursiveFileSearchDialog::FileType RicRecursiveFileSearchDialog::fileType() const
{
return m_fileType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -407,12 +432,24 @@ void RicRecursiveFileSearchDialog::updateFileListWidget()
if ( ensembleGroupingMode() != RiaEnsembleNameTools::EnsembleGroupingMode::NONE )
{
std::vector<QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByEnsemble( m_foundFiles, ensembleGroupingMode() );
for ( const QStringList& groupedFileNames : groupedByEnsemble )
if ( m_fileType == RicRecursiveFileSearchDialog::FileType::STIMPLAN_SUMMARY )
{
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( groupedFileNames, ensembleGroupingMode() );
new QListWidgetItem( QDir::toNativeSeparators( ensembleName ), m_fileListWidget );
addToFileListWidget( groupedFileNames );
std::map<QString, QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByStimPlanEnsemble( m_foundFiles );
for ( auto [ensembleName, groupedFileNames] : groupedByEnsemble )
{
new QListWidgetItem( QDir::toNativeSeparators( ensembleName ), m_fileListWidget );
addToFileListWidget( groupedFileNames );
}
}
else
{
std::vector<QStringList> groupedByEnsemble = RiaEnsembleNameTools::groupFilesByEnsemble( m_foundFiles, ensembleGroupingMode() );
for ( const QStringList& groupedFileNames : groupedByEnsemble )
{
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( groupedFileNames, ensembleGroupingMode() );
new QListWidgetItem( QDir::toNativeSeparators( ensembleName ), m_fileListWidget );
addToFileListWidget( groupedFileNames );
}
}
}
else
@@ -720,12 +757,24 @@ void RicRecursiveFileSearchDialog::slotFileFilterChanged( const QString& text )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicRecursiveFileSearchDialog::slotFileExtensionsChanged()
void RicRecursiveFileSearchDialog::slotFileTypeChanged( int index )
{
QStringList items = m_fileExtensionsField->text().split( '|' );
m_fileType = static_cast<FileType>( m_fileTypeField->itemData( index ).toInt() );
m_fileExtensions = trimLeftStrings( items, "." );
QString extension = fileExtensionForType( m_fileType );
m_fileExtensions = QStringList( extension );
m_fileExtensionField->setText( extension );
updateEffectiveFilter();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicRecursiveFileSearchDialog::slotFileExtensionChanged( const QString& text )
{
m_fileExtensions = QStringList( text );
updateEffectiveFilter();
}
@@ -933,28 +982,23 @@ RiaEnsembleNameTools::EnsembleGroupingMode RicRecursiveFileSearchDialog::ensembl
return RiaEnsembleNameTools::EnsembleGroupingMode::FMU_FOLDER_STRUCTURE;
}
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList trimLeftStrings( const QStringList& strings, const QString& trimText )
QStringList RicRecursiveFileSearchDialog::fileTypeToExtensionStrings( const std::vector<RicRecursiveFileSearchDialog::FileType>& fileTypes )
{
QStringList trimmedStrings;
for ( const auto& string : strings )
QStringList extensions;
for ( const auto& f : fileTypes )
{
QString trimmedString = string;
if ( string.startsWith( trimText ) )
{
trimmedString = string.right( string.size() - trimText.size() );
}
trimmedStrings.append( trimmedString );
extensions.append( RicRecursiveFileSearchDialog::fileExtensionForType( f ) );
}
return trimmedStrings;
return extensions;
}
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -1042,3 +1086,84 @@ bool RicRecursiveFileSearchDialog::pathFilterMatch( const QString& pathFilter, c
QRegExp regexp( pattern, Qt::CaseInsensitive, QRegExp::Wildcard );
return regexp.exactMatch( relPath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicRecursiveFileSearchDialog::fileExtensionForType( FileType fileType )
{
switch ( fileType )
{
case FileType::GRDECL:
return "GRDECL";
case FileType::EGRID:
return "EGRID";
case FileType::GRID:
return "GRID";
case FileType::SMSPEC:
return "SMSPEC";
case FileType::STIMPLAN_FRACTURE:
return "XML";
case FileType::LAS:
return "LAS";
case FileType::SURFACE:
return "TS";
case FileType::STIMPLAN_SUMMARY:
return "CSV";
case FileType::REVEAL_SUMMARY:
return "CSV";
default:
return "*";
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicRecursiveFileSearchDialog::fileNameForType( FileType fileType )
{
switch ( fileType )
{
case FileType::GRDECL:
return "Eclipse Text File";
case FileType::EGRID:
return "Eclipse Grid File";
case FileType::GRID:
return "Eclipse Grid File";
case FileType::SMSPEC:
return "Eclipse Summary File";
case FileType::STIMPLAN_FRACTURE:
return "StimPlan Fracture";
case FileType::LAS:
return "LAS File";
case FileType::SURFACE:
return "Surface File";
case FileType::STIMPLAN_SUMMARY:
return "StimPlan Summary File";
case FileType::REVEAL_SUMMARY:
return "Reveal Summary File";
default:
return "*";
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::FileType RicRecursiveFileSearchDialog::mapSummaryFileType( RicRecursiveFileSearchDialog::FileType fileType )
{
switch ( fileType )
{
case RicRecursiveFileSearchDialog::FileType::SMSPEC:
return RiaDefines::FileType::SMSPEC;
case RicRecursiveFileSearchDialog::FileType::REVEAL_SUMMARY:
return RiaDefines::FileType::REVEAL_SUMMARY;
case RicRecursiveFileSearchDialog::FileType::STIMPLAN_SUMMARY:
return RiaDefines::FileType::STIMPLAN_SUMMARY;
default:
{
CAF_ASSERT( false && "Unsupported file type" );
return RiaDefines::FileType::SMSPEC;
}
}
}

View File

@@ -23,6 +23,8 @@
#include "cafPdmPointer.h"
#include "RiaEnsembleNameTools.h"
#include "RiaSummaryDefines.h"
#include <QDialog>
class QLabel;
@@ -44,7 +46,7 @@ class RicRecursiveFileSearchDialogResult;
class RicRecursiveFileSearchDialog : public QDialog
{
Q_OBJECT
public:
enum Status
{
SEARCHING_FOR_DIRS,
@@ -52,22 +54,40 @@ class RicRecursiveFileSearchDialog : public QDialog
NO_FILES_FOUND
};
public:
static RicRecursiveFileSearchDialogResult runRecursiveSearchDialog( QWidget* parent = nullptr,
const QString& caption = QString(),
const QString& dir = QString(),
const QString& pathFilter = QString(),
const QString& fileNameFilter = QString(),
const QStringList& fileExtensions = QStringList() );
enum class FileType
{
GRDECL,
EGRID,
GRID,
SMSPEC,
STIMPLAN_FRACTURE,
LAS,
SURFACE,
STIMPLAN_SUMMARY,
REVEAL_SUMMARY
};
static RicRecursiveFileSearchDialogResult runRecursiveSearchDialog( QWidget* parent,
const QString& caption,
const QString& dir,
const QString& pathFilter,
const QString& fileNameFilter,
const std::vector<FileType>& fileTypes );
static QString fileNameForType( FileType fileType );
static QString fileExtensionForType( FileType fileType );
static RiaDefines::FileType mapSummaryFileType( RicRecursiveFileSearchDialog::FileType fileType );
private:
RicRecursiveFileSearchDialog( QWidget* parent, const QStringList& fileExtensions );
RicRecursiveFileSearchDialog( QWidget* parent, const std::vector<FileType>& fileTypes );
~RicRecursiveFileSearchDialog() override;
QString cleanTextFromPathFilterField() const;
QString rootDirWithEndSeparator() const;
QString pathFilterWithoutStartSeparator() const;
QString fileNameFilter() const;
QString cleanTextFromPathFilterField() const;
QString rootDirWithEndSeparator() const;
QString pathFilterWithoutStartSeparator() const;
QString fileNameFilter() const;
FileType fileType() const;
QStringList fileExtensions() const;
QString extensionFromFileNameFilter() const;
@@ -93,10 +113,13 @@ private:
static void populateComboBoxHistoryFromRegistry( QComboBox* comboBox, const QString& registryKey );
static QStringList fileTypeToExtensionStrings( const std::vector<RicRecursiveFileSearchDialog::FileType>& fileTypes );
private slots:
void slotPathFilterChanged( const QString& text );
void slotFileFilterChanged( const QString& text );
void slotFileExtensionsChanged();
void slotFileExtensionChanged( const QString& text );
void slotFileTypeChanged( int );
void slotBrowseButtonClicked();
void slotUseRealizationStarClicked();
void slotFindOrCancelButtonClicked();
@@ -119,8 +142,11 @@ private:
QLabel* m_fileFilterLabel;
QComboBox* m_fileFilterField;
QLabel* m_fileExtensionsLabel;
QLineEdit* m_fileExtensionsField;
QLabel* m_fileTypeLabel;
QComboBox* m_fileTypeField;
QLabel* m_fileExtensionLabel;
QLineEdit* m_fileExtensionField;
QLabel* m_effectiveFilterLabel;
QLabel* m_effectiveFilterContentLabel;
@@ -135,9 +161,10 @@ private:
QDialogButtonBox* m_buttons;
QStringList m_foundFiles;
const QStringList m_incomingFileExtensions;
QStringList m_fileExtensions;
QStringList m_foundFiles;
std::vector<FileType> m_incomingFileTypes;
QStringList m_fileExtensions;
FileType m_fileType;
bool m_isCancelPressed;
@@ -157,21 +184,24 @@ public:
const QString& rootDir,
const QString& pathFilter,
const QString& fileNameFilter,
RicRecursiveFileSearchDialog::FileType fileType,
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode )
: ok( ok )
, files( files )
, rootDir( rootDir )
, pathFilter( pathFilter )
, fileNameFilter( fileNameFilter )
, fileType( fileType )
, groupingMode( groupingMode )
{
}
bool ok;
QStringList files;
QString rootDir;
QString pathFilter;
QString fileNameFilter;
bool ok;
QStringList files;
QString rootDir;
QString pathFilter;
QString fileNameFilter;
RicRecursiveFileSearchDialog::FileType fileType;
RiaEnsembleNameTools::EnsembleGroupingMode groupingMode;
};

View File

@@ -276,234 +276,236 @@ void RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine( const QStrin
}
}
bool isEnsembleMode = ensembleColoringStyle != EnsembleColoringType::NONE;
std::vector<RimSummaryCase*> summaryCasesToUse;
if ( summaryFileNames.size() )
if ( summaryFileNames.empty() )
{
RicImportSummaryCasesFeature::createSummaryCasesFromFiles( summaryFileNames, &summaryCasesToUse, isEnsembleMode );
RicImportSummaryCasesFeature::addSummaryCases( summaryCasesToUse );
RiaApplication::instance()->setLastUsedDialogDirectory( RiaDefines::defaultDirectoryLabel(
RiaDefines::ImportFileType::ECLIPSE_SUMMARY_FILE ),
QFileInfo( summaryFileNames[0] ).absolutePath() );
RiaLogging::error( "Needs at least one summary case to create a plot." );
return;
}
if ( summaryCasesToUse.size() )
bool isEnsembleMode = ensembleColoringStyle != EnsembleColoringType::NONE;
RicImportSummaryCasesFeature::CreateConfig createConfig{ .fileType = RiaDefines::FileType::SMSPEC,
.ensembleOrGroup = isEnsembleMode,
.allowDialogs = true };
auto [isOk, summaryCasesToUse] = RicImportSummaryCasesFeature::createSummaryCasesFromFiles( summaryFileNames, createConfig );
if ( !isOk || summaryCasesToUse.empty() )
{
// Sort in summary and grid curve addresses
QStringList gridResultAddressFilters;
QStringList summaryAddressFilters;
RiaLogging::error( "Needs at least one summary case to create a plot." );
return;
}
RimSummaryPlot* lastPlotCreated = nullptr;
RicImportSummaryCasesFeature::addSummaryCases( summaryCasesToUse );
RiaSummaryStringTools::splitAddressFiltersInGridAndSummary( summaryCasesToUse[0],
allCurveAddressFilters,
&summaryAddressFilters,
&gridResultAddressFilters );
RiaApplication::instance()->setLastUsedDialogDirectory( RiaDefines::defaultDirectoryLabel( RiaDefines::ImportFileType::ECLIPSE_SUMMARY_FILE ),
QFileInfo( summaryFileNames[0] ).absolutePath() );
if ( summaryAddressFilters.size() )
// Sort in summary and grid curve addresses
QStringList gridResultAddressFilters;
QStringList summaryAddressFilters;
RimSummaryPlot* lastPlotCreated = nullptr;
RiaSummaryStringTools::splitAddressFiltersInGridAndSummary( summaryCasesToUse[0],
allCurveAddressFilters,
&summaryAddressFilters,
&gridResultAddressFilters );
if ( summaryAddressFilters.size() )
{
RimSummaryCaseCollection* ensemble = nullptr;
if ( isEnsembleMode )
{
RimSummaryCaseCollection* ensemble = nullptr;
ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases( summaryCasesToUse, "Ensemble", true );
}
if ( isEnsembleMode )
if ( isSinglePlot )
{
RimSummaryPlot* newPlot = nullptr;
if ( ensemble )
{
ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases( summaryCasesToUse, "Ensemble", true );
newPlot = createSummaryPlotForEnsemble( summaryCasesToUse,
ensemble,
summaryAddressFilters,
addHistoryCurves,
ensembleColoringStyle,
ensembleColoringParameter );
}
else
{
newPlot = createSummaryPlotForCases( summaryCasesToUse, summaryAddressFilters, addHistoryCurves );
}
if ( isSinglePlot )
{
RimSummaryPlot* newPlot = nullptr;
if ( ensemble )
{
newPlot = createSummaryPlotForEnsemble( summaryCasesToUse,
ensemble,
summaryAddressFilters,
addHistoryCurves,
ensembleColoringStyle,
ensembleColoringParameter );
}
else
{
newPlot = createSummaryPlotForCases( summaryCasesToUse, summaryAddressFilters, addHistoryCurves );
}
lastPlotCreated = newPlot;
lastPlotCreated = newPlot;
newPlot->setLegendsVisible( !hideLegend );
newPlot->setNormalizationEnabled( isNormalizedY );
newPlot->loadDataAndUpdate();
RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot );
}
else // Multiple plots, one for each separate summary address, put them all in a summary multiplot
{
std::vector<RimSummaryPlot*> summaryPlots = createMultipleSummaryPlotsFromAddresses( summaryCasesToUse,
ensemble,
summaryAddressFilters,
addHistoryCurves,
ensembleColoringStyle,
ensembleColoringParameter );
lastPlotCreated = summaryPlots.back();
for ( auto summaryPlot : summaryPlots )
{
summaryPlot->setLegendsVisible( !hideLegend );
summaryPlot->setNormalizationEnabled( isNormalizedY );
summaryPlot->loadDataAndUpdate();
}
RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( summaryPlots );
}
}
// Grid Cell Result vectors
if ( gridResultAddressFilters.size() )
{
// Todo: Use identical grid case import if -e -c or -cl
std::vector<RimEclipseCase*> gridCasesToPlotFrom = openEclipseCasesForCellPlotting( gridFileNames );
if ( isSinglePlot )
{
std::vector<RimGridTimeHistoryCurve*> createdCurves;
int curveColorIndex = 0;
for ( const QString& gridAddressFilter : gridResultAddressFilters )
{
std::vector<RigGridCellResultAddress> cellResAddrs =
RigGridCellResultAddress::createGridCellAddressesFromFilter( gridAddressFilter );
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
{
for ( RimEclipseCase* eclCase : gridCasesToPlotFrom )
{
if ( !( eclCase->eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) &&
eclCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->resultInfo( cellResAddr.eclipseResultAddress ) ) )
{
RiaLogging::warning( "Could not find a restart result property with name: \"" +
cellResAddr.eclipseResultAddress.resultName() + "\"" );
continue;
}
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult( eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress );
newCurve->setLineThickness( 2 );
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( curveColorIndex );
newCurve->setColor( curveColor );
if ( !isEnsembleMode ) ++curveColorIndex;
createdCurves.push_back( newCurve );
}
if ( isEnsembleMode ) ++curveColorIndex;
}
}
if ( createdCurves.size() )
{
RimSummaryPlot* newPlot = new RimSummaryPlot();
newPlot->enableAutoPlotTitle( true );
for ( auto curve : createdCurves )
{
newPlot->addGridTimeHistoryCurve( curve );
}
newPlot->setLegendsVisible( !hideLegend );
newPlot->setNormalizationEnabled( isNormalizedY );
newPlot->loadDataAndUpdate();
lastPlotCreated = newPlot;
RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot );
}
else // Multiple plots, one for each separate summary address, put them all in a summary multiplot
{
std::vector<RimSummaryPlot*> summaryPlots = createMultipleSummaryPlotsFromAddresses( summaryCasesToUse,
ensemble,
summaryAddressFilters,
addHistoryCurves,
ensembleColoringStyle,
ensembleColoringParameter );
lastPlotCreated = summaryPlots.back();
for ( auto summaryPlot : summaryPlots )
{
summaryPlot->setLegendsVisible( !hideLegend );
summaryPlot->setNormalizationEnabled( isNormalizedY );
summaryPlot->loadDataAndUpdate();
}
RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( summaryPlots );
}
}
// Grid Cell Result vectors
if ( gridResultAddressFilters.size() )
else // Multiplot
{
// Todo: Use identical grid case import if -e -c or -cl
int curveColorIndex = 0;
std::vector<RimEclipseCase*> gridCasesToPlotFrom = openEclipseCasesForCellPlotting( gridFileNames );
if ( isSinglePlot )
for ( const QString& gridAddressFilter : gridResultAddressFilters )
{
std::vector<RimGridTimeHistoryCurve*> createdCurves;
int curveColorIndex = 0;
for ( const QString& gridAddressFilter : gridResultAddressFilters )
std::vector<RigGridCellResultAddress> cellResAddrs =
RigGridCellResultAddress::createGridCellAddressesFromFilter( gridAddressFilter );
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
{
std::vector<RigGridCellResultAddress> cellResAddrs =
RigGridCellResultAddress::createGridCellAddressesFromFilter( gridAddressFilter );
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
std::vector<RimGridTimeHistoryCurve*> createdCurves;
for ( RimEclipseCase* eclCase : gridCasesToPlotFrom )
{
for ( RimEclipseCase* eclCase : gridCasesToPlotFrom )
if ( !( eclCase->eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) &&
eclCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->resultInfo( cellResAddr.eclipseResultAddress ) ) )
{
if ( !( eclCase->eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) &&
eclCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->resultInfo( cellResAddr.eclipseResultAddress ) ) )
{
RiaLogging::warning( "Could not find a restart result property with name: \"" +
cellResAddr.eclipseResultAddress.resultName() + "\"" );
continue;
}
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult( eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress );
newCurve->setLineThickness( 2 );
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( curveColorIndex );
newCurve->setColor( curveColor );
if ( !isEnsembleMode ) ++curveColorIndex;
createdCurves.push_back( newCurve );
RiaLogging::warning( "Could not find a restart result property with name: \"" +
cellResAddr.eclipseResultAddress.resultName() + "\"" );
continue;
}
if ( isEnsembleMode ) ++curveColorIndex;
}
}
if ( createdCurves.size() )
{
RimSummaryPlot* newPlot = new RimSummaryPlot();
newPlot->enableAutoPlotTitle( true );
for ( auto curve : createdCurves )
{
newPlot->addGridTimeHistoryCurve( curve );
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult( eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress );
newCurve->setLineThickness( 2 );
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( curveColorIndex );
newCurve->setColor( curveColor );
if ( !isEnsembleMode ) ++curveColorIndex;
createdCurves.push_back( newCurve );
}
newPlot->setLegendsVisible( !hideLegend );
newPlot->setNormalizationEnabled( isNormalizedY );
newPlot->loadDataAndUpdate();
lastPlotCreated = newPlot;
if ( isEnsembleMode ) ++curveColorIndex;
RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot );
}
}
else // Multiplot
{
int curveColorIndex = 0;
for ( const QString& gridAddressFilter : gridResultAddressFilters )
{
std::vector<RigGridCellResultAddress> cellResAddrs =
RigGridCellResultAddress::createGridCellAddressesFromFilter( gridAddressFilter );
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
if ( createdCurves.size() )
{
std::vector<RimGridTimeHistoryCurve*> createdCurves;
for ( RimEclipseCase* eclCase : gridCasesToPlotFrom )
RimSummaryPlot* newPlot = new RimSummaryPlot();
newPlot->enableAutoPlotTitle( true );
for ( auto newCurve : createdCurves )
{
if ( !( eclCase->eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) &&
eclCase->eclipseCaseData()
->results( RiaDefines::PorosityModelType::MATRIX_MODEL )
->resultInfo( cellResAddr.eclipseResultAddress ) ) )
{
RiaLogging::warning( "Could not find a restart result property with name: \"" +
cellResAddr.eclipseResultAddress.resultName() + "\"" );
continue;
}
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult( eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress );
newCurve->setLineThickness( 2 );
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( curveColorIndex );
newCurve->setColor( curveColor );
if ( !isEnsembleMode ) ++curveColorIndex;
createdCurves.push_back( newCurve );
newPlot->addGridTimeHistoryCurve( newCurve );
}
newPlot->setLegendsVisible( !hideLegend );
newPlot->setNormalizationEnabled( isNormalizedY );
newPlot->loadDataAndUpdate();
lastPlotCreated = newPlot;
if ( isEnsembleMode ) ++curveColorIndex;
if ( createdCurves.size() )
{
RimSummaryPlot* newPlot = new RimSummaryPlot();
newPlot->enableAutoPlotTitle( true );
for ( auto newCurve : createdCurves )
{
newPlot->addGridTimeHistoryCurve( newCurve );
}
newPlot->setLegendsVisible( !hideLegend );
newPlot->setNormalizationEnabled( isNormalizedY );
newPlot->loadDataAndUpdate();
lastPlotCreated = newPlot;
RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot );
}
RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( newPlot );
}
}
}
}
if ( lastPlotCreated )
{
RimMainPlotCollection::current()->summaryMultiPlotCollection()->updateConnectedEditors();
RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow();
// Needed to avoid unnecessary activation of sub windows (plots)
// which results in population of property editor, and missing deleteLater because we are outside any event
// loop when switching object. Results in stray widgets.
mpw->setBlockViewSelectionOnSubWindowActivated( true );
RiuPlotMainWindowTools::showPlotMainWindow();
mpw->setBlockViewSelectionOnSubWindowActivated( false );
RiuPlotMainWindowTools::setExpanded( lastPlotCreated );
RiuPlotMainWindowTools::selectAsCurrentItem( lastPlotCreated );
RiuMainWindow::closeIfOpen();
}
}
else
if ( lastPlotCreated )
{
RiaLogging::error( "Needs at least one summary case to create a plot." );
RimMainPlotCollection::current()->summaryMultiPlotCollection()->updateConnectedEditors();
RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow();
// Needed to avoid unnecessary activation of sub windows (plots)
// which results in population of property editor, and missing deleteLater because we are outside any event
// loop when switching object. Results in stray widgets.
mpw->setBlockViewSelectionOnSubWindowActivated( true );
RiuPlotMainWindowTools::showPlotMainWindow();
mpw->setBlockViewSelectionOnSubWindowActivated( false );
RiuPlotMainWindowTools::setExpanded( lastPlotCreated );
RiuPlotMainWindowTools::selectAsCurrentItem( lastPlotCreated );
RiuMainWindow::closeIfOpen();
}
}

View File

@@ -247,7 +247,8 @@ void RifCaseRealizationRunspecificationReader::parse()
//--------------------------------------------------------------------------------------------------
QString RifCaseRealizationParametersFileLocator::locate( const QString& modelPath )
{
int MAX_LEVELS_UP = 3;
// Chosen to find parameters file for StimPlan ensembles.
int MAX_LEVELS_UP = 5;
int dirLevel = 0;
QDir qdir( modelPath );

View File

@@ -382,10 +382,13 @@ QString RifSummaryCaseRestartSelector::getSummaryFileFromGridFile( const QString
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryCaseFileImportInfo::RifSummaryCaseFileImportInfo( const QString& summaryFileName, const QString& gridFileName )
RifSummaryCaseFileImportInfo::RifSummaryCaseFileImportInfo( const QString& summaryFileName,
const QString& gridFileName,
RiaDefines::FileType fileType )
: m_summaryFileName( summaryFileName )
, m_gridFileName( gridFileName )
, m_failOnSummaryFileImportError( false )
, m_fileType( fileType )
{
}
@@ -424,9 +427,18 @@ void RifSummaryCaseFileImportInfo::setFailOnSummaryFileError( bool failOnSummary
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryCaseFileResultInfo::RifSummaryCaseFileResultInfo( const QString& summaryFileName, bool includeRestartFiles )
RiaDefines::FileType RifSummaryCaseFileImportInfo::fileType() const
{
return m_fileType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryCaseFileResultInfo::RifSummaryCaseFileResultInfo( const QString& summaryFileName, bool includeRestartFiles, RiaDefines::FileType fileType )
: m_summaryFileName( summaryFileName )
, m_includeRestartFiles( includeRestartFiles )
, m_fileType( fileType )
{
CVF_ASSERT( !m_summaryFileName.isEmpty() );
}
@@ -447,6 +459,14 @@ bool RifSummaryCaseFileResultInfo::includeRestartFiles() const
return m_includeRestartFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::FileType RifSummaryCaseFileResultInfo::fileType() const
{
return m_fileType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -18,6 +18,8 @@
#pragma once
#include "RiaSummaryDefines.h"
#include "RicSummaryCaseRestartDialog.h"
#include <QString>
@@ -70,17 +72,21 @@ private:
class RifSummaryCaseFileImportInfo
{
public:
RifSummaryCaseFileImportInfo( const QString& summaryFileName, const QString& gridFileName );
RifSummaryCaseFileImportInfo( const QString& summaryFileName,
const QString& gridFileName,
RiaDefines::FileType fileType = RiaDefines::FileType::SMSPEC );
const QString& summaryFileName() const;
const QString& gridFileName() const;
bool failOnSummaryFileError() const;
void setFailOnSummaryFileError( bool failOnSummaryFileImportError );
const QString& summaryFileName() const;
const QString& gridFileName() const;
bool failOnSummaryFileError() const;
void setFailOnSummaryFileError( bool failOnSummaryFileImportError );
RiaDefines::FileType fileType() const;
private:
QString m_summaryFileName;
QString m_gridFileName;
bool m_failOnSummaryFileImportError;
QString m_summaryFileName;
QString m_gridFileName;
bool m_failOnSummaryFileImportError;
RiaDefines::FileType m_fileType;
};
//==================================================================================================
@@ -89,15 +95,19 @@ private:
class RifSummaryCaseFileResultInfo
{
public:
RifSummaryCaseFileResultInfo( const QString& summaryFileName, bool includeRestartFiles );
RifSummaryCaseFileResultInfo( const QString& summaryFileName,
bool includeRestartFiles,
RiaDefines::FileType fileType = RiaDefines::FileType::SMSPEC );
const QString& summaryFileName() const;
bool includeRestartFiles() const;
const QString& summaryFileName() const;
bool includeRestartFiles() const;
RiaDefines::FileType fileType() const;
bool operator<( const RifSummaryCaseFileResultInfo& other ) const;
bool operator==( const RifSummaryCaseFileResultInfo& other ) const;
private:
QString m_summaryFileName;
bool m_includeRestartFiles;
QString m_summaryFileName;
bool m_includeRestartFiles;
RiaDefines::FileType m_fileType;
};

View File

@@ -21,6 +21,7 @@
#include "RifEnsembleStatisticsReader.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "RigStatisticsMath.h"
@@ -137,15 +138,19 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*> sumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves )
void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& sumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves )
{
std::vector<time_t> allTimeSteps;
std::vector<std::vector<double>> caseAndTimeStepValues;
if ( !inputAddress.isValid() ) return;
auto [minTimeStep, maxTimeStep] = findMinMaxTimeStep( sumCases, inputAddress );
RiaDefines::DateTimePeriod period = findBestResamplingPeriod( minTimeStep, maxTimeStep );
caseAndTimeStepValues.reserve( sumCases.size() );
for ( const auto& sumCase : sumCases )
{
@@ -160,8 +165,7 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*> su
if ( !includeIncompleteCurves && timeSteps.size() != values.size() ) continue;
auto [resampledTimeSteps, resampledValues] =
RiaSummaryTools::resampledValuesForPeriod( inputAddress, timeSteps, values, RiaDefines::DateTimePeriod::DAY );
auto [resampledTimeSteps, resampledValues] = RiaSummaryTools::resampledValuesForPeriod( inputAddress, timeSteps, values, period );
if ( allTimeSteps.empty() ) allTimeSteps = resampledTimeSteps;
caseAndTimeStepValues.push_back( resampledValues );
@@ -220,9 +224,9 @@ void RimEnsembleStatisticsCase::clearData()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases( const std::vector<RimSummaryCase*> allSumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves )
std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases( const std::vector<RimSummaryCase*>& allSumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves )
{
std::vector<RimSummaryCase*> validCases;
std::vector<std::pair<RimSummaryCase*, time_t>> times;
@@ -239,7 +243,7 @@ std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases( const
{
time_t lastTimeStep = timeSteps.back();
if ( lastTimeStep > maxTimeStep ) maxTimeStep = lastTimeStep;
maxTimeStep = std::max( lastTimeStep, maxTimeStep );
times.push_back( std::make_pair( sumCase, lastTimeStep ) );
}
}
@@ -259,5 +263,54 @@ std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases( const
validCases.push_back( sumCase );
}
return validCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<time_t, time_t> RimEnsembleStatisticsCase::findMinMaxTimeStep( const std::vector<RimSummaryCase*>& sumCases,
const RifEclipseSummaryAddress& inputAddress )
{
time_t minTimeStep = std::numeric_limits<time_t>::max();
time_t maxTimeStep = 0;
for ( const auto& sumCase : sumCases )
{
const auto& reader = sumCase->summaryReader();
if ( reader )
{
const std::vector<time_t>& timeSteps = reader->timeSteps( inputAddress );
if ( !timeSteps.empty() )
{
minTimeStep = std::min( timeSteps.front(), minTimeStep );
maxTimeStep = std::max( timeSteps.back(), maxTimeStep );
}
}
}
return std::make_pair( minTimeStep, maxTimeStep );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::DateTimePeriod RimEnsembleStatisticsCase::findBestResamplingPeriod( time_t minTimeStep, time_t maxTimeStep )
{
std::vector<RiaDefines::DateTimePeriod> periods = { RiaDefines::DateTimePeriod::DAY,
RiaDefines::DateTimePeriod::HOUR,
RiaDefines::DateTimePeriod::MINUTE };
for ( auto p : periods )
{
size_t numSamples = RiaTimeHistoryCurveResampler::timeStepsFromTimeRange( p, minTimeStep, maxTimeStep ).size();
// Resampled data should ideally have at least 100 samples to look good.
if ( numSamples > 100 )
{
return p;
}
}
return RiaDefines::DateTimePeriod::DAY;
}

View File

@@ -18,7 +18,9 @@
#pragma once
#include "RiaDateTimeDefines.h"
#include "RiaDefines.h"
#include "RifEclipseSummaryAddress.h"
#include "RimSummaryCase.h"
@@ -55,11 +57,14 @@ public:
RiaDefines::EclipseUnitSystem unitSystem() const;
private:
void calculate( const std::vector<RimSummaryCase*> sumCases, const RifEclipseSummaryAddress& inputAddress, bool includeIncompleteCurves );
void clearData();
std::vector<RimSummaryCase*> validSummaryCases( const std::vector<RimSummaryCase*> allSumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves );
void calculate( const std::vector<RimSummaryCase*>& sumCases, const RifEclipseSummaryAddress& inputAddress, bool includeIncompleteCurves );
void clearData();
static std::vector<RimSummaryCase*> validSummaryCases( const std::vector<RimSummaryCase*>& allSumCases,
const RifEclipseSummaryAddress& inputAddress,
bool includeIncompleteCurves );
static std::pair<time_t, time_t> findMinMaxTimeStep( const std::vector<RimSummaryCase*>& sumCases,
const RifEclipseSummaryAddress& inputAddress );
static RiaDefines::DateTimePeriod findBestResamplingPeriod( time_t minTimeStep, time_t maxTimeStep );
private:
std::unique_ptr<RifEnsembleStatisticsReader> m_statisticsReader;

View File

@@ -33,6 +33,7 @@
#endif
#include "RimCaseDisplayNameTools.h"
#include "RimCsvSummaryCase.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEclipseResultCase.h"
#include "RimFileSummaryCase.h"
@@ -560,9 +561,25 @@ std::vector<RimSummaryCase*>
if ( !smspecFileName.isEmpty() )
{
auto newSumCase = new RimFileSummaryCase();
RimSummaryCase* newSumCase = nullptr;
if ( fileInfo.fileType() == RiaDefines::FileType::SMSPEC )
{
auto sumCase = new RimFileSummaryCase();
sumCase->setIncludeRestartFiles( fileInfo.includeRestartFiles() );
newSumCase = sumCase;
}
else
{
auto sumCase = new RimCsvSummaryCase();
if ( fileInfo.fileType() == RiaDefines::FileType::STIMPLAN_SUMMARY )
sumCase->setFileType( RimCsvSummaryCase::FileType::STIMPLAN );
else
sumCase->setFileType( RimCsvSummaryCase::FileType::REVEAL );
newSumCase = sumCase;
}
newSumCase->setIncludeRestartFiles( fileInfo.includeRestartFiles() );
newSumCase->setSummaryHeaderFileName( smspecFileName );
newSumCase->updateOptionSensitivity();
project->assignCaseIdToSummaryCase( newSumCase );

View File

@@ -62,12 +62,13 @@ caf::PdmObjectHandle* RimProject_importSummaryCase::execute()
absolutePath = startDir.absoluteFilePath( m_fileName );
}
QStringList summaryFileNames{ absolutePath };
std::vector<RimSummaryCase*> newCases;
bool ensembleOrGroup = false;
bool allowDialogs = false;
QStringList summaryFileNames{ absolutePath };
if ( RicImportSummaryCasesFeature::createSummaryCasesFromFiles( summaryFileNames, &newCases, ensembleOrGroup, allowDialogs ) )
RicImportSummaryCasesFeature::CreateConfig createConfig{ .fileType = RiaDefines::FileType::SMSPEC,
.ensembleOrGroup = false,
.allowDialogs = false };
auto [isOk, newCases] = RicImportSummaryCasesFeature::createSummaryCasesFromFiles( summaryFileNames, createConfig );
if ( isOk )
{
RicImportSummaryCasesFeature::addSummaryCases( newCases );

View File

@@ -89,6 +89,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSummaryReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaEnsembleNameTools-Test.cpp
)
if(RESINSIGHT_ENABLE_GRPC)

View File

@@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 Equinor 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 "gtest/gtest.h"
#include "RiaEnsembleNameTools.h"
#include <QStringList>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaEnsembleNameToolsTests, commonBaseName )
{
QStringList fileNames = { "/base/realization-0/iter-0/stimplan/output/B-H3_StimPlanModel_01_job-01/mainfrac/data_vs_time.csv",
"/base/realization-0/iter-0/stimplan/output/B-H3_StimPlanModel_02_job-02/mainfrac/data_vs_time.csv" };
ASSERT_EQ( "data_vs_time", RiaEnsembleNameTools::findCommonBaseName( fileNames ).toStdString() );
}

View File

@@ -25,7 +25,7 @@ TEST( RifCaseRealizationParametersReaderTest, LocatorTestSuccess )
//--------------------------------------------------------------------------------------------------
TEST( RifCaseRealizationParametersReaderTest, LocatorTestFailure )
{
QString file = RifCaseRealizationParametersFileLocator::locate( CASE_REAL_TEST_DATA_DIRECTORY_01 + "4/3/2/1" );
QString file = RifCaseRealizationParametersFileLocator::locate( CASE_REAL_TEST_DATA_DIRECTORY_01 + "6/5/4/3/2/1" );
QString expected = "";
EXPECT_EQ( expected.toStdString(), file.toStdString() );
}