Skip to content
Xylar Asay-Davis edited this page Mar 16, 2015 · 2 revisions

How to set up image datasets and parameter files before running ACCIV

What types of image datasets are appropriate for ACCIV?

The chief advantage of ACCIV over other multi-pass CIV techniques come from its ability to combine information from many pairs of images, and from its ability to track small-scale features in a flow over relatively long periods of time.

ACCIV gives the best results on datasets that contain:

  • some images separated by short period of time (over which advection has not rotated or sheared small-scale features very much) that can be used to create a "training" or "bootstrapping" velocity field
  • some images separated by longer periods of time (long enough that distortions from advection have become significant but not so long that small-scale features have been completely destroyed).

In practice, determining whether a given dataset is appropriate is sometimes a matter of trial and error, as is determining what may qualify as a "short" time separation, what qualifies as a useful "long" time separation, and what might be considered "too long", so that the tracked features have been completely lost.

Converting your images to HDF5 format

HDF5 files are like structures, and can contain different types of data: values, arrays, images, and probably more. Fortunately ACCIV's HDF5 input/output file structure is relatively simple.

HDFView is a nice standalone Java app that lets you browse HDF5 files with a graphical interface: http://www.hdfgroup.org/hdf-java-html/hdfview

There are also HDF utilities that you may or may not install when you’re installing ACCIV’s required libraries. For instance, there is a command line tool h5ls that quickly lists the contents of a HDF5 file.

The only input files needed are the image files, which contain four datasets:

> h5ls -v image001.h5
bounds                   Dataset {4/4}
	Chunks:    {4} 32 bytes
	Type:      native double
data                     Dataset {257/257, 257/257}
	Chunks:    {257, 257} 528392 bytes
	Type:      native double
mask                     Dataset {257/257, 257/257}
	Chunks:    {257, 257} 66049 bytes
	Type:      native unsigned char
time                     Dataset {1/1}
	Chunks:    {1} 8 bytes
	Type:      native double

Opening the same file in HDFView shows:

The bounds dataset gives the location of the corners of the images in physical units [xMin, xMax, yMin, yMax], which can either be units of length or longitude/latitude. The data is the actual image data in 64-bit floating point. The mask is 0 where data should be ignored, and 1 where data should be included (stored as 8-bit unsigned integers). The time gives the time of the frame. Typically the units of time would be seconds, with image000.h5 having time=0 and the following images having time=elapsed seconds since the first frame. This way, the ACCIV output is in units of length/second.

The minimumTimeSeparation and maximumTimeSeparation parameters (usually defined in defaultParameters.ascii, but sometimes given in parameters.ascii if different values are appropriate over long time separations than over shorter time separations) will be in the same units as the “time” element in the image frames.

ACCIV expects the data array to be stored in c++ indexing order (y first, then x). This means that an image that is 1200 pixels wide and 900 pixels tall is (not very intuitively) stored as:

acciv/tests/GalileoGRS1996Test> h5ls image001.h5
bounds                   Dataset {4}
data                     Dataset {900, 1200}
mask                     Dataset {900, 1200}
time                     Dataset {1}

Also, ACCIV assumes that the origin is at the lower-left corner of the image. (HDFView, on the other hand, displays images with the origin in upper-left corner.) When you convert your image data to HDF5 format, it may make sense to flip the data in the y-direction. If you choose not to do so, you simply need to keep in mind that y velocities will be positive when they point downward, rather than upward, meaning that you may have to flip the sign of vy in your plotting routines.

The folder tests/convertImages contains two simple examples of converting image datasets to the HDF5 format needed by ACCIV:

acciv/tests/convertImages> ls
csvToH5.py  tiffToH5.m

The first, csvToH5.py, is written in Python and requires the numpy and h5py modules. It shows how to convert two comma-separated text data files into HDF5 image files, assuming the unit of length is a pixel and the time separation between the images is 1 unit of time.

The second, tiffToH5.m, shows how to convert a series of three Tiff images to HDF5 format in Matlab. This example also includes an example of how we computed longitude and latitude bounds of an image and how we computed the time of each image.

Multiple passes in ACCIV=

ACCIV is an iterative technique. The output of one “pass,” or one velocity extraction, becomes the starting point for subsequent passes.

