Download as pdf or txt
Download as pdf or txt
You are on page 1of 74

Pyython

n for
M
MineSigght® Plann
ner
INTERNAL USSE ONLY

Pyython for MiineSight® Plaanner |


Table of Contents

Introduction ..................................................................................................................................... 1
Properties in MSPlanner .................................................................................................................. 2
Creating Properties ............................................................................................................................................................. 2
Summary Types ................................................................................................................................................................... 4
Formatting........................................................................................................................................................................... 5
Calculations ......................................................................................................................................................................... 7

Python Fundamentals ...................................................................................................................... 9


Variables.............................................................................................................................................................................. 9
Displaying Output ............................................................................................................................................................. 11
Data Types......................................................................................................................................................................... 12
Type Casting ...................................................................................................................................................................... 18
Comments ......................................................................................................................................................................... 21
Comparison Operators ...................................................................................................................................................... 22
Logical Operators .............................................................................................................................................................. 23
Decision Making ................................................................................................................................................................ 24
Looping .............................................................................................................................................................................. 25
Functions ........................................................................................................................................................................... 28
Built-in Functions .............................................................................................................................................................. 30
Modules ............................................................................................................................................................................ 34

Sample Property Calculations ......................................................................................................... 36


Example 01: Assign Geometry Element Name to a Property ........................................................................................... 36
Example 02: Selectively extract text from a given String.................................................................................................. 36
Example 03: Extract Level number from the standard Level Attribute ............................................................................ 38
Example 04: Retrieve a value from a lookup table based on another Property............................................................... 40
Example 05: Set Phase based on Numeric value stored in another Property .................................................................. 42
Example 06: Map Material to Destinations based on Grade and Phase .......................................................................... 45
Example 07: Calculate Ore and Waste Tonnes ................................................................................................................. 47
Example 08: Calculate Stripping Ratio .............................................................................................................................. 49
Example 09: List all Material types within a Cut ............................................................................................................... 51

Process Points ................................................................................................................................ 53


Creating Process Points ..................................................................................................................................................... 53
Calculations ....................................................................................................................................................................... 55

Python for MineSight® Planner | i


Basic Usage ....................................................................................................................................................................... 57

Sample Process Point Calculations ................................................................................................. 61


Example 01: Simple Material Mapping based on Grade Cutoff........................................................................................ 61
Example 02: Split Material between multiple Destinations ............................................................................................. 63
Example 03: Drying out wet Material ............................................................................................................................... 65

Appendix ....................................................................................................................................... 68
Code Window Keyboard Shortcuts ................................................................................................................................... 68

Python for MineSight® Planner | ii


Introduction
MineSight Planner (MSPlanner) is an interactive material reporting and manual scheduling tool used
to create, evaluate, implement, and report mining schedules. It expands upon the functionality of
MineSight Interactive Planner (MSIP), and delivers more robust features in a new, enhanced user
interface. MSPlanner is ideally suited for high-level manual scheduling, as a data repository for block
model reconciliation, and for grade control operations.

One of the most important features in MSPlanner that affords users a large degree of control and
customization is that of “Properties” – custom attributes that can hold different types of data for
individual mining cuts in a project. Properties may be populated with either simple Tokens, or
complex calculations that can include logical and conditional decision-making. The latter is
accomplished via code snippets written using the Python programming language.

This manual aims to provide all the necessary information required in order to start creating and
customizing Properties in MSPlanner. We will examine the creation of different types of Properties,
the use of inbuilt Tokens, and most importantly, learn fundamental Python programming concepts
and how to apply them in the creation of useful Properties.
Python for MineSight® Planner | 1
Properties in MSPlanner
“Properties” in MSPlanner are akin to “Attributes” in MSIP, i.e. they provide a way to store custom,
user-defined information per mining cut in the project. The nature of the information being supplied
or stored will dictate the data type of a Property, which must be set at creation time, along with a
unique name.

Creating Properties

Properties are set up and managed under the “Configuration” section of the Backstage, and can be
added, removed or modified at any time.

When a Property is first created, a unique name and data type must be specified. These two
attributes are not modifiable once the Property has been created, so it is important to identify
beforehand the type of information that Property will be storing. There are six different data types
available:

TYPE DESCRIPTION EXAMPLE

Integer A numeric value without a decimal component. 32, 512, 800

Double A numeric value with a decimal component. 75.5, 3.1416

String A sequence of text that can comprise a combination “Level 2000”,


of alpha, numeric, and special characters. “HG_Stk”

Python for MineSight® Planner | 2


Enumeration A list containing all possible values that a Property “Phase 01”, “Phase
may have. The values entered may be alphanumeric, 02”, “Phase 03”, 04,
however when accessing them programmatically, 05, 06
they must be referenced as Strings.

DateTime A date and time value returned as a single result.


Individual components of the date and/or time can be 16/05/2014 10:00 AM
also be accessed programmatically.

If the value of the Property being created is dependent on other Properties, it must be marked as a
“Derived Type” to ensure that its value is automatically recomputed each time any of the Properties it
depends on change.

Once a Property has been created, you can set its value in different ways, depending on the data type
it uses. Integer, Double, DateTime, and TimeSpan types can have a default, minimum and maximum
value, String types can have a default value, and Enumerated types can have a list of possible values
and a default value. The true power of a Property, however, lies in its ability to use a calculation for
each of these data types in order to assign values. This allows you to build smarter, more dynamic
Properties that can convey much more information easily. Calculations are written in the Python
programming language, with a large number of predefined functions and variables available to help
minimize the effort required to build complex calculations. Calculations can be tested to ensure that
they are syntactically and logically correct, and results can be previewed instantaneously.

Python for MineSight® Planner | 3


Additionally, String type Properties can make use of predefined Tokens for relatively simple cases,
similar to other MineSight 3D (MS3D) tools, albeit with a slightly different syntax.

Properties can also be created to display Grade item values per cut from the project’s associated
Reserve Logic file. In the case of these, the Property Name is automatically set to the Reserve Logic
item name, and the Data Type, Dependent Properties, and Calculation Code are all automatically set
as required.

Summary Types

For numeric Properties (Integer and Double types), an additional “Summary” field is available, which
lets you specify how the values of the Property in question will be summarized for reporting (i.e.
applicable to “Reporting” mode only).

A total of nine summary options are available:

OPTION DESCRIPTION

None Not summarized.

Count Reports the total number of occurrences of values of the group.

Python for MineSight® Planner | 4


Minimum Reports the minimum value of the group.

Maximum Reports the maximum value of the group.

Sum Reports the sum total of the values of the group.

Average Reports the average value of the group.

Tonnes Weighted Average Reports the tonnes weighted average of the group.

Volume Weighted Average Reports the volume weighted average of the group.

Weighted Average Reports the weighted average of the group based on the weighting
item selected.

