The TerraLook Python Shell provides access to image data in a Python scripting
environment with built-in mathematical functions (supplied by the Numeric
Python module). The TerraLook Python Shell adds a thin extra layer of
interpretation to ordinary python, allowing a slightly different syntax to be
used for some frequently used functions for typing convenience (no brackets).
The core convenience functions (called
commands) are registered
automatically when the Python Shell launches, and have more argument
checking infrastructure than regular python functions.
To illustrate the difference between python and command syntax,
the following example shows two ways of saving an array from the
Python Shell environment to a file:
Python:
SaveArray(my_array,'my_filename')
Command:
save my_array my_filename
Extension modules with other commands may be registered using the core
command
loadext, but commands require more overhead to implement and
in most cases it is preferable to use the ordinary python syntax.
If you're not familiar with Python or Numeric Python (NumPy) here are some
references:
At startup (from the Edit/Python Shell menu item) the Python environment
automatically imports functions from
Numeric and
gdalnumeric,
and registers the
core commands. Numeric
provides Numeric Python and gdalnumeric provides functions to access TerraLook
image data.
The shell consists of a command input window (bottom) and an output window
(top). Aside from the registered commands, it behaves in the same way as
the Python command line interpreter. Use the
up and down arrow keys to scroll through previous command history.
In addition to the functions imported from Numeric python, TerraLook's Python
shell includes the following functions:
- LoadFile(filename[,xoff][,yoff][,xsize][,ysize]) - returns
a numpy array containing the data from filename. If xoff and yoff
are specified, filename will be read starting at pixel (column) offset
xoff and line (row) offset yoff.
If xsize and ysize are
specified, only xsize pixels and ysize lines will be read;
otherwise, the remainder of the file will be read in. The returned
array will have dimensions ysize x xsize if the raster is
greyscale; N x ysize x xsize if the raster has N channels.
- display(array) - appends the array to the current TerraLook view and
displays it.
- roi() - returns the Region Of Interest (ROI) drawn out by the ROI tool
in the format (x, y, width, height).
- get_roi(array) - given an array, and an ROI marked by the
ROI tool, extract that region from array and return it.
- SaveArray(array,filename[,format])- save array
to file filename, using format. format must be a GDAL write-supported
format, such as 'GTiff' (Geotiff). If format is not specified, it will default to
'GTiff'.
- CopyDatasetInfo(src,dst)- copy metadata and georeferencing
information from GDAL dataset src to GDAL dataset dst.
Commands make use of an infrastructure that simplifies usage and help access for commonly used procedures that interact with the main
TerraLook application or describe the local environment. These commands are intercepted and parsed before being passed to the shell's python interpreter, and are entered with the command and arguments separated by spaces rather than by round brackets and commas. Commands cannot be loaded or used in a regular python shell; they
only have meaning within the context of TerraLook.
Core command list:
- newview- create a new TerraLook view.
- view3d- display a dem and drape in 3D mode in the current TerraLook view.
- get- grab data from the currently active TerraLook view/layer..
- show- display a Python Shell array or GvShapes variable in an
TerraLook view.
- clearview- clear the current TerraLook view.
- save- save a Python Shell array or GvShapes variable to a file.
- loadext- register commands from an extension module (command equivalent of python's import keyword).
- macro- run a sequence of commands/Python statements from a text file.
- journal- save text entered at the Python Shell command line to a text file.
- locals- list this session's local variables and their type codes.
- help- display help for a function or command.
- functions- list loaded python functions, or scan a module for functions.
- commands- list registered commands.
Here is a small tutorial that illustrates simple python usage and some
of TerraLook's python functions; for a more comprehensive general tutorial,
see the
www.python.org tutorial.
Example 1:
-
Load a file into a Numeric python array:
array1 = LoadFile(`filename.foo`)
Display it in the current view:
display(array1)
To get the Region Of Interest (ROI) marked on the image:
- launch the Edit toolbar using the menu entry Edit/Edit toolbar.
- select "Draw ROI" to activate the ROI tool.
- use the ROI tool to mark a region (left click to start drawing, drag, release to finish)
- roi() returns the ROI in (x, y, width, height)
Use the ROI tool to get a subarray:
- mark out an ROI with the tool on the image
- array2 = get_roi(array1)
To save array2 to a new file:
SaveArray(array2,'filename2.tif')
Numeric python functions such as
ones and
array can also be
used to create and manipulate arrays:
-
To create a floating point array of ones with 5 rows and 6 columns:
array3=ones([5,6],Float)
Reset rows 1 to 4, columns 1 to 5 of the array with some values:
array3[1:5,1:6]=array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]],Float)
Square it:
array3=power(array3,2)
Display it in the current view:
display(array3)
Some important points to note are:
- Numeric python arrays are indexed from zero.
- In slicing a Numeric python array using index range N:M, elements N, N+1, ...M-1 are included.
Example 2
We are starting with Python shell (Edit->Python Shell... menu item). You
should load some raster file into TerraLook to work with.
- Get active layer
layer = gview.app.sel_manager.get_active_layer()
...and load data array into memory:
ds = layer.get_parent().get_dataset()
data = DatasetReadAsArray(ds)
Note: using the core command get with the argument data
(ie. enter "get data" at the command line) will perform these three steps
for you.
If you don't want open and display your input data with TerraLook, but want
load the file(s) in memory, make some calculations and display result,
you can use other approach instead of previous steps:
data = LoadFile('filename.l1b')
(In this sample we will work with NOAA AVHRR data in L1B format).
- Now we are ready to operate with loaded data. For example,
calculate normalised difference vegetation index (NDVI) with NOAA
AVHRR data. In this case NDVI is calculated as
(Band2 - Band1)/(Band2 + Band1). We assume we have already calibrated
data in our file.
ndvi = (data[1] - data[0]) / (data[1] + data[0])
- Display result and, optionally, save it into file:
display(ndvi)
SaveArray(ndvi,'ndvi.tif','GTiff')
Note, that in all our computations arrays are fully loaded into
memory. Be sure you have enough resources for this. For large arrays
loading and calculations may take some time.
- Another operation: let's make a RGB composite image. In general
case this operation should be interactively controlled by the user,
because band colors should be carefully adjusted to produce the best
looking results. But we will simplify our task. NOAA AVHRR data has
10-bit depth (GDAL stores them in 16-bit integer), so we just scale
input data to 8-bit and fill three-component array.
rgb = zeros((3, ds.RasterYSize, ds.RasterXSize), UnsignedInt8)
for i in range(3):
rgb[i] = (data[i] * 256 / 1024).astype(UnsignedInt8)
display(rgb)
This code produces a RGB composite from the first three channels of
the input image, but you can unroll the loop and use channels you
want. Following code uses channel 5 as red, 2 as green and 3 as blue:
rgb[0] = (data[4] * 256 / 1024).astype(UnsignedInt8)
rgb[1] = (data[1] * 256 / 1024).astype(UnsignedInt8)
rgb[2] = (data[3] * 256 / 1024).astype(UnsignedInt8)
- Now we will use other data as a sample. Let load ASTER Level 1B
dataset (the second band) and try to calibrate it. This dataset
already reprocessed and should be calibrated with the simple linear
function. Function coefficients contained in the metadata records with
the appropriate number at the end (2 in case of the second band).
layer = gview.app.sel_manager.get_active_layer()
ds = layer.get_parent().get_dataset()
data = DatasetReadAsArray(ds)
incl = float(ds.GetMetadata()["INCL2"])
offset = float(ds.GetMetadata()["OFFSET2"])
data_cal = data * incl + offset
display(data_cal)
The python shell has three commands used to provide help on functions
and commands:
- help- display help for a function or command.
- commands- list registered commands.
- functions- list loaded python functions, or scan a module for functions.
These commands make use of python __doc__ strings and any help text
files that are registered. Help text files should only be used when
there is some reason for not updating the python __doc__ string itself
(eg. if documentation were going to be available in multiple languages,
or if the package is from a third party and you don't want to use
the doc string), or if the python documentation is fine but
it is desirable to display help for some
functions/commands that are not loaded so that the user is made
aware of them. In the latter case, the help text file should be
regenerated from the python documentation each time one of the functions'
documentation changes (at least for releases).
Help text files may have entries of the following three formats:
COMMAND_NAME=my_command
Module: my_module
Group: my_group
Html: my_html.html
documentation...
FUNCTION_NAME=my_func
Module: my_module
Html: my_html.html
documentation...
BUILTIN_NAME=my_builtin
Module: my_module
Html: my_html.html
documentation...
where my_command, my_func, and my_builtin are a user-defined command,
function, and builtin (bound C) function respectively. The Html entry
is used to indicate an html file with more information, and is optional
(currently, the python shell will not do anything with html information
other than store the name of the link- this may be used in future though).
The Module name is required to deal with the case of two modules defining
different commands/functions with the same name. The COMMAND_NAME,
FUNCTION_NAME, BUILTIN_NAME, Module, and Html parts of the text file are
case-sensitive (ie. an error will occur if the case is not as above).
See gvcorecmds.py's RegisterHelp
function for how to register a help file with the interpreter (this
function determines the location of gvcorecmds_help.txt assuming that
it is in the same directory as gvcorecmds.py, and loads the text from
it if it is present). The suggested convention
for text help files is that if they are needed, they be placed
in the same directory as the commands/functions they relate to, and have the
same name as the command module, minus the '.py', plus '_help.txt'.