def test_kriging_mutation(interpolator, map_sequential_pile): geo_model = map_sequential_pile geo_model.set_theano_graph(interpolator) gp.compute_model(geo_model, compute_mesh=False) gp.plot.plot_2d(geo_model, cell_number=25, show_scalar=True, series_n=1, N=15, direction='y', show_data=True) print(geo_model.solutions.lith_block, geo_model._additional_data) #plt.savefig(os.path.dirname(__file__)+'/figs/test_kriging_mutation') geo_model.modify_kriging_parameters('range', 1) geo_model.modify_kriging_parameters('drift equations', [0, 3]) print(geo_model.solutions.lith_block, geo_model._additional_data) # copy dataframe before interpolator is calculated pre = geo_model._additional_data.kriging_data.df.copy() gp.set_interpolator(geo_model, compile_theano=True, theano_optimizer='fast_compile', update_kriging=False) gp.compute_model(geo_model, compute_mesh=False) gp.plot.plot_2d(geo_model, cell_number=25, series_n=1, N=15, show_boundaries=False, direction='y', show_data=True, show_lith=True) print(geo_model.solutions.lith_block, geo_model._additional_data) plt.savefig(os.path.dirname(__file__)+'/../figs/test_kriging_mutation2') assert geo_model._additional_data.kriging_data.df['range'][0] == pre['range'][0]
def test_kriging_mutation(interpolator_islith_isfault, map_sequential_pile): geo_model = map_sequential_pile geo_model.set_theano_graph(interpolator_islith_isfault) gp.compute_model(geo_model, compute_mesh=False) gp.plot.plot_scalar_field(geo_model, cell_number=25, series=1, N=15, direction='y', show_data=True) print(geo_model.solutions.lith_block, geo_model.additional_data) plt.savefig('figs/test_kriging_mutation') geo_model.modify_kriging_parameters('range', 1) geo_model.modify_kriging_parameters('drift equations', [0, 3]) print(geo_model.solutions.lith_block, geo_model.additional_data) gp.compute_model(geo_model, compute_mesh=False) gp.plot.plot_scalar_field(geo_model, cell_number=25, series=1, N=15, direction='y', show_data=True) print(geo_model.solutions.lith_block, geo_model.additional_data) plt.savefig('figs/test_kriging_mutation2')
def test_magnetics_api(): # TODO add the check geo_model = gp.create_model('test_center_grid_slicing') geo_model.set_default_surfaces() geo_model.add_surface_points(X=-1, Y=0, Z=0, surface='surface1') geo_model.add_surface_points(X=1, Y=0, Z=0, surface='surface1') geo_model.add_orientations(X=0, Y=0, Z=0, surface='surface1', pole_vector=(0, 0, 1)) geo_model.surfaces.add_surfaces_values([0.037289, 0.0297], ['susceptibility']) # needed constants mu_0 = 4.0 * np.pi * 10e-7 # magnetic permeability in free space [N/A^2] cm = mu_0 / (4.0 * np.pi) # constant for SI unit incl = 77.0653 # NOAA decl = 6.8116 B_ext = 52819.8506939139e-9 # T geo_model.set_regular_grid(extent=[-5, 5, -5, 5, -5, 5], resolution=[5, 5, 5]) geo_model.set_centered_grid(np.array([0, 0, 0]), resolution=[10, 10, 15], radio=5000) gp.set_interpolator(geo_model, output=['magnetics'], incl=incl, decl=decl) gp.compute_model(geo_model) print(geo_model.interpolator.theano_graph.lg0.get_value()) return geo_model
def test_gravity(): geo_model = gp.create_model('2-layers') gp.init_data(geo_model, extent=[0, 12, -2, 2, 0, 4], resolution=[500, 1, 500]) geo_model.add_surfaces('surface 1') geo_model.add_surfaces('surface 2') geo_model.add_surfaces('basement') dz = geo_model.grid.regular_grid.dz geo_model.surfaces.add_surfaces_values([dz, 0, 0], ['dz']) geo_model.surfaces.add_surfaces_values([2.6, 2.4, 3.2], ['density']) geo_model.add_surface_points(3, 0, 3.05, 'surface 1') geo_model.add_surface_points(9, 0, 3.05, 'surface 1') geo_model.add_surface_points(3, 0, 1.02, 'surface 2') geo_model.add_surface_points(9, 0, 1.02, 'surface 2') geo_model.add_orientations(6, 0, 4, 'surface 1', [0, 0, 1]) device_loc = np.array([[6, 0, 4]]) geo_model.set_centered_grid(device_loc, resolution=[10, 10, 100], radius=16000) gp.set_interpolator(geo_model, output=['gravity'], pos_density=2, gradient=True, theano_optimizer='fast_compile') gp.compute_model(geo_model, set_solutions=True, compute_mesh=False) print(geo_model.solutions.fw_gravity) np.testing.assert_almost_equal(geo_model.solutions.fw_gravity, np.array([-9291.8003]), decimal=4)
def one_fault_model_topo_solution(one_fault_model): one_fault_model.update_additional_data() one_fault_model.update_to_interpolator() one_fault_model.set_topography(d_z=(800, 1800)) gp.compute_model(one_fault_model) return one_fault_model
def vista_obj(self) -> vs.Vista: """Return a GemPy Vista instance with basic geomodel attached.""" from gempy.plot import vista as vs geo_model = gp.create_data( [0, 2000, 0, 2000, 0, 2000], [50, 50, 50], path_o=input_path + '/input_data/tut_chapter1' '/simple_fault_model_orientations.csv', path_i=input_path + '/input_data/tut_chapter1' '/simple_fault_model_points.csv') gp.set_series( geo_model, { "Fault_Series": 'Main_Fault', "Strat_Series": ('Sandstone_2', 'Siltstone', 'Shale', 'Sandstone_1') }) geo_model.set_is_fault(['Fault_Series']) gp.set_interpolator(geo_model) gp.compute_model(geo_model) # with open(os.path.dirname(__file__)+"input_data/geomodel_fabian_sol.p", "rb") as f: # geo_model.solutions = load(f) return vs.Vista(geo_model)
def update(self, sb_params: dict): frame = sb_params.get('frame') extent = sb_params.get('extent') ax = sb_params.get('ax') marker = sb_params.get('marker') self.lock = sb_params.get('lock_thread') self.frame = frame # Store the current frame self.vmin = frame.min() self.vmax = frame.max() scale_frame = self.grid.scale_frame(frame) _ = self.grid.update_grid(scale_frame) self.geo_model._grid.topography.values = self.grid.depth_grid data = self.grid.depth_grid[:, 2].reshape( self.geo_model._grid.topography.resolution) self.geo_model._grid.topography.values_2d[:, :, 2] = data _ = self.geo_model._grid.update_grid_values() _ = self.geo_model.update_from_grid() gempy.compute_model(self.geo_model, compute_mesh=False) if len(marker) > 0: self.modelspace_arucos = self._compute_modelspace_arucos(marker) self.set_aruco_dict(self.modelspace_arucos) ax, cmap = self.plot(ax, self.geo_model, self._model_extent) sb_params['ax'] = ax sb_params['frame'] = scale_frame sb_params['cmap'] = cmap sb_params['marker'] = self.modelspace_arucos sb_params['active_cmap'] = False sb_params['active_shading'] = False sb_params['extent'] = self._model_extent sb_params['del_contour'] = not self.show_boundary return sb_params
def update_surfaces(self, recompute=True): import time if recompute is True: try: gp.compute_model(self.model, sort_surfaces=False, compute_mesh=True) except IndexError: t = time.localtime() current_time = time.strftime("[%H:%M:%S]", t) print(current_time + 'IndexError: Model not computed. Laking data in some surface') except AssertionError: t = time.localtime() current_time = time.strftime("[%H:%M:%S]", t) print(current_time + 'AssertionError: Model not computed. Laking data in some surface') self.remove_actor(self.regular_grid_actor) surfaces = self.model._surfaces # TODO add the option of update specific surfaces try: for idx, val in surfaces.df[['vertices', 'edges', 'surface']].dropna().iterrows(): self.surface_poly[val['surface']].points = val['vertices'] self.surface_poly[val['surface']].faces = np.insert(val['edges'], 0, 3, axis=1).ravel() except KeyError: self.plot_surfaces() return True
def test_magnetics_no_regular_grid(interpolator_magnetics): # TODO add the check geo_model = gp.create_model('test_center_grid_slicing') geo_model.set_default_surfaces() geo_model.add_surface_points(X=-1, Y=0, Z=0, surface='surface1') geo_model.add_surface_points(X=1, Y=0, Z=0, surface='surface1') geo_model.add_orientations(X=0, Y=0, Z=0, surface='surface1', pole_vector=(0, 0, 1)) geo_model._surfaces.add_surfaces_values([0.037289, 0.0297], ['susceptibility']) # needed constants mu_0 = 4.0 * np.pi * 10e-7 # magnetic permeability in free space [N/A^2] cm = mu_0 / (4.0 * np.pi) # constant for SI unit incl = 77.0653 # NOAA decl = 6.8116 B_ext = 52819.8506939139e-9 # T geo_model.set_centered_grid(np.array([0, 0, 0]), resolution=[10, 10, 15], radius=5000) Vmodel = MagneticsPreprocessing(geo_model._grid.centered_grid).set_Vs_kernel() # gp.set_interpolator(geo_model, output=['magnetics']) geo_model.set_theano_function(interpolator_magnetics) geo_model._interpolator.set_theano_shared_magnetics(V= Vmodel, pos_magnetics=1, incl= incl, decl=decl, B_ext=B_ext) # geo_model.interpolator.theano_graph.V.set_value(Vmodel) # geo_model.interpolator.theano_graph.incl.set_value(incl) # geo_model.interpolator.theano_graph.decl.set_value(decl) # geo_model.interpolator.theano_graph.B_ext.set_value(B_ext) gp.compute_model(geo_model) np.testing.assert_almost_equal(geo_model.solutions.fw_magnetics, np.array([473.7836]), decimal=4) gp.compute_model(geo_model) return geo_model
def test_pile_geomodel_2(): ve = 3 extent = [451e3, 456e3, 6.7820e6, 6.7840e6, -2309 * ve, -1651 * ve] geo_model = gp.create_model('Topology-Gullfaks') gp.init_data(geo_model, extent, [30, 30, 30], path_o=input_path + "/filtered_orientations.csv", path_i=input_path + "/filtered_surface_points.csv", default_values=True) series_distribution = { "fault3": "fault3", "fault4": "fault4", "unconformity": "BCU", "sediments": ("tarbert", "ness", "etive"), } gp.map_series_to_surfaces(geo_model, series_distribution, remove_unused_series=True) geo_model.reorder_series( ["unconformity", "fault3", "fault4", "sediments", "Basement"]) geo_model.set_is_fault(["fault3"]) geo_model.set_is_fault(["fault4"]) rel_matrix = np.array([[0, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) geo_model.set_fault_relation(rel_matrix) surf_groups = pd.read_csv(input_path + "/filtered_surface_points.csv").group geo_model.surface_points.df["group"] = surf_groups orient_groups = pd.read_csv(input_path + "/filtered_orientations.csv").group geo_model.orientations.df["group"] = orient_groups geo_model.surface_points.df.reset_index(inplace=True, drop=True) geo_model.orientations.df.reset_index(inplace=True, drop=True) gp.set_interpolator(geo_model, verbose=['mask_matrix_loop', 'mask_e', 'nsle']) gp.compute_model(geo_model) gp.plot.plot_section(geo_model, cell_number=25, direction='y', show_data=True) from gempy.plot.plot_api import plot_2d p = plot_2d(geo_model, cell_number=[25]) plt.savefig(os.path.dirname(__file__) + '/../figs/test_pile_lith_block') return geo_model
def test_magnetics_api(interpolator_magnetics): # TODO add the check geo_model = gp.create_model('test_center_grid_slicing') geo_model.set_default_surfaces() geo_model.add_surface_points(X=-1, Y=0, Z=0, surface='surface1') geo_model.add_surface_points(X=1, Y=0, Z=0, surface='surface1') geo_model.add_orientations(X=0, Y=0, Z=0, surface='surface1', pole_vector=(0, 0, 1)) geo_model._surfaces.add_surfaces_values([0.037289, 0.0297], ['susceptibility']) # needed constants mu_0 = 4.0 * np.pi * 10e-7 # magnetic permeability in free space [N/A^2] cm = mu_0 / (4.0 * np.pi) # constant for SI unit incl = 77.0653 # NOAA decl = 6.8116 B_ext = 52819.8506939139e-9 # T geo_model.set_regular_grid(extent=[-5, 5, -5, 5, -5, 5], resolution=[5, 5, 5]) geo_model.set_centered_grid(np.array([[0, 0, 0]]), resolution=[10, 10, 15], radius=5000) geo_model.set_theano_function(interpolator_magnetics) geo_model._interpolator.set_theano_shared_magnetics(V='auto', pos_magnetics=1, incl= incl, decl=decl, B_ext=B_ext) gp.compute_model(geo_model) print(geo_model._interpolator.theano_graph.lg0.get_value()) print(geo_model.solutions.fw_magnetics) np.testing.assert_almost_equal(geo_model.solutions.fw_magnetics, np.array([473.7836]), decimal=4) return geo_model
def test_gravity(interpolator_gravity): geo_model = gp.create_model('2-layers') gp.init_data(geo_model, extent=[0, 12, -2, 2, 0, 4], resolution=[500, 1, 500]) geo_model.add_surfaces('surface 1') geo_model.add_surfaces('surface 2') geo_model.add_surfaces('basement') dz = geo_model._grid.regular_grid.dz geo_model._surfaces.add_surfaces_values([dz, 0, 0], ['dz']) geo_model._surfaces.add_surfaces_values([2.6, 2.4, 3.2], ['density']) geo_model.add_surface_points(3, 0, 3.05, 'surface 1') geo_model.add_surface_points(9, 0, 3.05, 'surface 1') geo_model.add_surface_points(3, 0, 1.02, 'surface 2') geo_model.add_surface_points(9, 0, 1.02, 'surface 2') geo_model.add_orientations(6, 0, 4, 'surface 1', [0, 0, 1]) device_loc = np.array([[6, 0, 4]]) geo_model.set_centered_grid(device_loc, resolution=[10, 10, 100], radius=16000) geo_model.set_theano_function(interpolator_gravity) geo_model._interpolator.set_theano_shared_gravity(pos_density=2) print(geo_model._additional_data) gp.compute_model(geo_model, set_solutions=True, compute_mesh=False) print(geo_model.solutions.fw_gravity) np.testing.assert_almost_equal(geo_model.solutions.fw_gravity, np.array([-1624.1714]), decimal=4)
def test_compute_model(interpolator_islith_isfault, map_sequential_pile): geo_model = map_sequential_pile geo_model.set_theano_graph(interpolator_islith_isfault) gp.compute_model(geo_model, compute_mesh=False) test_values = [45, 150, 2500] if False: np.save(input_path + '/test_integration_lith_block.npy', geo_model.solutions.lith_block[test_values]) # Load model real_sol = np.load(input_path + '/test_integration_lith_block.npy') # We only compare the block because the absolute pot field I changed it np.testing.assert_array_almost_equal(np.round( geo_model.solutions.lith_block[test_values]), real_sol, decimal=0) gp.plot.plot_section(geo_model, cell_number=25, direction='y', show_data=True) plt.savefig( os.path.dirname(__file__) + '/../figs/test_integration_lith_block') gp.plot.plot_scalar_field(geo_model, cell_number=25, series=1, N=15, direction='y', show_data=True) plt.savefig(os.path.dirname(__file__) + '/../figs/test_integration_scalar')
def test_load_model_compressed_remote2(): model_file = pooch.retrieve(url="https://github.com/cgre-aachen/gempy_data/raw/master/" "data/gempy_models/Onlap_relations.zip", known_hash=None) geo_model = gp.load_model(name='Onlap_relations', path=model_file, recompile=True) gp.compute_model(geo_model) gp.plot_3d(geo_model, image=True)
def test_center_grid_slicing(test_magnetics_no_regular_grid): geo_model = test_magnetics_no_regular_grid geo_model.set_centered_grid(np.array([[0, 0, 0], [1, 1, 1]]), resolution=[10, 10, 15], radius=5000) gp.compute_model(geo_model) print(geo_model._interpolator.theano_graph.lg0.get_value())
def __init__(self, model, extent=None, associated_calibration=None, xy_isometric=True, lock=None): self.id = next(self._ids) self.__class__._instances.append(weakref.proxy(self)) self.xy_isometric = xy_isometric self.scale = [None, None, None] self.pixel_size = [None, None] self.output_res = None self.legend = True self.model = model gempy.compute_model(self.model) self.empty_depth_grid = None self.depth_grid = None self.cmap = None self.norm = None self.lot = None self.contours = True self.main_contours = numpy.arange(0, 5000, 100) self.sub_contours = numpy.arange(0, 5000, 25) self.scalar_contours = False self.scalar_main_contours = numpy.arange(0.0, 1.0, 0.1) self.scalar_sub_contours = numpy.arange(0.0, 1.0, 0.02) self.show_faults = True self.fault_contours = numpy.arange(0.5, 50.5, 1.0) self.stop_threat = False self.lock = lock self.delay = 0.0 self.show_framerate = False if associated_calibration is None: try: self.associated_calibration = Calibration._instances[-1] print( "no calibration specified, using last calibration instance created: ", self.associated_calibration) except: print( "ERROR: no calibration instance found. please create a calibration" ) # parameters from the model: else: self.associated_calibration = associated_calibration if extent is None: # extent should be array with shape (6,) or convert to list? self.extent = self.model.grid.extent else: self.extent = extent # check: array with 6 entries!
def model_horizontal_two_layers(interpolator): geo_model = gp.create_model('interpolator') # Importing the data from csv files and settign extent and resolution gp.init_data(geo_model, [0, 10, 0, 10, -10, 0], [50, 50, 50], path_o=input_path + "/GeoModeller/test_a/test_a_Foliations.csv", path_i=input_path + "/GeoModeller/test_a/test_a_Points.csv") geo_model.set_theano_function(interpolator) gp.compute_model(geo_model) return geo_model
def section_model(one_fault_model_topo_solution): geo_model = one_fault_model_topo_solution section_dict = {'section_SW-NE': ([250, 250], [1750, 1750], [100, 100]), 'section_NW-SE': ([250, 1750], [1750, 250], [100, 100])} geo_model.set_section_grid(section_dict) geo_model.set_active_grid('sections', reset=False) one_fault_model_topo_solution.update_additional_data() one_fault_model_topo_solution.update_to_interpolator() gp.compute_model(geo_model, sort_surfaces=False) return geo_model
def vista_object_computed_topo(self, one_fault_model_solution): """ Args: one_fault_model_solution: """ from gempy.plot.vista import GemPyToVista one_fault_model_solution.update_additional_data() one_fault_model_solution.update_to_interpolator() one_fault_model_solution.set_topography() gp.compute_model(one_fault_model_solution) return GemPyToVista(one_fault_model_solution, plotter_type='basic', off_screen=True)
def test_ch3_b(theano_f): geo_data = gp.read_pickle(os.path.dirname(__file__)+"/ch3-pymc2_tutorial_geo_data.pickle") # Check the stratigraphic pile for correctness: gp.get_sequential_pile(geo_data) # Then we can then compile the GemPy modeling function: #interp_data = gp.InterpolatorData(geo_data, u_grade=[1]) interp_data = theano_f interp_data.update_interpolator(geo_data) # Now we can reproduce the original model: lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(geo_data, lith_block[0], 0) # But of course we want to look at the perturbation results. We have a class for that: import gempy.posterior_analysis dbname = os.path.dirname(__file__)+"/ch3-pymc2.hdf5" post = gempy.posterior_analysis.Posterior(dbname) post.change_input_data(interp_data, 80) lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(interp_data.geo_data_res, lith_block[0], 2, plot_data=True) post.change_input_data(interp_data, 15) lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(interp_data.geo_data_res, lith_block[0], 2, plot_data=True) post.change_input_data(interp_data, 95) lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(geo_data, lith_block[0], 2) ver, sim = gp.get_surfaces(interp_data, lith_block[1], None, original_scale= True)
def test_2d_from_gempy_to_NURBS_NOT_WORKING(): geo_model = create_gempy_model(resolution=[5, 5, 5]) extent = geo_model.grid.regular_grid.extent section_dict = { 'section1': ([extent[0], extent[2] / 2], [extent[1], extent[3] / 2], [50, 50]) } geo_model.set_section_grid(section_dict) gp.compute_model(geo_model) plot_pathdict(geo_model, 'section1') from pygeoiga.nurb.gempy_to_NURBS import extract_control_points_from_cross_section control_points = extract_control_points_from_cross_section( geo_model, 'section1') plot_2d_control_points(control_points)
def test_compute_model(self, interpolator_islith_isfault, geo_model): geo_model.set_theano_function(interpolator_islith_isfault) sol = gp.compute_model(geo_model) print(interpolator_islith_isfault) print(sol) return sol
def compute_posterior_models_all(db, interp_data, indices, u_grade=None, get_potential_at_interfaces=False): """Computes block models from stored input parameters for all iterations. Args: db (): loaded pymc database (e.g. hdf5) interp_data (gp.data_management.InterpolatorData): GemPy interpolator object indices (list or np.array): Trace indices specifying which models from the database will be calculated. u_grade (list, optional): get_potential_at_interfaces: Returns: """ for i in tqdm.tqdm(indices): interp_data_loop = change_input_data(db, interp_data, i) lb, fb = gp.compute_model(interp_data_loop, output="geology", u_grade=u_grade, get_potential_at_interfaces=get_potential_at_interfaces) if i == 0 or i == indices[0]: lbs = np.expand_dims(lb, 0) fbs = np.expand_dims(fb, 0) else: lbs = np.concatenate((lbs, np.expand_dims(lb, 0)), axis=0) fbs = np.concatenate((fbs, np.expand_dims(fb, 0)), axis=0) return lbs, fbs
def test_b(self, theano_f): """ Two layers a bit curvy, drift degree 1 """ # Importing the data from csv files and settign extent and resolution geo_data = gempy.create_data([0, 10, 0, 10, -10, 0], [50, 50, 50], path_o=input_path+"/GeoModeller/test_b/test_b_Foliations.csv", path_i=input_path+"/GeoModeller/test_b/test_b_Points.csv") interp_data = theano_f # Updating the interp data which has theano compiled interp_data.update_interpolator(geo_data, u_grade=[1]) gempy.get_kriging_parameters(interp_data, verbose=1) # Compute model sol = gempy.compute_model(interp_data) gempy.plot_section(geo_data, sol[0][0, :], 25, direction='y', plot_data=True) plt.savefig(os.path.dirname(__file__)+'/figs/test_b.png', dpi=200) if False: np.save(input_path + '/test_b_sol.npy', sol) # Load model real_sol = np.load(input_path + '/test_b_sol.npy') # Checking that the plots do not rise errors gempy.plot_section(geo_data, sol[0][0, :], 25, direction='y', plot_data=True) gempy.plot_scalar_field(geo_data, sol[0][1, :], 25) # We only compare the block because the absolute pot field I changed it np.testing.assert_array_almost_equal(np.round(sol[0][0, :]), real_sol[0][0, :], decimal=0)
def test_compute_model_multiple_ranges(self, interpolator): # Importing the data from csv files and settign extent and resolution geo_data = gempy.create_data( extent=[0, 2000, 0, 2000, -2000, 0], resolution=[50, 50, 50], path_o=input_path + "/GeoModeller/test_f/test_f_Foliations.csv", path_i=input_path + "/GeoModeller/test_f/test_f_Points.csv") gempy.map_stack_to_surfaces( geo_data, { 'fault1': 'MainFault', 'series': ('Reservoir', 'Seal', 'SecondaryReservoir', 'NonReservoirDeep'), }, ) geo_data.set_theano_function(interpolator) geo_data.set_is_fault('fault1') geo_data.modify_kriging_parameters('range', [3000, 3500, 0]) geo_data._additional_data.kriging_data.set_default_c_o() # Compute model sol = gempy.compute_model(geo_data, sort_surfaces=True) gempy.plot.plot_2d(geo_data, cell_number=25, direction='y', show_data=True) plt.show()
def gempy_model(value=0, input_data=input_data, verbose=True): # modify input data values accordingly interp_data.geo_data_res.interfaces[["X", "Y", "Z"]] = input_data[0] # Gx, Gy, Gz are just used for visualization. The theano function gets azimuth dip and polarity!!! interp_data.geo_data_res.orientations[[ "G_x", "G_y", "G_z", "X", "Y", "Z", 'dip', 'azimuth', 'polarity' ]] = input_data[1] try: # try to compute model lb, fb = gp.compute_model(interp_data) if True: gp.plot_section(interp_data.geo_data_res, lb[0], 0, plot_data=True) return lb, fb except np.linalg.linalg.LinAlgError as err: # if it fails (e.g. some input data combinations could lead to # a singular matrix and thus break the chain) return an empty model # with same dimensions (just zeros) if verbose: print("Exception occured.") return np.zeros_like(lith_block), np.zeros_like(fault_block)
def geo_model(self, model_horizontal_two_layers): geo_data = model_horizontal_two_layers # Compute model sol = gempy.compute_model(geo_data, compute_mesh_options={'rescale': True}) return geo_data
def test_e(self, theano_f_1f): """ Two layers a bit curvy, 1 fault """ # Importing the data from csv files and settign extent and resolution geo_data = gempy.create_data([0, 10, 0, 10, -10, 0], [50, 50, 50], path_o=input_path+"/GeoModeller/test_e/test_e_Foliations.csv", path_i=input_path+"/GeoModeller/test_e/test_e_Points.csv") gempy.set_series(geo_data, {'series': ('A', 'B'), 'fault1': 'f1'}, order_series=['fault1', 'series'], order_formations=['f1','A','B'], verbose=0) interp_data = theano_f_1f # Updating the interp data which has theano compiled interp_data.update_interpolator(geo_data, u_grade=[1, 1]) # Compute model sol = gempy.compute_model(interp_data) if False: np.save(input_path + '/test_e_sol.npy', sol) gempy.plot_section(geo_data, sol[0][0, :], 25, direction='y', plot_data=True) plt.savefig(os.path.dirname(__file__)+'/figs/test_e.png', dpi=200) # Load model real_sol = np.load(input_path + '/test_e_sol.npy') # We only compare the block because the absolute pot field I changed it np.testing.assert_array_almost_equal(np.round(sol[0][0, :]), real_sol[0][0, :], decimal=0)
def update_surfaces_real_time(self, delete=True): try: gp.compute_model(self.model, sort_surfaces=False, compute_mesh=True) except IndexError: print( 'IndexError: Model not computed. Laking data in some surface') except AssertionError: print( 'AssertionError: Model not computed. Laking data in some surface' ) self.update_surfaces() return True
def plot_section(self, iteration=1, block='lith', cell_number=3, **kwargs): '''kwargs: gempy.plotting.plot_section keyword arguments''' self._change_input_data(iteration) lith_block, fault_block = gp.compute_model(self.interp_data) if 'topography' not in kwargs: if self.topography: topography = self.topography else: topography = None if block == 'lith': gp.plot_section(self.geo_data, lith_block[0], cell_number=cell_number, topography=topography, **kwargs) else: gp.plot_section(self.geo_data, block, cell_number=cell_number, topography=topography, **kwargs) else: if block == 'lith': gp.plot_section(self.geo_data, lith_block[0], cell_number=cell_number, **kwargs) else: gp.plot_section(self.geo_data, block, cell_number=cell_number, **kwargs)
def compute_posterior_models_all(db, interp_data, indices, u_grade=None, get_potential_at_interfaces=False): """Computes block models from stored input parameters for all iterations. Args: db (): loaded pymc database (e.g. hdf5) interp_data (gp.data_management.InterpolatorData): GemPy interpolator object indices (list or np.array): Trace indices specifying which models from the database will be calculated. u_grade (list, optional): get_potential_at_interfaces: Returns: """ for i in tqdm.tqdm(indices): interp_data_loop = change_input_data(db, interp_data, i) lb, fb = gp.compute_model( interp_data_loop, output="geology", u_grade=u_grade, get_potential_at_interfaces=get_potential_at_interfaces) if i == 0 or i == indices[0]: lbs = np.expand_dims(lb, 0) fbs = np.expand_dims(fb, 0) else: lbs = np.concatenate((lbs, np.expand_dims(lb, 0)), axis=0) fbs = np.concatenate((fbs, np.expand_dims(fb, 0)), axis=0) return lbs, fbs
def test_custom_grid_solution(interpolator_islith_nofault): """ Integration test for a gempy model using a custom grid 2 Horizontal layers with drift 0 :param interpolator_islith_nofault: :return: """ # Importing the data from csv files and settign extent and resolution geo_model = gempy.create_data([0, 10, 0, 10, -10, 0], [10, 10, 10], path_o=input_path + "/GeoModeller/test_a/test_a_Foliations.csv", path_i=input_path + "/GeoModeller/test_a/test_a_Points.csv") # add a custom grid cg = np.array([[5, 5, -9], [5, 5, -5], [5, 5, -5.1], [5, 5, -5.2], [5, 5, -1]]) values = geo_model.set_custom_grid(cg) assert geo_model.grid.active_grids[1] # set the theano function geo_model.set_theano_function(interpolator_islith_nofault) # Compute model sol = gempy.compute_model(geo_model, compute_mesh=False) assert sol.custom.shape == (2,1,5)
def test_ch2(theano_f): # Importing the data from csv files and settign extent and resolution geo_data = gp.create_data([696000,747000,6863000,6930000,-20000, 200], [50, 50, 50], path_o=input_path+"/input_data/tut_SandStone/SandStone_Foliations.csv", path_i=input_path+"/input_data/tut_SandStone/SandStone_Points.csv") gp.plotting.plot_data(geo_data, direction='z') # Assigning series to formations as well as their order (timewise) gp.set_series(geo_data, {"EarlyGranite_Series": 'EarlyGranite', "BIF_Series":('SimpleMafic2', 'SimpleBIF'), "SimpleMafic_Series":'SimpleMafic1'}, order_series = ["EarlyGranite_Series", "BIF_Series", "SimpleMafic_Series"], order_formations= ['EarlyGranite', 'SimpleMafic2', 'SimpleBIF', 'SimpleMafic1'], verbose=1) # interp_data = gp.InterpolatorData(geo_data, theano_optimizer='fast_run', # compile_theano=True, verbose=[]) interp_data = theano_f interp_data.update_interpolator(geo_data) lith_block, fault_block = gp.compute_model(interp_data) import matplotlib.pyplot as plt gp.plot_section(geo_data, lith_block[0], -2, plot_data=True, direction='z') fig = plt.gcf() fig.set_size_inches(18.5, 10.5) gp.plot_section(geo_data, lith_block[0],25, plot_data=True, direction='x') fig = plt.gcf() fig.set_size_inches(18.5, 10.5) # In[14]: gp.plot_scalar_field(geo_data, lith_block[1], 11, cmap='viridis', N=100) import matplotlib.pyplot as plt plt.colorbar(orientation='horizontal') vertices, simplices = gp.get_surfaces(interp_data, lith_block[1], None, original_scale=False) pyevtk = pytest.importorskip("pyevtk") gp.export_to_vtk(geo_data, path=os.path.dirname(__file__)+'/vtk_files', lith_block=lith_block[0], vertices=vertices, simplices=simplices)
def test_f(self, theano_f_1f): """ Two layers a bit curvy, 1 fault. Checked with geomodeller """ # Importing the data from csv files and settign extent and resolution geo_data = gempy.create_data([0, 2000, 0, 2000, -2000, 0], [50, 50, 50], path_o=input_path+"/GeoModeller/test_f/test_f_Foliations.csv", path_i=input_path+"/GeoModeller/test_f/test_f_Points.csv") gempy.set_series(geo_data, {'series': ('Reservoir', 'Seal', 'SecondaryReservoir', 'NonReservoirDeep' ), 'fault1': 'MainFault'}, order_series=['fault1', 'series'], order_formations=['MainFault', 'SecondaryReservoir', 'Seal', 'Reservoir', 'NonReservoirDeep'], verbose=0) interp_data = theano_f_1f # Updating the interp data which has theano compiled interp_data.update_interpolator(geo_data, u_grade=[1, 1]) # Compute model sol = gempy.compute_model(interp_data) if False: np.save(input_path + '/test_f_sol.npy', sol) real_sol = np.load(input_path + '/test_f_sol.npy') gempy.plot_section(geo_data, sol[0][0, :], 25, direction='y', plot_data=True) plt.savefig(os.path.dirname(__file__)+'/figs/test_f.png', dpi=200) # We only compare the block because the absolute pot field I changed it np.testing.assert_array_almost_equal(np.round(sol[0][0, :]), real_sol[0][0, :], decimal=0) ver, sim = gempy.get_surfaces(interp_data, sol[0][1], sol[1][1], original_scale=True)
def test_ch6(theano_f_1f): # initialize geo_data object geo_data = gp.create_data([0, 3000, 0, 20, 0, 2000], resolution=[50, 3, 67]) # import data points geo_data.import_data_csv(input_path+"/input_data/tut_chapter6/ch6_data_interf.csv", input_path+"/input_data/tut_chapter6/ch6_data_fol.csv") gp.set_series(geo_data, {"fault":geo_data.get_formations()[np.where(geo_data.get_formations()=="Fault")[0][0]], "Rest":np.delete(geo_data.get_formations(), np.where(geo_data.get_formations()=="Fault")[0][0])}, order_series = ["fault", "Rest"], verbose=0, order_formations=['Fault','Layer 2', 'Layer 3', 'Layer 4', 'Layer 5']) gp.plot_data(geo_data) plt.xlim(0,3000) plt.ylim(0,2000); interp_data = gp.InterpolatorData(geo_data, u_grade=[0,1]) lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(geo_data, lith_block[0], 0) G, centroids, labels_unique, lith_to_labels_lot, labels_to_lith_lot = gp.topology_compute( geo_data, lith_block[0], fault_block) gp.plot_section(geo_data, lith_block[0], 0, direction='y') gp.plot_topology(geo_data, G, centroids) lith_to_labels_lot["4"].keys() gp.topology.check_adjacency(G, 8, 3) G.adj[8] G.adj[8][2]["edge_type"]
def gempy_model(value=0, input_data=input_data, verbose=True): # modify input data values accordingly interp_data.geo_data_res.interfaces[["X", "Y", "Z"]] = input_data[0] # Gx, Gy, Gz are just used for visualization. The theano function gets azimuth dip and polarity!!! interp_data.geo_data_res.orientations[["G_x", "G_y", "G_z", "X", "Y", "Z", 'dip', 'azimuth', 'polarity']] = input_data[1] try: # try to compute model lb, fb = gp.compute_model(interp_data) if True: gp.plot_section(interp_data.geo_data_res, lb[0], 0, plot_data=True) return lb, fb except np.linalg.linalg.LinAlgError as err: # if it fails (e.g. some input data combinations could lead to # a singular matrix and thus break the chain) return an empty model # with same dimensions (just zeros) if verbose: print("Exception occured.") return np.zeros_like(lith_block), np.zeros_like(fault_block)
def test_ch1(theano_f_1f): # Importing the data from CSV-files and setting extent and resolution geo_data = gp.create_data([0, 2000, 0, 2000, 0, 2000], [50, 50, 50], path_o=input_path+'/input_data/tut_chapter1/simple_fault_model_orientations.csv', path_i=input_path+'/input_data/tut_chapter1/simple_fault_model_points.csv') gp.get_data(geo_data) # Assigning series to formations as well as their order (timewise) gp.set_series(geo_data, {"Fault_Series":'Main_Fault', "Strat_Series": ('Sandstone_2','Siltstone', 'Shale', 'Sandstone_1')}, order_series = ["Fault_Series", 'Strat_Series'], order_formations=['Main_Fault', 'Sandstone_2','Siltstone', 'Shale', 'Sandstone_1', ], verbose=0) gp.get_sequential_pile(geo_data) print(gp.get_grid(geo_data)) gp.get_data(geo_data, 'interfaces').head() gp.get_data(geo_data, 'orientations') gp.plot_data(geo_data, direction='y') # interp_data = gp.InterpolatorData(geo_data, u_grade=[1,1], # output='geology', compile_theano=True, # theano_optimizer='fast_compile', # verbose=[]) interp_data = theano_f_1f interp_data.update_interpolator(geo_data) gp.get_kriging_parameters(interp_data) # Maybe move this to an extra part? lith_block, fault_block = gp.compute_model(interp_data) gp.plot_section(geo_data, lith_block[0], cell_number=25, direction='y', plot_data=True) gp.plot_scalar_field(geo_data, lith_block[1], cell_number=25, N=15, direction='y', plot_data=False) gp.plot_scalar_field(geo_data, lith_block[1], cell_number=25, N=15, direction='z', plot_data=False) gp.plot_section(geo_data, fault_block[0], cell_number=25, plot_data=True, direction='y') gp.plot_scalar_field(geo_data, fault_block[1], cell_number=25, N=20, direction='y', plot_data=False) ver, sim = gp.get_surfaces(interp_data,lith_block[1], fault_block[1], original_scale=True) # Cropping a cross-section to visualize in 2D #REDO this part? bool_b = np.array(ver[1][:,1] > 999)* np.array(ver[1][:,1] < 1001) bool_r = np.array(ver[1][:,1] > 1039)* np.array(ver[1][:,1] < 1041) # Plotting section gp.plot_section(geo_data, lith_block[0], 25, plot_data=True) ax = plt.gca() # Adding grid ax.set_xticks(np.linspace(0, 2000, 100, endpoint=False)) ax.set_yticks(np.linspace(0, 2000, 100, endpoint=False)) plt.grid() plt.ylim(1000,1600) plt.xlim(500,1100) # Plotting vertices ax.plot(ver[1][bool_r][:, 0], ver[1][bool_r][:, 2], '.', color='b', alpha=.9) ax.get_xaxis().set_ticklabels([]) ver_s, sim_s = gp.get_surfaces(interp_data,lith_block[1], fault_block[1], original_scale=True)
def test_ch5(theano_f_grav, theano_f): # Importing the data from csv files and settign extent and resolution geo_data = gp.create_data([696000,747000,6863000,6950000,-20000, 200],[50, 50, 50], path_o = input_path+"/input_data/tut_SandStone/SandStone_Foliations.csv", path_i = input_path+"/input_data/tut_SandStone/SandStone_Points.csv") # Assigning series to formations as well as their order (timewise) gp.set_series(geo_data, {"EarlyGranite_Series": 'EarlyGranite', "BIF_Series":('SimpleMafic2', 'SimpleBIF'), "SimpleMafic_Series":'SimpleMafic1'}, order_series = ["EarlyGranite_Series", "BIF_Series", "SimpleMafic_Series"], order_formations= ['EarlyGranite', 'SimpleMafic2', 'SimpleBIF', 'SimpleMafic1'], verbose=1) gp.plot_data(geo_data) #interp_data = gp.InterpolatorData(geo_data, compile_theano=True) interp_data = theano_f interp_data.update_interpolator(geo_data) lith_block, fault_block = gp.compute_model(interp_data) import matplotlib.pyplot as plt gp.plot_section(geo_data, lith_block[0], 10, plot_data=True, direction='y') fig = plt.gcf() fig.set_size_inches(18.5, 10.5) from matplotlib.patches import Rectangle currentAxis = plt.gca() currentAxis.add_patch(Rectangle((7.050000e+05, 6863000), 747000 - 7.050000e+05, 6925000 - 6863000, alpha=0.3, fill='none', color ='green' )) ver_s, sim_s = gp.get_surfaces(interp_data, lith_block[1], None, original_scale=True) # gp.plot_surfaces_3D_real_time(interp_data, ver_s, sim_s) # Importing the data from csv files and settign extent and resolution geo_data_extended = gp.create_data([696000-10000, 747000 + 20600, 6863000 - 20600,6950000 + 20600, -20000, 600], [50, 50, 50], path_o=input_path + "/input_data/tut_SandStone/SandStone_Foliations.csv", path_i=input_path + "/input_data/tut_SandStone/SandStone_Points.csv") # Assigning series to formations as well as their order (timewise) gp.set_series(geo_data_extended, {"EarlyGranite_Series": 'EarlyGranite', "BIF_Series":('SimpleMafic2', 'SimpleBIF'), "SimpleMafic_Series":'SimpleMafic1'}, order_series = ["EarlyGranite_Series", "BIF_Series", "SimpleMafic_Series"], order_formations= ['EarlyGranite', 'SimpleMafic2', 'SimpleBIF', 'SimpleMafic1'], verbose=1) # interp_data_extended = gp.InterpolatorData(geo_data_extended, output='geology', # compile_theano=True) interp_data_extended = interp_data interp_data_extended.update_interpolator(geo_data_extended) geo_data_extended.set_formations(formation_values=[2.61,2.92,3.1,2.92,2.61], formation_order=['EarlyGranite', 'SimpleMafic2', 'SimpleBIF', 'SimpleMafic1', 'basement']) lith_ext, fautl = gp.compute_model(interp_data_extended) import matplotlib.pyplot as plt gp.plot_section(geo_data_extended, lith_ext[0], -1, plot_data=True, direction='z') fig = plt.gcf() fig.set_size_inches(18.5, 10.5) from matplotlib.patches import Rectangle currentAxis = plt.gca() currentAxis.add_patch(Rectangle((7.050000e+05, 6863000), 747000 - 7.050000e+05, 6925000 - 6863000, alpha=0.3, fill='none', color ='green' )) interp_data_grav = theano_f_grav interp_data_grav.update_interpolator(geo_data_extended) gp.set_geophysics_obj(interp_data_grav, [7.050000e+05,747000,6863000,6925000,-20000, 200], [10, 10],) gp.precomputations_gravity(interp_data_grav, 10) lith, fault, grav = gp.compute_model(interp_data_grav, 'gravity') import matplotlib.pyplot as plt plt.imshow(grav.reshape(10, 10), cmap='viridis', origin='lower', extent=[7.050000e+05,747000,6863000,6950000] ) plt.colorbar()
def test_ch3_a(theano_f): # set cube size and model extent cs = 50 extent = (3000, 200, 2000) # (x, y, z) res = (120, 4, 80) # initialize geo_data object geo_data = gp.create_data([0, extent[0], 0, extent[1], 0, extent[2]], resolution=[res[0], # number of voxels res[1], res[2]]) geo_data.set_interfaces(pn.read_csv(input_path+"/input_data/tut_chapter3/tutorial_ch3_interfaces", index_col="Unnamed: 0"), append=True) geo_data.set_orientations(pn.read_csv(input_path+"/input_data/tut_chapter3/tutorial_ch3_foliations", index_col="Unnamed: 0")) # let's have a look at the upper five interface data entries in the dataframe gp.get_data(geo_data, 'interfaces', verbosity=1).head() # Original pile gp.get_sequential_pile(geo_data) # Ordered pile gp.set_order_formations(geo_data, ['Layer 2', 'Layer 3', 'Layer 4','Layer 5']) gp.get_sequential_pile(geo_data) # and at all of the foliation data gp.get_data(geo_data, 'orientations', verbosity=0) gp.plot_data(geo_data, direction="y") plt.xlim(0,3000) plt.ylim(0,2000); gp.data_to_pickle(geo_data, os.path.dirname(__file__)+"/ch3-pymc2_tutorial_geo_data") #interp_data = gp.InterpolatorData(geo_data, u_grade=[1], compile_theano=True) interp_data = theano_f interp_data.update_interpolator(geo_data) # Afterwards we can compute the geological model lith_block, fault_block = gp.compute_model(interp_data) # And plot a section: gp.plot_section(geo_data, lith_block[0], 2, plot_data = True) import pymc # Checkpoint in case you did not execute the cells above geo_data = gp.read_pickle(os.path.dirname(__file__)+"/ch3-pymc2_tutorial_geo_data.pickle") gp.get_data(geo_data, 'orientations', verbosity=1).head() # So let's assume the vertical location of our layer interfaces is uncertain, and we want to represent this # uncertainty by using a normal distribution. To define a normal distribution, we need a mean and a measure # of deviation (e.g. standard deviation). For convenience the input data is already grouped by a "group_id" value, # which allows us to collectively modify data that belongs together. In this example we want to treat the vertical # position of each layer interface, on each side of the anticline, as uncertain. Therefore, we want to perturbate # the respective three points on each side of the anticline collectively. # These are our unique group id's, the number representing the layer, and a/b the side of the anticline. group_ids = geo_data.interfaces["group_id"].dropna().unique() print(group_ids) # As a reminder, GemPy stores data in two main objects, an InputData object (called geo_data in the tutorials) and # a InpterpolatorInput object (interp_data) in tutorials. geo_data contains the original data while interp_data the # data prepared (and compiled) to compute the 3D model. # # Since we do not want to compile our code at every new stochastic realization, from here on we will need to work # with thte interp_data. And remember that to improve float32 to stability we need to work with rescaled data # (between 0 and 1). Therefore all the stochastic data needs to be rescaled accordingly. The object interp_data # contains a property with the rescale factor (see below. As default depends on the model extent), or it is # possible to add the stochastic data to the pandas dataframe of the geo_data---when the InterpolatorInput object # is created the rescaling happens under the hood. interface_Z_modifier = [] # We rescale the standard deviation std = 20./interp_data.rescaling_factor # loop over the unique group id's and create a pymc.Normal distribution for each for gID in group_ids: stoch = pymc.Normal(gID+'_stoch', 0, 1./std**2) interface_Z_modifier.append(stoch) # Let's have a look at one: # sample from a distribtion samples = [interface_Z_modifier[3].rand() for i in range(10000)] # plot histogram plt.hist(samples, bins=24, normed=True); plt.xlabel("Z modifier") plt.vlines(0, 0, 0.01) plt.ylabel("n"); # Now we need to somehow sample from these distribution and put them into GemPy # ## Input data handling # # First we need to write a function which modifies the input data for each iteration of the stochastic simulation. # As this process is highly dependant on the simulation (e.g. what input parameters you want modified in which way), # this process generally can't be automated. # # The idea is to change the column Z (in this case) of the rescaled dataframes in our interp_data object (which can # be found in interp_data.geo_data_res). First we simply create the pandas Dataframes we are interested on: import copy # First we extract from our original intep_data object the numerical data that is necessary for the interpolation. # geo_data_stoch is a pandas Dataframe # This is the inital model so it has to be outside the stochastic frame geo_data_stoch_init = copy.deepcopy(interp_data.geo_data_res) gp.get_data(geo_data_stoch_init, numeric=True).head() @pymc.deterministic(trace=True) def input_data(value = 0, interface_Z_modifier = interface_Z_modifier, geo_data_stoch_init = geo_data_stoch_init, verbose=0): # First we extract from our original intep_data object the numerical data that is necessary for the interpolation. # geo_data_stoch is a pandas Dataframe geo_data_stoch = gp.get_data(geo_data_stoch_init, numeric=True) # Now we loop each id which share the same uncertainty variable. In this case, each layer. for e, gID in enumerate(group_ids): # First we obtain a boolean array with trues where the id coincide sel = gp.get_data(interp_data.geo_data_res, verbosity=2)['group_id'] == gID # We add to the original Z value (its mean) the stochastic bit in the correspondant groups id geo_data_stoch.loc[sel, 'Z'] += np.array(interface_Z_modifier[e]) if verbose > 0: print(geo_data_stoch) # then return the input data to be input into the modeling function. Due to the way pymc2 stores the traces # We need to save the data as numpy arrays return [geo_data_stoch.xs('interfaces')[["X", "Y", "Z"]].values, geo_data_stoch.xs('orientations').values] # ## Modeling function @pymc.deterministic(trace=False) def gempy_model(value=0, input_data=input_data, verbose=True): # modify input data values accordingly interp_data.geo_data_res.interfaces[["X", "Y", "Z"]] = input_data[0] # Gx, Gy, Gz are just used for visualization. The theano function gets azimuth dip and polarity!!! interp_data.geo_data_res.orientations[["G_x", "G_y", "G_z", "X", "Y", "Z", 'dip', 'azimuth', 'polarity']] = input_data[1] try: # try to compute model lb, fb = gp.compute_model(interp_data) if True: gp.plot_section(interp_data.geo_data_res, lb[0], 0, plot_data=True) return lb, fb except np.linalg.linalg.LinAlgError as err: # if it fails (e.g. some input data combinations could lead to # a singular matrix and thus break the chain) return an empty model # with same dimensions (just zeros) if verbose: print("Exception occured.") return np.zeros_like(lith_block), np.zeros_like(fault_block) # We then create a pymc model with the two deterministic functions (*input_data* and *gempy_model*), as well as all # the prior parameter distributions stored in the list *interface_Z_modifier*: params = [input_data, gempy_model, *interface_Z_modifier] model = pymc.Model(params) # Then we set the number of iterations: # Then we create an MCMC chain (in pymc an MCMC chain without a likelihood function is essentially a Monte Carlo # forward simulation) and specify an hdf5 database to store the results in RUN = pymc.MCMC(model, db="hdf5", dbname=os.path.dirname(__file__)+"/ch3-pymc2.hdf5") # and we are finally able to run the simulation: RUN.sample(iter=100, verbose=0)