ENVI 5, released last week, has a new UI and API. I’d like to show a pair of examples that use the API: this week, a batch program; next week, an extension (the successor to a user function).
Batch programs are used to perform a sequence of processing tasks, typically noninteractively. They may use routines from both the ENVI and IDL libraries. Since batch programs are invoked from IDL, they require ENVI+IDL.
I’d like to show a familiar task: creating an NDVI image from the Bighorn Landsat 7 ETM+ scene included in the ENVI distribution. Here’s the beginning of the batch program:
pro envi5_batch_ex compile_opt idl2 e = envi(/headless)
Calling ENVI as a function starts the interface to ENVI 5. (You can still access ENVI Classic (the new nickname for three-window ENVI) by calling ENVI as a procedure.) The HEADLESS keyword starts ENVI without a UI, similar to the Classic ENVI_BATCH_INIT routine. The return value from the ENVI function is a reference for this ENVI session.
Next, set up a path to the Bighorn Landsat file and get a reference to it:
infile = filepath('bhtmref.img', $ root_dir=e.root_dir, $ subdirectory=['classic','data']) bh = e.openraster(infile)
The reference e is used here twice: the ROOT_DIR property holds the path to the ENVI installation directory; the OpenRaster method creates a new instance of the ENVIRaster class for this file. The reference bh is analogous to a FID in Classic, but it also holds image metadata, so an ENVIRaster in effect combines the functionality of ENVI_OPEN_FILE and ENVI_FILE_QUERY in Classic.
To compute NDVI, I’ll choose to use the Classic NDVI_DOIT routine. Most of the DOIT routines haven’t yet been ported from Classic to ENVI 5; this will occur over the next few service packs. I’ll show here a technique that’ll work in this transitional period.
NDVI_DOIT requires an input FID, which we don’t have. Use the ENVIRASTERTOFID function to extract a FID from the existing ENVIRaster object:
bh_fid = envirastertofid(bh)
Note that ENVIRASTERTOFID has a complement, ENVIFIDTORASTER, that converts a FID to an ENVIRaster.
Next, set up additional information required by NDVI_DOIT:
outfile = e.getpreference('output_directory') + 'bhtmref_ndvi.img' bh_dims = [-1, 0, bh.ncolumns-1, 0, bh.nrows-1] bh_pos = [4,3] - 1 ; Landsat [nir,red] bands bh_dt = 4 ; float
The GetPreference method allows programmatic access to certain ENVI preferences. I’m using it here to get the path to the user’s output directory, where NVDI_DOIT will write its result. The variables bh_dims, bh_pos and bh_dt set up the band dimensions, band position vector and data type for the NDVI calculation. Note how the number of samples and number of lines in the image are pulled from the ENVIRaster reference bh.
Now that setup is complete, call NDVI_DOIT through the ENVI_DOIT wrapper:
envi_doit, 'ndvi_doit', $ fid=bh_fid, $ dims=bh_dims, $ pos=bh_pos, $ /check, $ out_bname='Calculated NDVI', $ out_dt=bh_dt, $ out_name=outfile, $ r_fid=r_fid print,'New file written to: ' + outfile
Finish the program by closing the headless ENVI session and returning to IDL:
e.close end
The Close method is the analogue to the Classic ENVI_BATCH_EXIT routine.
Execute this program with the Run button in the IDL Workbench or by calling it from the IDL command prompt:
IDL> envi5_batch_ex
% Compiled module: ENVI5_BATCH_EX.
% Restored file: ENVI.
New file written to: C:\mpiper\ENVI\output\bhtmref_ndvi.img
Grab the source code for this example here.
Pingback: An ENVI 5 extension | The IDL Data Point
Pingback: michaelgalloy.com — User functions in ENVI 5
While executing:
file = {multispectral landsat metadata file *MTL.txt}
raster = envi.OpenRaster(file)
fid= ENVIRasterToFID(raster)
ENVI_DOIT, ‘TMCAL_DOIT’, FID=fid, /USE_METADATA
Gives error:
Invalid pointer: <POINTER ()>.” The result may be invalid.
and while compiling says:
ENVIRASTERTOFID: Raster must be a single ENVIRaster.
Actually Landsat calibration is fine but it stops my script!
How to fix???
Full code is here:
PRO untitled2
compile_opt idl2
; insert here MTL.txt files
batchfiles = ["G:\KyprMat\!!!WorkFolder\!!!!!!!!1\163-015_20100731\L5163015_01520100731_MTL.txt", $
"G:\KyprMat\!!!WorkFolder\!!!!!!!!1\160-016_20010607\L71160016_01620010607_MTL.txt", $
"G:\KyprMat\!!!WorkFolder\!!!!!!!!1\162-015_20090907\L5162015_01520090907_MTL.txt"]
e = ENVI()
foreach file, batchfiles do begin
raster = e.OpenRaster(file)
fid_raster = ENVIRasterToFID(raster)
envi_file_query, fid_raster, DIMS=dims, NB=nb, BNAMES=bnames, FNAME=fname
;path and folder name
path = STRMID(file,0,STRPOS(file,’\',/REVERSE_SEARCH))
folder_name = STRMID(path,STRPOS(path,’\',/REVERSE_SEARCH),STRPOS(path,’\',/REVERSE_SEARCH))
; band 2
full_name = path + folder_name + ‘_b_2_.tif’
pos = [1]
ENVI_DOIT, ‘TMCAL_DOIT’, CAL_TYPE=1, DIMS=dims, FID=fid_raster, OUT_BNAME=bnames , OUT_NAME=full_name, pos=pos, R_FID=fid_output, /USE_METADATA
; band 4
full_name = path + folder_name + ‘_b_4_.tif’
pos = [3]
ENVI_DOIT, ‘TMCAL_DOIT’, CAL_TYPE=1, DIMS=dims, FID=fid_raster, OUT_BNAME=bnames , OUT_NAME=full_name, pos=pos, R_FID=fid_output, /USE_METADATA
; band 5
full_name = path + folder_name + ‘_b_5_.tif’
pos = [4]
ENVI_DOIT, ‘TMCAL_DOIT’, CAL_TYPE=1, DIMS=dims, FID=fid_raster, OUT_BNAME=bnames , OUT_NAME=full_name, pos=pos, R_FID=fid_output, /USE_METADATA
endforeach
end
You should check what the variable ‘raster’ is, comparing with how ENVI Classic handles MTL files.
ENVIRasterToFID does not appear to be returning unique FIDs for each raster object.
See ENVI IDL forum for more details:
http://www.exelisvis.com/language/en-US/UserCommunity/UserForums/forumid/27/postid/13247/scope/posts.aspx