While there are many extensions to this collection of classes and interfaces, we shall only introduce the fundamental Data object types and illustrate the parallels with quantities you may already be familiar with. Each will have a source code example to allow you to experiment on your own.
If you are new to Java, but come from a Fortran background, then this might be more familiar:double a,b,c; a = 10.; b = 255.; c = a + b; System.out.println("sum = "+c);
Well, if you want to use the VisAD Data model, here's what you'd say (the complete program is provided):REAL A,B,C A = 10 B = 255 C = A + B WRITE(*,*)'sum = ',C
When you run this example, you get:from visad import Real a = Real(10) b = Real(255) c = a + b print "sum=",c
By doing this, of course, you are not going to be convinced that there is any advantage to using the VisAD Data model. So, let's explore another form of constructor for visad.Real.sum = 265.0
allows us to provide an error estimate for the value. This estimate can then be propagated through mathematical operations to provide an error estimate.Real(value, error)
When you run this example, you still get:from visad import Real a = Real(10.,1.) b = Real(255.,10.) c = a + b print "sum=",c
The VisAD default for most math operations, however, is to not propagate errors, so to make use of this, we must explicitly indicate how we want error estimates to propagate. This is done by using an alternate signature of the add method (and all other math operators):sum = 265.0
When you run this example, you get:from visad import Real, Data a = Real(10,1) b = Real(255,10) c = a.add(b, Data.NEAREST_NEIGHBOR, Data.INDEPENDENT) print "sum =",c print "error of sum is=",c.getError().getErrorValue()
The constants supplied to the add method are the type of interpolation and the type of error propagation. In this simple case, the type of interpolation is not really relevant, but as you will see later, VisAD Data types may contain finite approximations to continuous functions and when these are combined mathematically, may need to be resampled in order to match domains.sum = 265.0 error of sum is=10.04987562112089
In the simplest form for dealing with Units, the constructor for a MathType which defines Real values is:
which allows you to assign a unique name to this MathType, as well as a Unit.getRealType(String name, Unit u)
To make use of this, we modify the program to read as follows:
When you run this example, you get:from visad import Real, SI from visad.python.JPythonMethods import * k = getRealType("kelvin", SI.kelvin) t2 = Real(k, 273) t1 = Real(k, 255) sum = t1 + t2 print "sum =",sum,sum.getUnit()
In this example, we were able to use an SI Unit (ampere, candela, kelvin, kilogram, meter, second, mole, radian, steradian). Note that we constructed two variables with the same MathType, that is the same name and Unit. The only thing that is different is the numeric value.sum = 528.0 K
If you are using some other unit, VisAD provides mechanisms for making up Units for those. As an example, you can use the makeUnit() method from the visad.python.JPythonMethods package to create a VisAD Unit from a String name.
When you run this example, you get:from visad import Real from visad.python.JPythonMethods import * degC = makeUnit("degC"); tc = getRealType("tempsC",degC); t2 = Real(tc,10.); k = getRealType("kelvin",SI.kelvin); t1 = Real(k,255.); sum = t1 + t2 print "sum =",sum,sum.getUnit()
Observe that although we defined the value of variable tc to be in degree Celsius, when we added the two variables together, the value of y was automatically converted to degrees Kelvin. As long as the units are transformable, VisAD handles this. If you attempt to combine quantities with incompatible units, an Exception is thrown.sum = 538.15 K
If you'd like to get the value listing in Celsius, then change the println to read:
When doing arithmetic on Real objects, you may need at some point to use a constant value for something. As with all VisAD Data objects, in order to perform these operations, the Units must all match. When you use the simplest form of constructor for Real to define a numeric value, VisAD sets its Unit to a default value which can then be used to do arithmetic with any other Real. To illustrate, let's modify the previous example to compute the average of the two temperature values:print "sum = ",sum.getValue(degC)
When you run this program, you get:from visad import Real, Unit, RealType from visad.python.JPythonMethods import * degC = makeUnit("degC") tc = getRealType("tempsC", degC) t2 = Real(tc, 10) rtk = getRealType("kelvin", SI.kelvin) t1 = Real(rtk, 255) average = (t1 + t2) / 2 print "average =",average,average.getUnit()
average = 269.075 K
from visad import Real, Unit, RealType, RealTupleType from visad.python.JPythonMethods import * degC = makeUnit("degC") temperature = getRealType("temperature", degC) kts = makeUnit("kts") speed = getRealType("speed", kts) sec = makeUnit("seconds") time = getRealType("time", SI.second) mydata = RealTupleType(time, speed, temperature)
When you run all this now, you get:obsTemp = 32 obsSpeed = 15 obsTime = 4096 values = (obsTime, obsSpeed, obsTemp) obs = RealTuple(mydata, values) print "obs =",obs
obs = (4096.0, 15.0, 32.0)
When you run this addition, you get:obsTemp2 = -10 obsSpeed2 = 7 obsTime2 = 1234 values2 = (obsTime2, obsSpeed2, obsTemp2) obs2 = RealTuple(mydata, values2) print "obs2 =",obs2
Our main purpose is to average all the values together. Again we need to define a Real for our constant, and then do just what we did previously:obs = (4096.0, 15.0, 32.0) obs2 = (1234.0, 7.0, -10.0)
Finally when you run the complete example, you get:avg = (obs + obs2) / 2 print "avg =",avg
Note that the temperature was converted to the base unit of kelvin.obs = (4096.0, 15.0, 32.0) obs2 = (1234.0, 7.0, -10.0) avg = (2665.0, 11.0, 284.15)
Most important -- as you can see the arithmetic capability of VisAD applies to all types of Data objects in the same manner.
Although we have used a VisAD RealTuple, it is of course just a specific kind of a Tuple that only contains Reals. Tuples can be used to collect together all types of VisAD Data objects...including Sets and Functions.
VisAD comes with lots of implementations of the Set interface, in order to represent lots of common topologies. In this introduction, however, we'll deal only with one form -- the Linear1DSet.
The Set object also defines the CoordinateSystem of the Field's domain and the Units of the domain's RealType components. The following section will deal more explicitly with Fields.
will produce this output when run:from visad import Linear1DSet s = Linear1DSet(-33, 33, 5) print "set s=",s
The Linear1DSet defined in this case has associated MathType of "Generic". There is an alternate form of the constructor for a Linear1DSet that allows you to define the MathType for this set of numbers, as well.set s = Linear1DSet: Length = 5 Range = -33.0 to 33.0
the program would produce the following output:sam = s.getSamples() for i in range( len(sam[0]) ): print "i =",i," sample =",sam[0][i]
Note that the first dimension of variable s is 1; the standard notation in VisAD for samples isset s = Linear1DSet: Length = 5 Range = -33.0 to 33.0 i = 0 sample = -33.0 i = 1 sample = -16.5 i = 2 sample = 0.0 i = 3 sample = 16.5 i = 4 sample = 33.0
[number of components] [number of samples]
Other methods worth checking out include indexToDouble() which returns an array of doubles given an array of indices. There is also an inverse method, doubleToIndex(). Refer to the VisAD Javadoc for more details.
In order to use Function objects, it is necessary to define
the sampling using a Set of some kind for the domain and
to supply appropriate samples for the corresponding range
values. Let's make a small example. In this case, I want to define a
Function that can convert temperatures from degrees Fahrenheit
to Kelvin.
Here, we have defined the RealType for our domain to represent degrees F, and for the range for degrees K. The FunctionType defines the mapping from the domain to the range. (Note that we have not included Units in this defining these two RealTypes, because we are going to do the conversions ourselves; otherwise, the visad.units package would have be able to do the conversion for us.)from visad import FunctionType, Linear1DSet, FlatField, Real from visad.python.JPythonMethods import * domain = getRealType("temp_F") range = getRealType("temp_Kelvin") convertTemp = FunctionType(domain, range)
We use a 1D Set because we are only defining a scalar at each point in the range (rather than a vector).domain_set = Linear1DSet(-40, 212, 2)
Which constructs a FlatField which is defined by a FunctionType defined over the values of the domain_set.convertData = FlatField(convertTemp, domain_set)
First, create an array that contains the numeric values of the range samples at the two points in the domain_set:
Then put the range samples into the FlatField using:values = ( (233.15, 373.15), ) # deg K values for -40F and 212F
convertData.setSamples(values)
When you run this whole example, you get:e = Real(14.0) v = convertData.evaluate(e) print "value for 14.0F =",v vf = (v.getValue() - 273.15) * 9 / 5. + 32 print " or (doing some math) = ",vf
Please note that utility functions in the JPythonMethods class would allow you to code this example as simply:value for 14.0F = 233.14999389648438 or (doing the math) = 13.999989013671915
domain_set = makeDomain("temp_F" -40, 212, 2) convertData = field(domain_set, "temp_Kelvin", (233.15, 373.15)) v = evaluate(convertData, 14.0) print "value for 14F =",v vf = (v.getValue() - 273.15) * 9 / 5. + 32 print " or (doing some math) = ",vf
If we change the evalute() call to read:
then results in this output when you run now:v = convertData.evaluate(e, Data.NEAREST_NEIGHBOR, Data.NO_ERRORS);
value for 14.0F = 263.1499938964844 or (doing the math) = -40.00001098632808
from visad.python.JPythonMethods import * from visad import Real domain = makeDomain(-40, 212, 2) values = (233.15, 373.15) # deg K values for -40F and 212F convertData = field(domain, "degF2K", values) e = Real(14) v = convertData.evaluate(e) print "value for 14.0F =",v vf = (v.getValue() - 273.15) * 9 / 5. + 32 print " or (doing some math) = ",vf