
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples/generated/scripts_synth_data/rosenbrock_neighpy.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_generated_scripts_synth_data_rosenbrock_neighpy.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_generated_scripts_synth_data_rosenbrock_neighpy.py:


Rosenbrock function with the Neighbourhood Algorithm
====================================================

.. GENERATED FROM PYTHON SOURCE LINES 9-14

|Open In Colab|

.. |Open In Colab| image:: https://img.shields.io/badge/open%20in-Colab-b5e2fa?logo=googlecolab&style=flat-square&color=ffd670
   :target: https://colab.research.google.com/github/inlab-geo/cofi-examples/blob/main/examples/metaheuristic_optimiser_tests/rosenbrock_neighpy.ipynb


.. GENERATED FROM PYTHON SOURCE LINES 17-24

If you are running this notebook locally, make sure you’ve followed
`steps
here <https://github.com/inlab-geo/cofi-examples#run-the-examples-with-cofi-locally>`__
to set up the environment. (This
`environment.yml <https://github.com/inlab-geo/cofi-examples/blob/main/envs/environment.yml>`__
file specifies a list of packages required to run the notebooks)


.. GENERATED FROM PYTHON SOURCE LINES 27-29

--------------


.. GENERATED FROM PYTHON SOURCE LINES 32-54

1. Introduction 
----------------

1.1 Rosenbrock function 
~~~~~~~~~~~~~~~~~~~~~~~~

The Rosenbrock function is a classic optimisation test function given by

.. math:: f(x,y) = (a - x)^2 + b(y - x^2)^2

with :math:`a = 1` and :math:`b = 100`. The function has a global
minimum at :math:`(a, a^2) = (1, 1)` where :math:`f(1,1) = 0`.

The minimum lies inside a narrow, curved valley. Finding the valley is
easy, but converging to the minimum within it is challenging for many
optimisers.

We work with the :math:`\log_{10}`-scaled version to avoid very
large/small values:

.. math:: F(x,y) = \log_{10}\left[(a - x)^2 + b(y - x^2)^2\right]


.. GENERATED FROM PYTHON SOURCE LINES 57-60

1.2 Neighbourhood Algorithm 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 60-69

.. code-block:: Python


    # display theory on the Neighbourhood Algorithm
    from IPython.display import display, Markdown

    with open("../../theory/neighbourhood_algorithm.md", "r") as f:
        content = f.read()

    display(Markdown(content))





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <IPython.core.display.Markdown object>




.. GENERATED FROM PYTHON SOURCE LINES 74-91

1.3 CoFI and the NA 
~~~~~~~~~~~~~~~~~~~~

The implementation of the NA that ``cofi`` wraps is called
```neighpy`` <https://github.com/inlab-geo/neighpy>`__. This
implementation implements both phases of the NA as described in the
original papers.

Because of the multi-phase nature of the NA, ``cofi`` gives you 3
options: 1. Run both phases, using the Direct Search Phase samples as
the initial ensemble for the Appraisal Phase (tool: ``neighpy``) 2. Only
run the Direct Search Phase (tool: ``neighpyI``) 3. Only run the
Appraisal Phase, using samples obtained from any method (tool:
``neighpyII``)

We will look at all of these options in this notebook.


.. GENERATED FROM PYTHON SOURCE LINES 94-96

--------------


.. GENERATED FROM PYTHON SOURCE LINES 99-102

2. Import modules 
------------------


.. GENERATED FROM PYTHON SOURCE LINES 102-111

.. code-block:: Python


    # -------------------------------------------------------- #
    #                                                          #
    #     Uncomment below to set up environment on "colab"     #
    #                                                          #
    # -------------------------------------------------------- #

    # !pip install -U cofi








.. GENERATED FROM PYTHON SOURCE LINES 113-123

.. code-block:: Python


    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.lines import Line2D
    from scipy.spatial import Voronoi, voronoi_plot_2d

    from cofi import BaseProblem, InversionOptions, Inversion

    np.random.seed(42)








.. GENERATED FROM PYTHON SOURCE LINES 128-130

--------------


.. GENERATED FROM PYTHON SOURCE LINES 133-136

3. Define the problem 
----------------------


.. GENERATED FROM PYTHON SOURCE LINES 136-141

