From 8a1fa384357fac90aa8e11e47e675fb1a3b66cfe Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 19 Feb 2020 15:20:34 +0100 Subject: [PATCH] #4549 Add python method to get selected cells. Equivalent to GetSelectedCells in Octave. --- .../GrpcInterface/GrpcProtos/Case.proto | 13 ++ .../rips/PythonExamples/selected_cells.py | 43 ++++++ .../GrpcInterface/Python/rips/case.py | 21 +++ .../Python/rips/tests/test_cases.py | 5 + .../GrpcInterface/RiaGrpcCaseService.cpp | 140 +++++++++++++++++- .../GrpcInterface/RiaGrpcCaseService.h | 28 ++++ 6 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/GrpcInterface/Python/rips/PythonExamples/selected_cells.py diff --git a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto index deb5454599..61b3acc3bb 100644 --- a/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto +++ b/ApplicationCode/GrpcInterface/GrpcProtos/Case.proto @@ -14,6 +14,7 @@ service Case rpc GetCellCornersForActiveCells(CellInfoRequest) returns (stream CellCornersArray) {} rpc GetCoarseningInfoArray(CaseRequest) returns (CoarseningInfoArray) {} rpc GetTimeSteps(CaseRequest) returns (TimeStepDates) {} + rpc GetSelectedCells(CaseRequest) returns (stream SelectedCells) {} rpc GetDaysSinceStart(CaseRequest) returns (DaysSinceStart) {} rpc GetCaseInfo(CaseRequest) returns (CaseInfo) {} rpc GetPdmObject(CaseRequest) returns (PdmObject) {} @@ -125,3 +126,15 @@ message DaysSinceStart { repeated double day_decimals = 1; } + +message SelectedCell +{ + int32 grid_index = 1; + Vec3i ijk = 2; +} + + +message SelectedCells +{ + repeated SelectedCell cells = 1; +} diff --git a/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/selected_cells.py b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/selected_cells.py new file mode 100644 index 0000000000..57799b74c7 --- /dev/null +++ b/ApplicationCode/GrpcInterface/Python/rips/PythonExamples/selected_cells.py @@ -0,0 +1,43 @@ +############################################################################ +# This example prints center and corners for the currently selected cells +# in ResInsight +############################################################################ + +import rips + +resinsight = rips.Instance.find() +if resinsight is not None: + cases = resinsight.project.cases() + + print ("Got " + str(len(cases)) + " cases: ") + for case in cases: + print(case.name) + cells = case.selected_cells() + print("Found " + str(len(cells)) + " selected cells") + + for cell in cells: + print("Selected cell: [{}, {}, {}] grid: {}".format(cell.ijk.i+1, cell.ijk.j+1, cell.ijk.k+1, cell.grid_index)) + + # Get the grid and dimensions + grid = case.grids()[cell.grid_index] + dimensions = grid.dimensions() + + # Map ijk to cell index + cell_index = dimensions.i * dimensions.j * cell.ijk.k + dimensions.i * cell.ijk.j + cell.ijk.i + + # Print the cell center + cell_centers = grid.cell_centers() + cell_center = cell_centers[cell_index] + print("Cell center: [{}, {}, {}]".format(cell_center.x, cell_center.y, cell_center.z)) + + # Print the cell corners + cell_corners = grid.cell_corners()[cell_index] + print("Cell corners:") + print("c0:\n" + str(cell_corners.c0)) + print("c1:\n" + str(cell_corners.c1)) + print("c2:\n" + str(cell_corners.c2)) + print("c3:\n" + str(cell_corners.c3)) + print("c4:\n" + str(cell_corners.c4)) + print("c5:\n" + str(cell_corners.c5)) + print("c6:\n" + str(cell_corners.c6)) + print("c7:\n" + str(cell_corners.c7)) diff --git a/ApplicationCode/GrpcInterface/Python/rips/case.py b/ApplicationCode/GrpcInterface/Python/rips/case.py index 54e6028607..b011dbfbc8 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/case.py +++ b/ApplicationCode/GrpcInterface/Python/rips/case.py @@ -895,3 +895,24 @@ class Case(PdmObject): for value in chunk.cells: cell_corners.append(value) return cell_corners + + def selected_cells_async(self): + """Get the selected cells. Async, so returns an iterator. + Returns: + An iterator to a chunk object containing an array of cells. + Loop through the chunks and then the cells within the chunk to get all cells. + """ + return self.__case_stub.GetSelectedCells(self.__request) + + def selected_cells(self): + """Get the selected cells. Synchronous, so returns a list. + + Returns: + A list of Cells. + """ + cells = [] + generator = self.selected_cells_async() + for chunk in generator: + for value in chunk.cells: + cells.append(value) + return cells diff --git a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py index 527b171dbb..0ab282eab6 100644 --- a/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py +++ b/ApplicationCode/GrpcInterface/Python/rips/tests/test_cases.py @@ -172,3 +172,8 @@ def test_exportFlowCharacteristics(rips_instance, initialize_test): file_name = tmpdirname + "/exportFlowChar.txt" case.export_flow_characteristics(time_steps=8, producers=[], injectors = "I01", file_name = file_name) +def test_selected_cells(rips_instance, initialize_test): + case = rips_instance.project.load_case(dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID") + assert(case.name == "TEST10K_FLT_LGR_NNC") + selected_cells = case.selected_cells() + assert(len(selected_cells) == 0) diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp index 172fb2e8d6..34f72dd6c6 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.cpp @@ -26,9 +26,9 @@ #include "RigMainGrid.h" #include "RimEclipseCase.h" -#include "RimGeoMechCase.h" +#include "RimEclipseResultDefinition.h" -#include // memcpy +#include "Riu3dSelectionManager.h" using namespace rips; @@ -547,6 +547,135 @@ grpc::Status RiaGrpcCaseService::GetCellCornersForActiveCells( grpc::ServerConte return stateHandler->assignCellCornersReply( reply ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaSelectedCellsStateHandler::RiaSelectedCellsStateHandler() + : m_request( nullptr ) + , m_eclipseCase( nullptr ) + , m_currentItem( 0u ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaSelectedCellsStateHandler::init( const rips::CaseRequest* request ) +{ + CAF_ASSERT( request ); + m_request = request; + + RimCase* rimCase = RiaGrpcServiceInterface::findCase( m_request->id() ); + m_eclipseCase = dynamic_cast( rimCase ); + + if ( !m_eclipseCase ) + { + return grpc::Status( grpc::NOT_FOUND, "Eclipse Case not found" ); + } + + if ( !m_eclipseCase->eclipseCaseData() || !m_eclipseCase->eclipseCaseData()->mainGrid() ) + { + return grpc::Status( grpc::NOT_FOUND, "Eclipse Case Data not found" ); + } + + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Status RiaSelectedCellsStateHandler::assignNextSelectedCell( rips::SelectedCell* cell, + const std::vector& items ) +{ + while ( m_currentItem < items.size() ) + { + size_t itemToTry = m_currentItem++; + + const RiuEclipseSelectionItem* item = items[itemToTry]; + CVF_ASSERT( item->type() == RiuSelectionItem::ECLIPSE_SELECTION_OBJECT ); + assignSelectedCell( cell, item ); + return grpc::Status::OK; + } + return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaSelectedCellsStateHandler::assignSelectedCell( rips::SelectedCell* cell, const RiuEclipseSelectionItem* item ) +{ + CVF_ASSERT( item->type() == RiuSelectionItem::ECLIPSE_SELECTION_OBJECT ); + size_t i = -1; + size_t j = -1; + size_t k = -1; + item->m_resultDefinition->eclipseCase() + ->eclipseCaseData() + ->grid( item->m_gridIndex ) + ->ijkFromCellIndex( item->m_gridLocalCellIndex, &i, &j, &k ); + + cell->set_grid_index( item->m_gridIndex ); + rips::Vec3i* ijk = new rips::Vec3i; + ijk->set_i( (int)i ); + ijk->set_j( (int)j ); + ijk->set_k( (int)k ); + cell->set_allocated_ijk( ijk ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaSelectedCellsStateHandler::assignReply( rips::SelectedCells* reply ) +{ + std::vector items; + Riu3dSelectionManager::instance()->selectedItems( items ); + + // Only eclipse cases are currently supported. Also filter by case. + std::vector eclipseItems; + for ( auto item : items ) + { + RiuEclipseSelectionItem* eclipseItem = dynamic_cast( item ); + if ( eclipseItem && eclipseItem->m_resultDefinition->eclipseCase()->caseId == m_request->id() ) + { + eclipseItems.push_back( eclipseItem ); + } + } + + const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount( sizeof( rips::SelectedCells ) ); + size_t packageIndex = 0u; + reply->mutable_cells()->Reserve( (int)packageSize ); + for ( ; packageIndex < packageSize && m_currentItem < eclipseItems.size(); ++packageIndex ) + { + rips::SelectedCell singleSelectedCell; + grpc::Status singleSelectedCellStatus = assignNextSelectedCell( &singleSelectedCell, eclipseItems ); + if ( singleSelectedCellStatus.ok() ) + { + rips::SelectedCell* allocSelectedCell = reply->add_cells(); + *allocSelectedCell = singleSelectedCell; + } + else + { + break; + } + } + + if ( packageIndex > 0u ) + { + return Status::OK; + } + return Status( grpc::OUT_OF_RANGE, "We've reached the end. This is not an error but means transmission is finished" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcCaseService::GetSelectedCells( grpc::ServerContext* context, + const rips::CaseRequest* request, + rips::SelectedCells* reply, + RiaSelectedCellsStateHandler* stateHandler ) +{ + return stateHandler->assignReply( reply ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -605,6 +734,13 @@ std::vector RiaGrpcCaseService::createCallbacks() &Self::GetCellCornersForActiveCells, &Self::RequestGetCellCornersForActiveCells, new RiaActiveCellInfoStateHandler ), + new RiaGrpcServerToClientStreamCallback( this, + &Self::GetSelectedCells, + &Self::RequestGetSelectedCells, + new RiaSelectedCellsStateHandler ), new RiaGrpcUnaryCallback( this, &Self::GetReservoirBoundingBox, &Self::RequestGetReservoirBoundingBox )}; diff --git a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h index 11b45515a8..51416ac0dd 100644 --- a/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h +++ b/ApplicationCode/GrpcInterface/RiaGrpcCaseService.h @@ -34,6 +34,7 @@ class RiaGrpcCallbackInterface; class RigCell; class RigActiveCellInfo; class RimEclipseCase; +class RiuEclipseSelectionItem; //================================================================================================== // @@ -76,6 +77,29 @@ protected: size_t m_currentCellIdx; }; +//================================================================================================== +// +// State handler for streaming of selected cells +// +//================================================================================================== +class RiaSelectedCellsStateHandler +{ + typedef grpc::Status Status; + +public: + RiaSelectedCellsStateHandler(); + + Status init( const rips::CaseRequest* request ); + Status assignReply( rips::SelectedCells* reply ); + void assignSelectedCell( rips::SelectedCell* cell, const RiuEclipseSelectionItem* item ); + Status assignNextSelectedCell( rips::SelectedCell* cell, const std::vector& items ); + +protected: + const rips::CaseRequest* m_request; + RimEclipseCase* m_eclipseCase; + size_t m_currentItem; +}; + //================================================================================================== // // gRPC-service answering requests about grid information for a given case @@ -110,6 +134,10 @@ public: const rips::CellInfoRequest* request, rips::CellCornersArray* reply, RiaActiveCellInfoStateHandler* stateHandler ); + grpc::Status GetSelectedCells( grpc::ServerContext* context, + const rips::CaseRequest* request, + rips::SelectedCells* reply, + RiaSelectedCellsStateHandler* stateHandler ); grpc::Status GetReservoirBoundingBox( grpc::ServerContext* context, const rips::CaseRequest* request, rips::BoundingBox* reply );