A sequence of image data for an ACCIV project can consist of either: a set of images with close time separations multiple sets of images with close time separations

Originally, ACCIV was designed to extract velocities from data taken over two Jupiter rotations. So a good way to think of the time separations is to consider data taken on Jupiter day #1 to be one set of images with close time separations, data taken on Jupiter day #2 to be another set of images with close time separations, and the full set of data make up a set with far time separations. This type of organization is used in the first set of test data, which is included in the ACCIV installation: tests/syntheticTest. syntheticTest: file organization These are the files and subdirectories within the test data directory:

compareVelocities.m       image000.h5      image033.h5
compareVelocityVectors.m  image001.h5      Makefile
day1/                     image002.h5      plotResiduals.m
day2/                     image003.h5      plotVelocities.py
days_1_2/                 image030.h5      plotVelocityData.m
defaultParameters.ascii   image031.h5      sixPassScript.csh
dos2unix_params.csh       image032.h5      sixPassScript.sh

Any ACCIV project should generally be organized this way. Details about the data files and their formats are below, but here we will talk more generally about the organization of an ACCIV project.

The imageNNN.h5 files contain the image data for the project. The frames need to all be uniform in size and the image bounds need to cover the same physical location (e.g. for images of Jupiter, each image needs to cover the same longitude/longitude). Masks can be included in case data are missing in parts of some frames. Together the image files make up the input data. The sixPassScript.* script files are examples of what you will execute to run ACCIV.

The file defaultParameters.ascii contains default parameters that ACCIV will use in all passes unless they are overridden by a the parameters.ascii file in that pass (see below).

Other files in the main directory are examples of how to plot ACCIV output in Matlab (*.m) or Python (*.py), a Makefile that can be used to remove all the results so you can start the test fresh, and a script, dos2unix_params.csh, that can be used to convert DOS text files to UNIX format. (DOS text files tend to cause problems when ACCIV tries to parse the parameters.ascii files.)

The day*/ directories will contain the output data: syntheticTest: output directories Here is a listing of what is inside all the day*/ directories:

day1/:
pass1/  pass2/

day2/:
pass1/  pass2/

days_1_2/:
pass1/  pass2/

You can see how the output data from six ACCIV passes will be organized. Two passes each in day1 and day2 will be based on the short time-separation data, and two passes in days_1_2 will be based on the full set of data including far time-separations.

Not shown are the initial contents of each passN directory, which is a single file called parameters.ascii. This file sets all the control parameters for an individual ACCIV pass.

For those familiar with multi-pass Correlation Image Velocimetry (CIV), the results of performing two ACCIV passes on images from the same "day" are similar to (though typically slightly better than) those from a two-pass CIV method. Similarly to multi-pass CIV, the information for the first pass is used to distort the windows of pixels that are correlated in the second pass, resulting in a more accurate velocity field in the second pass. The method used by ACCIV to achieve this distortion is rather different (advection of the images to a common time, rather than linear transformation of the correlation window in the later image).

Controlling ACCIV: parameters.ascii files

ACCIV is run pass by pass. For a single pass, when you call ACCIV, it looks for a parameters.ascii file in the current directory to tell it what to do. Below is a full parameters.ascii file and a full defaultParameters.ascii file that work with the current version of ACCIV, with comments given interspersed. The parameters.ascii file is fully loaded with helpful comments, so only minimal explanation is given.

A typical parameters.ascii:

# Parameters for ACCIV used construct a velocity field from a set of earlier 
# and a set of later images (which may be the same: an image will never be 
# compared with itself and each image pair will only be used once).
# 
# default parameters file, used to assign parameters that don't change between runs
defaultParameterFile = ../../defaultParameters.ascii

# the number of images in the earlier image set
earlierImageIndices = [0,1,2,3]

# the number of images in the later image set
laterImageIndices = [0,1,2,3]

The material above tells ACCIV where to find the default parameters and how the images are numbered. This example would direct ACCIV to look for image000.h5 ... image003.h5. The actual names you use for your data are flexible, but the parameters.ascii or defaultParameters.ascii file must reflect the names used.

# do we want to advect the images using a velocity field we already computed?
#   If this is the first ACCIV pass, there will be no velocity field to use yet,
#   so this flag should be set to false.  Otherwise it should be set to true.
advectImages = false

