retrieving the content of a display layer

Post any questions, ideas, or topics related to Jython and Python scripting.
User avatar
hproe
Posts: 504
Joined: Sat Nov 27, 2010 3:46 pm

retrieving the content of a display layer

Post by hproe »

Hi -

This might be a silly question, but I just cannot find a solution.

After having produced an image with GUI commands, e.g. a VIIRS image, I would like to further work with it in a script. How I see it, conceptually that could look like:
myImage=myLayer.retrieveContent()
Is there such a facility, alas hidden to me?

cheers, HP
User avatar
bobc
Posts: 990
Joined: Mon Nov 15, 2010 5:57 pm

Re: retrieving the content of a display layer

Post by bobc »

Hi HP -

I believe you would want to use getLayer.

For example, if I create a display of NPP data through the GUI and then want to change the color enhancement through scripting, I can do the following:

Code: Select all

nppLayer = activeDisplay().getLayer(1)
nppLayer.setEnhancement('Temperature')

The 1 after getLayer specifies the layer to grab from the display. This is 0-based, so the map layer (the first thing in the display) would be grabbed via getLayer(0).

Please let me know if this isn't what you are looking for.

Thanks -
Bob Carp
User avatar
joleenf
Posts: 1123
Joined: Mon Jan 19, 2009 7:16 pm

Re: retrieving the content of a display layer

Post by joleenf »

Hi HP,

There may be better ways to verify which layer you have than the following, but for a quick check after using the code that Bob posted, you could type

print layer

which will provide the layer type and if that layer has a display label, your could probably get useful information from

print layer.getLayerLabel()

Joleen
User avatar
bobc
Posts: 990
Joined: Mon Nov 15, 2010 5:57 pm

Re: retrieving the content of a display layer

Post by bobc »

Along the lines of what Joleen mentioned, here are a couple of other ways to verify the layer you selected with getLayer:

Code: Select all

print nppLayer.getDataSource()

In my case, this returns: VIIRS 2015-10-05 17:53:40 GMT

Code: Select all

print nppLayer.getDataChoice()

In my case, this returns: VIIRS-M3-SDR_All/Reflectance

- Bob
User avatar
hproe
Posts: 504
Joined: Sat Nov 27, 2010 3:46 pm

Re: retrieving the content of a display layer

Post by hproe »

good people -

Thanks for the hints. These are all fine, but do not solve my problen, which now describe in more detail.

There is a 'sandwich' formula, probably written by Mike and/or Martin Setvak. Obvioulsy, it has been used by Joleen (search for 'sandwich' here in the forum). You need to feed this formula with 2 images (an IR and a VIS). This is straightforward with data retrieved from ADDE servers, like

Code: Select all

ir=loadADDEImage()
vis=loadADDEImage()


However, it does not work when feeding it with images that have been displayed manually, doing

Code: Select all

ir=activeDisplay().getLayer(1)
vis=activeDisplay().getLayer(2)

In this case, I get an 'AttributeError' from getFloats when sandwich wants to 'float' image ir.

Alternative question: Is there a way to script the manual procedure that displays of a VIIRS band, in particular the sub-setting in the granule?

BTW Bob's print command

Code: Select all

print ir.getDataChoice()

does not dig down to primary data source, i.e when applying a formula during the data choice it is returning the name of this formula, e.g. 'swathToGrid' for VIIRS bands. Quite useless.

HP
User avatar
bobc
Posts: 990
Joined: Mon Nov 15, 2010 5:57 pm

Re: retrieving the content of a display layer

Post by bobc »

Hi HP -

I'm replicating your results with passing getLayer layers through a formula. It seems like what is returned from getLayer acts just like a layer, so you can do things like apply an enhancement to it, set the layer's visibility, etc... but it doesn't allow for passing it through a formula, and I'm not seeing an alternative way of doing this. I wrote up Inquiry 2189 mentioning that it would be nice if layers returned from getLayer could be passed through formulas, or if not it would be good to come up with a new function to pull data from a display that can be passed through a formula.

As for displaying VIIRS data through scripting, there is an under development function called loadVIIRSImage. This function is not yet documented because the actual NPP chooser is still under development. You can find documentation for loadVIIRSImage in the Background Processing Functions branch in the Jython Library. This function allows for aggregation of consecutive granules of data as long as the data and geolocation are contained in the same directory. The only subsetting currently supported by loadVIIRSImage is stride, where you can skip over pixels in the x and/or y direction. Here's a quick example script that displays SVM04 data from SSEC's peate ftp server:

Code: Select all

# setup.
from glob import glob
path = 'Directory/path/to/NPP/data/'

# define m4data as the SVM04 data in the above directory
m4parms = dict(
    # glob returns a list of all SVM04* files in 'path'
    file_list = glob(path+'SVM04*'),
    # product to display, as shown in the Field Selector
    field = 'VIIRS-M4-SDR_All/Reflectance',
    # set the x and y stride to 4 (default is 1 for full resolution)
    stride = 4,
    )
