3DMA Developer's Primer
Contents
Recommended reading
Back to top
- New to Unix/Linux?
Any book with a good review on Amazon
will probably serve you well.
However, I recommend using the Internet to search for help, as well as the
books:
- Graham Glass: "Unix for programmers and users"
- very well written, general overview of UNIX concepts
- Ellie Quigley: "Linux shells by example" - comes with a handy CD.
- Very useful Linux commands
-
ANSI standard C/C++
- Dietel/Dietel: "C: How to program" and "C++: How to program"
- Kernighan/Ritchie: "The C programming language"
- somewhat hard to digest, but these guys developed C and a lot of
unix routines, so coding examples inside represent efficient coding
classics.
-
Real stuff: +)
- Gabriele Lohmann: "Volumetric image analysis", 1998
- we are dealing with volumetric (3D) images and this book provides
a nice overview of image analysis issues encountered (segmentation,
medial axis extraction, ...)
.
- Jacob Bear: "Dynamics of Fluids in Porous Media", 1972
- a bit old but a classic, it is a nice textbook;
its paperback price is budget friendly.
- F.A.L. Dullien: "Porous Media: Fluid Transport and Pore Structure",
1992 - this monograph contains a great deal of information but
personally I find it a bit too condensed. It is out of print and hard
to find.
- Sauro Succi: "The Lattice Boltzmann Equation for Fluid Dynamics and
Beyond", 2001 - a hands on approach to the Lattice Boltzmann method,
a good place to start.
- Of course, the
3DMA-rock webpage
and the papers cited therein.
Searching for papers
Back to top
Any of the papers you need to read are likely to be available online these days.
Even for old publications, a lot of effort has been made to scan them and make
available online.
-
Stony Brook Library
- STARS Library catalog will tell you if book/paper is on the shelves;
E-journals catalog will tell you if you can access it online
-
Interlibrary Loan
- you can ask for a book/paper SBU doesn't have to be loaned to you from
another library; ILL is indeed very efficient.
-
Web of Science
- the most comprehensive reference search;
e.g. you can get all the papers published by a specified author
-
Citeseer
- very good source of computer science oriented papers
-
Search for the author on the web - the papers might be posted on
personal webpages.
Coding conventions
Back to top
The C standard is VERY stable, and hence the older Kernighan-Ritchie
standard as well as the ANSI standard compile everywhere,
the C++ standard is continually evolving, so C++ codes are compiler sensitive.
3DMA contains one major C++ subdirectory of code, the rest is C.
Keep in mind that the C++ code has been compiled with a couple of generation of
RedHat g++/gcc compilers; all other C++ compilers ... who knows.
Most of the time it has been ported to Linux and Sun Unix/Solaris machines;
never heard of anybody porting it to Windows but it should work under
Cygwin which uses a 'gcc' compiler.
Rarely are codes designed to be self explanatory; this is true with 3DMA as
well.
When coding:
First go to the
3DMA General Users Manual
to get definitions straight and try to follow these minimal commenting
standards:
-
Record the research article that describes the algorithmic approach
you are following.
-
Record down an explanation on what the algorithm supposed to do!
It will be helpful both to you and to succeeding 3DMA-coding students
Array packing convention
Back to top
The three dimensional arrays typically processed in 3DMA provide a value
for each point (voxel) in a rectangular volume.
Rather than representing them as 3D arrays in C, volumetric data is packed
into a one dimensional array. This vastly speeds processing of data.
The convention is as follows
Given a 3D volume of
nx rows,
ny columns, (slice size nxy = nx*ny)
nz slices, (volume size nxyz = nx*ny*nz),
let (i,j,k) denote a point location in
[0..(nx-1)]
x
[0..(ny-1)]
x
[0..(nz-1)],
and ind = k*nxy + j*nx + i.
Then the data value at the point (i,j,k) is stored in the location dat[ind],
is a one dimensional array 'dat'.
Note that (i,j,k) <--> ind is a one-to-one correspondence.
io/cube.h defines a structure, Cube_Info, that stores volume
size information, as well as a number of macros such as
"Ind_2_ijk" and "Ijk_2_ind"
that switch back and forth between (i,j,k) and index 'ind'.
Example 3DMA driver
Back to top
Below is a printout of (an outdated version of) the file src/io/seal.c.
It represents an example of simple driver code in 3DMA and
demonstrates coding styles adopted for the 3DMA code.
Comments explaining the file and coding style are in
red.
I am assuming you have access to the code so you can look up the files
referenced in the commentary.
//The copyright declaration is a mandatory header of each file.
/*
* Copyrighted, Research Foundation of SUNY, 2003
*/
//Comment on file's purpose.
/*
* Artificially sealing the segmented data: 1-voxel layer of brick volume
* on all 6 sides is converted to phase 1(grain).
*/
#include <stdio.h>
//This is C header.
#include "dat_types.h"
//dat_types.h is in the src/
directory and contains typical
//shortcuts used in memory allocation like UCSZ used below
#include "io.h"
#include "filenames.h"
#include "cube.h"
#define MAT0 0
#define MAT1 1
void seal_driver(void)
{
//The list of all the functions used in this function
//is a mandatory part of each function.
extern void
get_filenames(char *,char **,char **,int *,int *,char *);
extern void
set_vol_size(int *,int *,int *,int *,int *,int *,int *);
extern void
set_mat_from_segfl_vol(unsigned char,File_Info *,
Cube_Info *,unsigned char *,unsigned char);
extern void
output_mat_segfl_vol(unsigned char,File_Info *,
unsigned char *, Cube_Info *,unsigned char);
//the following three functions are part of 3DMA memory checking routines
extern int
MEMCHECK(void *,char *,int);
extern void
FREE(void *,int);
extern void
clean_up(int);
File_Info segfl, segfl_new;
Cube_Info cube;
unsigned char *dat;
char *msg;
int i, j, k, ind, n, cnt;
//get_filenames is a standard routine that will import names of files
//needed by the function as well as information on compression etc.
get_filenames("segmented volume",&segfl.base,
&segfl.name,&segfl.len,
&segfl.cmprss,"");
set_vol_size(&cube.zs,&cube.ze,&cube.nx,
&cube.ny,&cube.nz,&cube.nxy,
&cube.nxyz);
get_filenames("sealed segmented",&segfl_new.base,
&segfl_new.name,
&segfl_new.len,&segfl_new.cmprss,"");
//dynamic memory allocation with typical use of MEMCHECK
dat = (unsigned char *)calloc(cube.nxyz,UCSZ);
msg = "dat in seal_driver()";
//this is an error message that will be displayed
//if memory cannot be allocated for some reason
//MEMCHECK will simply add the allocated number of bytes to a global
//counter. It is important to have that counter both for debugging and
//for finding the size of the volume that can be processed in memory
//consuming cases.
if( MEMCHECK((char *)dat,msg,cube.nxyz*UCSZ) ) clean_up(0);
//read in segmented data from a volume file into allocated memory
set_mat_from_segfl_vol(MAT1,&segfl,&cube,dat,MAT1);
//count number of phase 0 voxels
cnt = 0;
for( i = 0; i < cube.nxyz; i++ ) { if( dat[i] == MAT0 ) cnt++; }
printf("\nBefore sealing");
printf("\n%d phase 0 voxels, %d phase 1 voxels,
%d total voxels",
cnt,cube.nxyz - cnt,cube.nxyz);
printf("\nporosity %f",(float)cnt/cube.nxyz);
//set n=1 outside layer(s) of voxels to phase 1
ind = 0;
n = 1; //number of layers
for( k = 0; k < cube.nz; k++ )
{
for( j = 0; j < cube.ny; j++ )
{
for( i = 0; i < cube.nx; i++, ind++ )
{
if( (k < n) || (k >= cube.nz - n)
|| (j < n) || (j >= cube.ny - n)
|| (i < n) || (i >=
cube.nx - n) ) dat[ind] = 1;
}
}
}
//count number of phase 0 voxels
cnt = 0;
for( i = 0; i < cube.nxyz; i++ ) { if( dat[i] == 0 )
cnt++; }
printf("\nAfter sealing");
printf("\n%d phase 0 voxels, %d phase 1 voxels, %d total voxels",
cnt,cube.nxyz - cnt,cube.nxyz);
printf("\nporosity %f",(float)cnt/cube.nxyz);
//outputs new segmented volume data file
output_mat_segfl_vol(MAT1,&segfl_new,dat,&cube,1);
//FREE frees the pointer and subtracts memory(in bytes)
//from the global memory counter
FREE(dat,cube.nxyz*UCSZ);
}
Debugging with GDB
Back to top
- Uncomment the option DBX = -g in the makefile (src/makefile).
- Recompile the desired part of the code.
- Prepare a "stripped" input file using stripcomm:
stripcomm_linux -b < caseM.N.in > gdb.in
- Start gdb with the full path to your executable as argument, e.g.
gdb ~/3dma/bin/3dma_linux
- In the gdb environment, run the code by typing
run < gdb.in
(or
run < gdb.in > out
should you wish to redirect output).
- The main gdb commands you need to know are
run, where, break, next, cont, print and quit.
To learn more about gdb, follow this
link
Time profiling - finding out which function is taking the most CPU time
Back to top
There is a utility that can show you what percentage of time you
spend in every function of your code. This is very useful if you
need to figure out which parts of the program are taking too much time
and need to be redesigned. The basic three steps of time profiling are
-
Compile and link your program with the '-pg' option. e.g.
compiling:
gcc -g -c myprog.c utils.c -pg
linking:
gcc -o myprog myprog.o utils.o -pg
Note that in 3DMA this is equivalent to setting the option
"DBX = -g -pg"
in src/makefile and then recompiling all the files of
the code containing subroutines you wish to profile.
-
Execute your program, i.e.
% myprog
eg. in 3DMA, run the case you want,
% runcase linux caseM.N
This will create the file gmon.out in the working directory.
-
Run gprof,
% gprof myprog > gprof.ouput
eg. for the 3DMA code type
% gprof ~/3dma/bin/3dma_linux > gprof.out
(where ~/3dma/bin/3dma_linux should be substituted with the full path
of 3dma_linux executable you are using) and take a look at
gprof.output.
The above three steps are just a short reminder, you should read
this excellent summary on the gprof utility to get more details.
The memory debug compilation option in 3DMA
Back to top
Every time MEMCHECK() is used to increment global memory counter
(after dynamic memory allocations with malloc and realloc)
or memory is freed using FREE(), you can get a printout on
pointer and memory amount allocated (as well as any mismatches).
Furthermore, at the end of the output file a list (MEM_LIST) of pointers
that were not freed can be printed (File src/mem.c has more details).
To turn the above memort debugging option on, recompile the desired
part of the code AND src/mem.c with the option
DBX = -DMEM_DBG
in src/makefile, and then run the code as usual.
Workstations in the Lindquist lab
Back to top
| Workstations: |
berea, bubbles, fiber, jungle, medax, neuron, mukluk, petra, woof |
| File server: |
totem |
| Current operating system: |
Redhat Linux 9.0 |
| | |
| Software Tools: |
xpdf - pdf viewer |
| |
ggv, gs - ps viewer |
| |
xv, gimp - 2d image viewing/manipulation |
| |
Geomview (all machines),
Inventor (only on medax) |
- 3D image viewing/manipulation |
|
All data that resides on the workstations
(file systems /nfs/user[1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25])
is backed up on a weekly basis.
See this section to learn how one exports file
systems on a unix network.
Current backup schedule:
| |
backup of |
time |
| berea |
bubbles:/user24 |
Sat, 2am
|
bubbles
|
neuron:/user7,8,9
berea:/user17,18,19
|
Sat, 10pm |
| fiber |
N/A |
|
| medax |
petra:/user22 |
Fri, 11pm |
| mukluk |
berea:/user21
medax:/user3,4,5,6 |
Sun, 1am |
| neuron |
N/A |
|
| petra |
medax:/user3,4,5,6 |
Sun, 11pm
|
| woof |
fiber:/user1,2
mukluk:/user20,23 |
Sat, 4am |
How to know which hardware components are installed on your system?
Here are the basic commands:
/sbin/lspci --> list of all video, sound cards, etc.
uname -a --> name of the system, name of the machine,
Linux version and basic hardware type are listed,
among other things
dmesg --> gives everything the kernel saw as it loaded, in order
(and in much more detailed than you want to know)
If you're experiencing a problem,
Linuxquestions.org
most probably has an answer.
Exporting file systems on a Unix network
Back to top
Machine A has directory /userA that machine B needs to access.
It is to be mounted as /nfs/userA on machine B via the network file system.
Here is how to arrange exporting of /userA from A and access to it on B.
You need to be logged in as superuser (root) to do steps 1-4.
- Edit /etc/exports on machine A to contain the line
/userA/ B(rw,sync)
- Execute the command
% exportfs -r (or /usr/sbin/exportfs -r)
- On machine B, edit the file /etc/auto.fs and add the
following line
userA -exec,dev,suid,rw A:/userA
- Execute the command
% /etc/init.d/autofs reload
That's it.
Basic rpm installation instructions
Back to top
'rpm' is a Linux utility that will install/uninstall precompiled software
(from a file in .rpm format).
Most of the software on any linux system is installed this way.
rpm -qa
will list all the software installed on the system via rpm;
to search for a specific one you can pipe it to 'grep'.
For instance, to check whether the package "xv" is already installed, type
rpm -qa | grep xv
So, let's try to install 'xv' which is free software for
viewing/manipulating images.
- Use the internet to find an appropriate rpm that you need.
(Note that xv is not bundled with the RedHat 9 distribution CDs.)
The following link is an rpm repository that contains most of the existing
rpms:
http://rpmfind.net/linux/RPM/index.html
Search for "xv" in the above link - you will get plenty of options that
are associated with various Linux distributions. Try to find one that
you think is closest to your version of Linux (because of the
different compilers, some don't work, so you might need to try a number
of them). Let's say you picked and downloaded 'xv-3.10a-blah.rpm' to the
/user/downloads/ directory.
- To install the software you need to have 'root' access to the machine.
As root, do the following (in any directory)
rpm -ivh /user/downloads/xv-3.10a-blah.rpm
You will be notified about the success of the installation as well as
if there is any missing software/library. If there is missing
software, The RPMfind package, (available on the rpmfild.net site)is a great
resource for locating the missing piece
- just go back to the xv-3.10a-blah.rpm page and follow the appropriate link in
the "requires" section.
-
rpm --erase xv-3.10a-blah
will remove an installation.
-
man rpm
will give you more information about the 'rpm' utility.
Very useful Linux commands
Back to top
-
find performs a search of any directory tree (from '/' it can
search the entire disk, or at least the directories you have access to)
for certain files.
The command syntax is
find path_directory -name filename
e.g.
% find . -name "*neuron*"
searches for all files containing the string "neuron" in their name starting
in the current directory.
-
grep "expression" file(s)
searches the contents of file(s) for the given expression. e.g.
% grep "neuron" *.c
searches for the word "neuron" in all files with the .c extension in the
current directory)
-
top lists the current jobs (as well as who's running them) on the
machine. Might help you answer why the machine seems very slow and who's
responsible :+).
-
diff See man diff
-
Type
% import > file.ps
in a terminal window, use mouse movement and click-hold-release on the left
mouse button to define a rectangular region on the screen.
The contents of the rectangle will be saved as a postscript image in 'file.ps'.
The file extension "ps", "tif", "jpg", "pdf", etc. in fact determines the
format of the image file.
Very useful for grabbing screen content for inserting into a presentation.
Back to top
Created by Masa Prodanovic, January 2005