User-created numeric Properties have a default summary type of “None”, whereas Properties defined
by Reserve Logic grade items bring across their respective summary type from the Reserve Logic
setup.

Formatting

In addition to the Summary types described above, a Formatting feature is available for numeric
(Integer and Double types) and date/time (DateTime and TimeSpan types) Properties. This allows you
to customize the display of the Property’s value – for example, number of decimal places to show for
a Double, day-month-year order and type for a DateTime, etc.). A list of available formatting options
can be viewed by clicking the “[ i ]” icon under the “Format” section. This pops up a dialog showing all
Python for MineSight® Planner | 5
available format specifiers for different data types. Additional information is available online from the
“More info” hyperlinks.

It should be noted that the result displayed by testing a Property’s calculation does not honour any
format specifiers. These are only honored when displaying Properties in Activity Lists.

Python for MineSight® Planner | 6


This holds true for both, numeric and date/time Properties.

String type Properties do not feature any such options as they are literal text and are hence displayed
as setup. Additionally, you can make use of Python formatting functions to alter the display of
Property values that make use of calculations. This may give you finer control than the inbuilt
formatting features in some scenarios, should you require it.

Calculations

To customize the value of a Property, you will want to use a calculation to specify how its final value is
derived. When you elect to “Use Calculation” after creating a Property, the interface presents you
with a calculation panel split into two vertically.

Python for MineSight® Planner | 7


The left side consists of a “Code” window, which is where all calculation logic is entered using Python
snippets. This section also allows previewing results and any error messages in case of incorrect code,
by popping up a “Result” pane whenever a test is run. The right side consists of a “Test” section,
which allows you to see the effect your code has on one or more Activities that are currently in the
project, and a “Variables” section, which includes several inbuilt attributes and functions that you can
use to help speed up the creation of your calculation logic.

To enter your calculation logic, simply place your cursor in the “Code” window and begin adding
Python snippets. You may also use the “[+]” button next to any of the inbuilt variables to insert their
value at the current position of your cursor in order to save time. The code window automatically
adds line numbers as you type; these are important and extremely useful in troubleshooting any
syntax errors that come up when testing, as the “Result” pane will convey the line number at which
an error has been detected.

Python for MineSight® Planner | 8


Python Fundamentals
Python is a widely used multi-purpose high level programming language, with an emphasis on code
readability and ease-of-use. It has an extensive standard library (i.e. a collection of ready-to-use
modules and functions for several different purposes like math, cryptography, file I/O, etc.) and
thousands of online tutorials, and is cross-platform, open source, and free – even for commercial use.
It is also a popular choice for a scripting language where developers wish to allow end users to extend
their application’s functionality – similar to how we implement its use in MineSight tools.

This section will focus on explaining all the core concepts of the Python language necessary to create,
work with, and understand Properties in MSPlanner. We will look at generic examples of
implementing each of the concepts first, and then learn how to apply these specifically to Properties
in MSPlanner. More often than not, you will need to combine multiple concepts to achieve the
desired result, so having a basic understanding of these beforehand is vital.

Variables

When writing any sort of computer application, you are essentially reading in information from one or
more data sources and performing one or more operations on it to produce a useful end result. For it
to be processed, data is loaded into RAM (Random Access Memory) and stored in blocks, with each
piece of information receiving a unique address. The data and the addresses exist in low-level
computer language, which might look something like this:

So as a programmer or script writer, how are you to access such obscurely-named memory locations?
Variables are the answer.

A variable is a user-defined name which references a specific memory location that holds certain
information. This information may be one of many standard Python data types (discussed later), and
once associated with a variable, can be referenced by simply using its name. For this reason, it is
important to ensure that all variables receive meaningful names.

Python for MineSight® Planner | 9


The symbol used to associate a given value with a variable is a single equal sign (=), technically known
as an assignment operator.

SYNTAX

<variableName> = <value>

Variable names typically start with a lowercase letter. If using a multi-word name, use camel
casing, wherein the first letter of every subsequent word is written in upper case. Underscores
are also acceptable as separators between words, however spaces cannot be used.

Python variables are dynamically-typed, meaning there is no need for you to explicitly specify a data
type when defining a variable; this is automatically determined as soon as a value is assigned to the
variable.

In the above example, “cutPhase” is a String type, and “millCapacity” is an Integer type.

Properties in MSPlanner make use of a special system variable called “Result”. After performing the
necessary calculations, you must always finish off by assigning the end result to this variable in order
for tests to run correctly and the Property to receive its value and display it in the Activity List. The
“Result” variable is the one exception where name must start with an uppercase letter.

As briefly mentioned previously, there are also several inbuilt variables available to help write your
calculation logic. These appear to the right of the “Code” window. The list is quite extensive and
contains several different types of variables, from geometric properties to certain MSPlanner project
settings and more. Properties that you have previous defined will also be added to this list, meaning
Python for MineSight® Planner | 10
you can use the result of one Property’s calculation in another. This is useful for building complex
Properties and can help keep the code clean and easy to read. Each variable lists an example value
(based on the Activity selected from the “Data” drop-down menu) and the data type it represents
alongside its name.

Displaying Output

Displaying information to the end user in a timely manner is one of the most basic and important
features of any software program, be it information dialogs, warnings, or error messages. Python
provides an extremely simple way of doing this, and although this is not a requirement to work with
Properties, it can be useful for debugging purposes, especially when writing more complex
calculations.

The print statement in Python is used to display output on the screen. This can be virtually anything –
literal text, numbers, special characters, or any expression that can be evaluated.

SYNTAX

print <value>

Python for MineSight® Planner | 11


When creating Properties, the print statement can be used to display information in the “Result”
window whenever a test is run. This can help check values of variables at different points of execution
and is a great way to ensure your calculation logic is working as expected.

Data Types

Python data types may be broadly classified into four categories – String, Numeric, Boolean, and
Containers. A number of functions can be applied to each of these data types to help with data
access, manipulation, formatting, etc.

NUMERIC

The standard numeric data types in Python include Integer and Floating Point numbers. These
correspond directly to the Integer and Double data types available when creating Properties. Accuracy
is “technically” unlimited in the case of integers (memory-constrained), and is limited in the case of
floating point numbers (approximately 17 decimal places). Standard math operations can be applied
to these types as expected – Addition (+), Subtraction (–), Division (/), Multiplication (*), Modulo (%),
and Exponent (**).

Division forms a special case when integers are involved and hence must be performed with care.
Integer division will always return an integer result, rounded down. Specifying the divisor as a floating
point number will return a floating point result, thus ensuring accurate division.

Python for MineSight® Planner | 12


Another point worth keeping in mind is that division by zero is undefined, so your calculation will
return a syntax error if a divide by zero occurs anywhere in the code.

STRING

