Skip to content

Commit ee92408

Browse files
committed
#13890 Python: Add scriptable API for selected-fault FAULTDIST
Expose the new RimFaultDistanceResult facility to Python by marking the relevant PDM classes and fields scriptable. RimEclipseView's m_faultCollection, RimFaultInViewCollection, RimFaultInView, RimFaultDistanceResult, and RimFaultDistanceResultCollection are now scriptable, so faults can be enumerated from Python via view.fault_collection().faults(). A new Rimc method add_fault_distance_result on RimFaultInViewCollection takes a name and a list of fault objects, creates the result (auto-numbered FAULTDIST<n> when the name is empty), and returns the new RimFaultDistanceResult. An empty fault list falls back to every fault in the view, matching the static-native FAULTDIST behaviour. Add a Python test exercising both a subset call and a parity check that asserts the all-faults result matches the existing static-native FAULTDIST cell-for-cell.
1 parent f75d865 commit ee92408

9 files changed

Lines changed: 219 additions & 12 deletions

File tree

ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "RimFaultInView.h"
3232
#include "RimFaultInViewCollection.h"
3333

34+
#include "cafPdmFieldScriptingCapability.h"
35+
#include "cafPdmObjectScriptingCapability.h"
3436
#include "cafPdmUiTreeSelectionEditor.h"
3537

3638
CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" );
@@ -40,11 +42,16 @@ CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" );
4042
//--------------------------------------------------------------------------------------------------
4143
RimFaultDistanceResult::RimFaultDistanceResult()
4244
{
43-
CAF_PDM_InitObject( "Fault Distance Result", ":/draw_style_faults_24x24.png" );
45+
CAF_PDM_InitScriptableObjectWithNameAndComment( "Fault Distance Result",
46+
":/draw_style_faults_24x24.png",
47+
"",
48+
"",
49+
"FaultDistanceResult",
50+
"Per-cell distance to a selected subset of faults" );
4451

45-
CAF_PDM_InitFieldNoDefault( &m_resultName, "ResultName", "Name" );
52+
CAF_PDM_InitScriptableFieldNoDefault( &m_resultName, "ResultName", "Name" );
4653

47-
CAF_PDM_InitFieldNoDefault( &m_faults, "SelectedFaults", "Faults" );
54+
CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "SelectedFaults", "Faults" );
4855
m_faults.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
4956
}
5057

ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "RimFaultDistanceResult.h"
2222

23+
#include "cafPdmFieldScriptingCapability.h"
24+
#include "cafPdmObjectScriptingCapability.h"
2325
#include "cafPdmUiTreeOrdering.h"
2426

2527
#include <QRegularExpression>
@@ -31,9 +33,14 @@ CAF_PDM_SOURCE_INIT( RimFaultDistanceResultCollection, "RimFaultDistanceResultCo
3133
//--------------------------------------------------------------------------------------------------
3234
RimFaultDistanceResultCollection::RimFaultDistanceResultCollection()
3335
{
34-
CAF_PDM_InitObject( "Fault Distance Results", ":/draw_style_faults_24x24.png" );
36+
CAF_PDM_InitScriptableObjectWithNameAndComment( "Fault Distance Results",
37+
":/draw_style_faults_24x24.png",
38+
"",
39+
"",
40+
"FaultDistanceResultCollection",
41+
"Collection of named, subset-based FAULTDIST results" );
3542

36-
CAF_PDM_InitFieldNoDefault( &m_items, "FaultDistanceResults", "" );
43+
CAF_PDM_InitScriptableFieldNoDefault( &m_items, "FaultDistanceResults", "" );
3744
}
3845

3946
//--------------------------------------------------------------------------------------------------

ApplicationLibCode/ProjectDataModel/Faults/RimFaultInView.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,24 @@
2424
#include "RimEclipseView.h"
2525
#include "RimIntersectionCollection.h"
2626

27+
#include "cafPdmFieldScriptingCapability.h"
28+
#include "cafPdmObjectScriptingCapability.h"
29+
2730
CAF_PDM_SOURCE_INIT( RimFaultInView, "Fault" );
2831

2932
//--------------------------------------------------------------------------------------------------
3033
///
3134
//--------------------------------------------------------------------------------------------------
3235
RimFaultInView::RimFaultInView()
3336
{
34-
CAF_PDM_InitObject( "RimFault", ":/draw_style_faults_24x24.png" );
35-
36-
CAF_PDM_InitFieldNoDefault( &name, "FaultName", "Name" );
37+
CAF_PDM_InitScriptableObjectWithNameAndComment( "RimFault",
38+
":/draw_style_faults_24x24.png",
39+
"",
40+
"",
41+
"FaultInView",
42+
"A fault belonging to a view's fault collection" );
43+
44+
CAF_PDM_InitScriptableFieldNoDefault( &name, "FaultName", "Name" );
3745
name.uiCapability()->setUiHidden( true );
3846
name.uiCapability()->setUiReadOnly( true );
3947

ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
#include "cafAppEnum.h"
3838
#include "cafPdmFieldCvfColor.h"
39+
#include "cafPdmFieldScriptingCapability.h"
40+
#include "cafPdmObjectScriptingCapability.h"
3941
#include "cafPdmUiCheckBoxEditor.h"
4042
#include "cafPdmUiLineEditor.h"
4143
#include "cafPdmUiTreeOrdering.h"
@@ -59,7 +61,12 @@ CAF_PDM_SOURCE_INIT( RimFaultInViewCollection, "Faults" );
5961
//--------------------------------------------------------------------------------------------------
6062
RimFaultInViewCollection::RimFaultInViewCollection()
6163
{
62-
CAF_PDM_InitObject( "Faults", ":/draw_style_faults_24x24.png" );
64+
CAF_PDM_InitScriptableObjectWithNameAndComment( "Faults",
65+
":/draw_style_faults_24x24.png",
66+
"",
67+
"",
68+
"FaultInViewCollection",
69+
"Per-view fault collection" );
6370

6471
CAF_PDM_InitField( &m_showFaultCollection, "Active", true, "Active" );
6572
m_showFaultCollection.uiCapability()->setUiHidden( true );
@@ -97,9 +104,9 @@ RimFaultInViewCollection::RimFaultInViewCollection()
97104
"Hide NNC Geometry if No NNC Result is Available" );
98105
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_hideNNCsWhenNoResultIsAvailable );
99106

100-
CAF_PDM_InitFieldNoDefault( &m_faults, "Faults", "Faults" );
107+
CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "Faults", "Faults" );
101108

