From cc75f4f69d46fd51a64a76bc565afb1488fa33ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Therese=20Natter=C3=B8y?= <61694854+tnatt@users.noreply.github.com> Date: Wed, 10 Jan 2024 16:43:59 +0100 Subject: [PATCH] Add option to store rft points in project --- docs/create_rft_ertobs.rst | 5 ++ .../qcforward/_blockedwells_vs_gridprops.py | 4 -- src/fmu/tools/rms/create_rft_ertobs.py | 65 ++++++++++++++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/docs/create_rft_ertobs.rst b/docs/create_rft_ertobs.rst index 465db5f2..827e7068 100644 --- a/docs/create_rft_ertobs.rst +++ b/docs/create_rft_ertobs.rst @@ -51,6 +51,7 @@ Additional options are specified through a RMS dictionary, and "gridname": "Simgrid", "zonename": "Zone", "verbose": True, + "clipboard_folder": "RFT_ERT_observations", # Optional folder for storage in RMS } create_rft_ertobs.main(CONFIG) @@ -120,6 +121,10 @@ trajectory_name The trajectory name for the wellpaths in the RMS project. Defaults to "Drilled trajectory". +clipboard_folder + Optional name of clipboard folder for storing RFT points inside the RMS project. + The folder will be created if not present. + See also ^^^^^^^^ diff --git a/src/fmu/tools/qcforward/_blockedwells_vs_gridprops.py b/src/fmu/tools/qcforward/_blockedwells_vs_gridprops.py index 617fde36..422cebba 100644 --- a/src/fmu/tools/qcforward/_blockedwells_vs_gridprops.py +++ b/src/fmu/tools/qcforward/_blockedwells_vs_gridprops.py @@ -192,7 +192,6 @@ def run( print(f"No lines are matching {lines}. Wrong input?:\n") else: - print("Show all well cells for all wells:") if len(comb) > 0: print(comb.to_string()) @@ -274,7 +273,6 @@ def _eval_tolerance(self, df_in, bwprop, modelprop, diffname, diffnameflag): return comb def _evaluate_diffs(self, comb, diffs) -> pd.DataFrame: - result: OrderedDict = OrderedDict( [ ("WELL", []), @@ -304,7 +302,6 @@ def _evaluate_diffs(self, comb, diffs) -> pd.DataFrame: status = "OK" for therule in self.ldata.actions: - warnrule = ActionsParser( therule.get("warn", None), mode="warn", verbosity=QCC.verbosity ) @@ -313,7 +310,6 @@ def _evaluate_diffs(self, comb, diffs) -> pd.DataFrame: ) for _, issue in enumerate([warnrule, stoprule]): - if wname != "all" and not issue.all: rulename = issue.mode.upper() + "RULE" result[rulename].append(issue.expression) diff --git a/src/fmu/tools/rms/create_rft_ertobs.py b/src/fmu/tools/rms/create_rft_ertobs.py index 31316b4a..4ec697b6 100644 --- a/src/fmu/tools/rms/create_rft_ertobs.py +++ b/src/fmu/tools/rms/create_rft_ertobs.py @@ -60,6 +60,7 @@ "verbose", "welldatefile", # WELL_AND_TIME_FILE in semeio "zonename", + "clipboard_folder", ] @@ -445,6 +446,7 @@ def ertobs_df_to_files( ["WELL_NAME", "DAY", "MONTH", "YEAR", "REPORT_STEP"] ].first().to_csv(Path(exportdir) / welldatefile, sep=" ", index=False, header=False) logger.info("Written welldata file to %s", Path(exportdir) / welldatefile) + return dframe def fill_missing_md_xyz( @@ -494,6 +496,59 @@ def fill_missing_md_xyz( return dframe +def store_rft_as_points_inside_project(dframe, project, clipboard_folder): + """ + Store RFT observations for ERT as points in RMS under Clipboard. + The points will be stored per zone and will include useful attributes as pressure wellname, date etc. + + """ + + dframe["DATE"] = dframe["DATE"].dt.strftime("%Y-%m-%d") + + # create zone mismatch column to include as attribute + if "rms_cell_zone_str" in dframe: + dframe["ZONE_MISMATCH"] = np.where( + dframe["ZONE"] == dframe["rms_cell_zone_str"], 1, 0 + ) + + # create points and store in rms + create_clipboard_points_with_attributes( + project, "All_RFTs", dframe, [clipboard_folder, "All RFT points"] + ) + + groupby = (col for col in ("ZONE", "YEAR", "WELL_NAME") if col in dframe) + for col in groupby: + for name, df in dframe.groupby(col): + create_clipboard_points_with_attributes( + project, name, df, [clipboard_folder, f"RFT points by {col}"] + ) + + print(f"Stored RFT points under clipboard folder {clipboard_folder}") + + +def create_clipboard_points_with_attributes(project, name, df, folder): + attribute_dtypes = { + "PRESSURE": float, + "DATE": str, + "ZONE": str, + "WELL_NAME": str, + "ERROR": float, + "YEAR": int, + "ZONE_MISMATCH": int, + } + + points = project.clipboard.create_points(str(name), folder) + + # set XYZ for the points + points.set_values(df[["EAST", "NORTH", "TVD"]].to_numpy()) + + # set attributes for the points + for attr, dtype in attribute_dtypes.items(): + if attr in df: + values = df[attr].values.astype(dtype) + points.set_attribute_values(attr, values) + + def main(config: Optional[Dict[str, Any]] = None) -> None: """The main function to be called from a RMS client python script. @@ -534,6 +589,7 @@ def main(config: Optional[Dict[str, Any]] = None) -> None: lambda df: grid.get_cells_at_points([df["EAST"], df["NORTH"], df["TVD"]]), axis=1, ) + else: assert not dframe["MD"].isnull().any() and not dframe["TVD"].isnull().any(), ( "MD and TVD must be supplied for all points " @@ -599,4 +655,11 @@ def main(config: Optional[Dict[str, Any]] = None) -> None: dframe["WELL_NAME"] = dframe["WELL_NAME"].apply(lambda x: config["alias"].get(x, x)) # Export *.obs, *.txt and well_date_rft.txt - ertobs_df_to_files(dframe, exportdir=config["exportdir"], welldatefile=welldatefile) + dframe = ertobs_df_to_files( + dframe, exportdir=config["exportdir"], welldatefile=welldatefile + ) + + if "project" in config and "clipboard_folder" in config: + store_rft_as_points_inside_project( + dframe, config["project"], config["clipboard_folder"] + )