A string can be a collection of any alphanumeric characters, and is denoted by a pair of quotes, either
single (‘ ‘) or double (“ “). Multiple strings can be joined together using a plus sign (+), a process
known as concatenation.

Since a string is effectively a list of characters, it can be sliced using List notation (more on Lists later)
to access specific portions of it. The first character starts at index 0 and counts upwards in increments
of 1. Note that string slicing is for read-only purposes – you cannot modify individual characters by
assigning a new one using this technique.

Python for MineSight® Planner | 13


SYNTAX

<value>[<startCharacterIndex> : <endCharacterIndex>]

Character index is zero-based.

Apart from slicing, knowing how to split a string is also extremely handy. This works best when you
have a string made up of multiple values, each of which is separated by some common character. In
this case, you can split the string at that character, which results in a list of individually accessible
values that made up the complete string.

SYNTAX

<value>.split(“<character>”)

Once you split a string, you can access the individual components by indexing into the list. If
your string contains multiple characters, you can run multiple passes of the split() function.

Python for MineSight® Planner | 14


BOOLEAN

This is a special data type that is used to represent the truth or falsehood of a statement. It can only
ever be one of two values – True or False. These are Python keywords and are case sensitive. They
most commonly are a result of a comparison or conditional statement, and indicate whether the
condition passed (True) or failed ( False).

In the example above, we are first checking to see whether 5 is greater than zero, and then checking
to see if 16 is less than 8. We are also simultaneously printing out the result of each comparison,
which results in a “True” (because 5 is indeed greater than zero) and a “False” (because 16 is
definitely not less than 8) respectively.

CONTAINERS

Python has 3 main container types – Lists, Dictionaries, and Tuples. These are known as containers
due to their ability to store multiple values to one variable, as opposed to a standard String or Integer
type, which can only hold one value at a time. Data stored in a container needs a single contiguous
block of memory, so caution must be exercised when using these in order to avoid running out of
memory. Of these, lists and dictionaries are the most commonly used, and we shall examine them in
detail.

A List is an ordered collection of values that is mutable (i.e. the values are modifiable in place). The
values can be of mixed data types, meaning you can have a single list that stores Integers, Doubles,
Booleans, and Strings. Furthermore, lists can also be nested inside other lists, but this should be done
Python for MineSight® Planner | 15
only when really necessary and not beyond a certain depth. Values within a list (known as the list’s
elements) are accessed via numeric index, starting at 0 and ending at n – 1, where n is the total
number of elements in the list.

SYNTAX (Creation)

<variableName> = [<value1>, <value2>, <value3>…<valueN>]

You can create an empty list to begin with and then add elements to it as and when required.

SYNTAX (Access)

<listName>[<index>]

You can modify an existing list item by assigning a new value to its index; the new value occupies this
place in memory and the old value is lost.

You can also continue to add values to a list once it has been created using the append() function.
Elements are appended at the end of the list, which automatically expands in size to accommodate
the new information.

Python for MineSight® Planner | 16


SYNTAX

<listName>.append(<value>)

A Dictionary is an unordered collection of Key:Value pairs that is mutable (i.e. the values are
modifiable in place). Keys and values can be of mixed data types, meaning a String key can be used to
reference an Integer value. Unlike lists, values within a dictionary are accessed via their key names
and not via a numeric index.

SYNTAX (Creation)

<variableName> = {<key1> : <value1>, <key2> : <value2>…<keyN> : <valueN>}

SYNTAX (Access)

<dictionaryName>[<key>]

You can modify an existing value by assigning a new value to its key; the new value occupies this place
in memory and the old value is lost.
Python for MineSight® Planner | 17
You can also retrieve separate lists of all the keys and values contained within a dictionary using the
keys() and values() functions.

SYNTAX

<dictionaryName>.keys()
<dicitonaryName>.values()

Using the values() function is the quickest way to convert a dictionary into a list.

Type Casting

As the name suggests, type casting refers to the process of taking a particular data type and
converting it to another data type. This can be applied in a few different cases and occasionally may
even be necessary in order to get correct results, depending on the information you are working with.
It is most commonly used when performing calculations and displaying output containing String and
Numeric data. Data can be type cast to a String, Integer, or Float type.

Python for MineSight® Planner | 18


SYNTAX

int(<value>)
float(<value>)
str(<value>)

In the example above, we perform a simple integer division, which as mentioned previously, results in
loss of accuracy. By type casting the divisor to a floating point number, we no longer perform an
integer division and thus end up with an accurate result.

Another common instance where type casting is necessary is when using the print statement to
display mixed data type output. For example, say you performed some calculations and wish to
display the final result along with a short message. You would type out your message and then
attempt to concatenate the result of the calculation to print them out together. However, you will see
that this won’t work as expected:

Python for MineSight® Planner | 19


The reason for this is because you are attempting to mix two different data types – a String and an
Integer – via the concatenation operator, and this is not possible. If you run the same example with a
simple String type cast however, the print statement works as expected:

It is important to remember that the data type of the value assigned to the “Result” variable for a
Property must always match the data type selected when the Property was created. In some cases
(especially Numeric types), it is possible to have a mismatch and still get a valid result, however when
tests are run, the “Result” window will warn you of this.

In the following example, an Integer type Property was created, but a floating point division was
carried out, resulting in a floating point value being assigned to “Result”. In this case, the test still
passes, but a warning message is issued.

If you choose to continue, the Property will still appear in the Activity List, however its value will be
inaccurate because its Integer data type will forcefully round the result to the nearest whole number.

Python for MineSight® Planner | 20


Comments

Quite often, code written by one person may be used, reviewed, or maintained several other people.
This would be especially true for a project that was shared amongst several users or departments, as
is often the case with mine sites. Hence, it is important (and considered good practice) to document
your code as it is being written, so that other users can quickly gain an understanding of what is going
on, rather than having to work this out manually by reading the snippets line by line.

This is where the concept of commenting comes in. Comments are specially marked lines of text that
help document and understand program code and logic. These are completely ignored by the
compiler, and may be placed anywhere within your Property calculation.

There are two types of comments – single-line (denoted by a hash) and multi-line (denoted by a set of
triple single quotes).

SYNTAX (Single-line)

# <Comment text here>

SYNTAX (Multi-line)

‘’’ <Comment line 1 here>


<Comment line 2 here>

<Comment line n here> ‘’’

Python for MineSight® Planner | 21


Comparison Operators

Comparing values against one another is extremely common in any program, and there are a standard
set of operators to be used for this purpose. All data involved in a comparison must be of the same
data type. Comparison operators are heavily used in decision-making logic.

OPERATOR DESCRIPTION

== Is Equal To

!= Is Not Equal To

> Is Greater Than

< Is Less Than

>= Is Greater Than or Equal To

<= Is Less Than or Equal To

SYNTAX

