Skip to content

Inplace volumes waterfall - #1858

Open
HansKallekleiv wants to merge 14 commits into
equinor:mainfrom
HansKallekleiv:pr/volume-change-decomposition
Open

Inplace volumes waterfall#1858
HansKallekleiv wants to merge 14 commits into
equinor:mainfrom
HansKallekleiv:pr/volume-change-decomposition

Conversation

@HansKallekleiv

@HansKallekleiv HansKallekleiv commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Closes #1808

New module decomposing the change in STOIIP/GIIP between two ensembles into
additive contributions from its volumetric factors (BULK, PORO or NTG+PORO_NET,
SW, BO/BG), rendered as a waterfall plot.

The reference and comparison ensembles are selected explicitly with two ensemble
dropdowns; the decomposition operates on per-ensemble means, so it does not
require realization alignment between the two ensembles.

Ported from the legacy webviz-subsurface waterfall.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new InplaceVolumesComparison module that compares two inplace-volumes sources (across ensembles and/or table sources) and visualizes the STOIIP/GIIP mean change as a Plotly waterfall decomposition into volumetric-factor contributions.

Changes:

  • Adds the new InplaceVolumesComparison module (settings + view) including factor-spec generation, decomposition math, and Plotly waterfall rendering.
  • Refactors shared inplace-volumes query utilities to support querying an explicit list of (ensemble, table) sources (not only a cross-product).
  • Updates inplace-volumes module registration metadata (descriptions/titles) and adds unit tests for the new decomposition and source-selection utilities.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/tests/unit/InplaceVolumesWaterfallSources.test.ts Adds unit tests for source lookup and endpoint label behavior.
frontend/tests/unit/InplaceVolumesWaterfallDecomposition.test.ts Adds unit tests for factor spec building and decomposition reconciliation/edge cases.
frontend/src/modules/registerAllModules.ts Registers the new InplaceVolumesComparison module.
frontend/src/modules/InplaceVolumesTable/registerModule.ts Updates module description text.
frontend/src/modules/InplaceVolumesPlot/registerModule.ts Updates deprecated-module description text.
frontend/src/modules/InplaceVolumesNew/registerModule.ts Updates module description and default title for the newer inplace-volumes plotting module.
frontend/src/modules/InplaceVolumesComparison/view/view.tsx Adds view wrapper wiring (status, sizing, plot rendering).
frontend/src/modules/InplaceVolumesComparison/view/utils/waterfallSources.ts Adds utilities for locating per-source table data and making endpoint labels.
frontend/src/modules/InplaceVolumesComparison/view/utils/computeVolumeChangeDecomposition.ts Implements factor spec creation and the decomposition computation.
frontend/src/modules/InplaceVolumesComparison/view/utils/buildWaterfallPlot.tsx Implements Plotly waterfall construction and subplot layout.
frontend/src/modules/InplaceVolumesComparison/view/hooks/useBuildWaterfallPlot.ts Implements orchestration: selection validation, data extraction, decomposition per group, and plot building.
frontend/src/modules/InplaceVolumesComparison/view/atoms/queryAtoms.ts Adds atoms for explicit source selection and statistical data queries.
frontend/src/modules/InplaceVolumesComparison/view/atoms/interfaceEffects.ts Wires settings→view interface values into view atoms.
frontend/src/modules/InplaceVolumesComparison/view/atoms/baseAtoms.ts Adds base atoms for view-side selections and derived state.
frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx Adds the module settings UI (sources, response, subplot-by, filters).
frontend/src/modules/InplaceVolumesComparison/settings/persistence.ts Adds settings persistence (schema + serialize/deserialize).
frontend/src/modules/InplaceVolumesComparison/settings/atoms/queryAtoms.ts Adds table-definition query for the selected ensembles.
frontend/src/modules/InplaceVolumesComparison/settings/atoms/persistableFixableAtoms.ts Adds persistable/fixable atoms for settings selections.
frontend/src/modules/InplaceVolumesComparison/settings/atoms/derivedAtoms.ts Adds derived atoms (available options, comparability, factor spec, query indices).
frontend/src/modules/InplaceVolumesComparison/settings/atoms/baseAtoms.ts Adds base atom for index-value criteria.
frontend/src/modules/InplaceVolumesComparison/registerModule.ts Registers the new module with metadata (DEV state).
frontend/src/modules/InplaceVolumesComparison/preview.tsx Adds module preview thumbnail drawing.
frontend/src/modules/InplaceVolumesComparison/persistence.ts Adds module-level state schema + serialization wiring.
frontend/src/modules/InplaceVolumesComparison/loadModule.tsx Adds module load/init wiring for settings + view components.
frontend/src/modules/InplaceVolumesComparison/interfaces.ts Adds settings→view interface definition and initialization mapping.
frontend/src/modules/_shared/InplaceVolumes/queryHooks.ts Adds InplaceVolumesSource and makeAggregatedStatisticalTableDataQueryOptions for explicit source querying.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread frontend/src/modules/InplaceVolumesComparison/view/hooks/useBuildWaterfallPlot.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (3)

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:81

  • areSourcesDistinct is also false while either table is unselected. Consequently, selecting two different ensembles can mark the reference ensemble as invalid during table loading—or permanently when one ensemble has no tables—even though the ensembles already differ. Only show this duplicate-source error once both table selections are present.
    const isSameSourceSelectedTwice = Boolean(
        referenceEnsembleIdent.value && comparisonEnsembleIdent.value && !areSourcesDistinct,
    );

