Validate BlockModel Sort Order

A block model is a 3D array of cells, each with a set of attributes. However, it is convenient to represent the attributes as a vector. The order of the data in the vector is determined by the order used in this (ravel) conversion.

The ravel order for OMF is C-style (row-major order). The ravel order for Pandas is C-style (row-major order). The ravel order for PyVista is F-style (column-major order).

  • C-style - row-major order: The last index (z) changes the fastest. The first index (x) changes the slowest. df.sort_index(['x', 'y', 'z'])

  • F-style - column-major order: The first index (x) changes the fastest. The last index (z) changes the slowest. df.sort_index(['z', 'y', 'x'])

This script completes some validations on the sort order of the block model data:

  • parquet file -> dataframe

  • dataframe -> omf file / regular block model

  • omf file / regular block model -> dataframe

  • pyvista visualisation

To conduct this test we use a small block model of shape (5, 4, 3) with a depth attribute.

So we will round-trip the data from the dataframe to the omf file, and back to a dataframe. We will also check the visualisation performs as expected.

from pathlib import Path

import numpy as np
import pandas as pd
import pyvista as pv

from omfpandas import OMFPandasWriter
from omfpandas.utils import create_test_blockmodel

Create Block Model Dataframe

shape = (5, 4, 3)
block_size = (1.0, 1.0, 0.5)
corner = (100.0, 200.0, 300.0)

blocks: pd.DataFrame = create_test_blockmodel(shape, block_size, corner)

The dataframe is C-style (x, y, z). The last index (z) changes the fastest.

blocks
c_style_xyz f_style_zyx depth
x y z
100.5 200.5 300.25 0 0 1.25
300.75 1 20 0.75
301.25 2 40 0.25
201.5 300.25 3 5 1.25
300.75 4 25 0.75
301.25 5 45 0.25
202.5 300.25 6 10 1.25
300.75 7 30 0.75
301.25 8 50 0.25
203.5 300.25 9 15 1.25
300.75 10 35 0.75
301.25 11 55 0.25
101.5 200.5 300.25 12 1 1.25
300.75 13 21 0.75
301.25 14 41 0.25
201.5 300.25 15 6 1.25
300.75 16 26 0.75
301.25 17 46 0.25
202.5 300.25 18 11 1.25
300.75 19 31 0.75
301.25 20 51 0.25
203.5 300.25 21 16 1.25
300.75 22 36 0.75
301.25 23 56 0.25
102.5 200.5 300.25 24 2 1.25
300.75 25 22 0.75
301.25 26 42 0.25
201.5 300.25 27 7 1.25
300.75 28 27 0.75
301.25 29 47 0.25
202.5 300.25 30 12 1.25
300.75 31 32 0.75
301.25 32 52 0.25
203.5 300.25 33 17 1.25
300.75 34 37 0.75
301.25 35 57 0.25
103.5 200.5 300.25 36 3 1.25
300.75 37 23 0.75
301.25 38 43 0.25
201.5 300.25 39 8 1.25
300.75 40 28 0.75
301.25 41 48 0.25
202.5 300.25 42 13 1.25
300.75 43 33 0.75
301.25 44 53 0.25
203.5 300.25 45 18 1.25
300.75 46 38 0.75
301.25 47 58 0.25
104.5 200.5 300.25 48 4 1.25
300.75 49 24 0.75
301.25 50 44 0.25
201.5 300.25 51 9 1.25
300.75 52 29 0.75
301.25 53 49 0.25
202.5 300.25 54 14 1.25
300.75 55 34 0.75
301.25 56 54 0.25
203.5 300.25 57 19 1.25
300.75 58 39 0.75
301.25 59 59 0.25


Sort to F-style (z, y, x). The first index (x) changes the fastest.

