Block model manipulation
Block models can be manipulated without Vulcan being opened. The following examples illustrate how to do this.
Topics:
Modules to import
Import the following libraries:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from maptek import vulcan
Open a block model
from maptek import vulcan
bm = vulcan.block_model()
bm.open('small.bmf')
Get a list of all variables
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
bm.field_list()
Block model information
Extract some common information about the block model.
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
nblocks = bm.n_blocks()
extent = bm.model_extent()
origin = bm.model_origin()
orientation = bm.model_orientation()
print("nblocks: {}".format(nblocks))
print("extents: {}".format(extent))
print("origin: {}".format(origin))
print("orientation: {}".format(orientation))
Get the value of a block
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
grade = bm.get('au')
print("First block au value: {:.3f}".format(grade))
Get all values using a loop
Loop through the block model and extract all values for a particular variable.
from maptek import vulcan
def get_all_values(bm,variable):
bm.rewind() # Go to start of block model
data=[] # Empty list
nblocks = bm.n_blocks() # Get number of blocks in model
for block in bm:
value = bm.get(variable) # Get value of block
data.append(value) # Append to list
bm.next() # Go to next block
return data
bm = vulcan.block_model('small.bmf')
au_vals = get_all_values(bm, 'au')
au_vals
All values as a numpy array
Read all values in a variable into a numpy array. Need to have enough physical memory to read in all the data.
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
au = bm.get_data('au')
All values in a Pandas dataframe
Read all values in a variable into a pandas dataframe. Need to have enough physical memory to read in all the data.
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
data = bm.get_pandas()
data.head()
Calculate statistics on a dataframe
Calculate statistics of the Pandas dataframe using the method describe.
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
data = bm.get_pandas()
data.describe()
Close the block model
from maptek import vulcan
bm = vulcan.block_model('small.bmf')
bm.close()
Modify a block selection
from maptek import vulcan
# open the block model
bm = vulcan.block_model('small.bmf')
# get all au and cu data inside the given solid i.e. a selection
data = bm.get_pandas(['au','cu'], '-t tq1.00t')
# change the values for the data inside the selection
data.au = 100
data.cu = 50
# write the modified data back to the block model
# the selection is maintained from the previous operation
# so the values are written into the correct locationsa
bm.put_pandas(data, ['au','cu'])
# close the block model
bm.close()
# statistics on dataframe
data.describe()
Sub-block model creation
An example of creating a sub-blocked model.
- The coordinates are in model coordinates not block.
- No blocks are created unless they are explicitly defined.
- The block model needs to be translated and rotated into the required world coordinates.
from maptek import vulcan
bm = vulcan.block_model()
xbegin = 0
ybegin = 0
zbegin = 0
xend = 50
yend = 50
zend = 50
x_num_pblock = 5
y_num_pblock = 5
z_num_pblock = 5
x_num_subblock=10
y_num_subblock=10
z_num_subblock=10
bm.create_irregular('subblock.bmf', xbegin, ybegin, zbegin, xend, yend, zend,
x_num_pblock, y_num_pblock , z_num_pblock,
x_num_subblock, y_num_subblock, z_num_subblock)
# Add variables to block model
bm.add_variable('au','integer','-99','gold')
bm.add_variable('cu','float','-99','copper')
bm.add_variable('lith','name','NA','lith')
# Check number of blocks, there should be none
print('Number of blocks: {0}'.format(bm.n_blocks()))
# move the origin of the block model to 100,100,50
bm.translate(100,100,50)
# actual rotation is bearing=23 but have to subtract standard vulcancan 90 degrees
# mod 360 constrains the answer to 360 degrees
bearing = (23 - 90)%360
dip = -5
plunge = -20
bm.rotate(dip, plunge, bearing)
# block length = 50/5 = 10
xlen = 10
ylen = 10
zlen = 10
# blocks are added in model space NOT world space the block is defined
# from the lower left of the 3d cube to the upper right of the 3d cube.
for i in range(0, xend, xlen):
for j in range(0, yend, ylen):
for k in range(0, zend, zlen):
# calculate the min/max block
xmin = i
ymin = j
zmin = k
xmax = i+xlen
ymax = j+ylen
zmax = k+zlen
# add block to block model
bm.add_block(xmin,ymin,zmin,xmax,ymax,zmax)
# Check number of blocks after adding them all
print('Number of blocks: {0}'.format(bm.n_blocks()))
bm.close()
Reset a variable to default
from maptek import vulcan
'''
This script will reset a block model to the variable default using the NumPy interface.
The var_data variable is a NumPy array with the values of all the blocks in the block
model.
The .fill function populates all values of that array with the variable default.
The data is then placed back in the model after being updated with the new values.
'''
with vulcan.block_model('small.bmf', 'w') as bm:
var_default = bm.field_default('au')
var_data = bm['au']
var_data.fill(var_default)
bm['au'] = var_data
print('Default value for au : {}'.format(var_default))
Block model calculation using NumPy
from maptek import vulcan
'''
The code below is an example of using NumPy to calculate the entire models
values within a single set of statements. NumPy uses large arrays of data
to make the calculations faster (~4x).
Code with # ** after it means it is syntax for the NumPy package in Python
'''
au_price = 1320
cu_price = 3.02
with vulcan.block_model('small.bmf', "w") as bm:
# Reset the calculated variable
au_eq = bm["au_eq"]
au_eq.fill(0) # **
# Get the data to work with
au = bm["au"]
cu = bm["cu"]
# Set anything with values less than zero to zero (-99 or -9)
au[au < 0] = 0 # **
cu[cu < 0] = 0 # **
# Calculate the new values
au_oz = au * (1/31.1035)
cu_lb = cu * 2240
# Calculate the new equivalent
au_eq = (au_oz * au_price + cu_lb * cu_price) / au_price
# Update the values
bm["au_eq"] = au_eq
print('Average au : {:.3f}'.format(au.mean()))
print('Average cu : {:.3f}'.format(cu.mean()))
print('Average au_eq : {:.3f}'.format(au_eq.mean()))
Block model calculation
from maptek import vulcan
'''
The code below does calculation one block at a time and can be slower
but is generally simpler to use.
'''
au_price = 1320
cu_price = 3.02
with vulcan.block_model('small.bmf', "w") as bm:
for block in bm:
# Get the data to work with
au = block["au"]
cu = block["cu"]
# Set anything with values less than zero to zero (-99 or -9)
if au < 0:
au = 0
if cu < 0:
cu = 0
# Calculate the new values
au_oz = au * (1/31.1035)
cu_lb = cu * 2240
# Calculate the new equivalent
au_eq = (au_oz * au_price + cu_lb * cu_price) / au_price
# Update the values
block["au_eq"] = au_eq
au_eq = bm["au_eq"]
print('Average au_eq : {:.3f}'.format(au_eq.mean()))
Looping through a model on a single block basis
from maptek import vulcan
with vulcan.block_model('small.bmf') as bm:
au_sum = 0.0
for block in bm:
if(block['au'] > 0):
au_sum += block['au']
ave_au = au_sum / bm.n_blocks()
print('Average au : {:.3f}'.format(ave_au))