Skip to content

Unified ensemble import dialog#732

Closed
magnesj wants to merge 20 commits intodevfrom
unified-emsemble-import
Closed

Unified ensemble import dialog#732
magnesj wants to merge 20 commits intodevfrom
unified-emsemble-import

Conversation

@magnesj
Copy link
Owner

@magnesj magnesj commented Mar 5, 2026

No description provided.

@qodo-code-review
Copy link

Review Summary by Qodo

Add unified grid and summary ensemble import dialog with file search

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add unified dialog for importing grid and summary ensemble files
• Implement file search and filtering with ensemble grouping modes
• Integrate new import feature into toolbar and main menu
• Make importSingleEnsembleFileSet public for external callers
• Fix debug build error in RigActiveCellInfo and lambda capture issue
Diagram
flowchart LR
  A["User triggers<br/>Import Feature"] --> B["RicImportGridAndSummaryEnsembleDialog"]
  B --> C["Search and filter<br/>grid/summary files"]
  C --> D["Group by ensemble<br/>mode"]
  D --> E["Select realizations"]
  E --> F["RicImportGridAndSummaryEnsembleFeature"]
  F --> G["Create grid and<br/>summary ensembles"]
Loading

Grey Divider

File Changes

1. ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.h ✨ Enhancement +117/-0

New dialog header for unified ensemble import

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.h


2. ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.cpp ✨ Enhancement +710/-0

Complete dialog implementation with file search

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.cpp


3. ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.h ✨ Enhancement +33/-0

New feature class header for ensemble import

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.h


View more (8)
4. ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.cpp ✨ Enhancement +80/-0

Feature implementation invoking import dialog

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.cpp


5. ApplicationLibCode/Commands/RicImportEnsembleFeature.h ✨ Enhancement +7/-6

Make importSingleEnsembleFileSet method public

ApplicationLibCode/Commands/RicImportEnsembleFeature.h


6. ApplicationLibCode/Commands/CMakeLists_files.cmake ⚙️ Configuration changes +4/-0

Register new dialog and feature in CMake

ApplicationLibCode/Commands/CMakeLists_files.cmake


7. ApplicationLibCode/UserInterface/RiuMainWindow.cpp ✨ Enhancement +1/-0

Add import feature action to toolbar

ApplicationLibCode/UserInterface/RiuMainWindow.cpp


8. ApplicationLibCode/UserInterface/RiuMenuBarBuildTools.cpp ✨ Enhancement +3/-0

Add import feature to Eclipse Cases menu

ApplicationLibCode/UserInterface/RiuMenuBarBuildTools.cpp


9. ApplicationExeCode/Resources/ResInsight.qrc ⚙️ Configuration changes +1/-0

Register new GridAndSummaryEnsemble icon resource

ApplicationExeCode/Resources/ResInsight.qrc


10. ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp 🐞 Bug fix +1/-1

Fix debug build assertion in setCellResultIndex

ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp


11. ApplicationLibCode/Application/RiaMemoryCleanup.cpp 🐞 Bug fix +1/-1

Fix lambda capture to use empty capture list

ApplicationLibCode/Application/RiaMemoryCleanup.cpp


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 5, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (3) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Wrong file-set inputs🐞 Bug ✓ Correctness
Description
The new feature unions grid+summary realizations into a single file set regardless of requested
ensemble types, which can make grid/sum ensembles try to load non-existent files. It also uses QSet
iteration (non-deterministic), undermining the comment that order is consistent for grouping/pattern
detection.
Code

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.cpp[R42-70]

