Several small examples

May, 2001

Introduction

In this section, we provide several small examples, designed to illustrate portions of using VisAD and Jython together. For quick reference, here's an index to this page:

  1. Making a display in Java
  2. Drawing lines on a basemap
  3. Extracting a single channel from a multi-banded image
  4. Plot a histogram comparing two channels of an image
  5. Make a scatter plot comparing two channels of an image
  6. Print a list of points in an image with a value > 100
  7. Plotting data from a text file
  8. Reading out the cursor coordinates on a display
  9. VisAD's Example 35 - Direct Manipulation
  10. Animating the last 3 images of realtime satellite data
  11. Saving an image to disk & restoring it
  12. Making a simple interactive VisAD display from an array of real numbers
  13. Fun with shapes!
  14. Using Irregular3DSet to make changeable shapes

Note: If you are running from the Jython command line interactive interpreter, be certain to type in these two lines before referencing any VisAD library functions:

from visad.python.JPythonMethods import *
from visad import *

Making a display in Java

Okay, so this doesn't have anything to do with VisAD directly...but it is important!
from java.awt import *
from java.awt.event import *

# method to show mouse coordinates when dragged
def showcoord(a):
  print "x=",a.getX(),"y=",a.getY()

# when button is pressed, close the window
def pressed(x):
  print "button pressed:",x
  f.dispose()

# the "program"
# define a Java frame, 200x200, and aim the mouseDragged action at showcoord()
f=Frame("myframe",size=(200,200),mouseDragged=showcoord)

# define the layout so the button looks good
f.setLayout(FlowLayout())

# add a button, and point its action to the pressed() routine
b=Button("close",actionPerformed=pressed)
f.add(b)

# show it!
f.show()


Drawing lines on a basemap

Here, we use the JPythonMethod's load() command to fetch a basemap file (you probably will have to change the path...), and the plot() function to make the display. After this, we use the subs.drawLine() to draw some colorful lines on the display.

from visad.python.JPythonMethods import *
import subs
from java.awt import Color

# get the basemap file and display it
a=load("OUTLUSAM")
plot("map",a)

# for now, there is a timing problem in getting some info from the
display...these next two lines gotta go...
import time
time.sleep(3.0)

# draw some lines into the "map" display
subs.drawLine("map", ( (-120,-100,-80,-60),(20,50,30,60) ), color=Color.orange)
subs.drawLine("map", ( (-120,-100,-80,-60),(10,40,20,50) ), color=Color.green)
subs.drawLine("map", ( (-120,-100,-80,-60),(30,60,40,80) ), color=Color.magenta)
subs.drawLine("map", ( (-120,-110,-100,-110,-120),(20,30,20,10,20) ), color=Color.yellow)


Extracting a single channel from a multi-banded image

from visad.python.JPythonMethods import *
# load two McIDAS area files
area7 = load("AREA0007")
area8 = load("AREA0008")  // this is the a multi-banded image

# extract one band from area8
area8a = extract(area8,0)

# subtract one area from the other, georeferenced
difference = area8a - area7

# plot area difference
clearplot()
plot(difference)

Plot a histogram comparing two channels of an image

from visad.python.JPythonMethods import *
# load a McIDAS area file
area = load("AREA0008")

# compute a 2-D histogram of the first two bands of the area
histogram = hist(area, [0, 1])

# plot the histogram
clearplot()
plot(histogram)

Make a quick scatter plot comparing two channels of an image

from visad.python.JPythonMethods import *
import graph

# load a McIDAS area file
area = load("AREA0008")

graph.scatter( extract(a,0), extract(a,2))

Print a list of all points in an image with values > 100

from visad.python.JPythonMethods import *
# read in a single-band image
image=load("AREA0007")

# get the sampling domain
dom=getDomain(image)

n=0
# only print the first 10 points...
for c in dom:
 
  # sample the image at point [c] in it's domain, and then
  # get the data value of the first [0-th] range component
  # to use for the comparison.  (note...this can be pretty slow...)

  z=(image[c])[0].getValue()
  if z > 100: 
    n=n+1
    print "value at",c,"is equal",z
    if n>10: break

Plot data from a text file

Suppose you have some values at latitude/longitude points in a text file...something like:
(Longitude, Latitude) -> (City(Text))
Latitude, Longitude, City(Text)
-12.3, 130.8, "Darwin"
-16.9, 146.5, "Cairns"
-23.6, 133.9, "Alice Springs"
-27.3, 153.1, "Brisbane"
-31.9, 115.9, "Perth"
-33.9, 151.2, "Sydney"
-37.6, 144.9, "Melbourne"
-35.3, 149.2, "Canberra"
-34.6, 138.5, "Adelaide"
If you just want to plot the values in the VisAD "box", here's a simple Jython way:
from visad.python.JPythonMethods import *
import subs

a=load("../data/text/auststn.txt")
dom = domainType(a)
rng = rangeType(a)

maps = subs.makeMaps(dom[0],"x", dom[1], "y", rng[0], "text")