<value1> <operator> <value2>

Python for MineSight® Planner | 22


Logical Operators

Going hand-in-hand with comparison operators are logical operators, which are used to combine one
or more expressions. There are 3 types of logical operators, and these can be mixed and matched in
any combination to help build powerful and complex logical expressions. They are also very useful in
decision-making.

OPERATOR DESCRIPTION

and Match both conditions

or Match either of the conditions

not Invert the logic of the condition

SYNTAX

<expression1> and <expression2> and … <expressionN>


<expression1> or <expression2> or … <expressionN>
not <expression>

For complex expressions involving multiple logical and comparison operators, use round
brackets to group statements appropriately. This is especially important when using the not
operator.

Python for MineSight® Planner | 23


Decision Making

While the concepts presented so far are at the core of any and every programming task, they do not
allow for any “smarts” to be added into your calculation logic. Quite often, performing simple math
operations and comparisons between values in a linear fashion are not enough to achieve the desired
results – your program or calculation may need to make certain choices based on a set of existing
conditions in order to reach an appropriate result.

This is the basic premise for decision making in programming. It allows a program to evaluate one or
more conditions and then decide on the right course of action. Comparison and Logical operators play
a major role in writing good, efficient decision making code, so you should be well-versed in their use.
In complex scenarios, you can have multiple levels of nested decision making logic, although every
effort should be made to keep this to a minimum. Lastly, always take care to provide a failsafe path –
one that can be taken if none of the prevailing conditions are satisfied.

SYNTAX

if <expression> <comparison> <value>:


<do this>
elif <another expression> < comparison> <value>:
<do that>
else:
<do something else>

Take note of the single tab-space indentation that follows each “if”, “elif”, and “else” statement – this
is part of Python’s syntax and helps the program identify what statements must be executed if a

Python for MineSight® Planner | 24


condition is met. When writing snippets for Properties, these tab spaces are to be added manually. If
nesting multiple decision blocks, the level of indentation must increase by one tab space per block.

Looping

At times, it is necessary to have your code perform a certain action or set of statements repetitively. A
simple example would be that of opening a file, reading its contents line by line, performing some
operations on each line, and then writing the results to another file. This is known as looping, a
process in which a program reiterates over a set of statements based on either a set number of
repetitions or some conditional logic. The statements to be executed are nested into the loop by one
tab-space, similar to using an if-else condition. There are two main types of loops that can be used in
Python, and their usage mainly depends on context and purpose.

FOR LOOP

A for loop is typically used when the number of repetitions to be performed is known beforehand. It
makes use of a variable that is incremented after each iteration, which is commonly referred to as the
loop counter.

SYNTAX

for <control variable> in <collection>:


<do something>

Use the range() function to implicitly generate a list of numbers given a minimum and maximum
value. The list will run from minimum to maximum – 1.

Python for MineSight® Planner | 25


WHILE LOOP

A while loop is normally used when the exact number of iterations is unknown, and so a conditional
expression is used to control looping instead. It continues to iterate over the given statements for as
long as the condition is satisfied.

SYNTAX

while <condition>:
<do something>

Care should be taken while constructing loops to ensure that an exit point is always reached
eventually, and that the program does not go into an infinite loop.

In the examples above, once the loop begins to execute, you must wait for all iterations to complete
before it proceeds with executing the rest of the code (if any). However in some scenarios, this isn’t
necessarily the most elegant solution. Consider a list of 1000 unique items. You want to iterate over
this to find a particular item and use it in some fashion. Suppose the item you wanted was the 50th in
the list – using the syntax shown above as-is would result in wasted processing time, as the loop
would continue running and checking item 51 to item 1000. This is not efficient at all, and can have
major implications in large applications. For this reason, there are two operations specific to loops
that can be performed to modify the flow of the loop as it runs. These are the break and continue
operations.

BREAK

The break statement forces immediate termination of the loop that contains it. As soon as it is
reached, the program jumps out of the loop and returns control to the next line of code. All pending
iterations for that loop are instantly skipped.
Python for MineSight® Planner | 26
SYNTAX

for or while loop:


<do something>

break

In the above example, we have a dictionary of Lithology codes and their corresponding String names.
We want to extract the name for code 6 using a loop. In this case, we use the break statement to stop
looping as soon as a match is found as we no longer need to keep the loop running.

CONTINUE

The continue statement causes a jump to the start of the containing loop and performs the next
iteration immediately. This means that as soon as this statement is encountered, any remaining
statements waiting to be executed within the loop in the current iteration are skipped over.

SYNTAX

for or while loop:


<do something>

continue

Python for MineSight® Planner | 27


The above example prints all odd numbers between zero and ten, by dividing each number by 2 and
checking to see if the remainder is zero. In this case, as soon as we know the remainder is zero, that
number is even, so we use the continue statement to start the next loop iteration immediately, which
skips printing the number.

Functions

Occasionally, you might find yourself dealing with some highly complex calculations or program logic
that requires several lines of code to accomplish a given task. In such scenarios, having dozens or even
hundreds of lines of code one after the other in a huge block makes it difficult to understand and
maintain later on. For these reasons, it is important and beneficial to try and separate pieces of code
logically. While this may require some more time initially, it will pay off in the long run when it comes
to modifying or reusing large chunks of code. This is where functions can help.

A function is a collection of statements that perform some specific task. Separating code blocks into
functions provides a cleaner look, promotes reusability, and makes maintenance easier.

SYNTAX (Definition)

def <functionName>(<parameters>):
<do something>
return <value>

SYNTAX (Function Call)

<functionName>(<parameters>)

Parameters and return values are optional components.

Python for MineSight® Planner | 28


Once a function has been defined in your code, it can be called from anywhere within the calculation.
When a function call is executed, control jumps to the function immediately, executes all the
statements contained within, and then returns back to the point where it was called from. For
functions that return a value, you must assign the function call to a variable so that its value can be
stored for later use.

In the above example, two simple functions have been defined – one for addition and the other for
subtraction. Each function takes two parameters a and b, and then returns the sum or the difference
of those values, respectively. Because a value is being returned, we assign the function call to our
“Result” variable, where the value is stored.

Much like breaking out of loops, program control can be forced to return prematurely from within a
function back to the point of call using the return keyword by itself, i.e. not followed by any value.

In the above example, we have a function that performs division between two give numbers, a and b.
However, if b (the divisor) turns out to be a zero, we display an error message and force a return as
we no longer care about further processing (as division by zero is not possible).

Python for MineSight® Planner | 29


Built-in Functions

In addition to writing your own functions, Python (and all other programming languages) comes with
a standard set of built-in functions that you can simply call upon and make use of. This section
describes a small set of such functions that can come in handy on a regular basis.

NUMERIC FUNCTIONS

• Absolute value – Returns the absolute value of a given numeric value (i.e. sign is ignored).

