Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ void RimCloudDataSourceCollection::createEnsemblesFromSelectedDataSources( const
sumCaseMainColl->updateAllRequiredEditors();
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCloudDataSourceCollection::addSumoDataSource( RimSummarySumoDataSource* dataSource )
{
if ( !dataSource ) return;
m_sumoDataSources.push_back( dataSource );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class RimCloudDataSourceCollection : public caf::PdmObject

std::vector<RimSummarySumoDataSource*> sumoDataSources() const;

void addSumoDataSource( RimSummarySumoDataSource* dataSource );
static void createEnsemblesFromSelectedDataSources( const std::vector<RimSummarySumoDataSource*>& dataSources );

private:
Expand Down
66 changes: 66 additions & 0 deletions ApplicationLibCode/ProjectDataModelCommands/RimcProject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "RicImportSummaryCasesFeature.h"

#include "Cloud/RimCloudDataSourceCollection.h"
#include "RimCornerPointCase.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseCellColors.h"
Expand All @@ -40,6 +41,10 @@
#include "RimTools.h"
#include "RimValveTemplateCollection.h"
#include "RimWellPathCollection.h"
#include "Sumo/RimSummaryEnsembleSumo.h"
#include "Sumo/RimSummarySumoDataSource.h"

#include "Summary/RiaSummaryTools.h"

#include "RiuMainWindow.h"
#include "RiuPlotMainWindow.h"
Expand Down Expand Up @@ -289,6 +294,67 @@ QString RimProject_createGridFromKeyValues::classKeywordReturnedType() const
return RimCornerPointCase::classKeywordStatic();
}

CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimProject, RimProject_importSummaryEnsembleSumo, "importSummaryEnsembleSumo" );

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimProject_importSummaryEnsembleSumo::RimProject_importSummaryEnsembleSumo( caf::PdmObjectHandle* self )
: PdmObjectCreationMethod( self )
{
CAF_PDM_InitObject( "Import Summary Ensemble from Sumo", "", "", "Import Summary Ensemble from Sumo" );

CAF_PDM_InitScriptableFieldNoDefault( &m_caseId, "CaseId", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_caseName, "CaseName", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_ensembleName, "EnsembleName", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_vectorNames, "VectorNames", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_realizationIds, "RealizationIds", "" );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimProject_importSummaryEnsembleSumo::execute()
{
if ( m_caseId().isEmpty() ) return std::unexpected( "Empty case ID not allowed" );
if ( m_ensembleName().isEmpty() ) return std::unexpected( "Empty ensemble name not allowed" );

auto cloudDataSourceCollection = RimCloudDataSourceCollection::instance();
if ( !cloudDataSourceCollection ) return std::unexpected( "No cloud data source collection found." );

auto sumCaseMainColl = RiaSummaryTools::summaryCaseMainCollection();
if ( !sumCaseMainColl ) return std::unexpected( "No summary case main collection found." );

auto dataSource = new RimSummarySumoDataSource();
dataSource->setCaseId( SumoCaseId( m_caseId() ) );
dataSource->setCaseName( m_caseName() );
dataSource->setEnsembleName( m_ensembleName() );
dataSource->setRealizationIds( m_realizationIds() );
dataSource->setVectorNames( m_vectorNames() );
dataSource->updateName();

cloudDataSourceCollection->addSumoDataSource( dataSource );

auto ensemble = new RimSummaryEnsembleSumo();
ensemble->setUsePathKey1( true );
ensemble->setSumoDataSource( dataSource );
sumCaseMainColl->addEnsemble( ensemble );
ensemble->loadDataAndUpdate();

RiaSummaryTools::updateSummaryEnsembleNames();
sumCaseMainColl->updateAllRequiredEditors();

return ensemble;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimProject_importSummaryEnsembleSumo::classKeywordReturnedType() const
{
return RimSummaryEnsembleSumo::classKeywordStatic();
}

CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimProject, RimProject_wellPathCollection, "wellPathCollection" );

//--------------------------------------------------------------------------------------------------
Expand Down
21 changes: 21 additions & 0 deletions ApplicationLibCode/ProjectDataModelCommands/RimcProject.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ class RimProject_createGridFromKeyValues : public caf::PdmObjectCreationMethod
caf::PdmField<QString> m_actnumKey;
};

