#4817 #4830 #4832 #4837 #4839 Python commands for WBS creation, well path import and well log file import (#4838)

* Better minimum width for well log tracks

* Fix alignment of scrollbar in Well log plots

* Better Well Log Plot export

* Hide scroll bar before plotting
* Better borders

* Create plots through Python

* #4817 Create WBS plots with Python

* Rebase Summary and WellLogPlot on top of a new RimPlot

* Also Python: Allow setting folder as a parameter to export_snapshots

* #4832 Prepare for well path import command

* Well Path import WIP

* #4830 #4832 Import well paths and well log files from file using Python.

* #4837 Implement import of formation names in Python

* Fix debug build issue

* Fix RiaLogging build issue

* Fix warnings

* Yet another RiaLogging.h import added

* #4839 Import exporting of las and ascii files from well log plots
This commit is contained in:
Gaute Lindkvist
2019-10-09 09:21:28 +02:00
committed by GitHub
parent b24b0932a3
commit 11117383db
106 changed files with 2128 additions and 339 deletions

View File

@@ -14,7 +14,9 @@ if resinsight is not None:
print ("Got " + str(len(cases)) + " cases: ")
for case in cases:
print("Case id: " + str(case.case_id))
print("Case name: " + case.name)
print("Case type: " + case.type)
print("Case grid path: " + case.grid_path())
timesteps = case.time_steps()

View File

@@ -0,0 +1,30 @@
import os
# Load ResInsight Processing Server Client Library
import rips
# Connect to ResInsight instance
resInsight = rips.Instance.find()
cases = resInsight.project.cases()
well_paths = resInsight.project.import_well_paths(well_path_folder='D:/Projects/ResInsight-regression-test/ModelData/Norne_LessWellPaths')
well_log_files = resInsight.project.import_well_log_files(well_log_folder='D:/Projects/ResInsight-regression-test/ModelData/Norne_PLT_LAS')
if len(well_paths) < 1:
print("No well paths in project")
exit(1)
print(well_paths)
for case in cases:
if case.type == "GeoMechCase":
print (case.case_id)
case_path = case.grid_path()
folder_name = os.path.dirname(case_path)
case.import_formation_names(formation_files=['D:/Projects/ResInsight-regression-test/ModelData/norne/Norne_ATW2013.lyr'])
# create a folder to hold the snapshots
dirname = os.path.join(folder_name, 'snapshots')
print("Exporting to: " + dirname)
for well_path in well_paths:
wbsplot = case.create_well_bore_stability_plot(well_path=well_path, time_step=0)
wbsplot.export_snapshot(export_folder=dirname)

View File

@@ -5,6 +5,7 @@
import rips
import grpc
import tempfile
resinsight = rips.Instance.find()
@@ -14,7 +15,25 @@ case = None
try:
case = resinsight.project.load_case("Nonsense")
except grpc.RpcError as e:
print("Expected Server Exception Received: ", e)
print("Expected Server Exception Received while loading case: ", e)
# Try loading well paths from a non-existing folder. We should get a grpc.RpcError exception from the server
try:
well_path_files = resinsight.project.import_well_paths(well_path_folder="NONSENSE/NONSENSE")
except grpc.RpcError as e:
print("Expected Server Exception Received while loading wellpaths: ", e)
# Try loading well paths from an existing but empty folder. We should get a warning.
try:
with tempfile.TemporaryDirectory() as tmpdirname:
well_path_files = resinsight.project.import_well_paths(well_path_folder=tmpdirname)
assert(len(well_path_files) == 0)
assert(resinsight.project.has_warnings())
print("Should get warnings below")
for warning in resinsight.project.warnings():
print (warning)
except grpc.RpcError as e:
print("Unexpected Server Exception caught!!!", e)
case = resinsight.project.case(case_id=0)
if case is not None:
@@ -53,5 +72,5 @@ if case is not None:
except IndexError:
print ("Got expected index out of bounds error on client side")

View File

@@ -0,0 +1,18 @@
# Import the tempfile module
import tempfile
# Load ResInsight Processing Server Client Library
import rips
# Connect to ResInsight instance
resInsight = rips.Instance.find()
# Get a list of all plots
plots = resInsight.project.plots()
export_folder = tempfile.mkdtemp()
print("Exporting to: " + export_folder)
for plot in plots:
plot.export_snapshot(export_folder=export_folder)
plot.export_data_as_las(export_folder=export_folder)
plot.export_data_as_ascii(export_folder=export_folder)