blocks.sort_index(level=['z', 'y', 'x'])
c_style_xyz f_style_zyx depth
x y z
100.5 200.5 300.25 0 0 1.25
101.5 200.5 300.25 12 1 1.25
102.5 200.5 300.25 24 2 1.25
103.5 200.5 300.25 36 3 1.25
104.5 200.5 300.25 48 4 1.25
100.5 201.5 300.25 3 5 1.25
101.5 201.5 300.25 15 6 1.25
102.5 201.5 300.25 27 7 1.25
103.5 201.5 300.25 39 8 1.25
104.5 201.5 300.25 51 9 1.25
100.5 202.5 300.25 6 10 1.25
101.5 202.5 300.25 18 11 1.25
102.5 202.5 300.25 30 12 1.25
103.5 202.5 300.25 42 13 1.25
104.5 202.5 300.25 54 14 1.25
100.5 203.5 300.25 9 15 1.25
101.5 203.5 300.25 21 16 1.25
102.5 203.5 300.25 33 17 1.25
103.5 203.5 300.25 45 18 1.25
104.5 203.5 300.25 57 19 1.25
100.5 200.5 300.75 1 20 0.75
101.5 200.5 300.75 13 21 0.75
102.5 200.5 300.75 25 22 0.75
103.5 200.5 300.75 37 23 0.75
104.5 200.5 300.75 49 24 0.75
100.5 201.5 300.75 4 25 0.75
101.5 201.5 300.75 16 26 0.75
102.5 201.5 300.75 28 27 0.75
103.5 201.5 300.75 40 28 0.75
104.5 201.5 300.75 52 29 0.75
100.5 202.5 300.75 7 30 0.75
101.5 202.5 300.75 19 31 0.75
102.5 202.5 300.75 31 32 0.75
103.5 202.5 300.75 43 33 0.75
104.5 202.5 300.75 55 34 0.75
100.5 203.5 300.75 10 35 0.75
101.5 203.5 300.75 22 36 0.75
102.5 203.5 300.75 34 37 0.75
103.5 203.5 300.75 46 38 0.75
104.5 203.5 300.75 58 39 0.75
100.5 200.5 301.25 2 40 0.25
101.5 200.5 301.25 14 41 0.25
102.5 200.5 301.25 26 42 0.25
103.5 200.5 301.25 38 43 0.25
104.5 200.5 301.25 50 44 0.25
100.5 201.5 301.25 5 45 0.25
101.5 201.5 301.25 17 46 0.25
102.5 201.5 301.25 29 47 0.25
103.5 201.5 301.25 41 48 0.25
104.5 201.5 301.25 53 49 0.25
100.5 202.5 301.25 8 50 0.25
101.5 202.5 301.25 20 51 0.25
102.5 202.5 301.25 32 52 0.25
103.5 202.5 301.25 44 53 0.25
104.5 202.5 301.25 56 54 0.25
100.5 203.5 301.25 11 55 0.25
101.5 203.5 301.25 23 56 0.25
102.5 203.5 301.25 35 57 0.25
103.5 203.5 301.25 47 58 0.25
104.5 203.5 301.25 59 59 0.25


Sort Order Check

Check the ordering by first sorting by x,y,z and confirming the c-raveled attribute is monotonic.

assert np.array_equal(blocks.sort_index(level=['x', 'y', 'z'])['c_style_xyz'].values, np.arange(len(blocks)))

Similarly, sort by z,y,x and confirm the f-raveled attribute is monotonic.

assert np.array_equal(blocks.sort_index(level=['z', 'y', 'x'])['f_style_zyx'].values, np.arange(len(blocks)))

Create OMF

omfp: OMFPandasWriter = OMFPandasWriter(filepath='test_blockmodel.omf')
omfp.create_blockmodel(blocks=blocks, blockmodel_name='sort_check', allow_overwrite=True)

Export to Pandas

Check the round trip: pandas > omf > pandas

blocks_omf = omfp.read_blockmodel(blockmodel_name='sort_check')

pd.testing.assert_frame_equal(blocks, blocks_omf)

Visualise

Plot the depth attribute to confirm the sort order is as expected.

p = omfp.plot_blockmodel(blockmodel_name='sort_check', scalar='depth', threshold=False)
p.show()
08 validate blockmodel sort order

Plot the c-raveled attribute.

p: pv.Plotter = omfp.plot_blockmodel(blockmodel_name='sort_check', scalar='c_style_xyz', threshold=False)
p.show()
08 validate blockmodel sort order

Plot the f-raveled attribute.

p = omfp.plot_blockmodel(blockmodel_name='sort_check', scalar='f_style_zyx', threshold=False)
p.show()
08 validate blockmodel sort order

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

Gallery generated by Sphinx-Gallery