From a9d291102c967f26421c96b1f8bf63be3334489f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 08:57:07 +0000 Subject: [PATCH] Adopt petrolib.data_qc_io in 2015-2019 articles Strangler-fig delegation of the data-QC forms to the canonical package (PR-B1 of the data_qc_io train, final plan domain): - src2015_04/article4: histogram_scale -> scale.normalize_to_reference (pct=None min/max endpoints) - src2016_02/article3: deviation_indicator -> clean.relative_discrepancy - src2016_12/article6: histogram_normalize -> scale.normalize_to_reference (explicit endpoints); affine_normalize -> scale.match_moments (+ bootstrap header) - src2017_10/article5: relative_discrepancy -> clean.relative_discrepancy (the |a-b|/(0.5(a+b)) arrangement rounds identically in IEEE) - src2018_12/article11: iqr_outliers -> clean.outlier_mask("iqr"); impute_gaps -> clean.impute_gaps - src2019_02/article4: closure -> clean.closure_residual All function names, signatures, and docstrings unchanged. Verified: stdout byte-identical old vs new for all six modules; golden_diff 6/6 directories pass; mypy clean; 252 tests pass. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01B2BX1XL8422gebCU1oVoQC --- src2015_04/article4_microresistivity_extraction.py | 4 +--- .../article3_low_permeability_measurements.py | 2 +- .../article6_gr_normalization_haynesville.py | 14 ++++++++++---- src2017_10/article5_permian_core_analysis.py | 2 +- src2018_12/article11_data_preconditioning.py | 9 ++------- .../article4_insitu_saturation_core_comparison.py | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src2015_04/article4_microresistivity_extraction.py b/src2015_04/article4_microresistivity_extraction.py index 893c26c..04f76db 100644 --- a/src2015_04/article4_microresistivity_extraction.py +++ b/src2015_04/article4_microresistivity_extraction.py @@ -37,9 +37,7 @@ def histogram_scale(image, ref_min, ref_max): """Linear min-max histogram scaling of an image array onto [ref_min, ref_max].""" - img = np.asarray(image, float) - lo, hi = np.min(img), np.max(img) - return ref_min + (img - lo) * (ref_max - ref_min) / (hi - lo) + return petrolib.data_qc_io.scale.normalize_to_reference(image, ref_min, ref_max, pct=None) def median_curve(image_array): diff --git a/src2016_02/article3_low_permeability_measurements.py b/src2016_02/article3_low_permeability_measurements.py index 2ab578b..8656aea 100644 --- a/src2016_02/article3_low_permeability_measurements.py +++ b/src2016_02/article3_low_permeability_measurements.py @@ -112,7 +112,7 @@ def deviation_indicator(x1, x2): the fractional discrepancy used to compare permeability/porosity from different techniques. """ - return 2.0 * abs(x1 - x2) / (x1 + x2) + return float(petrolib.data_qc_io.clean.relative_discrepancy(x1, x2)) # ---------------------------------------------- tests -------------- diff --git a/src2016_12/article6_gr_normalization_haynesville.py b/src2016_12/article6_gr_normalization_haynesville.py index 722fbcd..584fe47 100644 --- a/src2016_12/article6_gr_normalization_haynesville.py +++ b/src2016_12/article6_gr_normalization_haynesville.py @@ -26,13 +26,20 @@ import numpy as np +try: + import petrolib +except ImportError: # bare clone, not installed + import sys, pathlib + sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) + import petrolib + # ---------------------------------------------- normalization -------------- def histogram_normalize(gr, gr_min, gr_max, ref_min, ref_max): """Linear histogram normalization of a GR log onto a reference [ref_min, ref_max].""" - gr = np.asarray(gr, float) - return ref_min + (gr - gr_min) * (ref_max - ref_min) / (gr_max - gr_min) + return petrolib.data_qc_io.scale.normalize_to_reference( + gr, ref_min, ref_max, in_lo=gr_min, in_hi=gr_max) def tst_projection(gr_vertical, tst_vertical, tst_query): @@ -47,8 +54,7 @@ def affine_normalize(gr_raw, target_mean, target_std): GR_norm = (GR_raw - mean)/std * target_std + target_mean. """ - gr = np.asarray(gr_raw, float) - return (gr - gr.mean()) / gr.std() * target_std + target_mean + return petrolib.data_qc_io.scale.match_moments(gr_raw, target_mean, target_std) def max_percent_shift(gr_raw, gr_norm): diff --git a/src2017_10/article5_permian_core_analysis.py b/src2017_10/article5_permian_core_analysis.py index 9efb5cf..5928f3f 100644 --- a/src2017_10/article5_permian_core_analysis.py +++ b/src2017_10/article5_permian_core_analysis.py @@ -65,7 +65,7 @@ def hydrocarbon_pore_volume(phi, sw): def relative_discrepancy(value_a, value_b): """Relative discrepancy between two method results |a - b|/mean(a, b).""" - return abs(value_a - value_b) / (0.5 * (value_a + value_b)) + return float(petrolib.data_qc_io.clean.relative_discrepancy(value_a, value_b)) # ---------------------------------------------- tests -------------- diff --git a/src2018_12/article11_data_preconditioning.py b/src2018_12/article11_data_preconditioning.py index d0a04b0..7803ae9 100644 --- a/src2018_12/article11_data_preconditioning.py +++ b/src2018_12/article11_data_preconditioning.py @@ -50,17 +50,12 @@ def zscore_outliers(x, thresh=3.0): def iqr_outliers(x, k=1.5): """Boolean mask of IQR outliers (outside Q1 - k*IQR, Q3 + k*IQR).""" - x = np.asarray(x, float) - q1, q3 = np.percentile(x, [25, 75]); iqr = q3 - q1 - return (x < q1 - k * iqr) | (x > q3 + k * iqr) + return petrolib.data_qc_io.clean.outlier_mask(x, "iqr", k=k) def impute_gaps(x): """Fill NaN gaps by linear interpolation over the index.""" - x = np.asarray(x, float).copy() - idx = np.arange(len(x)); good = ~np.isnan(x) - x[~good] = np.interp(idx[~good], idx[good], x[good]) - return x + return petrolib.data_qc_io.clean.impute_gaps(x) # ---------------------------------------------- tests -------------- diff --git a/src2019_02/article4_insitu_saturation_core_comparison.py b/src2019_02/article4_insitu_saturation_core_comparison.py index 0671275..98d67b4 100644 --- a/src2019_02/article4_insitu_saturation_core_comparison.py +++ b/src2019_02/article4_insitu_saturation_core_comparison.py @@ -60,7 +60,7 @@ def reconstruct_insitu(so_measured, sg_measured, retention): def closure(sw, so, sg): """Saturation closure residual Sw + So + Sg - 1 (should be ~0).""" - return sw + so + sg - 1.0 + return float(petrolib.data_qc_io.clean.closure_residual(sw, so, sg)) # ---------------------------------------------- tests --------------