Source code for pygeopressure.basic.optimizer

# -*- coding: utf-8 -*-
"""
optimizer for different models

Created on Sep 16 2018
"""
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

__author__ = "yuhao"

from builtins import bytes, str
import json
from collections import OrderedDict

import numpy as np
from scipy.optimize import curve_fit

from pygeopressure.pressure.bowers import (
    virgin_curve, invert_virgin, power_bowers)
from pygeopressure.velocity.extrapolate import normal, normal_dt
from pygeopressure.pressure.obp import traugott
from pygeopressure.basic.well import Well
from pygeopressure.basic.well_log import Log
from pygeopressure.basic.utils import rmse, pick_sparse
from pygeopressure.pressure.eaton import power_eaton
from sklearn import linear_model


[docs]def optimize_bowers_virgin(well, vel_log, obp_log, upper, lower, pres_log='loading', mode='nc', nnc=5): """ Optimizer for Bowers loading curve Parameters ---------- well : Well vel_log : Log or str Log object or well log name stored in well obp_log : Log or str Log object or well log name stored in well upper : float or str upper bound of nct, depth value or horizon name lower : float or str lower bound of nct, depth value or horizon name pres_log : Log or str Log object storing measured pressure value or Pressure name stored in well mode : {'nc', 'pres', 'both'} which pressure to use for optimization, - 'nc' : points on NCT - 'pres' : points in pres_log - 'both' : both of them nnc : int number of points to pick on NCT Returns ------- a, b : tuple of floats optimized bowers loading curve coefficients rms_err : float root mean square error of pressure """ if isinstance(upper, (bytes, str)): depth_upper = well.params['horizon'][upper] else: depth_upper = upper if isinstance(upper, (bytes, str)): depth_lower = well.params['horizon'][lower] else: depth_lower = lower if isinstance(vel_log, (bytes, str)): vel_log = well.get_log(vel_log) if isinstance(obp_log, (bytes, str)): obp_log = well.get_log(obp_log) if isinstance(pres_log, (bytes, str)): # pres_log = well.get_loading_pressure() pres_log = well.get_pressure(pres_log) depth = np.array(obp_log.depth) nct_vel_to_fit = [] nct_es_to_fit = [] pres_vel_to_fit = [] pres_es_to_fit = [] if mode == 'nct' or mode == 'both': nct_es_data = np.array(obp_log.data) - np.array(well.hydrostatic) nct_mask = depth < depth_lower nct_mask *= depth > depth_upper nct_mask *= depth < vel_log.stop nct_vel_interval = np.array(vel_log.data)[nct_mask] nct_es_interval = nct_es_data[nct_mask] nct_vel_to_fit = np.array(pick_sparse(nct_vel_interval, nnc)) nct_es_to_fit = np.array(pick_sparse(nct_es_interval, nnc)) if mode == 'pres' or mode == 'both': vel = list() obp = list() pres = list() for dp in pres_log.depth: idx = np.searchsorted(depth, dp) vel.append(vel_log.data[idx]) obp.append(obp_log.data[idx]) vel, obp, pres = np.array(vel), np.array(obp), np.array(pres_log.data) es = obp - pres pres_vel_to_fit = vel pres_es_to_fit = es vel_to_fit = np.append(nct_vel_to_fit, pres_vel_to_fit) es_to_fit = np.append(nct_es_to_fit, pres_es_to_fit) popt, _ = curve_fit(virgin_curve, es_to_fit, vel_to_fit) a, b = popt es_predicted = invert_virgin(vel_to_fit, a, b) rms_err = rmse(es_to_fit, es_predicted) return a, b, rms_err
[docs]def optimize_bowers_unloading(well, vel_log, obp_log, a, b, vmax, pres_log='unloading'): """ Optimize for Bowers Unloading curve parameter U Parameters ---------- well : Well vel_log : Log or str Log object or well log name stored in well obp_log : Log or str Log object or well log name stored in well vmax : float vmax in bowers unloading curve pres_log : Log or str Log object storing measured pressure value or Pressure name stored in well Returns ------- u : float unloading curve cofficient U error : float Relative RMS error """ if isinstance(vel_log, (bytes, str)): vel_log = well.get_log(vel_log) if isinstance(obp_log, (bytes, str)): obp_log = well.get_log(obp_log) if isinstance(pres_log, (bytes, str)): pres_log = well.get_pressure(pres_log) depth = np.array(obp_log.depth) vel = list() obp = list() pres = list() for dp in pres_log.depth: idx = np.searchsorted(depth, dp) vel.append(vel_log.data[idx]) obp.append(obp_log.data[idx]) vel, obp, pres = np.array(vel), np.array(obp), np.array(pres_log.data) es = obp - pres sigma_max = invert_virgin(vmax, a, b) sigma_vc = invert_virgin(vel, a, b) popt, _ = curve_fit(power_bowers, sigma_vc/sigma_max, es/sigma_max) u, = popt return u
[docs]def optimize_bowers_trace(depth_tr, vel_tr, obp_tr, hydro_tr, depth_upper, depth_lower): es_data = np.array(obp_tr) - np.array(hydro_tr) depth = np.array(depth_tr) mask = depth < depth_lower mask *= depth > depth_upper vel_interval = np.array(vel_tr)[mask] es_interval = es_data[mask] vel_to_fit = pick_sparse(vel_interval, 3) es_to_fit = pick_sparse(es_interval, 3) popt, _ = curve_fit(virgin_curve, es_to_fit, vel_to_fit) a, b = popt return a, b
[docs]def optimize_eaton(well, vel_log, obp_log, a, b, pres_log="loading"): """ Optimizer for Eaton model Parameters ---------- well : Well vel_log : Log or str Log object or well log name stored in well obp_log : Log or str Log object or well log name stored in well a, b : float coefficients of NCT pres_log : Log or str Log object storing measured pressure value or Pressure name stored in well Returns ------- n : float optimized eaton exponential min_eer : float minimum error abtained by optimized n rms_err : array array of rms error of different n around minmum """ if isinstance(vel_log, (bytes, str)): vel_log = well.get_log(vel_log) if isinstance(obp_log, (bytes, str)): obp_log = well.get_log(obp_log) if isinstance(pres_log, (bytes, str)): # pres_log = well.get_loading_pressure() pres_log = well.get_pressure(pres_log) depth = np.array(obp_log.depth) hydrostatic = np.array(well.hydrostatic) es_normal = np.array(obp_log.data) - hydrostatic v_normal = normal(depth, a, b) vel = list() vel_norm = list() es_norm = list() obp = list() pres = list() for dp in pres_log.depth: idx = np.searchsorted(depth, dp) vel.append(vel_log.data[idx]) vel_norm.append(v_normal[idx]) es_norm.append(es_normal[idx]) obp.append(obp_log.data[idx]) vel, vel_norm = np.array(vel), np.array(vel_norm) vel_ratio = vel / vel_norm obp, pres = np.array(obp), np.array(pres_log.data) es = obp - pres es_norm = np.array(es_norm) es_ratio = es / es_norm popt, _ = curve_fit(power_eaton, vel_ratio, es_ratio) n, = popt return n
[docs]def optimize_multivaraite(well, obp_log, vel_log, por_log, vsh_log, B, upper, lower): if isinstance(vel_log, (bytes, str)): vel_log = well.get_log(vel_log) if isinstance(por_log, (bytes, str)): por_log = well.get_log(por_log) if isinstance(vsh_log, (bytes, str)): vsh_log = well.get_log(vsh_log) if isinstance(obp_log, (bytes, str)): obp_log = well.get_log(obp_log) # -------------------------------------------- obp_data = np.array(obp_log.data) por_data = np.array(por_log.data) vp_data = np.array(vel_log.data) vsh_data = np.array(vsh_log.data) depth = well.depth hydrostatic = well.hydrostatic es = obp_data - hydrostatic B = well.params['bowers']['B'] if B is None else B # 0.88 es_data = es**B mask = np.isfinite(vp_data) mask *= np.isfinite(por_data) mask *= np.isfinite(vsh_data) mask *= depth < lower #3500 mask *= depth > upper #1500 por_data = por_data[mask] vsh_data = vsh_data[mask] es_data = es_data[mask] vp_data = vp_data[mask] depth = depth[mask] por_data = por_data.reshape((por_data.shape[0], 1)) vsh_data = vsh_data.reshape((vsh_data.shape[0], 1)) es_data = es_data.reshape((es_data.shape[0], 1)) vp_data = vp_data.reshape((vp_data.shape[0], 1)) #_____________________REGRESSION______________________ data = np.hstack((por_data, vsh_data, es_data)) # global REG reg = linear_model.LinearRegression() reg.fit(data, vp_data) r2 = reg.score(data, vp_data) a0 = reg.intercept_[0] a1 = -reg.coef_[0][0] a2 = -reg.coef_[0][1] a3 = reg.coef_[0][2] return a0, a1, a2, a3
[docs]def optimize_nct(vel_log, fit_start, fit_stop): """ Fit velocity NCT Parameters ---------- vel_log : Log Velocity log fit_start, fit_stop : float start and end depth for fitting Returns ------- a, b : float NCT coefficients """ fit_start = fit_start fit_stop = fit_stop if fit_start is None or fit_start < vel_log.top: fit_start = vel_log.top if fit_stop is None or fit_stop > vel_log.bottom: fit_stop = vel_log.bottom a, b = optimize_nct_trace( np.array(vel_log.depth), np.array(vel_log.data), fit_start, fit_stop, pick=False) return a, b
[docs]def optimize_nct_trace(depth, vel, fit_start, fit_stop, pick=True): mask = depth > fit_start mask *= depth < fit_stop mask *= np.isfinite(vel) depth_interval = np.array(depth)[mask] vel_interval = np.array(vel)[mask] if pick is True: depth_to_fit = pick_sparse(depth_interval, 3) vel_to_fit = pick_sparse(vel_interval, 3) else: depth_to_fit = depth_interval vel_to_fit = vel_interval dt = vel_to_fit**(-1) log_dt = np.log(dt) popt, _ = curve_fit(normal_dt, depth_to_fit, log_dt) a, b = popt return a, b
[docs]def optimize_traugott(den_log, fit_start, fit_stop, kb=0, wd=0): """ Fit density variation against depth with Traugott equation Parameters ---------- den_log : Log Density log fit_start, fit_stop : float start and end depth for fitting kb : float kelly bushing height in meters wd : float water depth in meters Returns ------- a, b : float Traugott equation coefficients """ start_idx = den_log.get_depth_idx(fit_start) stop_idx = den_log.get_depth_idx(fit_stop) + 1 depth = np.array(den_log.depth[start_idx: stop_idx + 1]) den = np.array(den_log.data[start_idx: stop_idx + 1]) mask = np.isfinite(den) den_finite = den[mask] depth_finite = depth[mask] depth_finite_shift = depth_finite - kb - wd popt, _ = curve_fit(traugott, depth_finite_shift, den_finite) a, b = popt return a, b