View File

@@ -0,0 +1,32 @@
# Load ResInsight Processing Server Client Library
import rips
# Connect to ResInsight instance
resInsight = rips.Instance.find()
well_path_names = resInsight.project.import_well_paths(well_path_folder='D:/Projects/ResInsight-regression-test/ModelData/norne/wellpaths')
if resInsight.project.has_warnings():
for warning in resInsight.project.warnings():
print(warning)
for well_path_name in well_path_names:
print("Imported from folder: " + well_path_name)
well_path_names = resInsight.project.import_well_paths(well_path_files=['D:/Projects/ResInsight-regression-test/ModelData/Norne_WellPaths/E-3H.json',
'D:/Projects/ResInsight-regression-test/ModelData/Norne_WellPaths/C-1H.json'])
if resInsight.project.has_warnings():
for warning in resInsight.project.warnings():
print(warning)
for well_path_name in well_path_names:
print("Imported from indivdual files: " + well_path_name)
well_path_names = resInsight.project.import_well_log_files(well_log_folder='D:/Projects/ResInsight-regression-test/ModelData/Norne_PLT_LAS')
if resInsight.project.has_warnings():
for warning in resInsight.project.warnings():
print(warning)
for well_path_name in well_path_names:
print("Imported well log file for: " + well_path_name)

View File

@@ -9,4 +9,5 @@ from rips.grid import Grid
from rips.instance import Instance
from rips.pdmobject import PdmObject
from rips.view import View
from rips.project import Project
from rips.project import Project
from rips.plot import Plot

View File

@@ -25,7 +25,7 @@ class Case(PdmObject):
Operate on a ResInsight case specified by a Case Id integer.
Not meant to be constructed separately but created by one of the following
methods in Project: loadCase, case, allCases, selectedCasesq
methods in Project: loadCase, case, allCases, selectedCases
Attributes:
id (int): Case Id corresponding to case Id in ResInsight project.
@@ -37,11 +37,12 @@ class Case(PdmObject):
However we need overhead space, so the default is 8160.
This leaves 256B for overhead.
"""
def __init__(self, channel, case_id):
def __init__(self, channel, case_id, project):
# Private properties
self.__channel = channel
self.__case_stub = Case_pb2_grpc.CaseStub(channel)
self.__request = Case_pb2.CaseRequest(id=case_id)
self.__project = project
info = self.__case_stub.GetCaseInfo(self.__request)
self.__properties_stub = Properties_pb2_grpc.PropertiesStub(
@@ -51,7 +52,9 @@ class Case(PdmObject):
# Public properties
self.case_id = case_id
self.group_id = info.group_id
self.name = info.name
self.type = info.type
self.chunk_size = 8160
def __grid_count(self):
@@ -248,16 +251,17 @@ class Case(PdmObject):
self._execute_command(createView=Cmd.CreateViewRequest(
caseId=self.case_id)).createViewResult.viewId)
def export_snapshots_of_all_views(self, prefix=""):
def export_snapshots_of_all_views(self, prefix="", export_folder=""):
""" Export snapshots for all views in the case
Arguments:
prefix (str): Exported file name prefix
export_folder(str): The path to export to. By default will use the global export folder
"""
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(
type="VIEWS", prefix=prefix, caseId=self.case_id, viewId=-1))
type="VIEWS", prefix=prefix, caseId=self.case_id, viewId=-1, exportFolder=export_folder))
def export_well_path_completions(
self,
@@ -732,3 +736,33 @@ class Case(PdmObject):
undefinedValue=undefined_value,
exportFile=export_file,
))
def create_well_bore_stability_plot(self, well_path, time_step):
""" Create a new well bore stability plot
Arguments:
well_path(str): well path name
time_step(int): time step
Returns:
A new plot object
"""
plot_result = self._execute_command(createWellBoreStabilityPlot=Cmd.CreateWbsPlotRequest(caseId=self.case_id,
wellPath=well_path,
timeStep=time_step))
return self.__project.plot(view_id=plot_result.createWbsPlotResult.viewId)
def import_formation_names(self, formation_files=None):
""" Import formation names into project and apply it to the current case
Arguments:
formation_files(list): list of files to import
"""
if formation_files is None:
formation_files = []
elif isinstance(formation_files, str):
formation_files = [formation_files]
res = self._execute_command(importFormationNames=Cmd.ImportFormationNamesRequest(formationFiles=formation_files,
applyToCaseId=self.case_id))

View File

@@ -14,14 +14,27 @@ class PdmObject:
"""
def _execute_command(self, **command_params):
return self._commands.Execute(Cmd.CommandParams(**command_params))
self.__warnings = []
response, call = self._commands.Execute.with_call(Cmd.CommandParams(**command_params))
for key, value in call.trailing_metadata():
value = value.replace(';;', '\n')
if key == 'warning':
self.__warnings.append(value)
return response
def __init__(self, pb2_object, channel):
self._pb2_object = pb2_object
self._channel = channel
self._pdm_object_stub = PdmObject_pb2_grpc.PdmObjectServiceStub(
self._channel)
self._pdm_object_stub = PdmObject_pb2_grpc.PdmObjectServiceStub(self._channel)
self._commands = CmdRpc.CommandsStub(channel)
self.__warnings = []
def warnings(self):
return self.__warnings
def has_warnings(self):
return len(self.__warnings) > 0
def pb2_object(self):
""" Private method"""

