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

.. only:: html

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

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

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

.. _sphx_glr_auto_examples_06_reblocking.py:


Reblocking
==========

.. GENERATED FROM PYTHON SOURCE LINES 7-16

.. code-block:: Python


    import tempfile

    import pandas as pd
    from pathlib import Path
    import pyvista as pv

    from parq_blockmodel import ParquetBlockModel








.. GENERATED FROM PYTHON SOURCE LINES 17-20

Create a Parquet Block Model
----------------------------
We leverage the create_demo_block_model class method to create a Parquet Block Model.

.. GENERATED FROM PYTHON SOURCE LINES 20-28

.. code-block:: Python


    temp_dir = Path(tempfile.gettempdir()) / "block_model_example"
    temp_dir.mkdir(parents=True, exist_ok=True)

    pbm: ParquetBlockModel = ParquetBlockModel.create_demo_block_model(
        filename=temp_dir / "demo_block_model.parquet")
    pbm





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

 .. code-block:: none


    ParquetBlockModel(name=demo_block_model, path=/tmp/block_model_example/demo_block_model.pbm)



.. GENERATED FROM PYTHON SOURCE LINES 29-32

Visualise the Model
-------------------
A continuous attribute.

.. GENERATED FROM PYTHON SOURCE LINES 32-34

.. code-block:: Python

    pbm.plot(scalar='depth', threshold=False, enable_picking=True).show()




.. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_001.png
   :alt: 06 reblocking
   :srcset: /auto_examples/images/sphx_glr_06_reblocking_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 35-36

A categorical attribute.

.. GENERATED FROM PYTHON SOURCE LINES 36-39

.. code-block:: Python


    pbm.plot(scalar='depth_category', threshold=False, enable_picking=True).show()




.. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_002.png
   :alt: 06 reblocking
   :srcset: /auto_examples/images/sphx_glr_06_reblocking_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 40-43

Upsampling
-------
Create a new grid with smaller blocks, and visualise.

.. GENERATED FROM PYTHON SOURCE LINES 43-51

.. code-block:: Python

    upsampled_pbm: ParquetBlockModel = pbm.upsample(new_block_size=(0.5, 0.5, 0.5),
                                                    interpolation_config={
                                                        'depth': 'linear',
                                                        'depth_category': 'nearest'
                                                    })

    upsampled_pbm.plot(scalar='depth', threshold=False, enable_picking=True).show()




.. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_003.png
   :alt: 06 reblocking
   :srcset: /auto_examples/images/sphx_glr_06_reblocking_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 52-53

Visualise a reblocked categorical attribute.

.. GENERATED FROM PYTHON SOURCE LINES 53-55

.. code-block:: Python

    upsampled_pbm.plot(scalar='depth_category', threshold=False, enable_picking=True).show()




.. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_004.png
   :alt: 06 reblocking
   :srcset: /auto_examples/images/sphx_glr_06_reblocking_004.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 56-59

Downsample
----------
Downsample the upsampled model back to the original block size.

.. GENERATED FROM PYTHON SOURCE LINES 59-69

.. code-block:: Python


    downsampled_pbm: ParquetBlockModel = upsampled_pbm.downsample(new_block_size=(1.0, 1.0, 1.0),
                                                                  aggregation_config={
                                                                      'depth': {'method': 'mean'},
                                                                      'depth_category': {'method': 'mode'}
                                                                  })

    downsampled_pbm.plot(scalar='depth', threshold=False, enable_picking=True).show()
    downsampled_pbm.plot(scalar='depth_category', threshold=False, enable_picking=True).show()




.. rst-class:: sphx-glr-horizontal


    *

      .. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_005.png
          :alt: 06 reblocking
          :srcset: /auto_examples/images/sphx_glr_06_reblocking_005.png
          :class: sphx-glr-multi-img

    *

      .. image-sg:: /auto_examples/images/sphx_glr_06_reblocking_006.png
          :alt: 06 reblocking
          :srcset: /auto_examples/images/sphx_glr_06_reblocking_006.png
          :class: sphx-glr-multi-img





.. GENERATED FROM PYTHON SOURCE LINES 70-72

Validate
--------

.. GENERATED FROM PYTHON SOURCE LINES 72-118

.. code-block:: Python

    """Validate that reblocking preserves both data and centroids.

    1. Confirm the round trip (upsample then downsample) returns the
       original *data* when viewed in a consistent ijk ordering.
    2. Demonstrate that centroids derived from geometry are as expected.
    """

    # Read attribute data on the canonical ijk grid for both models. We work
    # only with the attributes of interest here (depth and depth_category)
    # rather than asserting equality for every auxiliary column.
    blocks_original: pd.DataFrame = pbm.read(index="ijk", dense=True)[["depth", "depth_category"]]
    blocks_up_down: pd.DataFrame = downsampled_pbm.read(index="ijk", dense=True)[["depth", "depth_category"]]

    # 1a. Ensure the reblocked attributes are fully populated (no NaNs) on
    # the dense ijk grid for this dense demo model.
    for col in ["depth", "depth_category"]:
        assert blocks_up_down[col].notna().all(), f"{col} contains NaNs after reblocking"

    # 1b. Numeric attribute: values should be similar after an
    # upsample→downsample round trip, but not necessarily identical. Check
    # that the maximum absolute difference is within a small tolerance.
    depth_diff = (blocks_up_down["depth"].sort_index() -
                  blocks_original["depth"].sort_index()).abs()
    assert depth_diff.max() < 0.5, (
        "Depth changed too much during reblocking; max |Δdepth| = "
        f"{float(depth_diff.max()):.3f}"
    )

    # 1c. Categorical attribute: in this demo we expect depth_category
    # labels to be preserved exactly by the round trip. We compare the
    # string representations to ignore differences in categorical metadata
    # such as the "ordered" flag.
    orig_cat = blocks_original["depth_category"].astype(str).sort_index()
    down_cat = blocks_up_down["depth_category"].astype(str).sort_index()
    pd.testing.assert_series_equal(orig_cat, down_cat, check_names=True)

    # Demonstrate that the logical ijk grid and XYZ centroids of the
    # downsampled model match those of the original geometry.
    orig_ijk = pbm.geometry.to_multi_index_ijk()
    down_ijk = downsampled_pbm.geometry.to_multi_index_ijk()
    pd.testing.assert_index_equal(orig_ijk, down_ijk)

    orig_xyz = pbm.geometry.to_multi_index_xyz()
    down_xyz = downsampled_pbm.geometry.to_multi_index_xyz()

    pd.testing.assert_index_equal(orig_xyz, down_xyz)








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

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


.. _sphx_glr_download_auto_examples_06_reblocking.py:

.. only:: html

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

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

      :download:`Download Jupyter notebook: 06_reblocking.ipynb <06_reblocking.ipynb>`

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

      :download:`Download Python source code: 06_reblocking.py <06_reblocking.py>`

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

      :download:`Download zipped: 06_reblocking.zip <06_reblocking.zip>`


.. only:: html

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

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