.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_ch2\ch2_ex2D.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_ch2_ch2_ex2D.py: ====================================== 2.4 2D Periodic Function Extrapolation ====================================== This script demonstrates an experiment using CodPy and SciPy models to visualize a 2D periodic function. It generates random data points (``x``, ``fx``) and (``z``, ``fz``), applies both CodPy and SciPy models, and visualizes the results using 3D plots. The script is divided into several parts: - Data generation: Creating random periodic data for different sizes. - Plotting: Inline plotting of generated and modeled data. - Model application: Applying CodPy and SciPy models for interpolation. .. GENERATED FROM PYTHON SOURCE LINES 17-148 .. code-block:: Python # Importing necessary modules import os import sys import time curr_f = os.path.join(os.getcwd(), "codpy-book", "utils") sys.path.insert(0, curr_f) import matplotlib.pyplot as plt import numpy as np from scipy.interpolate import Rbf # import CodPy's core module and Kernel class from codpy import core from codpy.kernel import Kernel # from codpy.plotting import plot1D # Lets import multi_plot function from codpy utils from codpy.plot_utils import multi_plot from sklearn.metrics import mean_squared_error # Define the sinusoidal function def periodic_fun(x): """ A sinusoidal function that generates a sum of sines based on the input ``x``. """ from math import pi sinss = np.cos(2 * x * pi) if x.ndim == 1: sinss = np.prod(sinss, axis=0) ress = np.sum(x, axis=0) else: sinss = np.prod(sinss, axis=1) ress = np.sum(x, axis=1) return ress + sinss # Lets define helper function to plot 3D projection of the function def plot_trisurf(xfx, ax, legend="", elev=90, azim=-100, **kwargs): from matplotlib import cm """ Helper function to plot a 3D surface using a trisurf plot. Parameters: - xfx: A tuple containing the x-coordinates (2D points) and their corresponding function values. - ax: The matplotlib axis object for plotting. - legend: The legend/title for the plot. - elev, azim: Elevation and azimuth angles for the 3D view. - kwargs: Additional keyword arguments for further customization. """ xp, fxp = xfx[0], xfx[1] x, fx = xp, fxp X, Y = x[:, 0], x[:, 1] Z = fx.flatten() ax.plot_trisurf(X, Y, Z, antialiased=False, cmap=cm.jet) ax.view_init(azim=azim, elev=elev) ax.title.set_text(legend) # Function to generate periodic data def generate_periodic_data(sizes_x, sizes_z): """ Generates 2D periodic data for given sizes of x and z. Parameters: - sizes_x: List of sizes for the x data. - sizes_z: List of sizes for the z data. Returns: - data_x: List of generated x arrays. - data_fx: List of function values corresponding to each x. - data_z: List of generated z arrays. - data_fz: List of function values corresponding to each z. """ # Generate x and z data of different sizes data_x = [np.random.uniform(-1, 1, (size, 2)) for size in sizes_x] data_z = [np.random.uniform(-1.5, 1.5, (size, 2)) for size in sizes_z] # Compute fx for each x and fz for each z data_fx = [periodic_fun(x).reshape(-1, 1) for x in data_x] data_fz = [periodic_fun(z).reshape(-1, 1) for z in data_z] return data_x, data_fx, data_z, data_fz # Function to plot the generated data points def plot_x_fx_z_fz(N=1024): """ Inline plot of the periodic data (x, fx) and (z, fz) for a fixed size N. Parameters: - N: Size of the generated x and z arrays (default is 1024). """ # Generate x and z data of size N x = np.random.uniform(-1, 1, (N, 2)) z = np.random.uniform(-1.5, 1.5, (N, 2)) # Compute fx for x and fz for z fx = periodic_fun(x).reshape(-1, 1) fz = periodic_fun(z).reshape(-1, 1) # Prepare the results for plotting (x, fx) and (z, fz) pairs results = [(x, fx), (z, fz)] # Legends for the subplots, displaying the size of x and z legends = [f"Data (x, fx) with N = {N}", f"Data (z, fz) with N = {N}"] # Plot the data using multi_plot in a 1x2 grid multi_plot( results, plot_trisurf, mp_nrows=1, mp_ncols=2, mp_figsize=(12, 6), legends=legends, projection="3d", ) # lets output the plot plot_x_fx_z_fz() .. image-sg:: /auto_ch2/images/sphx_glr_ch2_ex2D_001.png :alt: Data (x, fx) with N = 1024, Data (z, fz) with N = 1024 :srcset: /auto_ch2/images/sphx_glr_ch2_ex2D_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 149-151 The plot shows a sinusoidal pattern for the data generated in the cartesian coordinate system. The two curves for ``x`` and ``z`` exhibits the sinusoidal variations defined by ``periodic_fun(x)``. .. GENERATED FROM PYTHON SOURCE LINES 153-156 **Model Setup and Training** ######################################################################## .. GENERATED FROM PYTHON SOURCE LINES 156-289 .. code-block:: Python def run_experiment(data_x, data_fx, data_z): """ Runs the experiment applying CodPy and SciPy models on the data and plots the results. Parameters: - data_x: List of generated x arrays. - data_fx: List of function values corresponding to each x. - data_z: List of generated z arrays. """ # Apply CodPy and SciPy models for each (x, fx, z) pair codpy_models = [(z, codpy_model(x, fx, z)) for x, fx, z in zip(data_x, data_fx, data_z)] mmds_res = [np.sqrt(model.discrepancy(z)) for z, model in codpy_models] + \ [None for z in data_z] model_results = [ (z, cp_model(z)) for x, fx, z, (_,cp_model) in zip(data_x, data_fx, data_z, codpy_models) ] + [(z, rbf_interpolator(x, fx, z)) for x, fx, z in zip(data_x, data_fx, data_z)] # Titles for each subplot legends = [f"CodPy Model (N_z: {z.shape[0]})" for z in data_z] + [ f"SciPy Model (N_z: {z.shape[0]})" for z in data_z ] # Plot the model results using multi_plot multi_plot( model_results, plot_trisurf, mp_nrows=1, mp_ncols=4, mp_figsize=(18, 10), legends=legends, projection="3d", ) model_functions = [codpy_pred, rbf_interpolator] Nxs = [x.shape[0] for x in data_x] results = {} times = {} mmds = {} for j, Nx in enumerate(Nxs): results[Nx] = {} times[Nx] = {} mmds [Nx] = {} for i, model in enumerate(model_functions): start = time.perf_counter() _, f_z = model_results[j if i == 0 else j + len(data_x)] mmd = mmds_res[j if i == 0 else j + len(data_x)] end = time.perf_counter() mmds[Nx][model.__name__] = mmd results[Nx][model.__name__] = mean_squared_error(data_fz[j], f_z) times[Nx][model.__name__] = end - start print(f"Model: {model.__name__}, Time taken: {end-start:.4f} seconds") res = [{"data": results}, {"data": mmds}, {"data": times}] def plot_one(inputs): results = inputs["data"] ax = inputs["ax"] legend = inputs["legend"] for model_name in next(iter(results.values())).keys(): x_vals = sorted(results.keys()) y_vals = [results[x][model_name] for x in x_vals] ax.plot(x_vals, y_vals, marker='o', label=model_name) ax.set_xlabel('Nx') ax.set_ylabel(legend) ax.legend() ax.grid(True) multi_plot( res, plot_one, mp_nrows=1, mp_ncols=3, legends=["Scores", "Discrepancy", "Times"], mp_figsize=(14, 10), ) plt.show() # Applies CodPy's kernel-based model for interpolation. def codpy_model(x, fx, z): kernel = Kernel( set_kernel=core.kernel_setter("gaussianper", None,2,1e-9), x=x, fx=fx, order=2, ) return kernel def codpy_pred(x,fx,z): return codpy_model(x, fx, z)(z) # SciPy RBF Interpolator for 2D data interpolation. def rbf_interpolator(x, fx, z): """ SciPy RBF Interpolator for 2D data interpolation. Parameters: - x: A (N, 2) array of 2D coordinates. - fx: A (N, 1) array of corresponding function values. - z: A (M, 2) array of new coordinates where we want to interpolate. Returns: - Interpolated function values at points in z. """ # Split the 2D x array into separate arrays for each dimension x1, x2 = x[:, 0], x[:, 1] # Flatten fx to be a 1D array fx_flat = fx.ravel() # Create the Rbf interpolator using the separate dimensions of x rbf = Rbf(x1, x2, fx_flat, function="multiquadric") # Split the 2D z array into separate arrays for each dimension z1, z2 = z[:, 0], z[:, 1] # Return the interpolated values at points in z return rbf(z1, z2).reshape(-1, 1) # Example Usage sizes_x = [484, 1024] sizes_z = [484, 1024] # Generate the data data_x, data_fx, data_z, data_fz = generate_periodic_data(sizes_x, sizes_z) # Run the experiment with CodPy and SciPy models run_experiment(data_x, data_fx, data_z) plt.show() pass .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_ch2/images/sphx_glr_ch2_ex2D_002.png :alt: CodPy Model (N_z: 484), CodPy Model (N_z: 1024), SciPy Model (N_z: 484), SciPy Model (N_z: 1024) :srcset: /auto_ch2/images/sphx_glr_ch2_ex2D_002.png :class: sphx-glr-multi-img * .. image-sg:: /auto_ch2/images/sphx_glr_ch2_ex2D_003.png :alt: ch2 ex2D :srcset: /auto_ch2/images/sphx_glr_ch2_ex2D_003.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none Model: codpy_pred, Time taken: 0.0000 seconds Model: rbf_interpolator, Time taken: 0.0000 seconds Model: codpy_pred, Time taken: 0.0000 seconds Model: rbf_interpolator, Time taken: 0.0000 seconds .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.161 seconds) .. _sphx_glr_download_auto_ch2_ch2_ex2D.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: ch2_ex2D.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: ch2_ex2D.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: ch2_ex2D.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_