.. code-block:: Python


    def rosenbrock(params, a=1, b=100):
        """Log10-scaled Rosenbrock function."""
        return np.log10((a - params[0])**2 + b * (params[1] - params[0]**2)**2)








.. GENERATED FROM PYTHON SOURCE LINES 143-157

.. code-block:: Python


    # Contour plot of the Rosenbrock function
    X, Y = np.meshgrid(np.linspace(-2, 2, 1000), np.linspace(-1, 3, 1000))
    Z = np.log10((1 - X)**2 + 100 * (Y - X**2)**2)

    plt.figure(figsize=(8, 6))
    plt.imshow(Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto")
    plt.colorbar(label="$\\log_{10}(f)$")
    plt.scatter(1, 1, c="r", marker="x", s=100, zorder=10, label="Global minimum (1, 1)")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("Rosenbrock function")
    plt.legend(loc="upper center")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_001.png
   :alt: Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_001.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    <matplotlib.legend.Legend object at 0x7efcbfc411d0>



.. GENERATED FROM PYTHON SOURCE LINES 159-167

.. code-block:: Python


    # Define the problem in CoFI
    inv_problem = BaseProblem()
    inv_problem.name = "Rosenbrock Function"
    inv_problem.set_objective(rosenbrock)

    inv_problem.summary()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    =====================================================================
    Summary for inversion problem: Rosenbrock Function
    =====================================================================
    Model shape: Unknown
    ---------------------------------------------------------------------
    List of functions/properties set by you:
    ['objective']
    ---------------------------------------------------------------------
    List of functions/properties created based on what you have provided:
    -- none --
    ---------------------------------------------------------------------
    List of functions/properties that can be further set for the problem:
    ( not all of these may be relevant to your inversion workflow )
    ['log_posterior', 'log_posterior_with_blobs', 'log_likelihood', 'log_prior', 'gradient', 'hessian', 'hessian_times_vector', 'residual', 'jacobian', 'jacobian_times_vector', 'data_misfit', 'regularization', 'regularization_matrix', 'forward', 'data', 'data_covariance', 'data_covariance_inv', 'initial_model', 'model_shape', 'blobs_dtype', 'bounds', 'constraints']




.. GENERATED FROM PYTHON SOURCE LINES 172-174

--------------


.. GENERATED FROM PYTHON SOURCE LINES 177-182

4. Full NA (direct search + appraisal) 
---------------------------------------

Here we run both phases of the NA in one go using the ``neighpy`` tool.


.. GENERATED FROM PYTHON SOURCE LINES 182-203

.. code-block:: Python


    bounds = [(-2, 2), (-1, 3)]
    n_initial_samples = 100
    n_samples_per_iteration = 70
    n_cells_to_resample = 10
    n_iterations = 20
    n_resample = 50000
    n_walkers = 10

    inv_options = InversionOptions()
    inv_options.set_tool("neighpy")
    inv_options.set_params(
        bounds=bounds,
        n_initial_samples=n_initial_samples,
        n_samples_per_iteration=n_samples_per_iteration,
        n_cells_to_resample=n_cells_to_resample,
        n_iterations=n_iterations,
        n_resample=n_resample,
        n_walkers=n_walkers,
    )








.. GENERATED FROM PYTHON SOURCE LINES 205-210

.. code-block:: Python


    inv = Inversion(inv_problem, inv_options)
    inv_result = inv.run()
    inv_result.summary()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    NAI - Initial Random Search
    NAI - Optimisation Loop:   0%|          | 0/20 [00:00<?, ?it/s]    NAI - Optimisation Loop:   5%|▌         | 1/20 [00:00<00:04,  4.29it/s]    NAI - Optimisation Loop:  30%|███       | 6/20 [00:00<00:00, 21.00it/s]    NAI - Optimisation Loop:  55%|█████▌    | 11/20 [00:00<00:00, 30.36it/s]    NAI - Optimisation Loop:  80%|████████  | 16/20 [00:00<00:00, 36.08it/s]    NAI - Optimisation Loop: 100%|██████████| 20/20 [00:00<00:00, 31.37it/s]
    ============================
    Summary for inversion result
    ============================
    SUCCESS
    ----------------------------
    model: [1.07679749 1.1598174 ]
    direct_search_samples: [[1.15976313 1.2663329 ]
     [0.27603632 1.95840675]
     [1.30366831 0.88045826]
     ...
     [1.07685765 1.1598225 ]
     [1.07685438 1.15982338]
     [1.07685384 1.1598245 ]]
    direct_search_objectives: [-0.19032542  2.54997852  1.82726273 ... -2.22833152 -2.22834468
     -2.22834377]
    appraisal_samples: [[ 1.18791177  1.80697917]
     [ 0.18183544  0.23945759]
     [ 0.54951805  0.31364752]
     ...
     [ 0.40972822  1.48295012]
     [ 1.24207273 -0.33868541]
     [ 0.46144746 -0.07465434]]




.. GENERATED FROM PYTHON SOURCE LINES 212-221

.. code-block:: Python


    best = inv_result.model
    ds_samples = inv_result.direct_search_samples
    ds_objectives = inv_result.direct_search_objectives
    appraisal_samples = inv_result.appraisal_samples

    print(f"Best model: x={best[0]:.4f}, y={best[1]:.4f}")
    print(f"True minimum: x=1, y=1")





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Best model: x=1.0768, y=1.1598
    True minimum: x=1, y=1




.. GENERATED FROM PYTHON SOURCE LINES 226-229

Voronoi cells from direct search
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 229-246

.. code-block:: Python


    fig = voronoi_plot_2d(
        Voronoi(ds_samples), show_vertices=False, line_width=0.5, line_colors="w"
    )
    ax = fig.gca()
    im = ax.imshow(Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto")
    fig.colorbar(im)
    _truth = ax.scatter(1, 1, c="r", marker="x", s=100, zorder=10, label="True minimum")
    _best = ax.scatter(*best, c="k", marker="+", s=100, zorder=10, label="Best sample (NA-I)")
    _voronoi = Line2D([0], [0], marker="o", label="Voronoi samples (NA-I)", markersize=5, linewidth=0)
    ax.set_xlim(-2, 2)
    ax.set_ylim(-1, 3)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.legend(handles=[_truth, _best, _voronoi], framealpha=1, edgecolor="black")
    ax.set_title("NA Direct Search - Voronoi cells on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_002.png
   :alt: NA Direct Search - Voronoi cells on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_002.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'NA Direct Search - Voronoi cells on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 251-254

Appraisal samples
~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 254-276

.. code-block:: Python


    fig = voronoi_plot_2d(
        Voronoi(ds_samples), show_vertices=False, line_width=0.5, line_colors="w"
    )
    ax = fig.gca()
    im = ax.imshow(Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto")
    fig.colorbar(im)
    _truth = ax.scatter(1, 1, c="r", marker="x", s=100, zorder=2, label="True minimum")
    _best = ax.scatter(*best, c="k", marker="+", s=100, zorder=2, label="Best sample (NA-I)")
    _resample = ax.scatter(
        *appraisal_samples.T, s=0.5, c="grey", zorder=0, label="Resampled points (NA-II)"
    )
    _voronoi = Line2D([0], [0], marker="o", label="Voronoi samples (NA-I)", markersize=5, linewidth=0)
    ax.set_xlim(-2, 2)
    ax.set_ylim(-1, 3)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.legend(
        handles=[_truth, _best, _voronoi, _resample], framealpha=1, edgecolor="black"
    )
    ax.set_title("NA-I and NA-II on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_003.png
   :alt: NA-I and NA-II on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_003.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'NA-I and NA-II on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 281-284

Conditional distributions
~~~~~~~~~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 284-350

.. code-block:: Python


    fig, axs = plt.subplots(
        2, 2,
        gridspec_kw=dict(height_ratios=[1, 5], width_ratios=[5, 1]),
        figsize=(7, 7),
        tight_layout=True,
    )
    axs[0, 1].set_visible(False)

    # Conditional posterior samples p(x|y=1)
    y_hist_edges = np.histogram_bin_edges(appraisal_samples[:, 1], bins=50, range=(-1, 3))
    best_ind_y = np.digitize(1, y_hist_edges)
    x_given_y = appraisal_samples[
        (appraisal_samples[:, 1] > y_hist_edges[best_ind_y - 1])
        & (appraisal_samples[:, 1] < y_hist_edges[best_ind_y]),
        0,
    ]
    axs[0, 0].hist(x_given_y, bins=50, orientation="vertical", color="grey")
    axs[0, 0].axvline(1, c="r", ls="--", lw=1)
    axs[0, 0].set_xlim(-2, 2)
    axs[0, 0].set_xticks([])
    axs[0, 0].text(
        0.05, 0.9, "p(x|y=1)",
        transform=axs[0, 0].transAxes, fontsize=12, verticalalignment="top",
    )

    # Conditional posterior samples p(y|x=1)
    x_hist_edges = np.histogram_bin_edges(appraisal_samples[:, 0], bins=50, range=(-2, 2))
    best_ind_x = np.digitize(1, x_hist_edges)
    y_given_x = appraisal_samples[
        (appraisal_samples[:, 0] > x_hist_edges[best_ind_x - 1])
        & (appraisal_samples[:, 0] < x_hist_edges[best_ind_x]),
        1,
    ]
    axs[1, 1].hist(y_given_x, bins=50, orientation="horizontal", color="grey")
    axs[1, 1].axhline(1, c="r", ls="--", lw=1)
    axs[1, 1].set_ylim(-1, 3)
    axs[1, 1].set_yticks([])
    axs[1, 1].text(
        0.05, 0.9, "p(y|x=1)",
        transform=axs[1, 1].transAxes, fontsize=12, verticalalignment="bottom",
    )

    # Full posterior samples
    im = axs[1, 0].imshow(
        Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto"
    )
    _truth = axs[1, 0].scatter(
        1, 1, c="r", marker="x", s=50, zorder=2, label="True minimum"
    )
    _best = axs[1, 0].scatter(
        *best, c="k", marker="+", s=50, zorder=2, label="Best sample (NA-I)"
    )
    _resample = axs[1, 0].scatter(
        *appraisal_samples.T, s=0.5, c="grey", zorder=0, label="Resampled points (NA-II)"
    )
    axs[1, 0].set_xlim(-2, 2)
    axs[1, 0].set_ylim(-1, 3)
    axs[1, 0].set_xlabel("x")
    axs[1, 0].set_ylabel("y")
    axs[1, 0].legend(
        handles=[_truth, _best, _resample], framealpha=1, edgecolor="black",
    )

    fig.suptitle("Conditional distributions from NA-II on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_004.png
   :alt: Conditional distributions from NA-II on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_004.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 0.98, 'Conditional distributions from NA-II on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 355-357

--------------


.. GENERATED FROM PYTHON SOURCE LINES 360-367

5. Direct search only 
----------------------

If you only want to optimise the objective function and find a point
estimate, you can run just the direct search phase using the
``neighpyI`` tool.


.. GENERATED FROM PYTHON SOURCE LINES 367-382

.. code-block:: Python


    inv_options_ds = InversionOptions()
    inv_options_ds.set_tool("neighpyI")
    inv_options_ds.set_params(
        bounds=bounds,
        n_initial_samples=n_initial_samples,
        n_samples_per_iteration=n_samples_per_iteration,
        n_cells_to_resample=n_cells_to_resample,
        n_iterations=n_iterations,
    )

    inv_ds = Inversion(inv_problem, inv_options_ds)
    inv_result_ds = inv_ds.run()
    inv_result_ds.summary()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    NAI - Initial Random Search
    NAI - Optimisation Loop:   0%|          | 0/20 [00:00<?, ?it/s]    NAI - Optimisation Loop:  25%|██▌       | 5/20 [00:00<00:00, 44.44it/s]    NAI - Optimisation Loop:  50%|█████     | 10/20 [00:00<00:00, 45.75it/s]    NAI - Optimisation Loop:  75%|███████▌  | 15/20 [00:00<00:00, 46.40it/s]    NAI - Optimisation Loop: 100%|██████████| 20/20 [00:00<00:00, 46.74it/s]    NAI - Optimisation Loop: 100%|██████████| 20/20 [00:00<00:00, 46.35it/s]
    ============================
    Summary for inversion result
    ============================
    SUCCESS
    ----------------------------
    model: [1.28686446 1.6562155 ]
    samples: [[-1.67484822  2.15015736]
     [-1.03846947  1.15364817]
     [-1.95464601 -0.95437107]
     ...
     [ 1.2869385   1.6572716 ]
     [ 1.28693635  1.65727174]
     [ 1.28693689  1.65727276]]
    objectives: [ 1.69942117  0.67406187  3.3596086  ... -1.08382908 -1.08382922
     -1.083828  ]




.. GENERATED FROM PYTHON SOURCE LINES 384-391

.. code-block:: Python


    best_ds = inv_result_ds.model
    ds_samples_only = inv_result_ds.samples
    ds_objectives_only = inv_result_ds.objectives

    print(f"Best model: x={best_ds[0]:.4f}, y={best_ds[1]:.4f}")





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Best model: x=1.2869, y=1.6562




.. GENERATED FROM PYTHON SOURCE LINES 393-410

.. code-block:: Python


    fig = voronoi_plot_2d(
        Voronoi(ds_samples_only), show_vertices=False, line_width=0.5, line_colors="w"
    )
    ax = fig.gca()
    im = ax.imshow(Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto")
    fig.colorbar(im)
    _truth = ax.scatter(1, 1, c="r", marker="x", s=100, zorder=10, label="True minimum")
    _best = ax.scatter(*best_ds, c="k", marker="+", s=100, zorder=10, label="Best sample (NA-I)")
    _voronoi = Line2D([0], [0], marker="o", label="Voronoi samples (NA-I)", markersize=5, linewidth=0)
    ax.set_xlim(-2, 2)
    ax.set_ylim(-1, 3)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.legend(handles=[_truth, _best, _voronoi], framealpha=1, edgecolor="black")
    ax.set_title("NA-I Direct Search on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_005.png
   :alt: NA-I Direct Search on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_005.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'NA-I Direct Search on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 415-417

--------------


.. GENERATED FROM PYTHON SOURCE LINES 420-430

6. Appraisal only 
------------------

The appraisal phase is implemented in the ``neighpyII`` tool. It takes a
set of samples and their corresponding log posterior probability
density.

Note that the direct search *minimises* an objective, but the appraisal
*maximises* a posterior. So we pass ``-objectives`` as ``log_ppd``.


.. GENERATED FROM PYTHON SOURCE LINES 430-445

.. code-block:: Python


    inv_options_app = InversionOptions()
    inv_options_app.set_tool("neighpyII")
    inv_options_app.set_params(
        bounds=bounds,
        initial_ensemble=ds_samples_only,
        log_ppd=-ds_objectives_only,
        n_resample=n_resample,
        n_walkers=n_walkers,
    )

    inv_app = Inversion(inv_problem, inv_options_app)
    inv_result_app = inv_app.run()
    inv_result_app.summary()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    ============================
    Summary for inversion result
    ============================
    SUCCESS
    ----------------------------
    new_samples: [[ 1.37579996  1.71047836]
     [ 0.89175276  1.67088524]
     [ 1.48016363  2.03048887]
     ...
     [ 1.14469765  1.2165956 ]
     [ 1.01351183  1.36735017]
     [-0.8633595   1.50488675]]




.. GENERATED FROM PYTHON SOURCE LINES 447-450

.. code-block:: Python


    appraisal_samples_only = inv_result_app.new_samples








.. GENERATED FROM PYTHON SOURCE LINES 455-458

Appraisal samples
~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 458-480

.. code-block:: Python


    fig = voronoi_plot_2d(
        Voronoi(ds_samples_only), show_vertices=False, line_width=0.5, line_colors="w"
    )
    ax = fig.gca()
    im = ax.imshow(Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto")
    fig.colorbar(im)
    _truth = ax.scatter(1, 1, c="r", marker="x", s=100, zorder=2, label="True minimum")
    _best = ax.scatter(*best_ds, c="k", marker="+", s=100, zorder=2, label="Best sample (NA-I)")
    _resample = ax.scatter(
        *appraisal_samples_only.T, s=0.5, c="grey", zorder=0, label="Resampled points (NA-II)"
    )
    _voronoi = Line2D([0], [0], marker="o", label="Voronoi samples (NA-I)", markersize=5, linewidth=0)
    ax.set_xlim(-2, 2)
    ax.set_ylim(-1, 3)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.legend(
        handles=[_truth, _best, _voronoi, _resample], framealpha=1, edgecolor="black"
    )
    ax.set_title("NA-II Appraisal on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_006.png
   :alt: NA-II Appraisal on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_006.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'NA-II Appraisal on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 485-488

Conditional distributions
~~~~~~~~~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 488-554

.. code-block:: Python


    fig, axs = plt.subplots(
        2, 2,
        gridspec_kw=dict(height_ratios=[1, 5], width_ratios=[5, 1]),
        figsize=(7, 7),
        tight_layout=True,
    )
    axs[0, 1].set_visible(False)

    # Conditional posterior samples p(x|y=1)
    y_hist_edges = np.histogram_bin_edges(appraisal_samples_only[:, 1], bins=50, range=(-1, 3))
    best_ind_y = np.digitize(1, y_hist_edges)
    x_given_y = appraisal_samples_only[
        (appraisal_samples_only[:, 1] > y_hist_edges[best_ind_y - 1])
        & (appraisal_samples_only[:, 1] < y_hist_edges[best_ind_y]),
        0,
    ]
    axs[0, 0].hist(x_given_y, bins=50, orientation="vertical", color="grey")
    axs[0, 0].axvline(1, c="r", ls="--", lw=1)
    axs[0, 0].set_xlim(-2, 2)
    axs[0, 0].set_xticks([])
    axs[0, 0].text(
        0.05, 0.9, "p(x|y=1)",
        transform=axs[0, 0].transAxes, fontsize=12, verticalalignment="top",
    )

    # Conditional posterior samples p(y|x=1)
    x_hist_edges = np.histogram_bin_edges(appraisal_samples_only[:, 0], bins=50, range=(-2, 2))
    best_ind_x = np.digitize(1, x_hist_edges)
    y_given_x = appraisal_samples_only[
        (appraisal_samples_only[:, 0] > x_hist_edges[best_ind_x - 1])
        & (appraisal_samples_only[:, 0] < x_hist_edges[best_ind_x]),
        1,
    ]
    axs[1, 1].hist(y_given_x, bins=50, orientation="horizontal", color="grey")
    axs[1, 1].axhline(1, c="r", ls="--", lw=1)
    axs[1, 1].set_ylim(-1, 3)
    axs[1, 1].set_yticks([])
    axs[1, 1].text(
        0.05, 0.9, "p(y|x=1)",
        transform=axs[1, 1].transAxes, fontsize=12, verticalalignment="bottom",
    )

    # Full posterior samples
    im = axs[1, 0].imshow(
        Z, origin="lower", extent=(-2, 2, -1, 3), aspect="auto"
    )
    _truth = axs[1, 0].scatter(
        1, 1, c="r", marker="x", s=50, zorder=2, label="True minimum"
    )
    _best = axs[1, 0].scatter(
        *best_ds, c="k", marker="+", s=50, zorder=2, label="Best sample (NA-I)"
    )
    _resample = axs[1, 0].scatter(
        *appraisal_samples_only.T, s=0.5, c="grey", zorder=0, label="Resampled points (NA-II)"
    )
    axs[1, 0].set_xlim(-2, 2)
    axs[1, 0].set_ylim(-1, 3)
    axs[1, 0].set_xlabel("x")
    axs[1, 0].set_ylabel("y")
    axs[1, 0].legend(
        handles=[_truth, _best, _resample], framealpha=1, edgecolor="black",
    )

    fig.suptitle("Conditional distributions from NA-II on Rosenbrock function")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_007.png
   :alt: Conditional distributions from NA-II on Rosenbrock function
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_rosenbrock_neighpy_007.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 0.98, 'Conditional distributions from NA-II on Rosenbrock function')



.. GENERATED FROM PYTHON SOURCE LINES 559-561

--------------


.. GENERATED FROM PYTHON SOURCE LINES 564-567

Watermark
---------


.. GENERATED FROM PYTHON SOURCE LINES 567-573

.. code-block:: Python


    watermark_list = ["cofi", "numpy", "scipy", "matplotlib"]
    for pkg in watermark_list:
        pkg_var = __import__(pkg)
        print(pkg, getattr(pkg_var, "__version__"))





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    cofi 0.2.11+68.gc319bc9
    numpy 2.2.6
    scipy 1.17.1
    matplotlib 3.10.9




.. GENERATED FROM PYTHON SOURCE LINES 574-574

sphinx_gallery_thumbnail_number = -1


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 34.566 seconds)


.. _sphx_glr_download_examples_generated_scripts_synth_data_rosenbrock_neighpy.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: rosenbrock_neighpy.ipynb <rosenbrock_neighpy.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: rosenbrock_neighpy.py <rosenbrock_neighpy.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: rosenbrock_neighpy.zip <rosenbrock_neighpy.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