SYNTAX

abs(<value>)

• Power – Returns the result of raising a given value to the specified power.

SYNTAX

pow(<value>, <n>)

• Round – Returns the result of rounding off a given value to the specified number of decimal
places.

SYNTAX

round(<value>, <ndec>)

Python for MineSight® Planner | 30


STRING FUNCTIONS

• Strip – Remove all leading and trailing whitespace from a given string.

SYNTAX

<value>.strip()

• Uppercase/Lowercase – Convert a given string’s case to either upper or lower case.

SYNTAX

<value>.upper()
<value>.lower()

• Find – Get the index of the first occurrence of the specified value within a given string.

SYNTAX

<value>.find(<findThis>)

• Replace – Replace all occurrences of the specified value within a given string with a new value.

SYNTAX

<value>.replace(<findThis>, <replaceWithThis>)

Note that these functions are called on an existing string value, unlike the Numeric functions, which
means they modify the original string value in-place.

Also note the whitespace in the “message” string in the example below; this has been introduced
deliberately to correctly demonstrate the strip() function.

Python for MineSight® Planner | 31


MISCELLANEOUS FUNCTIONS

• Minimum/Maximum – Get the minimum or maximum value from a given set of values. The
values can be passed as individuals in simple comma-separated form, or as a Container type.

SYNTAX

min(<value1>, <value2>, … <valueN>) OR min(<collection>)


max(<value1>, <value2>, … <valueN>) OR max(<collection>)

• Sorting – Sorts the given data in ascending or descending order based on the sort flag
specified.

SYNTAX

sorted(<collection>, reverse = <Boolean>)

Default sort order is ascending (i.e., “reverse” flag is “False”). To sort in descending order,
set the “reverse” flag to “True”.

• Length – Get the length of the given data. Can be used on collections (returns the number of
items contained within) and strings (returns the number of characters in the string).

Python for MineSight® Planner | 32


SYNTAX

len(<collection>) OR len(<string>)

• Range – Generate a sequential list of integers given a minimum and maximum value, and an
optional step size.

SYNTAX

range(<start>, <end>, <step>)

Python for MineSight® Planner | 33


Modules

The functions described in the previous section are just the tip of the iceberg; there are literally
hundreds more available in Python for various purposes, ranging from math and internet services to
cryptography and databases. These are not directly available to a snippet you may be writing, until
you explicitly signal that you wish to use them.

These functions are contained within modules, which are simply standard Python files containing
several pre-written functions and/or constants for you to use. Collectively, these are commonly
referred to as a programming language’s standard library. You first specify the name of the modules
you wish to use, and then reference their functions/constants via the dot operator.

SYNTAX (Import)

import <moduleName>

SYNTAX (Access)

<moduleName>.<constant>
<moduleName>.<function>(…)

Specify module imports at the very beginning of your code so you can manage them easily in
one place and avoid any import errors down the line for complex calculations.

Python for MineSight® Planner | 34


Note that while there are hundreds of modules in the standard Python library, their access is highly
restricted within the MSPlanner environment. Currently, only the math module is available for
import. Attempting to import any other Python modules will result in an error.

MATH

The math module provides access to a number of common mathematical functions, including power,
log, and trigonometric operations, and also has pre-defined constants for pi and e. For a
comprehensive listing of all available functions, check the Python Standard Library documentation.

Python for MineSight® Planner | 35


Sample Property Calculations
Having covered the fundamental Python concepts necessary to work with Properties in the previous
section, we will now take a look at some actual working examples of Python calculations in Properties.

Example 01: Assign Geometry Element Name to a Property

A highly common practice is to have element-named geometry (polygons or solids) in MS3D, which is
then also used to identify cuts uniquely within a plan.

Property Name Cut ID


Type String
Derived No

Since “Element Name” is available as an inbuilt attribute, we simply assign it to our Result variable
directly.

Example 02: Selectively extract text from a given String

Often times, cut names are actually a collection of different pieces of information used to uniquely
identify each one, such as a level number or bench name. These may or may not be separated by a
special character (hyphens or underscores are common). In such cases, we might want to store one of
those pieces of information in its own Property, by selectively extracting text from an existing string
or property.

Property Name Bench


Type String
Derived Yes
Dependent Property Cut ID

For this example, assume we have the following information:


Python for MineSight® Planner | 36
Cut ID AK74-SKS-R1

And say our bench name is the first n characters from the Cut ID string that are not numeric. We need
to write code that gives us the following result:

Bench AK

The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “Cut ID” attribute and store it in variable cutID.

2. Begin looping through the set of characters that make up the cutID string. This is accomplished
with a for loop , starting at index 0 and finishing at index len – 1.

0 1 2 3 4 5 6 7 8 9 10
A K 7 4 – S K S – R 1

3. Using a negation of the isalpha() String function, check each character to see whether it is a
number. Starting at index 0 and moving forward, we will complete two iterations of the loop
(because “A” and “K” are indeed alpha characters) before the if condition is satisfied (i.e. when

Python for MineSight® Planner | 37


we hit “7”).

0 1 2 3 4 5 6 7 8 9 10
A K 7 4 – S K S – R 1

4. As soon as the first numeric character in cutID is hit, we can terminate the loop as we no
longer need to keep iterating; this is achieved with the break statement.

5. Using String slice notation, extract all characters from the start of cutID up until the point
where we break out of the loop (i.e. the current position of our loop counter i). This is the final
Result.

The Property’s dependency on “Cut ID” can be tested by bringing up the Activity List and modifying
the first few alpha characters. As soon as you click/tab out of the “Cut ID” field, the value of “Bench”
should update automatically.

Example 03: Extract Level number from the standard Level Attribute

Another very commonly used piece of information is the level at which a particular cut exists. The
inbuilt attribute provided for this (“Level”) does display this information, however it also carries the
word “Level” and the name of the Project Control File (PCF) that is linked to the model currently in
use, all as part of the same string. For display purposes, it is much cleaner and simpler to have just the
level number without the extra content.

Python for MineSight® Planner | 38


Property Name Cut Level
Type String
Derived No

For this example, assume we have the following information:

Level Level 1453.00 (OTGC10.dat)

We need to write code that gives us the following result:

Cut Level 1453.00

The inbuilt attribute “Level” contains a few ‘child’ attributes, one of them being a “Name”. This is
what holds the entire level string as described above.

The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Retrieve the value of the inbuilt “Level Name” attribute and store it in the Result variable. This
gives us: Level 1453.00 (OTGC10.dat).

2. Suffix the String split() method without passing in a parameter; this will split the “Level Name”
value on every space, resulting in a list containing each individual component. This leaves us
with: [“Level”, “1453.00”, “(OTGC10.dat)”].

Python for MineSight® Planner | 39