frontend/src/modules/InplaceVolumesComparison/view/hooks/useBuildWaterfallPlot.ts:232

  • The intersection silently drops a selected group that has rows in only one source (for example after per-ensemble realization filtering). Such a group is neither plotted nor added to skippedGroupLabels, so the resulting comparison appears complete. Build the sorted union and treat a missing side as a skipped group.
    const groupKeys = Array.from(comparisonStatisticsByGroup.keys())
        .filter((groupKey) => referenceStatisticsByGroup.has(groupKey))
        .sort((a, b) => a.localeCompare(b));

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:50

  • Table-definition request failures are never propagated to the settings status writer. Because failed results are converted to empty definition arrays, the UI instead reports “No inplace volumes tables in this ensemble,” which misdiagnoses an API failure as missing data. Propagate tableDefinitionsQuery.errors via the shared API-error status hook, as the other inplace-volume settings modules do.

This issue also appears on line 79 of the same file.

    const tableDefinitionsQuery = useAtomValue(tableDefinitionsQueryAtom);

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated no new comments.

Suppressed comments (6)

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:211

  • A failed table-definition request also leaves comparisonTableNameOptions empty, causing this field to report that the ensemble has no tables. Distinguish tableDefinitionsQuery.errors from a successful empty response and present a load failure.
                        errorOverlay={
                            !tableDefinitionsQuery.isLoading &&
                            comparisonEnsembleIdent.value &&
                            comparisonTableNameOptions.length === 0
                                ? "No inplace volumes tables in this ensemble."
                                : undefined

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:307

  • When the only differences are columns missing from one source, enabling the switch cannot filter to a shared subset, but this branch still claims that it does and that the totals are partial. Base this message on whether there is at least one shared column with differing values, not only on the selected criterion.
                                {isIndexValueIntersectionEnabled
                                    ? "Only values present in both are compared, so the totals below are for that shared subset and will not match the full-field volumes."
                                    : "These indices are left unfiltered, so the full volume of both sources is compared and the difference in coverage shows up in the BULK contribution."}

frontend/src/modules/InplaceVolumesComparison/settings/atoms/derivedAtoms.ts:182

  • This marks intersection as active for missing-column differences too. Those columns cannot be intersected and never enter availableIndicesWithValuesAtom, so enabling the switch does not narrow the query, yet the view warns that only a shared subset is plotted. Treat intersection as active only when a shared column has differing values.
export const isIndexValueIntersectionActiveAtom = atom(
    (get) => get(isIndexValueIntersectionEnabledAtom) && get(indexColumnDifferencesAtom).length > 0,
);

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:180

  • A failed table-definition request is converted to an empty table list, so this condition reports “No inplace volumes tables” for network/server failures as well. Check tableDefinitionsQuery.errors and surface a load failure instead of misdiagnosing the ensemble as empty; the comparison-table field has the same issue.

This issue also appears on line 206 of the same file.

                        errorOverlay={
                            !tableDefinitionsQuery.isLoading &&
                            referenceEnsembleIdent.value &&
                            referenceTableNameOptions.length === 0
                                ? "No inplace volumes tables in this ensemble."
                                : undefined

frontend/src/modules/InplaceVolumesComparison/settings/settings.tsx:282

  • missingFrom names the side where the column is absent, but this message presents it as the side where the column exists. For example, a reference-only FACIES column is stored as missingFrom: "comparison" and is currently reported as existing only in comparison.

This issue also appears on line 305 of the same file.

                                            <> exists only in the {difference.missingFrom}, so it cannot be used.</>

frontend/src/modules/InplaceVolumesComparison/view/hooks/useBuildWaterfallPlot.ts:225

  • This branch is reached only when getAreTablesComparable() is false, which this module's accessor configuration defines as having no common index columns; result-name intersection is checked separately below. The current message can therefore incorrectly claim there are no common result names even when STOIIP/GIIP is shared.
    if (!areSelectedTablesComparable) {
        return makeErrorResult(
            "The selected tables are not comparable: they have no result names or index columns in common.",
        );

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.

Volume waterfall (ensemble comparison)

2 participants