#13806 Python: Add API for creating discrete grid properties

Add a data_type parameter to set_active_cell_property, set_active_cell_property_async
and set_grid_property so callers can upload INTEGER-typed discrete properties in
addition to the existing FLOAT properties. Previously a discrete property required
the result name to end with "NUM"; the explicit data type makes the intent
independent of the name.

The gRPC service now forwards the selected data type to
RigCaseCellResultsData::createCategoryResult, and the Python tests cover both
float and integer property uploads.
This commit is contained in:
Magne Sjaastad committed 2026-04-20 18:55:36 +02:00
1 parent bd3836ba25
commit 75c1cedaec
6 files changed
+78

No files matched your search

@@ -30,6 +30,11 @@ enum PropertyType {
UNDEFINED = 999;
}
enum PropertyDataType {
FLOAT = 0;
INTEGER = 1;
}
message AvailablePropertiesRequest {
CaseRequest case_request = 1;
PropertyType property_type = 2;
@@ -45,6 +50,7 @@ message PropertyRequest {
int32 time_step = 4;
int32 grid_index = 5;
PorosityModelType porosity_model = 6;
PropertyDataType data_type = 7;
}
message TimeStep { int32 index = 1; }
+12
View File
@@ -830,6 +830,7 @@ def set_active_cell_property_async(
property_name,
time_step,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
):
"""Set cell property for all active cells Async. Takes an iterator to the input values. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -839,15 +840,18 @@ def set_active_cell_property_async(
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum
data_type(str): property data type ("FLOAT" or "INTEGER"). Use "INTEGER" to create a discrete/category property.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
data_type_enum = Properties_pb2.PropertyDataType.Value(data_type)
request = Properties_pb2.PropertyRequest(
case_request=self.__request(),
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
porosity_model=porosity_model_enum,
data_type=data_type_enum,
)
request_iterator = self.__generate_property_input_iterator(values_iterator, request)
@@ -862,6 +866,7 @@ def set_active_cell_property(
property_name,
time_step,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
):
"""Set a cell property for all active cells. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -871,15 +876,18 @@ def set_active_cell_property(
property_name(str): name of an Eclipse property
time_step(int): the time step for which to get the property for
porosity_model(str): string enum
data_type(str): property data type ("FLOAT" or "INTEGER"). Use "INTEGER" to create a discrete/category property.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
data_type_enum = Properties_pb2.PropertyDataType.Value(data_type)
request = Properties_pb2.PropertyRequest(
case_request=self.__request(),
property_type=property_type_enum,
property_name=property_name,
time_step=time_step,
porosity_model=porosity_model_enum,
data_type=data_type_enum,
)
request_iterator = self.__generate_property_input_chunks(values, request)
reply = self.__properties_stub.SetActiveCellProperty(request_iterator)
@@ -896,6 +904,7 @@ def set_grid_property(
time_step,
grid_index=0,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
):
"""Set a cell property for all grid cells. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -906,9 +915,11 @@ def set_grid_property(
time_step(int): the time step for which to get the property for
grid_index(int): index to the grid we're setting values for
porosity_model(str): string enum
data_type(str): property data type ("FLOAT" or "INTEGER"). Use "INTEGER" to create a discrete/category property.
"""
property_type_enum = Properties_pb2.PropertyType.Value(property_type)
porosity_model_enum = Case_pb2.PorosityModelType.Value(porosity_model)
data_type_enum = Properties_pb2.PropertyDataType.Value(data_type)
request = Properties_pb2.PropertyRequest(
case_request=self.__request(),
property_type=property_type_enum,
@@ -916,6 +927,7 @@ def set_grid_property(
time_step=time_step,
grid_index=grid_index,
porosity_model=porosity_model_enum,
data_type=data_type_enum,
)
request_iterator = self.__generate_property_input_chunks(values, request)
reply = self.__properties_stub.SetGridProperty(request_iterator)
@@ -98,6 +98,43 @@ def test_10k_PoroPermX(rips_instance, initialize_test):
checkResults(poro, permx, poroPermX)
def test_10k_set_integer_active_cell_property(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
integer_values = [int(v * 100) for v in results]
# A name that does not end with "NUM" - only the data_type flag should
# cause this to be treated as a discrete/category property.
case.set_active_cell_property(
integer_values, "GENERATED", "MY_DISCRETE_ACTIVE", 0, data_type="INTEGER"
)
round_trip = case.active_cell_property("GENERATED", "MY_DISCRETE_ACTIVE", 0)
assert len(round_trip) == len(integer_values)
for expected, actual in zip(integer_values, round_trip):
assert expected == int(actual)
def test_10k_set_integer_grid_property(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
grid = case.grid()
grid_cell_count = grid.cell_count()
integer_values = [i % 4 for i in range(grid_cell_count)]
case.set_grid_property(
integer_values, "GENERATED", "MY_DISCRETE_GRID", 0, data_type="INTEGER"
)
round_trip = case.grid_property("GENERATED", "MY_DISCRETE_GRID", 0)
assert len(round_trip) == len(integer_values)
for expected, actual in zip(integer_values, round_trip):
assert expected == int(actual)
def test_exportPropertyInView(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(case_path)
@@ -104,10 +104,18 @@ public:
m_resultAddress = RigEclipseResultAddress( resultType, QString::fromStdString( request->property_name() ) );
auto dataType = ( request->data_type() == rips::PropertyDataType::INTEGER )
? RiaDefines::ResultDataType::INTEGER
: RiaDefines::ResultDataType::FLOAT;
m_resultAddress.setDataType( dataType );
if ( resultData->ensureKnownResultLoaded( m_resultAddress ) )
{
if ( timeStep < resultData->timeStepCount( m_resultAddress ) )
{
// Equality on RigEclipseResultAddress ignores dataType, so an existing entry
// keeps its original dataType. Patch it when overwriting from the client.
if ( m_clientStreamer ) resultData->updateResultDataType( m_resultAddress, dataType );
initResultAccess( caseData, request->grid_index(), m_porosityModel, timeStep, m_resultAddress );
return grpc::Status::OK;
}