3. Since we now have a list of values, we extract the element at index 1, which is the actual
numeric level value. This is the final Result.

Note that even though the final result appears to be a number, it is in fact a string of numeric
characters, because we simply extracted it from an existing string. This is perfectly acceptable as
long as the end result is not expected to be used in any calculations/arithmetic operations. If an
actual numeric value is desired, give the Property a Double data type and use a type cast when
assigning the Result.

Example 04: Retrieve a value from a lookup table based on another Property

Retrieving values from lookup tables/lists based on certain given values or some specific condition is
quite a common operation.

A good example of this would be having to lookup a lithology type string from a pre-defined Python
Dictionary, based on a given lithology integer code stored in another Property.

Property Name Lith Type


Type String
Derived No

For this example, assume we have the following information:

Lith Code 18

Lookup Table
0 DEFAULT
1 FILL
2 PNO
3 DRO
4 THO
5 IRO
6 MPO
7 MDO
8 ENO
9 SKO
10 PYS
Python for MineSight® Planner | 40
12 PNS
13 DRS
14 THS
15 IRS
16 MPS
17 MDS
18 ENS
19 SKS
20 PYS

We need to write code that gives us the following result:

Lith Type ENS

The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Define a dictionary containing all possible lithology codes (Integer keys) and lithology types
(String values). This is stored in variable lithTable.

2. Retrieve the value of the “Lith Code” Property and store it in the lithCode variable.

Python for MineSight® Planner | 41


3. Use the retrieved lithCode value to lookup the corresponding lithology type value from the
lithTable dictionary. This is done using the dictionary’s get() function, passing in the lithCode as
a parameter. This is the final Result.

Example 05: Set Phase based on Numeric value stored in another Property

In this example, we will setup a “Phase” Property that derives some information from our Cut ID
Property. Let’s say that the last n numeric characters of our Cut ID make up the phase number, and
we want to extract that number and prefix it with the characters “PH” (and optionally, with a “PH0” if
the phase number is less than 10).

Property Name Phase


Type String
Derived Yes
Dependent Property Cut ID

For this example, assume we have the following information:

Cut ID FAK94-MPS-R5

We need to write code that gives us the following result:

Phase PH05

The complete snippet to achieve the desired result is as follows:

Python for MineSight® Planner | 42


A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “Cut ID” Property and store it in variable cutID.

2. Begin looping through the set of characters that make up the cutID string, in reverse order.
This is accomplished with a for loop , starting at the last character (computed as one less than
the total length of the string) and finishing at index 0. The “reverse” order is achieved by
specifying an optional step size of -1 within the range() function.

0 1 2 3 4 5 6 7 8 9 10 11
F A K 9 4 - M P S - R 5

3. Using the isalpha() String function, check each character to see whether it is a number. Starting
at the end and moving backwards, we will complete one iteration of the loop (because “5” is a
number) before the if condition is satisfied (i.e. when we hit “R”).

Python for MineSight® Planner | 43


0 1 2 3 4 5 6 7 8 9 10 11
F A K 9 4 - M P S - R 5

4. As soon as the first alpha character in cutID is hit, we can terminate the loop as we no longer
need to keep iterating; this is achieved with the break statement.

5. We now have our phase number (note it is still a String type!) and all that remains is to add in a
“PH” prefix – however, this requires a conditional check to see whether the phase number is
less than 10 or not. If it is less than 10, we concatenate the number with a “PH0” prefix, and if
not, we simply concatenate it with a “PH” prefix. This is stored in the phase variable.

6. The phase variable is then simply assigned to be the final Result.

The Property’s dependency on “Cut ID” can be tested by bringing up the Activity List and modifying
the number at the end. As soon as you click/tab out of the “Cut ID” field, the value of “Phase” should
update automatically.

Python for MineSight® Planner | 44


Example 06: Map Material to Destinations based on Grade and Phase

Sometimes, you might have the need to send material to a particular destination based on one or
more properties of the cut in question (average grade, period, etc.).

In this example, we setup a String type Property to hold the destination name for each cut, which is
determined based on the AU grade and current mining phase.

Property Name Cut Destination


Type String
Derived Yes
Dependent Property AU, Phase

For this example, assume we have the following information:

AU 0.941
Phase PH01

Phase 01, 02, and 03


AU equal to and above 1.50 Mill
AU above 1.00 and below 1.50 HG_Stockpile
AU above 0.70 and below 1.00 MG_Stockpile
AU above 0.25 and below 0.70 LG_Stockpile
AU below 0.25 WST_Dump_NA

Phase 04, 05, and 06


AU equal to and above 1.10 Mill
AU above 0.80 and below 1.10 HG_Stockpile
AU above 0.50 and below 0.80 MG_Stockpile
AU above 0.20 and below 0.50 LG_Stockpile
AU below 0.50 WST_Dump_BR

This means we have two sets of grade cutoffs to determine material mapping – one each for Phases 1
to 3 and 4 to 6. Also, while the mill and stockpile destinations are shared between the two sets of
phases, we have separate waste dumps for each set.

We need to write code that gives us the following result:

Cut Destination MG_Stockpile

The complete snippet to achieve the desired result is as follows:

Python for MineSight® Planner | 45


A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “AU” and “Phase” Properties and store them in variables au and
phase, respectively.

2. Set a default Result value (“UNDEF” in this case); this will be used if none of our material
mapping conditions are met for a cut.
Python for MineSight® Planner | 46
3. Check the value of phase to see if it is either Phase 01, 02, or 03. If so, run a series of checks for
au to determine which cutoff bin the current cut matches. For each cutoff bin, set the
appropriate destination. This is our final Result for either of these phases.

4. Check the value of phase to see if it is either Phase 04, 05, or 06. If so, run a series of checks for
au to determine which cutoff bin the current cut matches. For each cutoff bin, set the
appropriate destination. This is our final Result for either of these phases.

The Property’s dependency on “Phase” and “AU” can be tested by bringing up the Activity List and
modifying the number at the end of “Cut ID” (as this updates “Phase”). As soon as you click/tab
out of the “Cut ID” field, the value of “Phase” will update automatically, which in turn will alter the
“Cut Destination”.

Example 07: Calculate Ore and Waste Tonnes

The Activity list only displays total tonnes for each cut by default. It can be quite useful to see how
this total is split between Ore and Waste type material. This example shows how to compute and
store these values in their own separate Properties that can then be displayed in the Activity List.

For Ore Tonnes, we have the following:

Property Name Ore Tonnes


Type Double
Derived Yes
Dependent Property Reserves
Python for MineSight® Planner | 47
The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Setup variable oreTonnes to accumulate ore tonnes from the Reserves parcels, initialized to a
value of zero.

2. Using a for loop, iterate through each Reserves parcel and check whether the material for the
current parcel is of type ore or waste using a negated if statement in conjunction with the
IsWaste attribute. If it is not of type waste, accumulate the Tonnes for that parcel into
oreTonnes.