View File

@@ -0,0 +1,73 @@
"""
ResInsight 2d plot module
"""
import rips.generated.Commands_pb2 as Cmd
from rips.pdmobject import PdmObject
class Plot(PdmObject):
"""ResInsight plot class
Attributes:
view_id(int): View Id corresponding to the View Id in ResInsight project.
"""
def __init__(self, pdm_object):
PdmObject.__init__(self, pdm_object.pb2_object(), pdm_object.channel())
self.view_id = pdm_object.get_value("ViewId")
def export_snapshot(self, export_folder='', file_prefix='', ):
""" Export snapshot for the current plot
Arguments:
export_folder(str): The path to export to. By default will use the global export folder
prefix (str): Exported file name prefix
"""
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(type='PLOTS',
prefix=file_prefix,
viewId=self.view_id,
exportFolder=export_folder))
def export_data_as_las(self, export_folder, file_prefix='', export_tvdrkb=False, capitalize_file_names=False, resample_interval=0.0):
""" Export LAS file(s) for the current plot
Arguments:
export_folder(str): The path to export to. By default will use the global export folder
file_prefix (str): Exported file name prefix
export_tvdrkb(bool): Export in TVD-RKB format
capitalize_file_names(bool): Make all file names upper case
resample_interval(double): if > 0.0 the files will be resampled
Returns:
A list of files exported
"""
res = self._execute_command(exportWellLogPlotData=Cmd.ExportWellLogPlotDataRequest(exportFormat='LAS',
viewId=self.view_id,
exportFolder=export_folder,
filePrefix=file_prefix,
exportTvdRkb=export_tvdrkb,
capitalizeFileNames=capitalize_file_names,
resampleInterval=resample_interval))
return res.exportWellLogPlotDataResult.exportedFiles
def export_data_as_ascii(self, export_folder, file_prefix='', capitalize_file_names=False):
""" Export LAS file(s) for the current plot
Arguments:
export_folder(str): The path to export to. By default will use the global export folder
file_prefix (str): Exported file name prefix
capitalize_file_names(bool): Make all file names upper case
Returns:
A list of files exported
"""
res = self._execute_command(exportWellLogPlotData=Cmd.ExportWellLogPlotDataRequest(exportFormat='ASCII',
viewId=self.view_id,
exportFolder=export_folder,
filePrefix=file_prefix,
exportTvdRkb=False,
capitalizeFileNames=capitalize_file_names,
resampleInterval=0.0))
return res.exportWellLogPlotDataResult.exportedFiles

View File