m4data = loadVIIRSImage(**m4parms)

# build window and display data
panel = buildWindow()
swathLayer = panel[0].createLayer('Image Display',m4data)

If you want, you can pass the m4data through one of the VIIRS formulas from the plugin (swathToGrid or RGB). I wrote up Inquiry 2190 to add keywords for geographic subsetting by lat/lon and line/ele with loadVIIRSImage.

As for the getDataChoice() printing out 'swathToGrid' for the swathToGrid layer, I'm replicating this as well. I've been looking for other functions that might list out the actual field passed through swathToGrid and all that I've found thus far is:

Code: Select all

print nppLayer.getDetailsContents()

... which returns a lengthy HTML string (but the string does include VIIRS-M4-SDR_All/Reflectance):
"<br> <b> Data:</b><ul><li> Derived quantity: <br>Formula: <i>swathToGrid(field, res[isuser=true,default=800.0], mode[isuser=true,default=1.0])</i><br><b>Field:</b> swathToGrid <b>(swathToGrid)</b><br>from: <ul><li><b>Field:</b> res[isuser=true,default=800.0] <b>(res[isuser=true,default=800.0])</b><li><b>Field:</b> mode[isuser=true,default=1.0] <b>(mode[isuser=true,default=1.0])</b><li><b>Field:</b> VIIRS-M4-SDR_All/Reflectance <b>(VIIRS-M4-SDR_All/Reflectance)</b> from: <br>Suomi NPP</ul> </ul>Geo selection:x:0 y:0 z:0 bbox:null<br>"
and...

Code: Select all

nppLayer.showDetails()

This pops up a details window for the layer (same that you would see through the Layer Controls for the layer when you go to Help>Details). It looks like the information written out in this Details window comes right from getDetailsContents(). Are either of these two functions giving you what you are looking for? Just as an FYI, I've been finding these functions in the DisplayControlImpl class in the javadocs.

Thanks -
Bob
User avatar
hproe
Posts: 504
Joined: Sat Nov 27, 2010 3:46 pm

Re: retrieving the content of a display layer

Post by hproe »

Hi Bob -

Very useful information, many thanks. Obviously, I have done a bad job in searching for adequate code. I got thins working.

