datagenerator.Augmentation
1from scipy.interpolate import PchipInterpolator 2from scipy.interpolate import UnivariateSpline 3import numpy as np 4import math 5from scipy.ndimage import uniform_filter 6from scipy.ndimage.morphology import distance_transform_edt 7 8 9def tz_stretch(x_cube, y_cube, wb): 10 """Apply stretch/squeeze to simulate time-depth conversion 11 12 Arguments: 13 x_cube {ndarray} -- 4D array containing seismic data, 1st dimension angles 14 y_cube {ndarray} -- 3D array containing hydrocarbon labels 15 wb {ndarray} -- 2D array containing seabed horizon in samples 16 17 Returns: 18 [ndarray, ndarray] -- Stretched/squeezed seismic data and hydrocarbon labels 19 """ 20 n_cubes, x_shape, y_shape, z_shape = x_cube.shape 21 seafloor_map = uniform_filter(wb, size=(31, 31)) 22 seafloor_min = int(seafloor_map.min()) 23 24 max_squeeze_depth = np.random.triangular( 25 seafloor_map.min() * 1.2, 26 (seafloor_map.min() + z_shape) / 2.0, 27 z_shape * 0.8, 28 ) 29 max_squeeze_pct = np.random.triangular(1.05, 1.15, 1.25) 30 31 # build function between ascending indices and stretched/squeezed indices 32 # - hang from min depth for seafloor 33 raw_depth_indices = np.arange(0.0, z_shape) 34 stretched_depth_indices = raw_depth_indices.copy() 35 36 # get depth (as index) and percentage to squeeze point that is midway 37 # between seafloor and bottom of trace 38 fit_indices = np.array( 39 [seafloor_min, seafloor_min + 1.0, max_squeeze_depth, z_shape - 1, z_shape] 40 ) 41 fit_depths = np.array( 42 ( 43 seafloor_min, 44 seafloor_min + 1.0, 45 max_squeeze_depth / max_squeeze_pct, 46 z_shape - 1, 47 z_shape, 48 ) 49 ) 50 spline_interp = UnivariateSpline(fit_indices, fit_depths) 51 stretched_depth_indices[seafloor_min + 1 : z_shape - 1] = spline_interp( 52 raw_depth_indices[seafloor_min + 1 : z_shape - 1] 53 ) 54 55 output_x_cube = np.zeros_like(x_cube) 56 output_y_cube = np.zeros_like(y_cube) 57 for k in range(n_cubes): 58 for i in range(x_shape): 59 for j in range(y_shape): 60 stretch_times = raw_depth_indices.copy() 61 fit_indices_ij = fit_indices - seafloor_min + seafloor_map[i, j] 62 fit_depths_ij = fit_depths - seafloor_min + seafloor_map[i, j] 63 seafloor_ind = int(seafloor_map[i, j]) + 1 64 spline_interp = UnivariateSpline(fit_depths_ij, fit_indices_ij) 65 stretch_times[seafloor_ind : z_shape - 1] = spline_interp( 66 raw_depth_indices[seafloor_ind : z_shape - 1] 67 ) 68 output_trace = np.interp( 69 stretch_times, raw_depth_indices, x_cube[k, i, j, :] 70 ) 71 output_trace[stretch_times >= z_shape - 1.0] = 0.0 72 output_x_cube[k, i, j, :] = output_trace.copy() 73 74 if k == 0: 75 # Apply to labels 76 output_trace = np.interp( 77 stretch_times, raw_depth_indices, y_cube[i, j, :] 78 ) 79 output_trace[stretch_times >= z_shape - 1.0] = 0.0 80 output_y_cube[i, j, :] = output_trace.copy() 81 82 return output_x_cube, output_y_cube 83 84 85def uniform_stretch(x_cube, y_cube): 86 x_max, y_max, t_max = x_cube.shape[1:] 87 88 x_in = np.arange(x_max) 89 y_in = np.arange(y_max) 90 t_in = np.arange(t_max) 91 92 squeeze_min = 0.85 93 squeeze_max = 1.15 94 # Uniform r.v. squeeze factors 95 x_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 96 y_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 97 t_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 98 99 x_out = x_in * x_squeeze_factor 100 if x_squeeze_factor > 1: 101 roll_x_by = math.floor(np.sum(x_out > x_max - 1) / 2) 102 # print(roll_x_by) 103 x_out = np.roll(x_out, roll_x_by) 104 105 y_out = y_in * y_squeeze_factor 106 if y_squeeze_factor > 1: 107 roll_y_by = math.floor(np.sum(y_out > y_max - 1) / 2) 108 # print(roll_y_by) 109 y_out = np.roll(y_out, roll_y_by) 110 111 t_out = t_in * t_squeeze_factor 112 if t_squeeze_factor > 1: 113 roll_t_by = math.floor(np.sum(t_out > t_max - 1) / 2) 114 # print(roll_t_by) 115 t_out = np.roll(t_out, roll_t_by) 116 117 x_cube_sqz = np.apply_along_axis( 118 lambda w: np.interp(x_out, x_in, w, left=0, right=0), axis=1, arr=x_cube 119 ) 120 y_cube_sqz = np.apply_along_axis( 121 lambda w: np.interp(x_out, x_in, w, left=0, right=0), axis=0, arr=y_cube 122 ) 123 y_cube_sqz = np.round(y_cube_sqz) 124 125 x_cube_sqz = np.apply_along_axis( 126 lambda w: np.interp(y_out, y_in, w, left=0, right=0), axis=2, arr=x_cube_sqz 127 ) 128 y_cube_sqz = np.apply_along_axis( 129 lambda w: np.interp(y_out, y_in, w, left=0, right=0), axis=1, arr=y_cube_sqz 130 ) 131 y_cube_sqz = np.round(y_cube_sqz) 132 133 x_cube_sqz = np.apply_along_axis( 134 lambda w: np.interp(t_out, t_in, w, left=0, right=0), axis=3, arr=x_cube_sqz 135 ) 136 y_cube_sqz = np.apply_along_axis( 137 lambda w: np.interp(t_out, t_in, w, left=0, right=0), axis=2, arr=y_cube_sqz 138 ) 139 y_cube_sqz = np.round(y_cube_sqz).astype( 140 "uint8" 141 ) # convert to uint8 for writing to disk 142 143 return x_cube_sqz, y_cube_sqz
def
tz_stretch(x_cube, y_cube, wb):
10def tz_stretch(x_cube, y_cube, wb): 11 """Apply stretch/squeeze to simulate time-depth conversion 12 13 Arguments: 14 x_cube {ndarray} -- 4D array containing seismic data, 1st dimension angles 15 y_cube {ndarray} -- 3D array containing hydrocarbon labels 16 wb {ndarray} -- 2D array containing seabed horizon in samples 17 18 Returns: 19 [ndarray, ndarray] -- Stretched/squeezed seismic data and hydrocarbon labels 20 """ 21 n_cubes, x_shape, y_shape, z_shape = x_cube.shape 22 seafloor_map = uniform_filter(wb, size=(31, 31)) 23 seafloor_min = int(seafloor_map.min()) 24 25 max_squeeze_depth = np.random.triangular( 26 seafloor_map.min() * 1.2, 27 (seafloor_map.min() + z_shape) / 2.0, 28 z_shape * 0.8, 29 ) 30 max_squeeze_pct = np.random.triangular(1.05, 1.15, 1.25) 31 32 # build function between ascending indices and stretched/squeezed indices 33 # - hang from min depth for seafloor 34 raw_depth_indices = np.arange(0.0, z_shape) 35 stretched_depth_indices = raw_depth_indices.copy() 36 37 # get depth (as index) and percentage to squeeze point that is midway 38 # between seafloor and bottom of trace 39 fit_indices = np.array( 40 [seafloor_min, seafloor_min + 1.0, max_squeeze_depth, z_shape - 1, z_shape] 41 ) 42 fit_depths = np.array( 43 ( 44 seafloor_min, 45 seafloor_min + 1.0, 46 max_squeeze_depth / max_squeeze_pct, 47 z_shape - 1, 48 z_shape, 49 ) 50 ) 51 spline_interp = UnivariateSpline(fit_indices, fit_depths) 52 stretched_depth_indices[seafloor_min + 1 : z_shape - 1] = spline_interp( 53 raw_depth_indices[seafloor_min + 1 : z_shape - 1] 54 ) 55 56 output_x_cube = np.zeros_like(x_cube) 57 output_y_cube = np.zeros_like(y_cube) 58 for k in range(n_cubes): 59 for i in range(x_shape): 60 for j in range(y_shape): 61 stretch_times = raw_depth_indices.copy() 62 fit_indices_ij = fit_indices - seafloor_min + seafloor_map[i, j] 63 fit_depths_ij = fit_depths - seafloor_min + seafloor_map[i, j] 64 seafloor_ind = int(seafloor_map[i, j]) + 1 65 spline_interp = UnivariateSpline(fit_depths_ij, fit_indices_ij) 66 stretch_times[seafloor_ind : z_shape - 1] = spline_interp( 67 raw_depth_indices[seafloor_ind : z_shape - 1] 68 ) 69 output_trace = np.interp( 70 stretch_times, raw_depth_indices, x_cube[k, i, j, :] 71 ) 72 output_trace[stretch_times >= z_shape - 1.0] = 0.0 73 output_x_cube[k, i, j, :] = output_trace.copy() 74 75 if k == 0: 76 # Apply to labels 77 output_trace = np.interp( 78 stretch_times, raw_depth_indices, y_cube[i, j, :] 79 ) 80 output_trace[stretch_times >= z_shape - 1.0] = 0.0 81 output_y_cube[i, j, :] = output_trace.copy() 82 83 return output_x_cube, output_y_cube
Apply stretch/squeeze to simulate time-depth conversion
Arguments: x_cube {ndarray} -- 4D array containing seismic data, 1st dimension angles y_cube {ndarray} -- 3D array containing hydrocarbon labels wb {ndarray} -- 2D array containing seabed horizon in samples
Returns: [ndarray, ndarray] -- Stretched/squeezed seismic data and hydrocarbon labels
def
uniform_stretch(x_cube, y_cube):
86def uniform_stretch(x_cube, y_cube): 87 x_max, y_max, t_max = x_cube.shape[1:] 88 89 x_in = np.arange(x_max) 90 y_in = np.arange(y_max) 91 t_in = np.arange(t_max) 92 93 squeeze_min = 0.85 94 squeeze_max = 1.15 95 # Uniform r.v. squeeze factors 96 x_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 97 y_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 98 t_squeeze_factor = np.random.rand() * (squeeze_max - squeeze_min) + squeeze_min 99 100 x_out = x_in * x_squeeze_factor 101 if x_squeeze_factor > 1: 102 roll_x_by = math.floor(np.sum(x_out > x_max - 1) / 2) 103 # print(roll_x_by) 104 x_out = np.roll(x_out, roll_x_by) 105 106 y_out = y_in * y_squeeze_factor 107 if y_squeeze_factor > 1: 108 roll_y_by = math.floor(np.sum(y_out > y_max - 1) / 2) 109 # print(roll_y_by) 110 y_out = np.roll(y_out, roll_y_by) 111 112 t_out = t_in * t_squeeze_factor 113 if t_squeeze_factor > 1: 114 roll_t_by = math.floor(np.sum(t_out > t_max - 1) / 2) 115 # print(roll_t_by) 116 t_out = np.roll(t_out, roll_t_by) 117 118 x_cube_sqz = np.apply_along_axis( 119 lambda w: np.interp(x_out, x_in, w, left=0, right=0), axis=1, arr=x_cube 120 ) 121 y_cube_sqz = np.apply_along_axis( 122 lambda w: np.interp(x_out, x_in, w, left=0, right=0), axis=0, arr=y_cube 123 ) 124 y_cube_sqz = np.round(y_cube_sqz) 125 126 x_cube_sqz = np.apply_along_axis( 127 lambda w: np.interp(y_out, y_in, w, left=0, right=0), axis=2, arr=x_cube_sqz 128 ) 129 y_cube_sqz = np.apply_along_axis( 130 lambda w: np.interp(y_out, y_in, w, left=0, right=0), axis=1, arr=y_cube_sqz 131 ) 132 y_cube_sqz = np.round(y_cube_sqz) 133 134 x_cube_sqz = np.apply_along_axis( 135 lambda w: np.interp(t_out, t_in, w, left=0, right=0), axis=3, arr=x_cube_sqz 136 ) 137 y_cube_sqz = np.apply_along_axis( 138 lambda w: np.interp(t_out, t_in, w, left=0, right=0), axis=2, arr=y_cube_sqz 139 ) 140 y_cube_sqz = np.round(y_cube_sqz).astype( 141 "uint8" 142 ) # convert to uint8 for writing to disk 143 144 return x_cube_sqz, y_cube_sqz