def show_stats_inside_rms(): """Get statistics for one realisation, poro/perm filtered on facies. This is an 'inside RMS' version; should work given runrmsx <project> but not tested. Focus on syntax for getting properties, otherwise code is quite similar. """ prj = project # type: ignore # noqa # pylint: disable=undefined-variable # names of icons... gridmodel = "Reek" faciesname = "Facies" propnames = ["Poro", "Perm"] # read facies (to be used as filter) facies = xtgeo.gridproperty_from_roxar(prj, gridmodel, faciesname) print("Facies codes are: {}".format(facies.codes)) for propname in propnames: prop = xtgeo.gridproperty_from_roxar(prj, gridmodel, propname) print("Working with {}".format(prop.name)) # now find statistics for each facies, and all facies for key, fname in facies.codes.items(): avg = prop.values[facies.values == key].mean() std = prop.values[facies.values == key].std() print("For property {} in facies {}, avg is {:10.3f} and " "stddev is {:9.3f}".format(propname, fname, avg, std)) avg = prop.values.mean() std = prop.values.std() print("For property {} in ALL facies, avg is {:10.3f} and " "stddev is {:9.3f}".format(propname, avg, std))
def test_rox_get_gridproperty(): """Get a grid property from a RMS project.""" print("Project is {}".format(PRJ)) poro = xtgeo.gridproperty_from_roxar(PRJ, GRIDNAME1, PORONAME1) assert poro.values.mean() == pytest.approx(0.16774, abs=0.001) assert poro.dimensions == (40, 64, 14) zone = xtgeo.gridproperty_from_roxar(PRJ, GRIDNAME1, ZONENAME1) assert "int" in str(zone.values.dtype) zone._roxar_dtype = np.int32 with pytest.raises(TypeError): zone.to_roxar(PRJ, GRIDNAME1, ZONENAME1)
def test_rox_get_gridproperty(): """Get a grid property from a RMS project.""" print("Project is {}".format(PRJ)) poro = xtgeo.gridproperty_from_roxar(PRJ, GRIDNAME1, PORONAME1) tsetup.assert_almostequal(poro.values.mean(), 0.16774, 0.001) assert poro.dimensions == (40, 64, 14)
def test_rox_get_modify_set_gridproperty(): """Get and set a grid property from a RMS project.""" poro = xtgeo.gridproperty_from_roxar(PRJ, GRIDNAME1, PORONAME1) adder = 0.9 poro.values = poro.values + adder poro.to_roxar(PRJ, GRIDNAME1, PORONAME1 + "_NEW") poro.from_roxar(PRJ, GRIDNAME1, PORONAME1 + "_NEW") assert poro.values[1, 0, 0] == pytest.approx(0.14942 + adder, abs=0.0001)
def test_rox_get_modify_set_gridproperty(): """Get and set a grid property from a RMS project.""" poro = xtgeo.gridproperty_from_roxar(PRJ, GRIDNAME1, PORONAME1) adder = 0.9 poro.values = poro.values + adder poro.to_roxar(PRJ, GRIDNAME1, PORONAME1 + "_NEW") poro.from_roxar(PRJ, GRIDNAME1, PORONAME1 + "_NEW") tsetup.assert_almostequal(poro.values[1, 0, 0], 0.14942 + adder, 0.0001)
def read_gridprops(self, gridprops, gridname=None, reuse=None): """Read 3D grid props, from file or RMS.""" gridname = gridname if self._project is not None else join( self._path, gridname) CMN.print_info("Reading grid properties...") gprops = [] if "gridprops" in reuse: reused_gprops, gridprops = self._reuse_gridprops( gridprops, gridname) gprops = reused_gprops if self._project is None: for gprop in gridprops: if isinstance(gprop, list): pname, pfile = gprop else: pfile = gprop pname = "unknown" gridproppath = join(self._path, pfile) xtg_gprop = xtgeo.gridproperty_from_file(gridproppath, name=pname, grid=self.grid) xtg_gprop.name = pname if pname != "unknown" else pfile gprops.append(xtg_gprop) if isinstance(gprop, list): self._xtgdata["gridprops"][gridname][tuple( gprop)] = xtg_gprop else: self._xtgdata["gridprops"][gridname][gprop] = xtg_gprop else: # read from RMS/ROXAPI for pname in gridprops: xtg_gprop = xtgeo.gridproperty_from_roxar( self._project, gridname, pname) gprops.append(xtg_gprop) self._xtgdata["gridprops"][gridname][pname] = xtg_gprop self._gridprops = xtgeo.GridProperties() self._gridprops.append_props(gprops)
def test_qcreset(): """Test qcreset metod in roxapi.""" # ================================================================================== # pylint: disable=invalid-name from fmu.tools.rms import qcreset rox = xtgeo.RoxUtils(project=PRJ) SETUP1 = { "project": rox._project, "horizons": { "DS_whatever": ["TopReek", "MidReek"], }, "grid_models": { "Simgrid": ["PORO"], }, "value": 0.088, } SETUP2 = { "project": rox._project, "horizons": { "DS_whatever": ["TopReek", "MidReek"], }, "grid_models": { "Simgrid": ["PORO"], }, } qcreset.set_data_constant(SETUP1) topr = xtgeo.surface_from_roxar(rox._project, "TopReek", "DS_whatever") assert topr.values.mean() == pytest.approx(0.088) poro = xtgeo.gridproperty_from_roxar(rox._project, "Simgrid", "PORO") assert poro.values.mean() == pytest.approx(0.088) qcreset.set_data_empty(SETUP2) top = rox._project.horizons["TopReek"]["DS_whatever"] assert top.is_empty() is True
def extract_grid_zone_tops( project: Optional[_roxar.Project] = None, well_list: Optional[list] = None, logrun: str = "log", trajectory: str = "Drilled trajectory", gridzonelog: str = None, mdlogname: str = None, grid: str = None, zone_param: str = None, alias_file: str = None, rms_name: str = "RMS_WELL_NAME", ecl_name: str = "ECLIPSE_WELL_NAME", ) -> pd.DataFrame: """ Function for extracting top and base from gridzones, both in TVD and MD. A pandas dataframe will be returned. Users can either input a pre-generated gridzonelog or a grid and a zone parameter for computing the gridzonelog. The function works both inside RMS and outside with file input. If input from files, and a MD log is not present in the well a quasi md log will be computed and used. """ use_gridzonelog = False if gridzonelog is None else True if not use_gridzonelog: if grid is not None and zone_param is not None: if project is not None: mygrid = xtgeo.grid_from_roxar(project, grid) gridzones = xtgeo.gridproperty_from_roxar(project, grid, zone_param) else: mygrid = xtgeo.grid_from_file(grid) gridzones = xtgeo.gridproperty_from_file(zone_param, grid=mygrid) gridzones.name = "Zone" else: raise ValueError("Specify either 'gridzonelog' or 'grid' and 'zone_param") dfs = [] if well_list is None: well_list = [] for well in well_list: try: if project is not None: xtg_well = xtgeo.well_from_roxar( project, str(well), trajectory=trajectory, logrun=logrun, inclmd=True, ) else: xtg_well = xtgeo.well_from_file(str(well), mdlogname=mdlogname) # quasi md log will be computed xtg_well.geometrics() except (ValueError, KeyError): continue # if no gridzonelog create one from the zone parameter if not use_gridzonelog: xtg_well.get_gridproperties(gridzones, mygrid) gridzonelog = "Zone_model" if xtg_well.dataframe[gridzonelog].isnull().values.all(): continue # Set gridzonelog as zonelog and extract zonation tops from it xtg_well.zonelogname = gridzonelog dframe = xtg_well.get_zonation_points(top_prefix="", use_undef=True) dframe.rename( columns={ "Z_TVDSS": "TOP_TVD", xtg_well.mdlogname: "TOP_MD", "Zone": "ZONE_CODE", "WellName": "WELL", }, inplace=True, ) # find deepest point in well while in grid df_max = ( xtg_well.dataframe[["Z_TVDSS", xtg_well.mdlogname, gridzonelog]] .dropna() .sort_values(by=xtg_well.mdlogname) ) # create base picks also dframe["BASE_TVD"] = dframe["TOP_TVD"].shift(-1) dframe["BASE_MD"] = dframe["TOP_MD"].shift(-1) dframe.at[dframe.index[-1], "BASE_TVD"] = df_max.iloc[-1]["Z_TVDSS"] dframe.at[dframe.index[-1], "BASE_MD"] = df_max.iloc[-1][xtg_well.mdlogname] # adjust zone values to get correct zone information dframe["ZONE_CODE"] = shift_zone_values(dframe["ZONE_CODE"].values.copy()) dframe["ZONE"] = ( dframe["ZONE_CODE"] .map(xtg_well.get_logrecord(xtg_well.zonelogname)) .fillna("Outside") ) dfs.append(dframe.drop(columns=["TopName", "Q_INCL", "Q_AZI"])) df = pd.concat(dfs) if alias_file is not None: well_dict = make_alias_dict(alias_file, rms_name, ecl_name) df["WELL"] = df["WELL"].replace(well_dict) return df
def _read_from_rms(self, data): """Read data from inside RMS or via Roxar API""" _get_verbosity(self, data) self._project = data["project"] reuse_grid = False if "grid" in data.keys(): gridname = data["grid"] if gridname == self._gridname: self.print_info("Grid is already loaded") reuse_grid = True # grid is already loaded else: self.print_info("Reading grid...") self.print_debug("GRIDNAME: {}".format(gridname)) self._grid = xtgeo.grid_from_roxar(self._project, gridname) self._gridname = gridname self.print_debug("Looking for zone...") if "zone" in data.keys(): if reuse_grid and data["zone"] == self._gridzonename: self.print_info("Grid zone is already loaded") else: self._gridzone = xtgeo.gridproperty_from_roxar( self._project, data["grid"], data["zone"] ) self._gridzonename = data["zone"] self.print_debug("GRIDZONE: {}".format(self._gridzonename)) if "wells" in data.keys(): # wells area allowed to spesified by regular expressions, e.g. # ["55_33-[123]", "55_33-.*A.*"] if "zonelogname" in data: self._zonelogname = data["zonelogname"] wdata = [] rmswells = [wll.name for wll in self._project.wells] self.print_debug("All RMS wells: {}".format(rmswells)) if not isinstance(data["wells"], list): raise ValueError("Wells input must be a list") self.print_debug("Data wells to match: {}".format(data["wells"])) for rmswell in rmswells: for wreg in data["wells"]: self.print_debug("Trying match {} vs re {}".format(rmswell, wreg)) if re.match(wreg, rmswell): wdata.append( xtgeo.well_from_roxar( self._project, rmswell, logrun=self._wlogrun, trajectory=self._wtrajectory, lognames=[self._zonelogname], ) ) self.print_info("Regex match found, RMS well: {}".format(rmswell)) self._wells = xtgeo.Wells() self._wells.wells = wdata