Understanding VisAD

Hello VisADevelopers,

I have some thoughts on how to better understand VisAD, and was interested
to hear other opinions.

Looking through the VisAD examples I find the examples easier to understand 
if I adopt a consistent convention for the variable names.

The aim here is to have variable names which suggest what the
underlying structure is, and which I can understand just
by looking at them. This relieves me of the burden of looking
back through the code continuously to see what a given variable

Combined with using Hungarian notatation (eg preceeding FunctionType 
variable names with ft), and listing all the variables in say 30 lines or so,
I can understand the flow of the program (after some study
and cross reference to the program of course).

Three attachments follow:
* a summary of the "self explanatory" data structures and variables

* comments on two of the highlights of the program, as I see it

* and the complete source code using the above convention plus Hungarian

Hope this helps,


James Kelly
Supervisor of Regional Development            Bureau of Meteorology
PO Box 1289K                                  Melbourne 3001, Australia
Phone: 61-3-9669-4724 Fax: 61-3-9669-4128     Email: J.Kelly@xxxxxxxxxx
Using the Hungarian Notation Conventions:

rt       RealType
rta      RealType[] 
rtt      RealTupleType
ft       FunctionType
ff       FlatField
sl1ds    Set: Linear1DSet
sg1dds   Set: Gridded1DDoubleSet
fi       FieldImpl
fia      FieldImpl[]
t        Tuple
dri      DataReferenceImpl

Test03 can be represented by the following VisAD Data Structures and Variables:

Part 1 : define the meta data (math types)

rt       rtVis    rtIr 
rta      rtaLatLon rtaVisIr rtaIrVis rtaTime
rtt      rttLatLon rttVisIr rttIrVis rttTime        
ft       ftLatLon2VisIr                           ((lat,lon)->(Vis,Ir))
         ftLatLon2IrVis                           ((lat,lon)->(Ir,Vis))
ft       ftTime2ftLatLon2VisIr              time->((lat,lon)->(Vis,Ir))
         ftTime2ftLatLon2IrVis              time->((lat,lon)->(Ir,Vis))

Part 2 : create the actual data

ff       ffLatLon2VisIr                     ff.makeField(ftLatLon2VisIr)
         ffLatLon2IrVis                     ff.makeField(ftLatLon2IrVis)
fi       fiTime2ftLatLon2VisIr              loop of 
         fiTime2ftLatLon2IrVis              loop of 
fia      fiaImages                          array of 2 fi
t        tImages                            tuple based on fia
dri      driImages                          display reference impl based on t

[then add reference dri and scalar maps to the display]

Other VisAD variables used in the program are:
ra       raDeltaVisIr                        increments to add to each time step
sl1ds    sl1dsTime                          set of 4 times for 
sg1dds   sg1ddsTime                         set of 6 times for 

   <title>UnderstandingVisAD: Features of Test03.java</title>


So what is so good about Test03.java, and what benefit is VisAD here?

Other than the visualisation aspect, there are 2 really neat features of
the Test03 program:

1) The same data structure raDeltaVisIr is used to increment both:
   * a data structure with the same elements in the same order (ffLatLon2VisIr)
   * a data structure with the same elements in a different order 

   VisAD analyses the meta data (math types) to see how to add the data 
   to the similar and dissimilar structures

2) Two datasets of different time resolutions are displayed and animated.
   One data set is at times t, t+600, t+1200, t+1800, t+2400, t+3000
   The other is at times    t, t+1000, t+2000, t+3000

   Intelligent decisions are automatically made about what to display at a given
   timestep. The timesteps displayed on screen are that of the highest 
   time series.

   This has obvious implications for Met data where time resolution is 
   different between data sets



VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 1999 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA

// Test03 modified for Hungarian Notation to aid understanding
// by James Kelly Nov 1999
import java.awt.Component;

import java.rmi.RemoteException;

import visad.*;

import visad.java3d.DisplayImplJ3D;
import visad.util.AnimationWidget;

public class Test03
  extends UISkeleton
  public Test03() { }

  public Test03(String[] args)
    throws RemoteException, VisADException

  DisplayImpl[] setupServerDisplays()
    throws RemoteException, VisADException
    DisplayImpl[] diDisplay = new DisplayImpl[1];
    diDisplay[0] = new DisplayImplJ3D("display", DisplayImplJ3D.APPLETFRAME);
    return diDisplay;

  void setupServerData(LocalDisplay[] diDisplay)
    throws RemoteException, VisADException
                // PART 1 : define the meta data (math types)
                // define all RealTypes (rt) and RealType Arrays (rta)
    RealType rtVis = new RealType("rtVis", null, null);
    RealType rtIr = new RealType("rtIr", null, null);

    RealType[] rtaTime = {RealType.Time};
    RealType[] rtaLatLon = {RealType.Latitude, RealType.Longitude};
    RealType[] rtaVisIr = {rtVis, rtIr};
    RealType[] rtaIrVis = {rtIr, rtVis};

                // define all RealTypeTypes (rtt) from ReadType Arrays (rta)
    RealTupleType rttLatLon = new RealTupleType(rtaLatLon);
    RealTupleType rttVisIr = new RealTupleType(rtaVisIr);
    RealTupleType rttIrVis = new RealTupleType(rtaIrVis);
    RealTupleType rttTime = new RealTupleType(rtaTime);

                // define all FunctionTypes (ft) which are mappings from one 
