ENVI API Frequently Asked Questions

This topic provides a list of common questions and answers related to programming in ENVI.

Data Management

Analytics

Regions of interest (ROIs)

Data Management

How do I view the properties of a data file?

Print the properties of a raster, vector, or region of interest (ROI) object, as the following example shows:

IDL> e = ENVI()

ENVI> File = FILEPATH('qb_boulder_msi', $

  Subdir=['data'], Root_Dir=e.Root_Dir)

ENVI> Raster = e.OpenRaster(File)

ENVI> Print, Raster

IDL prints the basic properties of the input file such as the data type (unsigned integer), number of bands (4), number of columns (1024), and number of rows (1024). See the Properties section of the ENVIRaster, ENVIVector, ENVIPointCloud, or ENVIROI help topics for descriptions of each property.

To determine the spatial reference of a raster object, issue a PRINT statement on the SPATIALREF property, as follows:

ENVI> Print, Raster.SPATIALREF

IDL prints details of the spatial reference such as the coordinate system, pixel size, rotation angle, tie point map coordinates, and the pixel location of the tie point coordinates.

Note: Vectors do not have spatial references, but they have coordinate systems. See Map Information for details.

Rasters also have metadata. Issue a print statement on the METADATA property to see the available metadata fields:

ENVI> Print, Raster.METADATA

To get the details of a particular metadata field, use brackets and single quotes as follows:

ENVI> Print, Raster.METADATA['wavelength']

How do I open and process multiple files in a loop?

Use the following code as a template. It opens multiple image files from disk, including all subdirectories underneath the indicated directory. It uses a FOR loop to process the data.

PRO ProcessMultipleFilesExample

COMPILE_OPT IDL2

 

; Start the application

e = ENVI(/HEADLESS)

 

; Select input files

Files = File_Search('C:\MyData\', '*.tif')

 

FOR i=0, N_Elements(Files)-1 DO BEGIN

  Raster = e.OpenRaster(Files[i])

 

; data processing here

 

ENDFOR

END

How do I set a data value to ignore?

To permanently set a data value to ignore on one or more rasters, use the ENVIRasterMetadata::UpdateItem or ENVIRasterMetadata::AddItem method, depending on whether or not a 'data ignore value' header field exists. Then write the resulting metadata to an ENVI header file. For example, suppose that a data vendor distributes imagery with ocean pixels set to a fill value of -9999. Set a data ignore value as follows:

PRO SetDataIgnoreValue

COMPILE_OPT IDL2

 

; Start the application

e = ENVI()

 

; Open the raster

file = 'C:\Data\Myfile.dat'

raster = e.OpenRaster(file)

 

; Set a data ignore value

metadata = raster.METADATA

 

IF (metadata.HasTag ('data ignore value')) THEN BEGIN

  metadata.UpdateItem, 'data ignore value', -9999.0

ENDIF ELSE BEGIN

  metadata.AddItem, 'data ignore value', -9999.0

ENDELSE

 

; Save the raster to ENVI format so that the

; header file will update

outFile = e.GetTemporaryFilename()

raster.Export, outFile, 'ENVI'

END

To temporarily set a data value to ignore when displaying a raster, set the DATA_IGNORE_VALUE keyword of the ENVI::OpenRaster method. This overrides any data ignore values already set in the header file, but it does not update the header file. For example:

file = 'C:\Data\Myfile.dat'

raster = e.OpenRaster(file, DATA_IGNORE_VALUE=-9999.0)

You can also set a unique data value for pixels that have a non-zero pixel state (NoData, Mask, Outside of ROI) when exporting a raster to disk. Here is an example that masks any pixels that are outside of a selected ROI. If you were to display the masked raster immediately after creating it, you would not see the masked pixels. In this case, you must export the masked raster and set the DATA_IGNORE_VALUE keyword to 0. When you reopen and display the masked raster, you will see the masked pixels.

; Start the application

e = ENVI()

 

; Open an input file

file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $

  SUBDIRECTORY = ['data'])

raster = e.OpenRaster(file)

 

; Open a multi-part ROI

