def read_wells(self, wells, welltype="wells", settings=False, reuse=None): """Reading wells""" settings = settings if settings else {} wellist = self._well_preparations(wells) CMN.print_info("Reading wells...") xtg_wells = [] if "wells" in reuse: reused_wells, wellist = self._reuse_wells(wellist, welltype) xtg_wells = reused_wells for well in wellist: try: if welltype == "wells": mywell = (xtgeo.well_from_file( well, lognames=settings.get("lognames", "all")) if self._project is None else xtgeo.well_from_roxar( project=self._project, name=well, lognames=settings.get("lognames", "all"), logrun=wells.get("logrun", "log"), trajectory=wells.get("trajectory", "Drilled trajectory"), )) else: mywell = (xtgeo.blockedwell_from_file(well) if self._project is None else xtgeo.blockedwell_from_roxar( project=self._project, gname=wells.get("grid", "Geogrid"), bwname=wells.get("bwname", "BW"), wname=well, lognames=settings.get("lognames", "all"), )) xtg_wells.append(mywell) self._xtgdata[welltype][well] = mywell CMN.print_debug(well) except ValueError as verr: print(f"Could not read well {well}: {verr}") CMN.print_debug(f"All valid welldata: {xtg_wells}") for mywell in xtg_wells: if "depthrange" in settings and settings["depthrange"] is not None: tmin, tmax = settings["depthrange"] mywell.limit_tvd(tmin, tmax) if "rescale" in settings and settings["rescale"] is not None: mywell.rescale(settings["rescale"]) if xtg_wells: if welltype == "wells": self._wells = xtgeo.Wells() self._wells.wells = xtg_wells else: self._bwells = xtgeo.BlockedWells() self._bwells.wells = xtg_wells else: raise RuntimeError("No wells read, wrong settings?")
def test_rox_wells(): """Various tests on Roxar wells.""" well = xtgeo.well_from_roxar(PRJ, "OP_2", trajectory="My trajectory", logrun="log") assert "Zonelog" in well.lognames assert well.dataframe["Poro"].mean() == pytest.approx(0.1637623936)
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