IDL Tips for Use with Band Math
The Band Math tool is powered by the speed and flexibility of IDL. You do not need to be an expert IDL programmer to use Band Math. The following tips will help you make the most of Band Math and avoid common problems.
Data Types
Doing arithmetic in IDL is a bit different than using a calculator. Important factors include the data type of your input bands and any constants you use in your expression. The following table lists the data types used in IDL:
Data Type |
Casting |
Shortcut |
Dynamic Range |
Bytes per Pixel |
Byte |
byte() |
B |
0 to 255 |
1 |
Integer |
fix() |
S |
-32,768 to +32,767 |
2 |
Unsigned integer |
uint() |
U or US |
0 to 65,535 |
2 |
Long integer |
long() |
L |
-2,147,483,648 to |
4 |
Unsigned long integer |
ulong() |
UL |
0 to approximately 4 billion |
4 |
64-bit integer |
long64() |
LL |
approximately |
8 |
64-bit Unsigned integer |
ulong64() |
ULL |
0 to approximately 2 x 1019 |
8 |
Floating-point |
float() |
. |
+/- 1 x 1038 |
4 |
Double precision |
double() |
D |
+/- 1 x 10308 |
8 |
Complex floating-point |
complex() |
|
same as float() |
8 |
Complex double precision |
dcomplex() |
|
same as double() |
16 |
Each data type has a limited dynamic range, particularly the integer types. This means that they can only represent a limited set of numbers. For example, a byte data type can only represent values between 0 and 255. If you were to add two byte bands together (b1 + b2)
and the sum was greater than 255, the result would not be what you expect.
When the value from a Band Math expression is bigger than the data type can hold, it overflows and starts counting from the beginning again. For example, suppose that you have a Band Math expression that results in values larger than 32,767 in an integer image. Those values will wrap around to the beginning of the integer dynamic range and will be assigned values of -32,768 (a largely negative number). Another common example is adding byte data with values of 250 and 10. The result would be 4.
This situation is commonly encountered in Band Math because remote sensing images are frequently stored as bytes or integers. To avoid data type overflow, you should promote the data type of input bands using one of the IDL data type casting functions listed in the above table. For example, when adding two-byte image bands together (as above), you will get the correct answer if you promote the data type to an integer using the IDL function FIX():
fix(b1) + b2
Promoting Data Types
Using a casting function such as FIX() is not the only way to promote the data type of your Band Math result. This is because IDL is dynamically typed, which means that the data type of an IDL statement is automatically promoted to the largest data type it encounters in the expression. Because certain numbers (such as small integers) can be represented by several different data types, IDL must apply some default rules about how these numbers are interpreted. For example, numbers without decimal points are always interpreted as integers (or long integers or 64-bit unsigned integers with larger values), even if they are within the dynamic range of a byte data type. For instance, the following expression adds the value 5 to a byte image:
b1 + 5
The number 5 is interpreted as a 2-byte integer, so the result would be promoted to an integer image, which uses twice as much disk space as a byte image. To keep the result a byte image, you could either use the data type casting function BYTE():
b1 + byte(5)
Or, use an IDL shortcut for casting an integer as a byte:
b1 + 5B
Adding a B (upper or lowercase) immediately following a number ensures that it is interpreted as a byte data type. See the "Shortcut" column in the table above for other helpful shortcuts.
Order of Operation
Mathematical operators are not necessarily carried out in the order they appear in the expression, but rather according to a hierarchy of precedence. Using parentheses can change the order of operations, with the most deeply nested part of the expression being carried out first. The table below lists the order of precedence for IDL operators. Operators that have the same precedence will be carried out in the order they appear in the expression. For example, consider the following expressions (with constants used in place of bands):
5 + 3 * 2
: Evaluates to 11 because the multiplication operator takes precedence.
(5 + 3) * 2
: Evaluates to 16 because the parentheses change the order of operation.
The order of precedence combined with the dynamic typing can also change the outcome of your expression. Be sure to promote the data type in the proper place in the expression to avoid data type overflow or integer division errors. For example, consider the following case:
Float(5) + 10 / 3
: All of the constants are integers but the float() function promotes the result into a floating-point data type. However, because the division operator has precedence over the addition, it is applied first and the division is carried out as integers, then added to 5 as a floating-point operation. The result is 8.0 (instead of the expected 8.3).
5 + 10 / float(3)
: If the data type promotion is moved to one of the division variables then the result is 8.3.
The following table describes the order of precedence for each operator:
Order of Precedence |
Operator |
Description |
First |
( ) |
Parentheses to group expressions |
Second |
^ |
Exponents |
Third |
* |
Multiplication |
# and ## |
Matrix multiplication |
|
/ |
Division |
|
MOD |
Modulus (remainder) |
|
Fourth |
+ |
Addition |
- |
Subtraction and negation |
|
< |
Minimum |
|
> |
Maximum |
|
NOT |
Boolean negation |
|
Fifth |
EQ |
Equal |
NE |
Not equal |
|
LE |
Less than or equal |
|
LT |
Less than |
|
GE |
Greater than or equal |
|
GT |
Greater than |
|
Sixth |
AND |
Boolean AND |
OR |
Boolean OR |
|
XOR |
Boolean exclusive OR |
|
Seventh |
? : |
Conditional expression (rarely used in Band Math). The following example expression compares two arrays, b1 and b2:
|
Integer Division
When performing division on bands that are not a floating-point data type, the results are not rounded up or down. Instead they are truncated so that the part of the number following the decimal point is dropped. To avoid integer division, always promote the data type to floating-point.
b1 / float(b2)
If you want to keep the results of the division as an integer, it is usually better to carry out the division as a floating-point operation. Then convert the results back to your desired data type. For example, use the following expression if your input bands are both byte data type and you want to round up the result and store it as an integer:
fix( ceil( b1/float(b2) ) )
Avoid Using IDL Functions that Require All of the Image Data at Once
Band Math processing is tiled just like other ENVI API routines. If you use an IDL function that requires all of the image data at once, you may see banding artifacts in the resulting image because the Band Math expression is applied individually to each tile of data. For example, consider using the IDL function MAX(), which determines the maximum value in an array:
b1 / max(b1)
If the Band Math processing is tiled, then each tile will be divided by the tile's maximum value, instead of the maximum value of the whole band. If you find that your Band Math result has broad horizontal stripes in it, tiling may be the cause of the problem (because the tiles are horizontal sections of the image). IDL functions to avoid include FFT, MAX, MIN, MEAN, MEDIAN, STDDEV, VARIANCE, and TOTAL. In most cases it is also difficult to use the BYTSCL function, but if you know beforehand the data range of your input bands then you can use BYTSCL as long as you include the MIN and MAX keywords.
Array Operators
IDL’s array operators are powerful and easy to use with Band Math. They allow you to examine and treat every pixel in an image individually without having to do a FOR loop, which is not allowed in Band Math. Array operators include the following:
- Relational operators (LT, LE, EQ, NE, GE, GT)
- Boolean operators (AND, OR, NOT, XOR)
- Minimum and maximum operators (<, >)
They operate simultaneously on every pixel in an image and return an image of the same dimensions. For example, to find all pixels with a negative value and replace them with the value -999, you could use the following Band Math expression:
(b1 lt 0) * (-999) + (b1 ge 0) * b1
The relational operators return 1 for true and 0 for false. So, the term (b1 lt 0)
will return an array of the same dimensions as b1, filled with ones where b1 was negative and zeros everywhere else. Multiplying this by the replacement value (-999) affects only those pixels that met the criterion of being negative. The second relational operator (b1 ge 0)
is the complement to the first, finding all of the pixels that are positive or zero, which is multiplied by their original value and added to the replacement value array.
The following table describes selected IDL array handling functions. For a complete list, see the IDL Help.
Category |
Available Functions |
Basic Arithmetic |
Addition (+), subtraction (-), multiplication (*), and division (/) |
Trigonometric Functions |
sin(x), cos(x), and tan(x) |
Arcs: asin(x), acos(x), and atan(x) |
|
Hyperbolics: sinh(x), cosh(x), and tanh(x) |
|
Relational and Logical Operators |
LT, LE, EQ NE, GE, GT |
AND, OR, NOT, XOR |
|
maximum (>) and minimum (<) |
|
Data Type Conversions |
See the table above. |
Other Math Functions |
Exponent (^) and natural exponent (exp(x)) |
Natural Logarithm: alog(x) |
|
Log Base 10: alog10(x) |
|
Integer rounding: round(x), ceil(x), and floor(x) |
|
Square Root: sqrt(x) |
|
Absolute Value: abs(x) |
Here is an example of a slightly more complicated expression: The expression below uses several criteria to create a binary mask identifying pixels that are predominantly clouds. This algorithm can actually be used to create cloud masks from calibrated daytime imagery from the Advanced Very High Resolution Radiometer (AVHRR) sensor.
- The variable b4 (a thermal band) must be negative, OR:
- The variable b2 (a reflectance band) must exceed 0.65, AND:
- The difference between bands b3 and b4 (middle-infared and thermal) must exceed 15 degrees.
Because relational operators return a value of 1 for true, the mask will have ones where there are clouds and zeros elsewhere.
(b4 lt 0) or ( b2 gt 0.65) and ((b3 - b4) gt 15 ))
The minimum and maximum operators are also array-based operators. Unlike the relational or Boolean operators, they do not return true or false, but rather the actual MAX or MIN value. The following expression shows an example. For every pixel in the image, the greater of zero, b2, or b3 is added to b1. This ensures that the value that is added to b1 is always positive.
b1 + (0 > b2 > b3)
In the next example, the use of both the minimum and maximum operators clips the data values in b1 at zero and one. No value in b1 will exceed one or fall below zero.
0 > b1 < 1
See Also
Band Math User Functions, Band Math, ENVI Modeler Example: Using Conditional Operators with Rasters, ENVIPixelwiseBandMathRaster, PixelwiseBandMathRaster Task