Python Extensions
Python Extensions
A Python extension is a Python script that contains a rungx()
function, and you can run a Python extension script just as you would a GX file (for example, see hello_world below). This includes adding a Python extension script file name to a menu or running a Python extension script from the "Settings / Run GX...".
Before running Python extensions Oasis montaj needs to be configured to locate your Python distribution folder. This is the folder that contains the "python.exe" file. To do this select "Settings / Global settings / Python..." and locate the Python folder. The folder location and the default console setting are stored in the geosoft/core/environment registry. See Environment Variables for more information.
If you are running Python extension scripts from a custom menu
You should place custom menu files in:
...\user\omn
You should place Python script referenced from your menus in
: ...\user\python
See Oasis montaj Menus for more information.
Geosoft Python API
The GX Developer Python package includes two modules:
Module | Description | Typical import |
---|---|---|
gxapi | This is the complete low-level GX API and includes all functions that are part of the standard API. Note that this is a direct mapping of the API available to all development languages, and as such the API style does not conform to a "pythonic" style of use. However, calling into the gxapi does provide access to everything within the development environment, and the usage follows the coding patterns you will find in Geosoft's legacy GXs that are part of Geosoft Desktop. Also, the gxapi is assured to be forward version compatible while the gxpy module is currently best-effort in this regard. If you choose to work with the gxapi you may find the many coding examples from the installed GX Developer, which you will find at |
|
gxpy | The gxpy module contains a set of sub-modules that a provide a higher-level "pythonic" interface to underlying gxapi. Many standard Python needs are included in the modules, and we suggest that straight-forward Python applications will be able to work with only the gxpy. The gxpy module covers only part of the full function of the gxapi, and with each release of GX Developer will continue to expand and extend the capabilities of gxpy. | import geosoft.gxpy as gxpy |
The gxpy module is made up of a number of sub-modules, each dealing with an area of responsibility summarized here:
Sub-Module | Description | Typical import |
---|---|---|
gx | Works with your GX context and licensing. |
|
agg | Image aggregates, which are used to render one or more grids together as images. | import geosoft.gxpy.agg as gxagg |
coordinate_system | Coordinate system handling | import geosoft.gxpy.coordinate_system as gxcs |
dataframe | Tables, which are compatible with Pandas dataframes | import geosoft.gxpy.dataframe as gxdf |
gdb | Geosoft database (gdb) handling | import geosoft.gxpy.gdb as gxgdb |
geometry | Basic geospatial geometric types | import geosoft.gxpy.geometry as gxgm |
grid | Geosoft grid handling. | import geosoft.gxpy.grid as gxgrd |
group | Drawing groups for 2D and 3D drawing into views. | import geosoft.gxpy.group as gxg |
map | Geosoft maps, which are containers for 2D views and geosoft_3dv views. | import geosoft.gxpy.map as gxmap |
project | Geosoft project instance to work with a Geosoft Desktop project. | import geosoft.gxpy.project as gxpj |
system | System-level functions. | import geosoft.gxpy.system as gxsys |
utility | General-purpose utilities. | import geosoft.gxpy.utility as gxutil |
va | Geosoft vector array handling. | import geosoft.gxpy.va as gxva |
view | 2D and 3D (geosoft_3dv ) views. | import geosoft.gxpy.view as gxv |
viewer | Viewer for maps and geosoft_3dv files. | import geosoft.gxpy.viewer as gxvwr |
vv | Geosoft vector handling. | import geosoft.gxpy.vv as gxvv
|
Python Examples
A number of example python extensions are provided in the gxpy-examples
repository (https://github.com/GeosoftInc/gxpy/tree/master/examples).
To run the examples, open an Oasis montaj project and run the python script by clicking on the GX button (or choose "Settings / Run a GX..."), then browse to the script (for example "hello_world.py
"):
Your script must contain a "rungx()" function, which will be run.
hello_world
This is a classically basic script that illustrates the of the API to do something very simple, which is say hello to the user.
import geosoft.gxapi as gxapi # gxapi methods import geosoft.gxpy as gxpy # gxpy methods def rungx(): # a python script must have a rungx(), which is executed by OM when the script is run gxp = gxpy.gx.GXpy() # get the current gx context gxapi.GXSYS.display_message("GX Python", "Hello {}".format(gxp.gid)) # say hello to the user identified by gxp.gid.
When you run this script from Oasis montaj you will see the following:
chanadd.py
This example shows how to work with a database by adding a constant value to a channel on all selected lines. User parameters are saved for re-use for the next time the extension is run from the same project.
import geosoft.gxpy as gxpy import geosoft.gxpy.project as gxprj import geosoft.gxpy.utility as gxu def rungx(): # api version gxpy.utility.check_version('9.2.0b0') # get the current database db = gxpy.gdb.Geosoft_gdb.open() # project parameters group = 'CHANADD' p_chan = 'CHANNEL' p_addval = 'ADDVAL' # get previous parameters from the parameter block, initializing to start-up defaults '' and 0.0 parms = gxu.get_parameters(group, {p_chan: '', p_addval: 0.0}) # if interactive, get user input if not gxprj.running_script(): try: # get channel to process from list of database channels chan = gxprj.get_user_input( 'Channel to process', 'Channel:', kind='list', default=parms.get(p_chan), items=sorted([k for k in db.list_channels().keys()])) # value to add to the channel addval = gxprj.get_user_input( 'Value to add to the data', 'value to add:', kind='float', default=parms.get(p_addval)) except gxprj.ProjectException: exit() # save parameters to new user settings parms[p_chan] = chan parms[p_addval] = addval gxu.save_parameters(group, parms) # work through the data a line at a time - get a list of selected lines lines = db.list_lines() # for each line, get the data, add a value, return the data to the line for l in lines: # print to the console to reflect progress print('line {}...'.format(str(l))) # get the data and determine the dummy to the data type data, ch, fid = db.read_line(l, channels=chan) dummy = gxu.gx_dummy(data.dtype) # make a dummy mask so we can replace dummies after processing dMask = gxu.dummy_mask(data) # process - add the value, then replace the dummies sum = data + addval sum[dMask] = dummy # write the data back to the database db.write_channel(l, chan, sum, fid) # pause the console so user can review input("Press return to continue...")
Debugging Python Extensions
Because Python extensions are run from Oasis montaj, interactive debugging of a Python script requires use of a remote debugging hook from an IDE that supports remote debugging using the pydevd package. For example, PyCharm is an excellent (and highly recommended) IDE that supports remote debugging using the pydevd package.
"pydevd" is not part of standard Anaconda Python and needs to be installed:
pip install pydevd
To create a debugging session from PyCharm, add a "Remote debugging" configuration to your project:
At the top of your extension script add the lines indicated in steps 2. and 3. in the Remote debugging configuration. For example, to setup the "hello_world.py" for remote debugging add lines 5 and 6 (these should be commented out or removed when not debugging):
# Oasis montaj Python extension to say Hello.import geosoft.gxapi as gxapi # gxapi methods # To run this extension, select "Settings / Run GX or Python...", then browse to this script file. # import pydevd import pydevd # when the following line is executed the IDE will break at the next executable line. The settrace() call must # be reemoved for normal use. pydevd.settrace('localhost', port=34765, stdoutToServer=True, stderrToServer=True) # You should set the next breakpoint somewhere after rungx(), and run to that point. Note that you cannot step # through the def rungx() line because that line is not visible to the remote debugger. import geosoft.gxapi as gxapi import geosoft.gxpy as gxpy # a python script must have a rungx(), which is executed by OM when the script is run def rungx(): # get the current gx context gxp = gxpy.gx.GXpy() # say hello to the user identified by gxp.gid. gxapi.GXSYS.display_message("GX Python", "Hello {}".format(gxp.gid))
With the "Remote debugging" configuration, run the debugger from the IDE and a remote server will start-up and wait for the "pydevd.settrace(...)
" call:
Run the extension from Oasis montaj using "Run a GX":
The debugger will give you control at the first executable line following the setrace(...)
call. Debug as you normally would, though note that you cannot step through the def rungx() line because the remote debugger cannot see that line. We suggest you set a breakpoint somewhere after that line and run to the breakpoint.
Note that to maintain the integrity of the client-server interaction between Oasis montaj and your debugger server you should complete your script and exit normally, with or without raising errors, such that Oasis montaj returns to a normal state. Closing Oasis montaj or your debugger during a debugging station may require you to restart Oasis montaj. Any change of configuration in the underlying Python installation, such as the addition or removal of a package, will also require that Oasis montaj be stopped and restarted