102-
CAF_PDM_InitFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" );
109+
CAF_PDM_InitScriptableFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" );
103110
m_distanceResults = new RimFaultDistanceResultCollection;
104111

105112
CAF_PDM_InitField( &m_showFaultsOutsideFilters_obsolete, "ShowFaultsOutsideFilters", true, "Show Faults Outside Filters" );

ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ RimEclipseView::RimEclipseView()
198198
CAF_PDM_InitFieldNoDefault( &m_wellCollection, "WellCollection", "Simulation Wells" );
199199
m_wellCollection = new RimSimWellInViewCollection;
200200

201-
CAF_PDM_InitFieldNoDefault( &m_faultCollection, "FaultCollection", "Faults" );
201+
CAF_PDM_InitScriptableFieldNoDefault( &m_faultCollection, "FaultCollection", "Faults" );
202202
m_faultCollection = new RimFaultInViewCollection;
203203

204204
CAF_PDM_InitFieldNoDefault( &m_faultReactivationModelCollection, "FaultReactivationModelCollection", "Fault Reactivation Models" );

ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ set(SOURCE_GROUP_SOURCE_FILES
3131
${CMAKE_CURRENT_LIST_DIR}/RimcGridView.cpp
3232
${CMAKE_CURRENT_LIST_DIR}/RimcIdenticalGridCaseGroup.cpp
3333
${CMAKE_CURRENT_LIST_DIR}/RimcPressureTable.cpp
34+
${CMAKE_CURRENT_LIST_DIR}/RimcFaultInViewCollection.cpp
3435
${CMAKE_CURRENT_LIST_DIR}/RimcFishbonesCollection.cpp
3536
${CMAKE_CURRENT_LIST_DIR}/RimcPolygonCollection.cpp
3637
${CMAKE_CURRENT_LIST_DIR}/RimcDataFilterCollection.cpp
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (C) 2026- Equinor ASA
4+
//
5+
// ResInsight is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE.
13+
//
14+
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
15+
// for more details.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////
18+
19+
#include "RimcFaultInViewCollection.h"
20+
21+
#include "RimFaultDistanceResult.h"
22+
#include "RimFaultDistanceResultCollection.h"
23+
#include "RimFaultInView.h"
24+
#include "RimFaultInViewCollection.h"
25+
26+
#include "cafPdmAbstractFieldScriptingCapability.h"
27+
#include "cafPdmFieldScriptingCapability.h"
28+
29+
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimFaultInViewCollection, RimcFaultInViewCollection_addFaultDistanceResult, "add_fault_distance_result" );
30+
31+
//--------------------------------------------------------------------------------------------------
32+
///
33+
//--------------------------------------------------------------------------------------------------
34+
RimcFaultInViewCollection_addFaultDistanceResult::RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self )
35+
: caf::PdmObjectCreationMethod( self )
36+
{
37+
CAF_PDM_InitObject( "Add Fault Distance Result", "", "", "Create a FAULTDIST cell result for a chosen subset of faults" );
38+
39+
CAF_PDM_InitScriptableFieldNoDefault( &m_resultName, "Name", "Name (default FAULTDIST<n> if empty)" );
40+
CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "Faults", "Faults to include (empty = all)" );
41+
}
42+
43+
//--------------------------------------------------------------------------------------------------
44+
///
45+
//--------------------------------------------------------------------------------------------------
46+
std::expected<caf::PdmObjectHandle*, QString> RimcFaultInViewCollection_addFaultDistanceResult::execute()
47+
{
48+
auto* hostCollection = self<RimFaultInViewCollection>();
49+
if ( !hostCollection ) return std::unexpected( QString( "No fault collection" ) );
50+
51+
auto* distanceCollection = hostCollection->faultDistanceResults();
52+
if ( !distanceCollection ) return std::unexpected( QString( "No fault distance results collection" ) );
53+
54+
auto* newResult = distanceCollection->addResult();
55+
if ( !newResult ) return std::unexpected( QString( "Failed to create fault distance result" ) );
56+
57+
if ( !m_resultName().isEmpty() ) newResult->setResultName( m_resultName() );
58+
59+
std::vector<RimFaultInView*> selected = m_faults.ptrReferencedObjectsByType();
60+
if ( selected.empty() ) selected = hostCollection->faults();
61+
62+
newResult->setSelectedFaults( selected );
63+
64+
hostCollection->updateConnectedEditors();
65+
distanceCollection->updateConnectedEditors();
66+
67+
return newResult;
68+
}
69+
70+
//--------------------------------------------------------------------------------------------------
71+
///
72+
//--------------------------------------------------------------------------------------------------
73+
QString RimcFaultInViewCollection_addFaultDistanceResult::classKeywordReturnedType() const
74+
{
75+
return RimFaultDistanceResult::classKeywordStatic();
76+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (C) 2026- Equinor ASA
4+
//
5+
// ResInsight is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE.
13+
//
14+
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
15+
// for more details.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////
18+
19+
#pragma once
20+
21+
#include "cafPdmField.h"
22+
#include "cafPdmObjectHandle.h"
23+
#include "cafPdmObjectMethod.h"
24+
#include "cafPdmPtrArrayField.h"
25+
26+
#include <QString>
27+
28+
class RimFaultInView;
29+
30+
//==================================================================================================
31+
///
32+
//==================================================================================================
33+
class RimcFaultInViewCollection_addFaultDistanceResult : public caf::PdmObjectCreationMethod
34+
{
35+
CAF_PDM_HEADER_INIT;
36+
37+
public:
38+
RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self );
39+
40+
std::expected<caf::PdmObjectHandle*, QString> execute() override;
41+
QString classKeywordReturnedType() const override;
42+
43+
private:
44+
caf::PdmField<QString> m_resultName;
45+
caf::PdmPtrArrayField<RimFaultInView*> m_faults;
46+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import math
2+
import os
3+
import sys
4+
5+
sys.path.insert(1, os.path.join(sys.path[0], "../../"))
6+
7+
import dataroot
8+
import rips
9+
10+
11+
GRID_PATH = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
12+
13+
14+
def _get_view(case):
15+
views = case.views()
16+
if views:
17+
return views[0]
18+
return case.create_view()
19+
20+
21+
def test_add_fault_distance_result_subset(rips_instance, initialize_test):
22+
case = rips_instance.project.load_case(GRID_PATH)
23+
view = _get_view(case)
24+
fault_collection = view.fault_collection()
25+
faults = fault_collection.faults()
26+
assert len(faults) > 0
27+
28+
result = fault_collection.add_fault_distance_result("PY_FAULTDIST", faults[:1])
29+
assert result is not None
30+
assert result.result_name == "PY_FAULTDIST"
31+
32+
33+
def test_add_fault_distance_result_all_matches_static(rips_instance, initialize_test):
34+
"""Passing every fault into add_fault_distance_result must reproduce the
35+
static-native FAULTDIST values cell-for-cell."""
36+
case = rips_instance.project.load_case(GRID_PATH)
37+
view = _get_view(case)
38+
fault_collection = view.fault_collection()
39+
all_faults = fault_collection.faults()
40+
assert len(all_faults) > 0
41+
42+
static_values = case.active_cell_property(
43+
rips.PropertyType.STATIC_NATIVE, "FAULTDIST", 0
44+
)
45+
46+
fault_collection.add_fault_distance_result("PY_FAULTDIST_ALL", all_faults)
47+
48+
generated_values = case.active_cell_property(
49+
rips.PropertyType.GENERATED, "PY_FAULTDIST_ALL", 0
50+
)
51+
52+
assert len(static_values) == len(generated_values)
53+
assert len(static_values) > 0
54+
for s, g in zip(static_values, generated_values):
55+
assert math.isclose(s, g, abs_tol=1e-6)

0 commit comments

Comments
 (0)