Writing calculated script data back to the block model

ronald reid 7 years ago in Scripting updated 7 years ago 3

Hi all expert python scripting people - I am converting a profit algorithm script from a Vulcan bcf script to Micromine python one and have a hurdle. I can call the file, make a copy and then hit a snag, first I have to create two new fields in the model called orsource and oretype, then pull data from several block model fields to use in filling the orsource field (oretype gets used later). The portion of the script attached runs wonderfully and does absolutely nothing....

Can someone point out what changes I need to a) create the fields and b) write the data to the fields I specify?

Pasted below because my file uplink wont work...


# profit algorithum script
# declare parameters

blkmdlin = 'HVK_LMIK_OBM.DAT'
blkmdlout = 'hvk_lmik_rsv_201412.DAT'
(Xfield,Yfield,Zfield) = ("East","North","RL")
BlockModelZoneName = "zone"
BlockmodeloxstateName = "oxstate"
BlockmodelRockTypeName = "rocktype"
# set conversion parameters
#XXXXX - Series of parameters defined in this portion for the calculations"""
# set up block model
Project = MMpy.Project() #Make a variable that points to the current project
Path = Project.path() #Get the path of the current project

print (blkmdlin)
print (blkmdlout)
print (Path)

myBlockModel = Path + blkmdlin
Myblkmdl = MMpy.BlockModel()

if Myblkmdl.open(myBlockModel,Xfield,Yfield,Zfield) == False:
sys.exit("Error: Problem opening Block Model")
print("%s contains %d records." %(myBlockModel,Myblkmdl.records_count))

Myblkmdl.copy(myBlockModel,Path + blkmdlout)
print("Copied \"" + blkmdlin + " to \"" + blkmdlout + "\"")


blkmdl = Path + blkmdlout #define the copried blockmodel

Myblkmdl_new = MMpy.BlockModel()

print("Opened \"" + blkmdl + "\"")

NumRecords = Myblkmdl_new.records_count
print('It contains {0} records.'.format(NumRecords))

# add in the oretype and orsource fields

BlockModelZoneField = Myblkmdl_new.get_field_id(BlockModelZoneName) #Get the field ID we'll need for the Blockmodel file
BlockmodeloxstateField = Myblkmdl_new.get_field_id(BlockmodeloxstateName)
BlockmodelRockTypeField = Myblkmdl_new.get_field_id(BlockmodelRockTypeName)

#for record_id in range(1, NumRecords+1): #Go through all records of the file
# set up ore source
# ore source 11 = hv fresh
# ore source 12 = hv transitional
# ore source 14 = hv oxide
# ore source 21 = kv fresh
# ore source 22 = kv transitional
# ore source 24 = kv oxide
# ore source 31 = hm fresh
# ore source 32 = hm transitional
# ore source 34 = hm oxide
# set up ore sources and ox states for recoveries, will also classify fill

for record_id in range(1, NumRecords+1):
Currentzone = Myblkmdl_new.get_num_block_value(BlockModelZoneField, record_id) #Get the Zone data of the current record
Currentoxstate = Myblkmdl_new.get_num_block_value(BlockmodeloxstateField, record_id) #Get the oxstate of the current record
CurrentRockType = Myblkmdl_new.get_num_block_value(BlockmodelRockTypeField, record_id) #Get the Rocktype of the current record

orsource = 0

if Currentzone == 10 and Currentoxstate == 1:
elif Currentzone == 10 and Currentoxstate == 2:
elif Currentzone == 10 and Currentoxstate == 3:
elif Currentzone == 20 and Currentoxstate == 1:
elif Currentzone == 20 and Currentoxstate == 2:
elif Currentzone == 20 and Currentoxstate == 3:
elif Currentzone == 30 and Currentoxstate == 1:
elif Currentzone == 30 and Currentoxstate == 2:
elif Currentzone == 30 and Currentoxstate == 3:
elif Currentzone == -99:
elif Currentzone > 50:
elif CurrentRockType == 1:


Hi Ronald,

I'm not a python expert but this might help.

In order to add a field to a file I normally use the following code. I altered this code from the code produced by recording the File-> Create or Modify File process. You could copy this function and put it at the beginning or end of your script. I tend to keep my functions in a separate python file and import as I would do any module. By making it a function you can call it repeatedly.

def modify_add_column(file_name, field_name, mmpy, field_type= "s",  width = "", precision= "", start_val= ""):
    field_types = ['n', 'c', 'r', 'f', 'l', 's']# The function takes these field types.
    dict_field_types = {ftype: str(i) for i, ftype in enumerate(field_types)}
    Modparms_FormSet1= mmpy.FormSet("MODPARMS","")
    Modparms_FormSet1.set_field("TYPE1",dict_field_types[field_type])#Changes field type to number
    if start_val is not "":
    if precision is not "":
    if width is not "":
        Exception #Python won't fall over if the field already exists 

The file_name does not include ".DAT". so if you want to use it with blkmdlout you should write blkmdlout[:-4]

You could use the function by calling it using the following line to add a column of Short type:

modify_add_column(blkmdlout[:-4], "orsource ", MMpy, field_type= "s")

You can add this line after you have created the file i.e. after you close the first block model file and before you open the blkmdlout file in Python.

It looks like the rest of your code is fine if you have the indentations correct except that you may need to replace

orsource = 0 #with something like:

orsource = Myblkmdl_new.get_field_id("orsource")

Just to be sure, the indentations at the end should look like this:

orsource = Myblkmdl_new.get_field_id("orsource")

for record_id in range(1, NumRecords+1):
    Currentzone = Myblkmdl_new.get_num_block_value(BlockModelZoneField, record_id)     
    Currentoxstate = Myblkmdl_new.get_num_block_value(BlockmodeloxstateField, record_id)    
    CurrentRockType = Myblkmdl_new.get_num_block_value(BlockmodelRockTypeField, record_id)

    if Currentzone == 10 and Currentoxstate == 1:
    elif Currentzone == 10 and Currentoxstate == 2:

I hope that helps and gets things working. Apologies if I've totally missed the point!


Hi Ronald,

For the sort of control that you want, you need to use MMpy.File rather than MMpy.BlockModel. The script snippet below adds 3 new fields to a COLLAR file, and then populates those fields.

I have 3 screenshots that show the original file, the file after the fields were added and then finally after the fields are populated.

# Screenshot 1

Collar_File_Name = "Collar"
Collar_Path_Name = MMpy.Project.path() + Collar_File_Name + '.DAT'
Collar_file = MMpy.File()if Collar_file.open(Collar_Path_Name) == False: sys.exit("Can't open Collarfile")
# Add Azimuth, Dip and Tenement Fields
struct = Collar_file.structure
struct.add_field("AZIMUTH", MMpy.FieldType.real,0,2) struct.add_field("DIP", MMpy.FieldType.real,0,2) struct.add_field("TENEMENT", MMpy.FieldType.character,20,0)
Collar_file.structure = struct
# Screenshot 2
field_names = ["AZIMUTH", "DIP", "TENEMENT"]
field_id = []
for i in range(0,len(field_names)): field_id.append(Collar_file.get_field_id(field_names[i]))
# Populate Azimuth, Dip and Tenement Fields for i in range(1, Collar_file.records_count+1): Collar_file.set_field_value(field_id[0], i, 45.0) Collar_file.set_field_value(field_id[1], i, -60.0) Collar_file.set_field_value(field_id[2], i, "ABC")
# Screenshot 3

Thanks guys,

Paul, thanks for your help Monday. I got it all sorted Monday night and yesterday and ran the script and worked as it should - will need to throw in a check for the fields before trying to add them though - only throws up an error and then still runs but it is annoying all the same.