If advectImages=false, then you’re basically just performing one-pass CIV on a set of data. If it is set to true, then you’re using the full power of ACCIV.

Generally, on pass1 of short time-separation data, you’ll set advectImages=false to get a crude initial velocity field. (You don't yet have a velocity field to advect images with.) That is the only time you’ll want to set this to false.

# if we are advecting images, to which time: "early", "middle", "late"
# "early" corresponds to the mean of the times of the earlier images
# "middle" corresponds to half way between the mean times of the earlier and of the later images
# "late" corresponds to the mean of the times of the later images
advectionTimeFlag = middle

Generally, advectionTimeFlag should be middle. The exception is when you only have one velocity field from short separations, and you are at the stage where you’re doing the first pass on the full data set including far separations. If the velocity field you have is from the later set of images, then it works better to advect the later images backward to the time of the earlier images (which didn’t generate a velocity field yet). In this case you would not advect all images to the midpoint in time, thus the flag advectionTimeFlag = early.

# the velocity data (if any) to be used to advect the earlier images to a common time
inEarlierVelocityFileName = ../pass1/outGridVelocity.h5

# the velocity data (if any) to be used to advect the later images to a common time
inLaterVelocityFileName = ../pass1/outGridVelocity.h5

Here is how to set these for different cases:

Pass1 of a short-separation set: ignored, because no advection used.

Later passes of a short-separation set: set both filenames to the same value, which specifies the velocity field generated in the previous pass.

Pass1 of a far-separation set: If two velocity fields exist, one for each set of short-separation data, then set these respectively to the velocity fields in the final passes of the early and late velocity extractions based on short-separation data. But if there is a velocity field for only one set of short-separation data, set both in*VelocityFileNames to the same value.

Later passes of a far-separation set: set both filenames to the same value, which specifies the velocity field generated in the previous pass.

# the size of the box of pixels used to perform correlations: [xSize, ySize]
correlationBoxSize = [40, 40]

This is one of the most important control parameters. This parameter is also called correlation box size in Asay-Davis et al. (2009).

# the range of pixels over which to search for correlations: [xMin, xMax, yMin, yMax]
# This search range will be scaled by the time separation between image
# pairs (normalized by the max time between image pairs).  This insures that ACCIV
# searches the same approximate range of velocities for each image pair
searchRange = [-30, 30, -30, 30]

This is one of the most important control parameters. This parameter is also called search range in Asay-Davis et al. (2009).

# the stride between correlations (after finding each correlation, how many pixels
# do we shift the correlation box by to find the next correlation): [xStride, yStride]
stride = [4,4]

This is one of the most important control parameters. This parameter is also called correlation box shift in Asay-Davis et al. (2009).

A typical defaultParameters.ascii:

This file will usually reside in the root directory of an ACCIV project and will contain default values for parameters that do not typically change from one pass to the next.

# Parameters for ACCIV used construct a velocity field from a set of earlier 
# and a set of later images (which may be the same: an image will never be 
# compared with itself and each image pair will only be used once).
# 
# file containing the geometric factors needed to convert from lon/s and lat/s to vx and vy
gridGeometryFactorsFileName = ../../gridGeometryFactors.h5

# the format of the earlier image file names (printf format)
earlierImageFileTemplate = ../../image%03i.h5

# the format of the later image file names (printf format)
laterImageFileTemplate = ../../image%03i.h5

The material above tells ACCIV where to find the file containing geometric factors that are used to convert from longitude/latitude to distances in meters (or which contains all ones if the geometry is flat) and image files it needs. This example would direct ACCIV to look for image000.h5, image001.h5 ... The actual names you use for your data are flexible, but the parameters.ascii or defaultParameters.ascii file must reflect the names used.

# if we are advecting images, to which time: "early", "middle", "late"
# "early" corresponds to the mean of the times of the earlier images
# "middle" corresponds to half way between the mean times of the earlier and of the later images
# "late" corresponds to the mean of the times of the later images
advectionTimeFlag = middle

Generally, advectionTimeFlag should be middle. The exception is when you only have one velocity field from short separations, and you are at the stage where you’re doing the first pass on the full data set including far separations. If the velocity field you have is from the later set of images, then it works better to advect the later images backward to the time of the earlier images (which didn’t generate a velocity field yet). In this case you would not advect all images to the midpoint in time, thus the flag advectionTimeFlag = early.

# the output file name for the scattered velocity vectors
outScatteredVelocityFileName = outScatteredVelocity.h5

# the output file name for the smooth, gridded velocity field
outGridVelocityFileName = outGridVelocity.h5

The output from an ACCIV pass will be stored in these two files.

# the fraction of a pixel to which a correlation location is found
correlationTolerance = 1e-2

# the minimum correlation coefficient for a tie point, below which it gets thrown out
minimumCorrelationCoefficient = 0.5

# the minimum time between images, below which image pairs will not be correlated
minimumTimeSeparation = 0.0

# the maximum time between images, above which image pairs will not be correlated
maximumTimeSeparation = 1e8

These last two parameters give you some control over which image pairs will be used or not used, based on which are “too close together” and which are “too far apart” in time to produce good correlations.

# the number of outer iterations of the overall function fitting and outlier removal process
smoothFitOutlierRemovalIterationCount = 1

# the number of inner iterations of streamline following, smooth function fitting process
# within the outer iteration loop (zero for no streamline following, but a smooth function will
# always be fitted to the data)
streamlineFollowingSmoothFitIterationCount = 2

ACCIV will automatically terminate the iterative process of fitting a smooth velocity on a grid once the change in the velocity field reaches the specified tolerance. However, the iteration will terminate “prematurely” when the maximum number of iterations specified above is reached.

# the threshold constant for defining outliers: a point x_i is defined to be an outlier
# if R_i > outlierThresholdConstant*median(R_i), where R_i = ||v_m(x_i) - v_s(x_i)||^2 
# is the root-mean-squared difference between the measured velocity and the smooth
# velocity interpolated to the same location, and where the median is taken over all
# measurements in the data set
outlierThresholdConstant = 8

# the minimum number of scattered data points that neighbor a given b-spline control point, 
# below which the control point is dropped from the fit
smoothFitMinControlPointScatteredNeighbors = 32

When computing the smooth velocity on the grid using a hierarchy of b-splines, each control point must have at least this many neighbors to contribute a non-zero change to the velocity field. Increase this number to get a smoother velocity (either for early passes or if the results are too noisy). Decrease this value if the velocity seems overly smooth.

# the number of vectors placed along each path by the streamline following process
pathVectorCount = 13

This can be set to a smaller number for earlier or cruder velocity fields. 10 or more good number for close to final passes. If this number is too small, "bumpy" artifacts may appear in the velocity. Decrease this number below 10 only if the number of scattered velocity vectors is getting too large to fit in memory.

# the relative error tolerance allowed in the Bulirsch-Stoer used to advect both
# displacement vectors and images
advectionErrorTolerance = 1e-4

# the maximum number of integration time steps allowed before the Bulirsch-Stoer
# integrator gives up
advectionMaxTimeStepCount = 10000

# Should we multiply the final velocity field by a mask so it is zero
# at the edges of the domain?
maskFinalVelocity = false

# work directory where data from intermediate ACCIV stages is stored
workDirectory = _work

The intermediate working directory will be created if it’s not already present. Files stored here show the intermediate steps that ACCIV goes through. They are useful for debugging problems with ACCIV or to better understand the process. Once and ACCIV pass has successfully produced output velocities (both scattered and on the grid), the user can delete this folder if desired. If you’re trying multiple extractions with different parameter settings, you might want to change this name for each round to keep multiple sets of intermediate output data for comparison.

#
# flags to determine which processes to do
#   these are useful if you want to resume the ACCIV process if it was
#   interrupted or if you need to change some parameters that only
#   affect later steps
#
# if the advectImages flag is also set, do we perform the image advection step?
doImageAdvectionStep = true

# do we perform the image correlation step?
doImageCorrelationStep = true

# if the advectImages flag is also set, do we perform the tie point un-advection step?
doUndoTiePointAdvectionStep = true

# do we perform the velocity construction step?
doVelocityConstructionStep = true

# do we replace work files if they already exist
#  overwriteWorkFiles = true is useful if redoing the computation (or part of it)
#  overwriteWorkFiles = false is useful if resuming a computation that was stopped
overwriteWorkFiles = false