+    // Build the union of base paths (extension-stripped) from both lists so every realization
+    // appears exactly once. findPathPattern requires each realization number to be unique across
+    // the input; duplicating paths with different extensions breaks the pattern detection.
+    auto stripExtension = []( const QString& path ) -> QString
+    {
+        int dot = path.lastIndexOf( '.' );
+        return dot != -1 ? path.left( dot ) : path;
+    };
+
+    QSet<QString> basePaths;
+    for ( const auto& f : result.gridFiles )
+        basePaths.insert( stripExtension( f ) );
+    for ( const auto& f : result.summaryFiles )
+        basePaths.insert( stripExtension( f ) );
+
+    if ( basePaths.isEmpty() ) return;
+
+    // Convert to list for the file set creation. The dialog should ensure that the base paths are in a consistent order, so the grouping
+    // should work as intended.
+    QStringList representativeFiles;
+    for ( const auto& base : basePaths )
+        representativeFiles << base;
+
+    auto fileSets = RimEnsembleFileSetTools::createEnsembleFileSets( representativeFiles, result.groupingMode );
+    if ( fileSets.empty() ) return;
+
+    if ( result.createGridEnsemble ) RimEnsembleFileSetTools::createGridEnsemblesFromFileSets( fileSets );
+
+    if ( result.createSummaryEnsemble ) RimEnsembleFileSetTools::createSummaryEnsemblesFromFileSets( fileSets );
Evidence
The dialog only appends a grid file when a grid file is present and only appends a summary file when
a summary file is present; therefore some realizations can be grid-only or summary-only in the
result lists. The feature then unions both lists into one representative list and creates a single
file set that is used to create both grid and summary ensembles; downstream, ensembles expand the
file-set’s realization range into concrete paths without checking existence (grid ensemble
immediately creates case objects for every generated path, and summary ensemble always generates
SMSPEC paths). This makes it easy to create ensembles containing paths that do not exist (e.g.,
summary-only realizations when creating a grid ensemble, or grid-only realizations when creating a
summary ensemble).

ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.cpp[161-190]
ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.cpp[42-70]
ApplicationLibCode/Application/Tools/Ensemble/RiaEnsembleImportTools.cpp[227-239]
ApplicationLibCode/ProjectDataModel/RimReservoirGridEnsemble.cpp[809-836]
ApplicationLibCode/ProjectDataModel/Summary/Ensemble/RimSummaryFileSetEnsemble.cpp[153-172]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RicImportGridAndSummaryEnsembleFeature` always unions `result.gridFiles` and `result.summaryFiles` into one file-set input list and then uses that file set to create *both* grid and summary ensembles. This can cause the created ensembles to reference non-existent files (e.g., creating grid cases for summary-only realizations).
### Issue Context
- The dialog only appends a grid file if one was found, and only appends a summary file if one was found.
- Downstream, ensembles expand the file set’s realization range into concrete paths without verifying existence.
- `QSet` iteration order is not stable, so grouping/path-pattern detection may become non-deterministic.
### Fix Focus Areas
- ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleFeature.cpp[42-70]
- ApplicationLibCode/Commands/RicImportGridAndSummaryEnsembleDialog.cpp[161-190]
### Suggested change
- If `result.createGridEnsemble &amp;amp;amp;amp;&amp;amp;amp;amp; !result.createSummaryEnsemble`: build representative list from `result.gridFiles` only.
- If `!result.createGridEnsemble &amp;amp;amp;amp;&amp;amp;amp;amp; result.createSummaryEnsemble`: build representative list from `result.summaryFiles` only.
- If both are true:
- Prefer building representative list from the *intersection* of base paths present in both lists (so both ensembles get the same, complete set), OR
- Create two separate `fileSets` (one from grid list, one from summary list) and create each ensemble type from the corresponding fileSets.
- Replace `QSet` iteration with deterministic ordering:
- Use a `QStringList`, de-dup explicitly, then sort with `QCollator` numeric mode (or reuse the dialog’s deterministic ordering).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Wrong bounds assert 🐞 Bug ✓ Correctness
Description
RigActiveCellInfo::setCellResultIndex asserts on reservoirCellResultIndex but indexes the vector
using reservoirCellIndex, allowing out-of-bounds writes. This is inconsistent with other methods
which correctly assert reservoirCellIndex before indexing.
Code

ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[R91-96]

void RigActiveCellInfo::setCellResultIndex( ReservoirCellIndex reservoirCellIndex, ActiveCellIndex reservoirCellResultIndex )
{
-    CVF_TIGHT_ASSERT( reservoirCellResultIndex < m_reservoirCellToActiveCell.size() );
+    CVF_TIGHT_ASSERT( reservoirCellResultIndex.value() < m_reservoirCellToActiveCell.size() );
 m_reservoirCellToActiveCell[reservoirCellIndex.value()] = reservoirCellResultIndex;
}
Evidence
setCellResultIndex writes m_reservoirCellToActiveCell[reservoirCellIndex.value()] but its guard
checks a different variable (reservoirCellResultIndex). If reservoirCellIndex is invalid, the
write can go out of range; nearby methods demonstrate the intended guard is to validate
reservoirCellIndex.value() < size() before indexing.

ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[50-60]
ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[91-96]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RigActiveCellInfo::setCellResultIndex` currently asserts the bounds of `reservoirCellResultIndex` but then indexes the vector using `reservoirCellIndex`, so an invalid `reservoirCellIndex` can still write out of bounds.
### Issue Context
Other methods in the same file (`isActive`, `cellResultIndex`) correctly assert `reservoirCellIndex.value() &amp;amp;amp;lt; m_reservoirCellToActiveCell.size()` before indexing.
### Fix Focus Areas
- ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[91-96]
### Suggested change
Replace:
- `CVF_TIGHT_ASSERT( reservoirCellResultIndex.value() &amp;amp;amp;lt; m_reservoirCellToActiveCell.size() );`
with:
- `CVF_TIGHT_ASSERT( reservoirCellIndex.value() &amp;amp;amp;lt; m_reservoirCellToActiveCell.size() );`
Optionally add a second assert if there is a well-defined upper bound for `reservoirCellResultIndex`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unrelated memory report lambda 📘 Rule violation ✓ Correctness
Description
The PR modifies the Show Memory Report button callback capture from [this] to [], which
appears unrelated to the ensemble import dialog work. This adds diff noise and should be reverted or
moved to a separate PR if not required for this feature.
Code

