Core API

This page describes the core functions in MiningPy

ijk

miningpy.core.ijk(blockmodel: DataFrame, method: str = 'ijk', indexing: int = 0, xyz_cols: Optional[Tuple[str, str, str]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), ijk_cols: Tuple[str, str, str] = ('i', 'j', 'k'), print_warnings: bool = True, inplace: bool = False) DataFrame

Calculate block ijk indexes from their xyz cartesian coordinates

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

method: str, default ‘ijk’

can be used to only calculate i, or j, or k

indexing: int, default 0

controls whether origin block has coordinates 0,0,0 or 1,1,1

xyz_cols: tuple of strings

names of x,y,z columns in model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

ijk_cols: tuple of strings, default (‘i’, ‘j’, ‘k’)

name of the i,j,k columns added to the model

print_warnings: bool, default True

if True then will check if blocks are on a regular grid before the IJK calculation and print a warning to the user if the blocks are not regular (i.e. could get funky IJK values).

inplace: bool, default False

whether to do calculation inplace on pandas.DataFrame

Returns
pandas.DataFrame

indexed block model

Examples

>>> import pandas as pd
>>> import miningpy
...
>>> # block model data and framework
>>> data = {'x': [5, 5, 15],
...         'y': [5, 15, 25],
...         'z': [5, 5, 5]}
>>> xdim, ydim, zdim = 5, 5, 5  # regular block dimensions
>>> xorg, yorg, zorg = 2.5, 2.5, 2.5  # model origin (corner of first block)
...
>>> # Create block model from data
>>> blockmodel = pd.DataFrame(data)
>>> print(blockmodel)
    x   y  z
0   5   5  5
1   5  15  5
2  15  25  5
>>> # calculate i, j, k indexes
>>> blockmodel.ijk(indexing=1,  # use ijk function just like any other Pandas function
...                 xyz_cols=('x', 'y', 'z'),  # input the x, y, z column names as a tuple
...                 origin=(xorg, yorg, zorg),
...                 dims=(xdim, ydim, zdim),
...                 inplace=True) # can do inplace True/False like other standard Pandas functions
>>> # print results of ijk calculation
>>> print(blockmodel)
    x   y  z  i  j  k
0   5   5  5  1  1  1
1   5  15  5  1  3  1
2  15  25  5  3  5  1

xyz

miningpy.core.xyz(blockmodel: DataFrame, method: str = 'xyz', indexing: int = 0, ijk_cols: Tuple[str, str, str] = ('i', 'j', 'k'), origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), xyz_cols: Tuple[str, str, str] = ('x', 'y', 'z'), inplace: bool = False) DataFrame

Calculate xyz cartesian cooridinates of blocks from their ijk indexes

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

method: str, default ‘xyz’

can be used to only calculate i, or j, or k

indexing: int, default 0

controls whether origin block has coordinates 0,0,0 or 1,1,1

ijk_cols: tuple of strings, default (‘i’, ‘j’, ‘k’)

name of the i,j,k columns added to the model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

xyz_cols: tuple of strings, default (‘x’, ‘y’, ‘z’)

names of x,y,z columns in model

inplace: bool, default False

whether to do calculation inplace on pandas.DataFrame

Returns
pandas.DataFrame

indexed block model

rotate_grid

miningpy.core.rotate_grid(blockmodel: DataFrame, xyz_cols: Tuple[str, str, str] = ('x', 'y', 'z'), origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), return_full_model: bool = True, derotate: bool = False, inplace: bool = False) Union[DataFrame, dict]

Rotate block model relative to cartesian grid This method uses a rotation matrix method Rotation is done using the right hand rule

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings, default (‘x’, ‘y’, ‘z’)

names of x,y,z columns in model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

return_full_model: bool, default True

whether to return the full block model or just a dict of the rotated x,y,z coordinates

derotate: bool

whether to rotate a model or derotate it back to it’s normal orthogonal coordinate system this parameter exists because using the reverse angles in more than one dimension will not derotate a model

inplace: bool, default False