rtt to another rtt
    FunctionType ftLatLon2VisIr = new FunctionType(rttLatLon, rttVisIr);
    FunctionType ftLatLon2IrVis = new FunctionType(rttLatLon, rttIrVis);

                // define all FunctionTypes (ft) which are mappings from a rtt 
to a ft
    FunctionType ftTime2ftLatLon2VisIr = new FunctionType(rttTime, 
    FunctionType ftTime2ftLatLon2IrVis = new FunctionType(rttTime, 

                // PART 2 : create the actual data, based on the meta data 
(math types)
                // now create some data which samples the above functions
                // This data is known as a Field, and in this case a FlatField
                // iSize = how many samples to take along each dimension of the 
functions domain
                //         ie 64 samples of Latitude, and 64 samples of Long = 
4096 samples
    int iSize = 64;
    FlatField ffLatLon2VisIr = FlatField.makeField(ftLatLon2VisIr, iSize, 
    FlatField ffLatLon2IrVis = FlatField.makeField(ftLatLon2IrVis, iSize, 

                // The FlatField will contain a daaSamples array which is 
                // where 2 = number of range components (1 Vis, 1 Ir)
                // and 4096 = 64 x 64 number of samples 
                // daaSamples is not used in this program, but is for 
illustrative purposes
                double[][] daaSamples = ffLatLon2VisIr.getValues();

    int iNtimes1 = 4;
    int iNtimes2 = 6;

    // different time resolution test
    // 2 May 99, 15:51:00
    double dStart = new DateTime(1999, 122, 57060).getValue();
    Set sl1dsTime =                  // 4 times: t+0,+1000,+2000,+3000
      new Linear1DSet(rttTime, dStart, dStart + 3000.0, iNtimes1);  
    double[][] daaTime =             // 6 times: 
      {{dStart, dStart + 600.0, dStart + 1200.0,
        dStart + 1800.0, dStart + 2400.0, dStart + 3000.0}};
    Set sg1ddsTime = new Gridded1DDoubleSet(rttTime, daaTime, iNtimes2);

                // now define some datasets which vary with time (with null 
data values)
                // first one with 4 time steps
    FieldImpl fiTime2ftLatLon2VisIr = new FieldImpl(ftTime2ftLatLon2VisIr, 
                // second one with 6 time steps
    FieldImpl fiTime2ftLatLon2IrVis = new FieldImpl(ftTime2ftLatLon2IrVis, 
                // copies of flatfields used to set up the FieldImpls
    FlatField ffMyVisIr = ffLatLon2VisIr;
    FlatField ffMyIrVis = ffLatLon2IrVis;
                // real array of rtVis and rtIr increments for each time step
    Real[] raDeltaVisIr = {new Real(rtVis, (float) iSize / 4.0f),
                      new Real(rtIr, (float) iSize / 8.0f)};
                // real tuple of rtVis and rtIr increments
    RealTuple rtupleDeltaVisIr = new RealTuple(raDeltaVisIr);
                // set data values for datasets (FieldImpls)
                // by incrementally adding the rtuple to a flatfield and 
                // the incremented ff to one of the timesteps of the fi
    for (int i=0; i<iNtimes1; i++) {
      fiTime2ftLatLon2VisIr.setSample(i, ffMyVisIr);
      ffMyVisIr = (FlatField) ffMyVisIr.add(rtupleDeltaVisIr);
    for (int i=0; i<iNtimes2; i++) {
      fiTime2ftLatLon2IrVis.setSample(i, ffMyIrVis);
      ffMyIrVis = (FlatField) ffMyIrVis.add(rtupleDeltaVisIr);

                // the above data sets are now like a 3d array of
                // time         (1 timestep per sample of fi)
                // channel      (range component of the ff, where say 0 = Ir, 1 
= Vis)
                // LatLon       (domain component of the ff, which has a size 
of 64 x 64 = 4096)
                // you can work backwards to obtain the 2D array if needed
                // eg to get a specific time step 
                FlatField  ffLatLon2IrVisAtTime0 = (FlatField) 
                // extract into a 2D array
                double[][] daaLatLon2IrVisAtTime0 = 

    FieldImpl[] fiaImages = {fiTime2ftLatLon2IrVis, fiTime2ftLatLon2VisIr};
    Tuple tImages = new Tuple(fiaImages);

    diDisplay[0].addMap(new ScalarMap(RealType.Latitude, Display.YAxis));
    diDisplay[0].addMap(new ScalarMap(RealType.Longitude, Display.XAxis));
    diDisplay[0].addMap(new ScalarMap(rtVis, Display.ZAxis));
    diDisplay[0].addMap(new ScalarMap(rtIr, Display.Green));
    diDisplay[0].addMap(new ConstantMap(0.5, Display.Blue));
    diDisplay[0].addMap(new ConstantMap(0.5, Display.Red));
    ScalarMap map1animation
      new ScalarMap(RealType.Time, Display.Animation);

    DataReferenceImpl driImages
      new DataReferenceImpl("driImages");
    diDisplay[0].addReference(driImages, null);

  String getFrameTitle() { return "VisAD animation controls"; }

  Component getSpecialComponent(LocalDisplay[] diDisplay)
    throws RemoteException, VisADException
    ScalarMap smMap1animation = (ScalarMap 
    return new AnimationWidget(smMap1animation, 3000);

  public String toString()
    return ": Animation different time resolutions and AnimationWidget";

  public static void main(String[] args)
    throws RemoteException, VisADException
    new Test03(args);