3. At the end of the loop, we have our final Result, which is simply oreTonnes.

For Waste Tonnes, we have the following:

Property Name Waste Tonnes


Type Double
Derived Yes
Dependent Property Reserves

The complete snippet to achieve the desired result is as follows:

Python for MineSight® Planner | 48


A detailed explanation of the logic used is as follows:

1. Setup variable wstTonnes to accumulate waste tonnes from the Reserves parcels, initialized to
a value of zero.

2. Using a for loop, iterate through each Reserves parcel and check whether the material for the
current parcel is of type ore or waste using an if statement in conjunction with the IsWaste
attribute. If it is of type waste, accumulate the Tonnes for that parcel into oreTonnes.

3. At the end of the loop, we have our final Result, which is simply wstTonnes.

Example 08: Calculate Stripping Ratio

Another piece of Reserves-related information you might want to have in your Activity List is Stripping
Ratio. While this is an inbuilt field in MSReserve, it isn’t so in MSPlanner, but it can be easily
computed and stored in a Property.

Property Name Stripping Ratio


Type Double
Derived Yes
Dependent Property Reserves

Python for MineSight® Planner | 49


The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Setup variables oreVolume and wstVolume to accumulate ore and waste volumes from the
Reserves parcels, both initialized to zero.

2. Using a for loop, iterate through each Reserves parcel and check whether the material for the
current parcel is of type ore or waste using an if statement in conjunction with the IsWaste
attribute. If it is of type waste, accumulate the Volume for that parcel into wstVolume, and if it
is of type ore, accumulate the Volume into oreVolume. At the end of the loop, we have total
ore and waste volumes.

3. Check if oreVolume is greater than zero. If so, divide wstVolume by oreVolume, and if not,
simply write out a value of zero. This is the final Result.

Python for MineSight® Planner | 50


Example 09: List all Material types within a Cut

This example demonstrates how to setup a String type Property that presents a comma-delimited list
of all Material names that are present for a given cut.

Property Name Cut Material


Type String
Derived Yes
Dependent Property Reserves

The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Setup variable materials to hold the list of material names present within a cut, initialized to an
empty list.

2. Using a for loop, iterate through each Reserves parcel and append the parcel’s Material Name
to the materials list. At the end of the loop, we have a complete list of all material types.
Python for MineSight® Planner | 51
3. Update materials to contain only unique values (i.e., only one occurrence of each material type
name) by running the set() function on itself.

4. Build the final comma-delimited String of material names using the join() function. This is the
final Result.

Python for MineSight® Planner | 52


Process Points
A Process Point is a special type of destination, one or more of which can be created in the
“Destinations” mode on the Process Canvas. These make use of Python snippets to control material
movement, and can be very useful when a high level of manual control or complex/precise movement
of material is required.

Creating Process Points

Process Points are setup and managed under the “Process Canvas” document of the “Destinations”
mode. One or more Process Points may be added and the calculations modified at any time.

Python for MineSight® Planner | 53


A Process Point may be given any name and have any type of icon from the included icon set, but it is
set apart visually from other destinations by a superscripted sigma (Σ) icon.

Spaces are acceptable in all destination names for the canvas, however these are automatically
substituted with an underscore for use in Process Point calculations. Remember to make use of a
destination’s “Calculation Name” when writing Process Point code, not the regular “Name”.

Python for MineSight® Planner | 54


Calculations

In order to use a Process Point, material has to be fed to it first. This is usually done at the material
mapping stage based on user requirements.

To control material movement and grade distribution from that point onwards, you need to write a
calculation using Python snippets. To do this, select the desired Process Point from the canvas, and
click the […] button next to the “Calculation” field in the Properties panel.

Python for MineSight® Planner | 55


This brings up the “Edit Destination Calculation” window.

The layout is identical to what we have seen when working with Properties. To enter your calculation
logic, simply place your cursor in the “Code” window and begin adding Python snippets. You may also
use the “[+]” button next to any of the inbuilt variables to insert their value at the current position of
your cursor in order to save time.

The main difference between writing code for Properties and Process Points lies in the “Result”
section. With Process Points, material coming in has to match the amount of material being sent out;
if this is not the case, a warning is issued when you run tests on your calculation.

Existing calculations can be edited at any time, however you must remember to re-run the routing
calculations in order for any updates to take effect.
Python for MineSight® Planner | 56
Basic Usage

All the fundamental Python concepts discussed earlier, as well as the syntax/semantics used to write
calculations for Properties, are relevant in the creation of Process Point logic. There are however a
few different concepts involved when it comes to working with Process Points, and these need to be
understood first. They are presented below.

ACCESSING DESTINATION DATA

Different destinations, including the Process Point itself, are accessed in code simply via their
“Calculation Name”. These can either be typed manually or added in with the help of the inbuilt
Variables.

Destinations, when accessed by themselves, simply contain Volume and Tonnes information (as seen
above). Additional information (such as grades) can be accessed using syntax similar to those used in
Properties.

Python for MineSight® Planner | 57


ACCESSING MATERIAL AND GRADE INFORMATION

The material type for a cut is determined by a combination of the Zone code and Material Set
configuration from the associated Reserve Logic. This information is stored in each destination’s
“Zone” variable. While the data type is a String, it uses a special function to access its value.

Grade values on the other hand can be accessed by name using the usual indexing syntax.

Python for MineSight® Planner | 58


MOVING MATERIAL AND GRADE TO DESTINATIONS

Once the desired Process Point logic is in place, material needs to be sent out to the appropriate
destination. In order to do this, you simply assign the Process Point to the required destination’s
Calculation Name.

To send only a portion of the material to a destination, simply multiply or divide the Process Point by
the required value.

This can also be applied on individual items from the Process Point, such as Tonnes, Volume, or any of
the available grade items using the standard index notation.

Python for MineSight® Planner | 59


CHECKING MATERIAL MAPPING RESULTS

Once the Process Points have been setup and material has been routed as required, you can use the
“Reserves” document under the “Destinations” mode to examine the outcome of your Process Point
calculations.

Columns can be added, removed, and used as filtering/grouping criteria as desired. The main thing to
ensure at this point is that no material is left over in the Process Points used; i.e. all material should
be distributed amongst the other destinations. If there is still material left over, the calculation logic
for that particular Process Point needs to be rectified until all input material is sent out correctly.

Python for MineSight® Planner | 60


Sample Process Point Calculations
Having covered the basics of setting up and using Process Points, we will now take a look at some
working examples of actual Process Point calculations.

Example 01: Simple Material Mapping based on Grade Cutoff

This example demonstrates the simplest use of a Process Point – all material zones except for the
default waste zone are mapped to the Process Point, and calculation logic is entered to route material
to the appropriate destinations based on the main grade cutoff.

