| Genie User Guide: for use with the Los Alamos ISIS/Genie 0.99.11 software release | ||
|---|---|---|
| <<< Previous | Next >>> | |
This is a short tutorial on writing elementary operators (aka "genes") for genie in IDL. It is assumed that the reader knows the basic ideas behind how genie works, and what operators generally do. It is also assumed that the reader has a minimal proficiency in writing IDL, but a minimal proficiency is really all that is needed, unless you want to do something complicated.
In general, operators read a small number of input planes (often one or two), perform some operations with them, based on an set of parameters (typically, zero to a few), and produce output planes (usually just one). A "plane" is a two-dimensional array of floating point numbers, and corresponds to either a "data plane" (a single spectral channel in the original multispectral image or auxilliary image such as a DEM) or to a "scratch plane" which is equivalent to a data plane when used as input, and which are used to store the output of operators (original data planes are not modified by operators).
Operators are not permitted to overwrite input planes. Note, in production mode, this is neither tested nor enforced, so be careful not to write an operator that does this; such an operator could alter a data plane and that would screw up the whole GENIE run.
An operator can assume that input planes are non-negative; an operator should write output planes that are non-negative. Again, in production mode, this is neither tested nor enforced.
Operators are IDL procedures (PRO's), not functions. The arguments are input planes first, output planes next, and parameter values last.
Avoid explicitly setting values to double precision; if the data is already in double precision, then operations will be promoted to that precision automatically; and if the data is ordinary floats, then the promotion to double precision will increase memory usage.
To begin, let's look at a simple operator: ADDP (for "add planes")
PRO ga_addp, in1, in2, out
out = in1 + in2
END
|
The first two arguments are the two input planes, and the third argument is the output plane. As long as the input planes are non-negative, the output plane will be non-negative, as required.
From the point of view of the operator internals, the input planes and output planes are expected to range from zero to a value dataScale. In the current implementation of GENIE, dataScale is set to 1.0, but this should not be depended upon. The variable dataScale is available from the COMMON block 'GenieParms'.
Note that, unlike the condition that data be greater than or equal to zero, which is a strict rule, the condition that data should be between zero and dataScale is an informal "fuzzy" condition. If the max data value in a plane is 0.01*dataScale, or 10*dataScale, then neither of those situations is technically illegal, but both violate the spirit of the dataScale. For good performance, you really do want your output data to be in this general range.
However, a very important rule is that your operators do not employ global properties of the image. One place where it is easy (but still incorrect) to break this rule is in rescaling input or output so that it covers the full range. Something like this
in_new = dataScale*in/max(in) ;; do not do this! |
ensures that the largest value of in_new is dataScale, but it will give different answers if you are looking at the whole scene or just a part of a scene. Put another way, the value of a pixel at point x,y will depend on values of pixels that are far far away from x,y.
External to the operator, the values of dataScale is invisible, and parameter values, for example, should scale with the value of dataScale when appropriate.
For example, here is another operator: ADDS ("add a scalar")
PRO ga_adds, in, out, scalar
COMMON GenieParms, dataScale
out = (in + dataScale*scalar) > 0
END
|
(Note the `x > 0' operator in IDL is equivalent to the minimum of x and 0; that is, it returns x as long as x is positive, but returns 0 whenever x is negative.)
Because IDL's morphological operators (notably dilate and erode) have invalid behavior near the edges of images, and because they do not permit floating point data, special effort must be employed to use them in GENIE. To assist in this, several helper routines have been written, including:
gs_padimage() pads the size of the image by the size of the structuring element. Note that the padding is removed by using the /unpad keyword.
gs_discretize() converts the floating point image data into long integers. The /undo keyword converts the integers back into floating point.
gs_mselt() produces a structuring element from a pair of parameters.
A simple example of how to use these helper functions is provided by the DILATE operator:
PRO ga_dilate, in, out, w, s
mse = gs_mselt(w,s) ;morphological structure element
;; scale input
tmp = gs_discretize(in)
tmp = gs_padimage(tmp,w)
tmp = dilate(tmp,mse,/gray,/ulong)
tmp = gs_padimage(tmp,w,/unpad)
;; rescale output
out = gs_discretize(tmp,/undo)
END |
Once you've written an operator in IDL, you need to place it somewhere GENIE can access the file, and you need to provide an 'eop' entry for it so that GENIE knows it is available and understands how to use it.
The standard location for IDL operators in individual 'pro' files is INSTALL_PATH/share/genie/pro. Here, for instance, INSTALL_PATH=/opt/isis on the the standard Solaris installations. For developers, INSTALL_PATH is ISIS_DEV/genie/CONFIG_GUESS. (If you are a developer, you should know what your ISIS_DEV path is, and CONFIG_GUESS is a string like 'sparc-sun-solaris2.6' which describes the platform on which you are running.)
The standard location for the 'eop' files of the GENIE distribution is INSTALL_PATH/share/genie.
If you are writing your own operators, you will find the files in these directories useful as examples of what do to. Although you can place your new or modified 'eop' files and 'pro' files in these directories, we actually recommend placing then elsewhere. GENIE can be directed to use them by setting the --eopSearchPath and --idlSearchPath options in your options ('.opt') file to include the new directories where you have placed your new .pro and .eop files. If you have written a new 'myfile.eop' then you should add "myfile" to the list of --eopFiles.
eop entries begin with an upper-case name, are followed by key=value pairs, and are terminated by a semicolon.
Regarding those key=value pairs on the first line:
rp is number of read (input) planes; if not specified, default is 1.
wp is number of write (output) planes, default is 1.
idl is the name of the idl routine that implements the operator, which should agree with the name of the .pro file in which the operator is implemented
A special type of key=value pair is the parm={...} line. These specify the parameters in the operator, and inside the curly braces is another set of key=value pairs, which include
type is either f (floating, default), i (integer), or s (symbolic) symbolic is like integer, except that no ordering is implied, e.g., the specification of the shape of a structuring element, such as circle or square, for a spatial operator.
initval is the initial value of the operator. Note that the notation [x:y] corresponds to the range from x to y, inclusive.
del is the size of the change permitted by a parameter mutation.
bound is the range inside of which the parameter is bounded, even after multiple mutations.
For example, here are three eop entries, from the three operators shown above.
ADDP rp=2 idl=ga_addp libgenie=ge_add_planes;
ADDS idl=ga_adds libgenie=ge_add_scalar_to_plane
parm={initval=[-1:1],del=.2};
DILATE idl=ga_dilate
parm={type=i,initval=[1:3],del=1,bound=[1:5]}
parm={type=s,initval=1,del=0,bound=[0:8]}; |
The 'ADDP' is a simple eop entry. There are two read planes (rp=2), one write plane (wp=1 is default), and the idl program is ga_addp, which is implemented in the file ga_addp.pro. There is also a libgenie entry for this operator, but it is ignored for GENIE running with IDL.
The 'ADDS' operator includes a single parameter, which is of the default floating point type. It is specified to start in the range from -1 to 1, and mutations are gaussian steps with standard deviation 0.2.
The 'DILATE' operator has a single read plane (rp=1 is default), a single write plane (wp=1 is default), and two parameters. The first is an integer specifying the radius of the structuring element. Note that the bound prevents the radius from being zero or negative. The second type is symbolic and corresponds to the shape of the structuring element. For many operators gs_mselt() provides some nine different shapes (see gs_melt.pro for the authoritative list), and all of those are allowed (bound=[0:8]), but the initial value will be 1, which corresponds to a circular element, and since del=0, there will be no mutations. That is, a run that uses this eop file will only use circular structure elements.
More information on eop files is in the documentation in the appendix on EOP files.
Note: the operators shown so far have a fixed number of inputs, outputs, and parameters. It is possible to write operators for which these numbers are variable. These are quite a bit more complicated, and the reader is referred to the operators in the MultiSpec.eop file, and the associated IDL .pro files, for examples.
| <<< Previous | Home | Next >>> |
| GENIE's runtime options | The EOP file structure |