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!



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 >

Ensure Mission Success With the Deployable Tactical Analytics Kit (DTAK)

Ensure Mission Success With the Deployable Tactical Analytics Kit (DTAK)

2/11/2025

In today’s fast-evolving world, operational success hinges on real-time geospatial intelligence and data-driven decisions. Whether it’s responding to natural disasters, securing borders, or executing military operations, having the right tools to integrate and analyze data can mean the difference between success and failure.... Read More >

How the COVID-19 Lockdown Improved Air Quality in Ecuador: A Deep Dive Using Satellite Data and ENVI® Software

How the COVID-19 Lockdown Improved Air Quality in Ecuador: A Deep Dive Using Satellite Data and ENVI® Software

1/21/2025

The COVID-19 pandemic drastically altered daily life, leading to unexpected environmental changes, particularly in air quality. Ecuador, like many other countries, experienced significant shifts in pollutant concentrations due to lockdown measures. In collaboration with Geospace Solutions and Universidad de las Fuerzas Armadas ESPE,... Read More >

Rapid Wildfire Mapping in Los Angeles County

Rapid Wildfire Mapping in Los Angeles County

1/14/2025

On January 8, WorldView-3 shortwave infrared (SWIR) imagery captured the ongoing devastation of the wildfires in Los Angeles County. The data revealed the extent of the burned areas at the time of the capture, offering critical insights for rapid response and recovery. To analyze the affected region, we utilized a random forest... Read More >

Supporting Disaster Response in LA: How Geospatial Insights Aid Disaster Response and Recovery

Supporting Disaster Response in LA: How Geospatial Insights Aid Disaster Response and Recovery

1/10/2025

In the face of unprecedented crises, the strength of a community lies in its ability to come together, adapt, and rebuild. As Los Angeles grapples with the devastating impact of the ongoing wildfires and the heightened risk of flash flooding and landslides, geospatial data and analytics are not just tools, they are lifelines. Geospatial... Read More >

1345678910Last
«March 2025»
SunMonTueWedThuFriSat
2324252627281
2345678
9101112131415
16171819202122
23242526272829
303112345
11895 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.