Python: create PyDoc type docs, fix some inconsistencies in code and update rips module version

This commit is contained in:
Gaute Lindkvist 2019-06-11 15:15:26 +02:00
parent 8f6858932b
commit fe268cd25f
8 changed files with 268 additions and 56 deletions

View File

@ -10,22 +10,33 @@ import App_pb2
import App_pb2_grpc import App_pb2_grpc
class App: class App:
"""ResInsight application information and control.
Allows retrieving of information and controlling the running instance
Not meant to be constructed manually, but exists as part of the Instance method
"""
def __init__(self, channel): def __init__(self, channel):
self.app = App_pb2_grpc.AppStub(channel) self.app = App_pb2_grpc.AppStub(channel)
def versionMessage(self): def __versionMessage(self):
return self.app.GetVersion(Empty()) return self.app.GetVersion(Empty())
def majorVersion(self): def majorVersion(self):
return self.versionMessage().major_version """Get an integer with the major version number"""
return self.__versionMessage().major_version
def minorVersion(self): def minorVersion(self):
return self.versionMessage().minor_version """Get an integer with the minor version number"""
return self.__versionMessage().minor_version
def patchVersion(self): def patchVersion(self):
return self.versionMessage().patch_version """Get an integer with the patch version number"""
return self.__versionMessage().patch_version
def versionString(self): def versionString(self):
"""Get a full version string, i.e. 2019.04.01"""
return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion()) return str(self.majorVersion()) + "." + str(self.minorVersion()) + "." + str(self.patchVersion())
def exit(self): def exit(self):
"""Tell ResInsight instance to quit"""
print("Telling ResInsight to Exit") print("Telling ResInsight to Exit")
return self.app.Exit(Empty()) return self.app.Exit(Empty())
def isConsole(self): def isConsole(self):
"""Returns true if the connected ResInsight instance is a console app"""
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION') return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION')
def isGui(self): def isGui(self):
"""Returns true if the connected ResInsight instance is a GUI app"""
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION') return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION')

View File

@ -10,6 +10,17 @@ import Case_pb2
import Case_pb2_grpc import Case_pb2_grpc
class Case: class Case:
"""ResInsight case class
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, selectedCases
Attributes:
id(int): Case Id corresponding to case Id in ResInsight project.
name(string): Case name
groupId(int): Case Group id
"""
def __init__(self, channel, id): def __init__(self, channel, id):
self.channel = channel self.channel = channel
self.stub = Case_pb2_grpc.CaseStub(channel) self.stub = Case_pb2_grpc.CaseStub(channel)
@ -21,8 +32,8 @@ class Case:
self.properties = Properties(self) self.properties = Properties(self)
self.request = Case_pb2.CaseRequest(id=self.id) self.request = Case_pb2.CaseRequest(id=self.id)
# Get number of grids in the case
def gridCount(self): def gridCount(self):
"""Get number of grids in the case"""
try: try:
return self.stub.GetGridCount(self.request).count return self.stub.GetGridCount(self.request).count
except grpc.RpcError as e: except grpc.RpcError as e:
@ -31,32 +42,57 @@ class Case:
print("ERROR: ", e) print("ERROR: ", e)
return 0 return 0
# Get Grid of a given index. Returns a rips Grid object
def grid(self, index): def grid(self, index):
"""Get Grid of a given index. Returns a rips Grid object"""
return Grid(index, self) return Grid(index, self)
# Get a list of all rips Grid objects in the case
def grids(self): def grids(self):
"""Get a list of all rips Grid objects in the case"""
gridList = [] gridList = []
for i in range(0, self.gridCount()): for i in range(0, self.gridCount()):
gridList.append(Grid(i, self)) gridList.append(Grid(i, self))
return gridList return gridList
def cellCount(self, porosityModel='MATRIX_MODEL'): def cellCount(self, porosityModel='MATRIX_MODEL'):
"""Get a cell count object containing number of active cells and
total number of cells
Arguments:
porosityModel(string): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Cell Count object with the following integer attributes:
active_cell_count: number of active cells
reservoir_cell_count: total number of reservoir cells
"""
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Case_pb2.CellInfoRequest(case_request=self.request, request = Case_pb2.CellInfoRequest(case_request=self.request,
porosity_model=porosityModel) porosity_model=porosityModel)
return self.stub.GetCellCount(request) return self.stub.GetCellCount(request)
def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'): def cellInfoForActiveCells(self, porosityModel='MATRIX_MODEL'):
"""Get Stream of cell info objects for current case
Arguments:
porosityModel(string): String representing an enum.
must be 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
Returns:
Stream of cell info objects with the following attributes:
grid_index(int): grid the cell belongs to
parent_grid_index(int): parent of the grid the cell belongs to
coarsening_box_index(int): the coarsening box index
local_ijk(Vec3i: i(int), j(int), k(int)): local cell index in i, j, k directions.
parent_ijk(Vec3i: i(int), j(int), k(int)): cell index in parent grid in i, j, k.
"""
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Case_pb2.CellInfoRequest(case_request=self.request, request = Case_pb2.CellInfoRequest(case_request=self.request,
porosity_model=porosityModel) porosity_model=porosityModel)
return self.stub.GetCellInfoForActiveCells(request) return self.stub.GetCellInfoForActiveCells(request)
def timeSteps(self): def timeSteps(self):
"""Get a list containing time step strings for all time steps"""
return self.stub.GetTimeSteps(self.request).dates return self.stub.GetTimeSteps(self.request).dates
def daysSinceStart(self): def daysSinceStart(self):
"""Get a list of decimal values representing days since the start of the simulation"""
return self.stub.GetDaysSinceStart(self.request).day_decimals return self.stub.GetDaysSinceStart(self.request).day_decimals