However, I have hit a snag when calling 2 bands in sequence and doing bow-tie correction (swathToGrid). The second image has holes, similar to what I reported recently in the Forum thread 'VIIRS second image layer speckled'. While there re-selecting the sub-area helped, scripting does not offer this possibility (see Bob's comments below). Looks like you have to 'disturb' swathToGrid() somehow also in the scripting case. I experimented a bit and came up with a work-around - just vary the resolution given to swathToGrid() slightly, like

Code: Select all

 from glob import glob
 homeDir=os.path.expanduser('~') # OS-independent root
 imPath=homeDir+'/Documents/DATA/VIIRS/'
 irParms=dict(
  file_list=glob(imPath+'SVM15_npp_d20150920*'),
  field='VIIRS-M15-SDR_All/BrightnessTemperature',
  stride=1,
  )
 irImg=swathToGrid(loadVIIRSImage(**irParms),750,1)        #nominal resolution of 750m
 irLyr=activeDisplay().createLayer('Image Display',irImg)
 visParms=dict(
  file_list=glob(imPath+'SVM04_npp_d20150920*'),
  field='VIIRS-M4-SDR_All/Reflectance',
  stride=1,
  )
 visImg=swathToGrid(loadVIIRSImage(**visParms),751,1)    #slightly different resolution of 751m!!!!!!!!
 visLyr=activeDisplay().createLayer('Image Display',visImg)

There are other possibilites, but I found this to be leanest one. It does not impair noticably the image quality, though read-outs might differ. Sandwiches look fine!

Regarding the print commands, while not optimal they do the job.
User avatar
joleenf
Posts: 1123
Joined: Mon Jan 19, 2009 7:16 pm

Re: retrieving the content of a display layer

Post by joleenf »

Hi HP,

I hope understand the problem. If data is already in the Field Selector and the user does not repeat a scripting load of the same data, you could selectData().

These will open a field selector and allow access to the data within the jython shell.
On Mac OSX, the data returned is a FieldImpl for NPP but FlatField is need for input to the sandwich product.
Therefore, index the object returned from the selectData call. I use the following procedure:

ir=selectData('ir')
vis=selectData('vis')
rgbImg=('Sandwich', ir[0],vis[0],180,250, supress=True)

In case the calling sequence is different than what you have, the code I currently use is:

Code: Select all

def sandwich(enhancementTableIR, imgIR, imgVIS, minIR=180, maxIR=280,supress=False):

   """
     Sandwich product based on a method developed by Martin Setvak. McIDAS-V code written by Mike Hiley
     Input:
        enhancementTableIR: Name of chosen ehancement table for IR image
        imgIR:  The IR image being displayed
        imgVIS: The VIS image being displayed
     Output:
        rgbImg:  an RGB sandwich
   """
   # this is where the "blend" stuff starts...

   # get the 'rainbow' color table, i.e. Sanwich (low value is transparent otherwise 40%)
   ct = _mcv.getColorTableManager().getColorTable(enhancementTableIR)
   table = ct.getColorTable()
   # get the rgb values for each index of the rainbow table
   # flip the color table here so that cold temperatures are red
   rTable = table[0][::-1]   # should use ColorTable.IDX_RED etc.
   gTable = table[1][::-1]
   bTable = table[2][::-1]
   aTable = table[3][::-1] # alpha layer... all 1's for rainbow table
   nCols = len(rTable) - 1  # TODO: why minus 1?

   # scale the IR image from 0 to 1
   floatsIR = imgIR.getFloats(False)[0]
   scaledIR = (imgIR-minIR) / (maxIR-minIR)
   scaledFloats = scaledIR.getFloats(False)[0]
           
   # set up the r, g, b arrays to put the image in to
   rIR = imgIR.clone()
   gIR = imgIR.clone()
   bIR = imgIR.clone()
   rFloats = rIR.getFloats(False)[0]
   gFloats = gIR.getFloats(False)[0]
   bFloats = bIR.getFloats(False)[0]

   # make rainbow enhanced IR image in rgb-space
   for i, pixel in enumerate(scaledFloats):
       # set anything colder than threshold to r,g,b from color table,
       # otherwise just set to 1 (so that result after multiply is just the vis image)
       if (floatsIR[i] < maxIR):

           # if anything falls below the minIR, set it to the minIR (scaledFloats=0)
           if (floatsIR[i] < minIR):
              pixel = 0

           # need to convert float ranging from 0.0 to 1.0 into integer index
           # ranging from 0 to nCols
           # testing

           ind = int(pixel*nCols)
           
           try:
              rFloats[i] = rTable[ind]
              gFloats[i] = gTable[ind]
              bFloats[i] = bTable[ind]   
           except IndexError:
              errorMsg= 'Index Error:' + ' Pixel=' + str(pixel) +' nCols='+str(floatsIR[i]) +' ind=' + str(ind)
              raise(errorMsg)       
       else:
           rFloats[i] = 1
           gFloats[i] = 1
           bFloats[i] = 1

   # now scale rgb values by visible image to make the "sandwich" product
   imgVIS=noUnit(imgVIS)
   rIR=noUnit(rIR)
   gIR=noUnit(gIR)
   bIR=noUnit(bIR)
   
   rOutput = imgVIS*rIR     #+alpha*rIR
   gOutput = imgVIS*gIR     #+alpha*gIR
   bOutput = imgVIS*bIR     #+alpha*bIR

   # display the sandwich layer
   
   rgbImg = mycombineRGB(rOutput, gOutput, bOutput)
   if not (supress):
      print "Sandwich Code finsihed!/n Use RGB Composite to display the Layer"

   return rgbImg


There is a second, slightly more convoluted way to get the data directly from the displayed layer:

Code: Select all

p=activeDisplay()

layers=p.getLayers()

irLayer=layers[1]
visLayer=layers[2]

visDataChoice=visLayer.getDataChoice()
irDataChoice=irLayer.getDataChoice()

visDataSource=visLayer.getDataSource()
irDataSource=irLayer.getDataSource()

visData=visDataSource.getData(visDataChoice,None,None,None)
irData=visDataSource.getData(irDataChoice,None,None,None)

print whatType(visData)

rgbImg=sandwich('Sandwich',irData[0],visData[0],180,250,supress=False)

p.createLayer('RGB Composite', rgbImg)

layRGB.updateGamma(0.5)
layRGB.updateRedRange(0., 75.)
layRGB.updateGrnRange(0., 75.)
layRGB.updateBluRange(0., 75.)




I hope this helps.

Also, if you are using NPP data, you might want to contact Martin.
He applies a solar zenith angle correction to his sandwich images which helps tremendously for appearance
and adjusts for time of day issues.
Since the solar zenith angle field is available in NPP data, it might be useful to find out how he applies that correction.

Thanks,
Joleen
User avatar
hproe
Posts: 504
Joined: Sat Nov 27, 2010 3:46 pm

Re: retrieving the content of a display layer

Post by hproe »

Hi Joleen -

Many thanks for the hint and for re-posting the sandwich code. Actually, as you may see above, I have a solution with full scripting. For the time being, it has one drawback. I allows for no area sub-setting and produces speckled images when not applying the littel trick of varying slightly the resolution (see above). So, I might also try your method with selectData().

I will certainly contact Martin about the solar angle and also why is alpha disabled in the code.

HP
User avatar
bobc
Posts: 990
Joined: Mon Nov 15, 2010 5:57 pm

Re: retrieving the content of a display layer

Post by bobc »

Hi HP -

I'm replicating the speckle pattern in the second layer displayed with swathToGrid. I wrote this up as Inquiry 2195.

Thanks for reporting this bug -
Bob
Post Reply