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.
- Be sure to include PRO and END statements, along with the COMPILE_OPT IDL2 statement.
- The HEADLESS keyword to the ENVI function will process the data in batch mode without displaying the user interface. To display the user interface in your script, remove this keyword.
- Replace C:\MyData\ with a valid path to your own data files, and change the .tif file type to that of your own data files.
PRO ProcessMultipleFilesExample
COMPILE_OPT IDL2
e = ENVI(/HEADLESS)
Files = File_Search('C:\MyData\', '*.tif')
FOR i=0, N_Elements(Files)-1 DO BEGIN
Raster = e.OpenRaster(Files[i])
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
e = ENVI()
file = 'C:\Data\Myfile.dat'
raster = e.OpenRaster(file)
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
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.
e = ENVI()
file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $
SUBDIRECTORY = ['data'])
raster = e.OpenRaster(file)
fileName = Filepath('qb_boulder_roi.xml', SUBDIR=['data'], $
ROOT_DIR=e.Root_Dir)
rois = e.OpenRoi(fileName)
mask = ENVIRoiMaskRaster(raster, rois[2])
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:
e = ENVI()
File = Filepath('qb_boulder_msi', Subdir=['data'], $
Root_Dir=e.Root_Dir)
Raster = e.OpenRaster(File)
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:
e = ENVI()
file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $
SUBDIRECTORY = ['data'])
raster = e.OpenRaster(file)
expression = '((b4 + b2) - 2*b1) / ((b4 + b2) + 2*b1)'
bandMathRaster = ENVIPixelwiseBandMathRaster(raster, expression)
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
e = ENVI(/HEADLESS)
file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $
SUBDIRECTORY = ['data'])
raster = e.OpenRaster(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:
- Use the ENVIRaster::GetData method while setting the PIXEL_STATE keyword, to retreive the pixel data within the ROI.
- Get the locations (indices) of the "good" pixels in the masked raster, i.e., non-masked pixels. See Raster Pixel State for details.
- Do some processing on the ROI data.
Example:
e = ENVI()
file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $
SUBDIR = ['data'])
raster = e.OpenRaster(file)
View = e.GetView()
Layer = View.CreateLayer(raster)
ROIFile = FILEPATH('qb_boulder_roi.xml', $
ROOT_DIR=e.ROOT_DIR, SUBDIR = ['data'])
rois = e.OpenROI(ROIFile)
waterROILayer = Layer.AddROI(rois[2])
Print, 'Number of pixels in this ROI layer: ',rois[2].PixelCount(raster)
maskedRaster = ENVIROIMaskRaster(raster, rois[2])
data = maskedRaster.GetData(PIXEL_STATE=pixelState)
goodIndices = where(pixelState eq 0)
goodData = data[goodIndices]
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).