whether to do calculation inplace on pandas.DataFrame

Returns
pandas.DataFrame

rotated block model or dict of rotated x,y,z coordinates

group_weighted_average

miningpy.core.group_weighted_average(blockmodel: DataFrame, avg_cols: Union[str, List[str]], weight_col: str, group_cols: Optional[Union[str, List[str]]] = None) DataFrame

weighted average of block model attribute(s)

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

avg_cols: str or list of str

column(s) to take the weighted average

weight_col: str

column to weight on. Example the tonnes column

group_cols: str or list of str

the columns you want to group on. Either single column or list of columns

Returns
pandas.DataFrame

block model

nblocks_xyz

miningpy.core.nblocks_xyz(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0)) Tuple[Union[int, float], Union[int, float], Union[int, float]]

Number of blocks along the x,y,z axis. If the model is rotated, it is unrotated and then the number of blocks in the x,y,z axis is calculated.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

Returns
tuple of floats

Number of blocks along the x,y,z axis.

model_origin

miningpy.core.model_origin(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None) Tuple[float, float, float]

calculate the origin of a block model grid relative to its current xyz grid origin is the corner of the block with min xyz coordinates

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

Returns
tuple of floats

origin of a block model for each axis (x,y,z)

block_dims

miningpy.core.block_dims(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0)) Tuple[float, float, float]

estimate the x, y, z dimensions of blocks if the blocks are rotated then they are unrotated first then the x, y, z dimensions are estimated

note that this function just estimates the dimensions of the blocks it may not always get the perfectly correct answer if there are alot of blocks missing in the grid (i.e. a sparse array of blocks) the estimation is less likely to be correct

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

Returns
tuple of floats (xdim, ydim, zdim)

check_regular

miningpy.core.check_regular(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), tolerance: Union[int, float] = 1e-05) bool

check if the blocks in a block model are actually on a regular grid (including a rotated grid). note this is just an estimation of regularity, it is not perfect

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

tolerance: float or int, default 0.00001

the difference of a blocks centroid from the point on a grid it should be located generally in the range of 0.1 to 0.000001

Returns
bool

whether block model is regular or not. True if regular.

check_internal_blocks_missing

miningpy.core.check_internal_blocks_missing(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), origin: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0)) bool

check if there are missing internal blocks (not side blocks) within a regular block model

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

origin: tuple of floats or ints, default (0,0,0)

ONLY NEEDED IF MODEL IS ROTATED x,y,z origin of model - this is the corner of the bottom block (not the centroid)

Returns
bool

whether block model contains missing internal blocks returns True if so

vulcan_csv

miningpy.core.vulcan_csv(blockmodel: DataFrame, path: Optional[str] = None, var_path: Optional[str] = None, xyz_cols: Optional[Tuple[str, str, str]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, inplace: bool = False) DataFrame

transform pandas.Dataframe block model into Vulcan import compatible CSV format.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

path: str

filename for vulcan csv block model file

var_path: {optional} str

filename for csv that lists the Vulcan dtype of each column in block model (used if manually creating bdf)

xyz_cols: tuple of strings

names of x,y,z columns in model

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

inplace: bool, default False

whether to do calculation inplace (i.e. add Vulcan headers inplace) or return pandas.DataFrame with Vulcan headers

Returns
pandas.DataFrame

block model in Vulcan import CSV format

vulcan_bdf

miningpy.core.vulcan_bdf(blockmodel: DataFrame, path: Optional[str] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, start_offset: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0.0, 0.0, 0.0), end_offset: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, format: str = 'T') bool

Create a Vulcan block definition file from a vulcan block model. This script creates a BDF from a vulcan block model csv that can be imported into Vulcan. It assumes that bearing, dip and plunge are the default. values for the block model. Variables are given a default value of -99.0, a blank description and type ‘double’. This script will define the parent schema. All of these values can be edited within Vulcan once the script has been run and bdf imported.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model in Vulcan CSV import compatible format (use funtion: “vulcan_csv”)

path: str

filename for vulcan bdf file

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

start_offset: tuple of floats or ints, default (0.0, 0.0, 0.0)