disp = subs.makeDisplay(maps)
subs.addData("cities",a,disp)
subs.maximizeBox(disp, .70)

subs.showDisplay(disp)

Reading out the cursor coordinates in a display

If you want to know the cursor coordinates, either in "screen" coordinates or in "scalarmap" coordinates, this will get you started. Note the inner class that implements the visad.DisplayListener interface; this allows it to register as a DisplayListener, which means whenever something in the Display changes, the displayChanged method will be called.
from visad.python.JPythonMethods import *
from visad import DisplayListener, DisplayEvent
from graph import *
from subs import *

class coords(DisplayListener):
  def __init__(self, display):
    self.x, self.y, self.z, self.display = subs.getDisplayMaps(display)
    print "Found scalar mappings for x and y=",self.x, self.y
    self.dr = self.display.getDisplayRenderer()
    self.display.addDisplayListener(self)

  def displayChanged(self, event):
    if event.getId() == DisplayEvent.MOUSE_PRESSED_RIGHT:
      print "mouse_x=",event.getX()
      print "mouse_y=",event.getY()

    if event.getId() == DisplayEvent.MOUSE_PRESSED_CENTER:
      print "  x =",self.dr.getDirectAxisValue(self.x)
      print "  y =",self.dr.getDirectAxisValue(self.y)

a=load("../data/mcidas/AREA0001")
d=image(a)
coords(d)


VisAD's Example 35 - Direct Manipulation

This is translated from VisAD's example #35, which shows direct manipulation. It might be a bit daunting since it uses VisAD classes and methods directly to create some data...but is illustrative...

from visad import RealType, Real, FunctionType, FlatField, RealTuple
from visad.java3d import DisplayImplJ3D, DirectManipulationRendererJ3D
from visad.java2d import DisplayImplJ2D, DirectManipulationRendererJ2D
import subs

# make Types for our data
ir_radiance = RealType("ir_raidance")
count = RealType("count")
ir_histogram = FunctionType(ir_radiance, count)
vis_radiance = RealType("vis_radiance")

# make up the data values...
histogram = FlatField.makeField(ir_histogram, 64, 0)
direct = Real(ir_radiance, 2.0)
direct_tuple = RealTuple( (Real(count, 1.0), Real(ir_radiance,2.0), Real(vis_radiance, 1.0)) ) 

# create the scalar mappings for display 0
maps0=subs.makeMaps(vis_radiance,"z", ir_radiance,"x", 
                                     count, "y", count,"green")
# make display 0 a 3-D display
dpys0 = subs.makeDisplay3D(maps0)
subs.setPointSize(dpys0, 5.0)

# add the data to display 0 and keep the references
ref_hist = subs.addData("histo", histogram, dpys0, 
                 renderer=DirectManipulationRendererJ3D())
ref_dir = subs.addData("dir", direct, dpys0, 
                 renderer=DirectManipulationRendererJ3D())
ref_dir_tuple = subs.addData("dir_tup", direct_tuple, dpys0, 
                 renderer=DirectManipulationRendererJ3D())

# create the scalar mappings for display 1
maps1 = subs.makeMaps(ir_radiance,"x", count,"y", count,"green")

# make display 1 a 2-D display
dpys1 = subs.makeDisplay2D(maps1)
subs.setPointSize(dpys1, 5.0)

# add the data to this display, but use the references from
# the previous one so the direct manipulations interact with both
subs.addData("histo", histogram, dpys1, 
           renderer=DirectManipulationRendererJ2D(), ref=ref_hist)
subs.addData("dir", direct, dpys1, 
           renderer=DirectManipulationRendererJ2D(), ref=ref_dir)
subs.addData("dir_tup", direct_tuple, dpys1, 
           renderer=DirectManipulationRendererJ2D(), ref=ref_dir_tuple)

# function to clean up when display window is closed
def cleanup(event):
  dpys0.destroy()
  dpys1.destroy()
  frame.dispose()

# create window for display and add the dspy displays to it
from javax.swing import JPanel, JFrame
from java.awt import GridLayout
panel1 = JPanel()
panel1.add(dpys0.getComponent())
panel2 = JPanel()
panel2.add(dpys1.getComponent())

frame = JFrame("Test35", windowClosing=cleanup)
pane = frame.getContentPane()
pane.setLayout(GridLayout(1,2))
pane.add(panel1)
pane.add(panel2)
frame.setSize(600,300)
frame.setVisible(1)


Animating the last 3 weather satellite images

A very quick example of using ADDE to transfer the last 3 satellite images from a server in Colorado and then display them with graph.animation().
from visad.python.JPythonMethods import *
import graph

a=[]
for t in (-3, -2, -1):
  a.append( load ("adde://adde.unidata.ucar.edu/imagedata?group=RTIMAGES&descr=EDFLOATER-I&pos=%d&unit=BRIT&band=1&mag=1 1&version=1" % t ) )

graph.animation(a)



Saving an image to disk and restoring it later

