X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



Using ENVI and IDL Agents with Your Own API Keys

Using ENVI and IDL Agents with Your Own API Keys

6/22/2026

Earlier this year, we introduced the ENVI® Agent and IDL® Agent to bring intelligent, AI-driven automation to your geospatial and data science workflows. If you missed the launch, you can catch up on the full breakdown by watching our release webinar. Both agents are built upon GitHub Copilot, a powerful AI orchestration... Read More >

What We're Looking Forward to at Esri UC 2026

What We're Looking Forward to at Esri UC 2026

6/16/2026

Every year, the Esri User Conference brings together thousands of geospatial professionals to explore new technologies, share ideas, and learn how organizations are solving complex challenges with GIS. For many members of the NV5 team, attending Esri UC is an annual tradition. Some have attended for more than 15 years. Others will be... Read More >

New ENVI Agent, IDL Agent, and GeoAgent Quick Guides

New ENVI Agent, IDL Agent, and GeoAgent Quick Guides

6/9/2026

The recent release of ENVI® Agent, IDL® Agent, and GeoAgent™ revolutionize how users interact with geospatial software. These agentic AI applications act as partners to plan, simplify, and execute complex workflows. Knowing where to start can be challenging for new users. To this end, we developed three new quick guides to... Read More >

Introducing NISAR Data Support

Introducing NISAR Data Support

6/5/2026

The release of ENVI® SARscape 6.3 in April 2026 includes preliminary support for NASA-ISRO SAR (NISAR) data. The NISAR mission is a joint Earth-observing satellite project between NASA and the Indian Space Research Organization designed to monitor changes in the planet’s land and ice surfaces using advanced radar imaging. It... Read More >

Monitoring Illegal Mining in the Amazon: Turning Persistent Data Into Actionable Insight

Monitoring Illegal Mining in the Amazon: Turning Persistent Data Into Actionable Insight

5/28/2026

Illegal mining over decades has constituted one of the most persistent and complex socio-environmental problems in the Brazilian Amazon. In recent years, with the increasingly intensive use of mechanized extraction, the associated environmental impacts—such as deforestation, intense soil disturbance, river siltation, and mercury... Read More >

1345678910Last
21629 Rate this article:
No rating

Some Caveats when Overriding IDL_Object Methods

Anonym

Barrett’s post last week about using FOREACH with Hash objects reminded me of some problems I’ve had using FOREACH with the ENVIRasterSeries class.  This class inherits from IDL_Object and overrides the _overlodForeach() method, which changes the behavior of the loop.

Let’s use some code to explain this better.  First we can create a raster series using the data shipped with ENVI and the BuildTimeSeries ENVITask:

  e = ENVI(/headless)
 
  dataDir = FilePath('', SUBDIR=['data','time_series'], $
                     ROOT_DIR=e.ROOT_DIR)
  files = File_Search(dataDir, 'AirTemp*.dat')
 
  oTask = ENVITask('BuildTimeSeries')
  oTask.INPUT_RASTER_URI = files
  oTask.OUTPUT_RASTERSERIES_URI = e.GetTemporaryFilename('series')
  oTask.Execute
 
  oSeries = oTask.OUTPUT_RASTERSERIES

If we then use a FOREACH loop on the raster series object, one would logically expect one iteration of the loop with the series itself being the loop element, but instead it will perform 12 iterations for the 12 ENVIRasters that are in the raster series:

  foreach iter, oSeries do begin
    help, iter
  endforeach

Outputs

ITER            ENVIRASTER <249906>
ITER            ENVIRASTER <249960>
ITER            ENVIRASTER <250014>
ITER            ENVIRASTER <250068>
ITER            ENVIRASTER <250122>
ITER            ENVIRASTER <250176>
ITER            ENVIRASTER <250230>
ITER            ENVIRASTER <250284>
ITER            ENVIRASTER <250338>
ITER            ENVIRASTER <250392>
ITER            ENVIRASTER <250446>
ITER            ENVIRASTER <250500>

 

The ENVIRasterSeries class was designed this way so that you could use the more efficient FOREACH loop instead of a FOR loop over the size of the series with calls to Set and Raster:

  for i = 0, oSeries.Count-1 do begin
    oSeries.Set, i
    iter = oSeries.Raster
    help, iter
  endfor

Now let’s say you have a function that can take in an array of ENVIRasterSeries objects, and you want to use a FOREACH loop over the array, so that the loop element is the series in the array:

  foreach series, oSeriesArray do begin
    ; do stuff with each ENVIRasterSeries object
  endforeach

This will fail if a scalar ENVIRasterSeries is passed in, since it will instead result in the iteration over the rasters in the series and not the single series.  Fortunately we can take advantage of IDL’s array promotion capabilities.  If we wrap the oSeriesArray variable in square brackets, then we get the behavior we desire.  When a scalar is passed in, it becomes a 1-element array so the FOREACH loop will iterate over the array one time.  When an N-element array is passed in, it temporarily gets promoted to an Nx1 2-D array, which immediately collapses back into an N-element 1-D array.  Note that this technique won’t work in all cases, however, if you have a List of Hashs (from JSON_Parse(), perhaps), then wrapping the List in square brackets will create a 1-element array of Lists and the FOREACH loop will iterate once and have the List as the loop element, not the Hashs in the List as expected.  But in general this trick will work when you don’t know if you will get an array or a scalar.

  foreach series, [oSeriesArray] do begin
    ; do stuff with each ENVIRasterSeries object
  endforeach

Another IDL_Object override that can cause problems is _overloadSize(), as it can make N_Elements() appear to lie to you.  The List and Hash classes override this method, so that calling N_Elements() on them will tell you how many items are in the List or Hash, not how many List or Hash objects you have.  While an array of Lists sounds like a concept you’ll never encounter, an array of Hashs is possible, as it is what JSON_Parse(/TOARRAY) will return.

Let’s say we are writing a class that has a property that is a Hash, backed by a member variable to store the Hash.  The common pattern for SetProperty is to use N_Elements() on the keyword variable to determine if the method was called with that property name or not:

  if (N_Elements(myProp) gt 0) then begin
    self.myProp = myProp
  endif

The flaw here is that if an empty Hash is passed in the N_Elements() function will return 0 and we won’t update the property with the new value.  What we can do is call the base class implementation of _overloadSize(), which will return the number of Hash objects, not the number of elements in the Hash:

IDL> h = hash('foo', 1, 'bar', 2, 'baz', 3)
IDL> n_elements(h)
           3
IDL> h.IDL_Object::_overloadSize()
           1

Please login or register to post comments.