View File

@ -10,11 +10,20 @@ import Commands_pb2_grpc as CmdRpc
from .Case import Case from .Case import Case
class Commands: class Commands:
"""Command executor which can run ResInsight Command File commands nearly verbatim
Documentation Command File Interface:
https://resinsight.org/docs/commandfile/
The differences are:
1. Enum values have to be provided as strings. I.e. "ALL" instead of ALL.
2. Booleans have to be specified as correct Python. True instead of true.
"""
def __init__(self, channel): def __init__(self, channel):
self.channel = channel self.channel = channel
self.commands = CmdRpc.CommandsStub(channel) self.commands = CmdRpc.CommandsStub(channel)
def execute(self, **commandParams): def __execute(self, **commandParams):
try: try:
return self.commands.Execute(Cmd.CommandParams(**commandParams)) return self.commands.Execute(Cmd.CommandParams(**commandParams))
except grpc.RpcError as e: except grpc.RpcError as e:
@ -28,39 +37,39 @@ class Commands:
######################## ########################
def openProject(self, path): def openProject(self, path):
return self.execute(openProject=Cmd.FilePathRequest(path=path)) return self.__execute(openProject=Cmd.FilePathRequest(path=path))
def closeProject(self): def closeProject(self):
return self.execute(closeProject=Empty()) return self.__execute(closeProject=Empty())
def setStartDir(self, path): def setStartDir(self, path):
return self.execute(setStartDir=Cmd.FilePathRequest(path=path)) return self.__execute(setStartDir=Cmd.FilePathRequest(path=path))
def loadCase(self, path): def loadCase(self, path):
commandReply = self.execute(loadCase=Cmd.FilePathRequest(path=path)) commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path))
assert commandReply.HasField("loadCaseResult") assert commandReply.HasField("loadCaseResult")
return Case(self.channel, commandReply.loadCaseResult.id) return Case(self.channel, commandReply.loadCaseResult.id)
def replaceCase(self, path, caseId=0): def replaceCase(self, path, caseId=0):
return self.execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path, return self.__execute(replaceCase=Cmd.ReplaceCaseRequest(newGridFile=path,
caseId=caseId)) caseId=caseId))
def replaceSourceCases(self, gridListFile, caseGroupId=0): def replaceSourceCases(self, gridListFile, caseGroupId=0):
return self.execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile, return self.__execute(replaceSourceCases=Cmd.ReplaceSourceCasesRequest(gridListFile=gridListFile,
caseGroupId=caseGroupId)) caseGroupId=caseGroupId))
################## ##################
# Export Commands # Export Commands
################## ##################
def exportMultiCaseSnapshots(self, gridListFile): def exportMultiCaseSnapshots(self, gridListFile):
return self.execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile)) return self.__execute(exportMultiCaseSnapshot=Cmd.ExportMultiCaseRequest(gridListFile=gridListFile))
def exportSnapshots(self, type = 'ALL', prefix=''): def exportSnapshots(self, type = 'ALL', prefix=''):
return self.execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type, return self.__execute(exportSnapshots=Cmd.ExportSnapshotsRequest(type=type,
prefix=prefix)) prefix=prefix))
def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property): def exportProperty(self, caseId, timeStep, property, eclipseKeyword=property, undefinedValue=0.0, exportFile=property):
return self.execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId, return self.__execute(exportProperty=Cmd.ExportPropertyRequest(caseId=caseId,
timeStep=timeStep, timeStep=timeStep,
property=property, property=property,
eclipseKeyword=eclipseKeyword, eclipseKeyword=eclipseKeyword,
@ -71,7 +80,7 @@ class Commands:
if isinstance(viewNames, str): if isinstance(viewNames, str):
viewNames = [viewNames] viewNames = [viewNames]
return self.execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=caseId, return self.__execute(exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(caseId=caseId,
viewNames=viewNames, viewNames=viewNames,
undefinedValue=undefinedValue)) undefinedValue=undefinedValue))
@ -80,7 +89,7 @@ class Commands:
excludeMainBoreForFishbones, combinationMode): excludeMainBoreForFishbones, combinationMode):
if (isinstance(wellPathNames, str)): if (isinstance(wellPathNames, str)):
wellPathNames = [wellPathNames] wellPathNames = [wellPathNames]
return self.execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=caseId, return self.__execute(exportWellPathCompletions=Cmd.ExportWellPathCompRequest(caseId=caseId,
timeStep=timeStep, timeStep=timeStep,
wellPathNames=wellPathNames, wellPathNames=wellPathNames,
fileSplit=fileSplit, fileSplit=fileSplit,
@ -93,7 +102,7 @@ class Commands:
def exportSimWellFractureCompletions(self, caseId, viewName, timeStep, simulationWellNames, fileSplit, compdatExport): def exportSimWellFractureCompletions(self, caseId, viewName, timeStep, simulationWellNames, fileSplit, compdatExport):
if(isinstance(simulationWellNames, str)): if(isinstance(simulationWellNames, str)):
simulationWellNames = [simulationWellNames] simulationWellNames = [simulationWellNames]
return self.execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=caseId, return self.__execute(exportSimWellFractureCompletions=Cmd.ExportSimWellPathFraqRequest(caseId=caseId,
viewName=viewName, viewName=viewName,
timeStep=timeStep, timeStep=timeStep,
simulationWellNames=simulationWellNames, simulationWellNames=simulationWellNames,
@ -101,23 +110,23 @@ class Commands:
compdatExport=compdatExport)) compdatExport=compdatExport))
def exportMsw(self, caseId, wellPath): def exportMsw(self, caseId, wellPath):
return self.execute(exportMsw=Cmd.ExportMswRequest(caseId=caseId, return self.__execute(exportMsw=Cmd.ExportMswRequest(caseId=caseId,
wellPath=wellPath)) wellPath=wellPath))
def exportWellPaths(self, wellPaths=[], mdStepSize=5.0): def exportWellPaths(self, wellPaths=[], mdStepSize=5.0):
if isinstance(wellPaths, str): if isinstance(wellPaths, str):
wellPaths = [wellpaths] wellPaths = [wellpaths]
return self.execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize)) return self.__execute(exportWellPaths=Cmd.ExportWellPathRequest(wellPathNames=wellPaths, mdStepSize=mdStepSize))
def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0): def exportVisibleCells(self, caseId, viewName, exportKeyword='FLUXNUM', visibleActiveCellsValue=1, hiddenActiveCellsValue=0, inactiveCellsValue=0):
return self.execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId, return self.__execute(exportVisibleCells=Cmd.ExportVisibleCellsRequest(caseId=caseId,
viewName=viewName, viewName=viewName,
exportKeyword=exportKeyword, exportKeyword=exportKeyword,
visibleActiveCellsValue=visibleActiveCellsValue, visibleActiveCellsValue=visibleActiveCellsValue,
hiddenActiveCellsValue=hiddenActiveCellsValue, hiddenActiveCellsValue=hiddenActiveCellsValue,
inactiveCellsValue=inactiveCellsValue)) inactiveCellsValue=inactiveCellsValue))
def setExportFolder(self, type, path, createFolder=False): def setExportFolder(self, type, path, createFolder=False):
return self.execute(setExportFolder=Cmd.SetExportFolderRequest(type=type, return self.__execute(setExportFolder=Cmd.SetExportFolderRequest(type=type,
path=path, path=path,
createFolder=createFolder)) createFolder=createFolder))
@ -125,29 +134,29 @@ class Commands:
caseIds = [] caseIds = []
for case in cases: for case in cases:
caseIds.append(case.id) caseIds.append(case.id)
return self.execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path, return self.__execute(runOctaveScript=Cmd.RunOctaveScriptRequest(path=path,
caseIds=caseIds)) caseIds=caseIds))
def setMainWindowSize(self, width, height): def setMainWindowSize(self, width, height):
return self.execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height)) return self.__execute(setMainWindowSize=Cmd.SetMainWindowSizeParams(width=width, height=height))
def computeCaseGroupStatistics(self, caseIds): def computeCaseGroupStatistics(self, caseIds):
if isinstance(caseIds, int): if isinstance(caseIds, int):
caseIds = [caseIds] caseIds = [caseIds]
return self.execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds)) return self.__execute(computeCaseGroupStatistics=Cmd.ComputeCaseGroupStatRequest(caseIds=caseIds))
def setTimeStep(self, caseId, timeStep): def setTimeStep(self, caseId, timeStep):
return self.execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep)) return self.__execute(setTimeStep=Cmd.SetTimeStepParams(caseId=caseId, timeStep=timeStep))
def scaleFractureTemplate(self, id, halfLength, height, dFactor, conductivity): def scaleFractureTemplate(self, id, halfLength, height, dFactor, conductivity):
return self.execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id, return self.__execute(scaleFractureTemplate=Cmd.ScaleFractureTemplateRequest(id=id,
halfLength=halfLength, halfLength=halfLength,
height=height, height=height,
dFactor=dFactor, dFactor=dFactor,
conductivity=conductivity)) conductivity=conductivity))
def setFractureContainment(self, id, topLayer, baseLayer): def setFractureContainment(self, id, topLayer, baseLayer):
return self.execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id, return self.__execute(setFractureContainment=Cmd.SetFracContainmentRequest(id=id,
topLayer=topLayer, topLayer=topLayer,
baseLayer=baseLayer)) baseLayer=baseLayer))
@ -155,7 +164,7 @@ class Commands:
maxFracturesPerWell, topLayer, baseLayer, spacing, action): maxFracturesPerWell, topLayer, baseLayer, spacing, action):
if isinstance(wellPathNames, str): if isinstance(wellPathNames, str):
wellPathNames = [wellPathNames] wellPathNames = [wellPathNames]
return self.execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=caseId, return self.__execute(createMultipleFractures=Cmd.MultipleFracAction(caseId=caseId,
templateId=templateId, templateId=templateId,
wellPathNames=wellPathNames, wellPathNames=wellPathNames,
minDistFromWellTd=minDistFromWellTd, minDistFromWellTd=minDistFromWellTd,
@ -168,7 +177,7 @@ class Commands:
def createLgrForCompletions(self, caseId, timeStep, wellPathNames, refinementI, refinementJ, refinementK, splitType): def createLgrForCompletions(self, caseId, timeStep, wellPathNames, refinementI, refinementJ, refinementK, splitType):
if isinstance(wellPathNames, str): if isinstance(wellPathNames, str):
wellPathNames = [wellPathNames] wellPathNames = [wellPathNames]
return self.execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=caseId, return self.__execute(createLgrForCompletions=Cmd.CreateLgrForCompRequest(caseId=caseId,
timeStep=timeStep, timeStep=timeStep,
wellPathNames=wellPathNames, wellPathNames=wellPathNames,
refinementI=refinementI, refinementI=refinementI,
@ -179,5 +188,5 @@ class Commands:
def createSaturationPressurePlots(self, caseIds): def createSaturationPressurePlots(self, caseIds):
if isinstance(caseIds, int): if isinstance(caseIds, int):
caseIds = [caseIds] caseIds = [caseIds]
return self.execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds)) return self.__execute(createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=caseIds))

View File

@ -8,11 +8,20 @@ import Grid_pb2
import Grid_pb2_grpc import Grid_pb2_grpc
class Grid: class Grid:
"""Grid Information. Not meant to be constructed separately
Create Grid objects using mathods on Case: Grid() and Grids()
"""
def __init__(self, index, case): def __init__(self, index, case):
self.case = case self.case = case
self.index = index self.index = index
self.stub = Grid_pb2_grpc.GridStub(self.case.channel) self.stub = Grid_pb2_grpc.GridStub(self.case.channel)
def dimensions(self): def dimensions(self):
"""The dimensions in i, j, k direction
Returns:
Vec3i: class with integer attributes i, j, k representing the extent in all three dimensions.
"""
return self.stub.GetDimensions(Grid_pb2.GridRequest(case_request = self.case.request, grid_index = self.index)).dimensions return self.stub.GetDimensions(Grid_pb2.GridRequest(case_request = self.case.request, grid_index = self.index)).dimensions

View File

@ -14,16 +14,38 @@ from .Commands import Commands
from .Project import Project from .Project import Project
class Instance: class Instance:
launched = False """The ResInsight Instance class. Use to launch or find existing ResInsight instances
Attributes:
launched(bool): Tells us whether the application was launched as a new process.
If the application was launched we may need to close it when exiting the script.
app(App): Application information object. Set when creating an instance.
commands(Commands): Command executor. Set when creating an instance.
project(Project): Current project in ResInsight.
Set when creating an instance and updated when opening/closing projects.
"""
@staticmethod @staticmethod
def is_port_in_use(port): def __is_port_in_use(port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.2) s.settimeout(0.2)
return s.connect_ex(('localhost', port)) == 0 return s.connect_ex(('localhost', port)) == 0
@staticmethod @staticmethod
def launch(resInsightExecutable = '', console = False): def launch(resInsightExecutable = '', console = False):
""" Launch a new Instance of ResInsight. This requires the environment variable
RESINSIGHT_EXECUTABLE to be set or the parameter resInsightExecutable to be provided.
The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number.
Args:
resInsightExecutable (str): Path to a valid ResInsight executable. If set
will take precedence over what is provided in the RESINSIGHT_EXECUTABLE
environment variable.
console (bool): If True, launch as console application, without GUI.
Returns:
Instance: an instance object if it worked. None if not.
"""
port = 50051 port = 50051
portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') portEnv = os.environ.get('RESINSIGHT_GRPC_PORT')
if portEnv: if portEnv:
@ -36,7 +58,7 @@ class Instance:
' RESINSIGHT_EXECUTABLE is not set') ' RESINSIGHT_EXECUTABLE is not set')
return None return None
while Instance.is_port_in_use(port): while Instance.__is_port_in_use(port):
port += 1 port += 1
print('Port ' + str(port)) print('Port ' + str(port))
@ -47,24 +69,36 @@ class Instance:
parameters.append("--console") parameters.append("--console")
pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters) pid = os.spawnv(os.P_NOWAIT, resInsightExecutable, parameters)
if pid: if pid:
return Instance(port=port, launched=True) instance = Instance(port=port)
instance.launched = True
return instance
return None return None
@staticmethod @staticmethod
def find(startPort = 50051, endPort = 50071): def find(startPort = 50051, endPort = 50071):
""" Search for an existing Instance of ResInsight by testing ports.
By default we search from port 50051 to 50071 or if the environment
variable RESINSIGHT_GRPC_PORT is set we search
RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20
Args:
startPort(int): start searching from this port
endPort(int): search up to but not including this port
"""
portEnv = os.environ.get('RESINSIGHT_GRPC_PORT') portEnv = os.environ.get('RESINSIGHT_GRPC_PORT')
if portEnv: if portEnv:
startPort = int(portEnv) startPort = int(portEnv)
endPort = startPort + 20 endPort = startPort + 20
for tryPort in range(startPort, endPort): for tryPort in range(startPort, endPort):
if Instance.is_port_in_use(tryPort): if Instance.__is_port_in_use(tryPort):
return Instance(tryPort) return Instance(tryPort)
print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort)) print('Error: Could not find any ResInsight instances responding between ports ' + str(startPort) + ' and ' + str(endPort))
return None return None
def checkVersion(self): def __checkVersion(self):
try: try:
majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION) majorVersionOk = self.app.majorVersion() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION)
minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION) minorVersionOk = self.app.minorVersion() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION)
@ -72,12 +106,17 @@ class Instance:
except grpc.RpcError as e: except grpc.RpcError as e:
return False, False return False, False
def __init__(self, port = 50051, launched = False): def __init__(self, port = 50051):
""" Attempts to connect to ResInsight at aa specific port on localhost
Args:
port(int): port number
"""
logging.basicConfig() logging.basicConfig()
location = "localhost:" + str(port) location = "localhost:" + str(port)
self.channel = grpc.insecure_channel(location) self.channel = grpc.insecure_channel(location)
self.launched = launched self.launched = False
# Main version check package # Main version check package
self.app = App(self.channel) self.app = App(self.channel)
@ -85,14 +124,14 @@ class Instance:
connectionOk = False connectionOk = False
versionOk = False versionOk = False
if launched: if self.launched:
for i in range(0, 10): for i in range(0, 10):
connectionOk, versionOk = self.checkVersion() connectionOk, versionOk = self.__checkVersion()
if connectionOk: if connectionOk:
break break
time.sleep(1.0) time.sleep(1.0)
else: else:
connectionOk, versionOk = self.checkVersion() connectionOk, versionOk = self.__checkVersion()
if not connectionOk: if not connectionOk:
if launched: if launched:

View File

@ -12,18 +12,34 @@ import Project_pb2
import Project_pb2_grpc import Project_pb2_grpc
class Project: class Project:
"""ResInsight project. Not intended to be created separately.
Automatically created and assigned to Instance.
"""
def __init__(self, channel): def __init__(self, channel):
self.channel = channel self.channel = channel
self.project = Project_pb2_grpc.ProjectStub(channel) self.project = Project_pb2_grpc.ProjectStub(channel)
def open(self, path): def open(self, path):
"""Open a new project from the given path
Argument:
path(string): path to project file
"""
Commands(self.channel).openProject(path) Commands(self.channel).openProject(path)
return self return self
def close(self): def close(self):
"""Close the current project (and open new blank project)"""
Commands(self.channel).closeProject() Commands(self.channel).closeProject()
def selectedCases(self): def selectedCases(self):
"""Get a list of all cases selected in the project tree
Returns:
A list of rips Case objects
"""
caseInfos = self.project.GetSelectedCases(Empty()) caseInfos = self.project.GetSelectedCases(Empty())
cases = [] cases = []
for caseInfo in caseInfos.data: for caseInfo in caseInfos.data:
@ -31,6 +47,11 @@ class Project:
return cases return cases
def cases(self): def cases(self):
"""Get a list of all cases in the project
Returns:
A list of rips Case objects
"""
try: try:
caseInfos = self.project.GetAllCases(Empty()) caseInfos = self.project.GetAllCases(Empty())
@ -46,6 +67,13 @@ class Project:
return [] return []
def case(self, id): def case(self, id):
"""Get a specific case from the provided case Id
Arguments:
id(int): case id
Returns:
A rips Case object
"""
try: try:
case = Case(self.channel, id) case = Case(self.channel, id)
return case return case
@ -53,5 +81,12 @@ class Project:
return None return None
def loadCase(self, path): def loadCase(self, path):
"""Load a new case from the given file path
Arguments:
path(string): file path to case
Returns:
A rips Case object
"""
return Commands(self.channel).loadCase(path) return Commands(self.channel).loadCase(path)