fileName = Filepath('qb_boulder_roi.xml', SUBDIR=['data'], $

  ROOT_DIR=e.Root_Dir)

rois = e.OpenRoi(fileName)

 

; Create a masked raster based on the water ROI.

; Pixels outside of the ROI are masked.

mask = ENVIRoiMaskRaster(raster, rois[2])

 

; Save the masked raster to disk

outFile = e.GetTemporaryFilename()

mask.Export, outFile, 'ENVI', DATA_IGNORE_VALUE=0

See Masks for more information about creating and applying raster masks in ENVI.

How do I convert the pixel values of a raster to a different data type?

The process of converting data types (for example, integer to floating-point) is called casting or type-casting. Use ENVICastRaster or the CastRaster task for this purpose.

What are Hydrate and Dehydrate routines used for?

When using the ENVI API, you may have come across routines that are named Hydrate and Dehydrate. These pertain to a concept in computer science called serialization, where data objects are reduced into a simple format so they can be stored and transferred to different environments. The objects can be reconstructed back to their original form later. In the case of ENVI, objects such as ENVIRaster or ENVICoordSys can be dehydrated into text format so that they can be used in cloud-computing environments. Then they can be hydrated in order to restore them to their full state.

See the Dehydrate and Hydrate topics for ENVI API routines (for example, ENVIRaster::Dehydrate and ENVIRaster::Hydrate) for details on usage.

Analytics

Where can I find a list of task names?

See the ENVITask help topic for a list of available data-processing tasks. To print task names and the details of individual tasks, use these options:

Task_Names Property

This is the most common method for printing a list of task names. Type the following at the IDL command line:

IDL> e = ENVI()

ENVI> Print, e.Task_Names

Use a string from the resulting list to create an instance of a task, for example:

ENVI> Task = ENVITask('ISODATAClassification')

Print the task variable to learn what that task does:

ENVI> Print, Task

QueryTaskCatalog

You can access the catalog of ENVITasks anytime within a script by using the QueryTaskCatalog task:

Task = ENVITask('QueryTaskCatalog')

Task.Execute

taskNames = Task.TASKS

Use the QueryTask task to access details of a selected task within the catalog:

Task = ENVITask('QueryTask')

Task.Task_Name = 'ISODATA Classification'

Task.Execute

taskDefinition = Task.DEFINITION

Some data-processing operations are available as a virtual raster and an ENVITask. Which one should I use?

See the Virtual Rasters topic for more information about virtual rasters and how they differ from ENVITasks.

How do I save the result of an ENVITask to a file on disk?

Set the OUTPUT_RASTER_URI property to a valid path and filename for the raster. The result will be in ENVI raster format. Here is an example of saving a median filter image to disk:

; Start the application

e = ENVI()

 

; Open an input file

File = Filepath('qb_boulder_msi', Subdir=['data'], $

  Root_Dir=e.Root_Dir)

Raster = e.OpenRaster(File)

 

; Run the Median Filter task

Task = ENVITask('MedianFilter')

Task.INPUT_RASTER = Raster

Task.WINDOW_SIZE = 5

Task.OUTPUT_RASTER_URI = 'C:\MyData\MedianRaster.dat'

Task.Execute

ENVITasks that create vector output (for example, the ClassificationToShapefile task) behave similarly. In these cases, set the OUTPUT_VECTOR_URI property and provide a .shp file extension.

You can also have ENVI automatically create a filename and save the result to your system's temporary directory. Use the ENVI::GetTemporaryFilename method in conjunction with the OUTPUT_RASTER_URI property.

Task.OUTPUT_RASTER_URI = e.GetTemporaryFilename()

The resulting file remains in your system's temporary directory when you close the ENVI session; you must delete it manually if you no longer need it.

You can also save a raster to PNG, NITF 2.0, NITF 2.1, NSIF 1.0, and TIFF formats. Use the following tasks:

When creating a custom task that creates raster output, set the direction key to output for the OUTPUT_RASTER parameter in the task template. For example:

"name": "OUTPUT_RASTER",

"keyword": "OUT_FILENAME",