@@ -8,6 +8,7 @@ import grpc
from rips.case import Case
from rips.gridcasegroup import GridCaseGroup
from rips.pdmobject import PdmObject
from rips.plot import Plot
from rips.view import View
import rips.generated.Commands_pb2 as Cmd
@@ -49,7 +50,7 @@ class Project(PdmObject):
"""
command_reply = self._execute_command(loadCase=Cmd.FilePathRequest(
path=path))
return Case(self._channel, command_reply.loadCaseResult.id)
return Case(self._channel, command_reply.loadCaseResult.id, self)
def selected_cases(self):
"""Get a list of all cases selected in the project tree
@@ -60,7 +61,7 @@ class Project(PdmObject):
case_infos = self._project_stub.GetSelectedCases(Empty())
cases = []
for case_info in case_infos.data:
cases.append(Case(self._channel, case_info.id))
cases.append(Case(self._channel, case_info.id, self))
return cases
def cases(self):
@@ -74,7 +75,7 @@ class Project(PdmObject):
cases = []
for case_info in case_infos.data:
cases.append(Case(self._channel, case_info.id))
cases.append(Case(self._channel, case_info.id, self))
return cases
except grpc.RpcError as rpc_error:
if rpc_error.code() == grpc.StatusCode.NOT_FOUND:
@@ -91,7 +92,7 @@ class Project(PdmObject):
A rips Case object
"""
try:
case = Case(self._channel, case_id)
case = Case(self._channel, case_id, self)
return case
except grpc.RpcError:
return None
@@ -133,7 +134,7 @@ class Project(PdmObject):
"""Get a particular view belonging to a case by providing view id
Arguments:
id(int): view id
view_id(int): view id
Returns: a view object
"""
views = self.views()
@@ -142,6 +143,34 @@ class Project(PdmObject):
return view_object
return None
def plots(self):
"""Get a list of all plots belonging to a project"""
pdm_objects = self.descendants("RimPlot")
plot_list = []
for pdm_object in pdm_objects:
plot_list.append(Plot(pdm_object))
return plot_list
def plot(self, view_id):
"""Get a particular plot by providing view id
Arguments:
view_id(int): view id
Returns: a plot object
"""
plots = self.plots()
for plot_object in plots:
if plot_object.view_id == view_id:
return plot_object
return None
def well_paths(self):
"""Get a list of all the well path names in the project"""
pdm_objects = self.descendants("WellPathBase")
well_path_list = []
for pdm_object in pdm_objects:
well_path_list.append(pdm_object.get_value("WellPathName"))
return well_path_list
def grid_case_groups(self):
"""Get a list of all grid case groups in the project"""
case_groups = self.descendants("RimIdenticalGridCaseGroup")
@@ -230,3 +259,52 @@ class Project(PdmObject):
return self._execute_command(
setFractureContainment=Cmd.SetFracContainmentRequest(
id=template_id, topLayer=top_layer, baseLayer=base_layer))
def import_well_paths(self, well_path_files=None, well_path_folder=''):
""" Import well paths into project
Arguments:
well_path_files(list): List of file paths to import
well_path_folder(str): A folder path containing files to import
Returns:
A list of well path names (strings)
"""
if well_path_files is None:
well_path_files = []
res = self._execute_command(importWellPaths=Cmd.ImportWellPathsRequest(wellPathFolder=well_path_folder,
wellPathFiles=well_path_files))
return res.importWellPathsResult.wellPathNames
def import_well_log_files(self, well_log_files=None, well_log_folder=''):
""" Import well log files into project
Arguments:
well_log_files(list): List of file paths to import
well_log_folder(str): A folder path containing files to import
Returns:
A list of well path names (strings) that had logs imported
"""
if well_log_files is None:
well_log_files = []
res = self._execute_command(importWellLogFiles=Cmd.ImportWellLogFilesRequest(wellLogFolder=well_log_folder,
wellLogFiles=well_log_files))
return res.importWellLogFilesResult.wellPathNames
def import_formation_names(self, formation_files=None):
""" Import formation names into project
Arguments:
formation_files(list): list of files to import
"""
if formation_files is None:
formation_files = []
elif isinstance(formation_files, str):
formation_files = [formation_files]
res = self._execute_command(importFormationNames=Cmd.ImportFormationNamesRequest(formationFiles=formation_files,
applyToCaseId=-1))

View File

@@ -11,7 +11,7 @@ class View(PdmObject):
"""ResInsight view class
Attributes:
id(int): View Id corresponding to the View Id in ResInsight project.
view_id(int): View Id corresponding to the View Id in ResInsight project.
"""
def __init__(self, pdm_object):
@@ -195,15 +195,17 @@ class View(PdmObject):
viewIds=[self.view_id],
undefinedValue=undefined_value))
def export_snapshot(self, prefix=''):
def export_snapshot(self, prefix='', export_folder=''):
""" Export snapshot for the current view
Arguments:
prefix (str): Exported file name prefix
export_folder(str): The path to export to. By default will use the global export folder
"""
case_id = self.case().case_id
return self._execute_command(
exportSnapshots=Cmd.ExportSnapshotsRequest(type='VIEWS',
prefix=prefix,
caseId=case_id,
viewId=self.view_id))
viewId=self.view_id,
exportFolder=export_folder))