ApplicationLibCode/Application/RiaMemoryCleanup.cpp[337]

+    uiOrdering.addNewButton( "Show Memory Report", []() { RiaMemoryCleanup::showMemoryReport(); } );
Evidence
Compliance ID 1 requires limiting changes to those necessary for the task; changing the lambda
capture for the memory report UI is a separate concern from the new import dialog/feature.

CLAUDE.md
ApplicationLibCode/Application/RiaMemoryCleanup.cpp[337-337]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR includes a small, likely-unrelated change to the `Show Memory Report` button callback capture list, adding noise to the diff.
## Issue Context
This PR is focused on a unified ensemble import dialog/feature; unrelated refactors should be avoided or separated.
## Fix Focus Areas
- ApplicationLibCode/Application/RiaMemoryCleanup.cpp[337-337]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Unrelated CVF_TIGHT_ASSERT edit 📘 Rule violation ✓ Correctness
Description
The PR changes CVF_TIGHT_ASSERT to use reservoirCellResultIndex.value() in
RigActiveCellInfo::setCellResultIndex, which appears unrelated to the import dialog feature. If
this is a required bugfix, it should be justified; otherwise, it should be separated to keep the PR
minimal.
Code

ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[93]

+    CVF_TIGHT_ASSERT( reservoirCellResultIndex.value() < m_reservoirCellToActiveCell.size() );
Evidence
Compliance ID 1 requires minimal, task-related diffs; this assertion change is in reservoir cell
indexing code and does not appear connected to the ensemble import dialog/feature additions.