minimum offset along the x,y,z axes

end_offset: tuple of floats or ints

maximum offset along the x,y,z axes

format: {‘C’, ‘T’}, default ‘T’

block model file format (classic = C, extended = T)

Returns
True if Vulcan .bdf file is exported with no errors

geometric_reblock

miningpy.core.geometric_reblock(blockmodel: DataFrame, xyz_cols: Optional[Tuple[str, str, str]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, reblock_multiplier: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, varlist_agg: Optional[dict] = None, min_cols: Optional[list] = None, max_cols: Optional[list] = None)

Reblock a regular block model into larger or smaller blocks (aggregate or split blocks). Aggregating multiple small blocks into big blocks will be referred to as “superblocking” and splitting big blocks into smaller children will be referred to as “subblocking”. This tool can be used as a tool for geometrically aggregating blocks in bench-phases.

This function utilises a reblock_multiplier in (x, y, z) dimensions to define the reblock. The function will either superblock or subblock but not both in the same call. The reblock_multiplier must be a multiple of the parent dimension. To superblock in one dimension and subblock in another, subblock to the smallest dimensions required and then superblock to the required size.

Weighting of blocks, is handled by argument varlist_agg. This dictionary must have the block model attribute to weight by as the key and the attributes to be weighted as a list in the key.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

xyz_cols: tuple of strings

names of x,y,z columns in model

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

reblock_multiplier: tuple of floats or ints

the scalar to change dimensions of blocks. E.g., (2, 2, 1) will double the blocks in the x and y dimension and keep the z dimension the same.

varlist_agg: dictionary

used to weight attributes. Key is the attribute to weight by, value is a list of attributes to weight. All attributes that are required to be carried through the reblock must be a key in the dictionary even if they are not weighting anything. Keys with empty lists will be divided or summed accordingly E.g., to carry through ore tonnes, volume and energy with ore grades, varlist_agg = {‘ore_tonnes’: [‘au_grade’, ‘cu_grade’], ‘volume’:[‘density’], ‘energy’:[]}

min_cols: {optional} list of model attributes

attributes that require the min value e.g., pit_number

max_cols: {optional} list of model attributes

attributes that require the max value e.g., resource category

Returns
pandas.DataFrame

reblocked block model

Examples

>>> import pandas as pd
>>> import miningpy
>>> # block model example (zuck small - MineLib)
>>> url = "https://drive.google.com/uc?export=download&id=1SOrYhqiu5Tg8Zjb7be4fUWhbFDTU1sEk"
>>> # read in block model from link
>>> data = pd.read_csv(url, compression='zip')
>>> # listing attributes to carry through (n.b. dropping ID column)
>>> # keys are what to weight by and values are lists of attributes to be weighted
>>> varlist_agg = {
>>> 'rock_tonnes': ['cost', 'value'],
>>> 'ore_tonnes': [],
>>> }
>>> # take the max or min value of reblock
>>> min_cols = ['final_pit']
>>> max_cols = ['period']
>>> # reblock function
>>> reblock = data.geometric_reblock(
>>> dims=(1, 1, 1),  # original dims of model
>>> xyz_cols=('x', 'y', 'z'),
>>> origin=(-0.5, -0.5, -0.5),  # bottom left corner
>>> reblock_multiplier=(2, 2, 1),  # doubling x and y dim and keeping z dim the same
>>> varlist_agg=varlist_agg,
>>> min_cols=min_cols,
>>> max_cols=max_cols,
>>> )
>>> reblock.plot3D(dims=(2, 2, 1), xyz_cols=('x', 'y', 'z'), col='value', widget='section')  # reblocked plot
>>> data.plot3D(dims=(1, 1, 1), xyz_cols=('x', 'y', 'z'), col='value', widget='section')  # original plot

index_3Dto1D

miningpy.core.index_3Dto1D(blockmodel: DataFrame, indexing: int = 0, xyz_cols: Optional[Tuple[str, str, str]] = None, origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), nblocks_xyz: Optional[Tuple[int, int, int]] = None, idxcol: str = 'ijk', inplace: bool = False) DataFrame

