To start davinci, simply run it from the shell command prompt:
% davinci dv>
When started in this manner, davinci provides a command prompt, indicating it is waiting for input.
Constants and Variables
Davinci is similar to many programming languages in that it allows the user to store and manipulate values using symbolic variables and constant values. The following examples show some simple math using numeric constants:
dv> 3+4 7 dv> 3+4*2 11
All of the constants above are integers, but they could also be real numbers:
dv> 3+4.2 7.20000 dv> 3.1*4.2 13.0200
The results of mixed mode math are always cast up to the largest type. This means math with integer and real values always produces real (float) values.
Named variables can be used to store and reuse values. Variable names can be any number of letters, digits or underscores, but must start with a letter. The following example shows both integer and real variables, and computes the area and circumference of a circle:
dv> pi=3.14159 3.14159 dv> R=138 138 dv> area = pi*(R*R) 59828.4 dv> circumference = 2*pi*R 867.079
In addition to simple algebraic math, numerous transcendental functions are available. The following example computes the cube root of pi:
dv> pi=acos(-1) 3.14159 dv> exp(ln(pi)/3) 1.46459
The entire list of math functions is given in Category:Math.
In addition to the double and int64 variable types shown so far, davinci supports uint8/16/32/64, int8/16/32 and float and string types as well.
The following table shows all the types, their limits, and their memory usage:
|uint8||uint8(13)||0, 255||1 byte|
|uint16||uint16(13)||0, 65535||2 bytes|
|uint32||uint32(13)||0, 4294967295||4 bytes|
|uint64||uint64(13)||0, 18446744073709551615||8 bytes|
|int8||int8(13)||-128, 127||1 byte|
|int16||int16(13)||-32768, 32767||2 bytes|
|int32||int32(13)||-2147483648, 2147483647||4 bytes|
|int64||13||-9223372036854775807, 9223372036854775807||8 bytes|
|float||float(13.3)||1.1e-38, 3.4e38||4 bytes|
|double||1.3e-104||2.2e-308, 1.8e308||8 bytes|
The integer types other than int64 can only be input on the command line using the type conversion functions as shown in the table above. Similarly, all real numbers input on the command line are treated as 8 byte doubles unless you use the float conversion function. String variables can hold any amount of text.
Every numeric value in davinci is actually a 3 dimensional array of values. The constants that have been shown previously are 3-D arrays, with every axis having a dimension of 1. The following table describes common data objects, and shows the size of each axis:
In order to perform math on operands of differing dimension, every axis between the two objects must either match, or be of dimension 1. This means a spectra with the dimensions 1,1,5 could be added to a cube with the dimensions 3,4,5, but not to a cube with the dimensions 5,4,3.
Math between objects of differing dimension always produces a result the size of the largest operand. For example, the addition of a spectra with the dimensions 1,1,5 and a cube with the dimensions 3,4,5 would produce a cube with the dimensions 3,4,5.
The math functions also work on multi-dimensional data sets. The following example adds 1 and takes the square root of every element in the 3x3x1 array 'testdata':
dv> testdata 0.00000 3.00000 8.00000 15.0000 24.0000 35.0000 48.0000 63.0000 80.0000 dv> sqrt(testdata + 1.0) 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000
Individual elements of an array can be accessed using the range operator. Ranges are specified as a from and to value, separated by a colon. The range operator takes a range for each axis, separated by commas, and applies them to the specified array, to produce a subset. A range value of 0 for either the from or to value indicates the maximum range of the data in that axis. The following example extracts the a line along the Y axis from the 3x3x1 array shown above:
dv> testdata 0.00000 3.00000 8.00000 15.0000 24.0000 35.0000 48.0000 63.0000 80.0000 dv> testdata[2:2, 0:0, 0:0] 3.00000 24.0000 63.0000
When the from and to values for a specific axis are the same, the second value (and the colon) can be omitted. The following is identical to the example given above:
dv> testdata[2,0,0] 3.00000 24.0000 63.0000
Additionally, when the entire range of an axis is desired, the range values can be omitted completely. The following example is identical to the two given above:
dv> testdata[2,,] 3.00000 24.0000 63.0000
Finally, a single value can be extracted by specifying the location of the desired value in all dimensions.
dv> testdata[3,2,1] 35.0000
Reading and Writing Files
Data arrays are loaded into davinci, using the read() function. The read() function recognizes and can automatically read several file formats including:
- VICAR grayscale
- USGS Grid (GRD)
- PDS/ISIS Qube
- PBM, PGM and PPM
The following example shows the reading of a Vicar data cube and a SpecPR spectra:
dv> cube=read("VIMSdata.qbe") dv> corr=read("spd0141", record=15)
The keyword argument 'record', is required when reading SpecPR record. If it is specified when reading other file types, it is used as a band subset, to allow the rapid extraction of specific bands from data cubes.
Data can be written to file using the write() function. The write() function requires the following keyword argument pairs, which can be given in any order:
object=VAR - Specifies the data object to write. filename="path" - specifies the name of the file to create type=TYPE - Type of file to write. TYPE is one of: VICAR, SPECPR, GRD, PGM or PPM. The following simple example reads a vicar data cube, and writes it to disk: dv> data = read("VIMSdata.qbe") dv> write(object=data, filename="VIMSdata.copy.qbe", type=vicar)
If the specified filename exists, write() will not overwrite it unless the additional keyword force is used, as follows:
dv> write(object=data, filename="VIMSdata.copy.qbe", type=vicar, force=1)
In the following examples, the output from davinci has been omitted to make the input text easier to read.
This example reads a data cube, multiplies every element by a constant value, and writes the data cube back to the same file:
dv> cube="VIMSdata.qbe" dv> constant=3.67 dv> data = read(cube) dv> data = data * constant dv> write(object=data, filename=cube, type=vicar)
The following example reads a data cube, and a correction spectra (record 13 of a SpecPR file), multiplies the two together, and writes the results as a vicar data cube:
dv> cube="VIMSdata.qbe" dv> file="spd0141" dv> record=13 dv> data = read(cube) dv> spectra = read(file, record) dv> data = data * spectra dv> write(object = data, filename="VIMSdata.corrected.qbe", type=vicar)
The following example reads in a data cube, averages three bands, and writes the resulting image to a vicar file. The first image is promoted to integer using the int() conversion function, to insure that all math is performed using 4-byte integers. Otherwise, if the data cube contained byte or short data values, an overflow condition could easily occur when the three bands are added together.
The format function is used in this example twice, showing both its usage forms. The first usage simply reports the format of the data cube. The second usage is used to convert the output data from integer, to the same format as the input data, using the format string returned by the first usage.
dv> cube="VIMSdata.qbe" dv> a=2 dv> b=7 dv> c=9 dv> input_data = read(cube) dv> input_type = format(input_data) dv> image = int(input_data[,,a]) dv> image = image + input_data[,,b] dv> image = image + input_data[,,c] dv> image = image / 3 dv> image = format(image,type=input_type) dv> write(object=image, filename="v279", type=vicar)
The following example averages three data cubes, takes the difference of each cube from the average, and writes the resulting cubes to disk. This example also promotes the data type to int (by adding it to an integer zero), to insure no data is lost due to overflow, but leaves the data in 4-byte integer format, since taking the difference might produce negative values.
This example also minimizes the amount of memory needed, by loading and discarding the data cubes so that at most, only 2 cubes are in memory at any one time:
dv> cube1 = "VIMSdata.11314" dv> cube2 = "VIMSdata.21116" dv> cube3 = "VIMSdata.76314 dv> avg = 0 dv> avg = avg + read(cube1) dv> avg = avg + read(cube2) dv> avg = avg + read(cube3) dv> avg = avg/3 dv> write(avg - read(cube1), filename="avg.11314", type=vicar) dv> write(avg - read(cube2), filename="avg.21116", type=vicar) dv> write(avg - read(cube3), filename="avg.76314", type=vicar)