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
represents.
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
(hConventions.html)
* comments on two of the highlights of the program, as I see it
(Test03Features.html)
* and the complete source code using the above convention plus Hungarian
notation
(Test03.txt)
Hope this helps,
James
--
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
<pre>
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
fi.setSample(i,ff+raDeltaVisIr)
fiTime2ftLatLon2IrVis loop of
fi.setSample(i,ff+raDeltaVisIr)
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
fiTime2LatLon2VisIr
sg1dds sg1ddsTime set of 6 times for
fiTime2LatLon2IrVis
</pre>
<head>
<title>UnderstandingVisAD: Features of Test03.java</title>
</head>
<body>
<pre>
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
(ffLatLon2IrVis)
VisAD analyses the meta data (math types) to see how to add the data
structure
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
resolution
time series.
This has obvious implications for Met data where time resolution is
frequently
different between data sets
</pre>
</body>
</html>
/*
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
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
{
super(args);
}
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,
ftLatLon2VisIr);
FunctionType ftTime2ftLatLon2IrVis = new FunctionType(rttTime,
ftLatLon2IrVis);
//
// 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,
false);
FlatField ffLatLon2IrVis = FlatField.makeField(ftLatLon2IrVis, iSize,
false);
// The FlatField will contain a daaSamples array which is
double[2][4096]
// 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:
t+0,+600,+1200,+1800,+2400,+3000
{{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,
sl1dsTime);
// second one with 6 time steps
FieldImpl fiTime2ftLatLon2IrVis = new FieldImpl(ftTime2ftLatLon2IrVis,
sg1ddsTime);
// 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
assigning
// 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)
(fiTime2ftLatLon2IrVis.getSample(0));
// extract into a 2D array
double[][] daaLatLon2IrVisAtTime0 =
ffLatLon2IrVisAtTime0.getValues();
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);
diDisplay[0].addMap(map1animation);
DataReferenceImpl driImages
new DataReferenceImpl("driImages");
driImages.setData(tImages);
diDisplay[0].addReference(driImages, null);
}
String getFrameTitle() { return "VisAD animation controls"; }
Component getSpecialComponent(LocalDisplay[] diDisplay)
throws RemoteException, VisADException
{
ScalarMap smMap1animation = (ScalarMap
)diDisplay[0].getMapVector().lastElement();
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);
}
}