Convert 3D array of xyz block centroids to 1D index that is reversible. Opposite of the function index_1Dto3D()

This is identical to the “ijk” parameter in Datamine block models. Note that “ijk” value from this function and from Datamine may be different, depending on which axis Datamine uses as the major indexing axis. Bot “ijk” indexing values are still valid.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

indexing: int, default 0

controls whether origin block has coordinates 0,0,0 or 1,1,1

xyz_cols: tuple of strings

names of x,y,z columns in model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

nblocks_xyz: tuple of ints or None

number of blocks along the x,y,z axis. If the model is rotated, it is unrotated and then the number of blocks in the x,y,z axis is calculated. If “None” (default value) then the nx,ny,nz is automatically estimated

idxcol: str, default ‘ijk’

name of the 1D index column added to the model

inplace: bool

whether to do calculation inplace on pandas.DataFrame

Returns
pandas.DataFrame

block model with 1D indexed column

index_1Dto3D

miningpy.core.index_1Dto3D(blockmodel: DataFrame, indexing: int = 0, idxcol: str = 'ijk', origin: Optional[Tuple[Union[int, float], Union[int, float], Union[int, float]]] = None, dims: Optional[Tuple[Union[int, float, str], Union[int, float, str], Union[int, float, str]]] = None, rotation: Tuple[Union[int, float], Union[int, float], Union[int, float]] = (0, 0, 0), nblocks_xyz: Optional[Tuple[int, int, int]] = None, xyz_cols: Tuple[str, str, str] = ('x', 'y', 'z'), inplace: bool = False) DataFrame

Convert IJK index back to xyz block centroids. Opposite of the function index_3Dto1D()

This is identical to the “ijk” parameter in Datamine block models. Note that “ijk” value from this function and from Datamine may be different, depending on which axis Datamine uses as the major indexing axis. Bot “ijk” indexing values are still valid.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

indexing: int, default 0

controls whether origin block has coordinates 0,0,0 or 1,1,1

idxcol: str, default ‘ijk’

name of the 1D index column added to the model

origin: tuple of floats or ints

x,y,z origin of model - this is the corner of the bottom block (not the centroid)

dims: tuple of floats, ints or str

x,y,z dimension of regular parent blocks can either be a number or the columns names of the x,y,z columns in the dataframe

rotation: tuple of floats or ints, default (0,0,0)

rotation of block model grid around x,y,z axis, -180 to 180 degrees

nblocks_xyz: tuple of ints or None

number of blocks along the x,y,z axis. If the model is rotated, it is unrotated and then the number of blocks in the x,y,z axis is calculated.

xyz_cols: tuple of strings, default (‘x’, ‘y’, ‘z’)

names of x,y,z columns in model

inplace: bool

whether to do calculation inplace on pandas.DataFrame

Returns
pandas.DataFrame

block model with 1D indexed column

grade_tonnage_plot

miningpy.core.grade_tonnage_plot(blockmodel: DataFrame, grade_col: str, ton_col: str, cog_grades: Optional[List] = None, cog_grade_points: Optional[int] = None, plot_path: Optional[str] = None, show_plot: bool = False)

Create and return grade-tonnage table and optional export plot as a .png and save image. Grade-Tonnage curves are a visual representation of the impact of cut-off grades on mineral reserves. Grades to plot can be specified, else grades to plot will be generated based on the range of grades in the model.

Parameters
blockmodel: pd.DataFrame

pandas dataframe of block model

grade_col: str

name of grade to plot, typically ‘ore’ grade

ton_col: str

name of tonnage column in the model

cog_grades: {optional} ints, floats

list of cut off grades to plot

cog_grade_points: {optional} int, default 10

number of cut off grades to plot between min and max grade

plot_path: {optional} str

path to save plot .png

show_plot: {optional} bool

if running in interactive console, show plot, default False

Returns
pandas.DataFrame

dataframe of grade-tonnage

matplotlib.pyplot

Grade-Tonnage plot