CLAUDE.md
ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[93-93]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An unrelated assertion change was included in the PR, increasing scope and review noise.
## Issue Context
The PR goal is a unified ensemble import dialog; reservoir active cell assertion updates should be separate unless they are a prerequisite for this work.
## Fix Focus Areas
- ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[93-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Unrelated importSingleEnsembleFileSet exposure 📘 Rule violation ⛯ Reliability
Description
The PR moves importSingleEnsembleFileSet into the public section of RicImportEnsembleFeature,
expanding the public API surface without an evident need tied to the new grid/summary import dialog.
This should be justified or avoided to keep changes minimal and scoped.
Code

ApplicationLibCode/Commands/RicImportEnsembleFeature.h[R45-50]

+    static RimSummaryEnsemble* importSingleEnsembleFileSet( const QStringList&               fileNames,
+                                                            bool                             useEnsembleNameDialog,
+                                                            RiaDefines::EnsembleGroupingMode groupingMode,
+                                                            RiaDefines::FileType             fileType,
+                                                            const QString&                   defaultEnsembleName = QString() );
+
Evidence
Compliance ID 1 requires changes to be limited to what is necessary for the task; changing method
visibility and adding a new forward declaration increases scope and can have broader coupling impact
if not required for the feature.

CLAUDE.md
ApplicationLibCode/Commands/RicImportEnsembleFeature.h[45-50]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A method was moved to the public API surface (`importSingleEnsembleFileSet`) without clear linkage to the PR’s new import dialog/feature.
## Issue Context
The PR aims to add a unified grid+summary ensemble import flow; unrelated API visibility changes should be avoided or explicitly justified.
## Fix Focus Areas
- ApplicationLibCode/Commands/RicImportEnsembleFeature.h[45-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 91 to 96
void RigActiveCellInfo::setCellResultIndex( ReservoirCellIndex reservoirCellIndex, ActiveCellIndex reservoirCellResultIndex )
{
CVF_TIGHT_ASSERT( reservoirCellResultIndex < m_reservoirCellToActiveCell.size() );
CVF_TIGHT_ASSERT( reservoirCellResultIndex.value() < m_reservoirCellToActiveCell.size() );

m_reservoirCellToActiveCell[reservoirCellIndex.value()] = reservoirCellResultIndex;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Wrong bounds assert 🐞 Bug ✓ Correctness

RigActiveCellInfo::setCellResultIndex asserts on reservoirCellResultIndex but indexes the vector
using reservoirCellIndex, allowing out-of-bounds writes. This is inconsistent with other methods
which correctly assert reservoirCellIndex before indexing.
Agent Prompt
### Issue description
`RigActiveCellInfo::setCellResultIndex` currently asserts the bounds of `reservoirCellResultIndex` but then indexes the vector using `reservoirCellIndex`, so an invalid `reservoirCellIndex` can still write out of bounds.

### Issue Context
Other methods in the same file (`isActive`, `cellResultIndex`) correctly assert `reservoirCellIndex.value() < m_reservoirCellToActiveCell.size()` before indexing.

### Fix Focus Areas
- ApplicationLibCode/ReservoirDataModel/RigActiveCellInfo.cpp[91-96]

### Suggested change
Replace:
- `CVF_TIGHT_ASSERT( reservoirCellResultIndex.value() < m_reservoirCellToActiveCell.size() );`
with:
- `CVF_TIGHT_ASSERT( reservoirCellIndex.value() < m_reservoirCellToActiveCell.size() );`

Optionally add a second assert if there is a well-defined upper bound for `reservoirCellResultIndex`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

magnesj and others added 20 commits March 5, 2026 19:02
…ined import dialog

Make importSingleEnsembleFileSet public in RicImportEnsembleFeature to allow external callers.
Replace RiaDefines.h include with Summary/RiaSummaryDefines.h since
EnsembleGroupingMode is defined there. Add RimSummaryCaseMainCollection.h
include to the feature cpp to resolve undefined type error.
…ility

Update the feature to use a new dedicated SVG icon, add the action to the main toolbar, and move it to the top level of the Import menu for better accessibility.
…ation and UX improvements

- Create a default 3D view after importing grid ensemble
- Create a default summary multi-plot after importing summary ensemble
- Show plot main window when summary ensemble is imported
- Restore previously active main window after import (500ms deferred raise/activate)
- Add RimReservoirGridEnsemble::viewCollection() public accessor
- Fix RimEnsembleFileSetTools::createGridEnsemblesFromFileSets to call
  createGridCasesFromEnsembleFileSet() before loadDataAndUpdate() so cases
  are populated immediately (not only on project reload)
- Restore most recently used path pattern in dialog when preference is enabled
- Add GridAndSummaryEnsemble.svg icon and register in resource file
- Move menu item from Eclipse Cases submenu to top-level Import menu
…nd fix import guards

- Move firstLevelItems, setCheckedStateChildItems, findItemsMatching and
  populateComboBoxHistoryFromRegistry to public static methods on
  RicRecursiveFileSearchDialog, eliminating identical copies in
  RicImportGridAndSummaryEnsembleDialog
- Skip grid ensemble creation when no grid files are found
- Skip summary ensemble creation when no summary files are found
- Keep focus in plot window when no grid ensembles are created
@magnesj magnesj force-pushed the unified-emsemble-import branch from 8e5a8a8 to c546d49 Compare March 5, 2026 18:02
@magnesj magnesj closed this Mar 9, 2026
@magnesj magnesj deleted the unified-emsemble-import branch March 9, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant