Você está na página 1de 11

22nd

MineSight® Grail
Annual Data Access and Embedded Scripts
Seminar Introduction
MineSight® Grail is a flexible and powerful scripting library for customizing MineSight®
for site implementation engineers and end users. In addition, MineSight® Grail is a
replacement for MINTEC’s traditional MineSight® Compass™ procedure language.
It exploits the richness of Python as a scripting interface and provides a flexible GUI
layout tool. MineSight® Grail procedures can be run inside of MineSight® Compass™,
use MineSight® Compass™ Multi-Run, run inside MineSight® 3-D, as well as executed in
standalone mode from a desktop shortcut or from a command window.
There are many instances when working with a MineSight® project that a user is
required to customize and automate a number of processes. The current customization
method is to use MineSight® Compass™ procedures, which are based on a proprietary
language developed by MINTEC over a number of years. While this has served our clients
well, extending the traditional MineSight® Compass™ procedure language is not a trivial
undertaking. Since we already have developed Python scripting experience in providing
user customizable reserve calculations in MineSight® Interactive Planner, it was decided to
extend the use of Python into a more general scripting interface into the system.
It is important to note that MineSight® Grail is not just a replacement for MineSight®
Compass™ procedures, but is a glue interface that lets us bind processes together in an
easy way, and provide a rich interface toolkit that can be embedded in or run independent
of MineSight® 3-D or MineSight® Compass™.
This paper will explore two major concepts that MineSight® Grail brings to MineSight®.
They are:
1. Open data access
The data that MineSight® programs and procedures store are now accessible via
MineSight® Grail. This paper will concentrate on working with Model, Geometry
MSR, and Drillhole data files.
2. MineSight® Grail Embedded
This is the phrase we use to refer to running Python scripts and using the MineSight®
Grail library to help automate tasks within MineSight® 3-D. In addition, this will also
allow on-site engineers to customize functions in MineSight® 3-D to help meet their
unique circumstances.
How Python Integrates with MineSight® 3-D
The popular scripting language, Python, integrates with MineSight® 3-D via the
MineSight® Grail library.
The MineSight® Grail library provides python modules that allow,
• Direct access to MineSight data files.
• Python script execution within a Multi-run context.
• Work with MineSight Interactive Planner.
• Access to the internal operations in MineSight-3D.
• The ability to build graphical user interfaces using Python.
The above can be summarized in a table as,
Table 1 Decribes what style of MineSight® Grail scripts can be used in what context.
In this table a Basic script refers to any Python script that imports a component of the
MineSight® Grail library—such as access to drillhole files—but does not require an instance
of MineSight® Compass™ or MineSight® 3-D to be active in order to run.

MineSight® Grail—Data Access and Embedded Scripts Page 1


Embedded
Minesight® Grail
Minesight®
Interactive Planner
Minesight®
Compass™ Style
Basic
22nd
Minesight® 3-D ü
Minesight Compass™
®
ü Annual
Minesight® ü ü
Interactive Planner
Command Line ü ü
Seminar
Combining the power of the Python scripting language with MineSight® Grail library
will allow one to customize MineSight® products for site-specific implementations.
Data Access Examples
Since the release of MineSight® Grail v1.0, the most popular feature has been the access
to the MineSight® data files. The flexibility of the Python scripting language combined with
the MineSight® Grail library allows you perform custom on-sight calculations using the
MineSight® data files to suit a particular business need.
We will focus on three major types of MineSight® data files,
1. Models—Provides read and write access to the 3-D model files.
2. Geometry—Provides read and write access to the MineSight® 3-D geometry files.
3. Drillhole—Provides read and write access to the drillhole files.
With these data files you can make your calculations and use MineSight® 3-D to view
the results.
The follow sections will review some of the common operations that can be performed
using MineSight® Grail and Python.
Models
Prior to MineSight® Grail v1.0 access to 3-D model data could only be done via
FORTRAN subroutines. Now, with MineSight® Grail’s grail.data.model module you
can access any 3-D block model file via a Python script.
One of the major benefits with the MineSight® Grail approach to accessing data is that
you can retrieve what are known as slabs from the 3-D model. These slabs are chunks of
cells that are defined by you when you extract the data. You are no longer limited to small
sets of model cells when working with 3-D models files, you can specify how you want to
traverse the model and find the representation that best suites your needs.
Let’s work through an example of model access to illustrate how to make a basic
computation for each cell in the model. To start, import the model module and define the
dimensions and items with which you wish to work,

from grail.data import model


lvlmin, lvlmax = 1, 10
rowmin, rowmax = 1, 500
colmin, colmax = 1, 500
items = [“CU”, “MOLY”, “EQ”]

We are going to traverse the model and use the model items CU, MOLY, and EQ.
Assume that the samp10.dat and samp15.dat files have the above dimensions and
items. You can always use the grail.data.pcf module to query the PCF file and
determine how the model file is formed. Now, set up the looping calculation.
# model access “grain” is row by row
for row in xrange(rowmin, rowmax+1):
# define and retrieve a “slab”
m = model.Model(“samp10.dat”, “samp15.dat”,

Page 2 MineSight® Grail—Data Access and Embedded Scripts


lvlmin, lvlmax,
22nd row, row,
colmin, colmax,
Annual slab = m.slab()
items)

for col in xrange(colmin, colmax+1):


Seminar for lvl in xrange(lvlmin, lvlmax+1):
# make our computation; if either MOLY or CU
# are missing, set EQ to missing.
moly = slab.modget(“MOLY”, lvl, row, col)
cu = slab.modget(“CU”, lvl, row, col)
if model.isdefined(moly) and model.isdefined(cu):
eq = moly*0.5 + cu*1.2
else:
eq = model.UNDEFINED
slab.modset(“EQ”, lvl, row, col, eq)

m.storeslab() # commit our changes back to the model.


m.free() # free up some underlying memory.
The two important features to note here are the grain of the model access and the use of
modget() and modset() for the access to the Model.
When we mention the grain of a model, we are referring to the most efficient method
for model access. In this case the fastest way to access the model is to define the slab on a
row-by-row basis and walk through the cells inside that row. However, you are in no way
limited to this scheme of iteration. The way you decide to access the model is completely
up to you and dependent on your particular problem.
The modset() and modget() methods on the slab object are new in MineSight® Grail v1.1.
Previously in v1.0, the indices for the slab object where always offset from 0 and went to
the maximum extent of the slab’s definition. For example, if you decided to extract a slab
with 5 by 5 by 5 dimensions from the middle of a Model file (say at 200, 200, 200), then you
would iterate across the slab from 0 to 4 in all dimensions. Where the slab at 0, 0, 0 would
correspond to 200, 200, 200 in the model. This behaviour is still preserved when you use
the square brackets, [ ], or use the get() and set() methods on the slab object. However, over
the last year this concept proved confusing to our users. To alleviate the confusion, we
introduced the modset() and modget() methods. These methods allow you to access the slab
with the exact same dimensions that you used to specify the slab. For example, if you extract
a slab that is 5 by 5 by 5 from the 200, 200, 200 location in the Model file, then you would use
200, 200, 200 to access the first cell in the Slab object using modset() and modget().
Geometry
The geometry MSR files contain 3-D information for MineSight® 3-D. With MineSight®
Grail v1.0 the grail.data.geometry module provides access to the 3-D (and 2-D) data
stored within the MSR.
An example of accessing the MSR is the truck.py script (shown below). This script
will read XYZ co-ordinate information and update the position of a label in a geometry file.
Combining this with the timed refresh option will allow you to view live truck movements
in your 3-D geometry. This script could easily be extended to using Dispatch’s add-on
called Powerview and allow you to get the truck position directly from an SQL database.
The truck.py script is as follows:
import sys, string, fileinput, time
from grail.data import geometry

MineSight® Grail—Data Access and Embedded Scripts Page 3


def isgeometryfile(msrpath):
“““attempt to open the file, if it works, then its an msr file.”””
22nd
try:
msr = geometry.Geometry(msrpath)
except GeometryError:
Annual
return 0 # not an msr
msr.free()
Seminar
return 1 # it was a msr

def readfile(pointfile,coords):
for i in fileinput.input(pointfile):
line = string.split(i)
x1 = string.atof(line[0])
y1 = string.atof(line[1])
z1 = string.atof(line[2])
CentList = [(x1,y1,z1),(x1,y1-1,z1),(x1-1,y1,z1)]
coords.append(CentList)
return coords

def markerdisplay(msrpath,coords):
msr = geometry.Geometry(msrpath)
for i in range(len(coords)):
msr.addsemitlabel([“Truck 1”],coords[i])
print coords[i]
msr.storeresource()
time.sleep(5) # time it waits before reading next point
msr.deletesemitlabelat(0)
msr.free() # Clean up pythons internal structure

def main():
coords = []
try:
# attempt to read the paths from the command line.
msrpath = sys.argv[1]
pointfile = sys.argv[2]
except IndexError, e:
print “error: require msrpath and pointfile path.”
if isgeometryfile(msrpath):
readfile(pointfile,coords)
markerdisplay(msrpath,coords)

if __name__==”__main__”:
main()

In this script, the user will enter a msrpath and a pointfile path when you start the script.
The script should be executed on a timer (using a Microsoft® Window’s task manager). The
script will go through the following steps,
• Read the point file to determine the trucks current location.
• Open the geometry file.
• Remove the old truck location, if one exists.
• Write the new truck location based on the point file.
Now, when Minesight® 3-D refreshes the Datamanager the new label location for the
Page 4 MineSight Grail—Data Access and Embedded Scripts
®
22nd truck will have changed. Using this script to retrieve truck location data from a database
would in effect show your truck positions live in a Minesight® 3-D project.

Annual Drillholes
Starting in Minesight® Grail v3.40-00, the library will provide the ability to extract,
manipulate, and modify data in your drillhole and blasthole files. For simplicity, we will
Seminar refer to drillholes sets, but the concepts also extend to blasthole sets.
A drillhole set is analogous to a drillhole view in Minesight® 3-D.
The drillhole set is composed of three components,
1. drillhole or blasthole files: a pcf, an assay or composite file, and possibly a survey file.
2. a method of naming the drillholes or blastholes.
3. a method of defining the drillhole or blasthole geometry.
All three of the above components must be specified when defining a drillhole set.
Methods are provided for defining (opening) a drillhole set, querying each of its
attributes, and reading and writing data to the drillhole files.
The following script illustrates looping across all drillholes in a sample drillhole set. For
each assay interval it will add the values for the items TOTCU and MOLY and store the
result in the XTRA1 item.
from grail.data import dh

# define a dhset
dhset = dh.opentypicaldhset(“samp10.dat”, “samp11.dat”, “samp12.dat”)

# get a list of the loaded dhs


dhs = dhset.loadeddhlist()

# loop over all the dhs in the set


for dh in dhs:
# make sure this dh has well-defined interval geometry
if dhset.dhbadintervalcount(dh) < 1:
# loop over the intervals in this dh. interval go from
# 1 --> dhintervalcount
for intv in range(1, dhset.dhintervalcount(dh)+1):
# retrieve this interval’s TOTCU and MOLY values
totcu = dhset.dhintervaldataat(dh, intv, “totcu”)
moly = dhset.dhintervaldataat(dh, intv, “moly”)
# if neither value is MISSING, add them and put the
# result in XTRA1. else put dh.MISSING in XTRA1
if totcu== dh.MISSING or moly== dh.MISSING:
xtra1 = dh.MISSING
else:
xtra1 = totcu + moly
dhset.dhintervalsetfloatdataat(dh, intv, “xtra1”, xtra1)

#store all the dhs


dhset.storealldhs()

# check a dh interval and make sure xtra1 = totcu + moly


# i happen to know this dh and interval are well-defined.

dh = “sm-021”
totcu = dhset.dhintervaldataat(dh, 6, “totcu”)
moly = dhset.dhintervaldataat(dh, 6, “moly”)
xtra1 = dhset.dhintervaldataat(dh, 6, “xtra1”)

print “dh = “, dh, totcu, “ + “, moly, “ = “, xtra1

MineSight® Grail—Data Access and Embedded Scripts Page 5


Minesight® Grail Inside Minesight® 3-D
Currently MINTEC is working towards using Minesight® Grail to control the increasing
22nd
functions of Minesight® 3-D. The process of embedding Python access to Minesight® 3-D
via Minesight® Grail is known as Minesight® Grail Embedded. Currently, with Minesight®
Grail Embedded you have access to such components as the Datamanager, the user
Annual
selection set, and CAD tools (triangulation and contouring).
The following sections will discuss some common examples of using Minesight® Grail
Embedded to execute tasks within Minesight® 3-D.
Seminar
Common Terms
When referring to working with Minesight® Grail inside of Minesight® 3-D we have some
common terms. Some of these terms and definitions are:
• Elements—This is the generic term for all types of 3-D data that is used in
Minesight® 3-D.
• Selection Buffer—This is a collection of elements that the user has highlighted as a
selection.
• Minesight® Objects—These are the files inside the Datamanager. A Minesight®
object can be any of the typical items that you work with when working with the
Datamanager.
How to Create an Embedded Script
This section will discuss the basic creation of a Minesight® Grail embedded script.
It will go through the process of creating a script that displays “helloworld!” in the
Minesight® 3-D message window.
Note that an embedded script has some extra components that must be considered
above and beyond the basic Minesight® Grail script.
The process for creating and running an embedded script involves first, editing your
script, then executing your script within Minesight® 3-D.
To start the creation of a basic helloworld script go to $(winexe)\scripts and copy
the em-boilerplate.py to a new file called helloworld.py
Now open the helloworld.py script and go to the run_code function, which will look
something like this:
def run_code():
“””Sample ‘function’ in embedded script.

This function will write some text out the message


window, but you can have it do anything you like.
“””
print “Boilerplate.”
Replace the “Boilerplate” text with “Helloworld!” The complete script can be found at
$(winexe)\scripts\em-helloworld.py of your 3.40 installation.
Running the Script
To execute the helloworld.py script, you must,
1. Start up Minesight® 3-D.
2. Select File | Run Script...
3. Use the file chooser to select helloworld.py
After selecting the file, the script will execute. The “Helloworld!” string will be
displayed within your Minesight® 3-D message window.
Details
This simple example can be useful for discussing a few points regarding embedded
scripts,

Page 6 MineSight® Grail—Data Access and Embedded Scripts


22nd Using grail.ms3d
Any script that has a “from grail.ms3d import...” line within it is termed a
Minesight® Grail embedded script. This means that the script can only be executed
Annual within the context of a Minesight® 3-D environment.
Notice, that since Minesight® Interactive Planner (IP) is also within Minesight® 3-D
you can use embedded features within a Minesight® IP script.
Seminar What is gmain?
The gmain function is a standard entry point for all scripts. This is the location in
the script through which any Minesight® product can communicate.
Of the numerous messages that can travel through a gmain function you are
generally only concerned with the messages.gRUN message. All messages can be
found in the grail.messages module.
Redirecting the Output
To allow use to use the Python print statement we use a neat trick whereby we
redirect the standard system output (sys.stdout). The redirection is done in the
following line,
sys.stdout = mssys.stdout
This line is saying, “Do not use the python standard output, use the Minesight®
3-D standard output instead.” This is equivalent to telling Python to send all print
statements to the Minesight® 3-D message window.
Working with the Selection Buffer
The idea is to allow you to gain access to everything that a user has selected and stored
within the selection buffer. The user will select their elements, and then execute a script
that will work with the selected elements.
As an example, consider running a script that will look at each element within the
selection and report on its area. If the element does not have an area, for example a marker,
it will simple report n/a for not applicable. The script is as follows:
import sys
from grail import gsys
from grail import messages
from grail.ms3d import elementop
from grail.ms3d import selectionbuffer
from grail.ms3d import mssys
from grail.ms3d import project

# re-wire the “print” statement to the message window.


sys.stdout = mssys.stdout

def gmain(msg, data):


“””Main entry functin.”””
if msg is messages.gRUN:
areareport()
else:
return gsys.grailmain(msg,data)

def areareport():
elements = selectionbuffer.getelements()
if elements == []:
mssys.stdout.write(“There where no elements selected.”)
else:
reportareas(elements)

def reportareas(elements):
print “Element Name, Area”
cnt = 0

MineSight® Grail—Data Access and Embedded Scripts Page 7


for element in elements:
try:
areastr = ‘%f’ % (elementop.calcarea(element))
22nd
cnt += 1
except TypeError, e: # element has no area (i.e. markers)
areastr = “n/a”
Annual
print “%s, %s %s^2” % (element.getname(),
areastr,
getprojectdim())
Seminar
print “Computed %d areas.” % (cnt)

def getprojectdim():
if project.getunittype()==project.METRIC:
return “m”
else:
return “ft”
Early on in the script, we inform python that it will use mssys.stdout for all its print
statements. Using mssys.stdout will ensure that all print statements are displayed in the
Minesight® 3-D Message window.
The elements are retrieved in the selectionbuffer.getelements() statement, and a loop
across all the elements is performed with the area calculated for all elements that can have
an area.
The area is then reported to the message window via the print statement.
Manipulating the Datamanager
With Minesight® Grail Embedded you will also be able to manipulate objects within the
Datamanager. These objects are commonly referred to as Minesight® Objects (MOBs).
Currently, you can create a new MOB of type geometry and populate it with geometry
objects. This technique will be used for the automated triangulation and contouring
examples also described in this paper.
However, as a simple example of creating a Datamanager object and inserting a
polylines consider the following script:
import sys
from grail import gsys
from grail import messages
from grail.ms3d import element
from grail.ms3d import mssys
from grail.ms3d import datamanager

# re-direct print statements to the message window.


sys.stdout = mssys.stdout

def gmain(msg, data):


if msg==messages.gRUN:
drawpolylines()

def drawpolylines():
# create our polygon elements to store in the
# geometry object.
numpolylines = 10
polylines = [None]*numpolylines
print “creating polylines...”,
for idx in range(numpolylines):
points = [[-10., -10., float(idx*10)],
[0., 0., float(idx*10)],
[10., 10., float(idx*10)]]

Page 8 MineSight® Grail—Data Access and Embedded Scripts


22nd polylines[idx] = element.createpolyline(points)
print “OK.”

Annual if datamanager.isobject(“\\newobject”):
print “removing \\newobject...”,
datamanager.remove(“\\newobject”)

Seminar print “OK.”

print “creating geometry object...”,


g = datamanager.create(“\\newobject”,
datamanager.GEOMETRY_OBJECT,
“\\materials\\Geometry”)
print “OK.”

print “adding polylines...”,


g.addelements(polylines)
print “OK.”

This script generates 10 polylines, a new Minesight® object within the Datamanager, and
stores those polylines within that Datamanager object.
Automating Triangulations
Running triangulates can be a time-consuming and repetitive task. Now with Minesight®
Grail v1.2 and Embedded Grail within Minesight® 3-D v3.4 you will be able to run a
triangulation routine on any Element that you extract from either the selection buffer or
from a Datamanager Minesight® Object (MOB).
The follow small script illustrates the triangulation of all data stored in MOBs within the
data folder in the Datamanager.
import sys
import os
import time

from grail import gsys


from grail import messages
from grail.ms3d import datamanager
from grail.ms3d import progressmeter
from grail.ms3d import mssys
from grail.ms3d import element
from grail.ms3d import elementop

sys.stdout = mssys.stdout # all “prints” go to the message window.

def gmain(msg, data):


“””Main entry point.”””
if msg is messages.gRUN:
run()
else:
return gsys.grailmain(msg, data)

def ispolyline(el):
“””Indicates if a given element is a polyline or not.”””
return el.gettype() in [element.PolylineType, element.PolygonType]

def run():
print “-”*50+”\nstarting triangulation (%s) ... “ % (sys.argv[0])
for item in datamanager.listfolder(“\\data”):
srcpath = os.path.join(datamanager.ROOT, “data”, item)
dstpath = os.path.join(datamanager.ROOT, “data”, “tri_”+item)

MineSight® Grail—Data Access and Embedded Scripts Page 9


triangulateobj(dstpath, srcpath, “\\materials\\Geometry”)
print “ triangulated: ‘%s’ -> ‘%s’” % (srcpath, dstpath)
print “... done.\n”+”-”*50
22nd
def triangulateobj(dstpath, srcpath, materialpath):
mob = datamanager.open(srcpath)
Annual
polylines = filter(ispolyline, mob.getelements())
mob.close()
surface = elementop.triangulate(polylines)
Seminar
mob = datamanager.create(dstpath,
datamanager.GEOMETRY_OBJECT,
materialpath)
mob.addelements([surface])
mob.close()

The above script works with the Datamanager to find polylines within the data folder to
triangulate. The triangulation in this case is a simple triangulation operation, but the effect
is a surface. Each surface is stored as “tri_xxx” where “xxx” is the original name of the
Datamanager object that contained the polylines.
One can easily combine the triangulation operation shown above with the contouring
operation shown below. With these two steps one can take a series of polylines, generate a
surface, and then generate a contour interval to their specifications.
Automating Contouring
With the Minesight® Grail Embedded you will be capable of generating contours for a
given surface.
The contour operation is the basic creation of a polylines for a given elevation on a
surface. A smoothing operation is left as another operation to be executed on the resultant
contour polylines.
The following script will open every Minesight® geometry object in the \data directory
of the Datamanager. It will look for surfaces and generate contours for that surface. Those
contours will be stored back into a file prefixed with “cont”. Generally you would have
some specific set of regular and index contours you wish to generate for your surfaces,
but for purposes of illustration, this script will just apply a percent of contours base on the
elevation difference for a particular surface.
The contour.py script is as follows:

import os, sys

from grail import gsys, messages, ag


from grail.ms3d import datamanager, progressmeter,
from grail.ms3d import mssys, elementop, element

sys.stdout = mssys.stdout # redirect “print” to the message window

# Prefix in front of new geometries.


PREFIX = “cont_”
# Folder we scan for geometries to contour.
SAMPLE_FOLDER = “\\data”
# Decimal percent for the number of contours per surface.
CONTOUR_PERCENT = .50

def gmain(msg, data):


if msg is messages.gRUN:
runcontour()
else:
return gsys.grailmain(msg, data)

Page 10 MineSight® Grail—Data Access and Embedded Scripts


def runcontour():
22nd materialpath = os.path.join(datamanager.ROOT,
“materials”,
“Geometry”)
Annual for item in datamanager.listfolder(SAMPLE_FOLDER):
srcpath = os.path.join(datamanager.ROOT, “data”, item)
dstpath = os.path.join(datamanager.ROOT, “data”, PREFIX+item)
Seminar contouritem(dstpath, srcpath, materialpath)
print “ contoured: ‘%s’ -> ‘%s’” % (srcpath, dstpath)

def issurface(el):
return el.gettype() == element.ShellType

def contouritem(dstpath, srcpath, materialpath):


“””For all the surfaces in the srcpath, generate contours.”””
mob = datamanager.open(srcpath)
surfaces = filter(issurface, mob.getelements())
mob.close()

contours = []
for surface in surfaces:
min, max = ag.pointlistboundingvolume(surface.getpointlist())
minz, maxz = min[2], max[2]
diff = maxz-minz # only need to examine “Z”
step = diff/(diff*CONTOUR_PERCENT)
print “ contouring with: [%f, %f) and steps of %f” %\
(minz, maxz, step)

# append to our growing list of contours.


contours += elementop.contour(surface, minz,
maxz+ag.EPSILON, step)

# If we have contours from the above loop across the surfaces


# then generate a datamanager object and store the values.
if bool(contours):
mob = datamanager.create(dstpath,
datamanager.GEOMETRY_OBJECT,
materialpath)
mob.addelements(contours)
mob.close()

Summary
Using Python with Minesight® Grail allows you to accomplish a multitude of tasks for
your business needs. The Minesight® Grail library will provide you with the ability to
access Minesight® data in any way that you see fit. In the future, Minesight® Grail will be
used to help automate and customize your Minesight® 3-D experience.

MineSight® Grail—Data Access and Embedded Scripts Page 11

Você também pode gostar