//==================================================================================================
///
//==================================================================================================
class RimProject_importSummaryEnsembleSumo : public caf::PdmObjectCreationMethod
{
CAF_PDM_HEADER_INIT;

public:
RimProject_importSummaryEnsembleSumo( caf::PdmObjectHandle* self );

std::expected<caf::PdmObjectHandle*, QString> execute() override;
QString classKeywordReturnedType() const override;

private:
caf::PdmField<QString> m_caseId;
caf::PdmField<QString> m_caseName;
caf::PdmField<QString> m_ensembleName;
caf::PdmField<std::vector<QString>> m_vectorNames;
caf::PdmField<std::vector<QString>> m_realizationIds;
};

//==================================================================================================
///
//==================================================================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
Import a SUMO ensemble into ResInsight using the fmu-sumo Python package.

This script demonstrates how to use the fmu-sumo package to access SUMO metadata
and then import the ensemble into ResInsight for visualization and analysis.

The fmu-sumo package provides a high-level API for accessing SUMO data, replacing
the fragile direct Elastic search queries used by ResInsight's built-in SUMO connector.

Prerequisites:
pip install fmu-sumo rips

Usage:
python sumo_ensemble_import.py
"""

# Load ResInsight Processing Server Client Library
import rips

# Load the fmu-sumo Explorer for metadata access
from fmu.sumo.explorer import Explorer


def import_sumo_ensemble(
asset_name: str,
case_name: str,
iteration_name: str,
) -> None:
"""Import a SUMO ensemble into ResInsight.

Uses fmu-sumo to access SUMO metadata (cases, ensembles, vector names,
realization IDs) and then creates the corresponding ensemble in ResInsight.
The actual summary data is fetched lazily by ResInsight when plots are created.

Arguments:
asset_name (str): The SUMO asset (field) name, e.g. "Drogon"
case_name (str): The SUMO case name to search for
iteration_name (str): The ensemble/iteration name within the case
"""

# Connect to ResInsight instance
resinsight = rips.Instance.find()
project = resinsight.project

# Connect to SUMO using fmu-sumo Explorer
# The Explorer handles authentication automatically
sumo = Explorer(env="prod")

# Find cases matching the given asset and case name
cases = sumo.cases.filter(asset=asset_name)
matching_cases = [c for c in cases if c.name == case_name]

if not matching_cases:
print(f"No case found with name '{case_name}' for asset '{asset_name}'")
return

sumo_case = matching_cases[0]
print(f"Found SUMO case: {sumo_case.name} (id: {sumo_case.uuid})")

# Find the ensemble/iteration within the case
iterations = sumo_case.iterations
matching_iterations = [it for it in iterations if it.name == iteration_name]

if not matching_iterations:
available = [it.name for it in iterations]
print(f"Iteration '{iteration_name}' not found. Available: {available}")
return

iteration = matching_iterations[0]
print(f"Found iteration: {iteration.name}")

# Get realization IDs from the iteration
realization_ids = [str(r) for r in iteration.realizations]
print(f"Found {len(realization_ids)} realizations")

# Find summary tables within the iteration
summary_tables = iteration.tables.filter(tagname="summary")

if not summary_tables:
print("No summary tables found for this iteration")
return

summary_table = summary_tables[0]

# Get vector names (column names) from the summary table
# Exclude metadata columns (DATE, REAL, ENSEMBLE, etc.)
metadata_columns = {"DATE", "REAL", "ENSEMBLE", "ITER"}
vector_names = [
col for col in summary_table.column_names if col.upper() not in metadata_columns
]
print(f"Found {len(vector_names)} summary vectors")

# Import the ensemble into ResInsight
# This creates a SummaryEnsembleSumo object that will lazily load
# the actual parquet data when plots are created
ensemble = project.import_summary_ensemble_sumo(
case_id=sumo_case.uuid,
case_name=sumo_case.name,
ensemble_name=iteration.name,
vector_names=vector_names,
realization_ids=realization_ids,
)

if ensemble is not None:
print(f"Successfully imported SUMO ensemble: {ensemble.name}")
else:
print("Failed to import SUMO ensemble")


if __name__ == "__main__":
# Example: import a Drogon ensemble from SUMO
import_sumo_ensemble(
asset_name="Drogon",
case_name="Drogon_AHM_2023-02-01",
iteration_name="iter-0",
)