Process Point Name ProcessPoint


Destination Names Mill, LG_Stockpile, MG_Stockpile, HG_Stockpile,
WST_Dump
Grade Item CU

Material is to be routed to the destinations based on the following logic:

CU equal to and above 0.70 Mill


CU up to 0.50 and below 0.70 HG_Stockpile
CU up to 0.25 and below 0.50 MG_Stockpile
CU up to 0.15 and below 0.25 LG_Stockpile
CU below 0.15 WST_Dump

The complete snippet to achieve the desired result is as follows:

Python for MineSight® Planner | 61


A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “CU” attribute and store it in variable grade.

2. Run a series of checks for grade to determine which cutoff bin the current cut matches, using
if-elif statements. For each cutoff bin, the material is sent to the appropriate destination by
assigning the Process Point name to the respective destination name.

Python for MineSight® Planner | 62


Example 02: Split Material between multiple Destinations

This example extends on the concept of the previous one and shows how to send portions of material
from the same cut to different destinations, based on some user-defined criteria/logic. Again, all
material zones except for the default waste zone are mapped to the Process Point.

Process Point Name ProcessPoint


Destination Names Mill, LG_Stockpile, MG_Stockpile, HG_Stockpile,
WST_Dump
Grade Item CU

Material is to be routed to the destinations based on the following logic:

CU equal to and above 0.70 25% to HG_Stockpile 75% to Mill


CU up to 0.50 and below 0.70 100% to HG_Stockpile
CU up to 0.25 and below 0.50 100% to MG_Stockpile
CU up to 0.15 and below 0.25 For “Class 02” material: For all other material:
50% to LG_Stockpile, 100% to LG_Stockpile
50% to MG_Stockpile
CU below 0.15 WST_Dump

The complete snippet to achieve the desired result is as follows:

Python for MineSight® Planner | 63


A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “CU” and “Zone” attributes and store them in variables grade and
material, respectively.
Python for MineSight® Planner | 64
2. Run a series of checks for grade to determine which cutoff bin the current cut matches, using
if-elif statements.

3. For the 0.15 – 0.25 bin, run an additional check to see if material is of type “CLASS 02”. If so,
send 50% to the LG_Stockpile and MG_Stockpile destinations each, by assigning the Process
Point name multiplied by 0.5 to the respective destination names. If not, assign the Process
Point name to the LG_Stockpile destination name.

4. For the 0.7 and above bin, send 25% material to the HG_Stockpile and 75% material to the Mill
by assigning the Process Point name multiplied by 0.25 and 0.75 to the respective destination
names.

5. For all other bins, 100% material is sent to the appropriate destination by assigning the Process
Point name to the respective destination name.

Example 03: Drying out wet Material

In some instances, material taken from the production source tends to be wet, and needs to be dried
out as an intermediate step before processing can take place. In this example, we have an item in the
Block Model and Reserve Logic that stores moisture content information, and we will make use of this
to “dry out” the material in the Process Point before sending it on to the desired destination.

In this case, all material at a 0.7 or greater cutoff is mapped to the Process Point.

Process Point Name ProcessPoint


Destination Names Mill
Moisture Item MOIS
Python for MineSight® Planner | 65
The complete snippet to achieve the desired result is as follows:

A detailed explanation of the logic used is as follows:

1. Retrieve the value of the “MOIS” attribute, divide it by 100 and store it in variable moisture.
“MOIS” is stored as a percentage in the Block Model (0 – 100), and this will clamp it between 0
and 1.

2. Compute the required drying factor for the material by subtracting moisture from 1, and store
the result in variable dryFactor.

3. Send the material to the Mill by assigning the Mill destination name to the Process Point name.

4. Set the material’s tonnage at the Mill to be the total tonnes multiplied by dryFactor, in order to
get the try tonnes.

5. Set the “MOIS” attribute at the Mill to zero, as we have effectively removed all moisture from
the material.

Python for MineSight® Planner | 66


Note that the result of this calculation when tested will include the warning about total material
output not matching the input. This is because the input was in wet tonnes (i.e., higher) and the
output is in dry tonnes (i.e., lower).

Python for MineSight® Planner | 67


Appendix
Code Window Keyboard Shortcuts

The code window used to define Property and Process Point calculations is a DevExpress® “Rich-Text”
control, which allows for a variety of keyboard shortcuts to be used for various purposes. These are
detailed here.

TEXT INSERTION, SELECTION AND MODIFICATION

SHORTCUT DESCRIPTION

Ctrl + X Cut selection

Ctrl + C Copy selection

Ctrl + V Paste selection

Ctrl + Z Undo last action

Ctrl + Y Redo last undo

Ctrl + Arrows (Left/Right) Move cursor past entire word (previous/next)

Shift + Arrows (Left/Right) Select single character (previous/next)

Ctrl + Shift + Arrows (Left/Right) Select entire word (previous/next)

Ctrl + A Select all

Python for MineSight® Planner | 68


TEXT FORMATTING

SHORTCUT DESCRIPTION

Ctrl + B Bold

Ctrl + I Italics

Ctrl + U Underline

Ctrl + Shift + D Double Underline

Ctrl + Square Brackets (Left/Right) Change font size by 1 point (decrease/increase)

Ctrl + D Display font options dialog

The “Font” dialog enables customization of several aspects of the text entered into the Code window.
Font face, style, size and colour are all modifiable, and additional effects such as strikethroughs,
subscripts, superscripts, etc. are available.

While some of these effects will have no use on actual Python syntax, they might come in handy for
comments and user notes.

Python for MineSight® Planner | 69


Text formatting options are lost once the Configuration window is closed. It is best to apply
these right before saving the code out to a file.

SAVING AND LOADING

SHORTCUT DESCRIPTION

Ctrl + S Save

F12 Save As

Ctrl + O Open

Calculation code is saved to a Rich Text Format (.rtf) file, which maintains all syntax highlighting and
formatting features, including proper indentation.

Using “Ctrl + S” will initially ask for a save location, but subsequent uses will simply overwrite the
original file with new information, even across multiple Properties. It is hence strongly
recommended that the “F12” shortcut is used for saving instead.

If you have code saved to an RTF file and you wish to populate a Property with it, simply create a new
Property, then press “Ctrl + O” to browse for the desired file, and the code will be loaded into the
code window. The imported code will be saved upon exiting the Configuration dialog.

Python for MineSight® Planner | 70


FIND AND REPLACE

SHORTCUT DESCRIPTION

Ctrl + F Find

Ctrl + H Find and Replace

The code window features full “Find and Replace” functionality, including built-in support for Regular
Expressions. This can be extremely handy when a particular change has to be made, especially in
large/complex calculations.

Python for MineSight® Planner | 71

You might also like