View File

@ -10,11 +10,17 @@ import Case_pb2
import Case_pb2_grpc import Case_pb2_grpc
class Properties: class Properties:
""" Class for streaming properties to and from ResInsight
"""
def __init__(self, case): def __init__(self, case):
"""
Arguments:
case(Case): A rips case to handle properties for
"""
self.case = case self.case = case
self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel) self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel)
def generatePropertyInputIterator(self, values_iterator, parameters): def __generatePropertyInputIterator(self, values_iterator, parameters):
chunk = Properties_pb2.PropertyInputChunk() chunk = Properties_pb2.PropertyInputChunk()
chunk.params.CopyFrom(parameters) chunk.params.CopyFrom(parameters)
yield chunk yield chunk
@ -24,7 +30,7 @@ class Properties:
chunk.values.CopyFrom(valmsg) chunk.values.CopyFrom(valmsg)
yield chunk yield chunk
def generatePropertyInputChunks(self, array, parameters): def __generatePropertyInputChunks(self, array, parameters):
# Each double is 8 bytes. A good chunk size is 64KiB = 65536B # Each double is 8 bytes. A good chunk size is 64KiB = 65536B
# Meaning ideal number of doubles would be 8192. # Meaning ideal number of doubles would be 8192.
# However we need overhead space, so if we choose 8160 in chunk size # However we need overhead space, so if we choose 8160 in chunk size
@ -47,6 +53,22 @@ class Properties:
yield chunk yield chunk
def available(self, propertyType, porosityModel = 'MATRIX_MODEL'): def available(self, propertyType, porosityModel = 'MATRIX_MODEL'):
"""Get a list of available properties
Arguments:
propertyType(string): string corresponding to propertyType enum
Can be one of the following:
'DYNAMIC_NATIVE'
'STATIC_NATIVE'
'SOURSIMRL'
'GENERATED'
'INPUT_PROPERTY'
'FORMATION_NAMES'
'FLOW_DIAGNOSTICS'
'INJECTION_FLOODING'
porosityModel(string): 'MATRIX_MODEL' or 'FRACTURE_MODEL'.
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.AvailablePropertiesRequest (case_request = Case_pb2.CaseRequest(id=self.case.id), request = Properties_pb2.AvailablePropertiesRequest (case_request = Case_pb2.CaseRequest(id=self.case.id),
@ -55,6 +77,18 @@ class Properties:
return self.propertiesStub.GetAvailableProperties(request).property_names return self.propertiesStub.GetAvailableProperties(request).property_names
def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'): def activeCellProperty(self, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'):
"""Get a cell property for all active cells. Async, so returns an iterator
Arguments:
propertyType(string): string enum. See available()
propertyName(string): name of an Eclipse property
timeStep(int): the time step for which to get the property for
porosityModel(string): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
You first loop through the chunks and then the values within the chunk to get all values.
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.PropertyRequest(case_request = Case_pb2.CaseRequest(id=self.case.id), request = Properties_pb2.PropertyRequest(case_request = Case_pb2.CaseRequest(id=self.case.id),
@ -66,6 +100,19 @@ class Properties:
yield chunk yield chunk
def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): def gridProperty(self, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'):
"""Get a cell property for all grid cells. Async, so returns an iterator
Arguments:
propertyType(string): string enum. See available()
propertyName(string): name of an Eclipse property
timeStep(int): the time step for which to get the property for
gridIndex(int): index to the grid we're getting values for
porosityModel(string): string enum. See available()
Returns:
An iterator to a chunk object containing an array of double values
You first loop through the chunks and then the values within the chunk to get all values.
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.PropertyRequest(case_request = self.case.request, request = Properties_pb2.PropertyRequest(case_request = self.case.request,
@ -77,17 +124,25 @@ class Properties:
for chunk in self.propertiesStub.GetGridProperty(request): for chunk in self.propertiesStub.GetGridProperty(request):
yield chunk yield chunk
def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): def setActiveCellPropertyAsync(self, values_iterator, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'):
"""Set a cell property for all active cells. Async, and so takes an iterator to the input values
Arguments:
values_iterator(iterator): an iterator to the properties to be set
propertyType(string): string enum. See available()
propertyName(string): name of an Eclipse property
timeStep(int): the time step for which to get the property for
porosityModel(string): string enum. See available()
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.PropertyRequest(case_request = self.case.request, request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = propertyTypeEnum, property_type = propertyTypeEnum,
property_name = propertyName, property_name = propertyName,
time_step = timeStep, time_step = timeStep,
grid_index = gridIndex,
porosity_model = porosityModelEnum) porosity_model = porosityModelEnum)
try: try:
reply_iterator = self.generatePropertyInputIterator(values_iterator, request) reply_iterator = self.__generatePropertyInputIterator(values_iterator, request)
self.propertiesStub.SetActiveCellProperty(reply_iterator) self.propertiesStub.SetActiveCellProperty(reply_iterator)
except grpc.RpcError as e: except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND: if e.code() == grpc.StatusCode.NOT_FOUND:
@ -95,17 +150,25 @@ class Properties:
else: else:
print("Other error", e) print("Other error", e)
def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'):
"""Set a cell property for all active cells.
Arguments:
values(list): a list of double precision floating point numbers
propertyType(string): string enum. See available()
propertyName(string): name of an Eclipse property
timeStep(int): the time step for which to get the property for
porosityModel(string): string enum. See available()
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.PropertyRequest(case_request = self.case.request, request = Properties_pb2.PropertyRequest(case_request = self.case.request,
property_type = propertyTypeEnum, property_type = propertyTypeEnum,
property_name = propertyName, property_name = propertyName,
time_step = timeStep, time_step = timeStep,
grid_index = gridIndex,
porosity_model = porosityModelEnum) porosity_model = porosityModelEnum)
try: try:
request_iterator = self.generatePropertyInputChunks(values, request) request_iterator = self.__generatePropertyInputChunks(values, request)
self.propertiesStub.SetActiveCellProperty(request_iterator) self.propertiesStub.SetActiveCellProperty(request_iterator)
except grpc.RpcError as e: except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND: if e.code() == grpc.StatusCode.NOT_FOUND:
@ -114,6 +177,16 @@ class Properties:
print("Other error", e) print("Other error", e)
def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'): def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'):
"""Set a cell property for all grid cells.
Arguments:
values(list): a list of double precision floating point numbers
propertyType(string): string enum. See available()
propertyName(string): name of an Eclipse property
timeStep(int): the time step for which to get the property for
gridIndex(int): index to the grid we're setting values for
porosityModel(string): string enum. See available()
"""
propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType) propertyTypeEnum = Properties_pb2.PropertyType.Value(propertyType)
porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel) porosityModelEnum = Case_pb2.PorosityModelType.Value(porosityModel)
request = Properties_pb2.PropertyRequest(case_request = self.case.request, request = Properties_pb2.PropertyRequest(case_request = self.case.request,
@ -123,7 +196,7 @@ class Properties:
grid_index = gridIndex, grid_index = gridIndex,
porosity_model = porosityModelEnum) porosity_model = porosityModelEnum)
try: try:
request_iterator = self.generatePropertyInputChunks(values, request) request_iterator = self.__generatePropertyInputChunks(values, request)
self.propertiesStub.SetGridProperty(request_iterator) self.propertiesStub.SetGridProperty(request_iterator)
except grpc.RpcError as e: except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND: if e.code() == grpc.StatusCode.NOT_FOUND:

View File

@ -6,7 +6,7 @@ with open('README.md') as f:
with open('LICENSE') as f: with open('LICENSE') as f:
license = f.read() license = f.read()
RIPS_DIST_VERSION = '1' RIPS_DIST_VERSION = '2'
setup( setup(
name='rips', name='rips',