"display_name": "Output Raster",

"type": "ENVIRASTER",

"direction": "output",

"required": true,

"description": "This is a reference to the output raster of filetype ENVI."

By doing this, ENVI will automatically create an OUTPUT_RASTER_URI input property.

How do I perform band math with rasters?

Use ENVIPixelwiseBandMathRaster to apply a mathematical expression to a raster on a pixel-by-pixel basis. You must name the band variables as bx, where x is the order of the band (not the band number). For example, b1 is the first band in the raster, b2 is the second band, and so forth. Here is an example:

; Start the application

e = ENVI()

 

; Open an input file

file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $

SUBDIRECTORY = ['data'])

raster = e.OpenRaster(file)

 

; Calculate enhanced NDVI

expression = '((b4 + b2) - 2*b1) / ((b4 + b2) + 2*b1)'

bandMathRaster = ENVIPixelwiseBandMathRaster(raster, expression)

 

; Display the result

View = e.GetView()

Layer = View.CreateLayer(bandMathRaster)

If you are writing a script that uses ENVITasks, use the PixelwiseBandMathRaster task.

How do I create and apply masks?

Please refer to the Masks topic, which describes working with masks in the ENVI user interface and API.

Regions of Interest (ROIs)

How do I process the pixels within an ROI?

You can do some simple tasks with ROIs using the ENVI API:

However, you may want process the pixels within an ROI, for example calculating statistics or analyzing the pixel data. Set the ROI keyword in the ENVIRaster::GetData method to retrieve the pixel data within an ROI. The following example shows how to calculate the mean value of the pixels in a multi-part ROI:

PRO GetROIExample

COMPILE_OPT IDL2

; Start the application

e = ENVI(/HEADLESS)

 

; Open an input raster

file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $

  SUBDIRECTORY = ['data'])

raster = e.OpenRaster(file)

 

; Open an ROI file

file = FILEPATH('qb_boulder_roi.xml', ROOT_DIR=e.ROOT_DIR, $

  SUBDIRECTORY = ['data'])

rois = e.OpenRoi(file)

 

FOREACH roi, rois DO BEGIN

  pixelData = raster.GetData(ROI=roi)

  mean = Total(pixelData,1, /DOUBLE) / roi.PixelCount(raster)

  Print,'Roi: ' + roi.Name

  Print,'Mean = ', mean

  Print

ENDFOREACH

END

Big ROIs will return a large amount of data. To avoid returning too much data, use a combination of ENVIROIMaskRaster and ENVIRaster::GetData as follows:

  1. Use the ENVIRaster::GetData method while setting the PIXEL_STATE keyword, to retreive the pixel data within the ROI.
  2. Get the locations (indices) of the "good" pixels in the masked raster, i.e., non-masked pixels. See Raster Pixel State for details.
  3. Do some processing on the ROI data.

Example:

; Launch the application

e = ENVI()

 

; Open and display an ENVIRaster

file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $

  SUBDIR = ['data'])

raster = e.OpenRaster(file)

View = e.GetView()

Layer = View.CreateLayer(raster)

 

; Open a multi-part ROI

ROIFile = FILEPATH('qb_boulder_roi.xml', $

  ROOT_DIR=e.ROOT_DIR, SUBDIR = ['data'])

rois = e.OpenROI(ROIFile)

 

; Display the water ROI only

waterROILayer = Layer.AddROI(rois[2])

 

; Print the number of pixels in this ROI

Print, 'Number of pixels in this ROI layer: ',rois[2].PixelCount(raster)

 

; Create a masked raster using the water ROI

maskedRaster = ENVIROIMaskRaster(raster, rois[2])

 

; Get the data values

data = maskedRaster.GetData(PIXEL_STATE=pixelState)

 

; Exclude pixels that have no data

goodIndices = where(pixelState eq 0)

 

; Process the good pixels

goodData = data[goodIndices]

 

    ; processing here

If you issue a Help command on the goodData variable, you will see that it is an unsigned integer array with 14,716 elements. This ROI has 3,679 pixels with four bands of data (3679 * 4 = 14716).