Contents
2.2.2 Encapsulated PostScript configuration.
2.3 Installation with framegrabber
2.3.1 Framegrabber installation
2.3.4 Video capture configuration
4.4.1 Setting output stream colour
4.4.7 Encapsulated PostScript streams
5.6.6 Particle Tracking Velocimetry
9.1 Basic mathematical functions
9.4 Type manipulation functions
9.8 Reading and writing images
9.12 Image processing functions
9.24 Data acquisition functions
9.27 Particle tracking functions
9.30 Configuration and licence functions
10.1.2 Control of input streams
10.1.3 Control of output streams
10.1.5 Multiple output streams
11.2 The DigiFlow Drawing format
12.1 Windows bitmap files (.bmp)
12.4 Enhanced metafiles (.emf)
12.6 Encapsulated PostScript (.eps)
12.7 DigiFlow floating point image format (.dfi)
12.7.3 8 bit image (DataType = #1001)
12.7.4 8 bit multi-plane image (DataType = #11001)
12.7.5 Compressed 8 bit image (DataType = #12001)
12.7.6 32 bit image (DataType = #1004)
12.7.7 32 bit multi-plane image (DataType = #11004)
12.7.8 Compressed 32 bit image (DataType = #12004)
12.7.9 64 bit image (DataType = #1008)
12.7.10 64 bit multi-plane image (DataType = #11008)
12.7.11 Compressed 64 bit image (DataType = #12008)
12.7.12 32 bit range (DataType = #1014)
12.7.13 64 bit range (DataType = #1018)
12.7.14 Rescale image (DataType = #1100)
12.7.15 Rescale image rectangle (DataType = #1101)
12.7.16 Colour scheme (DataType = #2000)
12.7.17 Colour scheme name (DataType = #2001)
12.7.18 Colour scheme name variable (DataType = #2002)
12.7.19 Description (DataType = #3000)
12.7.20 User comments (DataType = #3001)
12.7.21 Creating process (DataType = #3002)
12.7.22 Creator details (DataType = #3003)
12.7.23 Image time (DataType = #3018)
12.7.24 Image coordinates (DataType = #4008)
12.7.25 Image plane details (DataType = #4108)
12.8 DigiFlow Particle tracking format
12.9 DigiFlow pixel data format (.dfp)
12.10 DigiFlow drawing format (.dfd)
12.11 DigiFlow archive format (.dfa)
12.12 DigImage raw format (.pic)
12.13 DigImage compressed format (.pic)
12.14 DigImage movie format(.mov or .dfm)
DigiFlow provides a range of image processing features designed specifically for analysing fluid flows. The package is designed to be easy to use, yet flexible and efficient, and includes a powerful yet flexible macro language. Whereas most image processing systems are intended for analysing or processing single images, DigiFlow is designed from the start for dealing with sequences or collections of images in a straightforward manner.
Before installing or using DigiFlow, please read the Licence Agreement (see §16) and ensure you have completed the registration requirements.
The origins of DigiFlow lie in an earlier system by the same author: DigImage. This earlier system, with its origins in 1988 and first released commercially in 1992, pioneered many uses of image processing in fluid dynamics. Utilising its own DOS-extender technology, DigImage existed in the base 640kB of DOS memory (and later from the command prompt under Windows 3.x and 9x), accessing around 12MB of extended memory for image storage and interface with the framegrabber hardware.
To obtain the necessary performance in these early days of image processing on desktop computers, DigImage required a framegrabber card to be installed to provide not only image capture, but also image display and some of the processing. While this close coupling allowed efficient real-time processing and frame-accurate control of a video recorder, it ultimately restricted the development and deployment of the technology. The original ISA bus based Data Translation DT2861 and DT2862 frame grabber cards remained available until 2001, but by that time suitable motherboards had become difficult to source. At time of writing (2007) and despite its reliance on outdated technology, DigImage is still used in many laboratories around the world.
The development of DigiFlow began in 1994, although the project had a number of false starts and development put on hold a number of times due to other commitments. The code of this version has its origins in 1997 as part of the development of synthetic schlieren (see §5.6.4). The computational and resolution requirements for synthetic schlieren could not be accommodated efficiently within the framework of DigImage.
Despite sharing many approaches, algorithms and techniques, DigiFlow does not re-use any of DigImage’s 8Mbytes Fortran 77 and 2MB Assembler source code. The design goals for power, flexibility and efficiency in DigiFlow could only be achieved by starting again from scratch.
DigiFlow builds on experience with DigImage from the user view point to provide a more powerful, more flexible, but simpler interface. It also builds on the programming experience to provide a more flexible, powerful and maintainable code base (now in excess of 15MB of source).
A central feature of DigiFlow is a powerful macro language (dfc) and interpreter. This provides users with an efficient and flexible environment in which to automate and customise processing, as well as proving to be a very useful general computational and plotting tool.
Versions of DigiFlow have been in use in Cambridge since 2000, and at other selected laboratories since 2002. Its wider dissemination began in late 2003 with a series of beta releases. The first commercial release (version 1.0) dates from February 2005, with parallel processing and other technologies providing substantial speed increases being introduced with version 2.0 during 2007. Version 3.0, released in 2008, provides further performance improvements plus a wealth of new processing features.
DigiFlow has been designed from the outset to provide a powerful yet efficient environment for acquiring and processing a broad range of experimental flows to obtain both accurate quantitative and qualitative output.
Central to design philosophy is the idea that an image stream may be processed as simply as a single image. Image streams may consist of a sequence of images (e.g. from a ‘movie’), or a collection of images related in some other manner.
Efficiency is obtained through the use of advanced algorithms (many of them unique to DigiFlow/DigImage) for built in processing options.
Power and flexibility are obtained through an advanced fully integrated macro interpreter (using DigiFlow’s dfc macro language) providing a similar level of functionality to industry standard applications such as MatLab. This interpreter is available to the user either to directly run macros, or as part of the various DigiFlow tools to allow more flexible and creative use. Commercial versions of DigiFlow include additional features such as partial compilation to further improve performance.
Although not an essential component, DigiFlow retains the potential DigImage released by the control of a framegrabber. Not only does this greatly simplify the process of running experiments, acquiring images, processing them, extracting and plotting data, but it also enables real-time processing of particle streaks and synthetic schlieren, for example.
This User Guide is designed to provide the primary reference for DigiFlow. The User Guide is supplied in both .html and .pdf formats and is linked to the help system within DigiFlow. Pressing the F1 function key within DigiFlow will start a web browser and take you to the most appropriate point in the .html version of the User Guide.
The User Guide is not in itself complete: detailed descriptions of the many functions provided by the macro interpreter may be found in the interactive help system (Help: dfc Functions). The User Guide is also supplemented by a variety of scientific publications that expand on some of the underlying technologies.
The typographical convention used in the User Guide is described below:
|
Typography |
Description |
|
Analyse |
Windows elements such as prompts, menu items and dialogs. |
|
Expt_A.dfi |
File names, etc. |
|
read_image() |
Interpreter commands and functions. |
|
:= |
Interpreter operators and syntax. |
|
"string" |
Interpreter operators and syntax. |
|
# comment |
Formal argument names for interpreter functions. |
|
my_image |
Variables, numbers, etc., for the interpreter. |
|
file0 |
Formal argument names for interpreter functions. |
Although DigiFlow will work on any Windows XP or later machine, we recommend that you avoid using Windows Vista if possible as the performance of Vista is significantly worse than either Windows XP or Windows 7. There are versions of DigiFlow that can operate under both 32-bit and 64-bit implementations, although at present it cannot control a digital video camera under a 64-bit implementation of Windows.
DigiFlow is a typical Windows application with a graphical user interface, menus, dialog boxes and toolbars. However, unlike many applications, DigiFlow does not require a special installation procedure, but can simply be copied to the desired directory. In most cases DigiFlow will be delivered in a .zip or self-extracting (.exe) archive file, downloaded from the web. This should simply be unzipped into your selected directory. However, to make the best of DigiFlow, there are some additional settings and tasks to be completed. The setup.bat file that is copied to the installation folder will help with this process. Refer to GettingStarted.pdf for further details.
The installed part of DigiFlow consists of DigiFlow.exe, which contains the core functionality, and a range of DLL files that handle specific menu options. DigiFlow also makes use of various global start-up files stored in the same directory.
During use, DigiFlow generates two status files in the directory in which it is started. These are DigiFlow_Status.dfs (§13.5), which contains a range of information describing the settings, and DigiFlow_Dialogs.dfs (§13.4), which records your last responses to many of the prompts, etc. By storing this information in the directory in which DigiFlow is started, DigiFlow is able to keep a separate set of information for each user, or for each specific task, without polluting the registry. Additionally, these status files can be deleted or moved as the user wishes. In some circumstances, DigiFlow_Status.dfs may become corrupted. If DigiFlow fails to start, or exhibits unexpected behaviour, you should try removing (or renaming) DigiFlow_Status.dfs to see if this cures the problem.
It is recommended that you use a new directory for each new set of experiments and for each new project. In this way the DigiFlow strategy of storing localised status files will facilitate use of DigiFlow in the various different contexts. In such an environment it is frequently most convenient to start DigiFlow from the command prompt within the appropriate directory structure, although other strategies such as multiple shortcuts or setting up associations for Windows Explorer are also possible.
If you wish to run DigiFlow from a command prompt (strongly recommended), it is worth putting this directory on the path so that DigiFlow may be started by simply typing DigiFlow at the prompt (DigiFlow will normally add itself to the search path the first time it is run to enable this). If you prefer to start DigiFlow from the desktop or start menu, you will need to create a shortcut at that point and set the Start in directory appropriately. It is strongly recommended that you do not run DigiFlow from the directory in which the program resides, exept during the set-up procedure.
Details of the basic setup and configuration of DigiFlow under Windows is covered in GettingStarted.pdf. This section reiterates some of the key points and highlights other considerations that may facilitate your use of DigiFlow. Note that DigiFlow can also be installed to run under Wine on a Linux machine, although it is not possible to control a digital video camera and .eps (Encapsulated PostScript) files do not have access to the normal range of fonts and appear visually less satisfying.
Specification of the file extension for file names within DigiFlow is mandatory in most circumstances as DigiFlow utilises this extension to determine the file type for output. However, by default, Windows XP and later hide the extensions to files of known types, a feature that can cause problems with DigiFlow. We recommend, therefore, that you turn off this feature. DigiFlow will attempt to do this for itself, but this may not work on some systems. If DigiFlow does not make all extensions visible automatically, then you may achieve this manually through the View tab of Tools: Folder Options under Windows Explorer. Simply remove the check mark from Hide extensions for known file types. Note that this will need to be done for each DigiFlow user.
By default, DigiFlow will not be associated with any file types or extensions, unless you install it using setup.bat (in which case .dfc, .dfd, .dfi, .dfm, .dfs and .dft will be associated with DigiFlow). The easy way to make or add such associations is to right-click on a file with such an association then select Open with (or Open if Open with is not visible) and choose the default program from the Open With dialog and check the Always use… box. If DigiFlow is not listed in this dialog, then locate it using the Browse button.

Figure 1: The Open With dialog for selecting the default program.
We recommend that the following extensions are associated with DigiFlow on all installations: .dfc, .dfd, .dfi, .dft and .dfs. You may also wish to set up associations for other standard image formats such as .bmp, .tif, .png and .jpg.
DigiFlow can create Encapsulated PostScript (.eps) files from image and graphical output for incorporation into documents in packages such as LaTeX and Word. This can be achieved either through DigiFlow’s inbuilt .eps facility, or using a Windows printer driver. The former is restricted to bit images (or a rasterised version of graphics), whereas the latter can produce both bit image and vector graphics.
By default, DigiFlow searches for a printer named EPS to use to create the .eps files. Creation of this printer is relatively straight forwards. Start the Add Printer Wizard from the Printers and faxes window, selecting Local printer attached to this computer and using the File: (print to file) port. Select a PostScript printer driver (we recommend the HP C LaserJet 4500-PS if you are using Windows XP, or the Xerox Phaser 6120 PS if you are using Windows 7) and name the printer “EPS”. (You do not want to make this the default printer, you may, however, wish to share the printer to simplify the setting up of further machines.) For Windows Vista, it is recommended that you download an Adobe PostScript driver from www.adobe.com as some of the drivers distributed with Windows Vista format their PostScript in a manner that inhibits the use of LaTeX packages such as psfrag.
Once the wizard has finished, right-click on the new EPS printer and select Printing preferences. Click on the Advanced button expand Document Options and PostScript Options within it. Under PostScript Output Option select Encapsulated PostScript (EPS), as indicated in figure 2.

Figure 2: Encapsulated PostScript (.eps) printer setup.
Note: if you are using Remote Desktop to access the computer with DigiFlow installed, you are best to disable the feature making local printers available to the remote session as this can cause problems if the EPS printer exists on your local machine.
DigiFlow cannot itself read back in an Encapsulated PostScript file it produces. However, if DigiFlow detects that GhostScript is installed on the machine, then DigiFlow will attempt to use GhostScript to help it load the .eps file in an appropriate format. For this to be achieved, then GhostScript must be on the system PATH and the GS_LIB environment variable must be set up to point to the GhostScript libraries.
Note that GhostScript is not distributed with or required by DigiFlow. Use of GhostScript is governed entirely by the licence of that product and not by the DigiFlow Licence.
The maximum linear address range under 32 bit Windows is 32 bits or 4GB. By default under Windows this is subdivided into two ranges for each process. The first 2GB of memory is for the process’s own use, while the second is for the operating system. Although 2GB superficially appears a lot, there are times when it would be useful to have more. (At the time Windows was designed, 2GB was considered a good approximation to an unlimited memory resource, but things have moved on…) With Windows XP and later it is possible to change the 50:50 default split to reserve 3GB for processes, restricting the system. Not all software, particularly some drivers, support this extension. DigiFlow, however, is able to and so if you start running low on virtual memory, it may be worth a try.
To install the 3GB process memory option, select System Properties (right click on My Computer and select Properties) then the Advanced tab. Click the Startup and Recovery Settings button, then the Edit button to open NotePad to make the necessary changes. Note that you need to have Administrative access rights to be able to do this.

Figure 3: Dialogs for setting the /3GB option to increase available virtual memory.
NotePad will allow you to edit the boot.ini file that controls the startup of Windows. Typically, this will look like
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
To enable the 3GB option, you need to add the /3GB switch to the end of the line specifying Windows startup. It is best to do this by adding an additional startup option so that you can boot your machine in either standard 2GB or 3GB modes. The resulting boot.ini should look something like this:
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional (3GB)" /noexecute=optin /fastdetect /3GB
Note that the order of these two lines determines whether the default boot is 2GB or 3GB. In the above example, the standard 2GB boot is the default. Reverse the order of the two lines to make the 3GB boot the default.
If you are installing DigiFlow in a machine equipped with a BitFlow R2, R3, R64 or R64e series framegrabber then some additional steps are required. These require administrative access to implement.
The framegrabber should be installed and tested using the BitFlow installation procedure. You will require the BitFlow drivers for version 5.00, 5.20 or 5.30. Later versions may also be supported (contact Dalziel Research Partners for details). You should note that on some systems the BitFlow installation procedure can hang; if this occurs, try installing after rebooting Windows in Safe Mode.
The BitFlow framegrabber requires a configuration file (.cam, .rcl or .r64) for the camera being used. Configuration files for cameras known to work with DigiFlow may be found at http://www.dalzielresearch.com/digiflow/cameras/.
If you have a multi-user system where most users do not have administrative access, we recommend that you change the permissions on the BitFlow software to allow all users to change the camera configuration file if and when they need to. This is achieved using the Registry Editor (regedit.exe; accessible from the command prompt) to adjust the permissions on all keys in the registry relating to ‘BitFlow’ by adding the ‘Authenticated Users’ security principle with ‘Full control’. Failure to do this would mean that only users with administrative access could change the camera configuration.
DigiFlow requires information over and above what is provided in the configuration file for the framegrabber card. This additional information about the camera capabilities and users preferences is stored in DigiFlow_Cameras.dfc; consult §13.3 for details of the format of this file. Cameras not listed in this file have not been tested, although there is a reasonable chance that all that is required (for a camera supported by the BitFlow frame grabber) is the addition of appropriate entries, provided a suitable camera configuration file is also available for the BitFlow framegrabber. Please contact Dalziel Research Partners if you require any help or guidance with this.
In the ‘Local security policy’ (found in the ‘Administrative tools’ section of the ‘Control Panel’), open the ‘Local Policies: User Rights Assignment’ option. You need to add permission for all DigiFlow users to the following items:
· Adjust memory quotas for a process
· Increase scheduling priority
· Lock pages in memory
It is suggested that you do this by giving full control to ‘Authenticated users’
These adjustments are necessary to ensure that DigiFlow is able to manage the machine performance adequately to ensure trouble-free capture.
It is strongly recommended that video capture is to a disk other than that containing the operating system in order to obtain adequate performance. The necessary disk system bandwidth may be in excess of 240MB/s in some cases (e.g. with a Dalsa 4M60 camera), thus requiring a Mode 0 RAID array, or using Windows to ‘stripe’ across multiple disks. However, for most cameras 40MB/s is sufficient and this may be achieved via a fast IDE or SATA disk (but not the one the operating system is on!).
The capture process in DigiFlow can be configured in two ways. Either you can directly specify the capture file and location each time (risking the user specifying a disk system with insufficient bandwidth), or setting up DigiFlow to capture to a fixed location and require the user to ‘review’ (and possibly edit) the sequence in order to copy it into their own directory space. For multi-user systems, this second is generally preferred as it allows users to utilise the capture facility like a video recorder while preventing retention of unwanted video footage.
The default configuration takes the second option, and assumes that the capture location is V:\Cache\CaptureVideo.dfm. We recommend that you configure your system so that this directory exists (either by appropriate naming of the capture disk, or by setting up a share to an appropriate point and then connecting to it). This directory must not be compressed and must have full access for all DigiFlow users. Once you have created this directory, you should run File: Live Video: Setup (see §5.1.4.3 for further details) to create the initial V:\Cache\CaptureVideo.dfm. It is strongly recommended that you do this before writing any other data to the capture disk. Details on how to change the name or location of the cache file may be found in 13.2.
It is important that the space DigiFlow reserves in this file remains as a single contiguous block on the disk drive. If it becomes fragmented for any reason then, due to the very high data transfer rates required, DigiFlow may not be able to write to the disk as fast as data becomes available from the camera and so timing errors may result.
Once created, V:\Cache\CaptureVideo.dfm will be flagged as Read only by the operating system (although DigiFlow will still be able to write to it). The file will not shrink if a smaller sequence is captured, but may grow if one larger than that specified during File: Live Video: Setup is requested (note that there is a risk of fragmentation if this occurs). It is important, therefore, that you go through the review process outlined in §5.1.4.2, rather than simply copying this file, as in general only a part of the file will contain valid data.
Consult §13.2 on DigiFlow_LocalData.dfc should you wish to change the name or location of V:\Cache\CaptureVideo.dfm.
It is recommended that you use a new directory for each new set of experiments and for each new project. In this way the DigiFlow strategy of storing localised status files will facilitate use of DigiFlow in the various different contexts. In such an environment it is frequently most convenient to start DigiFlow from the command prompt (see figure 4) within the appropriate directory structure, although other strategies such as multiple shortcuts or setting up associations for Windows Explorer are also possible.

Figure 4: It is frequently most convenient to start DigiFlow from the command prompt.
If you wish to run DigiFlow from a command prompt (strongly recommended), it is worth putting this directory on the path so that DigiFlow may be started by simply typing DigiFlow at the prompt, and placing a shortcut to the command prompt on the topmost level of the Start button. It is also worth pinning a shortcut to the command prompt to the start menu (and/or task bar for Windows 7), and in the properties setting the Start in path to an appropriate location.
If you are not familiar with the use of the command prompt, then the following brief list of the most useful commands may be of some value.
|
Command |
Description |
|
cd folder |
Changes to the directory (folder) located within the current directory. |
|
cd .. |
Move up one directory level. |
|
cd \ |
Move to the topmost (root) directory on the current drive |
|
dir |
List all files in the current directory. |
|
dir *.dfi |
List all .dfi files in the current directory. |
|
dir *.dfc /s |
List all dfc files located either in the current directory, or any subdirectories. |
|
move file dest |
Move file to a new directory dest. Can also be used to rename folders. |
|
copy srce dest |
Copy the file srce to dest. |
|
xcopy srce dest |
A more flexible form of copy. |
|
xcopy srce dest /s/d |
If srce and dest are directories, then will copy all the files in the directory and any subdirectories to dest, but only if the srce version is newer. This might be used, for example, as xcopy expt\*.dfd results /s/d to update a collection of DigiFlow drawings (dfd files) in a results folder. |
|
ren file new |
Rename file with the name new. |
A very useful feature of Windows XP and later is that the <tab> key will expand a file name. For example, if you are in a directory that contains subdirectories named Expt1, Expt2 and Expt3, then typing cd e followed by <tab> will expand this to cd Expt1. Pressing <tab> a second time will change this to cd Expt2, and so on. To find out more about the commands available at the command prompt, then search for command prompt in the Window’s Help and Support Centre and select Using Command Prompt. Alternatively, if you know the name of the command but want more details of its options, type the command followed by /? at the command prompt (see figure 5 for an example).

Figure 5: Help is available for a command at the command prompt by adding /? after the command.
If you prefer to start DigiFlow directly from the desktop or start menu, you will need to create a shortcut at that point and set the Start in directory appropriately (see figure 6). It is strongly recommended that you do not normally run DigiFlow from the directory in which the program resides.

Figure 6: Properties dialog for a short cut to start DigiFlow.
DigiFlow supports a number of command line arguments. The most common use is to specify either an image file or movie to be loaded when DigiFlow starts, or a dfc file to be run. In both these cases, simply type DigiFlow at a command prompt, followed by the name of the image file/movie or dfc file.
Additionally, there are a number of command line switches that can be used in special circumstances. These are given in the following table.
|
Switch |
Description |
|
/stack multiple |
Sets the multiple for stack size allocation. If not specified, thenthe default multiple is 1.0. This switch can be used in an attempt to decrease or increase the size of the stack created for separate computational threads in event of memory problems. |
|
/timing |
This turns on a performance timing feature incorporated in some of the DigiFlow facilities. |
|
/con |
Start up a conole window at the same time as starting DigiFlow. (The console window can also be started from dfc code using open_console() or open_file().) |
|
/wine |
Changes some features to improve performance when running DigiFlow under Wine on Linux. |
|
/dev |
Enable certain features related to internal performance monitoring. Intended for use by the developer. |
|
/? |
Give the command line options for starting DigiFlow. |
The final option for starting DigiFlow is to double-click in Windows Explorer on a file associated with DigiFlow.
The main DigiFlow window follows that common for most applications with a Multiple Document Interface (MDI). The menu bar at the top provides access to the majority of the facilities, while the toolbar underneath gives a more convenient method of accessing the more widely used functions. A typical example is shown in figure 7.


Figure 7: The basic DigiFlow window.
As is normally the case for Windows applications, the main window and the client windows may be resized by dragging the frame of the window. Holding down the control key, while dragging the boundary of a client window, will cause the contents of the window to be zoomed so as to make the best use of the available space. If you do not hold down the control key, then the window size is changed without changing the zoom applied to its contents.
As is common with most Windows applications, help while using DigiFlow can be obtainined by pressing the f1 key. This will start an instance of Internet Explorer and bring up an html copy of this manual. DigiFlow will automatically scroll to the position within the manual that is most relevant to the dialog or process you have open at the time. Subsequent presses of f1 will utilise the same tab in Internet Explorer, provided this remains open.
Some users, particularly when first starting, may prefer to have the manual automatically keeping track with their activities. This can be achieved by turning on the AutoHelp facility, either from the Help menu, or by clicking the questionmark button () on the toolbar. When activated, an instance of the Internet Explorer browser will be activated and track your activity, providing timely help.
As an option to using the html version of this manual, the manual is also provided as DigiFlow.pdf.
DigiFlow uses image selectors to specify image streams for input to and output from a given process. Four types of image stream are supported:
Single images. These contain just a single image.
Movie. A movie contains multiple images stored in a single file.
Sequence. A sequence is a collection of related files, typically identified by a numeric part of the file name that increases by one between neighbouring images in the sequence.
Collection. A collection is a group of image files that have no special relationship to each other. Collections may be subdivided into two groups: homogeneous collections and heterogeneous collections. In a homogeneous collection, all the images within the collection have the same format (same size, colour depth, file type, etc.). With a heterogeneous collection, the format may vary from one image to another. At present, most processes within DigiFlow do not support heterogeneous collections.
Image selectors may specify not only raster format image files, but also vector format files. DigiFlow supports many standard raster formats, including .bmp, .tif, .gif, .png, .jpg, and .avi along with special formats to provide backward compatibility with DigImage (.pic and .mov, the latter now renamed .dfm in DigiFlow). DigiFlow also introduces the new DigiFlow Image format, .dfi, to allow images to be saved with full floating point precision, and the DigiFlow Pixel format (.dfp) provides text output specifically tailored for raster images.
Vector format files include Enhance Meta Files (.emf) Windows Meta Files (.wmf) and DigiFlow Drawing format (.dfd). The last of these provides output formatted as plain text containing both data and drawing commands. This text may be imported into other applications, or read back into DigiFlow to reconstruct the image or drawing it represents. If GhostScript is installed on the system (see GettingStarted.pdf), then Encapsulated PostScript (.eps) files can also be opened with DigiFlow.
DigiFlow also provides a specialised file format (.dft) for storing particle tracking data. While these may be treated as images, in general the functionality available through the specialised particle tracking facilities is to be preferred.
The specialised DigiFlow and DigImage formats (.dfm, .dfi, .dfp, dft and .dfd) are described more thoroughly in §11.2.
The concept of an archive file was introduced to DigiFlow in version 3.4 as a method of both collecting multiple image files that form part of a sequence, and of storing additional details about an image or a sequence of images when the file format being used does not provide a mechanism for storing this information.
DigiFlow archive files use a .dfa extension appended on to the corresponding image file or sequence name. For example, if a .dfa file is generated for a sequence of images image000.png, image001.png, … image732.png, then the name of the .dfa file will be image###.png.dfa.
If the use of archive files is enabled, then when reading the image sequence back in as image###.png, additional information not present in the .png files themselves (such as the method used to construct the sequence and the timing of the sequence) will be recovered from the .dfa file. Alternatively, attempting to open image###.png.dfa will both read the sequence image###.png and recover the additional information from the .dfa file.
The use of DigiFlow archive files is enabled or disabled through the Open Image and Save Image dialogs (see §4.1 and §4.2).
For further details on the format of .dfa files, refer to §12.11.
A key concept associated with input image streams is sifting. In DigiFlow, sifting is the process by which images are extracted from in input stream. The extraction process may result in all the images being extracted, or only a subset of images (typically specified by a start number, an end number and a step). It may also result in a subregion of the image (a rectangular window within the image) being returned, or, in the image being modified to conform to some reference. Further details of the sifting process are given in §4.3.
DigiFlow includes a powerful interpreter and associated macro language. The language is referred to as dfc code. While the programming language for dfc code is specific to DigiFlow, it follows the general syntax and conventions of many other modern high-level languages. In addition to the basic functionality expected of such languages, DigiFlow provides a vast range of functions tailored specifically to tasks for which DigiFlow is ideal. This includes not only image processing functions (ranging from contour tracing to Fast Fourier Transforms), and data analysis functions (such as statistics, least squares fits), to numerical solution of the equations of motion (e.g. Goudnov solution of shallow water equations and stream function-vorticity formulation for two-dimensional Boussinesq flows).
The present manual contains introductory documentation for the use of dfc functions and code. However, much of the detailed documentation for the individual dfc functions is to be found in the interactive help system Help: dfc Functions. The most convenient way of accessing this is frequently through the dfcConsole feature described in §5.2.9. The DigiFlow macros\ subdirectory (found in the folder where DigiFlow is installed) contains a number of documented examples of macro code.
One important aspect of DigiFlow is that it supports not only multiple image windows, but also multiple processing threads. This has two important benefits. First, it allows DigiFlow to continue to be used interactively while it is processing simultaneously one or more sequence of images, thus allowing real-time inspection of the progress. Second, for PCs with multiple processors, the execution time of a single process can be greatly reduced. (It should also be noted that more than one copy of DigiFlow may be used simultaneously).
If the user attempts to close a window that is in
use with an active thread, then the system will warn the user that closing the
window will also kill the thread. Depending on the version of DigiFlow you are
using, windows that are playing a role in an active thread have the name of the
thread indicated in the window status bar at the bottom of the window and have
a ‘sloshing tank’ symbol
in the bottom right-hand corner.
The user may also control the individual threads
more directly, stopping them, pausing or resuming them, or changing their
priority. This is achieved through the View Threads menu item (§5.3.10), or the corresponding
button on the main
toolbar. (All active process threads may be suspended by clicking
on the toolbar.)
Some of DigiFlow’s features include graphical and text output. In such cases it may be desirable to include more than simple plain text. To achieve this, fully licenced copies of DigiFlow support LaTex-like math-mode text formatting. For example, in Analyse: Time Series: Summarise (see §5.6.1.6) it is possible to specify the titles of the axes of the graph produced. Specifying it as the string "Dimensionless height $\big(\frac{h}/{\alpha^2H_0}\big)$" would produce the label
.
Although DigiFlow does not understand the full range of LaTeX commands and macros, it can interpret those most likely to be of use in figures and graphs. The list includes:
Upper and lower case greek letters (e.g. \Alpha or \zeta)
$
\!
\#
\$
\%
\&
\,
\2dots
\:
\;
\aleph
\angle
\approx
\backslash
\bar
\bf
\big
\BIG
\Big
\bigsizes
\bullet
\cdot
\circ
\copyright
\cos
\cosh
\dagger
\ddagger
\dddot
\ddot
\div
\dot
\dots
\downarrow
\Downarrow
\ell
\equiv
\euro
\exists
\exp
\footnotesize
\forall
\frac
\ge
\geq
\gg
\hat
\HUGE
\huge
\Im
\in
\infty
\int
\it
\langle
\LARGE
\large
\Large
\lbrace
\lbrack
\le
\left(
\left[
\Leftarrow
\leftarrow
\Leftrightarrow
\leftrightarrow
\leq
\ll
\ln
\log
\mathbf
\mathit
\mathrm
\minus
\mp
\nabla
\ne
\neq
\normalsize
\notin
\oplus
\oslash
\otimes
\overchar
\P
\partial
\phantom
\pm
\pounds
\prime
\prod
\propto
\qquad
\quad
\rangle
\rbrace
\rbrack
\Re
\right)
\right]
\rightarrow
\Rightarrow
\S
\scriptsize
\sim
\simeq
\sin
\sinh
\small
\sqrt
\subset
\subseteq
\sum
\supset
\supseteq
\surd
\tan
\tanh
\textbf
\textit
\textnormal
\textrm
\therefore
\tilde
\times
\tiny
\underline
\Uparrow
\uparrow
\wedge
\wp
\yen
\\
\^
\_
\{
\}
\~
Thereare some minor restrictions and additional requirements for the DigiFlow LaTeX-like syntax compared with standard LaTeX. For example, the standard LaTeX $\left(\frac{a}{b}\right)$ should be stated in DigiFlow as $\left({\frac{a}{b}}\right)$. The additional pair of braces tells DigiFlow that the fraction a/b is controlling the size of the large left bracket. This additional pair of braces does not affect the processing of the string by LaTeX. A further example is that DigiFlow accepts LaTeX macros such as \alpha whether or not it is in ‘maths mode’ (i.e. between $..$).
This LaTeX-like text formatting (available only with fully licensed copies of DigiFlow) may also be used in dfc code, for example through the draw_text(..), draw_axes(..) and plot_titles(..) commands.
It is not possible to define additional LaTeX-like macros from within LaTeX-like formatted text. However, additional macros may be defined from within dfc code; see §11.4 and the dfc help for further details.
A powerful feature of this component of DigiFlow is the way it works to support the use of Encapsulated PostScript (.eps) files in LaTeX through the psfrag macro package. See §5.1.10 for further details.
The Open Image dialog box is used throughout DigiFlow to open source image selectors (§3.1).

(a)

(b)
Figure 8: The Open Image dialog box under Windows XP. (a) Showing all files and (b) using Compact List option.
The Open Image dialog box consists of a standard Explorer-style display of folders, files, file types, etc., along with a preview pane on the right-hand side. This preview pane will attempt to display the currently selected file.
DigiFlow supports a range of industry standard image formats, plus some special formats. The special formats both provide compatibility with the earlier DigImage system, and provide facilities (e.g. floating point data representation) not found in industry-standard formats. These non-standard formats are described in more detail in §11.2 (DigiFlow drawing format) and §12 (DigiFlow image file formats). Note that DigiFlow expects the user to specify the extension of the file. It is therefore important that all extensions are visible in the dialog (refer to §2.2 for how to achieve this).
To select a single image or a movie, simply click on the name of the file containing this object. If you prefer, the name of the file may be typed at the File name prompt. If you type in the file name a preview will not be generated automatically, but can be requested by clicking the Preview button. If manually entering the file name, then it is important that you specify the file extension to remove any potential ambiguity.
To select a sequence, the name of the sequence must be typed at the File name prompt, using hashes (#) to indicate the varying numeric part of the file name. Alternatively, click on any member of the sequence and check the Numbers as #### box. This will convert (starting from the right-hand end of the file name) any digits found into the appropriate number of hash characters, thus allowing easy specification of the sequence. However, numbers enclosed in parentheses or square brackets (i.e. (..) or [..]) will not be converted to hashes. This allows numeric data to be included unambiguously in the file name. Again, the Preview button may be used to generate a preview if it is not generated automatically.
The precise behaviour of the Compact list check box depends on which version of Windows you are using. The motivation, however, is to provide a more compact way of accessing a large number of numbered images in a given folder. Under Windows XP, the Compact list check box will provide a more compact summary of those present by displaying the name of the first few in a given sequence, and using the compact hash notation to summarise the rest. An example of this is given in figure 8, where figure 8a shows all the files (without Compact list checked) and figure 8b shows how the number of files visible is decreased and sequences are replaced by hashes in the file name when the Compact list box is checked.. Selecting the summary containing hashes is equivalent to selecting the entire series. (Note that clicking on Compact list will retain the files specified at the Object name prompt, but remove any selection in the view window.)
Unfortunately, this simple Compact list option is not available under Windows Vista or Windows 7. Instead, checking Compact list searches for .dfa DigiFlow archive files (see §3.5) and displays only them. Provided all the images and sequences have been created with the archive facility enabled, then the net effect is very similar. An example of this is shown in figure 9.
Whichever version of Windows you are using, if you select an image file (rather than a .dfa file) then the .dfa file is read only if the Read .dfa archive box is checked. However, if you select the .dfa file itself, then it will always be read, along with the image or sequence of images.

(a)

(b)
Figure 9: The Open Image dialog box under Windows 7. (a) Showing all files and (b) using Compact List option. Note that only thos files for which a .dfa archive file was generated will be shown when the Compact list box is checked.
Note that the default settings of the Number as ####, Compact list and Read .dfa archive check boxes is remembered from one invocation of the dialog to the next.
A collection of images may be specified using the mouse in combination with the <shift> key to select a range of files, or the <ctrl> keys to select or deselect individual files. Alternatively, the names may be typed at the File name prompt, each name enclosed by double quotation marks. The collection is sorted into alphabetical order for display and processing. (If a collection is specified in this manner then any hash characters will be interpreted as hashes. Similarly, checking Number as #### will be ignored.) In general, a sequence is preferable to a collection as it offers a greater level of control.
A collection of images may also be selected using wildcards. This may be achieved in two ways. If you use the standard Windows wild cards (? to represent a single character, and * to represent a variable number of characters) then the dialog will display only those files that fit the description; you may then select them in the normal manner. Alternatively, you may use % in place of ? and $ in place of * to do the selection directly. For example, typing Sheep*.* will cause the dialog to display sheep2.tif, sheep.bmp, sheep.jpg, sheep.pic and sheep.tif to be displayed in the dialog box, which may then be selected using the mouse and shift key. Alternatively, Sheep$.$ will achieve the same result, selecting all five files.
If the selected image contains true colour, then the Colour component list box is enabled. This list box allows selection of whether the image is to be treated as full colour, or how the colour information is converted to a greyscale for processing by DigiFlow. For example, selecting RGB will allow DigiFlow to process the red, green and blue image planes separately (where this makes sense), while green will take the green component of the colour image and treat it as a greyscale image, or hue will process the colour using a hue/saturation/intensity representation of the image. The options greyscale and mean all produce a similar effect, although precise details of how the resulting image is constructed from the red, green and blue components differs. The table below gives the relationships.
|
Key |
Returns |
Comments |
|
RGB |
Three colour planes |
Full colour image |
|
Mono |
0.11*red + 0.59*green + 0.30*blue |
Same as grey. |
|
Red |
red |
Red component only. |
|
Green |
green |
Green component only. |
|
Blue |
blue |
Blue component only. |
|
hue |
|
Image hue (colour) |
|
saturation |
|
Image saturation (purity) |
|
intensity |
|
Image intensity (brightness) |
|
cyan |
1 – red |
|
|
magenta |
1 – green |
|
|
yellow |
1 – blue |
|
|
grey |
0.11*red + 0.59*green + 0.30*blue |
Same as mono. |
|
mean |
(red + green + blue)/3 |
Mean of three components. |
|
max |
max(red, green, blue) |
The brightest component. |
|
min |
min(red, green, blue) |
The darkest component. |
An image containing only a single plane of data may contain colour information if captured from a camera fitted with a Bayer colour mosaic filter. To provide support for this and since it is unlikely that the image file will contain information that DigiFlow can use to automatically detect such an image, when DigiFlow detects a single plane of data in the image to be opened it provides the following supporting options:
|
Key |
Returns |
Comments |
|
(single plane) |
P |
Standard image |
|
RGB from Bayer filter |
Three colour planes |
Interpret as a full colour image using a standard Bayer filter layout |
|
times 2 |
2*P |
Intensities rescaled |
|
times 4 |
4*P |
Intensities rescaled |
|
times 8 |
8*P |
Intensities rescaled |
|
times 16 |
16*P |
Intensities rescaled |
|
times 32 |
32*P |
Intensities rescaled |
|
times 64 |
64*P |
Intensities rescaled |
|
div 2 |
P/2 |
Intensities rescaled |
|
div 4 |
P/4 |
Intensities rescaled |
|
div 8 |
P/8 |
Intensities rescaled |
|
div 16 |
P/16 |
Intensities rescaled |
The Save Image As dialog is essentially the same as the Open Image dialog (§4.1), but is produced when the name of the output image selector (§3.1) is required.

Figure 10: The Save Image As dialog box.
If an image selector of the same name does not exist already, then the file name must be entered by typing at the File name prompt. The extension to be used should be specified explicitly as DigiFlow uses this to determine the file type to be created. It is therefore important that all extensions are visible in the dialog (refer to §2.2 for how to achieve this). Simply selecting a type from the Save as type list will not necessarily have the desired effect if more than one possible type is indicated.
Note that some file types have a range of options such as bit depth and compression. These are normally controlled from outside the Save Image As dialog box using the Options… button in the parent dialog. Refer to §4.4 for further details.
DigiFlow supports a range of industry standard image formats, plus some special formats. The special formats both provide compatibility with the earlier DigImage system, and provide facilities (e.g. floating point data representation) not found in industry-standard formats. These non-standard formats are described in more detail in §11.2 (DigiFlow drawing format) and §12 (DigiFlow image file formats).
The Compact list check box operates in the same way as for the Open Image dialog described in §4.1. Here, the Create .dfa archive check box replaces the Read .dfa archive and causes DigiFlow to create a .dfa archive for the output it produces (see §3.5).
When processing an image stream it is often desirable to select only a subset of the stream for processing. This subset may contain only some of the images from the stream, and/or it may contain only part of each image. Within DigiFlow this process of selecting a specific part of an image stream for processing is referred to as ‘sifting’. When sifting is available, the corresponding dialog will have a Sift… button (typically one for each input selector) that starts a tabbed dialog box controlling the sifting process. The following subsections describe the various sifting options.
The Selector Timing tab of the Sift dialog allows the user to specify which times from a multi-image image selector (§3.4) will be used for a process.

Figure 11: The standard Selector Timing tab of the Sift dialog.
This tab allows the preview of the image selector and specification of the processing start and end points as well as the step between the images to be processed.
The buttons down the right-hand side allow the image
selector to be played, the speed of this preview controlled by the hare and
tortoise buttons. The slider allows the currently visible frame to be dragged
to any time. The Frame
edit box and spin control allow more precise movement of the preview frame. The
and
buttons move to the currently
specified limits for the processing.
The frame numbers for the start and end points may be typed in the From and To edit boxes, and the spacing in the Step edit box. The corresponding time boxes below will be updated automatically.
Clicking the
buttons adjacent to the From or To edit boxes will set the corresponding
from or to position to the current position, shown by the slider and the edit
boxes immediately above (time) and below (frame).
Alternatively (but less precisely), holding <shift> while dragging the slider will allow specification of the timings.
When the From and To times are set, or Step is not unity, then this information is displayed on a yellow background at the top of the image preview.
For files that do not store timing information, the DigiFlow assumes by default that the files are separated in time by one second. This may be changed using In file, in which the image spacing may be specified in either seconds or, using the lower of the two controls, in frames per second. These two controls are disabled for files that store time information, but display the relevant details.
Reset to All resets the start and end points to include the entire selector.
Checking the Default colours control will cause the preview image to be displayed using the DigiFlow default colour scheme rather than the colour scheme stored in the image file.
The Selector Region tab of the Sift dialog allows the user to specify a region within an image selector (§3.4) that will be used for a process.

Figure 12: The standard Selector Region tab of the Sift dialog.
For a process requiring more than one input stream (and hence having more than one image selector in its dialog box), one of the streams (typically the first in the dialog box) will be the master stream. If the region for this stream is changed, then the region for the other (slave) streams will be changed automatically to conform to (typically made the same as) that for the master stream. It remains possible, however, to change independently the region for the slave selectors, provided the size of the region for the slave selector is compatible with that for the master selector.
The type of region is selected by the Region type group of radio buttons. The example shown in figure 12 is for a master selector; the Conform option is not available here, but would be visible above All when sifting slave selectors.
If Pixel window is selected, the pixel coordinates of the left, right, top and bottom of the window may be specified in the edit controls within the black rectangle. If preferred, the size may be increased without shifting the centre of the region, or the location of the region may be changed without adjusting the size, using the Size and Position controls, respectively.
Alternatively, clicking the Draw button opens a full size window that allows the window to be moved and resized dynamically using the mouse (see figure 13). (Hint: it is sometimes worth dragging a corner of the window to increase its size and thus make it easier to grab the edge of the region window.) The Zoom In and Zoom Out buttons may be used to control the magnification while drawing. Similarly, you may swap between this window and the Sift dialog box to use the various edit and spin controls to move the region around. Click on the End Draw… button to close the drawing window and re-enable the other controls on the Sift dialog.


If Named region is selected, then previously saved regions are displayed and may be selected. This provides a convenient method of using the same region in a range of different processes. The four buttons to the right of the list box may be used to manage these named regions. New named regions may be created either by clicking the New button, in which case a subdialog is produced to allow specification of the region, or by clicking the Name button (when Pixel window is selected) to give a name to a pixel window. The Edit button allows alteration of an existing window, while Delete removes the region from the list. Note that selecting a named region that is a Pixel window will update the controls in the Pixel window group. Switching back to Pixel window allows editing of these values, while Name may be used to overwrite the old values with the new ones, or to create a copy.

Quantitative measurements often require that the intensities are matched between different frames and sequences. The intensities of the raw image streams may fluctuate due to a number of reasons. One common one is the mismatch in frequencies between the illumination and the camera frame rate. Depending on the type of light source and the shutter speed of the camera, this mismatch may lead to a modulation of nearly 50% of the signal amplitude, while automatic gain features can lead to similar results. While it is in general best to avoid these problems by using continuous or high frequency light sources, this is not always practical.
The Match Intensity tab in the Sift dialog (figure 15) provides a basic mechanism for correcting the intensities of input image streams to match them to some fixed reference. The basic strategy is for the image to contain two reference regions that contain approximately uniform intensities that should not change with time. These two regions are then used to generate a linear mapping between the input image and a reference intensity, thereby adjusting the intensities in preparation for processing.

Figure 15: The Match Intensities tab provides the ability to directly relate an image to reference values.
The Match Intensity facility is turned on and off using the radio button group in the top-left; .when off (None), then the intensities are read without alteration. The Match Intensity facility can be enabled either using details provided locally (Local), or with details saved previously (Named), in a similar manner to that used for Regions.
A locally defined Match Intensity reference consists of a pair of rectangular regions, Region A and Region B. The location and size of these regions is controlled by a variety of controls for specifying the left, right, top and bottom of each of the rectangles. Additionally, as with the Regions dialog, the regions may be drawn on an image and dragged to their desired location by clicking the Draw… button (see figure 16).
Each region requires an intensity to be associated with it. When Reference from is set to Values, then the Intensity controls in the Region A and Region B groups is enabled. The user may directly enter the desired (target) reference here, or by using File in Match to selector to select a suitable image, then the Match button will read the intensities from the specified image. Alternatively, if Reference from is set to First image, then the reference intensities are not entered at this point, but rather they are determined automatically from the first image in the stream to be processed.
Once the various controls for a Local Match Intensity have been set, their values may be saved for use elsewhere by clicking Name…. This prompts for a user-supplied descriptive name, saves the settings, and switches the dialog into Named mode.
Selecting an entry from Named matches loads the corresponding settings for use. If you wish to alter the settings of a saved match, load it by selecting from the list, then switch to Local mode. Make any necessary changes, then click again on Name to name and save it (you may re-use an existing name).

Figure 16: Drawing regions for intensity matching.
This section describes the various modifications that may be made to the output streams. These modifications are accessed via the Options… button in the output stream select group. The precise contents of this dialog will vary depending on the output file type that has been selected.

Figure 17: The Save Options dialog.
The colour scheme for the output stream is selected from the list of known colour schemes in the Colour scheme list box. Selecting the (input) member will set the colour scheme to be the same as for the master input stream.
If you wish to add a new colour scheme or modify an existing scheme, you must use the View: Colour Scheme… menu option. Refer to §5.3.6 for further details.
For output formats such as .bmp, .png or .jpg that support true colour images, a Full colour checkbox is produced. If checked, then the output is saved as in a 24 bit true colour format. If not checked, then a greyscale version of the output is saved, along with the selected false colour map (the false colour map is not saved for .jpg files).
The File format group invokes various options that may exist for the specified file type. The contents of this group will depend on the file type specified: in many cases there are no options and so the group is left empty.
The Bit depth field determines the number of significant bits saved for each pixel in the image. Most image formats use 8 bits, but for high resolution images, or images that result from numerical computations, a greater depth may be desired. If the .dfi format is specified for the file type, then bit depths of 8, 32 and 64 bits are possible.
When available, the Compression level edit and spin control will determine whether or not the image is to be compressed using a lossless compression. A value of zero indicates no compression, with positive integers giving various levels of compression. Typically compressing an image reduces its size by around a factor of two, but at the cost of slower access (although for a very slow hard disk the access speed may improve with compression). The additional time taken to compress an image will depend in part on the level of compression requested, and in part on the structure of the image. If a process seems particularly slow, but still producing the correct answer, try reducing the level of compression.
In the case of an .avi file, selecting zero causes full, uncompressed images to be saved, whereas setting Compression level to 1 will use the Cinepak compression (installed by default with Windows). For other compressions specify a value of 2 for Compression level which will then cause the standard Windows Video Compression dialog to be produced when DigiFlow is ready to save the first frame of the output stream. (Note that most of the .avi compression options are ‘lossy’ in the sense that only an approximation to each image is saved.)

Figure 18: Standard Windows Video Compression dialog.
For .jpg images, the compression applied is ‘lossy’. The higher the level of compression, the greater the fraction of information lost. This is controlled by the Quality control. Note that in general the lossy nature of the compression in .jpg images means that they should not be used for the storage of intermediate results.
By default, the first image in a sequence produced by DigiFlow will be given a zero index (numerical part of the file name). The First index control may be used to change the index for this first image. In either case, subsequent images will always be produced with unit increments from this value.
When the .dfi image format is selected, it is possible to rescale the output stream before it is saved and then reverse this rescaling when the image is subsequently read in. Typically this option is used to reduce the resolution of the saved image, but maintain its size by interpolating back to the original size before using the image again.
This feature is enabled using the Resample check box. When enabled, the resolution of the saved image is controlled by the Factor edit control which accepts a floating point value for the relative resolution of the saved image. For example, a value of 0.5 will cause the saved image to have only Ľ of the number of pixels of the original in the file, but through interpolation the missing pixels are reconstructed when the image is read in again. This option is particularly valuable for use with images produced by the synthetic schlieren (§5.6.4.3) and PIV (§5.6.5.2) facilities.

Some file formats (e.g. .dfi, .dfd and .dft) allow user comments to be saved along with the images. These comments are specified using the User Comments tab of the Save Options dialog.
DigiFlow can produce Encapsulated PostScript (.eps) output either using the Export to EPS option in the File menu (see §5.1.10) or by specifying an .eps file as the output stream. In the latter case the normal Options dialog has an additional EPS button that invokes the dialog shown in figure 20.

Figure 20: The output options for Encapsulated PostScript (.eps) files.
The PostScript options provide the ability to add a title either above (Top) or below (Bottom) the image or graphic output, and to add a frame (Frame) around the output. DigiFlow (commercial version only) provides support for the LaTeX \psfrag macro package. This enables the text produced by DigiFlow to be readily replaced with text generated by LaTeX, thus keeping font and style information consistenet and allowing post-plotting adjustment of the text labels, etc. Selecting Normal produces the eps containing the original labels, whereas with either of the PSFrag options the text is replaced by a unique character for each element. At the same time, DigiFlow creates a .tex file that contains the mapping between these characters and the original text. This .tex file can then be embedded in included in the main LaTeX document to reproduce the figure. See §5.1.10 for further information on the Encapsulated PostScript formatting options.
As will be seen in §5, a large part of
DigiFlow’s power and flexibility is gained by the use of user-supplied macro
code. This code is known as dfc
code. Examples of facilities that require such code include Analyse: Time: Extract (§5.6.1.5), Analyse: Time: Summarise (§5.6.1.6), Tools: Transform Intensity (§5.7.2) and Tools: Combine Images (§5.7.3). Details of the macro code itself are given
in §§8 and 9.
However, this manual gives only a relatively brief introduction to a subset of
the dfc functions
available within DigiFlow. Instead, the bulk of the documentation is provided
within an interactive help facility available from within DigiFlow itself in
the Help: dfc Functions
menu item, and from the
button within dialogs where such information
is of value.
The help facility takes the form of the dialog illustrated in figure 21. To find a function performing a given task, simply type some information about that task into the Search for box. For example, if you want to find functions that have something to do with drawing, enter “draw”. You will notice that as you enter “draw”, the Look up list changes as each letter is typed. When you type the “d”, the size of the items in the list is reduced so that it only includes those with a “d” somewhere in their names. Similarly, “dr” leads to a further reduction, excluding those that do not have this pattern, and so on.
Spaces in the Search for box are interpreted as “and” criteria for the search. For example, entering “dr ma” would reduce the list to those functions with both “dr” and “ma” in their names, but without the two patterns needing to be adjacent. This, combined with the logical and descriptive (if somewhat verbose) naming conventions for DigiFlow functions, provides a very powerful search facility.
At all stages the Look up list is sorted alphabetically. (Note that if Search for is left blank, then Look up contains all possible functions.)
Selecting an item in the Look up list then brings up the documentation for the function in the three boxes below. The top of these identifies the role played by the entry within dfc code. The list box below gives the range of possible entry points to the function. As we shall see later, many DigiFlow functions are “overloaded” (i.e. they accept more than one type of data), and may have optional parameters. This list itemises the full range of possibilities. Selecting an entry point from this list and clicking the Copy button copies this entry point into the clipboard.
The bottom control on the dialog provides the detailed
documentation for the selected function. This documentation should be read in
conjunction with the entry point documentation. The help system is hyperlinked
(e.g. draw_start(..) in figure 21): clicking on a hyperlink will take you to the
corresponding help. Similarly, backward (
) and forward (
) buttons will move through
previously selected hyperlinks.
The General items list box provides access to more general information, such as modifiers for input and output streams, recent changes to DigiFlow, how to return images from code specified for tools such as Transform intenstiy, and how to produce simple plots.

Figure 21: The help dialog for dfc code.
The help facility may also be started from within a code edit box by right-clicking. Doing so will cause the word under the cursor to be pre-loaded into Search for field. Moreover, if that word is a known DigiFlow command, the details will be looked up automatically.
DigiFlow incorporates a number of features that will facilitate the re-use of the dfc code used in facilities such as Analyse: Time: Extract (§5.6.1.5), Analyse: Time: Summarise (§5.6.1.6), Tools: Transform Intensity (§5.7.2) and Tools: Combine Images (§5.7.3). This section describes the DigiFlow Code Library. Details of the macro code itself are given in §§8 and 9.
The dfc Code Library provides convenient method of storing and retrieving user-developed code. The library itself is stored in a file named DigiFlow_Library.dfs in the directory in which DigiFlow is started. Note that this file is re-read from the current directory every time the Code Library is invoked. The DigiFlow_Library.dfs file may be copied from one directory to another, if the user desires.
The library is accessed via the
Code Library button in appropriate
dialogs. Central to the Code Library dialog, shown in figure 22, is the Entry list that itemises all previously
saved items of code for this DigiFlow facility (a separate list is maintained
within the same file for each different facility). Any code currently specified
in the parent dialog box is recorded under the _current key; this will be the default
selection upon entry.
To retrieve a previously stored code item, simply select it from the Entry list and click OK to insert it in the parent dialog. The Code edit box will show the code, while Description will show any previously saved description. Clicking Cancel will return to the parent dialog without changing the code in that dialog.

Figure 22: The code library dialog.
The Code
and Description
may be edited before returning to the parent dialog. The Process list allows code to be selected
from different processes. The Delete
button may be used to remove an entry from the Code Library, and the
button gains
access to the dfc
Help facility. Finally, the Save
As button allows code to be saved into the data base (see figure 23) under any of the processes.

Figure 23: Name under which a Code Library entry is to be saved.
This section describes the main menu options. Some of these will be familiar as they follow standard Windows conventions, whereas others are specific to DigiFlow. Many of these menu options can be strung together to create processes that are more complex. Details of how to achieve this are given in §6.
Allows an image selector (§3.4) to be opened for viewing. The image is selected through the Open Image dialog box (§4.1). Both images and drawing formats may be opened. Encapsulated PostScript (.eps) may also be opened if DigiFlow is able to find an installed copy of GhostScript (see §2.2.2).
Opens and runs a DigiFlow dfc macro. Refer to §10 for further details.
This option allows the contents of the active window to be saved. Note that if the active window contains a sequence or other collection of images, only the currently displayed image will be saved. To copy an entire sequence use File Edit stream (see §5.1.5) or one of the related transformation tools.
This option creates a new window and streams live video directly to it. Whilst the live view is intended primarily for previewing camera output, it may be used in conjunction with macros such as camera_grab(..) to acquire single or multiple frames, or with camera_capture_file(..), camera_start_capture and camera_stop_capture(..) to acquire entire sequences.

Figure 24: The dialog controlling what is seen in a live video window.
Video captured using this option is fed continuously to the display until stopped by the user; it is not saved to hard disk (except via the use of dfc code). For this reason, no duration can be specified. For some cameras, it is possible to set the shutter speed (Shutter, in frames per second; n frames per second is equivalent to a shutter speed of 1/n seconds) independently of the acquisition rate (set by Capture, in frames per second). However, many digital cameras force the two rates to be equal. For some supported CameraLink cameras, the Shutter speed and camera Gain can be set as integer indices into the range of possible values. The meaning and acceptable range of values varies between different makes and models of cameras. (Note that a value of zero indicates unit gain on some cameras, but on others, such as the UniqVision UP1830CL, unit gain corresponds to a value of 128. The default value is obtained from the entry for a specific camera in DigiFlow_Cameras.dfc.)
The frame rate for updating the display is independent of the shutter and capture rates. Typically Display is set to a lower frame rate (there is little point exceeding around 12 frames per second). Any necessary processing of the incoming data stream to correct the format is undertaken automatically.
The Display resolution group controls how much of the original image being captured by the framegrabber will be displayed on the screen (note that this does not affect the data available through dfc functions such as camera_grab(..)). The meaning of the various options is self-explanatory.
In some cases, simple real-time processing of the image prior to display will greatly assist with the setting up and running of the experiment. The Display processing group controls the type of processing that will be done. These are described in more detail for the Capture Video option in §5.1.4.2. To suppress processing, select none from the list box. For large images, it may be best to use Display resolution to reduce the resolution and thus the computational burden of undertaking any processing.
The Tools: Slave Process family of functions (see §5.7.5) provides a convenient way of accessing an even broader range of additional functionality, ranging from focusing tools to real-time optical flow calculation.
If Display processing is set to particle streaks then the dialog shown in figure 25 is displayed to provide processing of display output while at the same time capturing the raw video to a file. There are four display options: Threshold, Maximum, Minimum and Direct.
For Threshold the incoming image is segmented into particles (bright points) and background (dark points) by varying the Threshold control. Using relatively simple processing, the particles so identified may be converted into comet-like streaks that slowly fade with time. The length (in time) of these streaks is determined by the Length control.
The Maximum and Minimum options work in a similar way except that rather than segmenting the incoming image, the brighter (Maximum) or dimmer (Minimum) of the incoming and stored images is used. Again the length of the streaks can be set using the Length control.
When Direct is selected, then the incoming images are displayed without any further processing.
The Reset button clears the display of all earlier times.

Figure 25: Particle streaks preview dialog.
The rate at which the screen is refreshed is set by Display fps. Note, however, that the desired rate may not be achieved if the computational load is too great.
The Display step group of controls is used to aid the viewing of very large images that may be larger than the available display area. The edit and spin controls set the step between displayed pixels (hence a value of 2, for example, will give a half-resolution image). The grid of buttons in the bottom left allows the view port into a larger image to be moved around in a manner that is efficient to display. These options are only enabled if the Window option in the Live Video dialog is checked.
If Display processing is set to synthetic schlieren then the dialog shown in figure 26 is displayed to provide processing of display output while at the same time capturing the raw video to a file. This allows real time visualisation of a synthetic schlieren image (see §5.6.4). There are three processing options: Difference is the simplest (and computationally fastest) technique that provides a qualitative output proportional to the magnitude of the gradient in the density perturbation. The Horizontal gradient and Vertical gradient options perform more a more sophisticated analysis that returns a semi-quantitative output of the specified component of the gradient in the density perturbation. Note that these two options distinguish between positive and negative gradients.

Figure 26: Synthetic schlieren preview dialog.
The Gain control determines the relationship between the gradient and the intensity of the display. The Reset button forces the reference image to be recaptured.
The rate at which the screen is refreshed is set by Display fps. Note, however, that the desired rate may not be achieved if the computational load is too great. The Direct button turns off the streaks processing and displays directly the camera input.
The Display step group of controls is used to aid the viewing of very large images that may be larger than the available display area. The edit and spin controls set the step between displayed pixels (hence a value of 2, for example, will give a half-resolution image). The grid of buttons in the bottom left allows the view port into a larger image to be moved around in a manner that is efficient to display. These options are only enabled if the Window option in the Live Video dialog is checked.
Using this facility, a video sequence may be captured from one of the digital video cameras supported by DigiFlow.

Figure 27: Dialog box controlling the capture of video.
The basic timing for the video sequence is controlled by a combination of the Duration and Frame Rates groups. The first of these sets the length of the sequence, either as a specified number of frames (if Number selected), or as time in seconds (Time selected). For some cameras, it is possible to set the shutter speed (Shutter, in frames per second; n frames per second is equivalent to a shutter speed of 1/n seconds) independently of the acquisition rate (set by Capture, in frames per second). By checking Shutter = capture, then the two of these are forced to be equal. For some supported CameraLink cameras, the Shutter speed and camera Gain can be set as integer indices into the range of possible values. The meaning and acceptable range of values varies between different makes and models of cameras. (Note that a value of zero indicates unit gain on some cameras, but on others, such as the UniqVision UP1830CL, unit gain corresponds to a value of 128.)
The frame rate for updating the display is independent of the capture rate. Typically Display is set to a lower frame rate (there is little point exceeding around 12 frames per second). This setting does not affect the data stored to disk. For some systems the bandwidth requirements of displaying the image while acquiring to hard disk exceeds that available. In such cases the Display during capture check box should be cleared, thus suppressing the display during the capture, although the display is still updated before capture begins and after capture finishes.
For some camera and framegrabber combinations, the raw data coming from the framegrabber may not be in the correct format for display. This typically occurs with multi-tap cameras; most single-tap cameras produce data in the correct format and require no additional processing. If additional processing is required, the Preprocess frame group determines what should be done in this situation. The Untangle option forces the data to be untangled before displaying or saving to hard disk. This option is the most processor and memory bandwidth intensive, and so may not function adequately on all systems, especially during the capture process when much of the bandwidth is already taken up. To overcome this, the Fast acquire option untangles the images before and after the capture process, thus giving an intelligible preview, but turns off the untangling during the capture. DigiFlow will automatically untangle the image subsequently when it reads the image file produced in this manner. The remaining option, None, turns off all processing.
The Display resolution group controls how much of the original image being captured by the framegrabber will be displayed on the screen (note that this does not affect the data stored to disk). The meaning of the various options is self-explanatory.
In some cases, simple real-time processing of the image prior to display will greatly assist with the setting up and running of the experiment. The Display processing group controls the type of processing that will be done. Note that this does not affect the data written to disk. To suppress processing, select none from the list box. For large images, it may be best to use Display resolution to reduce the resolution and thus the computational burden of undertaking any processing.
The Output group provides a standard interface to select the destination for the captured image. However, by default DigiFlow will be configured to always capture to a fixed location (see §13 for details) to avoid the user having to select a disk drive with appropriate characteristics and to force the user to go through a compulsory review process to extract only those parts of the image stream that are of value. If this feature is enabled, then the Output group will be disabled (the file name CaptureVideo.dfm will be visible) and following completion of the sequence capture, the Edit Stream dialog (see §5.1.5) will be started automatically to control this second step.
If you do not want to capture the entire field of view of the camera then you may choose the region you wish to save through the Region list. The region must have been defined within DigiFlow previously (e.g. using Edit: Regions; see §5.2.6, or as part of a Sift operation). Note that there is a time overhead in extracting a region from an image. Consequently, although the amount of data to be stored is reduced, the total time taken may be increased in some circumstances. However, if the region to be saved is more than around 20% smaller than the full view, then it could well be worth capturing a more limited region.
After pressing OK, DigiFlow opens an image preview, creates a Display processing dialog (see below) if display processing was selected, and then prompts the user to start the acquisition as illustrated in figure 28.

Figure 28: Message box starting the video capture.
After the sequence capture has finished, the performance is displayed in a message box, such as shown in figure 29. The precise text in the message box will depend on whether or not the compulsory review feature is enabled. Note that the ‘achieved’ timings may not be precise, especially for relatively short sequences.

Figure 29: Message box at end of video capture.
If the computer fails to keep up with the bandwidth requirements of the capture process, then this will be indicated by there being some missed frames, and a lower than expected frame rate being achieved. The amount of CPU time required is a strong function of any display processing required. The synthetic schlieren option was selected for the example illustrated in figure 29. This was performed on a 1GHz dual processor machine. Clearly more CPU time was required than the capture time, but each processor was busy only around 60% of the time. A single processor machine, however, would not have managed to keep up with the bandwidth requirements.
This menu item controls the configuration of the cache file used when DigiFlow is capturing a digital video sequence directly from an attached camera. As noted in §2.3.4, it is important that the cache file is located on a disk other than that containing the operating system, and that the capture file is in a single large contiguous block, rather than many fragments scattered over the disk. Typically, the disk drive will only be able to keep up with the camera if the drive can devote all its time to writing the video data. This will not be the case if there is other disk activity occurring for that drive (as would be the case if it contained the operating system), or if the heads of disk drive have to continually move backwards and forwards across the disk as would occur if the file becomes fragmented.
Ideally, this menu item will be run when the capture disk is empty (e.g. following a reformat of the disk) or at least nearly so. By default the disk should be assigned the drive letter V: (either through the Disk Manager or by net use V: … onto a share) and the directory V:\Cache should be created before running File: Live Video: Setup. (Details on how to change the name or location of the cache file may be found in 13.2.)

Figure 30: Configuration of the cache file for capturing video sequences.
Figure 30 shows the dialog that is produced. It is recommended that the default size of 50GB is used. While this may seem excessively large, if you make the file too small you may need to offload all your data and reformat the hard disk to be able to create a single large contiguous file at a later stage.
Note that if DigiFlow detects an existing V:\Cache\CaptureVideo.dfm, then this dialog will not be produced. DigiFlow does not provide a mechanism for you to remove or change the size of the cache file. If you must change the size, then you should delete it from Windows Explorer then run File: Live Video: Setup again. Note, however, that doing so may lead to fragmentation of this file, which may in turn prevent the hard disks from keeping up with the bandwidth from the camera.
This option provides efficient editing of a single video stream.

Figure 31: The Edit Stream dialog for editing a single video stream.
Parts of the Source Stream are copied to the Edited Stream; the parts to be copied are determined by the Sift button (see §4.3). Typically this is used to change image file format, reduce the time period, select only specific frames, and/or extract a subregion of the input stream. Note: if you do not click the Sift button when setting up the input stream, then DigiFlow might prompt you by starting up the sift dialog itself if it detects no or minimal changes are to be applied during the editing process.
The Input from capture cache check box disables the File and Process buttons, connecting instead the input to the capture cache file (see §5.1.4.2), allowing you to extract additional sequences from the cache file, if desired.
This option allows two video streams to be merged into a single stream to provide an extended sequence.

Figure 32: The Merge Streams dialog for combining image streams sequentially.
Two input selectors are provided: First and Second. These are written to the Output selector in the order suggested by their names. The timings of the two input selectors need not correspond, but the regions must conform. The First selector is the master, dictating the region to be used.
This option provides an efficient mechanism for exporting a sequence of images, drawings or a DigiFlow movie to a standard Windows AVI movie file.

Figure 33: The Export AVI dialog.
The dialog consists of a single input and a single output selector. The latter should be directed to an .avi file. The playback speed of the resulting .avi file is set by Frame rate, while Rescale allows the input image to be rescaled (typically reduced in size) before copying to the movie. If Compress is not checked, then the full raw data is saved to the .avi file. If Compress is checked, then the type of compression is determined by the list box to the right. Only a subset of the compressions methods available are listed explicitly in this box. However, specifying (ask) will cause DigiFlow to prompt the user with the complete range of methods available at the point where DigiFlow is ready to save the first image in the output stream (i.e. the user will be prompted after OK has been clicked; see figure 34).

Figure 34: Compression options when exporting to an .avi file.
Print out the currently selected viewing window. The menu version of this facility produces a dialog box allowing the user to select the printer, whereas the toolbar version simply prints to the currently selected printer.
This command is the same as File: Print View (see §5.1.8) except that only the currently visible part of the view is printed.
Converts the currently selected viewing window into an Encapsulated PostScript (.eps) file. Section 2.2.2 describes how to set up an .eps printer driver that allows both bit image and vector graphics to be converted to .eps format. If the .eps printer is not set up, then DigiFlow will convert vector graphics to a bit image before generating the .eps file.
When using the printer driver, not only can the user specify the name of the output file (figure 35a), but some control over the format is also provided (figure 35b). In particular, a title may be added either above or below the figure, and the figure may be given a frame. Further, using the Text filter group, it is possible to suppress all text on a figure, or to replace each element of text with a unique letter combination. These text filtering options are provided for convenience with manuscript submissions where some journals wish all text removed from figures, while others use systems such as the LaTeX \psfrag package to replace the original text and fonts. Selecting Normal produces the eps containing the original labels, whereas with either of the PSFrag options the text is replaced by a unique character for each element. At the same time, DigiFlow creates a .tex file that contains the mapping between these characters and the original text. This .tex file can then be embedded in included in the main LaTeX document to reproduce the figure.

Figure 35: The dialogs controlling the saving and formatting of the exported eps file.
For example, when the drawing shown in figure 36a is exported, all the text is replaced by single characters. Close inspection shows that these characters appear to be positioned incorrectly, but this is necessary to resolve differences between the way Windows positions characters, and the way psfrag determines their positioning from the eps file.

(a) (b)
Figure 36: Example of exporting a drawing through psfrag with the PSFrag (new sytle) option. (a) Before exporting. (b) The resulting eps file.
At the same time as producing the eps file, DigiFlow also generates the following LaTeX file that contains a psfrag wrapper:
\begin{figure}
\psfrag{a}[cc][Bl]{$0.0$}
\psfrag{b}[cc][Bl]{$10.0$}
\psfrag{c}[cc][Bl]{$20.0$}
\psfrag{d}[cc][Bl]{$30.0$}
\psfrag{e}[cc][Bl]{$40.0$}
\psfrag{f}[cc][Bl]{$50.0$}
\psfrag{g}[cc][Bl]{$60.0$}
\psfrag{h}[cc][Bl]{$x$}
\psfrag{i}[cr][Bl]{$0.0$}
\psfrag{j}[cr][Bl]{$5.0$}
\psfrag{k}[cr][Bl]{$10.0$}
\psfrag{l}[cr][Bl]{$15.0$}
\psfrag{m}[cr][Bl]{$20.0$}
\psfrag{n}[cr][Bl]{$25.0$}
\psfrag{o}[cr][Bl]{$30.0$}
\psfrag{p}[cr][Bl]{$35.0$}
\psfrag{q}[cr][Bl]{$40.0$}
\psfrag{r}[cr][Bl]{$45.0$}
\psfrag{s}[Bc][Bl]{$y$}
\psfrag{t}[Bc][Bl]{$-0.1$}
\psfrag{u}[Bc][Bl]{$0$}
\psfrag{v}[Bc][Bl]{$ 0.1$}
\psfrag{w}[Bc][Bl]{$T'$}
\includegraphics{junk2.eps}
\end{figure}
Each of the \psfrag{..}[..][..]{..} statements gives the letter code, the required alignment relative to the point specified in the eps file, how the point specified in the eps file relates to the character rendered in the eps file, and finally the text to be typese in place of the letter code. Due to incompatibilities between Windows and psfrag, it is necessary for DigiFlow to position the characters in the eps file above and to the right of the reference point or else confusion arises in the height and width of the string. Thus each of the entries has [Bl] as the second of the positioning codes. The LaTeX text, however, is rendered in the correct place via the first of the positioning codes, as illustrated in figure 37a, although if there is a change in the size of the font some further adjustments may be necessary to improve the spacing between some elements. Here, for example, the font size has been increased and the x axis and y axis titles would look better if they were moved away from the axes. This may be achieved, for example, by adding \raisebox(..)(..) in the above example. In particular,
\psfrag{h}[tc][Bl]{\raisebox{-10 pt}{$x$}}
\psfrag{s}[Bc][Bl]{\raisebox{5pt}{$y$}}


(a) (b)
Figure 37: LaTeX output using automatically generated psfrag replacements. (a) Straight from the LaTeX generated by DigiFlow. (b) After small adjustments to the positions of the x and y axis labels.
Such adjustments are less frequently necessary if the original graphic is produced with text of much the same size as will be used in the final version. With DigiFlow drawings, this may be achieved readily by including a call to draw_set_base_scales(..) near the start of the drawing.
Note that .eps files may also be specified for the output stream from most of DigiFlow’s menu options. If this is done, then the dialog in figure 35b replaces that normally produced by the Options button.
Some journals require the figures to be complete as .eps files rather than relying on \psfrag within the LaTeX. This does not prevent you, however, from using \psfrag in their production. The following process allows you to process the text with LaTex and end up with a stand-alone .eps file.
1. 1. Include the graphic plus all the psfrag commands in a LaTeX file with \thispagestyle{empty}. Probably best if standard PostScript fonts are used, so have something like:
\documentclass{article}
\usepackage{psfrag}
\usepackage{mathptmx} % PostScript fonts
\usepackage[T1]{fontenc}
\thispagestyle{empty}
\begin{document}
\input{myfig} % The figure in myfig.tex
\end{document}
2. Compile to create the .dvi and .ps, as normal. The output should all be on a single page.
3. Open the output .ps with GhostView. Select PS to EPS from the File menu. Select Automatically calculate BoundingBox, give the file a name (e.g. myfig.eps) and save.
4. Check that the myfig.eps can be read OK and has the correct bounding box.
This command is equivalent to File: Export to EPS (see §5.1.10) except that only the currently visible part of the view is used to generate Encapsulated PostScript.
The standard method of generating PostScript, described in §5.1.10, utilises a Windows printer driver to make the conversion. Vector graphics remain as vectors, while raster images remain as rasters. However, the Encapsulated PostScript produced tends to be cumbersome. Occasionally, Encapsulated PostScript with a simpler structure is desired. The present Export to simple EPS option does not utilise the Windows printer driver, but generates the Encapsulated PostScript directly. The big limitation of this option, however, is that it only produces raster formatted files. If applied to vector drawings, then these are first converted to a raster format.
Close the active window. This is equivalent to clicking on the close button ý at the top right corner of the document window.
Close all open views.
Closes DigiFlow and all open image windows. This is equivalent to clicking on the close button ý at the top right corner of the main DigiFlow window. If DigiFlow detects that any processes are currently running then it will prompt the user to ensure DigiFlow should still be closed as this will terminate those processes.
Copies the currently selected image or drawing to the system clipboard. The image or drawing is available to other applications in both raster and metafile formats.
Copies the currently selected image or drawing to the system clipboard, placing it there as a bitmap regardless of its initial form.
Provides a group of options that allow images to be copied to the clipboard at a size that differs from the full resolution image.
Copies the currently selected image to the system clipboard, doubling the size of the image using bicubic interpolation, where appropriate.
Identical to Edit Copy (§5.2.1). Copies the currently selected image to the system clipboard, doubling the size of the image using bicubic interpolation, where appropriate.
Copies the currently selected image to the system clipboard, halving the size of the image first.
Copies the currently selected image to the system clipboard, reducing the linear resolution of the image by a factor of three.
Copies the currently selected image to the system clipboard, reducing the linear resolution of the image by a factor of four.
Copies the currently selected image to the system clipboard, adjusting the resolution using a user-specified factor (see figure 38).

Figure 38: Dialog selecting scale factor for image to be placed on clipboard.
Displays the properties for the selected window.

Figure 39: Process that created the image.
The Process tab contains comments supplied by the user at the time when the image was created. Note that this tab is only available when the image is supplied by a file format that supports the storage of this information. The contents here is exactly that that invoked the command (either interactively or from a dfc macro).

The Notes tab contains comments supplied by the user at the time when the image was created. Note that this tab is only available when the image is supplied by a file format that supports comments.

The Format tab contains information describing the format of the image. This information is available for all image types.
Provides the ability to define, edit and delete coordinate systems providing a mapping between the pixel coordinates of an image and some user-defined coordinate system.
Note that once defined, the coordinate system is stored in the DigiFlow_Status.dfs file in the directory from which DigiFlow was started. This file uses the standard dfc syntax but is run automatically upon starting DigiFlow. In some cases you may wish to make a copy of the relevant part of the coordinate system for backup purposes.

Figure 42: Selection of coordinate system.
The top-level dialog provides the ability to select the active coordinate system for the current window by clicking on the desired entry in the list box, or to make changes to the available coordinates.
The Edit, New and Copy buttons are used to adjust an existing coordinate system, create a new coordinate system, or create a copy of an existing coordinate system (respectively). A more complete description of these buttons is given below. The Delete button will remove the currently selected coordinate system from DigiFlow, while Make Default will register the selected system as the default for other operations.
Note: details of all coordinate systems defined, and which system is the current default, are stored in the DigiFlow_Status.dfs file located in the directory from which you started DigiFlow. These details are local to instances of DigiFlow started from that directory, although you may either copy the DigiFlow_Status.dfs file to another directory, or open it in an editor and extract the details of the coordinate system for use in a dfc macro. Refer to §
To create a new coordinate system, click on New. This starts a dialog allowing the name, type and units of the new coordinate system to be specified.

Figure 43: Give a name and type to the new coordinate system.
The Name of the coordinate system is arbitrary. The user should select a name that is meaningful to the task at hand. This name will subsequently be used for identifying the coordinate system. The Units are also arbitrary. They may refer to some standard measure of length, or to a dimensionless unit. The name of these units is recorded for later use in captions, titles, etc.
There are three possible types of coordinate system that may be specified. Pixel coordinates have a one to one correspondence with the pixels in the image and are the least flexible.
Function coordinates have a user-specified mapping between the pixel and user coordinates. This form of mapping is the most precise, but will only be of use where there is some external method of determining the required mapping functions. Four functions are required, separated by semicolons. The first two functions give the world x and y coordinates as functions of the pixel coordinates i and j, while the third and fourth give the pixel coordinates as functions of the world coordinates.
Mapping coordinates are generally the most useful. These systems are specified through a combination of mapping functions and identification points where both the pixel and user coordinates are known. A least squares mapping is then used to generate the unknown coefficients in the mapping functions and complete the transformation. There are a number of pre-defined mapping functions, or the user may specify their own. The format of the mapping function specification is an arbitrary name followed by a colon then a list of basis functions, each separated by a semicolon and expressed in terms of the generalised coordinates x and y, and optionally the time t. The points defining the unknown coefficients are specified using the Edit button of the parent dialog.
The Edit button starts a dialog that may be used to edit the Units and Mapping functions for the coordinate system. As noted above, the coordinate system may also be time dependent, in which case Use Time-dependent Mapping should be checked and the points defining the coordinate system should span both space and time.

Figure 44: Editing coordinate systems.
To specify the points used for the mapping, the Edit Points button should be clicked, which will allow the user to specify points in the window that was active before entering the coordinate system dialogs. At the same time a modeless dialog box, which should be used to indicate the specification of the points is complete, is started.
Coordinate points are specified within the window by clicking at the desired location. This places a plus mark (+) at the position. The plus mark may then be dragged to a new location, if desired. Double-clicking the plus mark activates a dialog for specifying the user coordinates for this point.

Figure 45: World coordinates for a point when defining a coordinate system.
This dialog gives the current Pixel Position of the point (and allows this to be edited), and provides the ability for the user coordinates to be defined in the World Position group. If a time-dependent mapping were specified, then the Time for this point must also be specified.
Clicking Delete will remove the point, while checking Lock will prevent the point being dragged around the image accidentally.

Figure 46: Indicate that you have finished editing the coordinate system markers.
When you have finished adding and/or editing the coordinate system markers, click the Finished button in the dialog shown in figure 46.
The Copy button provides the ability to make a copy of an existing coordinate system.

Figure 47: Copy a coordinate system.
As an alternative to manually defining a coordinate system as outlined in the above subsections, DigiFlow provides a wizard for this purpose. This wizard, Wizard_CoordSystem.dfc, takes the form of a dfc macro and can be found in the folder in which DigiFlow is installed. The purpose of the wizard is to take an image of a regular grid of features, location the features and form a coordinate system from them.
One way of forming the grid of regular features is to use one of the CoordinateSystemGrid_*.pdf files found in the DigiFlow installation folder. When printing these out, make sure they are printed at the correct scale rather than ‘shrink to fit’! These grids, constructed from the following PostScript segment, can readily be printed out on paper or overhead transparency and placed in the flow. (It may be necessary to laminate a paper grid!)
%!PS-Adobe-3.0
% Select paper size (e.g. a4 or a2)
a4
/inch {72 mul} def
/mm { 25.4 div inch } def
% Make all subsequent measurements in mm
1 mm dup scale
% Set the spacing of the features
/FeatureSpacing 10 def
/radius 0.75 def
% Page size: can be much bigger than the actual page size!
/Width 1000 def
/Height 1000 def
0 setgray % Make black
0 FeatureSpacing Height
{/y exch def
0 FeatureSpacing Width
{/x exch def
x y radius
0 360 arc
closepath % make sure start and end are connected
fill}
for}
for
# Set the number of identical copies you want and print
/#pages 1 def
showpage
%%EOF
Figure 48 shows such an image captured from such a coordinate system grid. Here the grid was printed with features spaced at 20mm on an A2 format with the subsequent pages laminated and then carefully taped together. Once you have an image of your grid, simply start the wizard and it will lead you step-by-step through the definition of your coordinate system. Note, however, that the wizard requires the actual coordinate system to be closely aligned with the pixels and that the mapping required for the coordinate system is close to linear.

Figure 48: Image of coordinate system grid used with the Coordinate System Wizard.
In most cases the creation and modification of regions is handled as part of the sifting process started with the Sift button when specifying an input image stream, as described in §4.3.2. In some cases, however, it may be desirable to specify a region independently from processing any images (e.g. creating a region used during the capture of live video, as seen in §5.1.4.2). Selecting Edit: Region will start up a dialog containing only the Regions tab from the normal Sift dialog, as shown in figure 49. The only point in invoking this is to look at, define or modify a named region. The only lasting effect of this dialog is any changes in the definition(s) of named regions.

Figure 49: The Region tab from the Sift dialog is produced in response to Edit: Dialog.
Users often wish to reprocess an image, perhaps making minor changes to the control settings, or maybe to apply the same process to a different set of images. The Process again facility provides a convenient method for doing this.
To use this feature, simply open the image for which you wish to replicate the process, and click on the Process again button (or select from the Edit menu). DigiFlow will then recover the process settings from the image and, where possible, use them to initialise the dialog that was initially used to create the image.
Note that this feature only works with DigiFlow-specific formats such as .dfi, .dfd or .dft files as other formats do not provide an appropriate mechanism for storing the settings used to create the image.
The purpose of this facility is to provide an aid for those trying to create dfc files (see §8) to run processes, and to provide an alternative user interface to many of the DigiFlow processing facilities.

Figure 50: The Dialog Responses dialog that contains details of the responses corresponding to the latest invocations of the dialogs.
The Process list box indicates the dialog for which responses are required. This list is empty when DigiFlow is first started in a directory, but gradually fills as more DigiFlow features are used. Upon exit from DigiFlow, all this information is saved in the DigiFlow_Dialogs.dfs file that is created in the DigiFlow start directory.
Selecting a dialog from the Process list causes the corresponding response lines to be displayed in the Response variables edit box on the left-hand side of the dialog. Note that the entries in this edit control are always displayed in alphabetical order, and the list will only contain assignment statements. Entries in the edit box may be edited, selected, copied, etc., as is standard for edit boxes. Users may find it useful to copy the contents of this edit box to .dfc files they are creating.
If the responses variables are edited, then they may be saved by clicking Save; alternatively Reset restores them to their previous values. The user will also be prompted to save any alterations if a different dialog is selected from the list.
The corresponding dialog may be started (e.g. to provide updated values) by clicking the Dialog button, while clicking Execute will cause the corresponding process to be started.
The dfcConsole provides an interactive tool for writing, editing and debugging dfc macro code.

Figure 51: The dfcConsole dialog is resizable.
This resizable window contains an edit control allowing interactive editing of the dfc code to be run, alongside a series of controls allowing control over the execution environment and providing timely information.
The main window (top left) in the dfcConsole allows interactive editing of dfc code. Syntax is colourised and, matching parentheses, braces and square brackets are highlighted as they are entered (or when the <shift> key is depressed adjacent to a bracket). The buttons in the Code group down the right-hand side provide the basic editing functionality in conjunction with standard short cuts such as ctrl+Z for undo (or shift+ctrl+Z for redo).
The Execute group may be used to selectively execute code. If there is no text selected, then Line(s) will execute the current line. If there is an active selection, then Selection will execute the selected code, and Line(s) will execute not only the selected text, but all the lines on which some text is selected. Regardless of the selection, All will cause the entire code to be executed. If Auto reset is checked, then using All will first discard any existing variables, etc., from the interpreter. Note that <alt><enter> is equivalent to clicking Line(s).
Most of the control buttons are disabled while the code is
executing. Amongst the exceptions are the stop
and pause
buttons. Clicking the stop button
will abort the
currently executing code, while the pause button
will temporarily suspend
execution. When toggled, the
will cause the line currently being executed
to be displayed regularly (at intervals of about 1s) in the bottom-left control
of the console. If not toggled, then the
button will cause the line currently being
executed to be displayed when it is clicked. Checking Breaks (&) causes break points,
indicated by an ampersand in the code (see §8.12.5)
to be executed as and when they are found by the interpreter. If cleared, then
the break points are ignored. Note that the status of the Breaks (&) control may be changed by
the user as the dfc
program runs.
The Interpreter group controls the internal state of the DigiFlow interpreter. Reset will clear all variables and functions from the interpreter, while View displays the variables and objects defined within the interpreter using the view_variables(..) interface. If an error occurs, then Last Error will redisplay the last error message.
Below the code window is a documentation window. When
DigiFlow detects a function name under the cursor in the code window then it
will display the documentation for this function. This documentation (which is
also accessible through the dfc
help facility) is hyperlinked to aid navigation. Standard forward and back
navigation buttons are provided to the right of the window. A given help topic
may be pinned (or unpinned) using
, or by double tapping the <alt> key on
the keyboard. Double-clicking on a line from within the documentation window
will cause the corresponding text (e.g. the definition of the entry
point for a function) to be inserted at the cursor in the main edit window.
The two windows at the bottom of the dfcConsole provide information about the contents of variables. When the cursor is on a variable name, and that variable has a defined value (typically the result of executing part of the code), then a summary of its contents will be displayed in the left-hand window.
The bottom right-hand window serves two separate functions. As the user types in code, a list of possible corresponding function names will be shown in this window. Double-clicking on any of the entries in the list will cause the corresponding help text to be displayed in the documentation window. This provides a convenient method of determining the name and usage of the most appropriate function if you do not know its name in advance. At run-time the bottom right-hand window takes on a different role and displays the output resulting from a Query (see §8.12.4 for further details). The Show button in the Queries group may be used to switch between the possible function list and the query output whilst editing code.
Standard file open
and save
buttons are provided to handle dfc code, along with
a dedicated button
to reopen the last dfc code edited. The dfcConsole will automatically reopen the
last code edited if it did not complete cleanly its execution, and also saves
snapshots of the code prior to execution, etc., in DlgResponses.log.
The search facility is provided by a group of three buttons,
,
and
, that search
forwards or backwards for, or highlight all the text that matches that in the
edit box beneath the buttons. Cut (ctrl+X or
), copy (ctrl+C or
) and paste (ctrl+V or
) operate in the standard way.
Additionally, indenting (ctrl+space
or
),
unindenting (shift+ctrl+space
or
),
commenting (ctrl+/
or
) and
uncommenting (shift+ctrl+/
or
) can
help with the laying out and testing/documenting of dfc code.
Utility buttons to delete all code
, help
and code library
buttons are provided for
convenience. Similarly, the font size may be increased
or decreased
.
Information about where a running code is currently
executing can be found by clicking the
button. This will cause the line currently
being executed to be displayed in the dfc help window at the bottom of the
console. Similarly, clicking
turns on (or off) automatic display of the
line currently being executed, updated typically every second. Note that these
facilities can have a significant impact on the execution speed.
When toggled, the smart indent button,
, will attempt to align
elements of the code in an intelligent way. The settings button,
, opens the subdialog
shown in figure 52. This dialog controls
syntax and variable highlighting, and whether the calculator interpreter is
automatically reset each time All
is clicked.

Figure 52: dfcConsole settings for controlling syntax highlighting, etc.
Note that using either the Close or x buttons to close the window will prompt to save the dfc code it contains. This feature is bypassed if you close the main DigiFlow window which will simply close the window without prompting for the dfc code to be saved.
Zoom in the current window by a factor of two.
Zoom out the current window by a factor of two.
Zoom the current window to full size (one pixel on the display for each pixel in the stored image).
Starts the zoom dialog box that allows a broader range of zooms to be selected, and also allows specification of the aspect ratio for the displayed image.

Figure 53: The custom zoom dialog box.
The two slider controls are linked with the two edit boxes. The Zoom setting controls the number of pixels on the display used to display a single pixel in the stored image in the horizontal direction. In contrast, the Aspect Ratio control determines the shape of the virtual pixels to be displayed. For images captured through DigImage, the aspect ratio should be set to 0.68 for PAL systems, or 0.75 for NTSC, thus recovering the original aspect ratio of the images.
Changes the zoom to fit the current window.
Changes the zoom of all windows to 100%, and fits the windows to the size of the images.
Changes the zoom of all windows to 50%, and fits the windows to the size of the images.
Changes the zoom of all windows to 33%, and fits the windows to the size of the images.
Changes the zoom of all windows to 25%, and fits the windows to the size of the images.
Resizes the current window so that it fits the zoom of its contents.
Under all cursor modes, holding down the left mouse button will cause a duplicate cursor to be displayed at the same pixel location on all the other open image windows. At the same time, the current intensity and other related data (e.g. velocity) will be displayed in the status bar for that window. This feature is valuable when trying to assess the relationship between features in different images. As described below, the cursor can also be set to display other information or to perform other tasks when the buttons are clicked.
When the left mouse button is held down on an image, a popup window will appear next to the cursor showing the current pixel and (if defined) world coordinates. Clicking the right button (while the left button is still depressed) will produce a message box showing the coordinates, as seen in figure.

Figure 54: The message box produced when the right-hand mouse button is clicked whilst the left-hand button is held down. The coordinate i,j is in pixel coordinates, while x,y are in the current world coordinates. In this case a velocity field was being explored and U and V represent the velocity, and S gives the scalar field (here vorticity) on which the velocity is displayed.
When the left mouse button is held down on an image, a popup window will appear next to the cursor showing the distance between where the left-hand button was depressed and the current location of the mouse pointer. Clicking the right button (while the left button is still depressed) will produce a message box showing the distance.

Figure 55: The message box produced when measuring distances with the cursor. The first line gives the pixel coordinates of the start and end points, along with the Dx and Dy in pixels (within brackets) and the distance and angle (within <..> pairs). The second line repeats this for world coordinates. The last two lines give the principal angle from horizontal and vertical, respectively, for the line with the first value in each case being in pixel coordinates, whist the second gives the same information with reference to the world coordinate system.
When the left mouse button is held down on an image, moving the mouse will pan the image. If <shift> is held at the same time, then vertical mouse movements are used to zoom the image.
Increase the length of velocity vectors and similar arrows. For finer control, see View: Appearance (§5.3.5).
Decrease the length of velocity vectors and similar arrows. For finer control, see View: Appearance (§5.3.5).
This tool provides a variety of tools for adjusting the appearance of an image. The scope of the tools depends on the format of the image; in particular, if the image is integer or floating point, and whether it contains a single plane of information or multiple planes.

Figure 56: Dialog for adjusting the appearance of an image. This example shows the features available for an image containing a velocity field.
The Data plane control will show the data planes available within the image. For simple images, only one data plane will be listed, but for velocity fields, for example, both velocity (vector data) and a background image (scalar data) will be listed. The appearance of each data plane type can be changed by selecting it in the Data plane control, then making the required adjustments. For example, if a velocity plane is selected, then the scale of the vectors, the spacing between the vectors, and the colour in which they are plotted may all be changed. Additionally, a check box allows the removal of any mean velocity. For scalar data, the colour scheme and the mapping between the scalar values and the limits of the colour scheme can be changed. Some of this latter functionality is also available through the Colour scheme dialog – see §5.3.6.
Used to select the colour scheme for the active image, or define a new colour scheme. The Select Colour Scheme dialog box invoked by this option provides the ability to add, remove and alter colour schemes.

Figure 57: Dialog used for selecting the colour scheme for an image.
A specific colour scheme may be selected by clicking on the name in the list box. The (image default) scheme is the scheme in use when the window was created. The (view default) is that in use for the image when this dialog was entered.
Checking Adjust intensity and moving the sliders or typing a value into the associated edit boxes may alter the appearance of a given scheme. For example, by setting Black to 1.0 and Saturation to –1.0, a scheme with the negative colours may be produced. Colour schemes created and added through the dfc function add_colour_scheme(..) are saved in DigiFlow_Status.dfs and will be included in the list of available schemes.
Clicking on Add brings up a dialog for adding new colour schemes. Details of these new schemes are added to the DigiFlow_Status.dfs file and thus remain available the next time DigiFlow is started in the same directory.

Figure 58: Add a new colour scheme.
DigiFlow understands the DigImage colour schemes. These may be added, as illustrated in figure 58, by simply giving them a name and typing the full path specification of the colour scheme. For DigImage, the colour schemes are stored in the %DigImage%\LUTs directory under the name Output##.lut, where ## represents a two digit number, starting with 00 for the first DigImage colour scheme.
Alternatively, specifying an image in the File edit box will install the colour scheme stored in that image, or construct a colour scheme of your own. The following example uses a short piece of dfc code to construct and install a colour scheme that is white in the middle tending towards red for low values and blue for high values. In this particular case, the scheme is tweaked so that its equivalent greyscale intensity varies parabolically. (It is often useful to have a colour scheme that works in both colour and monochrome.) The parabolic nature will emphasise extreme values more than small values. Such a scheme can be useful for displaying vorticity, for example.
# Initialise arrays to white
red := make_array(1,256);
green := red;
blue := red;
# Make basic colour scheme as two linear ramps
for k:=0 to 63 {
z := k/64;
p := 128 + k;
q := 127 - k;
red[p] := 1 - z; # Remove red
blue[q] := 1 - z; # Remove blue
};
for k:=64 to 127 {
z := (k-64)/64;
p := 128 + k;
q := 127 - k;
red[p] := 0; # No red
green[p] := 1 - z; # Remove green
blue[q] := 0; # No blue
green[q] := 1 - z; # Remove blue
};
# Make parabolic in grey value
grey := 0.299*red + 0.587*green + 0.114*blue; # Current grey equivalent
p := x_index(256)/255;
limit := 0.8; # Limiting grey value for ends
target := 1 - 4*limit*(p - 0.5)^2; # Target grey equivalent
scale := target/(grey max 1e-8); # The required scaling
red *= scale;
green *= scale;
blue *= scale;
# Install the colour scheme
add_colour_scheme("test",red,green,blue);
# Now test the colour scheme
im := x_index(512,64)/511;
hV := view(im);
view_colour(hV,"test");
When an image is displayed using false colour, clicking this button will temporarily switch to greyscale. Clicking a second time will return the image to the original false colour scheme.
Turns on or off the toolbar at the top of the main DigiFlow window. It is recommended that you leave this turned on.
Slave windows are a special type of window that are tied to a normal window – the master window – in such a way that when the master window is updated, any changes are reflected in the slave window. For example, if the master window is part of a sequence, then stepping through the sequence will update not only the master window, but also its slave.
A given master window may have one or more slave windows. When a master window is closed, its slaves are closed automatically (without prompting). Closing a slave window does not alter the state of the master nor force it to close.
For a more comprehensive array of slaves, refer to Tools: Slave Process in §5.7.5.
This option takes a copy of the image in the current active window and uses the values it contains to create a three-dimensional surface plot in a new slave window. The special slave window has its own toolbar that controls the three-dimensional rendering and allows re-orientation and other visual changes. This window is illustrated in figure 59.

Figure 59: A three-dimensional slave view.
The buttons on the toolbar are divided into five groups. With the exception of the + and buttons (the second group), the first four groups of buttons act as a set of radio buttons in which only one button may be pressed at a time. The pressed button then selects the drawing attribute that is to be changed using the plus or minus buttons. A brief summary of the buttons is given below.
|
Button |
Description |
|
|
Enable rotations about the x axis. Once enabled, then the |
|
|
Enable rotations about the y axis. Once enabled, then the |
|
|
Enable rotations about the y axis. Once enabled, then the |
|
|
Decrements the number associated with a render setting. The render setting is selected by clicking on the corresponding radio button in the toolbar menu. |
|
|
Increments the number associated with a render setting. The render setting is selected by clicking on the corresponding radio button in the toolbar menu. |
|
|
Enable panning the
three-dimensional view left or right. Once enabled, then the |
|
|
Enable panning the
three-dimensional view up or down. Once enabled, then the |
|
|
Enable moving the camera closer
or further. Once enabled, then the |
|
|
Enable changing the vertical
scale of the plotted data. Once enabled, then the |
|
|
Enable changing the spacing of
the grid lines plotted on the surface. Once enabled, then the |
|
|
Toggle the grid on and off. |
|
|
Paint the surface |
|
|
Toggle hidden line removal |
|
|
Toggle depth fog on and off. |
|
|
Activate spotlight. |
|
|
Change the colour of the background. |
|
|
Toggle display of axes. |
|
|
Reset settings. |
Note that the view produced is displayed as a bitmap. This may be saved, printed and/or converted to an Encapsulated PostScript plot.
Starts the dialog box showing and controlling the various active processing threads.

Figure 60: The thread control dialog box.
Each thread is given a name composed of a brief description of the process responsible for the thread and an identification number. The latter is used to provide a unique identification of a particular thread.
To make any changes to a thread, first select it from the list. The current status and execution priority of the thread will then be displayed. The thread may be paused or resumed by clicking the corresponding buttons. Alternatively, clicking Stop will close the thread, terminating the associated process in a relatively graceful manner. Once a process thread has been stopped, it may only be restarted by starting the process again from the beginning. In contrast, a thread that has been paused may always be resumed.
Any threads still running when DigiFlow is exited will be stopped and cannot be restarted.
Note that Normal priority is one step lower than the default priority for most Windows applications, thus preventing a DigiFlow process from unacceptably impacting the overall performance of Windows.
This tool causes all threads currently running in DigiFlow to be paused until the OK button is pressed. Note that pausing these threads does not prevent you from opening images, changing colour schemes, or even starting new processes: it is only threads that were running at the time the tool was activated that are paused.

Figure 61: Message box indicating all processing within DigiFlow has been paused.
Note: it is advisable not to use this tool while using the File: Live Video features.
Causes the currently selected view to be refreshed from the corresponding file, if one exists. This is necessary if you wish to see any changes that have been made to the file since it was originally displayed. This is particularly valuable when editing .dfd files or viewing images made by external programs, for example.
From DigiFlow version 2.0 (excluding the free version), DigiFlow is able to execute some facilities in parallel when it detects multiple processors, allowing a significant speed-up of these facilities. Note, however, that due to overheads in the parallelisation, plus limited memory and disk bandwidth, the speed-up is less than the increased cpu usage. In general, when doing standard processing, better performance can be achieved by running two jobs at the same time on DigiFlow without the In Parallel facility invoked, than will be achieved by running the two jobs in succession using the In Parallel facility.
Note that the current cpu usage is shown in the main DigiFlow status bar at the bottom of DigiFlow. With multiple processors, invoking In Parallel should increase the cpu usage beyond 100%. In version 2.0 the parallelisation is coded explicitly in only a small number of facilities, although it is expected that in future versions parallel execution will be much more widely available within DigiFlow.
This menu is currently disabled.
This menu is only available when the active window contains a movie, sequence or collection of images. The menu largely replicates the functionality available from the toolbar along the top of these windows.

Figure 62: The movie tool bar.
|
Button |
Section |
Description |
|
|
Play backwards in a loop |
|
|
|
Play backwards quickly (Review) |
|
|
|
Play backwards |
|
|
|
Stop playing sequence |
|
|
|
Pause current movie animation |
|
|
|
Play forwards |
|
|
|
Play forwards quickly (Cue) |
|
|
|
Play forwards in a loop |
|
|
|
Jump to the start |
|
|
|
Move back one frame |
|
|
|
Move forwards one frame |
|
|
|
Jump to the end |
|
|
|
§ |
Speed up the playback |
|
|
§ |
Slow down the playback |
|
|
Synchronise with another view |
|
|
|
Control dialog for additional control over |
Plays the image selector (§3.4) from the current location onwards.
Clicking the middle mouse button will play the movie (unless it is already playing, forwards or backwards, in which case it will pause it). Holding the middle button down while dragging the mouse to the right (left) will move rapidly forwards (backwards) through the movie.
Plays backwards the image selector (§3.4) from the current location.
Double clicking the middle mouse button will play the movie backwards. Holding the middle button down while dragging the mouse to the right (left) will move rapidly forwards (backwards) through the movie.
5.5.1.2.1
Stops the playing of the image selector (§3.4) from the current location. The sequence is left with the final frame played visible, but internally the movie, sequence or collection is returned to its starting point. Playing the movie forwards again will start from the beginning, or backwards will start from the end.
Pauses the playing of the image selector (§3.4) from the current location. The sequence is left with the final frame played visible, and play operations will restart from this point.
Clicking the middle mouse button will pause the movie if it is already playing (either forwards or backwards. If the movie is not already playing, then clicking the middle mouse button will play it.
Plays the image selector (§3.4) at ten times the normal speed (showing only every tenth frame).
Plays the image selector (§3.4) backwards at ten times the normal speed (showing only every tenth frame).
Step forwards one frame in the image selector (§3.4), starting from the current location.
Rotating the mouse wheel will step the movie forwards or backwards, depending on the direction of rotation. Holding the middle button down while dragging the mouse to the right (left) will move rapidly forwards (backwards) through the movie.
Step backwards one frame in the image selector (§3.4), starting from the current location.
Rotating the mouse wheel will step the movie forwards or backwards, depending on the direction of rotation. Holding the middle button down while dragging the mouse to the right (left) will move rapidly forwards (backwards) through the movie.
Move to the start of the image selector.
Move to the end of the image selector.
Plays the image selector (§3.4) forwards in a continuous loop.
Plays the image selector (§3.4) backwards in a continuous loop.
Causes this image selector (§3.4) to be slaved to another selector. The other selector will provide the time information for synchronous advancement of this selector.
This option fires up a dialog providing more detailed control over the animation of the image selector.

Figure 63: The dialog box that provides detailed control of image animation.
The buttons and controls in this dialog box are similar to those found for the selector timing tab in the Sift dialog in §4.3.1. In addition, the dialog provides more detailed control over the animation speed.
Calculates a variety of averages and other statistics for an image selector.

Figure 64: Compute the average of an image selector.
The Input group contains the controls used to determine the image selector to be sampled. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box is produced. Finer control over which parts of the input stream are to be processed are determined via the Sift button; see §4.3. Alternatively, the output of a different process may be utilised by clicking the Process button (refer to §7 on chaining processes for further details).
Note that this tool can process not only images from any DigiFlow supported format, but also velocity fields and other complex data stored in .dfi files. The output stream preserves the data format of the input stream. For example, if the input stream is a velocity field, then the output stream will also contain velocity information.
The time average image is saved to the file specified in the Outputs group by clicking the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details). The colour scheme and compression options to be used for the output stream is set by clicking the Options button (§4.4).
The Method radio buttons select the averaging procedure adopted. Arithmetic returns the standard arithmetic mean, while RMS calculates the root mean square image. The image fluctuations are represented by the Std. Dev. option, while Geometric and Harmonic provide the other forms of averaging. These are summarised in the table below.
|
Method |
Formula |
Comments |
|
Arithmetic |
|
This is the standard mean value. |
|
RMS |
|
The root mean square value. |
|
Std. Dev. |
|
Standard deviation of the image series. |
|
Geometric |
|
Geometric mean. |
|
Harmonic |
|
Harmonic mean. |
|
Min |
|
Minimum value. |
|
Max |
|
Maximum value. |
The weighted time average facility provides an extension to that provided by the more simple averaging. In particular, the following table defines the weighted means. Here, Pi is the intensity at a given pixel from the image at time i, and Ai is the weighting applied to that pixel/image.
|
Method |
Formula |
Comments |
|
Arithmetic |
|
This is the standard mean value. |
|
RMS |
|
The root mean square value. |
|
Std. Dev. |
|
Standard deviation of the image series. |
|
Geometric |
|
Geometric mean. |
|
Harmonic |
|
Harmonic mean. |
|
Min |
|
Minimum value. |
|
Max |
|
Maximum value. |
The user interface for the weighted mean is similar to that for the simple mean facility (see §5.6.1.1), but has an additional (optional) Weighting selector for specifying a second input stream to provide information with which to construct the weighting Ai. The weighting itself is constructed by the code specified in Expression. This code should return an array of the same dimensions as the input Sequence, or a two-dimensional array of the same size in those two dimensions. This array can be constructed from the input Sequence and (when specified) the input Weighting. If Weighting is specified, then this image is available to the code through the array variable A and the compound variable B. If Weighting is not specified, then A and B point to the input Sequence. In both cases the input Sequence is also available through the array variable P and compound variable Q.
For simple images, the array variables A and P will have two
dimensions, whereas for more complex images A and P will have more than two dimensions.
The information in these multidimensional arrays will also be available through
individual components of the compound variables B and Q. For example, if the first input Sequence contains a
velocity field generated by the PIV facility (see §5.6.5.2) then Q.u and Q.v will contain the two components of
the velocity field, and (depending on the options selected during the
processing) Q.Scalar
may contain the vorticity field. Full colour images are supplied as their red,
green and blue components with a three-dimensional P array: P[:,:,0] contains the red component, P[:,:,1] contains the
green component, and P[:,:,2] contains the
blue component. For convenience, these are also supplied as Q.Red, Q.Green and Q.Blue. The
button may be
used to search for or provide information on specific DigiFlow functions. The
button may be
used to search for or provide information on specific DigiFlow functions.
One common use of the weighted average facility is for computing the temporal average of velocity fields where there may be an incomplete spatial coverage for the velocity at any particular time. In such cases, only points with valid velocity vectors should contribute to the temporal mean. This may be achieved by specifying the sequence of velocity fields to the input Sequence and simply specifying A<>0; as the Expression as the PIV subsystem sets the velocity to exactly zero when it is unable to determine a velocity. More sophisticated averaging can be achieved by using the Quality output from the PIV subsystem to construct a more continuous measure of quality to be used as the weighting.

Figure 65: Dialog controlling the weighted time average.
One valuable method of analysing periodic signals, such as waves, is by harmonic analysis to determine the phase and amplitude of the component of the signal at a given frequency or set of frequencies.
DigiFlow provides a convenient method of analysing a sequence for a given frequency and harmonics (integer multiples) of that frequency. The Input sequence should span one or preferably more periods of the frequency you wish to analyse. The Sift button should be used to ensure the period being analysed represents a time of steady oscillation. In general, the more images available within this period the better the results.
The Fundamental frequency to be analysed can be specified in a number of ways, with the Period stated in either time or frames, or the Frequency in Hertz (cycles per second) or radians per second. For best results, the input sequence should correspond to an exact multiple of the fundamental period. If the Conform input to period box is checked, then DigiFlow will automatically truncate the input sequence so that it is as close as possible to a multiple of the period.
In addition to analysing the fundamental frequency, DigiFlow can simultaneously analyse harmonics of this frequency, plus the mean (zero frequency) component. Unlike many other DigiFlow facilities, the Harmonic Analysis tool will generate the names of the harmonic files automatically from the files specified in Output for the fundamental. If the name for the fundamental file is amp.dfi, then the ´2 harmonic is saved in amp[x2].dfi. Similarly for other harmonics. (Note that even if the Number as #### or Compact list boxes are checked in the Open Image dialog then DigiFlow will not treat the number within the square brackets as part of a sequence number.)

Figure 66: Dialog controlling harmonic analysis within DigiFlow.

(a) (b)
Figure 67: Example of harmonic analysis, showing (a) amplitude and (b) phase of the fundamental frequency of an internal gravity wave.
Once the harmonic analysis has been completed, it is a simple matter to reconstruct the flow field at an instant in time. Alternatively, the field may be decomposed into the different wave components using a Hilbert Transform. A tool for achieving this is found under the Spectral recipes in Tools Transform Recipes. Figure ?? illustrates the results.

Figure 68: Hilbert Transform yielding waves with kx > 0 and ky > 0. (a) Amplitude. (b) Phase.
Extracts a time series of the intensity along some line or curve and forms an image with one spatial and one temporal dimension.

Figure 69: Dialog box controlling the extraction of time series information from an image sequence.
This facility takes a single input stream, and creates one or more output streams. The input streams are normally sequences, while the output streams are normally individual images.
The Input group contains the controls used to determine the image selector to be sampled. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box is produced. Finer control over which parts of the input stream are to be processed are determined via the Sift button; see §4.3 for further details. Alternatively, the output of a different process may be utilised by clicking the Process button (refer to §5.7.5 for further details).
Note that this tool can process not only images from any DigiFlow supported format, but also velocity fields and other complex data stored in .dfi files. The output stream preserves the data format of the input stream. For example, if the input stream is a velocity field, then the output stream will also contain velocity information.
A number of time series may be generated simultaneous in this manner, each representing a different section through time image, and each written to a different Timeseries Image. You may move between each of the possible time series using the Series edit control and associated spin control. Individual extraction codes are enabled or disabled via the Use check box, while the Reset All button may be used to turn off all and reset all extraction time series.
For each time series, the section through the image may be specified in a variety of ways. The Column and Row radio buttons allow data to be extracted from a given column or row within the image. In both cases, this data is written to the output image as a row of pixels, with each successive time being placed above the previous one.
The Between radio button allows two points to be specified, and the data extracted from the line joining the two points using a specified number of steps. The points may be specified in either pixel or world coordinates by selecting the appropriate Coordinate sytem.
Alternatively, expressions may be given to determine the line or curve along which data is to be sampled. These curves may be specified either as y(x), x(y), or parametrically as x(s) and y(s). Depending on which of these is selected, the formula supplied by the user should be cast in terms of x, y or s. The formula may also include time Time.tNow and/or the frame number Time.fNow (the limits on the selector times and frames are also available through Time.tFrom, Time.tTo, Time.tStep, Time.fFrom, Time.fTo and Time.fStep). In addition, the variable Time.iNow provides an iteration counter. This will always start at zero and increase by one for each image processed (in contrast, the first value for Time.fNow depends on where in the input sequence the sequence to be processed starts, and its increment depends on the stepping between the images to be processed). In all cases, the user can specify the number of sample points and the coordinate system to be used.
The direction of the time axis on the resulting images may be specified using the Time direction group.
Each Timeseries Image created has the samples taken across its width (from first to last left to right), and time increasing from bottom to top. The file that receives this image is specified in the Outputs group by clicking the Save As button. Note that a different destination is provided for each time series activated. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details). The colour scheme and compression options to be used for the output stream is set by clicking the Options button (§4.4).
In addition to the standard image formats for the output of each time series, this facility supports simple ASCII data files with a .dat extension that provides a more convenient format, including precise details of the pixel or world coordinates from where the data came.
Note that subpixel precision is obtained for all the samples by using bilinear interpolation, where appropriate.
Using a user-specified formula, extract a one-dimensional array of data from each image in a sequence, and use this to construct an image with one spatial and one temporal dimension.

Figure 70: Dialog controlling the extraction of calculated data from an image to form a time series of this data.
This facility takes a single input stream, specified through, and creates one or more output streams. The input streams are normally sequences, while the output streams are normally individual images.
The Input group contains the controls used to determine the image sequence to be sampled. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box is produced. Finer control over which parts of the input stream are to be processed are determined via the Sift button; see §4.3 for further details. Alternatively, the output of a different process may be utilised by clicking the Process button (refer to §7 for further details).
Note that this tool can process not only images from any DigiFlow supported format, but also velocity fields and other complex data stored in .dfi files. The output stream preserves the data format of the input stream. For example, if the input stream is a velocity field, then the output stream will also contain velocity information.
The Extraction code should take the current image and return a one-dimensional array of data to be added to the time series, and the Variables box lists some of the variables describing the image that are available for use in the code; a more comprehensive list may be viewed by clicking the Variables button.. A number of time series may be generated simultaneous in this manner, each with a different Extraction code, and each written to a different Timeseries image. You may move between each of the possible time series using the eSeries edit control and associated spin control. Individual extraction codes are enabled or disabled via the Use check box, while the Reset All button may be used to turn off all and reset all extraction time series.
Each Timeseries Image created as one axis as time and the other as the ordinal position of the one-dimensional array returned by the Extraction code. The direction of the time axis is specified by the Time direction group. The file that receives this image is specified in the Outputs group by clicking the Save As button. Note that a different destination is provided for each time series activated. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details). The colour scheme and other output options to be used for the output stream is set by clicking the Options button (§4.4).
The basic image from the input stream is supplied to the Extraction code in the array variable P. For simple images this will be a two-dimensional array. However, for more complex image formats (such as velocity fields stored in .dfi files), P will contain more than two dimensions. In such cases DigiFlow will also provide the same data split into its individual component two-dimensional arrays in the compound variable Q. For example, if the input stream contains a velocity field generated by the PIV facility (see §5.6.5.2) then Q.u and Q.v will contain the two components of the velocity field, and (depending on the options selected during the processing) Q.Scalar may contain the vorticity field. If the input stream contains a DigiFlow drawing (typically one or more .dfd files), then DigiFlow provides the drawing is available through its handle hD, in addition to a bitmap version of it in the array variable P. Additional drawing commands may be added to the drawing handle, or it may be incorporated into a compound drawing using draw_embed_drawing(..).
Full colour images are supplied as their red, green and blue components with a three-dimensional P array: P[:,:,0] contains the red component, P[:,:,1] contains the green component, and P[:,:,2] contains the blue component. For convenience, these are also supplied as Q.Red, Q.Green and Q.Blue.
DigiFlow also provides time information about the input stream through the Time compound variable. Typically this contains Time.fNow and Time.tNow giving the current frame number and time (in seconds) relative to the start of the entire input stream. An additional variable Time.iNow gives an iteration counter that is the frame number relative to the start of those that are actually being processed. Details of the entire input stream are provided through Time.fFirst, Time.fLast and Time.tFirst, Time.tLast that provide details of the first and last frame/time that exist in the input stream. Moreover, Time.fFrom, Time.fTo and Time.tFrom, Time.tTo provide information about which part of the stream is being processed.
Although the main variables available are listed in the Variables list box this list does not include any additional modifiers for the individual data plane variables beginning with Q. These modifiers include the description, scaling and (where appropriate) spacing of the data. A more comprehensive list may be viewed by clicking the Variables button. For further details, refer to the PIV data example in §5.7.2.
The Extraction
code may be as simple as returning a subarray (e.g. P[100,10:50]), or it may be the result of a complex calculation on the image. The
button may be
used to search for or provide information on specific DigiFlow functions.
Examples of more complex processing are given below.
For example, suppose you have an experiment of a gravity current propagating along a channel and want to produce a time history of the depth of the current. The first question is how to measure the depth. There are a number of possibilities.
The simplest measure of the depth would be the height from the bottom to the point where the density fell below some threshold. Suppose we have previously processed a sequence using the dye attenuation facility described in §5.6.3.1 and have an image stream that represents the concentration/density of the current. This could be defined as the number of pixels that exceed some threshold in intensity. In this case the Extraction code would be y_count(P > 0.1)/y_size(P), where the threshold is 0.1. Dividing by y_size(P) means that the resulting depth will be normalised by the height of the input stream.
A more robust measure would be to use the integral of the concentration over the depth. This is achieved simply by looking at the vertical mean as a function of position by y_mean(P). This gives a measure of the hydrostatic pressure excess at the base of the current.
As a more complex example, suppose we have a series of LIF images from turbulent flow (these may have been processed using the LIF facilities described in §5.6.3.2), and you would like to know how the power spectrum of some region evolves in time. The region might vary for each image. In particular here we are looking at Rayleigh-Taylor instability and are interested only in the region where the two layers are mixing. In this case the camera was turned on its side. We could rotate the image (e.g. using rotate_image_clockwise(..) or transpose(..)), but for this example we will work in the rotated space with x vertical and y horizontal. A suitable code segment is given below:
# Threshold for fluctuations
thresh := 0.05;
# Determine fluctuations
Fluct2 := y_rms(P)^2 - y_mean(P)^2;
# Fird first location where threshold exceeded
iStart := -1;
for i:=0 to x_size(P)-1 {
if (iStart = -1 and Fluct2[i] > thresh) {
iStart := i;
};
};
# Fird last location where threshold exceeded
iEnd := -1;
for i:=x_size(P)-1 to 0 step -1 {
if (iEnd = -1 and Fluct2[i] > thresh) {
iEnd := i;
};
};
# Compute power spectrum within this region
Spect := power_spectrum_column(P[iStart:iEnd,:]);
# Determine and return mean
x_mean(Spect);
To determine the region over which we will compute the concentration power spectrum we probe the magnitude of the concentration power spectrum, calculated from the root mean square and mean intensities (concentrations) in the y direction, looking for the first and last columns that satisfy a threshold condition. (Note we could use the function x_transition_index(..) in place of the loops for improved computational efficiency.)
The Time summarise facility is similar to the Time extract facility, except that it is tailored towards extracting and graphing scalar quantities from an image sequence.
Figure 71 shows the dialog controlling this facility. The Input group contains the controls used to determine the image sequence to be sampled. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box is produced. Finer control over which parts of the input stream are to be processed are determined via the Sift button; see §4.3 for further details. Alternatively, the output of a different process may be utilised by clicking the Process button (refer to §7 for further details).
The Extraction code should take the current image (provided in P for simple images) and return a scalar value to be added to the time series. This code may be as simple as returning the intensity at a specific point (e.g. P[100,10]), or it may be the result of a complex calculation on the image (see below for further details).
The result of the Extraction code is rendered on a graph against time. The method of representing the individual data points is determined by Draw with to specify line or mark type, and Colour to set the colour to be used. Multiple data sets may be plotted on the same graph by specifying different Extraction code, Draw with and Colour for each Series that is selected by Use.
The extracted data are all rendered on the same graph, specified by Output graph in the normal way. In this case, Output graph would normally be a vector format image (.dfd, .emf or .wmf file), but this may be saved as a raster image, if preferred. The x axis represents time, while the y axis is used for the extracted data. The limits on the y axis are set by yMin and yMax. The titles for the two axes are given by x Title and y Title. With fully licensed copies of DigiFlow these may contain LaTeX-like text formatting commands. For example, the string Dimensionless height $\big(\frac{h}/{\alpha^2H_0}\big)$ would produce the label
.
See §3.9 for further details.
A number of time series may be generated simultaneous in this manner, each with a different Extraction code, and each written to a different Timeseries image. You may move between each of the possible time series using the Series edit control and associated spin control. Individual extraction codes are enabled or disabled via the Use check box, while the Reset All button may be used to turn off all and reset all extraction time series.
The basic image from the input stream is supplied to the Extraction code in
the array variable P.
For simple images this will be a two-dimensional array. However, for more
complex image formats (such as velocity fields stored in .dfi files), P will contain more than two dimensions.
In such cases DigiFlow will also provide the same data split into its
individual component two-dimensional arrays in the compound variable Q. For example,
if the input stream contains a velocity field generated by the PIV facility
(see §5.6.5.2) then Q.u and Q.v will contain
the two components of the velocity field, and (depending on the options
selected during the processing) Q.Scalar may contain the vorticity field. Full colour
images are supplied as their red, green and blue components with a
three-dimensional P
array: P[:,:,0] contains the red
component, P[:,:,1] contains the
green component, and P[:,:,2] contains the
blue component. For convenience, these are also supplied as Q.Red, Q.Green and Q.Blue. The
button may be
used to search for or provide information on specific DigiFlow functions.
DigiFlow also provides time information about the input stream through the Time compound variable. Typically this contains Time.fNow and Time.tNow giving the current frame number and time (in seconds) relative to the start of the entire input stream. An additional variable Time.iNow gives an iteration counter that is the frame number relative to the start of those that are actually being processed. Details of the entire input stream are provided through Time.fFirst, Time.fLast and Time.tFirst, Time.tLast that provide details of the first and last frame/time that exist in the input stream. Moreover, Time.fFrom, Time.fTo and Time.tFrom, Time.tTo provide information about which part of the stream is being processed.
The main variables available are listed in the Variables list box. This list does not, however, include any additional modifiers for the individual data plane variables beginning with Q. These modifiers include the description, scaling and (where appropriate) spacing of the data. A more comprehensive list may be viewed by clicking the Variables button. For further details, refer to the PIV data example in §5.7.2.

Figure 71: The Analyse: Time Summarise dialog.
In the example shown in figure 71 (the code is repeated below for clarity) we want determine the evolution of the fractal dimension of a contour from a series of LIF images. Here we can make use of DigiFlow’s in-built box counting algorithm in conjunction with its ability to fit least squares curves.
# Count boxes
boxes := fractal_box_count(image:=P,threshold:=0.5);
# Only want to use mid-range for the fit
k0 := count(boxes[:,0] < 10];
k1 := count(boxes[:,0] < 100];
# Fit a power law
fit := fit_expression(expr:="1;ln(size);",
varNames:="size;",values:=boxes[k0:k1,0],rhs:=boxes[k0:k1,1],rhsExpr:="ln(n);",rhsNames:="n;");
# Return the slope
-fit.coeff[1];
The net result (just visible in the preview of the output image) is a time series showing the evolution of the fractal dimension. In reality, it is advisable to plot the individual box count verses box size curves for individual images before embarking on processing such as that described above in order to ensure a power law relationship exists in the range of box sizes selected (here between 10 and 100 pixels).
Suppose we want to know the mean intensity along some line within an image. Obviously, if the line is simply a line or column then we need simply specify mean(P[10,:]), for example, for the mean intensity of column 10. However, if the user wishes to specify the line interactively, we might use
if (Time.iNow = 0) {
# For first iteration, find line and determine points
hView := get_active_view();
line := get_mouse_line(hView);
dx := line.x1 - line.x0;
dy := line.y1 - line.y0;
if (abs(dx) > abs(dy)) {
x := make_array(0,abs(dx));
y := line.y0 + x*dy/dx;
x := line.x0 + dx/abs(dx)*x_index(x);
} elseif (abs(dy) > 0) {
y := make_array(0,abs(dy));
x := line.x0 + y*dx/dy;
y := line.y0 + dy/abs(dy)*x_index(y);
} else {
x := make_array(line.x0,1);
y := make_array(line.y0,1);
};
};
# Extract values for specified points and determine the mean
points := sample_values(P,x,y);
mean(points);
In this case, we use Time.iNow to detect the first time through and set up the x and y arrays to contain the points on the line specified by the user drawing it on the input image stream. Here we rely on the input view being active at the time the code segment starts, allowing its handle to be determined by get_active_view(..).
It is frequently desirable to determine the behaviour of flows across an ensemble of experiments. The Ensemble Mean facility provides one of the basic building blocks for analysing an ensemble of experiments.

Figure 72: Dialog controlling the calculation of ensemble means.
The interface for specifying an ensemble of experiments differs slightly from the normal mechanism of specifying input streams in DigiFlow in order to provide a more compact and convenient specification process, although this is at the cost of some of the functionality of the standard interface. The Input group provides the various controls needed to specify the members of the ensemble. Add will fire up the standard Open Image dialog for specifying an input stream. Once specified, the name of the input stream is added to the list on the left of the group. An input stream may be sifted by selecting it from the list then clicking the Sift button (see §4.3). While a given member of the ensemble is selected, its name and directory are displayed at the bottom of the Input group, with a preview just above. The Master checkbox indicates if the selected stream is the master (controls the timing, region, etc.). This checkbox may be used to specify the currently selected stream as the master, but not to deselect it (to deselect a stream you must select another stream as the master). Streams may be removed from the ensemble by selecting from the list then clicking the Remove button. Alternatively, all members of the ensemble may be removed using the Reset button.
The ensemble mean image is saved to the file specified in the Outputs group by clicking the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §6 for further details). The colour scheme and compression options to be used for the output stream is set by clicking the Options button (§4.4).
The Controls group allows specification of the type of average to be computed, and whether or not to include zero values in the average. Seven types of average are provided through the Kind group. The meaning of each of these is identical to that given for the time averaging in §5.6.1.1. If the Ignore zeros box is checked, then only those points which are not identically zero are included in the averaging. DigiFlow’s synthetic schlieren and PIV facilities both flag missing data with identical zeros, thus checking Ignore zeros provides a convenient way of calculating a mean that is not contaminated by missing data.
Correct a back-illuminated image for variations in the intensity of the back-illumination. Pre- and post-correction manipulations allow for easy implementation of camera calibration and dye calibration procedures.
Let us consider polychromatic light from a source with an intensity i0(x,y,k) = I0(x,y) J(k), where x,y are the location on the source and k the wavenumber of the light emitted. For simplicity, we assume the source colour is independent of the position within the source. Here, I0(x,y) represents the spatial variation in the intensity of the illumination, while J(k) gives the spectral colour. Assuming the spectral response of a linear monochrome camera (with no black offset) is described by S(k), then the intensity perceived by the camera viewing this source directly is
.
For a colour camera, there will (typically) be three such expressions, one each for the red, green and blue components (with corresponding SR(k), SG(k) and SB(k) leading to P0R, P0G and P0B). For simplicity, we shall concentrate on a camera yielding a single (monochrome) component. Moreover, we shall assume that the only light received by the camera is that from the source I0 and that the source is ‘in focus’.
Suppose we conduct an experiment using coloured (non-fluorescing) dye of concentration c(x,y,z,t) such that the attenuation of light from the source passing in the z direction through the dye is governed by
,
where a = a(k) describes the colour of the dye. The intensity falling on the camera is therefore
,
where
is the
mean concentration along the light ray connecting the source and camera, and L(x,y,t) is the thickness of the
region in which we are interested in associating with the mean
. Here we have assumed that the light
rays are parallel (or nearly parallel) with the z
axis.
The intensity perceived by the camera is therefore
We proceed by considering three classes of dyes, catagorised by a(k) in conjunction with the J(k)S(k) combination.
If the dye is neutral density (a(k) = a0 = const) then (1) reduces to
.
Here we have defined Q as the normalised intensity P/P0. Similarly, if the light is monochromatic of wavenumber k1 at which a(k1) = a1, or the camera’s response is monochromatic of wavenumber k1, then
.
We shall call these two situations as the ‘ideal’ case. The first can be achieved using a black dye such as nigrosin, while the second can be achieved either using a monochromatic light source or by placing in front of the camera lens.
In this ‘ideal’ case, if L is known a priori, then we can readily determine the mean concentration as
,
where the combination aiL is typically determined
by calibration. Similarly, if
is know a
priori (typically by setting c(x,y,z,t) = c0
= const), then we can use the same relation to determine the thickness
(depth) of the layer from
.
If L is constant in time but varies in space, it is often more convenient to determine this from an image of a constant concentration of dye, rather than attempting to measure it everywhere. Suppose the camera perceives an image of intensity PL when the experiment is filled with a constant concentration of dye cL. From this we can calculate
,
where QL = PL/P0, and substitute back to determine
.
If the dye is not ideal (i.e. it is neither neutral density nor illuminated by a monochromatic light source) then additional calibration is required. Recall that the camera perceives
.
For a given illumination and camera response, we can
write
where g(j)
(which is bounded above by one) characterises the response of the dye as
.
If g(j) is invertible then we can determine the concentration as
.
As we saw above, for an ideal dye g-1(Q)
is
.
In general, however, we may not have a detailed knowledge of the spectrum of the light source J(k), the spectral response of the camera S(k) or of the dye absorption a(k), but must instead determine by calibration g(j) or, more usefully, the inverse g-1(Q).
Suppose we determine, through a calibration procedure, that g-1(Q) » Dye(Q),
then we can proceed to compute
or L.
In particular, if L is known a priori, then
,
while if
is know a
priori then
.
As before, if L is constant in
time but varies in space we can compute
by introducing a
calibration image PL
of a uniform dye concentration cL to obtain
,
where QL = PL/P0.
Some dyes can be approximated as being transparent to some wavelengths of light while strongly filtering other wavelengths. The spectral response of such a dye could be approximated by a(k) = a0 + a1H(k-k0), where H(×) is the Heaviside step function, a0 (ł 0) and a1 are constant attenuation rates and k0 is a constant wavenumber. If, further, we assume the product J(k)S(k) is constant for k1 Ł k Ł k2¸and zero outside this range, then for such a dye g(j) becomes

In the limits of a1 >> a2 and of a1 ~ -a0, then g(j) is well approximated by a constant plus a decaying exponential. The constant term is due to little attenuation of light over some bandwidth, while the exponential is due to a rapid (nearly constant) attenuation of light over the remainder of the spectrum. As seen by a number of previous authors, this model is a good approximation to the behaviour of some food colourings when illuminated by white light.

Figure 73: Analysis of variations in background illumination to determine the dye concentration.
This process takes either two or three source image selectors, depending on whether the base optical thickness needs to be calculated.
The Dye Image group determines the image selector to be corrected. This image selector may be selected from a file by clicking the File button, in which case the standard Open Image dialog box (§4.1) is produced. Precise details of the region and times to be used may be set using the Sift button (§4.3). Alternatively, clicking the Process button will allow a source process to be used (refer to §7 on chaining processes for further details).
The Background Image group determines the image selector containing the background illumination. Only the first image will be used if an image selector containing multiple images is selected, although the particular image from a sequence may be specified using the Sift button. As with the Dye Image group, clicking File activates the Open Image dialog box (§4.1), whereas clicking Process allows a source process (§7) to be used.
The resulting image selector is saved to the file specified in the Concentration Image group by clicking the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details).
The Controls group allows user specification of the camera and dye calibration.
The Camera calibration is applied to both the Dye Image and Background Image prior to their processing. The calibration is specified as a function of the intensity in the input image selectors, represented in the expression as the variable P (upper case). Note that regardless of the format of the input selectors, all processing is performed in floating point arithmetic and normally the images will be scaled between an intensity of 0.0 for the darkest parts and 1.0 for the brightest parts. Thus the default P – 16/255 would set an intensity of 16 in an eight-bit greyscale image to zero. Refer to §8 for further details on the interpreter.
The Dye calibration mapping is applied to the image(s) resulting from this procedure. The mapping function should be specified in terms of the intensity of the corrected image. Here this corrected image intensity is expressed through the variable Q (upper case), which is again in the range 0.0 to 1.0. The default for this calibration is dye_deal(Q), which is simply –ln(Q)
The normal processing undertaken by this feature may be described as
,
where Camera(..) represents the Camera calibration, Dye(..) represents the Dye calibration, PDye is the Dye Image, PBack is the Background Image and PConc is the Concentration Image. The result of Camera(PDye)/Camera(PBack) is what is provided in the variable Q, thus PConc = Dye(Q).
However, strictly speaking, PConc is proportional to the integral of the dye concentration over the length of the light ray seeing dye as it passes through the flow. Thus, if the length of this light ray varies (e.g. due to tank geometry or camera parallax), the PConc image is contaminated by this variation.
As noted above, by using an additional image, PL, of the tank containing a uniform concentration of dye CL, it is possible to correct for this variation in the length of the light rays. In such a case the required processing is
.
This more advanced processing is enabled by checking Use Thickness Image. This then enables the Thickness Image group to determine the image selector containing the background illumination. Only the first image will be used if an image selector containing multiple images is selected. As with the Dye Image group, clicking File activates the Open Image dialog box, whereas clicking Process allows a source process to be used.
LIF, often referred to as Laser Induced Fluorescence but more generally can stand for Light Induced Fluorescence, describes the family of techniques where a sheet of light is used to stimulate emission from a fluorescent dye. Typically this dye is dissolved in the fluid at very low concentrations, rendering it a passive tracer, but which is used to tag some other species (e.g. salt concentration) thereby providing a means of visualising and quantifying an otherwise invisible component of the flow.
Fluorescent dyes are often used in fluids experiments to obtain an image of the concentration field on a single plane of a flow. The name often given to such techniques is LIF or Laser Induced Fluorescence. However, the use of a laser is not obligatory, and white light may be used to produce comparable results, provided the colour temperature of the light source is sufficiently high. Xenon arc lamps, for example, provide an excellent and safer alternative to the high cost of lasers.
The fluorescent dyes used in LIF typically absorb energy from incident light over a range of wave lengths and radiate it at a single or well defined range of wave lengths. Typically the absorption in the range of wave lengths radiated is relatively small so that radiated light passing through regions of fluid containing the fluorescent dye is not attenuated significantly by that dye. Clearly the illuminating light must attenuate as it passes through the dye. For most useful dyes the efficiency of this fluorescence is relatively high so that only very weak solutions are required and the attenuation of the illuminating light is small.
If the flow is illuminated by monochromatic light (such as a laser, or at least coloured light with a narrow power spectrum) with a wave length significantly different from that of the fluoresced light, then it is possible to eliminate the effect of any light scattered directly from the experimental apparatus or contaminants in the water by introducing a filter in front of the camera to cut the wave length(s) of the light source. However for reasons of cost, availability and safety, a laser was not employed for these experiments. Thus our LIF images contain a component of directly scattered light despite efforts to minimise this.
In all the LIF experiments reported here, sodium fluorescein was used as the fluorescent dye. Its choice was based on its high efficiency, low cost and relative safety. The light fluoresced typically appears green, with the dye responding better to the blue end of the visible spectrum (this is one of the reasons the blue-white light of the arc lamp was better than the yellow-white light of the halogen light source).
As mentioned above, as the illuminating light sheet passes through the dyed fluid, some of the light is absorbed thus reducing the intensity of the light sheet. In addition, the light sheet will typically diverge slightly, effectively reducing the intensity further. In order to obtain quantitative information about the density field (as marked by dye concentration) it is necessary to correct the LIF images for this attenuation and divergence. In this subsection we briefly outline the technique used in this work for performing this correction.
Consider an image p = p(x) of a flow containing a fluorescent dye of concentration C = C(x). We define a virtual light sheet P = P(x) such that
Assume that the attenuation of the virtual light sheet as it passes through the dye can be described by
where s describes the path of the light rays and s = s(x) is the attenuation of the virtual light sheet. Suppose we have a calibration image p0 of a constant concentration C0. Now we may estimate the spatial structure of the attenuation from
where
is the
least squares fit of
to the calibration image p0 (it is
often necessary only to include the linear term in the exponential). Using our
estimate of the attenuation we can calculate an estimate
(say) for the virtual sheet from
and thus obtain our estimate of the concentration field
where
is the
estimate for the virtual light sheet evaluated from equation (3).
We may determine how accurate this process is by performing this process on the calibration image, and then comparing the result with the known virtual sheet P0 = p0/C0 to obtain the defect ratio
In some cases we may wish to adjust our calculation for other images using this defect ratio by determining
This approximation guarantees perfect reconstruction of the calibration image, but does not necessarily ensure an improved concentration field for other images.
Another technique that can be useful is to use Rdefect to improve the estimate to the decay law fit rather than as a direct modification to the concentration field. To achieve this, a least squares fit of the same form as (5) is applied to Rdefect (which we would hope was a constant), and the coefficients a1, a2, etc., are used as a correction to those obtained from (5). Applying this correction iteratively will ensure that in the mean Rdefect is unity.
The processing of LIF images in DigiFlow is somewhat more sophisticated than that described above, extending the basic idea to include multiple point light sources, distributed light sources, and additional models for the behaviour of light rays.

Figure 74: Dialog controlling correction of LIF images.
The example illustrated in figure 74 is for Rayleigh-Taylor instability. In this case, the camera was rotated by 90 degrees so that the initially dense layer is to the left and the light layer to the right. The flow was illuminated from below by a sheet of white light. Fluorescent dye (disodium fluorescein) was present in the upper layer. The two layers were initially separated by a barrier at half the depth of the tank.
The Dye Image input image stream is the raw footage of the experiment. The attenuation and divergence of the illuminating light sheet as it passes through the fluorescent dye is clearly visible. In this case, the light sheet is generated by a pair of 300W arc lamps, each effectively a point source. The Left-hand light source and Right-hand light source input streams give images of the two separate light sources illuminating the tank when it contains a uniform concentration of dye. These images are used for calibration purposes. Each of these three input selectors is specified in the normal manner using the associated File and Sift buttons.
The Controls group contains the various parameters that affect the modelling of the light passing through the dye. For this correction procedure to operate effectively, it is important that the experiment is carefully set up, that there are no stray reflections reaching the camera, and that all the necessary details are recorded at the time of the experiment.
The Camera calibration should specify the relationship between the digitised values and real intensities. With most modern scientific CCD and CMOS cameras the relationship is close to being linear. However, ‘black’ seldom digitises to zero. Here, we assume a linear relationship with black digitising to a value of 0.034. A number of methods for determining this black level are described in §6.1.
Provided the concentration of the fluorescent dye is sufficiently low, then the assumption that the fluoresced signal is linear in its concentration is reasonable. Deviations from this may be entered in the Dye calibration control.
The Concentration value is the (arbitrary) concentration used in the calibration images Left-hand light source and Right-hand light source. Note that these images are used not only to calibrate the response of the light sheet as it passes through the dye, but also to calibrate the intensity of the light sheet entering the dyed region. In this latter context it is important that these images (and also the experimental images) extent to the tank boundaries where the light first enters the dye.
The Ray from group indicates the direction from which the light rays enter the image. Here it is the bottom of the tank which corresponds to the right-hand side of the image. The Ray source type allows selection between single point light sources, distributed light sources, and double point light sources. (The Right-hand light source input stream is enabled only for the last of these.) The Defocus control recognises that the lights might not in fact be true point sources and that they will become slightly defocused as they pass through the flow.
Alongside the origin of the light rays is their direction which will not normally be aligned exactly with the pixel coordinates. Indeed, the light rays will typically be diverging. The Ray n group provides a means of specifying the orientation of light rays. This process is typically achieved by capturing an additional image of the uniform concentration in which a grid has been imposed on the light sheet in order to show clearly the direction of the light rays. This additional image (or two additional images when double light sources are used) is temporarily loaded into the Left-hand light source stream. Clicking Show rays then superimposes the ray definitions from the Ray n group on that image. Subsequent use of the controls within this group allows interactive specification of the orientation of the rays. It is recommended that three or four such light rays are specified as a minimum.


Figure 75: Light ray definition for LIF processing.
Up to ten sets of light rays may specified. Each set contains either one or two directions, depending on the Ray source type. The rays in each set share a common Start, but can have different rotations through the First ray and Second ray controls. The ray definitions may be reset using the Reset Rays button.
Modelling of the light sheet can be handled in a number of different ways using the Light sheet group. Both Model and Fix defects begin by fitting a model decay law (using least squares) to the calibration image(s) to determine the relationship between fluorescence and attenuation. If Iterative is checked, then this process is performed iteratively to improve the model by taking into account the directions of the light rays. In many cases the linear model 1;s; (corresponding to an exponential decay of light through the calibration image) is most appropriate. However, in some circumstances higher order terms can improve performance (a combination of visual inspection and tests for mass conservation should be used to determine the optimal model).
The difference between Model and Fix defects is that the latter compares the calculation performed on the calibration image with the ‘known’ constant concentration it contains and develops a multiplicative correction to force a uniform concentration in the output. This correction may be appropriate in cases where optical imperfections alter the apparent lighting in a static manner that does not coincide with the simple attenuation modelling.
Calculations using the Direct fit light sheet model are similar to the other two, but rather than fitting an exponential decay law, the data in the calibration image is used directly, pixel by pixel, to determine the relationship between fluorescence and absorption. This approach is likely to lead to a higher noise level in most situations, but may have advantages in cases with complex optical effects such as reflections.
For most good quality experiments, the combination of Fix defects with 1;s; and Iterative selected will yield the best results.
Finally, the output stream may be specified in the normal way using the Save As and Options buttons.
Synthetic schlieren is a novel technique for producing qualitative visualisations of density fluctuations and for obtaining quantitative whole-field density measurements in two-dimensional density-stratified flows. This set of techniques is outlined in detail in Dalziel et al. (2000) (and a subset in Sutherland et al. 1999). In this section, we discuss only the most advanced of these techniques, ‘pattern matching refractometry’, and how this may be applied to provide accurate quantitative measurements of a two-dimensional density field.
While synthetic schlieren has its origins in the classical optical schlieren and moiré fringe techniques, synthetic schlieren is much simpler to set up than the classical schlieren and interferometry methods, and provide useful information in situations where shadowgraph is of little or no value. Moreover, they may be set-up to analyse much larger domains than is feasible with the classical approaches, and do not require high quality optical windows in the experimental apparatus. Ultimately the greatest strength of these techniques is the ability to extract accurate, quantitative measurements of the density field.
The basic setup for synthetic schlieren is illustrated in figure 76. An illuminated mask (normally simply a piece of paper printed with a pattern) with a strong pattern is placed to the rear of the experiment. This mask is then viewed by the video camera looking through the experiment.

Figure 76: Basic setup for synthetic schlieren. An illuminated textured mask is placed on one side of the experiment, and is viewed by the camera on the other side of the experiment.
The key idea behind synthetic schlieren is the bending of rays of light by fluctuations in the refractive index field. A detailed description of this process is required in order to make quantitative measurements. This description may start from a number of points. Sutherland et al. (1999) analysed a ray of light by invoking Snell’s law. Here we shall start from Fermat’s variational principle for the behaviour of light in an inhomogeneous medium
where s is oriented along the light ray and n(x,y,z) is the refractive index field (the ratio of the speed of light through a vacuum to that through the medium). We select our coordinate system (x,y,z) with x along the length of the tank, y across the width (the direction in which variations in the flow are negligible) and z vertically upward.
Rather than solving the full variational problem, we restrict ourselves to rays of light which always have a component in the y direction so that their paths may be described by x = x(y) and z = z(y). This restriction is simply a requirement that light is able to cross the tank, a fundamental requirement for synthetic schlieren. The variational principle then gives rise to a pair of coupled ordinary differential equations (Weyl 1954) relating the light path to the gradients of n in the x-z plane:
. (11b)
For synthetic schlieren we are interested primarily in light rays which remain approximately parallel to the y direction. Under this restriction the terms (dx/dy)2 and (dz/dy)2 may be neglected, effectively decoupling (11a) and ((11b). For a two-dimensional flow where there are only weak varitions in density (and hence weak variations in the refractive index) along the ray path, we may integrate these expressions across the width W of the tank to obtain the path of the light ray across the tank:
, (12b)
where xi, zi describe the incident location and tanfx = dx/dy(y=y0) and tanfz = dz/dy(y=y0) describe the horizontal and vertical components (respectively) of the angle at which the light ray enters the tank (measured relative to the y direction).
With synthetic schlieren, we are interested in how an image of a mask placed some distance B behind the tank appears to change as the result of flow-induced refractive index variations relative to the refractive index variations in the absence of the flow. Specifically we wish to analyse the changes in the image formed by the camera as a shift in the origin of the light ray reaching the camera. By back tracking the light rays received by the camera the apparent shift (Dx,Dz) in the origin of the light ray is given by
. (13b)
Here we have decomposed the refractive index field n into n0 + nbase + n', where n0 is the nominal refractive index of the medium (e.g. n0 = 1.3332 for water), nbase represents spatial variations associated with the “known” base state (e.g. the changes introduced by adding a quiescent linear background stratification) and n' is the variation caused by the flow under consideration (e.g. the internal wave field). In obtaining (13) we have assumed the variations nbase and n' in the refractive index field are small compared with the nominal value n0. (As we will see below, a correction is necessary to take into account the refractive index contrasts between air, the material the tank is made of and the working fluid.)
In many cases, it is more convenient to consider the apparent displacement of the origin of the light rays in terms of their projection on the experiment in the absence of any fluctuations in the density field. This then allows us to use a common coordinate system for both the coordinates within the experiment and for the texture mask located behind the experiment. Taking the distance between the texture mask and the camera as L, and assuming that the experiment is ‘thin’ (i.e. W/L << 1), then we may use simple projective geometry to show that the apparent displacements in experiment coordinates are
. (14b)
Here we have defined the experiment coordinate system to be at the mid-plane of the experiment. If W/B << 1 or (B+˝W)/L << 1, then the precise location of the coordinate system within the experiment is unimportant. Note also that the optical gain provided by increasing B is greatest for large L.
The above expression, however, ignores the effect of the refractive index change between the tank and the (presumably) air between the tank and the mask. Taking the refractive index of air as nair, then this amplifies the slope on exit from the tank by n0/nair. An additional correction can also be made for the refractive index of the tank wall, nwall. This does not change the slope within the air, but does provide an additional offset. If the tank wall has thickness T and we measure B from the outside of the tank wall, then (14) becomes
in the coordinate system of the textured mask. Similarly, if the experiment is not thin, then the magnification term projecting this onto the central plane must take into account the refractive index variations for rays entering and leaving the tank. The net result of this is that
. (16b)
As stated above, there is normally a constitutive relationship between the density of the fluid and the refractive index. To a good approximation the relationship between refractive index and density for salt water is linear (Weast 1981), allowing us to write
where
and r0 is the nominal reference density (1000kg m-3). Substitution into (13) then gives the relationship between density fluctuations r' and apparent movement of the source of a light ray
. (19b)
Simply measuring the apparent displacements and inverting (19) then allows us to determine the perturbation density gradient. This may, in turn, be integrated once to return the density perturbation itself.
The main difficulty is determining the apparent displacements Dxexp and Dzexp with sufficient accuracy for the whole process to be meaningful. Often the apparent displacements are only a small fraction of a pixel. DigiFlow employs a range of techniques to achieve this. The most accurate, but computationally expensive, use powerful pattern matching techniques to determine the apparent displacement as accurately as possible: the design of this part of the system has concentrated more on accuracy than speed. DigiFlow also offers faster (but less accurate) techniques to provide a reasonable approximation relatively quickly.
This option provides a qualitative or semi-quantitative preview of an image sequence using relative simple processing to determine the gradient of the perturbation density field. The processing used here is similar to that provided during Video Capture (see §5.1.4).
Starting the option provides access to a simple dialog box (see figure 77) for selecting the input image stream (Experiment selector) and, optionally, a Background Image. If the latter is not specified, then the first frame of the Experiment file is utilised. Both these selectors have the standard Sift button (see §4.3).

Figure 77: Dialog for determining which sequence is to be previewed with synthetic schlieren.
Once the sequence has been identified, an image window is opened to show the preview. The preview itself is controlled by a second dialog. Some of the controls on this dialog are reminiscent of those seen in §5.5.1.14 for controlling the animation of sequences. Controls specific to synthetic schlieren are found in the Processing and Gain groups. The first of these determines the type of processing to be performed.

Figure 78: Control dialog for qualitative synthetic schlieren preview.
There are four processing options: Direct simply shows the input stream without any processing, while Difference is the simplest (and computationally fastest) technique that provides a qualitative output proportional to the magnitude of the gradient in the density perturbation. The Horizontal gradient and Vertical gradient options perform more a more sophisticated analysis that returns a semi-quantitative output of the specified component of the gradient in the density perturbation. Note that these two options distinguish between positive and negative gradients.
The Gain control determines the relationship between the gradient and the intensity of the display. The display colour scheme may be changed using Colours, and a different set of input streams may be used by clicking Selectors.

(a) (b)

(c) (d)
Figure 79: Examples of output from Qualitative Synthetic Schlieren. (a) Direct, (b) Difference, (c) Horizontal gradient and (d) Vertical gradient.
The Synchronise display check box forces synchronisation such that each and every frame in the sequence is displayed, even if this slows the update rate below the desired frame rate. If Synchronise display is cleared and the computer cannot keep up with the desired frame rate, then frames are skipped to maintain that frame rate.
The method of calculating the synthetic schlieren image used in this option is a compromise between speed and accuracy. While it is based on a similar technology to that used in the Qualitative Preview version of synthetic schlieren discussed in §5.6.4.1, the algorithm is tuned to give a wider dynamic range, greater accuracy, and more complete coverage of data. However, the resulting measurements remain less accurate than those obtained using Pattern Matching version of synthetic schlieren (see §5.6.4.3).
The processing here was conceived for masks located behind the experiment containing lines, however experience has shown that it also provides reasonable semi-quantitative measurements for other mask geometries (e.g. random dots).
Suppose the changes in the refractive index gradient give an apparent vertical displacement of the mask by some amount Dz at time t. We shall assume the curvature in r' is small so that Dz varies only over length scales large compared to the features contained in the mask.
As we have seen, the intensity of a pixel is related to the mean of the (unknown) intensity falling on the CCD sensor by
The combination of optical imperfections, noise and imperfections in the mask will ensure that p(x,z;t) is a continuous function, even when the mask contains discrete steps. We may approximate p(x,z;t) using a piece-wise quadratic interpolation in a manner similar to that employed for numerical solution of the advection equation in control volume techniques. The idea here is that the approximation Pij(t) = p(xi,zj;t) (approximating the integral in (20)) by the so-called mid-point rule for numerical integration) has an error O(Dz3) which is of the same order as the error in a quadratic interpolation of the intensity (xi,zj). More specifically, if 0,ij(z-zj) is the quadratic interpolation of the unperturbed image around (xi,zj), we look to solve for the value z-zj = Dzij such that 0,ij(Dzij) = Pij(t). Thus the apparent displacement (in the z direction) of the mask Dzij is given by the roots of
P0,0 - P + ˝(P0,1 - P0,‑1)Dz + ˝(P0,1 - 2P0,0 + P0,‑1)Dz2 = 0. (21)
Here we have used the shorthand P = Pij(t), P0,0 = P0,ij, P0,‑1 = P0,i,j‑1 and P0,1 = P0,i,j+1. To avoid ambiguity as to which root of (21) should be taken, we solve (21) only if P0,0 is intermediate between P0,-1 and P0,1, and the intensity contrast across the three lines is sufficiently large (i.e. |P0,1‑P0,‑1| > DPmin). Further, we select the root of (21) with smallest |Dz|, effectively limiting Dz to be less than the spacing of the lines on the mask.
As an alternative to solving the quadratic expression for Dz given by (21), we may utilise a binomial expansion to show that this process has the same O(Dz2) accuracy as assuming Dz is quadratic in P0,ij. This latter approach was used by Sutherland et al. (1999) and gives
As with (21), Dz is calculated from (22) only if P0,0 is intermediate between P0,‑1 and P0,1, and there is sufficient intensity contrast across the three lines.
Once Dz has been determined from either (21) or (22), it is mapped from pixel space into physical space and (19) is applied to determine ¶r'/¶z. Points for which Dz could not be calculated (typically points where ¶P/¶z is too small, as may occur if a line is centred on a pixel and would lead to an ambiguity in the sign of the displacement) are replaced by interpolated values using a Gaussian weighting function. The final result is scaled and used to construct an image representing ¶r'/¶z.
In the present implementation, if the value of Dz determined from (22) exceeds one pixel then the reference image intensities are themselves displaced so as to avoid extrapolation. This effectively increases the accuracy and dynamic range of the technique.

Figure 80: The inputs dialog tab for interpolative synthetic schlieren.
The Experiment stream, specified using File and optionally sifted with Sift, should contain an image of a strong texture located behind the experiment. DigiFlow then compares this input stream with a reference image to determine the apparent displacements. The reference image may be specified using the optional Background image input stream. If no stream is specified, then the first frame of the Experiment input stream is used instead.
As noted above, this method was conceived for masks containing lines, in which case Gradient direction should be set normal to the lines. The most accurate results will be obtained in this configuration. However, if the mask contains two-dimensional features (such as random dots), then it is possible to generate Both in-plane components of the gradient.
The Flow geometry group enables internal processing options that attempt to ensure the result is consistent with the underlying geometry of the flow.
Details of the experimental setup are required in the Lengths group to allow interpretation of the apparent movements of the dots. The units for these should be consistent with the units for the density gradient that will be determined. Ultimately, the output will be (1/r0)Ńr˘, which has dimensions of 1/length. Specifying the distances here in metres will give units of m-1 for the final result.
Note that a distance of zero is acceptable for Experiment to texture, the distance from the back of the experiment to the texture mask, but not for Experiment thickness. The Experiment thickness should be the internal measurement of the tank, while Experiment to texture should be measured from the outside of the tank. The Wall thickness should be specified for the wall closer to the texture, and its corresponding Tank wall material selected.
Camera to texture is the distance between the effective focal plane of the camera and the texture mask. It is generally sufficient to measure the distance from the base of the lens to the texture. Experiment to texture is the distance from the back of the experiment to the texture mask. This distance can be zero for some set ups. Experiment thickness is the width of the flow through which the light rays experience density fluctuations. This cannot be zero.
The Medium list box allows selection of different media for the experiment. The key detail, picked up from a DigiFlow data base, is the relationship between refractive index and density changes. In addition to the normal media, two pseudo media are also included: Unity returns refractive index gradients rather than density gradients, while (displacements) returns the calculated apparent displacements (with units of the selected coordinate system) rather than density gradients.
The coordinate system required to interpret the experiment is specified in the Coordinate system list box.

Figure 81: The outputs tab for interpolative synthetic schlieren.
The most important controls on the Outputs tab are for selecting the main output streams x Gradient and/or y Gradient. Whether one or both of these is required depends on the selected option in the Gradient direction group on the Inputs tab. The visual scaling of the images produced is determined by the Gradient entry in the Saturation values group. This value sets the gradient that will produce a saturated image. For most image formats, getting this wrong will require reprocessing of the image due to quantisation errors introduced. For this reason the use of the .dfi file format is recommended as this does not sacrifice dynamic range and the scaling may be subsequently changed at a later date.

Figure 82: The advanced control tab for interpolative synthetic schlieren.
In most cases the controls on the Advanced control tab should be left on Automatic. The Interrogation window group controls the limits on the quadratic interpolation that must be satisfied before the results can be used, and also controls how to fill in any missing values. The Validation group determines how to check for consistency with neighbouring points.
The most sophisticated (and slowest) of the synthetic schlieren algorithms is based on an advanced pattern matching algorithm that has its origins in PIV (Particle Image Velocimetry; see §5.6.5.2).
The mask behind the flow giving the texture to the image is typically constructed from random features of high contrast. The simplest way of generating this is by printing a pattern onto overhead projector transparencies and then tiling these up into a sheet of the required side with clear adhesive tape. The following PostScript file may be used to generate a suitable pattern. The pattern is a basic square grid of dots, with each of the dots perturbed by a random amount. The randomness helps prevent aliasing errors and ensures that the pattern is robust against any defects produced when you overlap slightly multiple tiles of transparency.
%!PostScript
% Generate dot pattern for synthetic schlieren
/mm {25.4 div 72 mul} def
% Set the basic size of the pattern (mean spacing in mm)
/Size 2 def
% Set the size of the sheet
/Sheet 300 Size mul def
% Relative size of dots to their mean spacing
/DotFraction 0.25 def
% Scale for randomnesss
/Randomness 0.6 def
% Draw black background
0 0 moveto
Sheet mm 0 rlineto
0 Sheet mm rlineto
Sheet mm neg 0 rlineto
closepath
0 setgray
fill
% Draw grid of white dots with random perturbations
1 setgray
0 Size Sheet
{/y exch mm def
0 Size Sheet
{/x exch mm def
gsave
x rand 0.25e9 div Size mul Randomness mul add
y rand 0.25e9 div Size mul Randomness mul add
%x y
translate
0 0 Size DotFraction mul mm 0 360 arc
closepath
fill
grestore}
for}
for
% Set number of copies of sheet to be made
/#copies 2 def
showpage
This PostScript file can be simply copied to any PostScript printer. If a PostScript printer is not available, an interpreter such as GhostScript/GhostView could be used. The pattern should be scaled (using the /Size definition) so that the dots are close to the limit of what the camera can resolve. Some trial and error may be required to determine the optimal size for a given experimental setup.

Figure 83: The Inputs tab of the synthetic schlieren dialog.
The synthetic schlieren interface is divided into six tabbed dialogs. The first two, Inputs and Outputs are mandatory and control what is to be processed, and where the results are to be stored, respectively. The other four tabs, Interrogation, Validation, Quality and User Interpolation may be used by experienced users to tweak the process to yield better performance in some situations. The more advanced controls on these tabs are not available under the Free DigiFlow Licence.
The standard synthetic schlieren process takes two input streams. The first, specified by the Experiment group, is the video sequence of the experiment itself. As normal, an image selector is used to specify the stream.. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box (see §4.1) is produced. Alternatively, clicking the Process button will allow a source process to be used (refer to §7 on chaining processes for further details).
The Background input takes a single image (specified in the normal manner). This image should be of the background texture mask before the experiment introduces any density perturbations. Typically, this image is taken just prior to the experiment, and contains all the ambient refractive index variations due to, for example, a background density stratification.
The Mask zeros check box causes DigiFlow to ignore all pixels with an identically zero intensity. This feature is designed to allow simple masking of images. Such masking may be used to remove parts of the field of view that do not contain the flow. For example, it could be a static boundary to the flow, a free surface, or possibly an object moving through the flow. In each case external processing of the image sequence should be made to apply the mask prior to starting the synthetic schlieren processing.
There are eight groups of controls on the Inputs tab. The first controls maximum apparent displacement that will be searched for. The values Max x and Max y are specified in pixels and are assumed symmetric about zero. These values should be set to represent slightly more than the maximum expected apparent displacement of the mask. In most circumstances this will be limited to two or three pixels, and will generally be isotropic (hence specify the same values for Max x and Max y). Note that the computation required to determine the displacement increases approximately as the product of these two values, hence specifying excessively large values is counterproductive.
The Flow Geometry group is used to indicate the basic geometry of the flow under consideration, and control the invocation of processes optimised for the specific geometry. The entries 2D and 3D have the obvious meaning. Similarly, Axisymmetric is for flows where the symmetry axis lies in the mid-plane (normal to the viewing axis) of the experiment, and Symmetric is for flows where the mid-plane is a plane of symmetry, but the flow is not axisymmetric.
The Lengths group specifies the geometric setup of the experiment. The distances should be specified in the same units as the selected coordinate system (see below), or it will be difficult to interpret the results of the calculation. Note that a distance of zero is acceptable for Experiment to texture, the distance from the back of the experiment to the texture mask, but not for Experiment thickness. The Experiment thickness should be the internal measurement of the tank, while Experiment to texture should be measured from the outside of the tank. The Wall thickness should be specified for the wall closer to the texture, and its corresponding Tank wall material selected.
Both input streams may be sifted (§4.3) to extract the desired subregion and times. This feature is activated using the Sift button associated with each of the input streams.
To provide a simplified interface to the internal workings of the synthetic schlieren algorithm, DigiFlow provides a range of predefined settings that have the effect of producing different resolutions and accuracies. The Resolution and Accuracy list boxes both have six possible settings: Very low, Low, Medium, High, Very high and Best. The choice will depend on a combination of the intended purpose of the results, and the time available to undertake the processing. The fastest processing is achieved at the Very low end of both scales, while the most detailed and accurate measurements are obtained with both Resolution and Accuracy set to Best. In the latter case, even with relatively basic analogue video equipment, the accuracy with which the apparent movement of the texture mask may be detected can be better than 1/100 of a pixel, and the spatial resolution of the measurements is a few pixels. By default, the Resolution and Accuracy controls will be enabled. However, if the Automatic check box for the Interrogation window group on the Advanced Control tab is cleared, then the Resolution and Accuracy controls will be disabled.
To determine the relationship between refractive index and density, DigiFlow requires that a fluid medium is specified with the Medium list box. This box contains a range of standard fluids (e.g. Water and Air), plus the special fluid Unity in which all the physical constants are set to unit values. In the context of synthetic schlieren, DigiFlow extracts the value of b = (r0/n0)(dn/dr) (see (17) and (18)) for the selected medium. Additionally, (displacements) will cause the pattern matching process to return the apparent displacements of the mask rather than the density gradient.
The final input on this tab is Coordinate System. This specifies the coordinate system that will be used to relate pixel to world coordinates. The coordinate system is assumed to have been defined in the mid-plane of the experiment (not the plane of the dots). See §5.2.5 for further details on setting up a coordinate system.

Figure 84: The Outputs tab of the synthetic schlieren dialog.
The Outputs tab controls the destination and scale of the output from the synthetic schlieren calculation. This dialog page consists of three image selectors, each with its own Options and File buttons and Display check boxes. The destination for the output stream is selected by clicking the File button (thus starting the standard Open Image dialog box; see §4.2), while the colour scheme and other related details are selected with the Options button (see §4.4).
The x Gradient, y Gradient and Density images are centred with a zero value corresponding to half the intensity range (i.e. 128 for an 8 bit image format). Saturation corresponds to the values given in the Scales group for Gradient and Density. The gradient images have the units of ‘per unit length’ (what the unit length is depends on the coordinate system selected), and represent Ńr˘/r0, unless (displacements) was specified for .the Fluid Medium on the Inputs tab.
The optional Density output (not available with free licences) is calculated by a least squares integration of the density gradient field. In general, integration of a vector field to find a scalar potential is not unique, as the vector field will contain both irrotational and rotational parts. With synthetic schlieren, the density gradient field should be irrotational, which would make the integration unique, but inevitable measurement noise renders some rotational component. The integration procedure used in DigiFlow aims to find the scalar potential (here r˘/r0) that minimise the root mean square of this rotational part (effectively minimising the enstrophy), hence is a least squares solution. The solution process is achieved iteratively using a multigrid approach that is aware of any missing data or masked regions in the synthetic schlieren results. (Inevitably, there is some data loss in the neighbourhood of any masked regions.) The integration procedure leaves one unknown arbitrary constant of integration which DigiFlow sets by forcing the spatial mean density perturbation to vanish. Of course, this may not always be appropriate.
The DigiFlow Data format (.dfd) or DigiFlow Pixel format (.dfp) may be specified for any of these output images so that the data is readable in other applications. However, it is recommended that the .dfi floating point format is used if you wish to make quantitative use of the data.
Selecting the Compact check box causes DigiFlow to save an approximation to the calculated density gradient field by only saving the gradient at the nominal location of the interrogation windows used to calculate the gradient. DigiFlow will automatically expand out this approximate gradient field, when it is reloaded, to produce one that is very close to that saved without the Compact option. The files produced, however, are much smaller.
Figure 85 shows an example of the density gradient fields and the density perturbation. Note that in all cases they are normalised by the reference density r0. The density gradient fields therefore have dimensions of per length; it is important that you use the same units for the Lengths group on the Inputs tab as you use in the chosen coordinate system, or else it will be difficult to interpret the output!
You may choose not to calculate the density perturbation while doing the synthetic schlieren computation, but instead calculate it later from the density gradient field. Tools: Recipies contains a suitable recipe to do this in the Differential group.

(a) (b) (c)
Figure 85: Example of synthetic schlieren output. (a) (1/r0) ¶r˘/¶x, (b) (1/r0) ¶r˘/¶x and (c) r˘/r0 for a thermal plume erupting from a boundary layer.

Figure 86: The Interrogation tab of the synthetic schlieren dialog.
The Interrogation page enables direct control over many of the underlying values of the synthetic schlieren calculation. For most users, checking the Automatic box yields optimal performance, with the Resolution and Accuracy controls on the Inputs tab providing all the performance tuning necessary. Advanced users, however, may wish to fine tune the processing manually; clearing the Automatic check box enables the remaining controls and disables the Resolution and Accuracy controls on the Inputs tab.
The Size subgroup controls the Width and Height of the interrogation window. Increasing the size of the window increases the accuracy, but decreases the spatial resolution and slows the computation. If the window is too small, relative to the pattern size, then very poor results are achieved. The Adjust check box specifies whether DigiFlow can adjust the size of the window if it thinks this is necessary to produce more reliable data.
The Spacing subgroup has the most direct control on the spatial resolution of the synthetic schlieren computation. This specifies the x and y spacing between points where the pattern matching process is undertaken. Clearly reducing this value, specified in pixels, increases the amount of computation, but may not always increase the spatial resolution due to the interplay with the Size of the interrogation window.
The Difference measure subgroup specifies the type of difference calculation. This is the function that DigiFlow minimises as it searches for the correct apparent shift. In practice, there is little to choose between the three functions. The Absolute option is computationally a little cheaper, while Correlation is that frequently used in PIV techniques. Table 1 summarises the various difference measures f that may be used in DigiFlow. Note that in all cases the summation is over N valid pixels in the interrogation region. The Power option is simply a generalisation of Absolute and Square. The Normalise check box rescales each of the measures, based on the strength of the texture in the interrogation region.
|
f |
Standard |
Normalised |
|
Absolute |
|
|
|
Square |
|
|
|
Power |
|
|
|
Correlation |
|
|
Table 1: The difference measures used in DigiFlow pattern matching.
The Peak fitting transform group determines the method of processing interpolating in the neighbourhood of the smallest value of the difference measure f (or largest value, for the case of the correlation measure) in order to provide an improved estimate. In all cases a bi-quadratic least squares procedure using nine points is employed. However, DigiFlow provides the option of transforming the difference measure prior to undertaking the fitting. The possible transformations are shown in table 2. Note that the logarithmic option effectively assumes a Gaussian form for the difference measure in the neighbourhood of the optimal shift.
|
|
None |
Linear |
Square |
Log |
|
Absolute |
f |
f |
f 2 |
log(f) |
|
Square |
f |
Öf |
F |
log(f) |
|
Power |
f |
f 1/p |
f 2/p |
log(f) |
|
Correlation |
f |
f |
f 2 |
log(f) |
Table 2: Transformation of the difference measure f prior to computing bi-quadratic least squares fit.
The Subpixel passes subgroup has a pronounced effect on the accuracy, resolution and speed of the calculation. The radio buttons determine the basic type of treatment to obtain improved subpixel accuracy: None is the fastest but least accurate. Linear offers a good compromise between speed and accuracy, while Cubic provides the best results, but is substantially slower. The Passes edit box controls the number of levels of subpixel treatment. For Linear a value of 1 to 3 is recommended, while Cubic normally only requires 1.
The Interpolate fields radio group controls how the data, initially obtained only at the centres of the interrogation zones, is expanded to fill the complete image. The simplest option of Linear, which uses a bilinear interpolation, tends to end up with an artificial appearance. The next level of sophistication, Cubic, produces a good balance between speed and accuracy. While the resulting fields are continuous, they are not continuously differentiable. This problem is overcome by the computationally more expensive cubic b-spline and the quintic b-spline. For most circumstances either the cubic or cubic spline provides the best compromise between computational efficiency and accuracy.
If the interrogation window Spacing is small to improve the spatial resolution, then it is recommended that Also distorted is checked. This enables DigiFlow’s unique image distortion technology to substantially increase the spatial resolution. A further improvement in both resolution and accuracy may obtained in some circumstances by also checking Also reverse.However, for high quality images, undertaking the reverse pass may lead to a deterioration in the quality of the results.
Checking Discard in Big differences will dynamically discard pixels that DigiFlow determines may not belong to the pattern it is trying to match. While discarding valid pixels can detrimentally affect the signal to noise ratio, retaining invalid ones can have an even more serious effect. The Limit controls the level at which pixels are discarded.
For images that have a poor signal to noise ratio, a fluctuating level of illumination, and strong spatial gradient in intensity, a spurious signal can be obtained from the interaction between the spatial gradient and the temporal fluctuations. The Mean differences group controls whether DigiFlow will attempt to correct for this by rescaling the image intensities to remove this signal. Selecting None will turn off the image rescaling to deal with mean differences between images, while Global will force the mean intensity of the two images (excluding any pixels of zero intensity) to be the same. The processing invoked by Local is similar to that of Global except that it does it locally for individual interrogation windows. While Local may superficially seem the most attractive, the results are much more sensitive to noise and should only be used when there is no other solution. The Automatic setting will attempt to assess which of the other three settings is most appropriate.
The Algorithm control provides access to different internal versions of the pattern matching algorithm, thus ensuring backward compatibility.
The Enstrophy weighting controls the weighting applied to the condition that the apparent displacements must be expressed as the gradient of a scalar when determining the optimal apparent shift of the dots. The way in which this weighting is used depends on the Flow geometry setting in the Inputs tab.
Setting Predict using last result will suppress the initial pixel pass for points where a result has been calculated previously. This reduces the time required to converge on a solution.

Figure 88: The Validation tab of the synthetic schlieren dialog.
Clearing the Automatic check box in the Validation group allows direct user control over the parameters that control validation of the individual apparent displacement vectors. Min texture prohibits computation when the standard deviation of intensity within the interrogation window is less than the specified value. Similarly, Min range sets the minimum range (maximum minus minimum values) the intensity within the interrogation window must have before computation is permitted. Min curvature imposes a lower limit on how sharp the difference measure around optimal apparent displacement must be, while Reject difference imposes an upper bound on the difference measure. If the difference measure exceeds Accept difference multiplied by the range of intensities within the interrogation window (but is less than Reject difference, again multiplied by the range within the interrogation window) then it is subject to additional checks and processing to try to improve and ensure the quality of the resulting data.
The Outliers subgroup handles the identification and resolution of apparently erroneous data. For a well set up experiment, there should not be any erroneous data to be corrected. This feature is enabled by the Remove check box, with Limit applying to the difference between the value at the point and the mean of the neighbouring four vectors. This limit is expressed in terms of the apparent pixel displacements. If the Limit is exceeded, then the value is either Discarded, or relaxed towards a Linear or Cubic interpolation.
The apparent displacement field visualised by the synthetic schlieren is due to the gradient of the refractive index field. As such, the apparent displacement field should be irrotational since curl(grad(×)) ş 0. The Projection group attempts to make use of this as part of the validation process by projecting the measured displacement field onto an irrotational space when Onto irrotational space is selected. This projection will be made for every iterated value of the measured displacement field unless the Interpolation step only box is checked. When checked, the projection will only be applied to displacement fields used to the steps used to distort the images.
The final group, Means, is enabled by clearing its Automatic check box. The three check boxes within this allow for the removal of apparent mean gradients in the measurements. The Remove x mean control scans the data for each y and removes any mean apparent displacement for that y. The Remove y mean performs a similar calculation for each x, while Remove global mean simply calculates the mean apparent displacement for all the data, and subtracts this from the data. In most circumstances it is unnecessary to remove the means, but there are times when extraneous optical effects, or experimental setups such as having the camera and texture mask mounted on a traverse, will make this facility desirable.
DigiFlow determines a range of additional information about the apparent displacement field that represents the density gradient during the processing of the experimental images. While for most users this additional information is of little value, the Quality tab makes it possible to output some of this for advanced users.
This output requires a .dfi file if all the information is to be retained as there are multiple planes of data available. In particular, these planes contain the following information:
|
Plane |
Description |
|
0 |
Difference measure. This is the value of the difference measure (see Table 1) for the final match. |
|
1 |
x curvature. The curvature in the difference measure in the neighbourhood of the final match. |
|
2 |
y curvature. The curvature in the difference measure in the neighbourhood of the final match. |
|
3 |
State. Indicates the state of the pattern matching. State values are integer (although stored as floating point) as follows: 0 Good vector 1 No data 2 Insufficient texture 3 Insufficient curvature in difference measure 4 Difference too great – rejected 5 Displacement too great 6 Outlier 7 Interpolated value 8 No match found -1 Value set by user dfc code -2 Value set by user interpolation code -3 Value excluded by user dfc code. |
|
4 |
Fraction discarded. The fraction of the pixels in the interrogation window that were discarded due to them being too different between the two images. |
|
5 |
x vector position. Stores the location (in world units) at which the vector was determined. |
|
6 |
y vector position. Stores the location (in world units) at which the vector was determined. |
|
7 |
x displacement. Stores the actual displacement (in pixels) determined. |
|
8 |
y displacement. Stores the actual displacement (in pixels) determined. |

Figure 89: The Quality tab for synthetic schlieren.
As part of the pattern matching procedure, DigiFlow interpolates the apparent displacement field determined at discrete points to the entire image plane in order to distort the images. The performance of the pattern matching depends on the quality of this interpolation, but the default techniques may not always be optimal. Hence, the User Interpolation tab provides the user with a way of bypassing the default mechanism and supplying their own customised scheme.

Figure 90: The User Interpolation tab for synthetic schlieren.
The tab is activated only if Automatic interrogation is turned off on the Interrogation tab, and the Use user interpolation check box is checked on the User Interpolation tab. The default sample code uses a weighted least squares approach to completing the interpolation. This is more computationally costly than the default method, but provides a more robust method of handling missing data.
Parameters passed to this code include the interrogation-window apparent displacement vector uv, the required output resolution nx, ny, the nominal interrogation window size wx, wy (in pixels), the spacing between the vectors dx, dy (in pixels), the location of the first vector x0, x1, and the quality measure Quality. The string calltype indicates the point in the algorithm when the call to the filter is made. This may take one of the values "Pixel", "SubPixel", "Reverse", "Distorted" or "Final". The experimental image Pa and background image Pb are also available.
When OK is pressed, the dialog box will check that all mandatory values have been entered. If they have not, then the focus will return to the page and control of the first missing value.
The progress of the processing may be viewed by selecting the Progress window that appears once synthetic schlieren has started. The contents of this window are updated periodically during the processing of each of the images from the Experiment stream. Most of the time, this window provides information on the apparent vertical shift of the texture mask. The title bar on this window and the ‘thread message’ panel on the main status bar provide details of the individual calculations as they are performed.
The basic processing algorithm may be summarised by the following steps:
1 Determine optimal pixel shift.
ŕ Determine optimal pixel shift by moving interrogation window around on Experiment image, measuring the difference between this and the comparable unshifted window on the Background image.
ŕ For each optimal pixel shift, use a bi-quadratic least squares to obtain subpixel resolution.
ŕ Repeat for each grid point on this level.
ŕ Refine grid to next level by bi-linear interpolation, in a multi-grid-like process.
2 Determine optimal subpixel shift.
ŕ Determine optimal shift in a manner analogous to the pixel shift, but using an interpolated version of the Experiment image to allow smaller shifts to be probed.
ŕ For each optimal subpixel shift, use a bi-quadratic least squares to obtain an improved estimate of the optimal shift.
3 Determine optimal distorted shift.
ŕ Use the current estimates of the apparent displacement to distort the Experiment image back to the Background image (i.e. try to undo the apparent movements).
ŕ Repeat the optimal subpixel shift process, using this distorted image.
ŕ The optimal shift from this process should be small (it represents the error in the previous optimal shift) is used to correct the optimal subpixel shift
4 Repeat steps 3 the required number of times, each with a smaller subpixel shift of the Experiment image.
5 Repeat steps 2 and 3, but shifting the Backround image rather than the Experiment image.
ŕ The optimal shift that is produced by this reverse shift is inverted and itself distorted to shift it back to the Background frame of reference.
6 The forwards and distorted reverse shifts are combined to produce the ultimate optimal subpixel shift.
7 The shift is transformed to world coordinates.
8 The world coordinate shift is transformed into gradients in the density perturbation.
9 The density perturbation is computed by integrating the gradient field.
ŕ The direct integration method used does not require boundary conditions, and the arbitrary constant of integration is defined so that the mean perturbation vanishes.
During the processing, DigiFlow will display a Progress window that provides feedback on the performance of the pattern matching algorithm. One of the key components of this is the classification of displacement vectors by drawing boxes at their roots if there is some potential problem. The table below lists these classifications and gives a description of the various categories and an indication of the control that can affect this.
|
Symbol |
Description |
Advanced Control page |
|
Red cross |
No valid displacement vector |
|
|
Blue box |
The image does not contain an adequate texture for the matching to be reliable. |
Advanced: Min range Advanced: Min texture |
|
Magenta box |
The difference function being minimised does not have a well-defined peak. |
Advanced: Min curvature |
|
Yellow box |
The value of the difference function is too large. |
Advanced: Reject difference |
|
Light red |
The best match is found beyond the limit of the permissible shifts. |
Inputs: Displacements |
|
Dark green box |
The optimal match produced an outlier. This has been replaced by an interpolated value. |
Advanced: Outliers |
|
Green box |
Vector is the result of interpolation from surrounding vectors. |
|
|
Light magenta |
A best match could not be found. |
Inputs: Displacements: Max x and Max y |
Processing of particles is split between this submenu, which includes particle streaks (§5.6.5.1) and Particle Image Velocimetry (§5.6.5.2), and the Particle Tracking submenu (§5.6.6).
The Show as Streaks option provides a convenient method of reviewing and presenting image sequences containing particles. Such sequences will often be subsequently analysed in more detail using either Particle Tracking Velocimetry (PTV) or Particle Image Velocimetry (PIV). However, it is normally worth reviewing the sequence first as streaks as this will often give significant insight into the structure of the flow, regions where things are steady, and where the flow is unsteady, and where the contrast is adequate to proceed with quantitative measurements.
Two dialog boxes are produced as standard during the Show as Streaks process. The first (see figure 91) allows selection of the input data stream in the standard manner. Under most circumstances there will be no need to use Sift to change the timings, as this can be done subsequently. However, the exception to this is when dealing with image sequences that are interleaved so that images at different levels in a flow (for example) are stored adjacently and only every nth image is at the same level. In this case it may be desirable to set the time step using Sift.

Figure 91: Dialog box used to specify the input stream for the Show as Streaks facility.
The main control dialog (see figure 92) consists of standard video controls, track bar and speed control. This dialog sits alongside a floating window containing the processed streaks image. Note that you may swap between these with the mouse to pan the image around, if desired. Note that both windows are floating (i.e. they are not required to remain within the main DigiFlow window).

Figure 92: Dialog controlling the Show as Streaks facility.
The Processing group determines how the displayed image is to be constructed from the raw image stream. Direct simply shows the raw image, Threshold segments the raw image into a binary image prior to combining with a stored image (the Threshold group determining the intensity level for this split), Maximum intensity will take the greater of the intensity in the current image and the corresponding pixel in the stored image, Minimum intensity will take the smaller of the intensity in the current image and the corresponding pixel in the stored image, and Average will generate the streaks using a simple arithmetic averaging process. In all cases (except for Direct) the intensity of the stored image is reduced by the amount specified by the Decay group each time a new image is added, thus providing a fading memory of the flow. The Reset button clears the stored image, thus resetting the streaks.
Which processing option produces the best results depends in part on the quality of the original images. For clean images with uniform illumination and good contrast, Threshold is likely to produce the best results. However, if the images have strong variations in illumination, such as shown in figure 93, the Maximum intensity option produces more satisfactory results.

Figure 93: Example image from streaks facility. Here the field of view was 2.5´2.5m and particles illuminated by a 5W argon laser. The streaks show barotropic vortices interacting with the baroclinic hydraulic exchange through a strait containing an island.
The Synchronise display check box forces synchronisation such that each and every frame in the sequence is displayed, even if this slows the update rate below the desired frame rate. If Synchronise display is cleared and the computer cannot keep up with the desired frame rate, then frames are skipped to maintain that frame rate. In most cases streak images work best if frames are not skipped (i.e. you should normally have Synchronise display checked).
The Particle Image Velocimetry (PIV) component of DigiFlow has a great deal in common with the pattern matching synthetic schlieren component (§5.6.4.3), and indeed many of the unique features in the PIV system owe their development to synthetic schlieren.
The PIV interface is divided into a number tabbed dialogs. The first two, Inputs and Outputs are mandatory and control what is to be processed, and where the results are to be stored, respectively. The remaining tabs may be used by experienced users to tweak the process to yield better performance in some situations. Only the first two tabs are available under Free DigiFlow licences.

Figure 94: The Inputs tab of the PIV dialog.
The standard PIV process takes two input streams. The first, specified by the Experiment group, is the video sequence of the experiment itself. As normal, an image selector is used to specify the stream. This selector may be specified from a file by clicking the File button, in which case the standard Open Image dialog box is produced. Alternatively, clicking the Process button will allow a source process to be used (refer to §6 on chaining processes for further details).
The second stream, the Earlier Image input, may be tied to the Experiment stream by the One stream check box, or taken from an independent data source. In either case the interval between these two streams should be specified in the Interrogation interval group. If One stream is used, then Interrogation interval is specified in frames. If separate image streams are used, then the Interrogation interval is specified as the time interval between the two streams.
The Mask zeros check box causes DigiFlow to ignore all pixels with an identically zero intensity. This feature is designed to allow simple masking of images. Such masking may be used to remove parts of the field of view that do not contain the flow. For example, it could be a static boundary to the flow, a free surface, or possibly an object moving through the flow. In each case external processing of the image sequence should be made to apply the mask prior to starting the PIV processing.
There are four groups of controls on the Inputs tab. The first controls maximum displacement that will be searched for. The values x Max shift and y Max shift are specified in pixels and are assumed symmetric about zero. These values relate to the maximum expected particle displacement but need to be as large as that shift (they parameterise the initial search space for the particle displacement, but DigiFlow will search a larger space if necessary). In most circumstances the default 3 pixels is adequate. Note that the computation required to determine the displacement (and hence velocities) increases approximately as the product of these two values, hence specifying excessively large values is counterproductive.
If the velocity field has a significant bias in one direction (e.g. there is a mean flow), then specifying a nonzero x Bias and/or y Bias will allow greater computational efficiency by permitting smaller values for x Max shift and y Max shift. The units of x Bias and y Bias are pixel displacements and have an effect similar to shifting the second image by negative the specified amount. For example, if there is a mean velocity down and to the right, then you would specify x Bias as positive and y Bias as negative.
To provide a simplified interface to the internal workings of the PIV algorithm, DigiFlow provides a range of predefined settings that have the effect of producing different resolutions and accuracies. The Image quality, Resolution and Accuracy list boxes both have six possible settings: Very low, Low, Medium, High, Very high and Best. The choice will depend on a combination of the intended purpose of the results, and the time available to undertake the processing, and the quality of the original images. The fastest processing is achieved at the Very low end of both scales, while the most detailed and accurate measurements are obtained with both Resolution and Accuracy set to Best. In the latter case, even with relatively basic analogue video equipment, the accuracy with which the particle displacement may be detected can be better than 1/100 of a pixel in ideal circumstances (e.g. no particles disappearing), and the spatial resolution of the measurements is a few pixels. By default, the Image quality, Resolution and Accuracy controls will be enabled. However, if the Automatic check box for the Validation group on the Advanced tab is cleared, then Image quality is disabled. Similarly, the Interrogation window group on the Advanced tab is cleared, then the Resolution and Accuracy controls will be disabled.
The final input on this tab is Coordinate System. This specifies the coordinate system that will be used to relate pixel to world coordinates. The coordinate system is assumed to have been defined in the mid-plane of the experiment. See §5.2.5 for further details on setting up a coordinate system. Note that if you select a pixel coordinate system, then the To World Coordinates tool (§5.7.6) may be used to retrospectively convert the pixel PIV results to a world coordinate system. (It is generally better, however, to compute the PIV using the appropriate world coordinate system in the first instance.)
The Outputs tab controls the destination and scale of the output from the PIV calculation. This dialog page consists of two image selectors, each with its own Colour and File buttons. The destination for the output stream is selected by clicking the File button (thus starting the standard Open Image dialog box), while the colour scheme to be used with the stream is (optionally) selected with the Colour button. At least one of the four output streams must be given a file name before OK will close the dialog box and start the process.

Figure 96: The Outputs tab of the PIV dialog.
The mandatory Velocity output selector will contain an image of the velocity field calculated. It is recommended that you specify either a DigiFlow Drawing file (.dfd) or a DigiFlow Image file (.dfi) rather than an industry standard raster image format for this output. In general, a .dfi file is to be preferred. In a .dfd the velocity data as ASCII data in conjunction with a series of drawing commands. This format is very convenient if you are using other software to process the results as reading these files is straight forward. They are, however, not very compact. Using a .dfi file stores the velocity data as velocity data, but allows this to be processed by DigiFlow as though it were an image. For example, the time average facility (see §5.6.1.1) and most of the other manipulation tools can be used to process the velocity data. In general, saving the data in .dfi format will be preferable until you have finished all processing.
The scale length of the velocity arrows is determined by the Velocity scale setting. A unit value draws the arrows of a length equal to the distance the particles have moved in the time interval between the two images used in the PIV calculation. Increasing Velocity scale causes the length of the velocity to increase, etc. This approach allows Velocity scale to be largely independent of the coordinate system used. For many flows, a value of 2 to 10 is appropriate. Note that if Velocity scale is negative, then the arrows are drawn in the reverse direction.
The background to the velocity field may be selected through the Vector background control. Selecting (none) gives a plane white background for the velocity field map, and the output stream stores only the velocity field itself. When Vorticity is selected for the Vector background, then the vorticity field is calculated and stored in the output stream; the vorticity field is also displayed as a colour map behind the velocity field. The Experiment and Streaks options place an image of the experiment behind the velocity field (also storing it in the output stream). The Experiment option is self-explanatory, while the Streaks option synthesises a streak image (see §5.6.5.1 for an example of a streak image) to be displayed.
Selecting the Compact check box causes DigiFlow to save an approximation to the calculated velocity field by only saving the gradient at the nominal location of the interrogation windows used to calculate the gradient. DigiFlow will automatically expand out this approximate velocity field, when it is reloaded, to produce one that is very close to that saved without the Compact option. The files produced, however, are much smaller. This option works well with either no background, or using the vorticity field as a background. However, as the background is compressed in the same way as the velocity field, this option does not work so well when selecting either the experiment or particle streaks as the background.
The Save x,y positions is not normally necessary. This will add two data planes to each .dfi output by the PIV process, with one plane containing the x coordinate of every pixel, and the other the corresponding y coordinate. Note that the Quality output (see the discussion below on the Quality tab) also provides access to the location of each of the interrogation vectors.
If Classify vectors is checked, then the velocity vectors produced include an indication of the quality of the vector. This is indicated by a box or cross drawn at the base of any suspect vector, as per the table below. Note that the Progress window (which is always produced to show the progress of the PIV calculation) will also show this information, even if Classify vectors is turned off. At present, classification will only be indicated on output to .dfd files.
|
Symbol |
Description |
Advanced Control page |
|
Red cross |
No valid velocity vector |
|
|
Blue box |
The image does not contain an adequate texture for the matching to be reliable. |
Interrogation: Min range Interrogation: Min texture |
|
Magenta box |
The difference function being minimised does not have a well-defined peak. |
Interrogation: Min curvature |
|
Yellow box |
The value of the difference function is too large. |
Validation: Reject difference |
|
Light red |
The best match is found beyond the limit of the permissible shifts. |
Inputs: Displacements |
|
Dark green box |
The optimal match produced an outlier. This has been replaced by an interpolated value. |
Validation: Outliers |
|
Green box |
Vector is the result of interpolation from surrounding vectors. |
|
|
Light magenta box |
A best match could not be found. |
|
|
Yellow circle |
At least 5% of pixels discarded |
Interrogation: Big differences |
|
Red circle |
At least 20% of pixels discarded |
Interrogation: Big differences |
The vector field may be superimposed on a range of backgrounds. These are selected by the Vector background list box. If (none) is specified, then a plain, white background is used, whereas Experiment leads to the vectors being superimposed on the corresponding experimental image. Similarly Vorticity draws the arrows on an image of the vorticity field.
The Vorticity output selector is optional, and should normally specify a raster image format file. The Scale setting controls the rendering of the vorticity as a colour map. The value specified here will be taken as the saturation limit of the false colour map produced. Thus decreasing Scale amplifies the vorticity map. Note that this scale is used to determine the scaling of the vorticity map behind the velocity vectors if Vorticity is specified for Vector background, regardless of whether a separate vorticity output file is being created. Since vorticity has dimensions of inverse time (and so does not have a length scale), the scaling of vorticity is largely independent of the coordinate system selected.
Note that outputting the velocity field to a .dfi file works best when the coordinate system is essentially aligned with the image. In all cases the velocities are determined on a regular grid in pixel space. When output to a .dfd file, the velocity vectors will be displayed in world coordinates with a standard Cartesian grid in physical space; this may mean that the original pixel coordinates are no longer Cartesian. When output to a .dfi file, the original pixel coordinates remain Cartesian, and the world system may remain distorted.
The Interrogation tab is identical to that for synthetic schlieren described in §5.6.4.3. Most users will not need to disable the automatic settings on any of the controls.

Figure 99: The Interrogation tab of the PIV dialog.
The Interrogation tab is nearly identical to that for synthetic schlieren described in §5.6.4.3. Most users will not need to disable the automatic settings on any of the controls. One difference is that the Projection group contains an additional option, allowing projection of the velocity field onto either irrotational or incompressible (solenoidal) spaces. The latter is most likely to be of use when considering two-dimensional flows, as it only attempts to make the divergence in-plane measured velocity field vanish. In most other circumstances the projection should be turned off.

Figure 102: The Validation tab of the PIV dialog.
The User Filter tab provides the user with the ability to supplement or override DigiFlow’s normal validation filters. When enabled DigiFlow provides the user’s dfc code with the two images as the variables Pa and Pb, along with the pixel displacements as the two-dimensional arrays u and v. The locations of these vectors are supplied in x and y, while the current state of the vector is indicated by state. Finally, the string calltype indicates the point in the algorithm when the call to the filter is made. This may take one of the values "Pixel", "SubPixel", "Reverse", "Distorted" or "Final". The values taken by the state array reflect DigiFlow’s default assessment of the individual displacement vectors. A list of the categories is given in the lower half of the User filter tab.

Figure 106: The User Filter tab.
The user code should return a compound variable containing the components .state, .u and .v, each of which are arrays of the same size as the corresponding arrays provided to the dfc code. The return values in .state request DigiFlow to treat the displacement vector in the manner specified in the lower half of the User filter tab. If .state for a given vector is set to -1 then the vector supplied .u and .v will be used in place of that calculated by DigiFlow.
The User interpolation tab provides a way of customising one of the key steps in the pattern matching algorithm, namely interpolating the velocity field from the location of the interrogation vectors to the entire image plane.

Figure 107: The User interpolation tab provides a way of customising the interpolation step whereby the velocities at the interrogation points are interpolated to the entire image plane.
The controls available on this tab are identical to those for the pattern matching in synthetic schlieren (see §5.6.4.3). The example given in figure 107 uses a biquadratic fitted using a least-squares routine for all parts of the PIV process where interpolation is required. Note that this process only gives approximate interpolation as the least squares solution will not generally pass through the corresponding mesh points. Substituting the following code will keep the default behaviour for all except the generation of the intermediate velocity field used to distort the images:
if (callType = "Distorted") {
sx := x_size(uv);
sy := y_size(uv);
fit_image_b_spline(uv,nx,ny,x0,y0,dx,dy,nxParts:=sx/2,
nyParts:=sy/2,xOrder:=3,yOrder:=3);
} else {
null;
};
Here, we detect when the interpolated field is required for image distortion using the callType variable. If not, then returning a null indicates to DigiFlow to use the default interpolation. Here, when callType is "Distorted", we use a least squares fit of the velocity field using cubic b-splines to reconstruct a smoothed high-resolution version of the velocity field with which to distort the images prior to the next stage in the pattern matching algorithm.
The Quality tab provides the option of outputting information that DigiFlow generates to assess the quality of the individual velocity vectors.

Figure 108: Optional output of information relating to the quality of the velocity vectors.
The optional output stream created by this feature must be saved as a .dfi file. The pseudo image created contains multiple planes of image data, as indicated in the dialog box. Note that unlike with a .dfi file containing velocity information, DigiFlow does not format the image in any particular way for display. Opening a quality .dfi file will simply display the first image plane. The contents of the quality image is identical to that for Synthetic Schliere, thus the reader is referred to §5.6.4.3 for further details.
Selection of the most appropriate output file format (between .dfd and .dfi) depends on the type of post processing to be undertaken.
If the .dfi format is selected, then the PIV velocity files may be fed back into DigiFlow as multi-plane images containing the velocity field. These can be processed using most of the standard DigiFlow tools, preserving the nature of their contents. For example, the Analyse: Time Average facility can act upon a sequence of PIV velocity files to produce the time average velocity field. Similarly, the various other time series tools described in §5.6.1 can operate on these images, as can the general manipulation tools Recipe, Transform Intensity and Combine Images (see §§5.7.1, 5.7.2and 5.7.3). There are standard recipes in the Recipe facility to aid with basic manipulations of this data. For example, the recipe Velocity.Background.Divergence recipe lets you change the background of the velocity field from the one saved during the PIV processing to display the in-plane divergence field. Similarly, there are recipes for vorticity, stream function, velocity potential, shear, etc. Note that for PIV data, velocity gradients are obtained by a finite difference operation of the velocity field.
Saving the output in .dfd format is appropriate if post processing is to be undertaken using a third party or user-written program as the .dfd file contains an ASCII representation of the velocity field. Note that you can always convert a .dfi file into a .dfd file using Edit Stream (§5.1.5) or one of the other related image manipulation tools by simply specifying a .dfd file for the output.
Particle Tracking Velocimetry (PTV) differs from Particle Image Velocimetry (PIV) in a fundamental way. Whereas PIV (described in §5.6.5.2) relies on pattern matching in an essentially Eulerian way, PTV seeks to identify individual particles (or other equivalent features) and follow them in a Lagrangian sense. As PIV is the more widely used of these techniques, it is worth discussing the relative merits of the two approaches.
The strengths of PIV are that is fairly robust to noise and has excellent velocity resolution (the accuracy with which displacements may be obtained is a function of the cell size and the distribution of features within it rather than the pixel resolution). The spatial resolution is inversely proportional to the cell size: the overall data quality is thus a compromise between velocity and spatial resolution. The main disadvantages are the considerable time required to compute the optimal correlation and the inability to cope with any structure across the illuminated plane (i.e. velocity gradients parallel to the viewing direction). In general the method does not allow individual particles to be tracked, and hence has no immediate access to Lagrangian descriptions. However, it is a relatively simple matter to add some degree of particle tracing once the velocity field is known, and hence access the Lagrangian nature of the flow.
Particle tracking offers a more fundamental approach to PIV. There are two main approaches which are exactly equivalent to the manual methods of analysing streak (or multiple exposure) photographs and multiple (time series) photographs. In the streak photograph method, the effective camera shutter is opened for a long time during which the particles move many particle diameters. This long exposure may be produced directly with a suitably slow shutter speed, or synthesised by combining multiple exposures (e.g. ORing a sequence of video frames using a digital frame grabber with a shutter speed equal to the field rate - the DigiFlow facility described in §5.6.5.1 has this as an option). Once the streaks have been produced, image processing techniques may be applied to locate them and analyse their shape, orientation etc.
The alternative of utilising a time series of images offers a greater volume of information on the particle positions as a function of time, especially in the context of digital image processing where quantisation yields a relatively low spatial and intensity resolution. Knowing the approximate location of a particle at a relatively large number of times enables a much more accurate estimation of the position of a particle at a given time, and of its velocity, provided the sampling frequency is much higher than the highest frequency in the particle motion. To make use of this information some method must be developed for tracking particles from one image to the next. In the limit of particles moving only a small fraction of their diameter between each sample, the process of matching particles in one image with their position in the next image is straight forward - the particle images closest together in two adjacent samples will correspond to the same physical particle. However, if the particles may move many diameters between samples, more sophisticated algorithms must be employed.
The algorithm used in the matching process may utilise spatial and temporal information in addition to particle characteristics and prior knowledge of the flow. Generally, only some of these features will be needed to determine which particle image is which particle. For example, if spatial correlation is not utilised, then two-dimensional projections of three-dimensional flows with significant velocity gradients parallel to the direction of viewing, may be analysed (recall that PIV techniques are unable to cope with such images). Moreover, the basic approach is not limited to a two-dimensional projection of a three-dimensional flow but is capable of full three-dimensional analysis. By applying the matching process repeatedly, time-series for individual particles may be obtained to describe some of the Lagrangian nature of the flow.
The accuracy with which the velocities may be measured is limited by the accuracy with which the individual particle images may be located and the time period over which the velocity may reasonably be evaluated (this must be shorter than the period corresponding to the maximum frequency in which you are interested). The accuracy of location depends in turn on the particle size, the bit depth and quality of the images, and the method used to determine their positions. In general, the velocity resolution will be less than that for the cross-correlation approach, but is nevertheless excellent in many situations. The spatial resolution is limited primarily by the number of particles in the flow: the more particles, the higher the resolution. In practice the resolution of video technology and the frame grabber imposes the most stringent limitation on the number of particles able to be tracked. Eulerian as well as Lagrangian descriptions may be obtained, utilising a suitable interpolation method, if the particle seeding density is sufficiently high.
The techniques and algorithms used by DigiFlow are based on those originally developed in 1988 and described by Dalziel (1992). These same techniques and algorithms were incorporated in the DigImage processing system. These algorithms have been refined and enhanced in DigiFlow to improve computational efficiency and, more crucially, to improve the overall performance of the particle tracking process. The interface with these algorithms has been greatly simplified when compared with DigImage, making the tracking process more generally accessible.
This section outlines and describes the two-dimensional particle tracking technique utilised by DigiFlow. This method represents an efficient, reliable approach to tracking particles from a two-dimensional projection of a flow. The computation required to analyse each frame pair increases only slightly faster than linearly with the number of particles, allowing very high processing rates.
The basic strategy behind the particle location is to scan through the image for blobs that have an intensity satisfying some threshold requirement. If a blob is found, then its characteristics are determined and compared against a set of requirements for the blob to be considered a particle. If the blob satisfies these requirements, it is recorded as a particle, if it does not, it is discarded.
By scanning through the image with a range of different thresholds, it is possible to pick up particles with a broad range of intensities, allowing optimal performance. A blob that was rejected at one threshold may well be picked up as a particle at another threshold.
The particle location procedure ultimately records not only the location of the particle (as determined by its volume centroid, relative to the threshold, but also a broad range of other particle characteristics, some of which are used in the subsequent matching process.
Once all the particles in an image have been found (at t = tn+1, say), they need to be related back to the previous image (t = tn, say) to determine which particle image is which physical particle. In DigiFlow we use a modification of what is known in operations research as the Transportation Algorithm. This approach was that developed by Dalziel (1992). While the problem solved by the transportation algorithm may be represented as a 0-1 totally unimodular integer linear program, it is more efficient and illuminating to take a graph theory approach.
The idea is to choose a set of associations between two sets of entities, such that the set of associations is optimal in the sense that it minimises some linear function of the associations it includes. For the particle tracking, one of the sets is the set of particles P at t = tn and the other the set of particles Q at t = tn+1. We shall start by assigning a label to all the particles images in the two images. At t = tn the particle images are labelled pi for i=1 to i=M, while at t = tn+1 they are labelled qj for j=1 to j=N. Each pi or qj contains not only the location of the particle, but other characteristics such as size, shape, intensity, and any other desired piece of information. We now define a set of association variables aij. If aij is equal to one, then we will say that pi at t = tn is produced by the same particle as qj at t = tn+1. If aij is zero, then pi and qj represent different physical particles.
For the time being we shall assume that there is one and only one physical particle for each of the particle images. We shall consider groups of particles later in this discussion. For the present it is obvious that, for given pi, at most only one value of j can give aij equal to one, otherwise the physical particle must be two places at once! Identical arguments apply for each pj. If M is equal to N, it may be possible for there to be exactly M = N values of aij equal to one. However, this will seldom happen in real experiments, where there will normally be fewer than M = N values of aij equal to one. Moreover, the number of particles images at the two times will not always be equal.
There are many reasons why the number of particles in the image may be different at t = tn and t = tn+1. The simplest is that the particle may have moved outside the region of the flow being tracked, either by moving outside the bounds of the tracking region, or by moving out of the illuminated region (e.g. moving out of a sheet of light). To overcome this problem we define a0j and ai0 as dummy particles at times t = tn and t = tn+1. Unlike ordinary particles, more than one value of j or i may give a nonzero value of a0j or ai0 (respectively). In this case a nonzero value of ai0 indicates that particle pi at t = tn has been lost from the image by t = tn+1, either by moving out of the image or for some other reason. Similarly, a0j = 1 represents a particle qj present at t = tn+1 which was not there at t = tn.
In order to determine the optimal set of nonzero aij, we must first define the functional to be optimised. The only restriction this method puts on the functional is that it is linear in the associations, aij, and so may be represented by Z, the sum over i and j of aijcij. Elements of cij represent the cost of associating particle pi at t = tn with particle qj at t = tn+1. The optimal solution will be chosen to minimise the objective function Z.
Typically the costs cij will be specified using some function of the particle positions, particle characteristics, temporal history and the physics of the flow. Conceptually the simplest model is to set cij equal to the separation between particle pi and particle qj (c0j and ci0 may be set to the distance to the boundaries of the observed region, or the maximum allowable distance a particle may be allowed to travel between tn and tn+1). The optimal solution will then try to minimise the particle displacements, allowing only associations which do not exceed the cost limits placed by c0j and ci0. The costs cij could equally as easily be the squares of the displacements, yielding a type of least squares optimal solution.
If we are trying to measure the fluid velocity (rather than Brownian motion, say), then a more appropriate set of cost functions would include some fluid dynamics. This may be achieved at the most basic level by predicting the positions the particles at t = tn will have at t = tn+1 using their velocity (and possibly acceleration) at t = tn. The costs cij may then be some function of the separation between the predicted position of pi and the position of qj. If a particle at t = tn has only just entered the image, then we are unlikely to have more than a rough estimate for its velocity and so are unable to predict accurately where it might be at t = tn+1. To enable matchings to still occur to such particles, we must reduce the costs of associations with them and allow matchings over larger distances than for particles for which we have a velocity history (we may also, however, add some fixed cost for this new member). While the cost reduction – and associated increase in the allowable separations—when there is no velocity history may produce some mismatching, the requirement for a much more exact match would not then be satisfied at t = tn+2, and so the mismatch would not continue. During subsequent analysis, if we accept only paths which passed through three or more samples during the tracking phase, then we will eliminate any mismatches due to the less stringent matching requirement for a particle with no velocity history.
Additional factors such as the particle size, intensity, shape or even colour may easily be brought into the costing function. Every added component in a well-chosen functional will increase the probability of a correct matching, but at the expense of increased computation. Fortunately, provided the particle seeding density is not too dense, the extra criteria are unlikely to add significantly to the quality of the results. Experience has shown that the tracking results are relatively insensitive to the exact function used for the costs cij. Any mismatches which arise due to a short coming in the costing procedure will be short lived (they will fail to match on the next step) and may be trapped during the subsequent analysis phase through acceleration checks.
The basic cost in DigiFlow is given by
where F(pi) is a fee determined by previous history of pi. The summation is over a list of properties f determined by the location process. These properties include location, threshold (intensity) and size, but in some cases a broader range can be used.
For each particle property there is a unit cost wf(pi), a threshold tf and a cost function zf(pi,qj). The cost function zf(pi,qj) depends on the instantaneous properties of the particles pi and qj, whereas the unit cost wf(pi) may depend on whether or not the history of pi is known. A typical example of zf(pi,qj) is that for the particle’s location,
where xi and ui are the particle location and velocity at t = tn, while xj is the particle location at t = tn+1. The corresponding unit cost is
where L1, L2 and L3 are the maximum matching distances for the first, second and subsequent matches the particle pi may make. The cost of a change in threshold is similar,
where Ti and Tj is the threshold identifying the particle at tn and tn+1, respectively. Here the corresponding unit cost wT(pi) is divided into only two costs depending on whether or not a particle has a history.
The fee F(pi) is typically taken as zero if the particle has a valid velocity history, and positive if it does not (the ‘joining fee’). The purpose of this fee is to promote the preferential matching of particles with a valid velocity history. In contrast, m(pi) is reduced when there is no velocity history to allow matches further a field.
This strategy to assigning costs has proven simple yet flexible and provides a framework that is relatively easy to understand. This model is more sophisticated than that used in DigImage in that particle properties such as intensity and size play a more prominent role in DigiFlow. Tests have shown that this provides a substantially improved matching performance when there are very high particle number densities.
The DigiFlow PTV facility takes an input stream, showing the experiment, and produces an output stream that contains the particle locations, particle properties, and the inter-frame particle associations.

Figure 109: The PTV tab controlling the input and output streams.
The Input stream may be in any valid image format. This is specified in the normal way through clicking File to specify the source if the stream is to be taken from a movie or sequence of images. In such cases the stream may be trimmed for length, a subregion selected, etc., using the Sift button (see §4.3). If the image source is from an upstream process, then this should be specified using the Process button.
The Output stream should be specified as a .dft file. This special file format contains all the particle data and its associations. These .dft files may be viewed using the normal DigiFlow tools; in such cases, the particle data is rendered back as an image. However, these files are really intended for use with the other PTV tools within DigiFlow which can access their contents directly.
The output stream is specified in the standard way through the File button. While Options may be set, there is not generally any benefit to be gained from doing so.
The Progress window group controls what is displayed as the particle tracking proceeds. The information selected here can help assess the performance of the particle tracking, and provide a guide to any adjustments to the Cost policy that may be required. In all cases the velocity of matched particles will be displayed, using white for particles that have been matched over three or more intervals in time, yellow for particles matched over two intervals, and cyan for particles matched only once. An example of the Progress window is shown in figure 110.

Figure 110: Enlarged example of the Progress window for particle tracking with all the optional output switched on and Streaks selected as the backdrop. Here Vector scale is set to 4.0, so the arrows are four times the length of the actual displacements. The white arrows are particles that have been matched more than two times, the yellow arrows particles that have been matched twice and cyan arrows particles that have been matched only once. Dark green squares are old particles that have not been matched, with dark green circles showing their predicted position. Dark green diamonds are new particles that have not been matched. Dark magenta circles are the predicted positions of particles that were matched, and light green arrows are the gridded velocity field.
If Show unmatched old is checked then particles at the earlier time step that are not matched to the later time step will be highlighted by a square box drawn in dark green around them, and by a circle (also in dark green) at their predicted location. Similarly, if Show unmatched new is checked, then any particles in the later time step that were not matched will be highlighted by a diamond drawn in dark green around them. (If the dark green diamond coincides with a dark green circle then the corresponding particle was not matched due to its change in intensity, area or one of the other image attributes.)
Checking Show predictions for matched will cause dark magenta circles to be drawn around the predicted position for particles that were matched. Any difference between these circles and where the particle is actually located may help diagnose why mismatches occur.
DigiFlow allows particles to go to ‘sleep’ for one frame but for them to still be matched across this period of sleep. The Show sleeping matches check box causes such matches to be shown in the Progress window..
At each time step DigiFlow calculates an approximate gridded version of the velocity field. The primary use of this is as an estimate for the velocity of particles with no prior history. By checking Show grid velocity this grid will be displayed in the progress window in light green.
The initial size of the arrows for plotting the velocity is set by Velocity scale. A unit value causes the arrows to be drawn at the same length as the displacements they represent.
The vector and particle information shown in the Progress window is displayed on top of an image of the experiment. The Backdrop list selects exactly how this image is constructed. Selecting Streaks will use a decaying series of images superimposed to give an impression of the particle motion, while Old time and New time will show one or the other of the two images being processed.
The Image spacing is shown here for information only. If the particle tracking is to be undertaken on a sequence of images that do not contain time information, then the default spacing will be 1.0 seconds. This spacing may be changed, however, in the Sift dialog (see §3.6).
The location of particles is of central importance to the performance of PTV. In DigiFlow, this process is controlled by the Location policy tab.

Figure 111: Parameters controlling the PTV particle location policy.
Best results can be achieved from high quality images that have bright, clear particles approximately two or three pixels in linear dimensions, on a uniformly black background. Such experiments, however, can be difficult to achieve in practice. The particle location strategy used in DigiFlow builds on the experience with DigImage to provide a robust, accurate and efficient method of getting the best possible results from the available images.
DigiFlow provides a preview of the located particles to aid
the process of setting the various parameters. This preview is activated by
clicking the View
button. Placing the cursor over the preview will provide the normal feedback of
the intensity at the location of the cursor, while the
,
and
buttons provide the ability to zoom in, zoom
out and resize the preview window. The preview window contains white plus (+) marks
indicating the particle locations superimposed on top of an image of the image
(see figure 112). Additionally, a subset
of the rejected ‘blobs’ are indicated by magenta boxes (blobs too big), yellow
circles (inappropriate particle shape, controlled by Maximum correlation and Maximum edge to area ratio)
and cyan diamonds (mismatch between area and volume centroids, controlled by Maximum mismatch).
The preview window is terminated by a second click of the View button. The location of the preview
image within the time series is determined by the Frame control.
Even if the preview is not generated the Number of particles box will show the current estimate for the number of particles within the frame. This count is updated automatically whenever one of the location control parameters is changed. Note however, that if a control is changed while DigiFlow is still processing the last lot of changes, then the count (and preview) may not reflect the latest changes.
The best results can generally be obtained by directly probing a high quality raw image stream. However, for inexperienced users or less than ideal image streams, optimising the settings for this can be difficult. For this reason, DigiFlow provides the possibility of preprocessing the images to provide a more uniform and consistent structure to the images. This preprocessing necessarily destroys some of the information contained within the original images, but the algorithms are designed to keep this to a minimum.
The preprocessing is controlled through the Preprocess list box. As noted above, the greatest accuracy can be achieved by selecting (none) to suppress preprocessing, although for a given image stream this may not be appropriate. For inexperienced users the min-max filter option is recommended. This nonlinear filter attempts to remove background variations on scales larger than the particles, thus effectively resulting in the particles appearing on a uniform black background for subsequent location. A different form of preprocessing is available by selecting (background). This activates the controls on the Background Illumination tab (see below) which allows an image of the experimental setup without particles to be removed from the experimental images.
The starting point when changing the locations parameters is normally setting the range of intensities through which the threshold will be scanned. This is achieved using the Threshold group. The location process begins by looking for particles satisfying the threshold Maximum, gradually decreasing this in Number discrete steps down to Minimum. The Greater check box will cause DigiFlow to search for bright particles on a dark background, while clearing the check box sill invert the incoming image stream, thus allowing it to be treated in the same way. The Quadratic check box controls the distribution of thresholds between the two limits. For many experiments, having Quadratic checked works best.

Figure 112: Preview window showing the particles that have been located.
The Blob validation group provides the information necessary to decide whether or not a given blob that has been located should be treated as a particle. The left-hand column is pretty much self-explanatory. Blobs smaller than Minimum area will be ignored at a given threshold, but they may well be picked up as particles at a later (lower) threshold. Blobs exceeding Maximum area will be discarded. The reason for having limits on both linear dimensions and particle area is to help ensure the particles are roughly circular and ensure that they may be located with subpixel accuracy. The upper limits are provided to prevent spurious features within the image from being picked up accidentally. The Maximum x size and Maximum y size not only set the upper size limits, but also provides the length scale for the filter that is used when the min-max filter is selected for Preprocessing.
The mean intensity of a blob relative to the threshold at which it is identified must exceed Minimum excess, which ensures the image is sufficiently well defined. The location assigned by DigiFlow to a particle satisfying all other criteria is the volume centroid, where the third dimension is the intensity relative to the threshold. However, DigiFlow also calculates the area centroid; the maximum difference between the locations of these two centroids is determined by Maximum mismatch.
Other aspects of the geometry are tested using Maximum correlation, which is the correlation coefficient of the pixels within the blob. In general a value close to 1 or -1 indicates that the blob is linear rather than circular in nature. Similarly, Maximum edge to area ratio compares the square of the number of pixels marking the boundary of the blob with the number within the blob. A large value for this ratio indicates either linear blobs or blobs with very convoluted boundaries. As an indication, a large, circular blob would have this ratio equal to (2pr)2/(pr2) = 4p, a square would have a ratio of 16, while a line of length L and a single pixel wide would have the ratio equal to 4L. The default value is somewhat higher than this to allow a broader range of particles to be tracked.
The Reset button will restore all of these parameters to their default values.
In addition to providing a preview of the particles found, the View button also provides a plot of the size distribution of the particles identified.

Figure 113: Histogram showing particle number and area for given categories of particles identified by the Locaion policy.
The controls on the Background illumination tab are enabled by selecting (background) in the Preprocess list on the Location policy tab. The Background illumination tab provides a convenient method of correcting your experimental images for a non-uniform, non-zero background illumination in the experimental images.
Typically all that is required is a single image. This can be an image of the experimental setup with no particles present, or may be constructed from the experimental setup itself. If the particles are brighter than the background then a typical strategy for the latter is to work out the minum intensity for each pixel using the min feature in Analyse: Time Average (see §5.6.1.1). The rationale behind this is that a given pixel will be at its darkest when no particle is present. (If the particles are darker than the background, then use max instead of min.)

Figure 114: The Background intensity tab controls the removal of background variations in the intensity.
When Image is selected, the background image is specified as either a single image or as a sequence of images; which is determined by the Sequence check box. In most situations a sequence is unnecessary, but if there are moving parts, or significant predictable changes in illumination, then a sequence may be desirable.
If Calculate is specified, then a background illumination image is constructed from the experimental input in the manner described above. Rather than using every image in the input, it is frequently only necessary to use a subset of the images. The nSamples control specifies the maximum number of samples that should be used. These will be evenly distributed over the duration of the experimental image sequence. Note, this control shoul not be used when the experimental image sequence is obtained from a process rather than a file. The background image generated in this manner is not saved; moreover, it is not available until the particle tracking process starts, and so it can be more difficult to set the particle location parameters. For these reasons it will normally be more convenient to manually construct the background image using Analyse: Time Average (see §5.6.1.1), should you need one.

Figure 115: Parameters controlling the costing policy for particle tracking.
As noted earlier, the matching process is governed by the cost assigned to each of the possible associations between the sets of particles identified at different times. The Costing policy tab defines the various factors that go into determining the cost. Each of the parameters is described in turn below, followed by a brief guide on strategies for adjusting them, should this prove necessary.
The most important parameters in most cases are those in the Maximum matching distance group. The three distances given here determine the maximum distance (in pixel separation) between the predicted position of a particle and where one is actually found. As any prediction of a particle without a history the First match value should normally be larger than the other two. For flows with low accelerations the Second match and Later matches should be similar or even the same. These maximum separations will be realised only if the particles do not incur other costs in the Attribute costs group (see below). (For users familiar with DigImage, the Later matches is similar to [;USPM Maximum matching distance] and First match is similar to [;USM Max new paths error] when expressed in pixels.)
The Other costs group contains other costs that are used to modify the matching process. The Joining fee (range 0 to 1) is applied only to particles that do not have a history. Increasing the Joining fee does not affect the Maximum matching distance for the First match, but does decrease the probability that an association with the particle will be permitted.
The Attribute costs group is used to increase the cost of an association if the attributes of the particle images concerned differ. Two sets of values are specified: one for the First match, and a second for Later matches. In each case, no cost is incurred if the attributes differ by less than Threshold.
The Threshold change cost and Threshold, and the Area change cost and Threshold work in a similar way to the distance cost, although the measure of the area change is 2|Ai - Aj|/(Ei + Ej), where Ai and Aj are the areas and Ei and Ej the number of edge points for the old and new particles, respectively.
In most circumstances the default values (which can be restored using the Reset button) will work well. However, in some flows it might be necessary to adjust things either to reduce the number of spurious matches, or to allow DigiFlow to lock on to particles that are moving very rapidly.
The prediction policy (see figure 116) determines how velocity information is incorporated into the distance function (24). Velocity weighting determines how much of the velocity from the last match for a particle is used to predict its new position, and the Acceleration weighting does a similar thing with the particle Lagrangian acceleration (when there is sufficient history to evaluate this). This particle-based velocity is not the only potential source of velocity information. DigiFlow also calculates a grid velocity which is based on the average particle velocities within grid cells covering the domain. The Grid weighting determines how much of this is incorporated into the prediction. In particular, if V is the velocity weighting and G is the grid weighting, then for a particle with a velocity history the velocity the velocity used in (24) is
where uin is the particle velocity from the previous time step and ug is the grid velocity. When there is no velocity history then

Figure 116: The controls for the prediction policy.
The above strategy for determining the velocity may not be appropriate if the mean velocity is significantly different from zero. In this case we may enable use formula and specify (in pixel units) a background velocity field using u Formula and v Formula. The resultant prediction is then given by
ui = Vuin + (1-V)(Gug + (1-G)uf), (29)
when there is a history, and
when there is not. The u Formula and v Formula are specified in terms of its location x, y (in pixels) and the time t. A typical example of the use of this function would be for flow in a flume, where the two formulae would simply represent the mean flow.
When there is insufficient particle information to evaluate the grid velocity at a given point, DigiFlow will a memory of the last calculated grid at that point. This memory fades in a manner determined by Grid memory. If Use formula when no history is not set, then the grid velocity will decay towards zero by taking the product of Grid memory and the current grid at each time step.
In some cases it may be desirable to feed in the predicted velocity from a sequence of .dfi files. These may, for example, be the result of a previous attempt at PIV or PTV (using the PTV Grid velocity feature of §5.6.6.5). Such a two-stage process can help DigiFlow latch on to particles in problematic regions of high gradients or in high-speed flows. Note that once DigiFlow has latched on to the particles they will be treated in much the same way as normal. This feature is enabled via the Use velocity file checkbox. The supplied velocity information may be a single .dfi describing a steady mean flow (in which case clear the Sequence check box), or it may be a time-varying sequence. Note that in both cases it is essential that the velocity information is provided for the same region as the tracking and that the same time spacing is used. It is also normally best if the velocity information is provided in pixel coordinates. The Weighting control within the Predict with velocity file determines the relative importance of the supplied velocity file and the normal gridded velocity, described above.
Image sequences of high-speed flows sometimes consist of repeated short bursts of images where the image spacing within the burst is shorter than that between bursts. PIV often uses this technique with two closely spaced images in each burst. The Reset paths group is implemented to aid the tracking of sequences containing bursts of images with a different time interval between the bursts than between the images within the burst. For most cases, Periodic reset should be unchecked, meaning that the spacing between all images are the same and that matches should be made over each image pair in turn. Checking Periodic reset will force all paths to be broken (i.e. no matches allowed) at intervals specified by Interval (in frames). Not only will the paths be discarded, but also the gridded velocity field will be discarded. Thus, effectively, the particle tracking will start again from scratch. Note that utilising a Periodic reset on a flow that has a continuous record will degrade the results from the particle tracking. Moreover, the smaller the Interval, the poorer any velocity calculations will be. (It will also be necessary to ensure that the time used to calculate the velocity does not exceed the period of data between each reset.) For the case of PIV sequences with two images in each burst, then set Interval to two.
The default values may be restored using the Reset button.
During the tracking process, DigiFlow will display three windows. The Experiment will display the raw experimental image being processed, while the Particles image will display each of the identified particles as a dot. The colour of each dot is related to the threshold at which the blob in the experimental image was considered to be a particle.
Perhaps the most useful window is the Progress window. This window displays a variety of information about both the velocity field and the performance of the tracking process. Details of the different arrows and symbols used was given earlier in this section, with an example shown in figure 110. Statistics of the number of particles matched are also given in the title bar of the window.
Occasionally an obviously incorrect vector will be produced. If such a vector is yellow, then it is of little concern: the matching criteria for particles without a velocity history are necessarily less stringent, a feature that is likely to lead to the occasional mismatch. Such vectors are unlikely to persist, however, as the implied velocity history is much less likely to lead to a match on the next step.
There will be times, however, when spurious vectors persist. The table below lists potential problems and remedies.
|
Description |
Remedy |
|
Very few particles have vectors |
Check that location policy is reliably picking up particles on successive frames. |
|
|
If the intensity of the particles is fluctuating a lot, try reducing the Cost of a Threshold change, or increasing the Threshold before a cost is incurred. This problem is most likely to occur when the particles are extremely small. |
|
|
If the particles are moving relatively far and fast between frames, try increasing the Maximum matching distance group. |
|
Spurious white vectors persist. |
DigiFlow may be identifying too many particles, some of which are really just noise. Check the Location policy. |
|
|
Check that matches are not being made too readily. Try reducing Maximum matching distance group. |
|
|
Try increasing the Cost or reducing the Threshold for Threshold changes. |
Once the tracking has been completed, it is often desirable to calculate the particle velocities. The velocities may be calculated from a particle path in a number of ways. At the simplest level, the location of particle i on two consecutive frames, xi(n-1) and xi(n), can be used to estimate the velocity as
ui(n-˝) =(xi(n) - xi(n-1))/Dt,
where Dt is the spacing between two frames. Although this approach provides the highest possible frequency response, it is also the most subject to noise. If the error in the positions of the particle is sx, then the error in the velocity is su = 2sx/Dt. The simplest way of decreasing the error is to perform the calculation over a larger interval. If
ui(n-s/2) =(xi(n) - xi(n-s))/(sDt),
then the error is reduced to su = 2sx/sDt, provided the velocity is constant within the interval.
For most purposes it is better to decrease the interval between frames (decrease Dt) and then use a least squares fit to a sequence of s particle positions. The simplest alternative is to fit a line. Since the frame interval is constant, the estimate of the velocity is therefore
This velocity is then assigned to the least squares estimate of the particle’s position in the middle of the time interval. Key to the use of the least squares approach is its effect on the error in the velocity estimate. As shown by Dalziel (1992), the error estimate is reduced to
.
Increasing s leads to a reduction in the error estimate for the velocity, but only provided the velocity remains approximately constant over the interval sDt. Increasing s and decreasing Dt can achieve this, although there will normally be limits imposed by the camera frame rate that limits s. However, the interval sDt may be increased further if the model for the particle path remains reasonable; fitting a quadratic rather than linear function can achieve this.
Basic velocity statistics for the particles are available through this feature. The statistics are weighted by the number of particles, rather than the region of space in which particles were found.
The controlling dialog takes the normal form with the .dft tracking data being specified in the PTV data input stream. The Basic Statistics output takes the form of a single .dfd (or .emf or .wmf) output plot.
The particle tracking process is undertaken in pixel space. However the results will generally be required in world coordinates. In DigiFlow the transformation between the two is made during the analysis stage by selecting the appropriate Coordinate system.
The method of calculating the velocity, and the number of time intervals across which the calculation is made, is determined by the Velocity group. Typically a value of 4 or more should be used for the Length entry in conjunction with the Linear or Quadratic methods. It is recommended that the Extremes option only be used for testing purposes as this provides the least accurate approach.

Figure 117: Dialog controlling the calculation of basic PTV statistics.
Since particle tracking is an inherently Lagrangian process, it makes sense to analyse the particle tracks in a Lagrangian framework. The Lagrangian autocorrelation functions are one such way. Particle velocities are calculated for each point along a path using the methods outlined in §5.6.6.5 and then related to the velocity at another time along the same particle path to generate the autocorrelation coefficient
,
where the summation is over the N particles paths at least dt long occurring at any time t in a specified interval. Here the indices i and j refer to the velocity components u or v.

Figure 118: Control of the autocorrelation facility.
The PTV data input selector takes a series of .dft particle tracking files and extracts the data from them. The start and end points, and the spacing of output, can be set by the Sift button (see §4.3).
Output of the Autocorrelation is in the form of a .dfd drawing file, an .emf file, or a .wmf file. If you want access to the actual track data, then the .dfd option is preferred.
The particle tracking process is undertaken in pixel space. However the results will generally be required in world coordinates. In DigiFlow the transformation between the two is made during the analysis stage by selecting the appropriate Coordinate system.
The method of calculating the velocity, and the number of time intervals across which the calculation is made, is determined by the Velocity group. Typically a value of 4 or more should be used for the Length entry in conjunction with the Linear or Quadratic methods. It is recommended that the Extremes option only be used for testing purposes as this provides the least accurate approach.
The autocorrelation function will be calculated for all separations dt up to the maximum specified by Max path length, although the calculation will proceed only as far as particle paths of that length are still found.
Normally the results of this calculation will be the autocorrelation functions, selected by Correlations in the Plot group. However, it can be valuable to determine the standard deviations (velocity fluctuations) of the data as the conditional sampling associated with the very long particle paths can lead to a bias in the statistics. Select Standard deviations to see this data.
Particle tracking data begins as Lagrangian particle paths. Typically these are randomly distributed in space and variable length in time. The .dft file potentially contains particles that exist for only a single frame, and others that are part of paths spanning many frames. The PTV vectors facility provides the ability to review the contents of the .dft file, filtering out the paths that are too short.

Figure 119: Dialog controlling the production of particle tracking vectors.
The PTV data input selector takes a series of .dft particle tracking files and extracts the data from them. The start and end points, and the spacing of output, can be set by the Sift button (see §4.3).
Output of the Velocity vectors or particle tracks is in the form of a .dfd drawing file, or a .wmf or .emf file. If you want access to the actual track data, then the .dfd option is preferred as this will contain all the paths individually listed. The Draw axes check box determines whether the drawing includes axes or only the vectors/tracks. Note that specification of an output stream is optional. If not specified, the output will be displayed on the screen while it is computed, but will be discarded at the end of the processing.
The particle tracking process is undertaken in pixel space. However the results will generally be required in world coordinates. In DigiFlow the transformation between the two is made during the analysis stage by selecting the appropriate Coordinate system.
The output can contain either velocity vectors (select Vector) or the particle tracks (select Track) at each time, where the vectors/tracks are determined only for particles that extend for at least Path length intervals in time (half before and half after the current time). When Track is selected, the Arrow head check box determines whether or not an arrow head is draw; arrow heads are always drawn when Vector is selected.
For some purposes, it is desirable to transfer the randomly distributed particle paths, and their associated Lagrangian velocities, onto a regular grid. The basic approach for doing this is using a weighting kernel to distribute the particle velocities onto the grid. Suppose ui, i=0,1,…n-1 are the particle velocities known at locations xi, then we may estimate the velocity U at some location X by
where a(|xi – X|) is the weighting function. We select a(r) to provide finite support over some length scale L. This approach was pioneered in DigImage.
By ensuring a(r) and its derivatives are continuous, then we may use the same form to provide velocity gradients by analytically differentiating the kernel. For example, ¶U/¶x is given by
an approach that has had much use in the family of numerical techniques known as Smoothed Particle Hydrodynamics (SPH, e.g. Monaghan 1992) and offers substantially better performance than finite difference on the gridded velocities. Following the work with SPH, we use the axisymmetric cubic spline
This is plotted in figure 120.

Figure 120: The axisymmetric cubic spline used to distributed particle data to the grid.

Figure 121: Dialog controlling the process of gridding the particle tracking data.
The PTV data input selector takes a series of .dft particle tracking files and extracts the data from them. The start and end points, and the spacing of output, can be set by the Sift button (see §4.3).
Output of the Velocity vectors, and optional background image, is in the form of a .dfd drawing file, an .emf file, a .wmf file, or a .dfi image file. If you want access to the actual track data, then the .dfd option is preferred as this will contain all the paths individually listed. The Draw axes check box determines whether the drawing includes axes. Using a .dfi file will allow the resulting velocity fields to be manipulated by the various image processing tools available within DigiFlow. Note that specification of an output stream is optional. If not specified, the output will be displayed on the screen while it is computed, but will be discarded at the end of the processing.
The particle tracking process is undertaken in pixel space. However the results will generally be required in world coordinates. In DigiFlow the transformation between the two is made during the analysis stage by selecting the appropriate Coordinate system.
The method of calculating the velocity, and the number of time intervals across which the calculation is made, is determined by the Velocity group. Typically a value of 4 or more should be used for the Length entry in conjunction with the Linear or Quadratic methods. It is recommended that the Extremes option only be used for testing purposes as this provides the least accurate approach. The length scale of arrows used for the velocity is determined by Velocity Scale. A unit value will cause the arrows to represent the actual distance moved between two consecutive frames.
The grid velocity can represent either the instantaneous velocity field, or a temporal mean of the selected interval. The choice of which is determined by the Grid type group. With an Instantaneous grid, it is possible to employ a moving average, either to filter out the higher frequency components, or (for a flow that is steady in the Eulerian frame) to increase the available data for the gridding process.
The resolution of the grid and length scale of the kernel function are fixed by the Grid resolution group. Decreasing the Filter length can lead to improved spatial resolution, provided it remains sufficiently large to include an adequate number of particles for each of the nx by ny grid points.
The velocity field may be rendered by itself, or superimposed upon a background image. This is controlled by the Vector background list box in conjunction with a Scale factor.
Selection of the most appropriate output file format (between .dfd and .dfi) depends on the type of post processing to be undertaken.
If the .dfi format is selected, then the PTV gridded velocity files may be fed back into DigiFlow as multi-plane images containing the velocity field. These can be processed using most of the standard DigiFlow tools, preserving the nature of their contents. For example, the Analyse: Time Average facility can act upon a sequence of PTV gridded velocity files to produce the time average velocity field. Similarly, the various other time series tools described in §5.6.1 can operate on these images, as can the general manipulation tools Recipe, Transform Intensity and Combine Images (see §§5.7.1, 5.7.2and 5.7.3). There are standard recipes in the Recipe facility to aid with basic manipulations of this data. For example, the recipe Velocity.Background.Divergence recipe lets you change the background of the velocity field from the one saved during the PTV gridding process to display the in-plane divergence field. Similarly, there are recipes for vorticity, stream function, velocity potential, shear, etc., and for adding scales and other similar graphical manipulations. Note that for PTV data, velocity gradients are as part of the gridding process by analytical differentiation of the weighting kernel rather than by a finite difference operation of the velocity field. This retains more of the velocity information available from the randomly distributed particles.
Saving the output in .dfd format is appropriate if post processing is to be undertaken using a third party or user-written program as the .dfd file contains an ASCII representation of the velocity field. Note that you can always convert a .dfi file into a .dfd file using Edit Stream (§5.1.5) or one of the other related image manipulation tools by simply specifying a .dfd file for the output.
The idea behind Optical Flow is that illumination is a conserved quantity that is advected by some velocity field.
This menu item provides a basic algorithm for extracting the velocity field from an optical flow. The key idea is that if illumination is conserved then we can write an advection equation for it of the form
If we then assume that the velocity field (u,v) is constant over some region S containing intensities P0, P1, … PN, then we may write this as the over determined system
We can then estimate (u,v) as the least squares solution to (36). In reality, finite difference approximations to the spatial and temporal gradients of the illumination are used, and the noise in the signal, plus the need for the least squares problem to be well conditioned, places a practical lower limit on the size of the region S, while an upper limit is imposed by the velocity field not really being constant.
This process, which is sometimes referred to as ‘feature tracking’, can be used in a variety of contexts. With relatively slow flows containing particles, it provides a computationally cheap method of obtaining an estimate of the velocity field, although the resulting velocity field is less accurate than that obtained by other methods. The process can be particularly valuable for looking at the flow and distortion of dye fields, although the user must be aware that it is not necessarily the fluid velocities that will be returned.
Note, the Tools: Recipes: Slave Process (§5.7.5) facility provides a cut-down version of this facility for providing an estimated velocity in real time. This cut-down version is provided through the dfc function follow_optical_flow(..).

Figure 122: The inputs tab for Follow Optical Flow.
The Inputs tab bears some similarity to that for PIV (see §5.6.5.2) with either one or two input streams. If One stream is chosen, then the Interrogation interval group allows the number of frames between the first and second frame of each pair being processed. When the input is as two streams, the interval between each stream must be specified in seconds.
The Conserve light checkbox forces the mean intensity of each of the interrogation windows (the region given by S above) to be constant, Allow offset enables the temporal derivatives to be made in a semi-Lagrangian manner, and Central differencing makes the spatial derivatives a central second order approximation.
The Window size group controls the size of the interrogation window, which DigiFlow adjusts dynamically to give the best compromise between noise level, robust data, and the resolution of velocity gradients. This automatic adjustment is guided by minimum and maximum sizes for the base windows which DigiFlow applies to all interrogation points. DigiFlow will cause a window to increase above this base size, up to Max local size if the magnitude of the smallest (normalised) eigenvalue of the least squares problem falls below Eigen threshold (this indicates the least squares solution may be ilconditioned). If a bigger fraction of the windows are grown due to this criterion than Max frac grown, then DigiFlow will cause the base window size to increase (up to Max base size). If fewer windows are grown than the fraction Min frac grown, then DigiFlow will cause the base window size to decrease (down to Min base size).
The Coordinate System controls the conversion between pixel coordinates and any world coordinate system, while Vector spacing determines the spacing (in pixels) between the centres of the interrogation windows.

Figure 123: The outputs tab for Follow Optical Flow.
The principal output of Follow optical flow is the velocity field. This is specified by the Velocity selector. As with the PIV system, a scale for the arrows used to display this is specified by Velocity scale, and a background image may be placed behind the arrows with Vector background (the scale of which is controlled by Field scale, when appropriate). The Compact output check box forces the resolution of the output to be reduced so that data is saved only at the locations of the interrogation windows.
The Quality selector optionally stores information about the performance of the process. In particular, the first image plane gives the size of the minimum eigenvalue of the least squares process, while the second image plane gives the size of the window actually used.
This process provides a simplified entry point to many commonly used image processing procedures. Internally, this facility uses the same mechanism as Transform intensity and Combine images described in §§5.7.2 and 5.7.3, but the interface here presents the user with a broad list of pre-written processes rather than requiring the user to enter their own code.

Figure 124 Transform an intensity using a recipe of transformations.
Depending on which recipe is selected, either one or two input image selectors are required. The Input selector is required for all functions. This selector determines the timing and other key features. The second stream, With, is required only for a subset of the functions. For some functions this will represent a single image, while for others it will be a sequence. The title of the group is changed to reflect these differences. The controls associated with the With selector are disabled when it is not required.
Both input selectors have the normal mechanism for their specification and the range of controls. This may be taken from a file using the File button, or from another Process. The input stream may be sifted (§4.3) to extract the desired subregion and times. This feature is activated using the Sift button (see §4.3) associated with the input streams.
The Output group specifies the destination of the transformed image using the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details). The colour scheme and other output options to be used for the output stream are set by clicking the Options button. Although the output image will typically have a bit-map format, this is not always the case. Indeed, this tool can be used to transform a bitmap into a drawing, as will be illustrated below.
The Controls for this process centre on identifying the transformation. The predefined transformations are sorted by Category and Group. Each individual Recipe has a description that will be displayed beneath the selection lists. Some recipes will require one or more user-specified parameters. The required type for these parameters depends on the function selected. Some recipes produce images, and others produce drawings. The simplest way to determine which is by clicking the Preview button.
Users can add their own custom recipes to the list by creating a file named User_Recipes.dfc either in the current directory, or in the directory in which DigiFlow is installed. (A copy in the current directory will have precedence over one in the DigiFlow directory.) A typical entry for a single-stream recipe in this file would look like
Recipe.User.Stretch.Linear.Descr := "Stretch the intensity by a factor";
Recipe.User.Stretch.Linear.Code := {P*p0};
Recipe.User.Stretch.Linear.Prompt0 := "Factor";
Recipe.User.Stretch.Linear.Param0 := 2;
Recipe.User.Stretch.Linear.Check := {if (p0 = 1) {"No point multiplying by one"} else {null};
This would appear under Categgory User, Group Stretch, Recipe Linear. Here the recipe requires one parameter, producing the prompt Factor in the interface. The default value of this parameter is set by the .Param0 variable, and the parameter is provided to the code as the variable p0. In this case, since a .Check variable is specified, the value of the parameter is checked. If the .Check code returns a string, then this is displayed as a warning message.
If two input streams are required, then the variable xxx.With should be defined, containing either "sequence" or "single", depending on whether a sequence or only a single image is to be recovered from the With stream. The image recovered from the With stream is provided to the .Code in the variable Pb (or, for image planes in Qb – refer to §5.7.2 for further details).
The facilities available within the code segment .Code are exactly the same as those available in the Transform intensity and Combine images tools described in §§5.7.2 and 5.7.3. Up to 6 prompts may be requested, their types (integer, floating point or string) being determined by the type of the default value in the .Paramn variable. Note that the description and code may be specified interchangeably as strings, code segments or memos.
The database of built-in recipes may be found in DigiFlow_Recipes.dfc in the DigiFlow installation directory.
This process allows the transformation of the intensities of an image stream using a sequence of user-specified operations. This produces a very versatile tool, but one which requires some experience to master. A simplified interface to the same underlying mechanism is provided in Transform recipe described in §5.7.1.

Figure 125: Transform an intensity using a mathematical expression.
A single image selector provides the input stream in the Input group. This may be taken from a file using the File button, or from another Process. The input stream may be sifted (§4.3) to extract the desired subregion and times. This feature is activated using the Sift button (see §4.3) associated with the input streams.
The Output group specifies the destination of the transformed image using the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details). The colour scheme and other output options to be used for the output stream are set by clicking the Options button. Although the output image will typically have a bit-map format, this is not always the case. Indeed, this tool can be used to transform a bitmap into a drawing, as will be illustrated below.
The Controls for this process centre on the transformation itself.
The Transformation edit box is used to specify the intensity mapping function using dfi code.
The basic image from the input stream is supplied in the array
variable P.
For simple images this will be a two-dimensional array. However, for more
complex image formats (such as velocity fields stored in .dfi files), P will contain more than two dimensions.
In such cases DigiFlow will also provide the same data split into its
individual component two-dimensional arrays in the compound variable Q. For example,
if the input stream contains a velocity field generated by the PIV facility
(see §5.6.5.2) then Q.u and Q.v will contain
the two components of the velocity field, and (depending on the options
selected during the processing) Q.Scalar may contain the vorticity field. Full colour
images are supplied as their red, green and blue components with a three-dimensional
P array: P[:,:,0] contains the red
component, P[:,:,1] contains the
green component, and P[:,:,2] contains the
blue component. For convenience, these are also supplied as Q.Red, Q.Green and Q.Blue. The
button may be
used to search for or provide information on specific DigiFlow functions.
DigiFlow also provides time information about the input stream through the Time compound variable. Typically this contains Time.fNow and Time.tNow giving the current frame number and time (in seconds) relative to the start of the entire input stream. An additional variable Time.iNow gives an iteration counter that is the frame number relative to the start of those that are actually being processed. Details of the entire input stream are provided through Time.fFirst, Time.fLast and Time.tFirst, Time.tLast that provide details of the first and last frame/time that exist in the input stream. Moreover, Time.fFrom, Time.fTo and Time.tFrom, Time.tTo provide information about which part of the stream is being processed.
The main variables available are listed in the Variables list box. This list does not, however, include any additional modifiers for the individual data plane variables beginning with Q. These modifiers include the description, scaling and (where appropriate) spacing of the data. A more comprehensive list may be viewed by clicking the Variables button. For further details, refer to the PIV data example below.
Note that regardless of the format of the input selectors, all processing is performed in floating point arithmetic and normally the images will be scaled between an intensity of 0.0 for the darkest parts and 1.0 for the brightest parts. By default, when the image is saved to an 8 bit format, intensities less than 0.0 will be mapped to 0 and those greater than 1.0 mapped to 255. Refer to §8 for further details on the interpreter within DigiFlow to evaluate expressions. The Preview button allows you to preview the result of the transformation before applying it to the whole image sequence.

Figure 126: Example of previewing an image.
Note that the result of Transformation need not be an image, but can be a DigiFlow drawing. In this case the return value from code specified for the Transformation must be the handle to the drawing object (i.e. the handle returned by draw_start(..)). In this case, the output stream must have a format capable of containing a drawing.
If this feature is started from a dfc macro, then the code specified for the Transformation has access to functions and variables defined in that macro. In the case of variables, the ! global access prefix must be specified.
A number of examples of transformation code are given below.
One of the simplest examples is rescaling an image so that its intensities always span the range 0 to 1, regardless of the input values.
# Find limits
vMin := min_value(P);
vMax := max_value(P);
# Rescale
(P-vMin)/(vMax-vMin);
This particular code segment would have problems if the image was all the same intensity as then vMin and vMax would be equal which would lead to division by zero. This problem could be overcome in a number of different ways. The most straightforward is illustrated below:
# Find limits
vMin := min_value(P);
vMax := max_value(P);
# Rescale
if (vMax = vMin) {
0.5
} else {
(P-vMin)/(vMax-vMin);
};
One process used frequently in image processing is filtering. In DigiFlow a number of functions are provided specifically in support of this. In the context of the Transform intensity facility, all that is necessary is to specify the appropriate filter, if it exists. For example
filter_low_pass(P,5);
will implement a low-pass convolution filter with a 5´5 kernel. In particular, the intensity of each pixel will be replaced by the mean of it and its 24 nearest neighbours. The function filter_convolution(..) provides a more general alternative in which the convolution kernel is specified explicitly, allowing a broad range of filtering operations. (The filter_low_pass(..) function is effectively a call to filter_convolution(..) with all the kernel elements equal to 1/n2, where n is the specified size of the kernel.)
Built in nonlinear filters include erosion (filter_min(..)) and dilation (filter_max(..)).
Using DigiFlow’s Fast Fourier Transform function allows the construction of filters in the wavenumber domain. For example, a low-pass filter could be constructed using the following Transformation code:
spec := fft_2d(P[0:128,0:128]);
k := sqrt(spec.kx^2 + spec.ky^2);
spec.re := where(k < 16,spec.re,0);
spec.im := where(k < 16,spec.im,0);
image := inverse_fft_2d(spec);
image.re;
Here, we make use of the wavenumber arrays returned by fft_2d(..) rather than having to work out the ordering in which the function returns the data. The where(..) function then simply sets all entries with wave numbers in excess of 16 to zero. Note that the fft functions can cope with arbitrary numbers of pixels, but are most efficient for powers of two and other small primes.
Often we would like to contour an image for one reason or another. Suppose we just want to draw the contours in place of the image, then we could use the following code to step through the various contour levels, drawing only those contours that were at least 100 pixels long (thus discarding any high frequency ‘noise’):
# Create image for output
out := make_like(P,0);
# Loop through thresholds
for thresh:=0.1 to 1 step 0.1 {
# Find contours of this threshold and draw on blank image
this := contour_image(P,thresh,fill:=thresh,minLength:=100);
# Superimpose new contours on output image
out := this max out;
};
# Return output image
out;
Obviously we could have superimposed the contours on the input image. Using other options in the contour_image(..) function would allow us to apply a low pass filter to the contours.
Similarly, we could fit a parametric curve to the contours, or perform a FFT and filter them to return a Fourier Descriptor of the enclosed region. This could be achieved by
this := pixel_contour(P,threshold:=0.9,minLength:=500);
if (this.found) {
# Compute fourier descripter
fft := fft_row(this.xy[0,:],this.xy[1,:]);
fft.re := where(abs(fft.kx)<8,fft.re,0);
fft.im := where(abs(fft.kx)<8,fft.im,0);
cont := inverse_fft_row(fft.re,fft.im);
out := scatter_to_array(P,cont.re,cont.im,fill:=0);
} else {
out := P;
};
out;
In this example we only find a single contour, the result of which is shown in figure127. The code could easily be modified to loop and so find all contours satisfying the length criterion. Note that the scatter_to_array(..) function may leave some gaps in the curve rendered as the curve is drawn using individual points rather than lines.

Figure 127: Eighth order Fourier Descriptor showing in black the region of the sheep’s back with an intensity in excess of 0.9.
Suppose we are interested in the fractal dimension of a contour from an LIF image (which may have been processed using the facility described in §5.6.3.2). In this case we would probably wish to have a log-log plot of the number of boxes verses the box size as the output. This may be achieved as follows:
# Extract fractal data
boxes := fractal_box_count(P,0.5);
# Fit least squares line
fit := fit_expression("1;ln(size);","size;",
boxes[:,0],boxes[:,1],"ln(n);","n;");
curve := exp(evaluate_expression(fit,boxes[:,0]));
# Axes limits
minSize := min_value(boxes[:,0]);
maxSize := max_value(boxes[:,0]);
minNum := min_value(boxes[:,1]);
maxNum := max_value(boxes[:,1]);
# Create drawing
hDraw := draw_start(640,480);
draw_set_axes(hDraw,minSize,maxSize,minNum,maxNum,
xLog:=true,yLog:=true);
draw_x_axis(hDraw,"Box size");
draw_y_axis(hDraw,"Number of boxes");
draw_create_key(hDraw,0.8*minSize+0.2*maxSize,
0.6*minNum+0.4*maxNum,"Key");
# Draw data
draw_mark_type(hDraw,"plus");
draw_line_colour(hDraw,"red");
draw_mark(hDraw,boxes[:,0],boxes[:,1]);
draw_key_entry(hDraw,"Box counts");
# Draw fit
draw_line_colour(hDraw,"blue");
draw_lineto(hDraw,boxes[:,0],curve[:]);
draw_key_entry(hDraw,"Fit: slope="+(-fit.coeff[1]));
draw_end(hDraw);
hDraw;
Here we see the key element for producing a drawing: the code returns the drawing handle rather than an image.
Note that this code does more than the bare minimum. Not only does it plot the (hopefully power law) relationship between the number and the size of the boxes to cover the contour, but it also generates a least squares fit to that and plots it. Moreover, the key that is generated will inform the user of the slope (the fractal dimension) of that fit.
Suppose we have an image stream containing velocity and vorticity data, but we wish to change the background of the vectors to be speed rather than vorticity. In this case the following code could be used:
out.u := Q.u;
out.v := Q.v;
out.Scalar := sqrt(Q.u^2+Q.v^2);
out;
In this example, we have extracted the velocity data without change. Note that we have used Q.u for the x velocity. The name ‘u’ comes from the description of the ‘u’ data plane stored in the input stream. We could equally have used the generic Q.u name instead. For the output image, we cannot use the ‘u’ name, but must resort to the generic ‘u’ name for the data plane, as we have not yet got a description for this plane. Similar arguments apply to the other two data planes. Indeed, we need to be a little bit careful as at present the output will inherit the ‘Vorticity’ description from the input, even though the output contains speed rather than vorticity.
This naming problem, along with an associated scaling one is handled as follows. If no other details are given, then the output will inherit the details from the corresponding input plane (i.e. the speed output plane will be called ‘Vorticity’ and have the same scaling as the vorticity). However, overrides can be specified. If we wish to do this for the above example we may specify a new description and scaling for the speed plane as follows:
out.u := Q.u;
out.v := Q.v;
out.Scalar := sqrt(Q.u^2+Q.v^2);
out.Scalar_Descr := "Speed";
out.Scalar_Black := 0.0;
out.Scalar_White := max_value(out.Scalar);
out;
Manipulations that you might want to apply to the velocity data include setting a different plot spacing and scale. This may be achieved in the above example by setting values for out.u_xStep, out.u_yStep, out.u_Scale, etc. Of course, you can also change the description for the velocity data, should you so wish.
Note that the input values of these additional controls are available through Q.u_Scale, Q.u_xStep, Q.u_yStep, … Q.Scalar_Black, and Q.Scalar_White. The input description is also available through Q.u_Descr, …, Q.u_Descr. Other features of the input image such as information about its coordinate system are available through Q.dx, Q.dy, Q.xOrigin, Q.yOrigin, Q.xUnits, Q.yUnits and Q.CoordName. These variables, however, are not listed in the Variables list box; a more comprehensive list may be viewed by clicking the Variables button.
Images and drawings may be returned in a variety of ways from the code. In all cases, the final computed or referenced value represents the image returned, but this may be an array, a drawing handle, or a compound variable. The table below gives the possibilities and their interpretation by DigiFlow.
|
Return type |
Components |
Interpretation |
|
2D array |
|
Simple image. Colour scheme and scaling determined by dialog settings. |
|
3D array |
|
If the input is a 3D array, then the output will be interpreted in the same manner. For example, a 3D array output from full colour input will be taken as a full colour image, whereas a 3D array output from a velocity field input will be interpreted as a velocity field. |
|
Compound |
.Image (array) .Black (numeric) .White (numeric) .ColourScheme (string) .LUT (string or array) |
Simple image, but with the code optionally specifying the intensity to set to black (.Black or .black) and white (.White or .white), and the colour scheme to be used (.ColourScheme or .colourScheme or .LUT). Only the specification of the image (.Image, .image or .im) is mandatory. |
|
Compound |
.Red (array) .Green (array) .Blue (array) .Red_Black (numeric) .Red_White (numeric) .Green_Black (numeric) .Green_White (numeric) .Blue_Black (numeric) .Blue_White (numeric) |
Full colour image. The arrays specified for .Red, .Green and .Blue must all be two-dimensional and of the same size. The optional .Red_Black, .Red_White, etc., set the intensities to be interpreted as black or white for each of the three colour components. |
|
Compound |
.u (array) .v (array) .Scalar (array) .u_Scale (numeric) .u_xStep (numeric) .u_yStep (numeric) .u_ColourScheme (string) .Scalar_Black (numeric) .Scalar_White (numeric) .Scalar_ColourScheme (string) |
Vector field, specified in .u and .v arrays, with an optional background image specified in the .Scalar array. Both (all three) arrays must be the same size. The spacing between the vectors is determined by .u_xStep and .u_yStep, whereas the scale of the vectors is given by .u_Scale. The default colour for the arrows (black) may be changed by .u_ColourScheme. The black and white values of the optional background image, and the associated colour scheme, may be changed by .Scalar_Black, .Scalar_White and .Scalar_ColourScheme, respectively. |
|
Drawing handle |
|
The drawing will be used. If the output is a raster image, then the drawing will be converted into a bitmap before saving. |
This process allows multiple input image streams to be combined in arbitrary ways to produce an output image stream. This facility may be viewed as an expanded version of the Transform intensity described in §5.7.2. This produces a very versatile tool, but one which requires some experience to master. A simplified interface to the same underlying mechanism is provided in Transform recipe described in §5.7.1.

Figure 128: Combine image streams in an arbitrary way.
Up to 26 image selectors (fewer if operating on a free licence) provide multiple input streams in the Input group. These are visible three at a time, with the Next and Previous, First and Last buttons providing the ability to move along the list of selectors. Each image stream may be enabled or disabled through the Use check box, and each is assigned a two-letter name. For accessing the basic image the first letter is always P, while the second increases alphabetically from a, for the first stream, through to z, for the last possible stream. As we will see later, individual data planes for images with multiple planes of data may be accessed using Qa, Qb,… Qz, and drawings through hDa, hDb,… hDz. The Reset button will clear the inputs of all selectors, and clear the Use check box for all except the master stream (stream a).
The individual input streams may be taken as either dynamic or static. A dynamic stream, indicated by checking Sequence, will have one image read from it for each frame processed. In contrast, a static stream will read the input image only once at the start of the process.
Timing details may be set for both dynamic and static streams using the Sift buttons (see §4.3) to activate the standard Open Image dialog (§4.1). For a static stream, the effect of this is merely to select which image from a sequence is used as the static image.
Using the Save As button, the Output group specifies the destination of the combined image streams. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details).
Timing details for the output stream are determined by the master input stream. This stream is selected using the Master radio button associated with each input stream. Note that while only one input stream can provide the master timing details, the process will be terminated when the first of the dynamic input streams runs out of images.
The Controls for this process comprise two code groups. The first code group, Static, may be used to define functions and manipulate the static input streams using their respective variables (e.g. Pb). This code is executed only once (except in so far as user defined functions – §8.9 – may be executed many times). Images from either static or dynamic streams may be referenced in the code, with those belonging to the dynamic stream corresponding to the first images in such streams. Any return value from this code will be discarded, but any variables created by the code will be available to the later Varying code.
The second code group, Varying, is executed once for each frame of the dynamic input stream in order to compute the output stream. This code may access any of the available images (i.e. whether they are from static or dynamic streams), as well as any variables or functions defined in the Static code. The final code statement provides the return value that is stored in the output stream.
The output from the Varying code may be an array, a drawing handle, or a compound value containing a number of different components. The various options here are identical to those for Tools Transform Intensity and are described at the end of §5.7.2.
As noted above, the basic image from the input streams is
supplied in the array variables Pa, Pb,
… For simple images these will be a two-dimensional arrays. However, for more
complex image formats (such as velocity fields stored in .dfi files), Pa, Pb, … will contain more than two
dimensions. In such cases DigiFlow will also provide the same data split into
its individual component two-dimensional arrays in the compound variables Qa, Qb,… For
example, if the first input stream contains a velocity field generated by the
PIV facility (see §5.6.5.2) then Qa.u and Qa.v will
contain the two components of the velocity field, and (depending on the options
selected during the processing) Qa.Scalar may contain the vorticity field. Full colour
images are supplied as their red, green and blue components with a
three-dimensional Pa
array: Pa[:,:,0] contains the red
component, Pa[:,:,1] contains the
green component, and Pa[:,:,2] contains the
blue component. For convenience, these are also supplied as Qa.Red, Qa.Green and Qa.Blue. The
button may be
used to search for or provide information on specific DigiFlow functions.. The
button may be
used to search for or provide information on specific DigiFlow functions. If
the input stream(s) contains a DigiFlow drawing (typically one or more .dfd files), then
DigiFlow provides the drawing is available through its handle hDa, hDb, … hDz in addition
to a bitmap version of it in the array variable P. Additional drawing commands may be
added to the drawing handle, or it may be incorporated into a compound drawing
using draw_embed_drawing(..).
DigiFlow also provides time information about the input stream through the Ta, Tb,… compound variable. Typically this contains Ta.fNow and Ta.tNow giving the current frame number and time (in seconds) relative to the start of the entire input stream. An additional variable Ta.iNow gives an iteration counter that is the frame number relative to the start of those that are actually being processed. Details of the entire input stream are provided through Ta.fFirst, Ta.fLast and Ta.tFirst, Ta.tLast that provide details of the first and last frame/time that exist in the input stream. Moreover, Ta.fFrom, Ta.fTo and Ta.tFrom, Ta.tTo provide information about which part of the stream is being processed.
The main variables available are listed in the Variables list box. This list does not, however, include any additional modifiers for the individual data plane variables beginning with Qa, Qb,… Use the Variables button to generate a complete list of all the variables available and their contents. (This button loads all the image data then calls the view_variables(..) function.)
If this feature is started from a dfc macro, then the code specified for the Static and Varying code segments have access to functions and variables defined in that macro. In the case of variables, the ! global access prefix must be specified. The Preview button allows you to preview the result of the transformation before applying it to the whole image sequence (see Figure 130).

Figure 130: Preview for Tools: Combine Images.
As is standard with DigiFlow, all the input streams from integer format image files are interpreted as floating point values between 0.0 for the darkest parts and 1.0 for the brightest parts. By default, when the image is saved to an 8 bit format, intensities less than 0.0 will be mapped to 0 and those greater than 1.0 mapped to 255.
Note that the result of Varying need not be an image, but can be a DigiFlow drawing. In this case the return value from code specified for the Varying must be the handle to the drawing object (i.e. the handle returned by draw_start(..)). In this case, the output stream must have a format capable of containing a drawing. See the end of §5.7.2 for a complete list of the output options.
A number of non-trivial examples are given below.
In some circumstances it may be necessary to force alignment of images. This may be due to vibration of the camera, for example. Processing in this case would require two input streams: the images to be aligned, and a reference image. If the misalignment is small, then the following code could achieve the desired effect. Suppose that we have some reference point located near the bottom left corner of the image. These reference points may be found by looking for some blobs with an intensity exceeding some predefined threshold. If the images to be processed are presented to input stream Pa and the reference image to Pb, then we can divide the task into two parts. The Static code would find the reference locations of the points, while the Varying code would not only find the current location of the points, but also shift the image accordingly. To save replication of code, we choose to define a user-defined function within the Static code that is responsible for finding the current location of the reference points:
function FindRef(Image,thresh) {
# Find all the blobs
blobs := find_blobs(Image,thresh);
# Search for the largest blob.
# Volume is stored in blobs[4,:]
iBlob := max_index_x(blobs[4,:]);
ret.x := blobs[0,iBlob];
ret.y := blobs[1,iBlob];
ret;
};
ref := FindRef(Pb[0:10,0:10],0.15);
For the Varying code we then use
now := FindRef(Pa[0:10,0:10],0.15);
dx := ref.x - now.x;
dy := ref.y - now.y;
shift(Pa,dx,dy);
Here the shift(..) function will only move the image to pixel resolution.
If you require subpixel resolution then use shift_interpolated(..) instead. Note, however, that the latter function must have arrays for the shift indices. This could be achieved using the following code segment for Varying code instead:
now := FindRef(Pa[0:10,0:10],0.15);
dx := make_like(Pa,ref.x - now.x);
dy := make_like(Pa,ref.y - now.y);
shift_interpolated(Pa,dx,dy);
Here we use the make_like(..) function to convert the shift increments into arrays for feeding into shift_interpolated(..).
Suppose we are interested in examining the velocity fluctuations relative to some mean velocity field. In the simplest case we would look at the difference between the current velocity field and a time average field. Suppose the time varying velocity field is available through the Pa source stream, and the mean velocity field (perhaps computed by the Time Average facility described in §5.6.1.1) is specified as the Pb stream with the Sequence box cleared. In this case we need not specify any Static code. For the Varying code we could specify:
out.u := Qa.u - Qb.u;
out.v := Qa.v - Qb.v;
out.Scalar := Qa.Scalar - Qb.Scalar;
out;
In this particular case, since all three data planes are being treated in the same way and we are not changing the description of scaling of the data planes, we could treat all three planes simultaneously and simply use Pa – Pb. Validity of this, however, depends on the contents of the scalar field.
The operation of this menu item is similar to that of Tools: Recipe (see §5.7.1), but rather than taking a stream and returning one output image for each input image, here only a single output image is created. The simplest form of an accumulation is the mean of the image stream, but this tool is more flexible (but slightly slower) than the Analyse: Time Average (see §5.6.1.1). The dialog controlling Tools: Accumulate is almost identical to that of Tools: Recipe, with each accumulation recipe being assigned to a Group within a Category. Some of the accumulation recipies also require Parameters to control their action.

Figure 131: The Accumulate dialog.
Users can add their own custom recipes to the list by creating a file named User_Accumulate.dfc either in the current directory, or in the directory in which DigiFlow is installed. (A copy in the current directory will have precedence over one in the DigiFlow directory.) A typical entry for a single-stream recipe in this file would look like
Accumulate.User.Statistics.NumberOverThreshold.Descr := "Count the number of images exceeding a threshold";
Accumulate.User.Statistics.NumberOverThreshold.Accumulate := {
if (Time.iNow = 0) {
acc := make_like(P,0);
thresh := p0;
};
acc += P > thresh;
};
Accumulate.User.Statistics.NumberOverThreshold.PostAccumulation := {acc;};
Accumulate.User.Statistics.NumberOverThreshold.Prompt0 := "Threshold";
Accumulate.User.Statistics.NumberOverThreshold.Param0 := 0.5;
Accumulate.User.Statistics.NumberOverThreshold.Check := {if (p0 < 1) {"Must have positive threshold."} else {null};
This would appear under Categgory User, Group Statistics, Recipe NumberOverThreshold. Here the recipe requires one parameter, producing the prompt Threshold in the interface. The default value of this parameter is set by the .Param0 variable, and the parameter is provided to the code as the variable p0. In this case, since a .Check variable is specified, the value of the parameter is checked. If the .Check code returns a string, then this is displayed as a warning message.
If two input streams are required, then the variable xxx.With should be defined, containing either "sequence" or "single", depending on whether a sequence or only a single image is to be recovered from the With stream. The image recovered from the With stream is provided to the .Code in the variable Pb (or, for image planes in Qb – refer to §5.7.2 for further details).
The facilities available within the code segment .Accumulate are exactly the same as those available in the Transform intensity and Combine images tools described in §§5.7.2 and 5.7.3. Typically the code will start with an if statement, checking Time.iNow, to set things up on the first iteration. Once all the frames have been processed, the .PostAccumulation code is run to form the final output.
Up to 6 prompts may be requested, their types (integer, floating point or string) being determined by the type of the default value in the .Paramn variable. Note that the description and code may be specified interchangeably as strings, code segments or memos.
The database of built-in recipes may be found in DigiFlow_Accumulate.dfc in the DigiFlow installation directory.
Unlike most of the other features in DigiFlow, a Slave process is intended to provide a mechanism for extracting information directly from an input stream (including live video) for direct inspection by the user. The range of uses for this mechanism is continuously expanding and includes processes ranging from velocity calculation to aids in setting up and focusing a video camera.

Figure 132: Dialog controlling a slave process.
As with the recipes described in §5.7.1, the interface provides a hierarchical interface to a series of macros providing the desired output. However, unlike a recipes feature, a slave process does not have an explicit image stream for the source of its data. Rather, it taps on to the image stream being displayed in the window that had the focus at the time the slave process was started. This master image may be a movie opened by File: Open Image, the output of another process, or live video. If the selected process is not too computationally expensive, then it will take the information from this stream and process it to produce output each time the master image is updated. When the master image is live video, then the output may be less frequent, but can be tailored to make use of adjacent frames, for example.
To specify a slave process, ensure the desired master image stream is the active window before selecting the slave process menu item. Slave processes in each Category are divided into one or more Group, each of which contains a selection of Recipes. Once the required recipe is selected, then the Parameters group may allow specification of optional parameters to provide some control over the process.
Users can add their own custom slave processes to the list by creating a file named User_SlaveProcess.dfc either in the current directory, or in the directory in which DigiFlow is installed. (A copy in the current directory will have precedence over one in the DigiFlow directory.) A typical entry for a single-stream recipe in this file would look like
Slave.User.Filter.LowPass.Descr := "Low pass filter";
Slave.User.Filter.LowPass.Code :=
{hS := get_active_view();
im := get_image(hS);
if (not(is_null(im))) {
hV := view(im.image);
view_colour(hV,im.lut);
};
while (not(is_null(im))) {
out := filter_low_pass(im.image,p0);
view(hV,out);
im := get_image(hS);
};
close_view(hV);
};
Slave.User.Filter.LowPass.Prompt0 := "Length";
Slave.User.Filter.LowPass.Param0 := 3;
Slave.User.Filter.LowPass.Check := {if ((p0 <= 0) or ((p0 mod 2) <> 0)) {"Length must be positive odd integer"} else {null};};
This would appear under Categgory User, Group Filter, Recipe LowPass. Here the recipe requires one parameter, producing the prompt Length in the interface. The prompt is specified by the .Prompt0 string and the default value of this parameter is set by the .Param0 variable. The type for the returned parameter must be the same as that of its default value. The specified parameter is passed to the .Code as the variable p0. In this case, since a .Check variable is specified, the value of the parameter is checked. If the .Check code returns a string, then this is displayed as a warning message.
Unlike a recipe that needs to deal with only a single image (or single pair of images), a slave process needs to handle a continual stream of images, and look after both their extraction from the master image stream and their display in a suitable format. Typically the code for a slave process starts by determining the source for the master stream by a call to get_active_view(). The macro get_image(..) is then used to simplify the extraction of the images from the master stream, whether it be a standard image stream or live video. In both cases, get_image(..) waits efficiently for a new image to be available. In the above example, a window (view) is created to contain the output, then further image are extracted repeatedly from the master stream until either the slave process or the master image stream is terminated.
Transforms an image stream to make the associated world coordinate system orthogonal.

Figure 133: Transform an image stream to world coordinates.
A single image selector provides the input stream in the Input group. This may be taken from a file using the File button, or from another Process.
The Output group specifies the destination of the transformed image using the Save As button. If this process is acting as the source for another process, the Save As button is suppressed (refer to §7 for further details).
The Controls for this process include the specification of the Coordinate System to be used to map the image. The limits on the coordinates corresponding to the left (x min), right (x max), bottom (y min) and top (y max) of the output image, the size of which is specified by the Width and optional Height if the aspect ratio is not to be preserved.
Any pixels in the output image not corresponding to a point in the source image is filled with Fill Intensity, 0.0 representing the minimum value, and 1.0 the maximum.
For multi-plane images containing vector fields, the conversion process will also rescale the vector fields so that they are converted from pixel to world coordinate systems. Note that this only applies if the input stream is in pixel coordinates. This feature is of particular value if PIV velocity fields are computed in pixel coordinate yet are later required in world coordinates.
The Window menu follows the standard Windows format and will not be given in detail here.
Documentation for DigiFlow resides largely in this manual plus the dfc Help facility described in §4.5. This manual is distributed as both html format in DigiFlow.htm, and as an Acrobat file in DigiFlow.pdf.
Clicking on the Help entry in the Help menu will start up an instance of Internet Explorer and, where possible, take you to the table of contents in the html version of the DigiFlow User Guide. Selection the function key f1 at any point will have the same impact, but where possible will jump to the most relevant section of the guide.
This will start up the dfc Help facility described in §4.5.
When checked, a browser window containing DigiFlow.htm is opened and automatically scrolled to the relevant section for each action undertaken within DigiFlow.
The Help About DigiFlow option brings up a screen that gives you DigiFlow version and build date information (see figure ).

There are a number of ways of determining the intensity to which black digitises. When working with two light sources for LIF the easiest way is to take three calibration images. The first image will have the left-hand light source only, the second the right-hand light source only, and the third with both light sources turned on. By then using Tools: Combine Images with these three images forming the Pa, Pb and Pc input streams, the following code will determine the black value and test the hypothesis of linear dye response simultaneously:
Image:=Pa+Pb-Pc;
black := mean(Image);
message("Black:"+black);
Image;
This code first evaluates the difference between the sum of the images due to the left and right hand light sources separately, and the image due to the two light sources working in tandem. If black were to digitise the some value rblack, then we would expect the resultant Image to be rblack. Inspection of the resultant image will highlight any defects in the images or assumptions, while the message box produced will give the black value.
An alternative method of determining black relies on the fact that it should have the same digitised value regardless of the camera aperture. Begin by acquiring two images of the same scene using different f-stops on the camera. The image with the wider aperture (smaller f/number) should not quite saturate; the second image should be with the lens stopped down by one f-stop. The scene should contain a broad range of intensities. Again using Tools: Combine Images, with the two images as Pa and Pb, use the following code to first generate a scatter plot, then fit a least squares regression to that line, and finally determine the intercept between this and a line of unit slope.
# Create scatter plot, scaling intensities from 0-1 to 0-255.
Image := make_array(0,256,256);
Image := scatter_to_array(Image,255*Pa,255*Pb,fill:=1,flags:=1);
# Find the centroid of the scatter plot
y := y_centroid(Image)/255;
x := x_index(y)/255;
# Fit line to plot, but only to central part of data
fit := fit_expression("1;x;","x;",x[50:250],y[50:250]);
# Look for root of x = a + bx => x = a/(1-b)
rblack := fit.coeff[0]/(1-fit.coeff[1]);
# Generate the fitted line
f := evaluate_expression(fit,x);
# Create a plot
hDraw := draw_start(640,480);
draw_set_axes(hDraw,0,1,0,1);
draw_x_axis(hDraw,"Bright image");
draw_y_axis(hDraw,"Dim image");
draw_create_key(hDraw,0.1,0.6,"Key");
draw_mark(hDraw,x,y);
draw_key_entry(hDraw,"Scatter plot",line:=false,mark:=true);
draw_line_colour(hDraw,"blue");
draw_lineto(hDraw,x,f);
draw_key_entry(hDraw,"Fitted curve",line:=true);
draw_text(hDraw,0.2,0.8,"Black:"+rblack);
draw_line_colour(hDraw,"green");
draw_line(hDraw,0,0,1,1);
draw_key_entry(hDraw,"Unit slope",line:=true);
draw_end(hDraw);
# Return the drawing handle as the "image"
hDraw;
The result of this code is shown in figure 135 below.

A powerful feature of DigiFlow is the ability to chain multiple processes together, thus creating an efficient way of automating complex algorithms for processing image streams. In addition, piping images allows the full resolution of the image stream to be used, without the need to map the stream into some image format with a lower intensity resolution for each pixel.
The procedure for creating a process chain begins by identifying the process producing the output that is ultimately required, and work backwards from that point. For example, you may wish to determine the standard deviation of fluctuations in concentration from an image stream that contains corrected intensity images of a flow. The final process in this case is the Time Averaging found in §5.6.1.1.
In the Sequence group, click the Process button to indicate that the input image stream will be taken from another process. This starts the Image Source dialog.

Figure 136: The image source dialog for connecting processes together.
This dialog contains three list boxes. The first, labelled Category, reflects the menu items controlling processes, with the addition of (from file) that allows the image stream to be taken from a standard file (enables the corresponding File button in the parent dialog). The Process list box then lists the various processes available within the Category list, and the Output list box indicates the one or more image streams produced. The source process is specified by the combination of items selected in these three list boxes.
Clicking Dialog (or OK if this is the first time the Image Source dialog has been started for this image stream and source process combination) will then start up the dialog box for the source process. In this case the Transform Intensity dialog described in §5.7.2.

Figure 137: Transform intensity dialog as part of a process chain.
When a process is acting as a server for another process, the normal Save As button is disabled and the destination preview window indicates that the result will be piped into another process. The remainder of the dialog is unchanged. Once the image source has been specified using the File button, the timings and region may be set with the Sift button (§4.3). Alternatively, the chain may be extended by selecting another process with the Process button.
Exiting this dialog with the OK button returns to the parent dialog (here the Time Average dialog).

Figure 138: Time average dialog at the root of a chain.
This dialog, at the root of the processing chain, requires the destination for the Output image stream to be specified. The input image stream (the Sequence group) now has the File button disabled and indicates the source process in the preview pane. Once the specification of the dialog is complete, pressing OK will start the process.
DigiFlow contains a sophisticated mathematical interpreter capable of operating directly on numbers, arrays and/or entire images, and of controlling and automating complex processes. This interpreter is used widely within DigiFlow to provide the user with the maximum power and flexibility. The language utilised by this interpreter is often referred to as dfc code within this manual.
This section outlines the basic syntax, operators and execution control statements understood by the interpreter, and provides the key elements required to enter expressions and code segments in dialog boxes associated with the menu-driven processes provided by DigiFlow. Discussion of the broad range of basic and advanced functions and the use of the interpreter as a macro or command language are deferred until §9. Techniques used to access built in DigiFlow processes and write complete macros are described in §10. However, only brief details of the individual functions are given in this manual. More comprehensive documentation is to be found in the DigiFlow dfc Help facility described in §4.5.
Note that the interpreter is case sensitive with all pre-defined constants, functions, operators and variables specified by lower case names. Variables supplied by DigiFlow to represent a data stream or the result of a specific manipulation normally begin with an upper case character.
The basic syntax of DigiFlow dfc code has some similarities with other high level languages such as C, Pascal or Matlab, but also has a number of significant differences.
Of key interest to experienced programmers is that the assignment statement is :=, similar to Pascal, with C-like +=, -=, *= and /= variants. The conditional assignment operator ?= will only make an assignment if the target variable (on the right-hand side) does not already exist. Statements terminate with a semicolon (;), and blocks of code are delimited with braces ({…}).
Array and list indices utilise square brackets ([…]), with parentheses ((…)) being used for function arguments and mathematical brackets. Square brackets ([…]) can also be used to construct arrays, whereas double angle brackets (<<…>>) can be used to construct a compound variable.
Exponentation uses a caret (^), while mod, div, max and min are all binary operators. Logical true takes the numeric value of unity, while false is mathematically zero. Logical negation not(..) is a function, while the binary comparative operators are =, <>, >, >=, < and <=. Loops take the form for i:=0 to 100 step 2 {…}; or while (condition) {…};. Conditional execution uses if (condition1) {…} elseif (condition2) {…} else {…};. Note that for both while and if that the condition must be delimited by brackets.
Variables may be integer, logical, real, array (of real values), string, compound or list (of arbitrary types). A compound variable is similar to a structure in other languages, but is more flexible, whereas a list is effectively an array that can contain a mix of variables of any or all types. Arrays can be constructed using make_array(..), or directly using square brackets, e.g. [1 2 3] or [1,2,3]. Components within compound variables are separated with a dot and can be constructed using double angle brackets (e.g. this := <<time:=3.0,frame:=6>>).
Standard strings are specified using double quotes as "This is a sample string". To include double quotes within the string, double the quote up, i.e. "To use ""quotes"" within a string." However, there is a maximum length to a standard string of 256 characters. Longer strings should be specified as a memo, delimited as {/A memo can hold a string of arbitrary length. All DigiFlow functions where the 256 character limit on a standard string is likely to be limiting can accept memos as well as or instead of strings./}. Both strings and memos (and also blocks of code) may be concatenated using the + operator. Concatenating a numeric value with a string will cause the numeric value to be converted into a string before the concatenation. Similarly, concatenation of a string or a numeric value with a memo will result in a memo. For example, "File"+123 will yield the string "File123". More control over the format when converting a numeric value to a string is achieved using make_string(..). The function replace_hashes(..) provides a convenient method for constructing file names with a fixed number of digits including leading zeros.
A key difference compared with languages such as C or Pascal is that variable typing is all dynamic and determined by the assignment statement. A given symbol/name may change between any one of the basic types during the execution of code. Expressions involving mixed type are often permitted, with the result being, generally, what is expected. For example, if arr is an array, then the expression arr + 3 will add three to every element in arr.
By default, all user-defined functions are pure functions in that changes to any of the parameters are discarded with the return value being the way of returning all information to the calling code. The return value is the result of the last statement to be executed. It is not necessary for this statement to have a corresponding assignment. For example, the definition function Three() {ret := 3;}; and function Three() {3;}; will both return the integer three.
DigiFlow allows the use and creation of variables within all code segments. Variable names may use any alphanumeric character, plus the underscore. Names must not start with a numeric character. Variable names are case-sensitive.
There are four basic types of variable: integer, floating point, array and string. Additionally, there are a number of special purpose variable types, specifically memo, code and null. The last of these, null, is simply a place holder with no value, while memos provide a container for blocks of text that are too long to fit in standard strings. Code variable are a specialist form of memo that contain executable code.
Normally, declaration statements are not required to create a basic variable: it need simply occur on the left-hand side of an assignment statement (§8.3). However, in some cases an array of a particular size may be required, and in such cases the make_array(..) function, or one of the other more specialist array constructors (e.g. make_like(..), random_array(..), gaussian_array(..), x_index(..), y_index(..)) should be used on the right-hand side of an initial assignment statement. Similarly, a list can be created and initialised using make_list(..).
Both arrays and lists of strings can also be constructed in line using square brackets. If the contents between the square brackets are purely numeric, then an array is constructed. If the contents includes any strings, then a list is created. For example, [99, 98, 97, 96] will construct a one-dimensional array with four real elements (there are no integer arrays). In contrast, ["dog", "cat", "mouse"] produces a list with three string elements. The elements of a list need not all be of the same type, thus ["two", 3, "four"] is valid. Further information about arrays is given below in §8.4 and lists in §8.5.
A null value can be obtained either by assignment of null, or as the return value of certain functions (sometimes representing an error condition).
Memo variables can be constructed using the following syntax: MyMemo := {/The memo is contained between an openning brace-slash pair, and a corresponding closing slash-brace pair./};. Whereas standard strings in DigiFlow have a fixed maximum length, memos can be of arbitrary length. In many places, strings and memos may be used interchangeably.
Blocks of code are delimited by braces, whether as part of a control structure (e.g. a for loop or if block) or when being assigned to a variable. For example MyCode := {a += 5;}; execute(MyCode); creates the code variable MyCode then executes it.
For mathematical computations, type conversion will take place automatically as and where it is appropriate. For example, multiplying an array by a scalar will produce an array. Division of two integers will produce a real (floating point) value (integer division is achieved using the div operator).
Compound variables are similar to “structures” or user-defined “types” in other languages. Compound variables may be used to store more than one value of the same or different types. They are distinguished by having a dot (.) within their name. The part of the name to the left-hand side of the dot is the name of the compound variable, while the part of the name to the right-hand side is the name of the component: name.component. Each component may itself be any DigiFlow variable type, including arrays, lists and compound variables.
Whereas in most languages, the components contained within a compound variable need to be declared in advance, this is not true for DigiFlow. Here a compound variable is created by a standard assignment statement, and as many component variables as required may be added. Moreover, each of these component variables may themselves be compound variables.
The following example illustrates the use of simple and compound variables.
Start := 0; # Assignment to a simple variable
Using.Code := {1 – P}; # Create a compound variable
# and component variable
Using.File := "Test.dfm"; # Add a second component variable
Using.File_Time.FromStep := 0; # Component variable Time is a
# compound variable
Using.File_Time.ToStep := 1;
...
Result := MyProc(Start,Using); # Pass both simple and compound
# variables to a function.
If an existing simple variable appears on the left-hand side of a compound variable assignment, then the original contents of the simple variable will be discarded and a new compound variable of the same name created. In particular,
Var := "simple"; # Simple variable
Var.Handle := 1; # The string "simple" is discarded
Both simple and compound variables may be passed to functions or returned from functions (see §8.9). Compound variables are of particular value dealing with the processes that can be started from menu items (see §10.1.1).
In some circumstances, it can be convenient to assign multiple parts of a compound variable in a single statement. This is particularly true when calling a function which takes a parameter as a compound variable, but where you do not have such a compound variable setup already. Consider the assignments
This.time := 1.0;
This.frame := 25;
This.file.name := "Test.dfi";
This.file.sequence := false;
These may be reduced to the single compound statement:
This := <<time:=1.0; frame:=25; file:=<<name:="Test.dfi"; sequence:=false;>> >>;
The compound variable constructors, the << … >> pairs, are used to bracket the values to be combined into a single compound variable. As illustrated in the above example, the compound constructors may be nested.
The type of a given variable may be determined through one of the inquiry functions is_array(..), is_list(..), is_code(..), is_compound(..), is_integer(..), is_memo(..), is_null(..), is_numeric(..), is_real is_string(..).
Assignment takes place once all the operations and function evaluations are complete, if there is an assignment operator and variable at the start of the expression (e.g. a := b+c;). If there is no assignment, the result will be discarded, or, if it is the last result in a segment of code, it will be returned to the routine calling the interpreter.
The various assignment operators are listed below:
|
Assignment Operator |
Description |
Example |
|
:= |
Standard assignment. The result of the expression on the right-hand side is stored in the variable on the left-hand side. |
MyArray := (Pa + Pb)/2; |
|
+= |
Increment assignment. The result of the expression on the right-hand side is added to the contents of the variable on the left-hand side and the result stored back on the left-hand side. |
Count += 1; # This is equivalent to: Count := Count + 1; |
|
-= |
Decrement assignment. The result of the expression on the right-hand side is subtracted from the contents of the variable on the left-hand side and the result stored back on the left-hand side. |
Total –= a; # This is equivalent to: Total := Total – a; |
|
*= |
Multiple assignment. The result of the expression on the right-hand side is multiplied by the contents of the variable on the left-hand side and the result stored back on the left-hand side. |
Value *= 2; # This is equivalent to; Value := Value*2; |
|
/= |
Fraction assignment. The contents of the variable on the left-hand side is divided by the result of the right-hand side and the result stored back on the left-hand side. |
Test /= f; # This is equivalent to: Test := Test/f; |
|
?= |
Conditional assignment. An assignment is made only if the target variable does not already exist. If the target variable does exist, then its contents remain unchanged. |
This ?= default; # The above is equivalent to Tmp := default; if (not(exists("This"))) {This := default;}; |
All array variables are inherently four-dimensional, although in most cases only the first one or two dimensions are used and some cases the dimensions may be collapsed to make a vector (scalar). Use of specific elements within an array, and assignment to specific elements of an array may be performed as shown below. Note that an assignment statement specifying specific array elements requires the array to exist already. If the target array of an assignment does not already exist, then the assignment can only specify the entire array.
Arrays are generated as the result of expressions and as the return value of many dfc functions. DigiFlow also includes two functions specifically designed to construct arrays: make_array(fill,nx,ny,…) and make_like(template,value). In the first case, between two and five parameters may be specified to the function, the first giving the value the array should be initialised with, and the remainder giving the dimensions of the array (up to four dimensions can be specified, although only the first dimension is mandatory). The fill parameter must be either an integer or floating point scalar value. The second constructor, make_like(..), takes the specified template (which must be an existing array) as a guide to the dimensions of the array that is required, and initialises it with value. Unlike fill in make_array(..), the value passed to make_like(..) may be an array, the values of which will be packed into the new array (e.g. the function may be used to convert a two-dimensional array into a one-dimensional array, or vice versa), filling any extra values in the new array with zeros, or discarding any surplus values from value if the total number of elements do not coincide. If value is a scalar (integer or floating point value), then it is simply replicated to each of the elements in the newly constructed array.
|
Array |
Description |
Example |
|
a |
For array variables in expressions, the entire array will be utilised. For arrays on the left-hand side of assignment statements, the old contents of the variable will be discarded and replaced by the result of the expression. |
# Average two images This := (First + Second); |
|
a[i,j] |
Access to the i,jth element of the array a. Specification in an expression will return a floating point scalar. Specification on the left-hand side of an assignment will cause only the i,jth element to be updated. If the right-hand side returns an array, then the corresponding i,jth element from the right-hand side is used. If the right-hand side returns a scalar, then this value is used. |
# Location of centre i := x_size(Background)/2; j := y_size(Background)/2; # Intensity at centre iCentre := Background[i,j]; |
|
a[i0:i1,j0:j1] |
Access to the sub-array of a spanning from i0 to i1 and j0 to j1. Specification in an expression will return an array of size (i1 - i0 + 1)´(j1 - j0 + 1). Specification on the left-hand side of an assignment will cause only this sub-array to be updated. If the right-hand side returns an array, then the corresponding sub-array of elements from the right-hand side is used. If the right-hand side returns a scalar, then this value is used. If one or both limits are omitted, then the corresponding limit to the dimension will be used. Hence a[:,:] corresponds to the entire two-dimensional array. |
# Men intensity in window; |