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!



Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

6/3/2025

Rethinking the Reliability of Type 1a Supernovae   How do astronomers measure the universe? It all starts with distance. From gauging the size of a galaxy to calculating how fast the universe is expanding, measuring cosmic distances is essential to understanding everything in the sky. For nearby stars, astronomers use... Read More >

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

5/26/2025

Whether you’re new to remote sensing or a seasoned expert, there is no doubt that large language models (LLMs) like OpenAI’s ChatGPT or Google’s Gemini can be incredibly useful in many aspects of research. From exploring the electromagnetic spectrum to creating object detection models using the latest deep learning... Read More >

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

4/28/2025

When every second counts, the ability to process geospatial data rapidly and accurately isn’t just helpful, it’s critical. Geospatial Intelligence (GEOINT) has always played a pivotal role in defense, security, and disaster response. But in high-tempo operations, traditional workflows are no longer fast enough. Analysts are... Read More >

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

4/24/2025

This blog was written by Eli Dwek, Emeritus, NASA Goddard Space Flight Center, Greenbelt, MD and Research Fellow, Center for Astrophysics, Harvard & Smithsonian, Cambridge, MA. It is the fifth blog in a series showcasing our IDL® Fellows program which supports passionate retired IDL users who may need support to continue their work... Read More >

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

2/25/2025

This blog was written in collaboration with Adam O’Connor from Wyvern.   As hyperspectral imaging (HSI) continues to grow in importance, access to high-quality satellite data is key to unlocking new insights in environmental monitoring, agriculture, forestry, mining, security, energy infrastructure management, and more.... Read More >

1345678910Last
13669 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.