def _move_interface_orientation(self, new_df): # Check rows tht have changed b_i = ( new_df.xs('interfaces')[self.geo_data._columns_i_1].sort_index() != _gempy.get_data(self.geo_data, itype='interfaces')[ self.geo_data._columns_i_1].sort_index()).any(1) # Get indices of changed rows ind_i = new_df.xs('interfaces').index[b_i].tolist() # Check rows tht have changed b_o = ( new_df.xs('orientations')[self.geo_data._columns_o_1].sort_index() != _gempy.get_data(self.geo_data, itype='orientations')[ self.geo_data._columns_o_1].sort_index()).any(1) # Get indices of changed rows ind_o = new_df.xs('orientations').index[b_o].tolist() # Modify df self.geo_data.set_new_df(new_df) # Move widgets self.vv.SphereCallbak_move_changes(ind_i) self.vv.planesCallback_move_changes(ind_o)
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 ]
def test_set_orientations(): # 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.set_orientation_from_interfaces(geo_data, [0, 1, 2])
def test_issue_569(data_path): surface_points_df = df = pd.read_csv(data_path + "/coordinates_mwe.csv") orientations_df = pd.read_csv(data_path + "/orientations_mwe.csv") geo_model = gp.create_model("Deltatest") gp.init_data(geo_model, [ df.X.min() - 50, df.X.max() + 50, df.Y.min() - 50, df.Y.max() + 50, df.Z.min() - 50, df.Z.max() + 50, ], [50, 50, 50], surface_points_df=surface_points_df, orientations_df=orientations_df, default_values=True) fault_list = [] series = { "Strat_Series": surface_points_df.loc[ ~surface_points_df["formation"].str.contains("fault"), "formation"].unique().tolist() } for fault in surface_points_df.loc[ surface_points_df["formation"].str.contains("fault"), "formation"].unique(): series[fault] = fault fault_list.append(fault) gp.map_stack_to_surfaces(geo_model, series, remove_unused_series=True) geo_model.set_is_fault(fault_list) geo_model.reorder_features(['fault_a', 'fault_b', 'Strat_Series']) geo_model.add_surfaces("basement") plot = gp.plot_2d(geo_model, show_lith=False, show_boundaries=True, direction=['z']) plt.show(block=False) gp.set_interpolator( geo_model, compile_theano=True, theano_optimizer='fast_compile', ) gp.get_data(geo_model, 'kriging') sol = gp.compute_model(geo_model, sort_surfaces=True) gp.plot_2d(geo_model, show_scalar=True, series_n=0) gp.plot_2d(geo_model, series_n=0) gp.plot_3d(geo_model, image=True)
def load_model(): geo_model = gp.create_model('Model_Tuto1-1') # Importing the data from CSV-files and setting extent and resolution gp.init_data(geo_model, [0, 2000., 0, 2000., 0, 2000.], [50 ,50 ,50], path_o = input_path+"/simple_fault_model_orientations.csv", path_i = input_path+"/simple_fault_model_points.csv", default_values=True) gp.get_data(geo_model, 'surface_points').head() return geo_model
def set_geometric_data(geo_model: Model, surface_points_df=None, orientations_df=None, **kwargs): """ Function to set directly pandas.Dataframes to the gempy geometric data objects Args: geo_model: [s0] surface_points_df: A pn.Dataframe object with X, Y, Z, and surface columns orientations_df: A pn.Dataframe object with X, Y, Z, surface columns and pole or orientation columns **kwargs: Returns: Modified df """ r_ = None if surface_points_df is not None: geo_model.set_surface_points(surface_points_df, **kwargs) r_ = 'surface_points' elif orientations_df is not None: geo_model.set_orientations(orientations_df, **kwargs) r_ = 'data' if r_ == 'surface_points' else 'orientations' else: raise AttributeError('You need to pass at least one dataframe') return get_data(geo_model, itype=r_)
def observe_df(self, geo_data = None, itype='all'): if not geo_data: geo_data = self.geo_data self._original_df = copy.deepcopy(_gempy.get_data(geo_data, itype=itype)) qgrid_widget = geo_data.interactive_df_open(itype=itype) qgrid_widget.observe(self.qgrid_callBack, names=['_df']) return qgrid_widget
def test_load_model_df(): verbose = True df_i = pn.DataFrame(np.random.randn(6,3), columns='X Y Z'.split()) df_i['formation'] = ['surface_1' for _ in range(3)] + ['surface_2' for _ in range(3)] df_o = pn.DataFrame(np.random.randn(6,6), columns='X Y Z azimuth dip polarity'.split()) df_o['formation'] = ['surface_1' for _ in range(3)] + ['surface_2' for _ in range(3)] geo_model = gp.create_model('test') # Importing the data directly from the dataframes gp.init_data(geo_model, [0, 2000., 0, 2000., 0, 2000.], [50, 50, 50], surface_points_df=df_i, orientations_df=df_o, default_values=True) df_cmp_i = gp.get_data(geo_model, 'surface_points') df_cmp_o = gp.get_data(geo_model, 'orientations') if verbose: print(df_cmp_i.head()) print(df_cmp_o.head()) assert not df_cmp_i.empty, 'data was not set to dataframe' assert not df_cmp_o.empty, 'data was not set to dataframe' assert df_cmp_i.shape[0] == 6, 'data was not set to dataframe' assert df_cmp_o.shape[0] == 6, 'data was not set to dataframe' # try without the default_values command geo_model = gp.create_model('test') # Importing the data directly from the dataframes gp.init_data(geo_model, [0, 2000., 0, 2000., 0, 2000.], [50 ,50 ,50], surface_points_df=df_i, orientations_df=df_o) df_cmp_i2 = gp.get_data(geo_model, 'surface_points') df_cmp_o2 = gp.get_data(geo_model, 'orientations') if verbose: print(df_cmp_i2.head()) print(df_cmp_o2.head()) assert not df_cmp_i2.empty, 'data was not set to dataframe' assert not df_cmp_o2.empty, 'data was not set to dataframe' assert df_cmp_i2.shape[0] == 6, 'data was not set to dataframe' assert df_cmp_o2.shape[0] == 6, 'data was not set to dataframe' return geo_model
def observe_df(self, geo_data=None, itype='all'): if not geo_data: geo_data = self.geo_data self._original_df = copy.deepcopy( _gempy.get_data(geo_data, itype=itype)) qgrid_widget = geo_data.interactive_df_open(itype=itype) qgrid_widget.observe(self.qgrid_callBack, names=['_df']) return qgrid_widget
def _move_interface_orientation(self, new_df): # Check rows tht have changed b_i = (new_df.xs('interfaces')[self.geo_data._columns_i_1].sort_index() != _gempy.get_data( self.geo_data, itype='interfaces')[self.geo_data._columns_i_1].sort_index()).any(1) # Get indices of changed rows ind_i = new_df.xs('interfaces').index[b_i].tolist() # Check rows tht have changed b_o = (new_df.xs('orientations')[self.geo_data._columns_o_1].sort_index() != _gempy.get_data( self.geo_data, itype='orientations')[self.geo_data._columns_o_1].sort_index()).any(1) # Get indices of changed rows ind_o = new_df.xs('orientations').index[b_o].tolist() # Modify df self.geo_data.set_new_df(new_df) # Move widgets self.vv.SphereCallbak_move_changes(ind_i) self.vv.planesCallback_move_changes(ind_o)
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]
def test_set_orientations(): # Importing the data from CSV-files and setting extent and resolution geo_data = gp.create_data( extent=[0, 2000, 0, 2000, 0, 2000], resolution=[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.map_stack_to_surfaces(geo_data, { "Fault_Series": 'Main_Fault', "Strat_Series": ('Sandstone_2', 'Siltstone') }) geo_data._orientations.create_orientation_from_surface_points( geo_data.surface_points, [0, 1, 2]) gp.set_orientation_from_surface_points(geo_data, [0, 1, 2])
def load_model(): verbose = False geo_model = gp.create_model('Model_Tuto1-1') # Importing the data from CSV-files and setting extent and resolution gp.init_data(geo_model, [0, 2000., 0, 2000., 0, 2000.], [50 ,50 ,50], path_o=input_path+"/simple_fault_model_orientations.csv", path_i=input_path+"/simple_fault_model_points.csv", default_values=True) df_cmp_i = gp.get_data(geo_model, 'surface_points') df_cmp_o = gp.get_data(geo_model, 'orientations') df_o = pn.read_csv(input_path + "/simple_fault_model_orientations.csv") df_i = pn.read_csv(input_path + "/simple_fault_model_points.csv") assert not df_cmp_i.empty, 'data was not set to dataframe' assert not df_cmp_o.empty, 'data was not set to dataframe' assert df_cmp_i.shape[0] == df_i.shape[0], 'data was not set to dataframe' assert df_cmp_o.shape[0] == df_o.shape[0], 'data was not set to dataframe' if verbose: gp.get_data(geo_model, 'surface_points').head() return geo_model
def _move_interface(self, new_df): if self.verbose > 0: print(self.geo_data._columns_i_1, new_df.columns) # Check rows tht have changed b_i = (new_df[self.geo_data._columns_i_1].sort_index() != _gempy.get_data( self.geo_data, itype='interfaces')[self.geo_data._columns_i_1].sort_index()).any(1) # Get indices of changed rows ind_i = new_df.index[b_i].tolist() if self.verbose > 0: print('I am in modifing', ind_i) # Modify df self.geo_data.set_new_df(new_df) # Move sphere widget to new position self.vv.SphereCallbak_move_changes(ind_i)
def test_get_data(load_model): geo_model = load_model gp.get_data(geo_model, 'orientations').head()
"simple_fault_model_orientations.csv", path_i=data_path + "/data/input_data/getting_started/" "simple_fault_model_points.csv", default_values=True) # %% geo_model.surfaces # %% # The input data can then be listed using the command ``get_data``. Note # that the order of formations and respective allocation to series is # still completely arbitrary. We will fix this in the following. # # %% gp.get_data(geo_model, 'surface_points').head() # %% gp.get_data(geo_model, 'orientations').head() # %% # Declaring the sequential order of geological formations # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # - TODO update this section # # We want our geological units to appear in the correct order relative to # age. Such order might for example be given by a depositional sequence of # stratigraphy, unconformities due to erosion or other lithological # genesis events such as igneous intrusions. A similar age-related order # is to be declared for the faults in our model. In GemPy, the function
def test_get_data(self, one_fault_model): print(gp.get_data(one_fault_model)) print(gp.get_data(one_fault_model, itype='additional_data'))
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_get_data(self, geo_model): print(gp.get_data(geo_model)) print(gp.get_data(geo_model, itype='additional_data'))
}, remove_unused_series=True) # geo_model.series geo_model.set_is_fault(['Fault_Series']) geo_model.faults.faults_relations_df # gp.plot.plot_data(geo_model, direction='y') # gp.plot.plot_3D(geo_model) gp.set_interpolation_data(geo_model, compile_theano=True, theano_optimizer='fast_compile', verbose=[]) gp.get_data(geo_model, 'kriging') geo_model.additional_data.structure_data sol = gp.compute_model(geo_model, compute_mesh=True, sort_surfaces=False) gp.plot.plot_section(geo_model, cell_number=25, direction='y', show_data=True) ver , sim = gp.get_surfaces(geo_model) for i in range(len(ver)): fig = plt.figure() x, y, z = ver[i][:, 0], ver[i][:, 1], ver[i][:, 2] X, Y = np.meshgrid(x, y) Z = np.array([z]) Z = np.repeat(Z, Z.shape[1], axis=0) ax = fig.gca(projection='3d')
import gempy as gp import numpy as np import pandas as pd import matplotlib.pyplot as plt data_path = '../../data/GemPy/' geo_model = gp.create_model('Permo_Carb_Trough') gp.init_data(geo_model, [0, 30000., 0, 10., -7000, 1000.], [100, 1, 100], path_o = data_path+'line82_foliations.csv', path_i = data_path+'line82_interfaces.csv', default_values=False) #%% # Show data gp.get_data(geo_model, 'surface_points').head() gp.plot.plot_data(geo_model, direction='y') #%% # Assign formations to series gp.map_series_to_surfaces(geo_model, {"Fault7_series": 'Fault7', "Fault1_series": 'Fault1', "Fault6_series": 'Fault6', "Fault2_series": 'Fault2', "Fault5_series": 'Fault5', "Fault3_series": 'Fault3', "Fault4_series": 'Fault4', "Post_tectonic_series": ('Quaternary', 'Tertiary', 'Mesozoic'),
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)
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_get_data(self, model_complex): print(gp.get_data(model_complex)) print(gp.get_data(model_complex, itype='additional_data'))
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)
# %% model.map_stack_to_surfaces({ "Fault_Series": 'Main_Fault', "Strat_Series": ('Sandstone_2', 'Siltstone', 'Shale', 'Sandstone_1') }) # %% model._surfaces.df['series'] # %% model.surfaces # %% gp.get_data(model, 'surface points') # %% model.stack # %% # In the case of having faults we need to assign wich series are faults: # # %% model.faults # %% model.set_is_fault(['Fault_Series']) # %%