This example reads in a sub-section of an AREA file, displays it, and then saves it to disk using VisAD's VisADForm in 'binary' mode. It then loads the data back in and displays it as proof of concept.
from visad.python.JPythonMethods import *
from visad.data.mcidas import *
a = AreaAdapter("AREA0008", 200, 200, 200, 200)
plot(a.getData())
from visad.data.visad import VisADForm
b = a.getData()
VisADForm(1).save("data.out", b, 1)
clearplot()
c = load("data.out")
plot(c)


Making a simple interactive VisAD display from an array of real numbers

This is a code snippet that illustrates how to make a VisAD-based display of an array of real numbers that your Python program generates. In this example, the preceding code (not shown...) has created an array T[20][100][76] which is filled with real numbers. The goal is to display one slice at a time, from T[k][][] under user control.

This also illustrates creating MathTypes without actually knowing you are... When we pick up the code, no VisAD-related activities have happened yet:

...
...
...
from visad.python.JPythonMethods import *
from visad import FieldImpl
from visad.util import VisADSlider
import subs

ftype = makeType(" (liq_water -> ( (size, wavelen) -> reflectance) )")
fdom = makeDomain("liq_water", .05, 1.0, 20)

gdom = makeDomain("(size, wavelen)", 3,102,100,  1,76,76)

seq = FieldImpl(ftype, fdom)

for i in xrange(0,20):
  seq.setSample(i, field(gdom, "reflectance", T[i]) )

# at this point, you could simply:  plot(seq,1) to use a SpreadSheet panel

maps = subs.makeMaps("size","x",
                     "wavelen","y",
                     "reflectance","rgb", "reflectance","z",
                     "liq_water","selectvalue")

disp = subs.makeDisplay3D(maps)
showAxesScales(disp, 1)
subs.addData('reflect',seq, disp)
slide=VisADSlider(maps[4])
subs.showDisplay(disp, 400, 400, "Reflectance", bottom=slide)


Fun with shapes

This example illustrates the use of Shapes in the subs.py module. It will draw 3 shapes on the screen and then move the around.

from visad.python.JPythonMethods import *
from subs import *
import time

# simple ScalarMappings...
maps=makeMaps(getRealType("x"),"x", getRealType("y"),"y")
maps[0].setRange(-1., 1.)
maps[1].setRange(-1., 1.)

disp = makeDisplay(maps)

# first shape is actually text
inx3 = addShape(textShape("hello", size=.2))
moveShape(inx3, (1,1))

# just a X
inx = addShape("cross")
moveShape(inx, (.5,.5))

# a solid, green-colored square
inx2=addShape("solid_square", color="green")
moveShape(inx2, (-1, -1))

showDisplay(disp)

# now "animate" them...

for i in xrange(100):
  x2 = -1. + i/50.
  x = .5 - i/50.
  x3 = 1. - i/70.

  moveShape(inx2, (x2,x2))
  moveShape(inx, (x,.5))
  moveShape(inx3, (x3,x3))
  time.sleep(.4)


Using Irregular3DSets to make changeable shapes

This example illustrates the a technique for using an Irregular3DSet to make a triangle that can be morphed into different shaped triangles. It will draw 3 shapes on the screen and then move the around.

from visad.python.JPythonMethods import *
from visad import RealType, RealTupleType, ScalarMap, Display, ConstantMap, Irregular3DSet, DelaunayCustom
from subs import *
import time

# illustrates rehaping a shape in "box" coordinates (lat/lon/alt here)
la=RealType.Latitude
lo=RealType.Longitude
al=RealType.Altitude
mys=makeRealType("trishape")

maps=makeMaps(lo,"x", la, "y", al, "z", mys, "shape")
maps[0].setRange(-110., -80.)
maps[1].setRange(20., 40.)
maps[2].setRange(0., 10000.)

# make a couple of marks on the screen just so they're there
disp=makeDisplay(maps)

drawLine(disp, [ [-100.,-90.],[30.,35.],[3000.,6000.]], color="green")
inx = addShape("solid_triangle", color="white")
moveShape(inx, (-90., 20., 3000.))

# make moving triangle semi-transparent blue
cm = makeColorMap("blue")
cm.append(ConstantMap(.3, Display.Alpha))
# define points in lat/lon/elv space
mt = RealTupleType(lo,la,al)
pts= ((-90., -95., -85.),(35., 35., 35.),(7000., 0.,0.))
df=DelaunayCustom(pts, ( (0,1,2),))
mytri = Irregular3DSet(mt, pts, None, None, None, df)
myref = addData("tri",mytri, disp, cm)

showDisplay(disp)

# now, let's animate it!!
for i in xrange(100):
  lat=20. + i/100.*(40.-20.)
  lon = -105 + i/100. * (30.)
  alt = 10. + i/100. * (8000.)
  lat0 = lat-2.
  lat1 = lat + 2.
  lon0 = lon -5.
  lon1 = lon + 5.
  mytri = Irregular3DSet(mt, ((lon, lon0, lon1),(lat, lat0, lat1),(alt, 0.,0.)),None, None, None, df)
  myref.setData(mytri)
  time.sleep(.4)


Back to the home page