#8370: Address review comments

Keep original additional summary files on Save As, reject cases combined with ensembles, keep unrestored additional file mappings, support growing file sets, update short names on ensemble import, simplify aggregator and example.
This commit is contained in:
Magne Sjaastad committed 2026-10-16 09:57:12 +02:00
1 parent d93aa839a6
commit 597a7775d9
7 files changed
+73 -21

No files matched your search

@@ -52,9 +52,11 @@ std::pair<bool, std::vector<double>> RifSummaryReaderAggregator::values( const R
{
auto [isOk, readerValues] = reader->values( resultAddress );
if ( !readerValues.empty() ) anyReaderHasValues = true;
if ( readerValues.empty() )
if ( !readerValues.empty() )
{
anyReaderHasValues = true;
}
else
{
// When a well is introduced, no data is present before the time step the well is introduced
// Add values of zero for this interval
@@ -63,6 +63,35 @@ QString commonHeaderFolder( const std::vector<RimFileSummaryCase*>& fileCases )
return folder;
}
// Path of a summary header file relative to the common folder. A single realization has no distinguishing folder, so the parent folder
// name is included to allow a unique suffix match if realizations are added to the file set later.
QString headerStorageKey( const QString& header, const QString& commonFolder )
{
QString key = header.mid( commonFolder.size() );
if ( !key.contains( '/' ) )
{
const int lastSeparator = header.lastIndexOf( '/' );
const int prevSeparator = lastSeparator > 0 ? header.lastIndexOf( '/', lastSeparator - 1 ) : -1;
if ( prevSeparator >= 0 ) key = header.mid( prevSeparator + 1 );
}
return key;
}
std::map<QString, QString> parseAdditionalSummaryFiles( const QString& text )
{
std::map<QString, QString> additionalFileForHeader;
for ( const auto& line : text.split( '\n', Qt::SkipEmptyParts ) )
{
// The additional file name is generated and does not contain separator characters
auto separatorIndex = line.lastIndexOf( '|' );
if ( separatorIndex > 0 )
{
additionalFileForHeader[line.left( separatorIndex )] = line.mid( separatorIndex + 1 );
}
}
return additionalFileForHeader;
}
} // namespace internal
//--------------------------------------------------------------------------------------------------
@@ -250,13 +279,21 @@ void RimSummaryFileSetEnsemble::storeAdditionalSummaryFiles()
const QString commonFolder = internal::commonHeaderFolder( fileCases );
QStringList lines;
// Keep entries that could not be restored (for example when the additional files were not copied with the project), so the mapping
// is not lost on the next save
auto entries = internal::parseAdditionalSummaryFiles( m_additionalSummaryFiles() );
for ( auto fileSummaryCase : fileCases )
{
QString additionalFile = fileSummaryCase->additionalSummaryFilePath();
if ( additionalFile.isEmpty() ) continue;
lines.push_back( fileSummaryCase->summaryHeaderFilename().mid( commonFolder.size() ) + "|" + QFileInfo( additionalFile ).fileName() );
entries[internal::headerStorageKey( fileSummaryCase->summaryHeaderFilename(), commonFolder )] = QFileInfo( additionalFile ).fileName();
}
QStringList lines;
for ( const auto& [key, additionalFileName] : entries )
{
lines.push_back( key + "|" + additionalFileName );
}
m_additionalSummaryFiles = lines.join( '\n' );
@@ -269,16 +306,7 @@ void RimSummaryFileSetEnsemble::restoreAdditionalSummaryFiles( const std::vector
{
if ( m_additionalSummaryFiles().isEmpty() ) return;
std::map<QString, QString> additionalFileForHeader;
for ( const auto& line : m_additionalSummaryFiles().split( '\n', Qt::SkipEmptyParts ) )
{
// The additional file name is generated and does not contain separator characters
auto separatorIndex = line.lastIndexOf( '|' );
if ( separatorIndex > 0 )
{
additionalFileForHeader[line.left( separatorIndex )] = line.mid( separatorIndex + 1 );
}
}
const auto additionalFileForHeader = internal::parseAdditionalSummaryFiles( m_additionalSummaryFiles() );
std::vector<RimFileSummaryCase*> fileCases;
for ( auto summaryCase : summaryCases )
@@ -302,7 +330,7 @@ void RimSummaryFileSetEnsemble::restoreAdditionalSummaryFiles( const std::vector
// stored path to avoid losing the user-defined vectors.
auto findAdditionalFile = [&]( const QString& header ) -> QString
{
auto it = additionalFileForHeader.find( header.mid( commonFolder.size() ) );
auto it = additionalFileForHeader.find( internal::headerStorageKey( header, commonFolder ) );
if ( it != additionalFileForHeader.end() ) return it->second;
QString match;
@@ -478,7 +478,8 @@ void RimFileSummaryCase::setAdditionalSummaryFilePath( const QString& filePath )
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::onProjectBeingSaved()
{
// If additional data is stored in temp folder, copy to project folder and remove file in temp folder. The project file is not written
// If additional data is stored in temp folder, copy to project folder and remove file in temp folder. Files in other folders are
// copied and kept, so a project saved with Save As does not lose the data of the original project. The project file is not written
// yet, so additionalSummaryDataFilePath() would still point to the temp folder on the first save.
const QString projectFileName = RimProject::current() ? RimProject::current()->fileName() : QString();
if ( projectFileName.isEmpty() ) return;
@@ -493,7 +494,8 @@ void RimFileSummaryCase::onProjectBeingSaved()
if ( QFile::copy( existingFilePath, currentFilePath ) )
{
QFile::remove( existingFilePath );
const bool isInTempFolder = QFileInfo( existingFilePath ).absoluteDir() == QDir( QDir::tempPath() );
if ( isInTempFolder ) QFile::remove( existingFilePath );
m_additionalSummaryFilePath = currentFilePath;
}
else
@@ -175,6 +175,11 @@ std::expected<caf::PdmObjectHandle*, QString> RimProject_importSummaryEnsemble::
auto ensemble = mainCollection->addEnsemble( newCases, m_ensembleName(), true );
for ( auto summaryCase : ensemble->allSummaryCases() )
{
summaryCase->updateAutoShortName();
}
// The name template is only used when auto naming is disabled
if ( !m_ensembleName().isEmpty() ) ensemble->setAutoName( false );
RiaSummaryTools::updateSummaryEnsembleNames();
@@ -55,6 +55,11 @@ std::expected<caf::PdmObjectHandle*, QString> RimcSummaryMultiPlot_appendSubplot
auto multiPlot = self<RimSummaryMultiPlot>();
if ( !m_summaryCases().empty() && !m_ensembles().empty() )
{
return std::unexpected( "Specify either summary cases or ensembles, not both." );
}
RimSummaryPlot* newPlot = RimcSummaryPlotCollection_newSummaryPlot::createSummaryPlot( m_summaryCases.ptrReferencedObjectsByType(),
m_ensembles.ptrReferencedObjectsByType(),
m_addressString() );
@@ -62,8 +62,13 @@ RimcSummaryPlotCollection_newSummaryPlot::RimcSummaryPlotCollection_newSummaryPl
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcSummaryPlotCollection_newSummaryPlot::execute()
{
RimSummaryPlot* newPlot =
createSummaryPlot( m_summaryCases.ptrReferencedObjectsByType(), allEnsembles( m_ensemble(), m_ensembles ), m_addressString() );
auto ensembles = allEnsembles( m_ensemble(), m_ensembles );
if ( !m_summaryCases().empty() && !ensembles.empty() )
{
return std::unexpected( "Specify either summary cases or ensembles, not both." );
}
RimSummaryPlot* newPlot = createSummaryPlot( m_summaryCases.ptrReferencedObjectsByType(), ensembles, m_addressString() );
// Plots created without an address are already added to a multi plot
if ( newPlot && !newPlot->firstAncestorOrThisOfType<RimSummaryMultiPlot>() )
@@ -173,6 +178,11 @@ std::expected<caf::PdmObjectHandle*, QString> RimcSummaryPlotCollection_newSumma
{
if ( m_addressStrings().empty() ) return std::unexpected( "Specify at least one address." );
if ( !m_summaryCases().empty() && !m_ensembles().empty() )
{
return std::unexpected( "Specify either summary cases or ensembles, not both." );
}
// A subplot without an address is created in a separate multi plot
for ( const QString& address : m_addressStrings() )
{
@@ -23,7 +23,7 @@ summary_plot_collection = project.summary_plot_collection()
plot = summary_plot_collection.new_summary_plot(ensembles=ensembles, address="FOPT")
# Append more subplots to the multi plot containing the first subplot
multi_plot = project.descendants(rips.MultiSummaryPlot)[-1]
multi_plot = plot.ancestor(rips.MultiSummaryPlot)
multi_plot.append_subplot(ensembles=ensembles, address="FWPT")
multi_plot.append_subplot(ensembles=ensembles, address="FGPT")