Index: Makefile.ALPHA =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.ALPHA,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- Makefile.ALPHA 25 Sep 2003 19:45:42 -0000 1.6 +++ Makefile.ALPHA 9 Feb 2004 03:29:14 -0000 1.7 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -rc RANLIB = echo ranlib not needed on $(ARCH) for NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.CRAY =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.CRAY,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- Makefile.CRAY 25 Sep 2003 19:45:42 -0000 1.5 +++ Makefile.CRAY 9 Feb 2004 03:14:50 -0000 1.6 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo ranlib not needed on $(ARCH) for NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.DARWIN =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.DARWIN,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- Makefile.DARWIN 25 Sep 2003 19:45:42 -0000 1.5 +++ Makefile.DARWIN 6 May 2004 21:59:28 -0000 1.6 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = ranlib NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.HPPA =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.HPPA,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- Makefile.HPPA 25 Sep 2003 19:45:42 -0000 1.5 +++ Makefile.HPPA 9 Feb 2004 03:14:50 -0000 1.6 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo ranlib not needed on $(ARCH) for NEWER = newer +SHR_EXT = sl +SHR_LD = ld -b include Makefile.common Index: Makefile.HPPA20 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.HPPA20,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- Makefile.HPPA20 25 Sep 2003 19:45:42 -0000 1.6 +++ Makefile.HPPA20 9 Feb 2004 03:14:50 -0000 1.7 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo ranlib not needed on $(ARCH) for NEWER = newer +SHR_EXT = sl +SHR_LD = ld -b include Makefile.common Index: Makefile.LINUX =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.LINUX,v retrieving revision 1.14 retrieving revision 1.15 diff -a -u -r1.14 -r1.15 --- Makefile.LINUX 25 Sep 2003 20:08:44 -0000 1.14 +++ Makefile.LINUX 9 Feb 2004 03:14:50 -0000 1.15 @@ -4,7 +4,7 @@ # CC = cc -ARCH_CFLAGS = -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DFORTRAN_ADD_UNDERSCORE -DUSE_PNG -Wimplicit -O +ARCH_CFLAGS = -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DFORTRAN_ADD_UNDERSCORE -DUSE_PNG -Wimplicit -g LD = $(CC) ARCH_LFLAGS = ARCH_LIBS = -lpng -lz @@ -12,5 +12,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.LINUXI386 =================================================================== RCS file: Makefile.LINUXI386 diff -N Makefile.LINUXI386 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Makefile.LINUXI386 4 Mar 2004 19:46:40 -0000 1.1 @@ -0,0 +1,18 @@ +# +# LINUX-specific Makefile for FMRI software +# +# + +CC = cc +ARCH_CFLAGS = -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DFORTRAN_ADD_UNDERSCORE -DUSE_PNG -Wimplicit -DLINUX -O +LD = $(CC) +ARCH_LFLAGS = +ARCH_LIBS = -lpng -lz +AR = ar +ARCH_ARFLAGS= -r +RANLIB = echo "%%%%" ranlib not needed for +NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared + +include Makefile.common Index: Makefile.SGI5 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.SGI5,v retrieving revision 1.7 retrieving revision 1.8 diff -a -u -r1.7 -r1.8 --- Makefile.SGI5 25 Sep 2003 19:45:42 -0000 1.7 +++ Makefile.SGI5 9 Feb 2004 03:14:50 -0000 1.8 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = /usr/lib/desktop/newer +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.SGI6 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.SGI6,v retrieving revision 1.4 retrieving revision 1.5 diff -a -u -r1.4 -r1.5 --- Makefile.SGI6 25 Sep 2003 19:45:42 -0000 1.4 +++ Makefile.SGI6 9 Feb 2004 03:14:50 -0000 1.5 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = /usr/lib/desktop/newer +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.SGI64 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.SGI64,v retrieving revision 1.10 retrieving revision 1.11 diff -a -u -r1.10 -r1.11 --- Makefile.SGI64 25 Sep 2003 19:45:42 -0000 1.10 +++ Makefile.SGI64 9 Feb 2004 03:14:50 -0000 1.11 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = /usr/lib/desktop/newer +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.SGIMP64 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.SGIMP64,v retrieving revision 1.4 retrieving revision 1.5 diff -a -u -r1.4 -r1.5 --- Makefile.SGIMP64 25 Sep 2003 19:45:42 -0000 1.4 +++ Makefile.SGIMP64 9 Feb 2004 03:14:50 -0000 1.5 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = /usr/lib/desktop/newer +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.SUN4SOL2 =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.SUN4SOL2,v retrieving revision 1.11 retrieving revision 1.12 diff -a -u -r1.11 -r1.12 --- Makefile.SUN4SOL2 25 Sep 2003 20:08:44 -0000 1.11 +++ Makefile.SUN4SOL2 9 Feb 2004 03:14:50 -0000 1.12 @@ -13,5 +13,7 @@ ARCH_ARFLAGS= -r RANLIB = echo "%%%%" ranlib not needed for NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -G include Makefile.common Index: Makefile.T3D =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.T3D,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- Makefile.T3D 25 Sep 2003 19:45:42 -0000 1.5 +++ Makefile.T3D 9 Feb 2004 03:14:50 -0000 1.6 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = echo ranlib not needed on $(ARCH) for NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.T3E =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.T3E,v retrieving revision 1.4 retrieving revision 1.5 diff -a -u -r1.4 -r1.5 --- Makefile.T3E 25 Sep 2003 19:45:42 -0000 1.4 +++ Makefile.T3E 9 Feb 2004 03:14:50 -0000 1.5 @@ -14,5 +14,7 @@ ARCH_ARFLAGS= -r RANLIB = ranlib NEWER = $(FMRI)/src/csh/test_newer.csh +SHR_EXT = so +SHR_LD = cc -shared include Makefile.common Index: Makefile.common =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/Makefile.common,v retrieving revision 1.43 retrieving revision 1.45 diff -a -u -r1.43 -r1.45 --- Makefile.common 7 Oct 2003 23:25:10 -0000 1.43 +++ Makefile.common 4 Mar 2004 19:46:40 -0000 1.45 @@ -27,7 +27,9 @@ RANLIB="$(RANLIB)" \ UNIX_STAT_HOME="$(UNIX_STAT_HOME)" \ AFS_FLAG="$(AFS_FLAG)" SPLUSEXE="$(SPLUSEXE)" \ - LAPACK_LIBS="$(LAPACK_LIBS)" NEWER="$(NEWER)" + LAPACK_LIBS="$(LAPACK_LIBS)" NEWER="$(NEWER)" \ + SHR_EXT="$(SHR_EXT)" SHR_LD="$(SHR_LD)" + SRCDIRS = util libcrg libmri libdcdf fmri reader baseline deghost \ meanc recon smregpar ireg outlier detrend \ intsplit stats displace summary phadj image_proc \ @@ -41,6 +43,7 @@ Makefile.HPPA Makefile.HPPA20 Makefile.SGI5 Makefile.SGI64 \ Makefile.SUN4SOL2 Makefile.T3D Makefile.T3E src/Makefile.pkg \ Makefile.SGIMP64 Makefile.LINUX Makefile.SGI6 Makefile.DARWIN \ + Makefile.LINUXI386 \ config.mk configure splus/Makefile.splus DOCFILES = doc/fiasco_executables.html doc/fiasco_install.html \ doc/fiasco_instruct.html \ Index: doc/fiasco_executables.html =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/doc/fiasco_executables.html,v retrieving revision 1.48 retrieving revision 1.55 diff -a -u -r1.48 -r1.55 --- doc/fiasco_executables.html 24 Sep 2003 23:15:36 -0000 1.48 +++ doc/fiasco_executables.html 4 May 2004 21:51:59 -0000 1.55 @@ -12,9 +12,26 @@

Some Fiasco shell scripts:

+
afni_estireg3d.csh +
may be substituted for estireg3d.csh to use AFNI's 3dvolreg.
color_by_phase.csh -
Produces a single image from a complex Pgh MRI dataset, showing +
produces a single image from a complex Pgh MRI dataset, showing magnitude and phase as brightness and color. +
convert_ifiles.py +
converts a directory full of GE image file subdirectories into +a collection of Pgh MRI datasets. +
coregister.py +
implements automatic coregistration of functional and structural scans. +
coregister_inplane.py +
is used to translate and rotate functional data to align with + inplane structural scans. +
+ coregister_struct_to_inplane.py +
is used to translate and rotate axial structural data to align with + inplane structural scans. +
customize_local.py +
is a project-specific script for setting up the .local.csh files + for individual Fiasco runs.
dataset_matches_env.py
checks that a dataset is compatible with the Fiasco environment variables.
FIASCO @@ -27,9 +44,14 @@
performs comparisons between the response of two different groups to experimental conditions.
make_cine.csh -
Produces an MPEG animation from a Pgh MRI dataset. +
produces an MPEG animation from a Pgh MRI dataset. +
make_group_anat.csh +
produces group averages of structural anatomy datasets. +
make_P_P_plots.csh +
produces a P-P plot from one or more Pmaps.
make_phase_cine.csh -
Produces an MPEG animation from a complex Pgh MRI dataset, +
produces an MPEG animation from a complex Pgh MRI dataset, showing magnitude and phase as brightness and color.
merge_fisher.csh
combines multiple Fiasco session results for the same subject @@ -37,15 +59,22 @@
merge_detrend.csh
combines multiple Fiasco session results for the same subject by aligning and concatenating the detrended session data. +
multi_runner.py +
automatically runs batches of individual Fiasco runs.
physio_correct_triggered.py
performs physio correction based on scanner trigger pulse data. +
+ pick_n_voxels.py +
Finds threhsolds to select the N most active voxels in a Pmap or Tmap.
pooled_mean.csh
constructs the pooled mean of a group of means with associated counts.
pooled_stdv.csh
constructs the pooled standard deviation of a group of stdvs with associated counts. +
renumber_ifiles.py +
builds renumbered links to GE image file directories
stats_to_floats.csh
Generated single precision floating point versions of stats files.
testingroup.csh @@ -96,6 +125,8 @@
motion estimation in the slice plane.
estireg3d
motion estimation in 3D. +
estiwarp +
estimates Affine warp parameters to align data in 2D or 3D.
extract
is deprecated. Please use mri_subset.
generate_vmpfx_in @@ -113,6 +144,8 @@
motion correction
ireg3d
motion correction in 3D +
iwarp +
implements Affine warps
matte
overlays one image on another, with transparency.
meanc @@ -166,6 +199,8 @@
change dimensions of Pittsburgh File Format, for example changing a time dimension into a (smaller) time dimension and a condition. +
mri_resample +
resamples one dimension of a Pgh MRI dataset.
mri_rpn_math
Tool to do general math on Pgh MRI datasets.
mri_scan_fold @@ -287,7 +322,7 @@
Joel Welling
-Last modified: Wed Sep 24 19:14:36 EDT 2003 +Last modified: Tue May 4 17:51:08 EDT 2004 Index: splus/script/anova.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/anova.S,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- splus/script/anova.S 18 Dec 1997 20:17:55 -0000 1.2 +++ splus/script/anova.S 24 Feb 2004 23:29:10 -0000 1.3 @@ -13,7 +13,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: anova.S,v 1.2 1997/12/18 20:17:55 welling Exp $ +# $Id: anova.S,v 1.3 2004/02/24 23:29:10 welling Exp $ # #interpretsplit <- function(spltfile) @@ -86,37 +86,37 @@ cvalsBySlice } -runAnovas _ function (x, tdim, xdim, ydim, zdim, formula) +runAnovas <- function (x, tdim, xdim, ydim, zdim, formula) { - x_x[,1:length(attr(terms(formula), "variables"))-1] - m _ length(terms(formula)) # or: dim(attr(terms(formula),"factors"))[2] + x<-x[,1:length(attr(terms(formula), "variables"))-1] + m <- length(terms(formula)) # or: dim(attr(terms(formula),"factors"))[2] - FValues _ array(0, dim=c(xdim, ydim, zdim ,m)) - inBuf _ array(0, dim=c(tdim, xdim)) - outBuf _ array(0, dim=c(xdim, m)) + FValues <- array(0, dim=c(xdim, ydim, zdim ,m)) + inBuf <- array(0, dim=c(tdim, xdim)) + outBuf <- array(0, dim=c(xdim, m)) for (sl in 0:(zdim-1)) for (y in 0:(ydim-1)) { - inBuf _ BioReadFloats(inBuf) + inBuf <- BioReadFloats(inBuf) RES <- t(matrix(inBuf, nrow=xdim)) x.new <- data.frame(t(x[sl,]),I(RES)) names(x.new) <- c(names(x), "RES") - wx _ aov(formula, x.new) - swx _ summary(wx) + wx <- aov(formula, x.new) + swx <- summary(wx) for (i in 1:xdim) - FValues [i, y+1, sl+1, ] _ as.matrix(swx[[i]])[1:m,4] + FValues [i, y+1, sl+1, ] <- as.matrix(swx[[i]])[1:m,4] } return (FValues) } -x _ interpretsplit(getenv("F_SPLIT_FTZ"),6) -formula _ eval(parse(getenv("F_FORMULA_FTZ"))) -ans _ runAnovas(x, 6, 64, 64, 4, formula) -ans[is.na(ans)]_ -1 # This finds all invalid results and substitutes -1 -dims _ dim (ans) +x <- interpretsplit(getenv("F_SPLIT_FTZ"),6) +formula <- eval(parse(getenv("F_FORMULA_FTZ"))) +ans <- runAnovas(x, 6, 64, 64, 4, formula) +ans[is.na(ans)]<- -1 # This finds all invalid results and substitutes -1 +dims <- dim (ans) dims[4] # emits number of following datasets for (i in 1:dims[4]){ paste(getenv("F_HEADER"),".F.", Index: splus/script/epiprintpar.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/epiprintpar.S,v retrieving revision 1.9 retrieving revision 1.10 diff -a -u -r1.9 -r1.10 --- splus/script/epiprintpar.S 28 Feb 2003 00:52:29 -0000 1.9 +++ splus/script/epiprintpar.S 24 Feb 2004 23:29:10 -0000 1.10 @@ -13,28 +13,28 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: epiprintpar.S,v 1.9 2003/02/28 00:52:29 welling Exp $ +# $Id: epiprintpar.S,v 1.10 2004/02/24 23:29:10 welling Exp $ # postscript("test.ps",horizontal=T) -shift _ c("Baseline.1","Baseline.2","Mean Adjustment","Deghost") +shift <- c("Baseline.1","Baseline.2","Mean Adjustment","Deghost") -baseraw _ matrix(scan("baseadjrw"),ncol=2,byrow=T) -basesmt _ matrix(scan("baseadjsm"),ncol=2,byrow=T) -means _ matrix(scan("meancprm")) +baseraw <- matrix(scan("baseadjrw"),ncol=2,byrow=T) +basesmt <- matrix(scan("baseadjsm"),ncol=2,byrow=T) +means <- matrix(scan("meancprm")) if (dodeghost) { - degraw _ matrix(scan("deghostrw")) - degsmt _ matrix(scan("deghostsm")) + degraw <- matrix(scan("deghostrw")) + degsmt <- matrix(scan("deghostsm")) par(mfrow=c(inc,4)) } else { par(mfrow=c(inc,3)) } -images _ length(basesmt[,1])/nslice +images <- length(basesmt[,1])/nslice for (pagenum in 0:(((nslice-1)/inc))){ for (rownum in 0:(min(c(inc-1,nslice-pagenum*inc-1)))){ - h _ rownum+pagenum*inc - sub _ (0:(images-1))*nslice+h+1 - subt _ (1:images) + h*images + h <- rownum+pagenum*inc + sub <- (0:(images-1))*nslice+h+1 + subt <- (1:images) + h*images plot(1:images,baseraw[sub,1],xlab="Image number",ylab=shift[1], main=paste("name Slice",h),pch='.') Index: splus/script/printregist.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/printregist.S,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- splus/script/printregist.S 8 Jan 2002 23:48:13 -0000 1.6 +++ splus/script/printregist.S 24 Feb 2004 23:29:10 -0000 1.7 @@ -13,25 +13,25 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: printregist.S,v 1.6 2002/01/08 23:48:13 welling Exp $ +# $Id: printregist.S,v 1.7 2004/02/24 23:29:10 welling Exp $ # # postscript("test.ps",horizontal=T) shift<-c("X Shift in Pixels","Y Shift in Pixels", "Rotation in Degrees","Average Displacement in Pixels") -p _ 4 -if ( nimage > 400 ) p _ 2 +p <- 4 +if ( nimage > 400 ) p <- 2 par(mfrow=c(inc,p)) -x _ matrix(scan("par/rreg"),ncol=6,byrow=T)[,3:5] -x_cbind(x,scan("par/dixplace")) -y_matrix(scan("par/sxreg"),ncol=6,byrow=T)[,3:5] -y_cbind(y,scan("par/smdisplace")) -images_length(x[,1])/nslice +x <- matrix(scan("par/rreg"),ncol=6,byrow=T)[,3:5] +x<-cbind(x,scan("par/dixplace")) +y<-matrix(scan("par/sxreg"),ncol=6,byrow=T)[,3:5] +y<-cbind(y,scan("par/smdisplace")) +images<-length(x[,1])/nslice for (pagenum in 0:(((nslice-1)/inc))){ for (rownum in 0:(min(c(inc-1,nslice-pagenum*inc-1)))){ for (plotnum in 1:4){ - h_rownum+pagenum*inc - sub_(0:(images-1))*nslice+h+1 + h<-rownum+pagenum*inc + sub<-(0:(images-1))*nslice+h+1 # plot(1:images,x[h*images+(1:images),plotnum],xlab="Image number",ylab=shift[plotnum],main=paste("name Slice",h)) plot(1:images,x[sub,plotnum],xlab="Image number",ylab=shift[plotnum],main=paste("name Slice",h),pch='.') # lines(1:images,y[h*images+(1:images),plotnum]) Index: splus/script/printregist3d.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/printregist3d.S,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- splus/script/printregist3d.S 20 Dec 2001 23:58:25 -0000 1.2 +++ splus/script/printregist3d.S 24 Feb 2004 23:29:10 -0000 1.3 @@ -13,7 +13,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: printregist3d.S,v 1.2 2001/12/20 23:58:25 welling Exp $ +# $Id: printregist3d.S,v 1.3 2004/02/24 23:29:10 welling Exp $ # # postscript("test.ps",horizontal=T) @@ -21,11 +21,11 @@ "3D X shift", "3D Y shift", "3D Z shift", "3D MSE", "3D Net Rotation", "3D Net Translation", "3D Displacement") par(mfrow=c(3,4)) -x _ matrix(scan("rreg"),ncol=9,byrow=T)[,2:9] -x _ cbind(x,matrix(scan("dixplace"),ncol=4,byrow=T)[,2:4]) -y _ matrix(scan("sxreg"),ncol=9,byrow=T)[,2:9] -y _ cbind(y,matrix(scan("smdisplace"),ncol=4,byrow=T)[,2:4]) -images _ length(x[,1]) +x <- matrix(scan("rreg"),ncol=9,byrow=T)[,2:9] +x <- cbind(x,matrix(scan("dixplace"),ncol=4,byrow=T)[,2:4]) +y <- matrix(scan("sxreg"),ncol=9,byrow=T)[,2:9] +y <- cbind(y,matrix(scan("smdisplace"),ncol=4,byrow=T)[,2:4]) +images <- length(x[,1]) for (plotnum in 9:11){ plot(1:images,x[,plotnum],xlab="Image number",ylab=shift[plotnum], main="name",pch='.') Index: splus/script/read.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/read.S,v retrieving revision 1.1 retrieving revision 1.2 diff -a -u -r1.1 -r1.2 --- splus/script/read.S 25 Jul 1997 21:50:40 -0000 1.1 +++ splus/script/read.S 24 Feb 2004 23:29:10 -0000 1.2 @@ -13,18 +13,18 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: read.S,v 1.1 1997/07/25 21:50:40 welling Exp $ +# $Id: read.S,v 1.2 2004/02/24 23:29:10 welling Exp $ # attach(paste(getenv("FIASCO"),"/../../splus/S/PVM_ARCH",sep=""),pos=1) -readHead _ function (name) +readHead <- function (name) { - type _ ndim _ vec _ 0 - dims _ rep(0, 100) - storage.mode (type) _ "integer" - storage.mode (ndim) _ "integer" - storage.mode (vec) _ "integer" - storage.mode (dims) _ "integer" - tmp _ .C("readFieldHead", + type <- ndim <- vec <- 0 + dims <- rep(0, 100) + storage.mode (type) <- "integer" + storage.mode (ndim) <- "integer" + storage.mode (vec) <- "integer" + storage.mode (dims) <- "integer" + tmp <- .C("readFieldHead", "name"=name, "type"=type, "ndim"=ndim, @@ -33,13 +33,13 @@ tmp } -writeField _ function (name, field,type,ndim,veclen,dims) +writeField <- function (name, field,type,ndim,veclen,dims) { - storage.mode (type) _ "integer" - storage.mode (ndim) _ "integer" - storage.mode (veclen) _ "integer" - storage.mode (dims) _ "integer" - storage.mode (field) _ "single" + storage.mode (type) <- "integer" + storage.mode (ndim) <- "integer" + storage.mode (veclen) <- "integer" + storage.mode (dims) <- "integer" + storage.mode (field) <- "single" .C("writeField", "name"=name, "type"=type, @@ -50,28 +50,28 @@ return (0) } -readField _ function (iL=rep(0,4), iU=rep(1,4)) +readField <- function (iL=rep(0,4), iU=rep(1,4)) { - res _ array (0, prod((iU-iL) + 1)) - storage.mode (iL) _ "integer" - storage.mode (iU) _ "integer" - storage.mode (res) _ "single" - tmp _ .C("readField", + res <- array (0, prod((iU-iL) + 1)) + storage.mode (iL) <- "integer" + storage.mode (iU) <- "integer" + storage.mode (res) <- "single" + tmp <- .C("readField", "iL"=iL, "iU"=iU, "value"=res) tmp } -runAnovas _ function (name, x, formula) +runAnovas <- function (name, x, formula) { - head _ readHead (name) - adim _ head$dims [1] - cdim _ head$dims [4] - m _ length(terms(formula)) # or: dim(attr(terms(formula),"factors"))[2] + head <- readHead (name) + adim <- head$dims [1] + cdim <- head$dims [4] + m <- length(terms(formula)) # or: dim(attr(terms(formula),"factors"))[2] - FValues _ array(0, dim=c(head$dims [1], head$dims [2],head$dims [3],m)) - x_x[,1:length(attr(terms(formula), "variables"))-1] + FValues <- array(0, dim=c(head$dims [1], head$dims [2],head$dims [3],m)) + x<-x[,1:length(attr(terms(formula), "variables"))-1] for (sl in 0:(head$dims [3]-1)) for (y in 0:(head$dims [2]-1)) @@ -81,11 +81,11 @@ x.new <- data.frame(x,I(RES)) names(x.new) <- c(names(x), "RES") - wx _ aov(formula, x.new) - swx _ summary(wx) + wx <- aov(formula, x.new) + swx <- summary(wx) for (i in 1:adim) - FValues [i, y+1, sl+1, ] _ as.matrix(swx[[i]])[1:m,4] + FValues [i, y+1, sl+1, ] <- as.matrix(swx[[i]])[1:m,4] } return (FValues) Index: splus/script/spiralprintpar.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/spiralprintpar.S,v retrieving revision 1.7 retrieving revision 1.8 diff -a -u -r1.7 -r1.8 --- splus/script/spiralprintpar.S 1 Mar 2002 19:38:10 -0000 1.7 +++ splus/script/spiralprintpar.S 24 Feb 2004 23:29:10 -0000 1.8 @@ -13,10 +13,10 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: spiralprintpar.S,v 1.7 2002/03/01 19:38:10 welling Exp $ +# $Id: spiralprintpar.S,v 1.8 2004/02/24 23:29:10 welling Exp $ # postscript("test.ps",horizontal=T); -shift _ c("Spikes","Mean Adjustment","Outliers"); +shift <- c("Spikes","Mean Adjustment","Outliers"); par(mfrow=c(inc,3)); if (exists("file.access")) { @@ -25,28 +25,28 @@ } if (!access("meancprm")) { - mc _ matrix(scan("meancprm")); + mc <- matrix(scan("meancprm")); } else { - mc _ matrix(0,nrow=nimage*nslice,ncol=1); + mc <- matrix(0,nrow=nimage*nslice,ncol=1); } if (!access("spikeprm")) { - spk _ matrix(scan("spikeprm"),ncol=3,byrow=T)[,3]; + spk <- matrix(scan("spikeprm"),ncol=3,byrow=T)[,3]; } else { - spk _ matrix(0,nrow=nimage*nslice,ncol=1); + spk <- matrix(0,nrow=nimage*nslice,ncol=1); } if (!access("outlierprm")) { - ol _ matrix(scan("outlierprm")); + ol <- matrix(scan("outlierprm")); } else { - ol _ matrix(0,nrow=nimage*nslice,ncol=1); + ol <- matrix(0,nrow=nimage*nslice,ncol=1); } -lclimgcnt _ length(mc)/nslice +lclimgcnt <- length(mc)/nslice for (pagenum in 0:(((nslice-1)/inc))){ for (rownum in 0:(min(c(inc-1,nslice-pagenum*inc-1)))){ - h _ rownum+pagenum*inc - sub _ (0:(lclimgcnt-1))*nslice + h+1 + h <- rownum+pagenum*inc + sub <- (0:(lclimgcnt-1))*nslice + h+1 plot(1:lclimgcnt,spk[sub],xlab="Image number",ylab=shift[1],main=paste("name Slice",h),type='h') plot(1:lclimgcnt,mc[sub],xlab="Image number",ylab=shift[2],main=paste("name Slice",h),pch='.') # lines(supsmu((1:lclimgcnt),mc[sub])) Index: splus/script/tsprintpar.S =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/splus/script/tsprintpar.S,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- splus/script/tsprintpar.S 2 Dec 2002 06:07:11 -0000 1.6 +++ splus/script/tsprintpar.S 24 Feb 2004 23:29:10 -0000 1.7 @@ -13,25 +13,25 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: tsprintpar.S,v 1.6 2002/12/02 06:07:11 welling Exp $ +# $Id: tsprintpar.S,v 1.7 2004/02/24 23:29:10 welling Exp $ # postscript("test.ps",horizontal=T) -shift _ c("Shot 1 Base Real","Shot 1 Base Imag","Shot 2 Base Real", +shift <- c("Shot 1 Base Real","Shot 1 Base Imag","Shot 2 Base Real", "Shot 2 Base Imag","Mean Adjustment") par(mfrow=c(inc,5)) -baseraw _ matrix(scan("par/baseadjrw"),ncol=2,byrow=T) -basesmt _ matrix(scan("par/baseadjsm"),ncol=2,byrow=T) -means _ matrix(scan("par/meancprm")) +baseraw <- matrix(scan("par/baseadjrw"),ncol=2,byrow=T) +basesmt <- matrix(scan("par/baseadjsm"),ncol=2,byrow=T) +means <- matrix(scan("par/meancprm")) -images _ length(basesmt[,1])/(2*nslice) +images <- length(basesmt[,1])/(2*nslice) for (pagenum in 0:(((nslice-1)/inc))){ for (rownum in 0:(min(c(inc-1,nslice-pagenum*inc-1)))){ - h _ rownum+pagenum*inc + h <- rownum+pagenum*inc for (shot in 1:2) { for (plotnum in 1:2){ - sub _ (0:(images-1))*(2*nslice) + (shot-1)*nslice + h + 1 + sub <- (0:(images-1))*(2*nslice) + (shot-1)*nslice + h + 1 plot(1:images,baseraw[sub,plotnum],xlab="Image number", ylab=shift[2*(shot-1)+plotnum],main=paste("name Slice",h), pch='.') @@ -39,7 +39,7 @@ } } - sub _ (0:(images-1))*nslice + h + 1 + sub <- (0:(images-1))*nslice + h + 1 plot(1:images,means[sub,1],xlab="Image number",ylab=shift[5], main=paste("name Slice",h),pch='.') # lines(supsmu((1:images),means[sub,1])) Index: src/csh/FIASCO =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/FIASCO,v retrieving revision 1.28 retrieving revision 1.29 diff -a -u -r1.28 -r1.29 --- src/csh/FIASCO 3 Dec 2003 22:00:11 -0000 1.28 +++ src/csh/FIASCO 6 May 2004 18:15:28 -0000 1.29 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: FIASCO,v 1.28 2003/12/03 22:00:11 bakalj Exp $ +# $Id: FIASCO,v 1.29 2004/05/06 18:15:28 bakalj Exp $ # Check for help command if ( $#argv >= 1 ) then @@ -46,14 +46,14 @@ echo '#BEGINNING NEW ANALYSIS' >>& $LOGFILE setenv F_STARTDATE "`date`" echo '#'$F_STARTDATE $0 >>& $LOGFILE -echo '$Id: FIASCO,v 1.28 2003/12/03 22:00:11 bakalj Exp $'\ +echo '$Id: FIASCO,v 1.29 2004/05/06 18:15:28 bakalj Exp $'\ >>& $LOGFILE echo '#'`whoami`' '`hostname` >>& $LOGFILE echo '#'$1' Processing' >>& $LOGFILE # FIASCO_VERSION number setenv FIASCO_VERSION 5.2 -setenv FIASCO_PATCHLVL 2 +setenv FIASCO_PATCHLVL 3 echo "#FIASCO Version "$FIASCO_VERSION" patch "$FIASCO_PATCHLVL\ >>& $LOGFILE if ($1 == 'spiral') then Index: src/csh/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/Makefile,v retrieving revision 1.23 retrieving revision 1.30 diff -a -u -r1.23 -r1.30 --- src/csh/Makefile 24 Sep 2003 23:09:49 -0000 1.23 +++ src/csh/Makefile 4 May 2004 21:54:07 -0000 1.30 @@ -23,7 +23,11 @@ pooled_mean.csh pooled_stdv.csh stats_to_floats.csh \ make_cine.csh make_phase_cine.csh color_by_phase.csh \ overlay.csh physio_correct_triggered.py \ - dataset_matches_env.py + dataset_matches_env.py pick_n_voxels.py customize_local.py \ + coregister_inplane.py make_P_P_plots.csh \ + coregister_struct_to_inplane.py coregister.py \ + multi_runner.py renumber_ifiles.py convert_ifiles.py \ + make_group_anat.csh afni_estireg3d.csh include ../Makefile.pkg Index: src/csh/afni_estireg3d.csh =================================================================== RCS file: src/csh/afni_estireg3d.csh diff -N src/csh/afni_estireg3d.csh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/afni_estireg3d.csh 4 May 2004 21:54:07 -0000 1.2 @@ -0,0 +1,183 @@ +#!/bin/csh -efx +# afni_estireg3d.csh +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1995,1996 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# * * +# * Original programming by S. Ali Imam * +# ************************************************************/ +# +echo '#'`date` $0 +echo '#$Id: afni_estireg3d.csh,v 1.2 2004/05/04 21:54:07 welling Exp $' +if (! -d par) mkdir par + +# Check for help command +if ( $#argv >= 1 ) then + if ( junk$argv[1] == junk-help ) then + if ( $#argv >= 2 ) then + scripthelp $0 $argv[2] + else + scripthelp $0 + endif + exit + endif +endif + +# Default behavior is to align data to mean. +if ( ! ${?F_EST3D_ALIGN} ) then + setenv F_EST3D_ALIGN "mean" +endif + +set dimstr = `mri_printfield -field images.dimensions $1` +if ( $dimstr == xyzt ) then + set perm_order = "txyz" +else + set perm_order = "vtxyz" +endif + +set xvox = \ + `mri_printfield -field images.voxel_spacing.x -nofail $1` +if (${#xvox} != 0) then + if ( $xvox != 0 ) then + echo "x voxel already there" + else + mri_setfield -field images.voxel_spacing.x -value ${F_XVOXEL} $1 + endif +else + mri_setfield -field images.voxel_spacing.x -value ${F_XVOXEL} $1 +endif + +set yvox = \ + `mri_printfield -field images.voxel_spacing.y -nofail $1` +if (${#yvox} != 0) then + if ( $yvox != 0 ) then + echo "y voxel already there" + else + mri_setfield -field images.voxel_spacing.y -value ${F_YVOXEL} $1 + endif +else + mri_setfield -field images.voxel_spacing.y -value ${F_YVOXEL} $1 +endif + +set zvox = \ + `mri_printfield -field images.voxel_spacing.z -nofail $1` +if (${#zvox} != 0) then + if ( $zvox != 0 ) then + echo "z voxel already there" + else + mri_setfield -field images.voxel_spacing.z -value ${F_ZVOXEL} $1 + endif +else + mri_setfield -field images.voxel_spacing.z -value ${F_ZVOXEL} $1 +endif + +# +# changing the target value into and afni dataset +# so we can use 3dvolreg on it. +# +pghtoafni -func $1 ${1}+orig + +if ( $F_EST3D_ALIGN == "mean" ) then +# +# calculating a mean in able to transform into afni +# and perform needed tasks +# + if ( ! -d stat) mkdir stat + mri_rpn_math -out data/junk -c missing \ + '$t, $z, 1.0, 1.0, if_print_3, 0.0' \ + $1 > fake_newsplit + stats -condition fake_newsplit -input $1 \ + -meanprefix stat/unmoved -stdvprefix \ + stat/unmoved -tsprefix stat/unmoved \ + -maxtpairs 0 + mri_destroy_dataset data/junk + rm fake_newsplit + + pghtoafni -anat stat/unmovedMean_1 Mean1+orig + set target = Mean1+orig +else if ( $F_EST3D_ALIGN == "median" ) then +# +# calculating the median +# + mri_permute -order $perm_order $1 ${1}_p + mri_subsample -median -d t -l 1 ${1}_p ${1}_median + mri_destroy_dataset ${1}_p + mri_remap -order vxyzt ${1}_median + + pghtoafni -anat ${1}_median Median+orig + set target = Median+orig +else + pghtoafni -anat $F_EST3D_ALIGN Mean1+orig + set target = Mean1+orig +endif + +# +# run afni's 3d volume registration +# +3dvolreg -base ${target} -dfile paramfile \ + -prefix aligned ${1}+orig + +smartreader -i data/aligned+orig.HEAD -out $2 + +# +# Getting rid of the extra files made by smartreader +# +set useless = ${2}.V* +while ( $#useless != 0 ) + mri_delete_chunk -c afni.${useless[1]:e} ${useless[1]:r} + rm $useless[1] + if ( $#useless != 1 ) then + set useless = ${2}.V* + else + break + endif +end + +set xdim = `mri_printfield -fld images.extent.x $1` +set ydim = `mri_printfield -fld images.extent.y $1` + +par_translate -i afni3d -o estireg3d -t ${F_NIMAGE} \ + -z ${F_NSLICE} -nx $xdim -ny $ydim -nz ${F_NSLICE} \ + -vx ${F_XVOXEL} -vy ${F_YVOXEL} -vz ${F_ZVOXEL} \ + paramfile par/${F_EST3D_PARMS}.$$ + +set step = `depath.csh $0` +echo "$step par/${F_EST3D_PARMS}.$$" >> $F_SUMM_INPUT + +# +# Cleaning up +# +if ( $F_EST3D_ALIGN == "median" ) then + rm Median+orig* +else if ( $F_EST3D_ALIGN == "mean" ) then + rm Mean1+orig* + mri_destroy_dataset stat/unmovedMean_1 + mri_destroy_dataset stat/unmovedStdv_1 +else + rm Mean1+orig* +endif + +rm ${1}+orig* +rm paramfile +rm data/aligned+orig* Index: src/csh/cg_brain.makeps.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/cg_brain.makeps.csh,v retrieving revision 1.12 retrieving revision 1.13 diff -a -u -r1.12 -r1.13 --- src/csh/cg_brain.makeps.csh 10 Sep 2003 20:17:23 -0000 1.12 +++ src/csh/cg_brain.makeps.csh 11 Dec 2003 23:53:50 -0000 1.13 @@ -28,7 +28,7 @@ # * Mods by Joel Welling * # ************************************************************/ # -echo '#$Id: cg_brain.makeps.csh,v 1.12 2003/09/10 20:17:23 bakalj Exp $' +echo '#$Id: cg_brain.makeps.csh,v 1.13 2003/12/11 23:53:50 welling Exp $' echo '#'`date`$0 cd stat @@ -58,6 +58,45 @@ ${F_MRI_TO_PS} ${fname:r} mv ${fname:r}*.ps ../ps end + + +# Threshold Bayes.P to select a given number of voxels if requested. +if ( ${?F_PICKN_COUNT} ) then + set twotailed = 0 + set titlestr = "$F_PICKN_COUNT vox left tail" + if ( ${?F_PICKN_TWOTAILED} ) then + if ( ${F_PICKN_TWOTAILED} ) then + set twotailed = 1 + set titlestr = "$F_PICKN_COUNT vox either tail" + endif + endif + + foreach i ( Bayes.P.mri ) + set b = $i:t + set j = $b:r + if ( $twotailed ) then + set val = `pick_n_voxels.py -P --twotails $F_PICKN_COUNT $j` + set hival = `python -c "print repr(1.0-${val})"` + echo "# Picking $F_PICKN_COUNT implies thresholding $j at P<$val or P>$hival" + overlay.csh -inmap $j.mri -inimage Baselevel.Mean \ + -headerout ${j}_n.mri \ + -lowthresh $val -highthresh $hival + -mingray 64 -maxgray 191 + else + set val = `pick_n_voxels.py -T $F_PICKN_COUNT $j` + echo "# Picking $F_PICKN_COUNT implies thresholding $j at P<$val " + overlay.csh -inmap $j.mri -inimage Baselevel.Mean \ + -headerout ${j}_n.mri \ + -lowthresh $val -highthresh 2.0 \ + -mingray 64 -maxgray 191 + endif + setenv F_PS_TITLE2 "$j $titlestr" + ${F_MRI_TO_PS} ${j}_n + mv ${j}_n*.ps ../ps + + end + +endif # Make overlayed versions of Tmap files if ( ${?F_LOWERT} || ${F_UPPERT} ) then Index: src/csh/convert_ifiles.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/convert_ifiles.csh,v retrieving revision 1.3 retrieving revision 1.4 diff -a -u -r1.3 -r1.4 --- src/csh/convert_ifiles.csh 10 Sep 2003 20:17:23 -0000 1.3 +++ src/csh/convert_ifiles.csh 10 Mar 2004 23:47:52 -0000 1.4 @@ -1,4 +1,4 @@ -#!/bin/csh -ef +#!/bin/csh -efx # convert_ifiles.csh #/************************************************************ # * * @@ -27,34 +27,9 @@ # ************************************************************/ # echo '#'`date` $0 -echo '# $Id: convert_ifiles.csh,v 1.3 2003/09/10 20:17:23 bakalj Exp $' +echo '# $Id: convert_ifiles.csh,v 1.4 2004/03/10 23:47:52 welling Exp $' -# Make the subdirectories of links, doing unpacking, etc. as need. -renumber_ifiles.csh +# This script has been converted to Python to work around some +# portability issues. +convert_ifiles.py -# Convert the resulting files to Pgh MRI format -foreach series ( 1 2 3 4 5 6 7 8 9 ) - set linkdir = "series"${series}"_links" - set tfile = "series"${series}"_with_guide" - set ofile = "series"${series} - if ( -d $linkdir ) then - echo "#####################################################" - echo "Converting series $series" - smartreader -i "${linkdir}/I.####" -multi -out $tfile - set tdim = `mri_printfield -field 'images.extent.t' -nofail $tfile` - if ( dummy$tdim != dummy ) then - if ( $tdim > 1 ) then - @ keept = $tdim - 1 - echo "Dropping guide volume from ${series}; ${keept} times remain" - mri_subset -d t -l $keept -s 1 $tfile $ofile - else - echo "Series ${series} is a single volume" - mri_copy_dataset $tfile $ofile - endif - else - echo "Series ${series} is a single volume" - mri_copy_dataset $tfile $ofile - endif - mri_destroy_dataset $tfile - endif -end Index: src/csh/convert_ifiles.py =================================================================== RCS file: src/csh/convert_ifiles.py diff -N src/csh/convert_ifiles.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/convert_ifiles.py 8 Apr 2004 22:21:36 -0000 1.2 @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# convert_ifiles.py +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1995,1996 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# ************************************************************/ +# +import sys +import os +import os.path +import string +import getopt +import re +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= '# $Id: convert_ifiles.py,v 1.2 2004/04/08 22:21:36 welling Exp $' + +ifileRegex= re.compile('I\.\d\d\d') +gzIfileRegex= re.compile('I\.\d\d\d\.gz') +zIfileRegex= re.compile('I\.\d\d\d\.Z') + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ) + else: + os.system( "scripthelp %s"%sys.argv[0] ) + sys.exit() + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",[]) +except: + errorMessage("%s: Invalid command line parameter" % sys.argv[0]) + describeSelf() + sys.exit(1) + +Message(idString) + +# Parse args +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + +smartreaderFlags= "" +if getDebug() or getVerbose(): + smartreaderFlags= smartreaderFlags+ "-verbose " +flags= " " +if getDebug(): + flags= flags+"-d " +if getVerbose(): + flags= flags+"-v " + +# Make the subdirectories of links, doing unpacking, etc. as need. +os.system("renumber_ifiles.py %s"%flags) + +# Convert the resulting files to Pgh MRI format +for series in xrange(1,10): + linkdir= "series%d_links"%series + tfile= "series%d_with_guide"%series + ofile= "series%d"%series + if os.access(linkdir,os.R_OK): + Message("#####################################################") + Message("Converting series %d"%series) + safeRun("smartreader %s -i %s/I.#### -multi -out %s"%\ + (smartreaderFlags,linkdir,tfile)) + tmpDS= MRIDataset(tfile) + imageChunk= tmpDS.getChunk("images") + if imageChunk.hasValue("extent.t"): + tdim= imageChunk.getDim("t") + else: + tdim= 1 + if tdim > 1: + keept = tdim - 1 + Message("Dropping guide volume from %d; %d times remain"%\ + (series,keept)) + safeRun("mri_subset -d t -len %d -s 1 %s %s"%(keept,tfile,ofile)) + else: + Message("Series %d is a single volume"%series) + safeRun("mri_copy_dataset %s %s"%(tfile,ofile)) + safeRun("mri_destroy_dataset %s"%tfile) + Index: src/csh/coregister.py =================================================================== RCS file: src/csh/coregister.py diff -N src/csh/coregister.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/coregister.py 3 Apr 2004 00:20:24 -0000 1.9 @@ -0,0 +1,129 @@ +#! /usr/bin/env python +# +################# +# Notes- +################# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: coregister.py,v 1.9 2004/04/03 00:20:24 welling Exp $" + +################# +# +# Main +# +################# + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 3 : + describeSelf() + sys.exit(1) + +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + +funcBBox= bboxFromFilename(os.path.abspath(pargs[0])) +funcChunk= funcBBox.chunk +funcVox= funcBBox.vox +inplaneBBox= bboxFromFilename(os.path.abspath(pargs[1])) +inplaneChunk= inplaneBBox.chunk +inplaneVox= inplaneBBox.vox +strctBBox= bboxFromFilename(os.path.abspath(pargs[2])) +strctChunk= strctBBox.chunk +strctVox= strctBBox.vox + +#Check reasonableness of input +for thisChunk in (funcBBox.chunk, inplaneBBox.chunk, strctBBox.chunk): + dimstr= thisChunk.getValue('dimensions'); + if dimstr != "xyz": + if dimstr == "xyzt": + if thisChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if thisChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if thisChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if thisChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +# Move to a temporary directory +tmpdir= makeTempDir('tmp_coregister') +homedir= os.getcwd() +os.chdir(tmpdir) + +flags= "" +if (getVerbose()): + flags= flags+"-v " + +if (getDebug()): + flags= flags+"-d " + +verboseMessage("#### Coregistering functionals to inplanes ####") +safeRun("coregister_inplane.py %s %s %s"%\ + (flags,funcBBox.chunk.ds.fname,inplaneBBox.chunk.ds.fname)) +verboseMessage("#### Coregistering axial structurals to inplanes ####") +safeRun("coregister_struct_to_inplane.py %s %s %s"%\ + (flags,inplaneBBox.chunk.ds.fname,strctBBox.chunk.ds.fname)) +verboseMessage("#### Generating transformation to inplane coordinates ####") +safeRun("coregister_inplane_to_inplane.py %s %s"%\ + (flags,inplaneBBox.chunk.ds.fname)) + +# Use the newly generated scripts to produce datasets for cowarping +verboseMessage("#### Generating datasets for cowarping ####") +safeRun("apply_coreg_inplane.gen_csh %s alignedFunc resampFunc"%\ + funcBBox.chunk.ds.fname); +safeRun("mri_subsample -d x -len %d %s tmp"%\ + (funcBBox.chunk.getDim('x'),inplaneBBox.chunk.ds.fname)) +safeRun("mri_subsample -d y -len %d tmp lowresInplane"%\ + funcBBox.chunk.getDim('x')) +lowresInplaneBBox= bboxFromFilename("lowresInplane") +lowresInplaneBBox.setVox(funcBBox.vox) +lowresInplaneBBox.setCorners(Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0)) +lowresInplaneBBox.exportBounds() + +# Generate the cowarp script +verboseMessage("#### Cowarping inplanes to functionals ####") +safeRun("cowarp_inplane.py %s alignedFunc lowresInplane"%flags) + +verboseMessage("#### Cleaning up ####") +# Move all the generated scripts back to the home directory +safeRun("cp *.gen_csh %s"%homedir) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/coregister_inplane.py =================================================================== RCS file: src/csh/coregister_inplane.py diff -N src/csh/coregister_inplane.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/coregister_inplane.py 2 Apr 2004 20:19:09 -0000 1.9 @@ -0,0 +1,270 @@ +#! /usr/bin/env python +# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: coregister_inplane.py,v 1.9 2004/04/02 20:19:09 welling Exp $" + +magicSizes= [ 2, 4, 8, 16, 32, 48, 64, 96, 128, 192, 256 ] + +generatedScriptHdr="""\ +#!/bin/csh -ef +# +# This is an automatically generated script! It's only good +# for this particular special case. Don't copy it around or +# edit it unless you *really* know what you're doing! +# +# Inputs: +# $1: input functional MRI file name +# $2: output functional MRI, translated and rotated to +# orientation of the inplane +# $3: $2 resampled up to the in-plane structural resolution +# +cat > tmp_coreg_inpl.par << EOF +""" +generatedScriptBody="""\ +EOF +ireg3d -x %f -y %f -z %f -i $1 -h $2 -p tmp_coreg_inpl.par +mri_resample -d x -len %d -start 0.0 -end %f $2 tmp_coreg_inpl_1 +mri_resample -d y -len %d -start 0.0 -end %f tmp_coreg_inpl_1 $3 +mri_setfield -field images.voxel_spacing -allxyz -value ' %f,%f,%f' $3 +mri_setfield -field images.voxel_size -allxyz -value ' %f,%f,%f' $3 +foreach ds ( $2 $3 ) + mri_setfield -field images.tlf -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.trf -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.tlb -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.trb -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.blf -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.brf -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.blb -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.brb -all012 -value ' %f,%f,%f' $2 + mri_setfield -field images.ctr -all012 -value ' %f,%f,%f' $2 +end +mri_destroy_dataset tmp_coreg_inpl_1 +rm tmp_coreg_inpl.par +""" + +def pickMagicPadSize( sz ): + for magic in magicSizes: + if magic>=sz: + return magic-sz; + +def getMean(chunk): + totDim= chunk.getDim('x')*chunk.getDim('y')*chunk.getDim('z') + safeRun("mri_copy_dataset %s tmp_mean_1"%chunk.ds.fname) + safeRun("mri_remap -order q -length %d tmp_mean_1"%totDim) + safeRun("mri_subsample -d q -length 1 -mean tmp_mean_1 tmp_mean_2") + lines= readCmdOutputToList("mri_rpn_math -out junk '0,$1,1,if_print_1' tmp_mean_2") + return float(lines[0]) + +def makeGradMag3D(ch,vox,dsname): + safeRun("mri_smooth -d x -smoother_type ddx %s tmp_x"%ch.ds.fname) + safeRun("mri_smooth -d y -smoother_type ddx %s tmp_y"%ch.ds.fname) + safeRun("mri_smooth -d z -smoother_type ddx %s tmp_z"%ch.ds.fname) + safeRun("mri_rpn_math -out %s '$1,dup,*,%f,dup,*,/,$2,dup,*,%f,dup,*,/,+,$3,dup,*,%f,dup,*,/,+,sqrt' tmp_x tmp_y tmp_z"%(dsname,vox[0],vox[1],vox[2])) + newDS= MRIDataset(dsname) + newChunk= newDS.getChunk('images') + return BBox(newChunk) + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 2 : + describeSelf() + sys.exit(1) + +oscript= "apply_coreg_inplane.gen_csh" +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--oscript": + oscript= b + +funcDS= MRIDataset(os.path.abspath(pargs[0])) +funcChunk= funcDS.getChunk('images') +strctDS= MRIDataset(os.path.abspath(pargs[1])) +strctChunk= strctDS.getChunk('images') + +# Move to a temporary directory +tmpdir= makeTempDir('tmp_coregister_inplane') +homedir= os.getcwd() +os.chdir(tmpdir) + +# Get relevant dimensions +xdim= funcChunk.getDim("x"); +ydim= funcChunk.getDim("y"); +zdim= funcChunk.getDim("z"); + +#Check reasonableness of input +dimstr= funcChunk.getValue('dimensions'); +if dimstr != "xyz": + if dimstr == "xyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +funcBBox= BBox(funcChunk) +strctBBox= BBox(strctChunk) +if getVerbose(): + funcBBox.printBounds("Functional bounding box:") + strctBBox.printBounds("Inplane structural bounding box:") +funcTlf= funcBBox.tlf +funcBlf= funcBBox.blf +funcTrf= funcBBox.trf +funcBrf= funcBBox.brf +funcTlb= funcBBox.tlb +funcBlb= funcBBox.blb +funcTrb= funcBBox.trb +funcBrb= funcBBox.brb +funcCtr= funcBBox.ctr +strctCtr= strctBBox.ctr +verboseMessage("Separation between centers is %f mm"%(funcCtr-strctCtr).mag()) +ctrShift= funcCtr - strctCtr +verboseMessage("Center shift: %s"%ctrShift) +#if ctrShift.mag() > 0.001: +if ctrShift.mag() > 1.0: + sys.exit("Structural and functional centers don't line up!") + +funcVox= [ funcChunk.getFloat('voxel_spacing.x'), \ + funcChunk.getFloat('voxel_spacing.y'), \ + funcChunk.getFloat('voxel_spacing.z') ]; +verboseMessage("functional voxel: "+str(funcVox)) +strctVox= [ strctChunk.getFloat('voxel_spacing.x'), \ + strctChunk.getFloat('voxel_spacing.y'), \ + strctChunk.getFloat('voxel_spacing.z') ]; +verboseMessage("structural voxel: "+str(strctVox)) +safeRun("mri_resample -d x -len %d -start 0.0 -end %f %s resampx"%\ + (funcChunk.getDim('x'),strctChunk.getDim('x')-1.0,strctChunk.ds.fname)) +safeRun("mri_resample -d y -len %d -start 0.0 -end %f resampx strctResamp"%\ + (funcChunk.getDim('y'),strctChunk.getDim('y')-1.0)) +strctResampBBox= bboxFromFilename('strctResamp') + +funcResampGrad= makeGradMag3D(funcChunk,funcVox,'funcGrad') +strctResampGrad= makeGradMag3D(strctResampBBox.chunk,funcVox,\ + 'strctResampGrad') +pad= pickMagicPadSize(funcResampGrad.chunk.getDim('z')) + +safeRun("mri_pad -d z -len %d -shift %d funcGrad funcGradPad"%\ + (zdim+pad, pad/2)) +safeRun("mri_pad -d z -len %d -shift %d strctResampGrad strctResampGradPad"%\ + (zdim+pad, pad/2)) + +funcGradMean= getMean(funcResampGrad.chunk) +strctGradMean= getMean(strctResampGrad.chunk) +safeRun("mri_rpn_math -out strctGradPadScaled '$1,%f,*' strctResampGradPad"%\ + (funcGradMean/strctGradMean)) + +verboseMessage("Beginning 3D alignment") +if getDebug(): + debugStr= '-debug' +else: + debugStr= '' +safeRun(("parallel.run.csh estireg3d -x %f -y %f -z %f -input funcGradPad "+\ + "-align strctGradPadScaled %s -alg opt=nelmin_t -p rot.par")%\ + (funcVox[0], funcVox[1], funcVox[2],debugStr)) +verboseMessage("Finished 3D alignment") + +# +# Uncomment this if you want to copy intermediate files back to +# the home directory +# +##safeRun("ireg3d -x %f -y %f -z %f -i %s -h rot1 -p rot.par"%\ +## (funcVox[0],funcVox[1],funcVox[2],funcChunk.ds.fname)) + +##safeRun("mri_resample -d x -len %d -start 0.0 -end %f rot1 fresampx"%\ +## (strctChunk.getDim('x'),funcChunk.getDim('x')-1.0)) +##safeRun("mri_resample -d y -len %d -start 0.0 -end %f fresampx funcResamp"%\ +## (strctChunk.getDim('y'),funcChunk.getDim('y')-1.0)) +##safeRun("mri_setfield -field %s.voxel_spacing -allxyz -value ' %f,%f,%f' funcResamp"%\ +## (funcChunk.name,strctVox[0],strctVox[1],strctVox[2])) +##safeRun("mri_setfield -field %s.voxel_size -allxyz -value ' %f,%f,%f' funcResamp"%\ +## (funcChunk.name,strctVox[0],strctVox[1],strctVox[2])) +##safeRun("cp *.par %s"%homedir) +##safeRun("mri_copy_dataset rot1 %s/funcAlignedInplane"%homedir) +##safeRun("mri_copy_dataset strctResamp %s/strctDownsamp"%homedir) +##safeRun("mri_copy_dataset funcResamp %s/funcResamp"%homedir) +##safeRun("mri_copy_dataset funcGradPad %s/funcGradPad"%homedir) +##safeRun("mri_copy_dataset strctResampGradPad %s/strctResampGradPad"%homedir) + +# By definition, the bounding volume of the aligned functional now +# matches that of the inplane anatomical dataset. We also want to +# think of these datasets as being in inplane coordinates, such that +# the Fiasco Z direction corresponds to the slice normal direction. +# We implement this by setting the BBoxes of the structural and +# functional appropriately, so that they will be written out +# that way when we generate the scripts. Note that we do not export +# these bounds, since we want the input files to keep their original +# corners! +strctBBox.setCorners(Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), Vec4(0.0,0.0,1.0)) + +# All done- now we write a shell script that implements this transformation. +scriptName= os.path.join(homedir,oscript); +ofile= open(scriptName,"w") +ofile.write(generatedScriptHdr) +ifile= open("rot.par","r") +parLines= ifile.readlines() +ifile.close() +for line in parLines: + ofile.write(line) + +argList= funcVox[0:3] +argList= argList + [ strctChunk.getDim('x'), funcChunk.getDim('x')-1.0,\ + strctChunk.getDim('y'), funcChunk.getDim('y')-1.0 ] +argList += strctVox[0:3] +argList += strctVox[0:3] +# Remember that these are the corners in inplane coordinates, not the +# scanner coordinate corners which actually appear in the inplane struct +# input file. +for corner in ('tlf', 'trf', 'tlb', 'trb', 'blf', 'brf', 'blb', 'brb', 'ctr'): + vtx= strctBBox.__dict__[corner] + argList= argList+[ vtx[0], vtx[1], vtx[2] ] + +ofile.write(generatedScriptBody%tuple(argList)) +ofile.close() +safeRun("chmod u+x %s"%scriptName) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/coregister_inplane_to_inplane.py =================================================================== RCS file: src/csh/coregister_inplane_to_inplane.py diff -N src/csh/coregister_inplane_to_inplane.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/coregister_inplane_to_inplane.py 2 Apr 2004 01:09:58 -0000 1.1 @@ -0,0 +1,113 @@ +#! /usr/bin/env python +# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: coregister_inplane_to_inplane.py,v 1.1 2004/04/02 01:09:58 welling Exp $" + +tol= 0.001 + +generatedScriptHdr="""\ +#!/bin/csh -ef +# +# This is an automatically generated script! It's only good +# for this particular special case. Don't copy it around or +# edit it unless you *really* know what you're doing! +# +# Inputs: +# $1: input inplane MRI file name (functional or matching anatomical) +# $2: output inplane MRI file, identical to $1 but with corners +# expressed in inplane coordinates +# +# NOTE: the input file must have consistent voxel size and +# bounds information. +# +mri_copy_dataset $1 $2 +""" + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 1 : + describeSelf() + sys.exit(1) + +oscript= "apply_coreg_inplane_to_inplane.gen_csh" +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--oscript": + oscript= b + +inplaneBBox= bboxFromFilename(pargs[0]) + +#Check reasonableness of input +dimstr= inplaneBBox.chunk.getValue('dimensions'); +if dimstr != "xyz": + if dimstr == "xyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +# Where are we? +homedir= os.getcwd() + +# All we need to do is to reset corner coordinates. +inplaneBBox.printBounds("Inplane bounding box, scanner coordinates") +inplaneBBox.setCorners(Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0)) +inplaneBBox.printBounds("Inplane bounding box, inplane coordinates") + +# Write a shell script that implements this change of coordinates +scriptName= os.path.join(homedir,oscript); +ofile= open(scriptName,"w") +ofile.write(generatedScriptHdr) +for corner in ('tlf', 'trf', 'tlb', 'trb', 'blf', 'brf', 'blb', 'brb', 'ctr'): + vtx= inplaneBBox.__dict__[corner] + ofile.write("mri_setfield -fld images.%s -all012 -value ' %f,%f,%f' $2\n"%\ + (corner,vtx[0], vtx[1], vtx[2])); +ofile.close() +safeRun("chmod u+x %s"%scriptName) + +# Clean up +# None to do for this script + Index: src/csh/coregister_struct_to_inplane.py =================================================================== RCS file: src/csh/coregister_struct_to_inplane.py diff -N src/csh/coregister_struct_to_inplane.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/coregister_struct_to_inplane.py 3 Apr 2004 00:20:24 -0000 1.4 @@ -0,0 +1,494 @@ +#! /usr/bin/env python +# +################# +# Notes- +# -Do I want to be aligning grad mags? +################# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: coregister_struct_to_inplane.py,v 1.4 2004/04/03 00:20:24 welling Exp $" + +magicSizes= [ 2, 4, 8, 16, 32, 48, 64, 96, 128, 192, 256, 320, 384 ] + +parFileFormat= """\ +##Format: order:index_t, type:raw +##Format: names:(3d_q_x,3d_q_y,3d_q_z,3d_q_w,3d_deltax,3d_deltay,3d_deltaz,mse) +# Input file: none +# Alignment file: none +# Stdv file: none +# voxel size x= %f, y= %f, z= %f +0 %f %f %f %f %f %f %f %f +""" + +generatedScriptHdr="""\ +#!/bin/csh -ef +# +# This is an automatically generated script! It's only good +# for this particular special case. Don't copy it around or +# edit it unless you *really* know what you're doing! +# +# Inputs: +# $1: input structural MRI file name +# $2: output structural MRI, translated and rotated to +# orientation of the inplane dataset, inplane coordinates +# $3: $2 resampled to match in-plane structural, inplane coordinates +# +cat > tmp_coreg_strct_to_inplane.par << EOF +""" +generatedScriptBody="""\ +EOF +ireg3d -x %f -y %f -z %f -i $1 -h $2 -p tmp_coreg_strct_to_inplane.par +mri_setfield -field images.tlf -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.trf -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.tlb -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.trb -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.blf -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.brf -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.blb -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.brb -all012 -value ' %f,%f,%f' $2 +mri_setfield -field images.ctr -all012 -value ' %f,%f,%f' $2 +mri_resample -d x -len %d -start %f -end %f $2 tmp_coreg_stoi_1 +mri_resample -d y -len %d -start %f -end %f tmp_coreg_stoi_1 tmp_coreg_stoi_2 +mri_resample -d z -len %d -start %f -end %f tmp_coreg_stoi_2 $3 +mri_setfield -field images.tlf -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.trf -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.tlb -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.trb -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.blf -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.brf -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.blb -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.brb -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.ctr -all012 -value ' %f,%f,%f' $3 +mri_setfield -field images.voxel_spacing -allxyz -value ' %f,%f,%f' $3 +mri_setfield -field images.voxel_size -allxyz -value ' %f,%f,%f' $3 +mri_destroy_dataset tmp_coreg_stoi_1 +mri_destroy_dataset tmp_coreg_stoi_2 +rm tmp_coreg_strct_to_inplane.par +""" + +def pickMagicPadSize( sz ): + for magic in magicSizes: + if magic>=sz: + return magic-sz; + +def getMean(chunk): + totDim= chunk.getDim('x')*chunk.getDim('y')*chunk.getDim('z') + safeRun("mri_copy_dataset %s tmp_mean_1"%chunk.ds.fname) + safeRun("mri_remap -order q -length %d tmp_mean_1"%totDim) + safeRun("mri_subsample -d q -length 1 -mean tmp_mean_1 tmp_mean_2") + lines= readCmdOutputToList("mri_rpn_math -out junk '0,$1,1,if_print_1' tmp_mean_2") + return float(lines[0]) + +def getMaskedMean(chunk, maskChunk): + safeRun("mri_rpn_math -out tmp_mask_1 '$1,40,<' %s"%maskChunk.ds.fname) + safeRun("mri_rpn_math -out tmp_mask_2 '0,$1,$2,if_keep' %s tmp_mask_1"%\ + chunk.ds.fname) + totDim= chunk.getDim('x')*chunk.getDim('y')*chunk.getDim('z') + safeRun("mri_remap -order q -length %d tmp_mask_1"%totDim) + safeRun("mri_remap -order q -length %d tmp_mask_2"%totDim) + safeRun("mri_subsample -d q -length 1 -sum tmp_mask_1 tmp_mask_3") + safeRun("mri_subsample -d q -length 1 -sum tmp_mask_2 tmp_mask_4") + lines= readCmdOutputToList("mri_rpn_math -out junk '0,$1,$2,/,1,if_print_1' tmp_mask_4 tmp_mask_3") + return float(lines[0]) + +def calcBBoxAxes( bbox ): + xvec= bbox.brf - bbox.blf + xvec.normalize() + yvec= bbox.blb - bbox.blf + yvec.normalize() + zvec= bbox.tlf - bbox.blf + zvec.normalize() + return (xvec, yvec, zvec) + +def checkDots(lbl,qTrans,vec,basisX,basisY,basisZ): + dots= [] + for b in (basisX, basisY, basisZ): + vDup= vec.clone() + trans_vec_mult(qTrans,vDup) + dots.append(vDup.dot(b)) + debugMessage("%s: %f %f %f "%(lbl,dots[0],dots[1],dots[2])) + +def makeAligningRotation( fromBBox, toBBox ): + fromX, fromY, fromZ = calcBBoxAxes(fromBBox) + toX, toY, toZ = calcBBoxAxes(toBBox) + axis1= fromZ.cross( toZ ) + cosTheta= fromZ.dot( toZ ) + sinTheta= axis1.mag() + axis1.normalize() + theta= atan2(sinTheta,cosTheta) + Q1= quat_from_axis_angle(None,axis1[0],axis1[1],axis1[2],theta) + Q1Trans= Transform() + quat_to_trans(Q1Trans,Q1,0.0,0.0,0.0); + rotFromX= fromX.clone() + trans_vec_mult(Q1Trans,rotFromX) + axis2= rotFromX.cross(toX) # direction same as toZ + cosPhi= rotFromX.dot(toX) + sinPhi= axis2.mag() + axis2.normalize() + phi= atan2(sinPhi,cosPhi) + Q2= quat_from_axis_angle(None,axis2[0],axis2[1],axis2[2],phi) + Q= quat_copy(None,Q1) + quat_mult_right(Q,Q2) + QTrans= Transform() + quat_to_trans(QTrans,Q,0.0,0.0,0.0) + debugMessage( "Generating aligning transformation:") + debugMessage( " fromX: %s"%fromX ) + debugMessage( " fromY: %s"%fromY ) + debugMessage( " fromZ: %s"%fromZ ) + debugMessage( " toX: %s"%toX ) + debugMessage( " toY: %s"%toY ) + debugMessage( " toZ: %s"%toZ ) + debugMessage( " theta= %f radians = %f degrees"%(theta,(180.0/pi)*theta) ) + debugMessage( " axis is %s"%axis1 ) + debugMessage( " phi= %f radians = %f degrees"%(phi,(180.0/pi)*phi) ) + if getDebug(): + identityTrans= Transform() + checkDots(" raw X",identityTrans,fromX,toX,toY,toZ) + checkDots(" aligned X",QTrans,fromX,toX,toY,toZ) + checkDots(" raw Y",identityTrans,fromY,toX,toY,toZ) + checkDots(" aligned Y",QTrans,fromY,toX,toY,toZ) + checkDots(" raw Z",identityTrans,fromZ,toX,toY,toZ) + checkDots(" aligned Z",QTrans,fromZ,toX,toY,toZ) + return Q + +############################## +# +# Main +# +############################## + + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 2 : + describeSelf() + sys.exit(1) + +oscript= "apply_coreg_struct_to_inplane.gen_csh" +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--oscript": + oscript= b + +inplaneBBox= bboxFromFilename(os.path.abspath(pargs[0])) +inplaneChunk= inplaneBBox.chunk +inplaneVox= inplaneBBox.vox +strctBBox= bboxFromFilename(os.path.abspath(pargs[1])) +strctChunk= strctBBox.chunk +strctVox= strctBBox.vox + +#Check reasonableness of input +for thisChunk in (inplaneBBox.chunk, strctBBox.chunk): + dimstr= thisChunk.getValue('dimensions'); + if dimstr != "xyz": + if dimstr == "xyzt": + if thisChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if thisChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if thisChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if thisChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +# Move to a temporary directory +tmpdir= makeTempDir('tmp_coreg_stoi') +homedir= os.getcwd() +os.chdir(tmpdir) + +inplaneBBox.printBounds("Inplane bounding box") +strctBBox.printBounds("Structural bounding box") +inplaneCtr= inplaneBBox.ctr +strctCtr= strctBBox.ctr +ctrShift= inplaneCtr - strctCtr +Message( "Center shift: %s"%ctrShift ) +Message( "Separation between centers is %f mm"%ctrShift.mag() ) + +Q1= makeAligningRotation(strctBBox, inplaneBBox) +Q1_bar= quat_copy(None,Q1) +quat_conjugate(Q1_bar) +Q1_bar_transform= Transform() +quat_to_trans(Q1_bar_transform,Q1_bar,0.0,0.0,0.0); +rotCtrShift= ctrShift.clone() +trans_vec_mult(Q1_bar_transform,rotCtrShift) +Message( "Rotated center shift: %s"%rotCtrShift ) +scaledRotCtrShift= Vec4( rotCtrShift[0]/strctVox[0], \ + rotCtrShift[1]/strctVox[1], \ + rotCtrShift[2]/strctVox[2] ) +verboseMessage("Rotated center shift in structural voxels: %s"%scaledRotCtrShift) + +Message("Geometrical transformation to bring structurals into inplane space:") +Message("Quaternion 1: %s"%Q1) +Message("Translation 1 (unscaled): %s"%rotCtrShift) +Message("Translation 1 (scaled): %s"%scaledRotCtrShift) + +safeRun("mri_copy_dataset %s strctDup"%strctBBox.chunk.ds.fname) +safeRun("mri_copy_dataset %s inplaneDup"%inplaneBBox.chunk.ds.fname) +safeRun("mri_remap -order xyzt strctDup") +f= open("rot1.par","w") +f.write("# Estimate for rot to bring structurals to inplane alignment\n") +f.write("0 %f %f %f %f %f %f %f 1.0\n"%\ + (Q1_bar.x,Q1_bar.y,Q1_bar.z,Q1_bar.w,\ + -scaledRotCtrShift[0],-scaledRotCtrShift[1],-scaledRotCtrShift[2])) +f.close() +safeRun("ireg3d -x %f -y %f -z %f -i strctDup -h rot1 -p rot1.par -real"%\ + (strctVox[0],strctVox[1],strctVox[2])) + +rot1BBox= bboxFromFilename("rot1") +rot1BBox.setCtr( inplaneCtr ) +rot1BBox.setVox(strctVox) +rot1BBox.setCorners( Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), Vec4(0.0,0.0,1.0) ) +rot1BBox.printBounds("Bounds for rotated structurals,inplane coordinates") +rot1BBox.exportBounds() +rot1Chunk= rot1BBox.chunk + +inplaneDupBBox= bboxFromFilename("inplaneDup") +inplaneDupBBox.setCtr(inplaneCtr) +inplaneDupBBox.setVox(inplaneVox) +inplaneDupBBox.setCorners( Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0)) +inplaneDupBBox.printBounds("Bounds for inplanes, inplane coordinates") +inplaneDupBBox.exportBounds() + +rot1Tlf= rot1BBox.tlf +rot1Blf= rot1BBox.blf +rot1Trf= rot1BBox.trf +rot1Brf= rot1BBox.brf +rot1Tlb= rot1BBox.tlb +rot1Blb= rot1BBox.blb +rot1Trb= rot1BBox.trb +rot1Brb= rot1BBox.brb +rot1Ctr= copy.copy(inplaneCtr) +rot1Vox= rot1BBox.vox + +# +# rot1 gives us the transformation to bring the structurals to the +# inplane coordinates, as calculated directly from the scanner data. +# We now estimate an additional small rotation and shift to bring +# the rot1 data to the structural data, to account for head motion +# between the two scans. +# +# We must pick a target size in Z which is good for FFTs and larger +# than the number of actual slices in the inplane dataset. +# + +zPad= pickMagicPadSize(inplaneBBox.zdim+1)+1 + +# +# Start by downsampling the inplanes in x and y, and downsampling the +# rotated structurals in z, so that everyone has the same (maximum) +# voxel size and the corresponding bounding box. +# + +xStart= (rot1Tlf[0]-rot1Ctr[0])/inplaneVox[0] + (inplaneChunk.getDim('x')/2); +xEnd= (rot1Trf[0]-rot1Ctr[0])/inplaneVox[0] + (inplaneChunk.getDim('x')/2); +safeRun("mri_resample -d x -len %d -start %f -end %f %s inplResampX"%\ + (rot1BBox.chunk.getDim('x'), xStart, xEnd, inplaneChunk.ds.fname)) + +yStart= (rot1Tlf[1]-rot1Ctr[1])/inplaneVox[1] + (inplaneChunk.getDim('y')/2); +yEnd= (rot1Tlb[1]-rot1Ctr[1])/inplaneVox[1] + (inplaneChunk.getDim('y')/2); +safeRun("mri_resample -d y -len %d -start %f -end %f inplResampX inplResampXY"%\ + (rot1BBox.chunk.getDim('y'), yStart, yEnd)) + +safeRun("mri_pad -d z -len %d -shift %d inplResampXY inplResampXYZ"%\ + (inplaneBBox.zdim+zPad, (zPad+1)/2)) + +inplResampVox= [ strctVox[0], strctVox[1], inplaneVox[2] ] + +inplResampXYZBBox= bboxFromFilename('inplResampXYZ') +inplResampXYZBBox.setCtr( inplaneCtr ) +inplResampXYZBBox.setVox( inplResampVox ) +inplResampXYZBBox.setCorners( Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0) ) +inplResampXYZBBox.printBounds("Bounds for resampled inplanes,inplane coordinates") +inplResampXYZBBox.exportBounds() + +inplaneTlf= inplResampXYZBBox.tlf +inplaneBlf= inplResampXYZBBox.blf +inplaneTrf= inplResampXYZBBox.trf +inplaneBrf= inplResampXYZBBox.brf +inplaneTlb= inplResampXYZBBox.tlb +inplaneBlb= inplResampXYZBBox.blb +inplaneTrb= inplResampXYZBBox.trb +inplaneBrb= inplResampXYZBBox.brb + +zStart= ((inplaneBlf[2]-inplaneCtr[2])/rot1Vox[2]) + (rot1Chunk.getDim('z')/2); +zEnd= ((inplaneTlf[2]-inplaneCtr[2])/rot1Vox[2]) + (rot1Chunk.getDim('z')/2); +safeRun("mri_resample -d z -len %d -start %f -end %f %s rot1ResampZ"%\ + (inplResampXYZBBox.chunk.getDim('z'), zStart, zEnd, \ + rot1Chunk.ds.fname)) + +rot1ResampZBBox= bboxFromFilename('rot1ResampZ') +rot1ResampZBBox.setCtr( inplaneCtr ) +rot1ResampZBBox.setVox( inplResampVox ) +rot1ResampZBBox.setCorners( Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0) ) +rot1ResampZBBox.printBounds("Bounds for resampled structurals,inplane coordinates") +rot1ResampZBBox.exportBounds() + +inplResampXYZMean= getMaskedMean(inplResampXYZBBox.chunk,\ + inplResampXYZBBox.chunk) +rot1ResampZMean= getMaskedMean(rot1ResampZBBox.chunk,inplResampXYZBBox.chunk) +safeRun("mri_rpn_math -out alignto '$1,%f,*' inplResampXYZ"%\ + (rot1ResampZMean/inplResampXYZMean)) + +flags= "" +if getDebug(): + flags= flags+"-debug" +verboseMessage("Beginning 3D alignment") +safeRun("parallel.run.csh estireg3d %s -x %f -y %f -z %f -input rot1ResampZ -align alignto -p rot2.par"%\ + (flags, inplResampVox[0], inplResampVox[1], inplResampVox[2])) +verboseMessage("Finished 3D alignment") + +ifile= open("rot2.par","r") +parLines= ifile.readlines() +ifile.close() +for line in parLines: + if line[0] != '#': + vals= map(float,string.split(line)) + break + +Q2_bar= Quat(vals[1],vals[2],vals[3],vals[4]) +Q2= quat_copy(None,Q2_bar) +quat_conjugate(Q2) +rawShift2= Vec4(-vals[5],-vals[6],-vals[7]) +unscaledShift2= Vec4(rawShift2[0]*inplResampVox[0],\ + rawShift2[1]*inplResampVox[1],\ + rawShift2[2]*inplResampVox[2]); +rescaledShift2= Vec4(unscaledShift2[0]/strctVox[0], + unscaledShift2[1]/strctVox[1], + unscaledShift2[2]/strctVox[2]); + +Message("Geometrical transformation for structural/inplane relative motion:") +Message("Quaternion 2: %s"%Q2) +Message("Translation 2 (unscaled): %s"%unscaledShift2) +Message("Translation 2 (scaled): %s"%rescaledShift2) + +# +# Merge first and second transformations. We are calculating: +# Tnet Rnet = T2 R2 T1 R1 = T2 ( R2 T1 R2' ) R2 R1 +# where ' means inverse. We'll use quaternion algebra. +# +t1Quat= quat_identity(None) +t1Quat.x= rotCtrShift[0] +t1Quat.y= rotCtrShift[1] +t1Quat.z= rotCtrShift[2] +t1Quat.w= 0.0 +quat_mult_right(t1Quat,Q2_bar) +quat_mult_left(Q2,t1Quat) +rotatedT1= Vec4(t1Quat.x,t1Quat.y,t1Quat.z) +netTrans= unscaledShift2 + rotatedT1 +Message("unscaled net translation: %s"%netTrans) +rescaledNetTrans= Vec4(netTrans[0]/strctVox[0], \ + netTrans[1]/strctVox[1], \ + netTrans[2]/strctVox[2]) +netQ= quat_copy(None,Q2) +quat_mult_right(netQ,Q1) +netQ_bar= quat_copy(None,netQ) +quat_conjugate(netQ_bar) +Message("Net transformation to align structural to inplane:") +Message("Net Quaternion: %s"%netQ) +Message("Net Translation (unscaled): %s"%netTrans) +Message("Net Translation (scaled): %s"%rescaledNetTrans) + +# Generate a parameter file for the net rotation +f= open("netRot.par","w") +f.write(parFileFormat%( strctVox[0], strctVox[1], strctVox[2], \ + netQ_bar.x, netQ_bar.y, netQ_bar.z, netQ_bar.w, \ + -rescaledNetTrans[0], -rescaledNetTrans[1], \ + -rescaledNetTrans[2], 1.0 )) +f.close() +safeRun("ireg3d -x %f -y %f -z %f -i strctDup -h alignedStruct -p netRot.par -real"%\ + (strctVox[0],strctVox[1],strctVox[2])) +alignedStrctBBox= bboxFromFilename('alignedStruct') +alignedStrctBBox.setCtr( inplaneCtr ) +alignedStrctBBox.setCorners( Vec4(1.0,0.0,0.0), Vec4(0.0,1.0,0.0), \ + Vec4(0.0,0.0,1.0) ) +alignedStrctBBox.printBounds("Bounds for aligned structurals,inplane coordinates") +alignedStrctBBox.exportBounds() + +# All done- now we write a shell script that implements this transformation. +# This block consists mainly of filling out the blanks in the generated +# script. +scriptName= os.path.join(homedir,oscript); +ofile= open(scriptName,"w") +ofile.write(generatedScriptHdr) +ifile= open("netRot.par","r") +parLines= ifile.readlines() +ifile.close() +for line in parLines: + ofile.write(line) +argList= strctVox[0:3] +for corner in ('tlf', 'trf', 'tlb', 'trb', 'blf', 'brf', 'blb', 'brb', 'ctr'): + vtx= alignedStrctBBox.__dict__[corner] + argList= argList+[ vtx[0], vtx[1], vtx[2] ] + +xStart= (inplaneDupBBox.tlf[0]-inplaneDupBBox.ctr[0])/strctVox[0] \ + + (alignedStrctBBox.chunk.getDim('x')/2); +xEnd= (inplaneDupBBox.trf[0]-inplaneDupBBox.ctr[0])/strctVox[0] \ + + (alignedStrctBBox.chunk.getDim('x')/2); +argList= argList+ [ inplaneDupBBox.chunk.getDim('x'), xStart, xEnd ] + +yStart= (inplaneDupBBox.tlf[1]-inplaneDupBBox.ctr[1])/strctVox[1] \ + + (alignedStrctBBox.chunk.getDim('y')/2); +yEnd= (inplaneDupBBox.tlb[1]-inplaneDupBBox.ctr[1])/strctVox[1] \ + + (alignedStrctBBox.chunk.getDim('y')/2); +argList= argList+ [ inplaneDupBBox.chunk.getDim('y'), yStart, yEnd ] + +zStart= (inplaneDupBBox.blf[2]-inplaneDupBBox.ctr[2])/strctVox[2] \ + + (alignedStrctBBox.chunk.getDim('z')/2); +zEnd= (inplaneDupBBox.tlf[2]-inplaneDupBBox.ctr[2])/strctVox[2] \ + + (alignedStrctBBox.chunk.getDim('z')/2); +argList= argList+ [ inplaneDupBBox.chunk.getDim('z'), zStart, zEnd ] + +for corner in ('tlf', 'trf', 'tlb', 'trb', 'blf', 'brf', 'blb', 'brb', 'ctr'): + vtx= alignedStrctBBox.__dict__[corner] + argList= argList+[ vtx[0], vtx[1], vtx[2] ] + +argList= argList+inplaneVox[0:3] +argList= argList+inplaneVox[0:3] +ofile.write(generatedScriptBody%tuple(argList)) +ofile.close() +safeRun("chmod u+x %s"%scriptName) + +#safeRun("cp *.par %s"%homedir) +#safeRun("mri_copy_dataset rot1 %s/rot1"%homedir) +#safeRun("mri_copy_dataset alignto %s/alignto"%homedir) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/coregistration.csh =================================================================== RCS file: src/csh/coregistration.csh diff -N src/csh/coregistration.csh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/coregistration.csh 31 Mar 2004 06:18:00 -0000 1.2 @@ -0,0 +1,126 @@ +#!/bin/csh -efx +# coregistration.csh +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1995 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# * Original programming by Bill Eddy * +# ************************************************************/ +# +echo '#'`date` $0 +echo '#$Id: coregistration.csh,v 1.2 2004/03/31 06:18:00 welling Exp $' + +# Do we have the necessary info +if ( ! ${?F_CRG_INPL_INPUT} ) then + echo "No coregistration inplane input specified; skipping coregistration" + exit +endif +if ( "dummy"${F_CRG_INPL_INPUT} == "dummy" ) then + echo "No coregistration inplane input specified; skipping coregistration" + exit +endif + +if ( ! ${?F_CRG_ANAT_INPUT} ) then + echo "No coregistration anatomy input specified; skipping coregistration" + exit +endif + +if ( "dummy"${F_CRG_ANAT_INPUT} == "dummy" ) then + echo "No coregistration anatomy input specified; skipping coregistration" + exit +endif + +if ( ! ${?F_CRG_FUNC} ) then + echo "No coregistration functional dataset specified; skipping coregistration" + exit +endif + +if ( "dummy"${F_CRG_FUNC} == "dummy" ) then + echo "No coregistration functional dataset specified; skipping coregistration" + exit +endif + +# Check needed dirs +if ( ! -d anat) mkdir anat +if ( ! -d coregistered_anat) mkdir coregistered_anat +if ( ! -d coregistered_func) mkdir coregistered_func +if ( ! -d generated_scripts) mkdir generated_scripts + +# Generate the inplane and axial anatomical datasets +smartreader $F_CRG_ANAT_OPTS -input $F_CRG_ANAT_INPUT \ + -out anat/$F_CRG_ANAT -verbose +smartreader $F_CRG_INPL_OPTS -input $F_CRG_INPL_INPUT \ + -out anat/$F_CRG_INPL -verbose + +# There is a problem with some inplane anatomicals acquired before +# about 11/02 in which the slice planes are skewed. This can cause +# smartreader to fail to identify the set of slices as a volume, and +# hence to fail to calculate volume corners appropriately. We patch +# over this by copying in volume corners from the (theoretically +# identical) functional bounding volume if necessary. +set has_corners = 0 +foreach cnr ( "tlf" "trf" "tlb" "trb" "blf" "brf" "blb" "brb" ) + set fld = `mri_printfield -fld "images."$cnr".0" -nofail anat/$F_CRG_INPL` + if ( junk$fld != junk ) then + set has_corners = 1 + break + endif +end +if ( ! $has_corners ) then + foreach cnr ( "tlf" "trf" "tlb" "trb" "blf" "brf" "blb" "brb" ) + set fld1 = `mri_printfield -fld "images."$cnr".0" -nofail $F_CRG_FUNC` + set fld2 = `mri_printfield -fld "images."$cnr".1" -nofail $F_CRG_FUNC` + set fld3 = `mri_printfield -fld "images."$cnr".2" -nofail $F_CRG_FUNC` + if ( junk$fld1 != junk && junk$fld2 != junk && junk$fld3 != junk ) then + mri_setfield -all012 -fld "images."$cnr \ + -value '" '$fld1':'$fld2':'$fld3'"' anat/$F_CRG_INPL + endif + end +endif + +# Strip the skulls from the anatomical data +strip_skull.py -v anat/$F_CRG_ANAT anat/$F_CRG_ANAT_STRIPPED +strip_skull.py -v anat/$F_CRG_INPL anat/$F_CRG_INPL_STRIPPED + +# Coregister +coregister.py -v $F_CRG_FUNC anat/$F_CRG_INPL_STRIPPED \ + anat/$F_CRG_ANAT_STRIPPED +mv apply_coreg*.gen_csh generated_scripts +mv apply_cowarp*.gen_csh generated_scripts + +# Make the coregistered anatomical for normalization +generated_scripts/apply_coreg_struct_to_inplane.gen_csh \ + anat/$F_CRG_ANAT coreg_tmp1 coreg_tmp2 +generated_scripts/apply_cowarp_inplane.gen_csh coreg_tmp1 \ + coregistered_anat/$F_CRG_ANAT_COWARPED +generated_scripts/apply_cowarp_inplane.gen_csh coreg_tmp2 \ + coregistered_anat/$F_CRG_ANAT_INPL +mri_destroy_dataset coreg_tmp1 +mri_destroy_dataset coreg_tmp2 + +# Make the coregistered functional prototype +generated_scripts/apply_coreg_inplane.gen_csh $F_CRG_FUNC \ + coregistered_func/$F_CRG_FUNC_COREG coreg_tmp3 +mri_destroy_dataset coreg_tmp3 + + Index: src/csh/cowarp_inplane.py =================================================================== RCS file: src/csh/cowarp_inplane.py diff -N src/csh/cowarp_inplane.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/cowarp_inplane.py 31 Mar 2004 06:17:08 -0000 1.2 @@ -0,0 +1,198 @@ +#! /usr/bin/env python +# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: cowarp_inplane.py,v 1.2 2004/03/31 06:17:08 welling Exp $" + +tol= 0.001 + +generatedScriptHdr="""\ +#!/bin/csh -ef +# +# This is an automatically generated script! It's only good +# for this particular special case. Don't copy it around or +# edit it unless you *really* know what you're doing! +# +# Inputs: +# $1: input structural MRI file name +# $2: output structural MRI, warped to match shape and +# location of functionals +# +# NOTE: the input file must have consistent voxel size and +# bounds information. +# +cat > tmp_cowarp_inpl.par << EOF +""" +generatedScriptBody="""\ +EOF +set xvox = `mri_printfield -fld images.voxel_spacing.x $1` +set yvox = `mri_printfield -fld images.voxel_spacing.y $1` +set zvox = `mri_printfield -fld images.voxel_spacing.z $1` +iwarp -x $xvox -y $yvox -z $zvox -i $1 -h $2 -p tmp_cowarp_inpl.par +rm tmp_cowarp_inpl.par +""" + +def pickMagicPadSize( sz ): + for magic in magicSizes: + if magic>=sz: + return magic-sz; + +def getMean(chunk): + totDim= chunk.getDim('x')*chunk.getDim('y')*chunk.getDim('z') + safeRun("mri_copy_dataset %s tmp_mean_1"%chunk.ds.fname) + safeRun("mri_remap -order q -length %d tmp_mean_1"%totDim) + safeRun("mri_subsample -d q -length 1 -mean tmp_mean_1 tmp_mean_2") + lines= readCmdOutputToList("mri_rpn_math -out junk '0,$1,1,if_print_1' tmp_mean_2") + return float(lines[0]) + +def makeGradMag3D(ch,vox,dsname): + safeRun("mri_smooth -d x -smoother_type ddx %s tmp_x"%ch.ds.fname) + safeRun("mri_smooth -d y -smoother_type ddx %s tmp_y"%ch.ds.fname) + safeRun("mri_smooth -d z -smoother_type ddx %s tmp_z"%ch.ds.fname) + safeRun("mri_rpn_math -out %s '$1,dup,*,%f,dup,*,/,$2,dup,*,%f,dup,*,/,+,$3,dup,*,%f,dup,*,/,+,sqrt' tmp_x tmp_y tmp_z"%(dsname,vox[0],vox[1],vox[2])) + newDS= MRIDataset(dsname) + newChunk= newDS.getChunk('images') + return BBox(newChunk) + +def checkBBoxCornersMatch( bbox1, bbox2 ): + for corner in ["tlf","blf","trf","brf","tlb","blb","trb","brb"]: + if bbox1.__dict__.has_key(corner) and bbox2.__dict__.has_key(corner): + loc1= bbox1.__dict__[corner] + loc2= bbox1.__dict__[corner] + if (loc1-loc2).mag() > tol: + sys.exit("Bounding boxes don't align at corner %s!"%corner) + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 2 : + describeSelf() + sys.exit(1) + +oscript= "apply_cowarp_inplane.gen_csh" +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--oscript": + oscript= b + +funcDS= MRIDataset(os.path.abspath(pargs[0])) +funcChunk= funcDS.getChunk('images') +strctDS= MRIDataset(os.path.abspath(pargs[1])) +strctChunk= strctDS.getChunk('images') + +# Move to a temporary directory +tmpdir= makeTempDir('tmp_cowarp_inplane') +homedir= os.getcwd() +os.chdir(tmpdir) + +# Get relevant dimensions +xdim= funcChunk.getDim("x"); +ydim= funcChunk.getDim("y"); +zdim= funcChunk.getDim("z"); + +#Check reasonableness of input +dimstr= funcChunk.getValue('dimensions'); +if dimstr != "xyz": + if dimstr == "xyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if funcChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if funcChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +funcBBox= BBox(funcChunk) +strctBBox= BBox(strctChunk) +if getVerbose(): + funcBBox.printBounds("Aligned functional bounding box:") + strctBBox.printBounds("Inplane structural bounding box:") +checkBBoxCornersMatch(funcBBox,strctBBox) + +funcVox= [ funcChunk.getFloat('voxel_spacing.x'), \ + funcChunk.getFloat('voxel_spacing.y'), \ + funcChunk.getFloat('voxel_spacing.z') ]; +verboseMessage("functional voxel: "+str(funcVox)) +strctVox= [ strctChunk.getFloat('voxel_spacing.x'), \ + strctChunk.getFloat('voxel_spacing.y'), \ + strctChunk.getFloat('voxel_spacing.z') ]; +verboseMessage("structural voxel: "+str(strctVox)) +for i in range(0,3): + if abs(funcVox[i]-strctVox[i]) > tol: + sys.exit("Structural and functional voxel sizes do not match!") + +verboseMessage("Producing grad magnitudes") +funcGrad= makeGradMag3D(funcBBox.chunk,funcVox,'funcGrad') +strctGrad= makeGradMag3D(strctBBox.chunk,funcVox,'strctGrad') +funcGradMean= getMean(funcGrad.chunk) +strctGradMean= getMean(strctGrad.chunk) +safeRun("mri_rpn_math -out strctGradScaled '$1,%f,*' strctGrad"%\ + (funcGradMean/strctGradMean)) +safeRun("mri_remap -order xyzt strctGradScaled") + +verboseMessage("Beginning co-warp") +flags= '' +if getVerbose(): + flags= flags+'-v ' +if getDebug(): + flags= flags+'-debug' +safeRun(("parallel.run.csh estiwarp -x %f -y %f -z %f -input strctGradScaled " +\ + "-align funcGrad -alg inplane,opt=praxis -p warp.par %s")%\ + (funcVox[0],funcVox[1],funcVox[2],flags)) + +# All done- now we write a shell script that implements this transformation. +scriptName= os.path.join(homedir,oscript); +ofile= open(scriptName,"w") +ofile.write(generatedScriptHdr) +ifile= open("warp.par","r") +parLines= ifile.readlines() +ifile.close() +for line in parLines: + ofile.write(line) +ofile.write(generatedScriptBody) +ofile.close() +safeRun("chmod u+x %s"%scriptName) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/customize_local.py =================================================================== RCS file: src/csh/customize_local.py diff -N src/csh/customize_local.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/customize_local.py 27 Mar 2004 01:34:45 -0000 1.3 @@ -0,0 +1,442 @@ +#! /usr/bin/env python +# + +# +# The purpose of this script is to provide a level of indirection +# between session, group, and study names and the directory structure in +# which they are stored. +# + +import sys +import os +import os.path +import string +import getopt +import urllib +import re +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: customize_local.py,v 1.3 2004/03/27 01:34:45 welling Exp $" + +transDict= {} +dbDict= {} +pfileRegex= re.compile('P(\d+)\.(\d)') +geLxImageRegex= re.compile('I\.\d\d\d') +srcDir= None + +def termsFromUrl( dict, url ): + global transDict + debugMessage("Reading URL <%s>"%url) + f= urllib.urlopen(url); + urlLines= f.readlines(); + f.close() + in_row_flag= 0 + for line in urlLines: + if string.find(line,'ERROR:') >= 0: + Message("SQL database query failed: %s"%\ + line[string.find(line,':')+1:]) + break + if in_row_flag: + if string.find(line,'%%%END') >= 0: + break; + else: + (key,val)= string.split(string.strip(line),':',1) + debugMessage("Adding <%s>=><%s>"%(key,val)) + dict[key]= val + else: + if string.find(line,'%%%START') >= 0: + in_row_flag= 1 + +def fillDbDict( dict ): + global transDict + idUrl= "http://www.stat.cmu.edu/~welling/do_query_textonly.php?db_uname=%s&db_passwd=%s&db_table=CS_ID&subj_id=%s"%\ + (transDict["db_uname"],transDict["db_passwd"],transDict["subj"]) + scanUrl= "http://www.stat.cmu.edu/~welling/do_query_textonly.php?db_table=CS_SCANDATA&subj_id=%s&run=%s&db_uname=%s&db_passwd=%s"%\ + (transDict["subj"],transDict["runnum"],\ + transDict["db_uname"],transDict["db_passwd"]) + termsFromUrl( dict, idUrl ) + termsFromUrl( dict, scanUrl ) + +############################## +# +# Translation Methods +# +############################## + +def countImageFiles( dirName ): + count= 0 + for fname in os.listdir(dirName): + if geLxImageRegex.match(fname): + count= count+1 + print "count is %d for <%s>"%(count,dirName) + return count + +def dirMethod( line ): + return "/home/YODA/roushre/DATA/Pfiles/%02d/%s_%s"%\ + (int(transDict['subj']),transDict['task'],transDict['runnum']) +# return readCmdOutputToList("map_name.py -d file=pfiles -d task=%s -d runnum=%s %s"%\ +# (transDict["task"],transDict["runnum"],\ +# transDict["subj"]))[0] + +def inplInputMethod( line ): + global transDict, dbDict + dirBase= "/home/YODA/roushre/DATA/Pfiles/%02d/struct_%s/"%\ + (int(transDict['subj']),transDict['runnum']) + for dirnum in range(1,20): + dirPath= os.path.join(dirBase,"%03d"%dirnum) + if os.access(dirPath,os.R_OK): + count= countImageFiles(dirPath) + if count==int(dbDict['SLICE']): + return "'%s'"%os.path.join(dirPath,'I.###') + raise Exception("No suitable inplane image set in %s"%dirBase) + +def inplOptsMethod( line ): + global transDict, dbDict + return "'-multi'" + +def anatInputMethod( line ): + global transDict, dbDict + dirBase= "/home/YODA/roushre/DATA/Pfiles/%02d/struct_%s/"%\ + (int(transDict['subj']),transDict['runnum']) + for dirnum in range(1,20): + dirPath= os.path.join(dirBase,"%03d"%dirnum) + if os.access(dirPath,os.R_OK): + count= countImageFiles(dirPath) + if count>100 and count<150: + return "'%s'"%os.path.join(dirPath,'I.###') + raise Exception("No suitable anat image set in %s"%dirBase) + +def anatOptsMethod( line ): + global transDict, dbDict + return "'-multi'" + +def refpMethod( line ): + global transDict, dbDict + pfileDir= dirMethod(line) + vList= [] + for f in os.listdir(pfileDir): + m= pfileRegex.match(f) + if m: + suffix= m.group(2) # they had better all be the same! + vList.append(int(m.group(1))) + vList.sort() + oldV= vList[0] + firstV= vList[0] + deltaList= [ firstV ] + for v in vList[1:]: + deltaList.append(v-oldV) + oldV= v + deltaList.sort() + biggestDelta= deltaList[-1] + if biggestDelta==firstV: + return "P%05d.%s"%(firstV,suffix) + else: + oldV= firstV + for v in vList[1:]: + if v-oldV == biggestDelta: + return "P%05d.%s"%(v,suffix) + oldV= v + +def splitMethod( ofile, line ): + global transDict, dbDict + ofile.write("1 bynumimages\n") + ofile.write("Condition\n") + ofile.write("0Back 0\n") + ofile.write("1Back 0\n") + ofile.write("2Back 0\n") + first= 1 + for c in dbDict['NBACK']: + if first: + first= 0 +# ofile.write("%dBack 2\n"%int(c)) +# ofile.write("NA 33\n") + ofile.write("%dBack 35\n"%int(c)) + else: + ofile.write("NA 1\n") + ofile.write("%dBack 34\n"%int(c)) + +def headerMethod( line ): + global transDict, dbDict + result= "'subj %s %s %s"%(transDict["subj"],transDict["task"],\ + transDict["runnum"]) + if transDict.has_key('tag'): + result= "%s %s'"%(result,transDict['tag']) + else: + result= "%s'"%(result) + return result + +def genderMethod( line ): + global transDict, dbDict + if int(dbDict['GENDER'])==1: + return "F" + else: + return "M" + +def diag1Method( line ): + global transDict, dbDict + if dbDict['PT']==2: + return "none" + else: + return "concussion" + +def ageMethod( line ): + global transDict, dbDict + if dbDict.has_key('SDATE') and dbDict.has_key('DOB'): + birthDate= string.strip(dbDict['DOB']) + if len(birthDate)==0: + return '' + scanDate= string.strip(dbDict['SDATE']) + if len(scanDate)==0: + return '' + yBirth,mBirth,dBirth= map(int,string.split(dbDict['DOB'],'-')) + yScan,mScan,dScan= map(int,string.split(dbDict['SDATE'],'-')) + age= yScan-yBirth + if mBirth < mScan or ( mBirth == mScan and dBirth <= dScan ): + age= age+1 + return str(age) + else: + return '' + +def descriptionMethod( line ): + global transDict, dbDict + tmpAge= ageMethod( line ) + if len(tmpAge)<1: + tmpAge= '??' + return "'%s age %s, %s"%(genderMethod(line),tmpAge,headerMethod(line)[1:]) + +def nsliceMethod( line ): + global transDict, dbDict + try: + return int( dbDict['SLICE']) + except: + sys.exit("Could not parse SLICE database entry!") + +def nimageMethod( line ): + global transDict, dbDict + return 35*len(dbDict['NBACK']) + +def iaiMethod( line ): + global transDict, dbDict + return '1.5' + +def xvoxelMethod( line ): + global transDict, dbDict + return '3.125' + +def yvoxelMethod( line ): + global transDict, dbDict + return '3.125' + +def zvoxelMethod( line ): + global transDict, dbDict + return '3.2' + +def estiregfixedMethod( line ): + global transDict, dbDict + return 'median' + +def est3dalignMethod( line ): + global transDict, dbDict + return 'median' + +def lowertMethod( line ): + global transDict, dbDict + return '-6' + +def uppertMethod( line ): + global transDict, dbDict + return '6' + +def upperfMethod( line ): + global transDict, dbDict + return '36' + +def lowerqMethod( line ): + global transDict, dbDict + return '0.00625' + +def tmpdirMethod( line ): + global transDict, dbDict + return "/home/YODA/%s/tmp"%os.environ['LOGNAME'] + +def checkInitialDefs( dict ): + errStr= "" + errFlag= 0 + if not dict.has_key('subj'): + errFlag= 1 + errStr= errStr + " subj=subjectID (int)" + if not dict.has_key('task'): + errFlag= 1 + errStr= errStr + " task=taskname (string)" + if not dict.has_key('runnum'): + errFlag= 1 + errStr= errStr + " runnum=N (int)" + if not dict.has_key('tag'): + errFlag= 1 + errStr= errStr + " tag=tagString (string)" + if not dict.has_key('db_uname'): + errFlag= 1 + errStr= errStr + " db_uname=databaseUsername (string)" + if not dict.has_key('db_passwd'): + errFlag= 1 + errStr= errStr + " db_passwd=databasePassword (string)" + if errFlag: + Message("The following required key-value pairs are missing:") + Message(errStr) + sys.exit("Not enough initial information given!") + +############################## +# +# Translation Tables +# +############################## + +envDict= {"F_HEADER":headerMethod, "F_DIR":dirMethod, "F_REFP":refpMethod, + "F_DESCRIPTION":descriptionMethod, 'F_SUBJ_SEX':genderMethod, + 'F_SUBJ_1DIAG':diag1Method, 'F_SUBJ_AGE':ageMethod, + 'F_XVOXEL':xvoxelMethod, 'F_YVOXEL':yvoxelMethod, + 'F_ZVOXEL':zvoxelMethod, 'F_NSLICE':nsliceMethod, + 'F_IAI':iaiMethod, 'F_ESTIREG_FIXED':estiregfixedMethod, + 'F_LOWERT':lowertMethod, 'F_UPPERT':uppertMethod, + 'F_UPPERF':upperfMethod, 'F_LOWERQ':lowerqMethod, + 'F_NIMAGE':nimageMethod, 'F_TEMP':tmpdirMethod, + 'F_EST3D_ALIGN':est3dalignMethod, + 'F_CRG_INPL_INPUT':inplInputMethod, 'F_CRG_INPL_OPTS':inplOptsMethod, + 'F_CRG_ANAT_INPUT':anatInputMethod, 'F_CRG_ANAT_OPTS':anatOptsMethod, + } + +catDict= {"$F_SPLIT_FILE":splitMethod} + + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ) + else: + os.system( "scripthelp %s"%sys.argv[0] ) + sys.exit() + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["src="]) +except: + errorMessage("%s: Invalid command line parameter" % sys.argv[0]) + describeSelf() + sys.exit(1) + +verboseMessage(idString) + +# Parse args +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--src": + srcDir= b + +outName= None +for arg in pargs: + if string.find(arg,"=") >= 0: + (key,val) = map(string.strip,string.split(arg,"=")) + transDict[key]= val + else: + if outName == None: + outName= arg + else: + sys.exit("%s: command line contains repeated output filenames" + %sys.argv[0]) + +if outName==None: + sys.exit("%s: name of file to customize was not given!"%sys.argv[0]) + +# Check environment for database password if it's not already set +if not transDict.has_key('db_passwd'): + if os.environ.has_key('F_DB_PASSWD'): + transDict['db_passwd']= os.environ['F_DB_PASSWD'] + +# Do I have the initial definitions I need? +checkInitialDefs(transDict) + +if srcDir==None: + if not os.environ.has_key('FIASCO'): + sys.exit("No source directory given and FIASCO environment variable is not set!") + srcDir= os.environ['FIASCO'] + +inName= os.path.join(srcDir,outName); + +debugMessage("Translating %s to %s"%(inName,outName)) +if not os.path.isfile(inName): + sys.exit("%s does not exist!"%inName) + +f= file(inName) +canExecute= os.access(inName,os.X_OK) +inLines= f.readlines() +f.close() + +fillDbDict( dbDict ) +if not dbDict.has_key("GENDER"): + sys.exit("No subject id %s found in database!"%transDict["subj"]) +if not dbDict.has_key("SDATE"): + sys.exit("No scan %s for subject id %s found in database!"%\ + (transDict["runnum"],transDict["subj"])) +if dbDict.has_key('NBACK'): + pattern= dbDict['NBACK'] + if len(pattern)==1: + tmpDict= {} + url= "http://www.stat.cmu.edu/~welling/do_query_textonly.php?db_uname=%s&db_passwd=%s&db_table=LU_NBKORDER&letter=%s"%\ + (transDict["db_uname"],transDict["db_passwd"],pattern) + termsFromUrl( tmpDict, url ) + pattern= tmpDict['ORDER'] + dbDict['NBACK']= string.replace(pattern, ' ', '') +ofile= file(outName,"w") +skipMode= 0 +skipEnd= None +for line in inLines: + trimmedLine= string.strip(line) + if skipMode: + if trimmedLine[0:len(skipEnd)]==skipEnd: + ofile.write(line) + skipMode= 0 + else: + continue + elif len(trimmedLine)==0: + ofile.write(line) + elif trimmedLine[0]=='#': + ofile.write(line) + else: + words= string.split(trimmedLine) + if words[0]=='setenv': + debugMessage("found setenv of <%s>"%words[1]) + if envDict.has_key(words[1]): + debugMessage("found translation method for setenv <%s>"%words[1]) + ofile.write("setenv %s %s\n"%\ + (words[1], envDict[words[1]](trimmedLine))) + else: + ofile.write(line) + elif words[0]=='cat' and words[1]=='>' and words[3]=='<<': + if catDict.has_key(words[2]): + ofile.write(line) + catDict[words[2]](ofile,line) + skipMode= 1 + skipEnd= words[4] + else: + ofile.write(line) + else: + ofile.write(line) + +ofile.close() + +if canExecute: + verboseMessage("Making %s executable by anyone!"%outName) + safeRun("chmod +x %s"%outName) + + Index: src/csh/do_by_blocks.py =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/do_by_blocks.py,v retrieving revision 1.1 retrieving revision 1.4 diff -a -u -r1.1 -r1.4 --- src/csh/do_by_blocks.py 27 Nov 2003 02:02:58 -0000 1.1 +++ src/csh/do_by_blocks.py 31 Mar 2004 06:15:23 -0000 1.4 @@ -27,9 +27,6 @@ # # Notes: # - Needs documentation in scripthelp! -# - Implement export of par files -# - Implement export of summaries -# - And of course, smartreader has to make acq_blocks chunk. # # import sys @@ -42,35 +39,130 @@ sys.path.append(os.environ["FIASCO"]) from fiasco_utils import * -idString= "$Id: do_by_blocks.py,v 1.1 2003/11/27 02:02:58 welling Exp $" +idString= "$Id: do_by_blocks.py,v 1.4 2004/03/31 06:15:23 welling Exp $" +zdim= None +tdim= None paramRegex= re.compile('.*\.par\.(\d+)') datRegex= re.compile('.*\.dat') mriRegex= re.compile('.*\.mri') -summaryRegex= re.compile('summary\..*') +summaryInputRegex= re.compile('.*summary\.input') +summaryMissingRegex= re.compile('.*summary\.missing') anyRegex= re.compile('.*') +summary_missing_file= None +summary_missing_step= None +first_created_mri= None +parDict= {} +parFormatDict= {} + +def parZFastestMethod( fname, parList ): + # This one is easy- just dump in order + ofile= file(fname,'a') + for parLine in parList: + for tok in parLine: + ofile.write(tok) + ofile.write("\n") + ofile.close() + +def parIndexTZMethod( fname, parList ): + global tdim, zdim + slices= [] + for i in xrange(zdim): + slices.append([]) + for parLine in parList: + slices[int(parLine[1])].append(parLine[2:]) + ofile= file(fname,'a') + for z in xrange(zdim): + t= 0 + for parLine in slices[z]: + ofile.write("%d %d "%(t,z)) + for tok in parLine: + ofile.write(tok+' ') + ofile.write("\n") + t= t+1 + ofile.close() + +parFormatExportMethods= {'z_fastest':parZFastestMethod, \ + 'index_tz':parIndexTZMethod } def exportParam(topName,parts,tmpdir): + global parDict, parFormatDict verboseMessage("Exporting %s as a param file!"%topName); + firstPart= parts[0] + f= open(os.path.join(tmpdir,firstPart),"r") + lines= f.readlines() + f.close() + ofile= file(topName,"w") + debugMessage("Creating %s"%topName) + parFormatDict[topName]= "unknown" + keepTheseLines= [] + for line in lines: + if line[0:9]=='##Format:': + if ofile != None: + ofile.write(line) #Transfer format info + if string.find(line[9:],'order:')>=0: + pairs= string.split(line[9:]) + for p in pairs: + toks= string.split(p,':') + if string.strip(toks[0])=='order': + parFormatDict[topName]= string.strip(toks[1]) + else: + if line[0] != '#': + keepTheseLines.append( string.split(line) ) + ofile.close() + for thisPart in parts[1:]: + f= open(os.path.join(tmpdir,thisPart),"r") + lines= f.readlines() + f.close() + for line in lines: + if line[0] != '#': + keepTheseLines.append( string.split(line) ) + parDict[topName]= keepTheseLines def exportDat(topName,parts,tmpdir): verboseMessage("Ignoring %s as a .dat file!"%topName); def exportMri(topName,parts,tmpdir): + global first_created_mri verboseMessage("Exporting %s as a .mri file!"%topName); cmd= "mri_paste -d t -out %s "%topName for p in parts: cmd= "%s %s"%(cmd,os.path.join(tmpdir,p)) safeRun(cmd) + if first_created_mri==None: + first_created_mri= topName -def exportSummary(topName,parts,tmpdir): - verboseMessage("Ignoring %s as a summary file!"%topName); +def exportSummaryInput(topName,parts,tmpdir): + verboseMessage("Handling %s as a summary.input file!"%topName); + firstPart= parts[0] + f= open(os.path.join(tmpdir,firstPart),"r") + lines= f.readlines() + f.close() + if len(lines)>0: + ofile= file(key,"a") + for l in lines: + ofile.write("%s.%d\n"%(l[0:string.rfind(l,".")],os.getpid())) + ofile.close() + +def exportSummaryMissing(topName,parts,tmpdir): + global first_created_mri, summary_missing_file, summary_missing_step + verboseMessage("Handling %s as a summary.input file!"%topName); + firstPart= parts[0] + f= open(os.path.join(tmpdir,firstPart),"r") + lines= f.readlines() + f.close() + if len(lines)>0: + l= lines[0] + summary_missing_file= topName + summary_missing_step= "%s.%d"%(l[0:string.rfind(l,".")],os.getpid()) def exportAny(topName,parts,tmpdir): verboseMessage("Ignoring %s as a any file!"%topName); exportMethodPairs= [ (paramRegex,exportParam), (mriRegex,exportMri), \ - (datRegex,exportDat), (summaryRegex,exportSummary), \ + (datRegex,exportDat), \ + (summaryInputRegex,exportSummaryInput), \ + (summaryMissingRegex,exportSummaryMissing), \ (anyRegex,exportAny) ] # 'any' must be last! def checkEnvInt(val, name): @@ -163,6 +255,7 @@ #Check reasonableness of input tdim= 0 +zdim= 0 prevDS= None if len(inDSList) == 0: sys.exit("None of the given datasets exist!"); @@ -184,9 +277,14 @@ if tdim != main.getDim("t"): sys.exit("acq_blocks tdim does not match that of %s chunk!"%\ (mainChunk)) + if zdim == 0: + zdim= main.getDim("z") + elif main.getDim("z") != zdim: + sys.exit("Dataset %s has a different z dimension from %s!"%\ + (thisDS,prevDS)) prevDS= thisDS -debugMessage("tdim= %d"%tdim) +debugMessage("tdim= %d, zdim= %d"%(tdim,zdim)) # Make up a temporary directory tmpdir= makeTempDir("tmp_do_by_blocks") @@ -280,7 +378,7 @@ else: debugMessage("<%s> is unchanged."%key) -if getDebug: +if getDebug(): debugMessage("###### Created files:") for key in createdDict: debugMessage("%s -> %s"%(key,createdDict[key])) @@ -288,29 +386,47 @@ for key in changedDict: debugMessage("%s -> %s"%(key,createdDict[key])) -# Create directories to output datasets if necessary +# Commence constructing the output files! os.chdir(homedir) -for thisDS in outDSList: - checkPathExists(thisDS) # Build the output files for key in createdDict: - print("Exporting newly created file %s"%key) + checkPathExists(key) for regex, mthd in exportMethodPairs: if regex.match(key): mthd(key,createdDict[key],tmpdir) break for key in changedDict: - print("Exporting changed file %s"%key) for regex, mthd in exportMethodPairs: if regex.match(key): mthd(key,changedDict[key],tmpdir) break -# Generate entries for summary.missing and summary.error +# Generate entries for summary.missing +if summary_missing_file != None and summary_missing_step != None \ + and first_created_mri != None: + verboseMessage("Generating %s info from %s"%\ + (summary_missing_file,first_created_mri)) + ofile= file(summary_missing_file,"a") + ofile.write("%s\n"%summary_missing_step) + cmd= "count_missing.csh %s"%first_created_mri + lines= readCmdOutputToList(cmd) + for l in lines: + ofile.write(l) + ofile.close() + +# Fill the exported parameter files +for fname in parDict: + parList= parDict[fname] + format= parFormatDict[fname] + if parFormatExportMethods.has_key(format): + parFormatExportMethods[format](fname,parList) + else: + Message("Unable to export %s: format %s is unknown."%(fname,format)) # Clean up -removeTmpDir(tmpdir) +if not getDebug(): + removeTmpDir(tmpdir) Index: src/csh/epi.defaults.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/epi.defaults.csh,v retrieving revision 1.48 retrieving revision 1.49 diff -a -u -r1.48 -r1.49 --- src/csh/epi.defaults.csh 7 Aug 2003 21:13:19 -0000 1.48 +++ src/csh/epi.defaults.csh 27 Mar 2004 01:41:25 -0000 1.49 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -echo '#$Id: epi.defaults.csh,v 1.48 2003/08/07 21:13:19 welling Exp $' +echo '#$Id: epi.defaults.csh,v 1.49 2004/03/27 01:41:25 welling Exp $' if(! -d in)mkdir in # # @@ -561,4 +561,42 @@ # setenv F_WATCHER_LOG out/watcher.log # +# +# Coregistration +# +# Pgh MRI dataset to be used as the prototype functional data for coreg +setenv F_CRG_FUNC stat/GrandMean +# +# name of the coregistered version of F_CRG_FUNC dataset +setenv F_CRG_FUNC_COREG aligned_GrandMean +# +# Input for smartreader to generate inplane anatomical data (unset by default) +setenv F_CRG_INPL_INPUT "" +# +# smartreader options for the inplane anatomical data +setenv F_CRG_INPL_OPTS "" +# +# name of the inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL inplane +# +# name of skull-stripped inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL_STRIPPED stripped_inplane +# +# Input for smartreader to generate axial anatomical data (unset by default) +setenv F_CRG_ANAT_INPUT "" +# +# smartreader options for the axial anatomical data +setenv F_CRG_ANAT_OPTS "" +# +# name of the axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT axial +# +# name of skull-stripped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_STRIPPED stripped_axial +# +# name of coregistered and warped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_COWARPED warped_axial +# +# name of coregistered, warped axial resampled to match inplanes +setenv F_CRG_ANAT_INPL warped_axial_resampled Index: src/csh/epi.despike.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/epi.despike.csh,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- src/csh/epi.despike.csh 9 Sep 2003 16:25:45 -0000 1.5 +++ src/csh/epi.despike.csh 3 Feb 2004 20:54:29 -0000 1.6 @@ -28,7 +28,7 @@ # ************************************************************/ # echo '#'`date` $0 -echo '#$Id: epi.despike.csh,v 1.5 2003/09/09 16:25:45 bakalj Exp $' +echo '#$Id: epi.despike.csh,v 1.6 2004/02/03 20:54:29 welling Exp $' # Find out some dimensions set vdim = `mri_printfield -field images.extent.v $1` @@ -40,6 +40,7 @@ @ pdim = ( $xdim * $ydim ) # Make a working copy, and give it the needed shape. +if ( ! -d data ) mkdir data mri_type_convert -float $1 data/raw_samples mri_remap -order vpsczt -length ${vdim}:${pdim}:1:1:${zdim}:${tdim} \ data/raw_samples Index: src/csh/epi.local.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/epi.local.csh,v retrieving revision 1.19 retrieving revision 1.21 diff -a -u -r1.19 -r1.21 --- src/csh/epi.local.csh 7 Mar 2003 23:00:13 -0000 1.19 +++ src/csh/epi.local.csh 27 Mar 2004 01:41:25 -0000 1.21 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: epi.local.csh,v 1.19 2003/03/07 23:00:13 welling Exp $ +# $Id: epi.local.csh,v 1.21 2004/03/27 01:41:25 welling Exp $ # # @@ -54,23 +54,41 @@ setenv F_DESCRIPTION "INTERESTING EPI TEST DATA SET" # -# Information describing the data format. If the input data is -# a Pfile, set F_READER_DIMS to "" . +# Information describing the data format. # # number of slices setenv F_NSLICE 2 +# # number of images setenv F_NIMAGE 20 -# lengths of input data dimensions. Modify the 64 below if this -# is partial-k scan data. +# +# If this scan is in raw binary (.raw or .ra) form, you must complete +# the F_READER_DIMS field to specify input data dimensions. Otherwise, +# set the value to "" (empty quotes). If this is a raw binary partial-k +# scan modify the 64 in the dimensions to give the number of rows acquired. +# setenv F_READER_DIMS "128 64 $F_NSLICE $F_NIMAGE" # -# Other reader options. See the documentation for "reader"; -# these are generally only needed for Pfiles. +# Other reader options. See the documentation for "smartreader"; +# some common flags include '-multi' and '-auxfile' # setenv F_READER_OPTS "" -# Voxel dimensions for the final reconstructed images. +# If an axial anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_ANAT_INPUT "" +setenv F_CRG_ANAT_OPTS "" + +# If an inplane anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_INPL_INPUT "" +setenv F_CRG_INPL_OPTS "" + +# Voxel dimensions for the final reconstructed functional images. # F_ZVOXEL should include the slice separation! setenv F_XVOXEL 3.125 setenv F_YVOXEL 3.125 @@ -114,6 +132,13 @@ # to be generated, and will calculate and produce overlays with the # given false discovery rate. setenv F_LOWERQ 0.05 + +# Active voxel count threshold. Uncommenting the first line will cause +# Tmap overlays to be generated showing the N voxels with strongest +# activation. Uncommenting the second line will pick these voxels +# from both tails of the distribution, rather than just the left tail +#setenv F_PICKN_COUNT 200 +#setenv F_PICKN_TWOTAILED 1 # Uncomment the following line to prevent summary information from # this run being sent to Fiasco Headquarters. This summary info is Index: src/csh/fiasco_utils.py =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/fiasco_utils.py,v retrieving revision 1.6 retrieving revision 1.12 diff -a -u -r1.6 -r1.12 --- src/csh/fiasco_utils.py 27 Nov 2003 02:02:58 -0000 1.6 +++ src/csh/fiasco_utils.py 1 Apr 2004 02:05:53 -0000 1.12 @@ -26,12 +26,15 @@ # This script should not be run directly; it's library routines # for other Python scripts. # -_idString_= "$Id: fiasco_utils.py,v 1.6 2003/11/27 02:02:58 welling Exp $" +_idString_= "$Id: fiasco_utils.py,v 1.12 2004/04/01 02:05:53 welling Exp $" import sys import os import string import getopt +import math +import copy +import _quaternion global _debug_ global _verbose_ @@ -87,8 +90,16 @@ def safeRun(cmd): debugMessage("running <%s>"%cmd) - cmdout= os.popen(cmd) - cmdout.readlines() # Throw away the output + if _debug_: + (cmdin,cmdout)= os.popen4(cmd,'t',128) + try: + for line in cmdout: + debugMessage(string.strip(line)) + except StopIteration: + pass + else: + cmdout= os.popen(cmd) + cmdout.readlines() # Throw away the output if cmdout.close() != None : sys.exit("Command failed: <%s>"%cmd) @@ -165,6 +176,18 @@ xstr= string.strip(xstr) return (xstr=='[chunk]') +def checkExeFound( exeName, pkgName ): + "Throw an exception if exeName (from package pkgName) is not in PATH" + try: + whichStr= readCmdOutputToList("which %s"%exeName)[0] + except: + raise Exception("%s executable %s is not in PATH"%\ + (pkgName,exeName)) + splitWhichStr= string.split(string.strip(whichStr)) + if len(splitWhichStr) != 1: + raise Exception("%s executable %s is not in PATH"%\ + (pkgName,exeName)) + class MRIChunk: def __init__(self,ds,name): self.ds= ds @@ -178,6 +201,8 @@ return self.dict.has_key(key) def getValue(self,key): return self.dict[key] + def getFloat(self,key): + return float(self.dict[key]) def getDim(self,d): return int(self.getValue("extent.%s"%d)) @@ -227,3 +252,426 @@ def getOrphan(self,key): return self.orphans[key] + +class Vec4: + "A homogeneous coordinate 4-vector" + def __init__(self,v1,v2,v3,v4=1): + self.data= [v1,v2,v3,v4] + def __str__(self): return str(self.data) + def __repr__(self): return "Vec4(%lf,%lf,%lf,%lf)"%tuple(self.data) + def __add__(self,other): + return Vec4( (self.data[0]*other.data[3])+(other.data[0]*self.data[3]), + (self.data[1]*other.data[3])+(other.data[1]*self.data[3]), + (self.data[2]*other.data[3])+(other.data[2]*self.data[3]), + self.data[3]*other.data[3]) + def __sub__(self,other): + return Vec4( (self.data[0]*other.data[3])-(other.data[0]*self.data[3]), + (self.data[1]*other.data[3])-(other.data[1]*self.data[3]), + (self.data[2]*other.data[3])-(other.data[2]*self.data[3]), + self.data[3]*other.data[3]) + def clone(self): + return Vec4(self.data[0],self.data[1],self.data[2],self.data[3]) + def dot(self,other): + tot= 0.0 + for i in xrange(3): + tot+= self.data[i]*other.data[i] + return tot/(self.data[3]*other.data[3]) + def mag(self): return math.sqrt(self.dot(self)) + def normalize(self): + val= self.mag() + for i in xrange(3): + self.data[i]= self.data[i]/(val*self.data[3]) + self.data[3]= 1.0 + def cross(self,other): + v1= self.data + v2= other.data + return Vec4(v1[1]*v2[2]-v1[2]*v2[1], + v1[2]*v2[0]-v1[0]*v2[2], + v1[0]*v2[1]-v1[1]*v2[0], + v1[3]*v2[3]) + def __rmul__(self,other): + return Vec4(other*self.data[0], other*self.data[1], + other*self.data[2], self.data[3]) + def __getitem__(self,range): return self.data[range] + def __setitem__(self,range,val): + self.data[range]= val + +class Transform: + "A homogeneous 4x4 transformation matrix" + def __init__(self,dList=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,\ + 0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]): + if len(dList) != 16: + raise TypeError, 'bad Transform initialization list' + self.data= copy.copy(dList) + def __str__(self): return str(self.data) + def __repr__(self): return "Transform(%s)"%repr(self.data) + def __len__(self): return len(self.data) + def __getitem__(self,range): return self.data[range] + def __setitem__(self,range,val): + self.data[range]= val + +def getVec4( chunk, which ): + if chunk.hasValue(which+'.0') and chunk.hasValue(which+'.1') and chunk.hasValue(which+'.2'): + return Vec4( chunk.getFloat(which+'.0'), chunk.getFloat(which+'.1'), + chunk.getFloat(which+'.2') ) + else: + return None + +def getVox( chunk ): + which= 'voxel_spacing' + if chunk.hasValue(which+'.x') and chunk.hasValue(which+'.y') \ + and chunk.hasValue(which+'.z'): + return [ chunk.getFloat(which+'.x'), chunk.getFloat(which+'.y'), \ + chunk.getFloat(which+'.z') ] + else: + return None + +class BBox: + def __init__(self,chunk): + self.chunk= chunk + self.tlf= getVec4(chunk,'tlf') + self.trf= getVec4(chunk,'trf') + self.tlb= getVec4(chunk,'tlb') + self.trb= getVec4(chunk,'trb') + self.blf= getVec4(chunk,'blf') + self.brf= getVec4(chunk,'brf') + self.blb= getVec4(chunk,'blb') + self.brb= getVec4(chunk,'brb') + self.ctr= getVec4(chunk,'ctr') + self.xdim= chunk.getDim('x') + self.ydim= chunk.getDim('y') + self.zdim= chunk.getDim('z') + self.vox= getVox(chunk) + # Try to get any missing corners + changes= 1 + missing=1 + xedge= None + yedge= None + zedge= None + while changes>0 and missing>0: + missing= 0 + changes= 0 + if xedge==None: + if self.tlf != None and self.trf != None: + xedge= self.trf - self.tlf + elif self.blf != None and self.brf != None: + xedge= self.brf - self.blf + elif self.tlb != None and self.trb != None: + xedge= self.trb - self.tlb + elif self.blb != None and self.brb != None: + xedge= self.brb - self.blb + if yedge==None: + if self.trb != None and self.trf != None: + yedge= self.trb - self.trf + elif self.brb != None and self.brf != None: + yedge= self.brb - self.brf + if self.tlb != None and self.tlf != None: + yedge= self.tlb - self.tlf + elif self.blb != None and self.blf != None: + yedge= self.blb - self.blf + if zedge==None: + if self.tlf != None and self.blf != None: + zedge= self.tlf - self.blf + if self.trf != None and self.brf != None: + zedge= self.trf - self.brf + if self.tlb != None and self.blb != None: + zedge= self.tlb - self.blb + if self.trf != None and self.brf != None: + zedge= self.trb - self.brb + if self.tlf == None: + missing= missing+1 + if xedge != None and self.trf != None: + self.tlf= self.trf - xedge + changes= changes+1 + elif yedge != None and self.tlb != None: + self.tlf= self.tlb - yedge + changes= changes+1 + elif zedge != None and self.blf != None: + self.tlf= self.blf + zedge; + changes= changes+1 + if self.trf == None: + missing= missing+1 + if xedge != None and self.tlf != None: + self.trf= self.tlf + xedge + changes= changes+1 + elif yedge != None and self.trb != None: + self.trf= self.trb - yedge + changes= changes+1 + elif zedge != None and self.brf != None: + self.trf= self.brf + zedge; + changes= changes+1 + if self.tlb == None: + missing= missing+1 + if xedge != None and self.trb != None: + self.tlb= self.trb - xedge + changes= changes+1 + elif yedge != None and self.tlf != None: + self.tlb= self.tlf + yedge + changes= changes+1 + elif zedge != None and self.blb != None: + self.tlb= self.blb + zedge; + changes= changes+1 + if self.trb == None: + missing= missing+1 + if xedge != None and self.tlb != None: + self.trb= self.tlb + xedge + changes= changes+1 + elif yedge != None and self.trf != None: + self.trb= self.trf + yedge + changes= changes+1 + elif zedge != None and self.brb != None: + self.trb= self.brb + zedge; + changes= changes+1 + if self.blf == None: + missing= missing+1 + if xedge != None and self.brf != None: + self.blf= self.brf - xedge + changes= changes+1 + elif yedge != None and self.blb != None: + self.blf= self.blb - yedge + changes= changes+1 + elif zedge != None and self.tlf != None: + self.blf= self.tlf - zedge; + changes= changes+1 + if self.brf == None: + missing= missing+1 + if xedge != None and self.blf != None: + self.brf= self.blf + xedge + changes= changes+1 + elif yedge != None and self.brb != None: + self.brf= self.brb - yedge + changes= changes+1 + elif zedge != None and self.trf != None: + self.brf= self.trf - zedge; + changes= changes+1 + if self.blb == None: + missing= missing+1 + if xedge != None and self.brb != None: + self.blb= self.brb - xedge + changes= changes+1 + elif yedge != None and self.blf != None: + self.blb= self.blf + yedge + changes= changes+1 + elif zedge != None and self.tlb != None: + self.blb= self.tlb - zedge; + changes= changes+1 + if self.brb == None: + missing= missing+1 + if xedge != None and self.blb != None: + self.brb= self.blb + xedge + changes= changes+1 + elif yedge != None and self.brb != None: + self.brb= self.brf + yedge + changes= changes+1 + elif zedge != None and self.trf != None: + self.brb= self.trb - zedge; + changes= changes+1 + missing= missing-changes + # Here we assume that the center is the geometrical center + # of the corners, since it would be recorded if it were + # otherwise. + if self.ctr == None: + if self.tlf != None and self.brb != None: + self.ctr= 0.5*(self.tlf+self.brb) + elif self.trf != None and self.blb != None: + self.ctr= 0.5*( self.trf+self.blb ) + elif self.tlb != None and self.brf != None: + self.ctr= 0.5*( self.tlb+self.brf ) + elif self.trb != None and self.blf != None: + self.ctr= 0.5*(self.trb+self.blf) + elif self.tlf != None and self.blf != None \ + and self.blb != None and self.brf != None: + dx= self.brf-self.blf + dy= self.blf-self.blb + dz= self.tlf-self.blf + self.ctr= self.blf+(0.5*(dx+dy+dz)) + else: + sys.exit("Cannot find enough corners in dataset %s chunk %s!"%\ + (chunk.ds.fname,chunk.name)) + + + + def setCorners(self,xAxis,yAxis,zAxis): + "Set the corner locs based on current center, size, and given unit vectorss" + dx= (self.xdim/2)*self.vox[0] # high side + dy= (self.ydim/2)*self.vox[1] # high side + dz= (self.zdim/2)*self.vox[2] # high side + self.trb= self.ctr + (dx*xAxis) + (dy*yAxis) + (dz*zAxis) + self.tlb= self.ctr - (dx*xAxis) + (dy*yAxis) + (dz*zAxis) + self.trf= self.ctr + (dx*xAxis) - (dy*yAxis) + (dz*zAxis) + self.tlf= self.ctr - (dx*xAxis) - (dy*yAxis) + (dz*zAxis) + self.brb= self.ctr + (dx*xAxis) + (dy*yAxis) - (dz*zAxis) + self.blb= self.ctr - (dx*xAxis) + (dy*yAxis) - (dz*zAxis) + self.brf= self.ctr + (dx*xAxis) - (dy*yAxis) - (dz*zAxis) + self.blf= self.ctr - (dx*xAxis) - (dy*yAxis) - (dz*zAxis) + + def setCtr(self,ctr): + self.ctr= ctr + + def setVox(self,vox): + self.vox= copy.copy(vox) + + def printBounds(self, label): + Message('-----------------------') + Message(label) + Message(' tlf: '+str(self.tlf)) + Message(' trf: '+str(self.trf)) + Message(' tlb: '+str(self.tlb)) + Message(' trb: '+str(self.trb)) + Message(' blf: '+str(self.blf)) + Message(' brf: '+str(self.brf)) + Message(' blb: '+str(self.blb)) + Message(' brb: '+str(self.brb)) + Message(' ctr: '+str(self.ctr)) + if self.chunk.hasValue('table_delta'): + Message(" tableDelta: %f"%\ + self.chunk.getFloat('table_delta')) + Message(' voxel size: %s'%self.vox) + Message('-----------------------') + + def copyBoundsFrom(self,other): + self.trb= other.trb + self.tlb= other.tlb + self.trf= other.trf + self.tlf= other.tlf + self.brb= other.brb + self.blb= other.blb + self.brf= other.brf + self.blf= other.blf + self.ctr= other.ctr + + def exportBound(self, which, val): + safeRun("mri_setfield -field %s.%s -all012 -value ' %f,%f,%f' %s"%\ + (self.chunk.name,which,val[0],val[1],val[2], + self.chunk.ds.fname)) + + def exportBounds(self): + self.exportBound("tlf",self.tlf) + self.exportBound("trf",self.trf) + self.exportBound("tlb",self.tlb) + self.exportBound("trb",self.trb) + self.exportBound("blf",self.blf) + self.exportBound("brf",self.brf) + self.exportBound("blb",self.blb) + self.exportBound("brb",self.brb) + self.exportBound("ctr",self.ctr) + safeRun("mri_setfield -field %s.voxel_spacing -allxyz -value ' %f,%f,%f' %s"%\ + (self.chunk.name, self.vox[0], self.vox[1], self.vox[2], \ + self.chunk.ds.fname)) + +def bboxFromFilename(fname): + newDS= MRIDataset(fname) + ch= newDS.getChunk('images') + return BBox(ch) + + +################################################# +# This file was created automatically by SWIG. +# Don't modify this file, modify the SWIG interface instead. +# This file is compatible with both classic and new-style classes. + +import _quaternion + +def _swig_setattr(self,class_type,name,value): + if (name == "this"): + if isinstance(value, class_type): + self.__dict__[name] = value.this + if hasattr(value,"thisown"): self.__dict__["thisown"] = value.thisown + del value.thisown + return + method = class_type.__swig_setmethods__.get(name,None) + if method: return method(self,value) + self.__dict__[name] = value + +def _swig_getattr(self,class_type,name): + method = class_type.__swig_getmethods__.get(name,None) + if method: return method(self) + raise AttributeError,name + +import types +try: + _object = types.ObjectType + _newclass = 1 +except AttributeError: + class _object : pass + _newclass = 0 +del types + + +class Quat(_object): + __swig_setmethods__ = {} + __setattr__ = lambda self, name, value: _swig_setattr(self, Quat, name, value) + __swig_getmethods__ = {} + __getattr__ = lambda self, name: _swig_getattr(self, Quat, name) + __swig_setmethods__["x"] = _quaternion.Quat_x_set + __swig_getmethods__["x"] = _quaternion.Quat_x_get + if _newclass:x = property(_quaternion.Quat_x_get, _quaternion.Quat_x_set) + __swig_setmethods__["y"] = _quaternion.Quat_y_set + __swig_getmethods__["y"] = _quaternion.Quat_y_get + if _newclass:y = property(_quaternion.Quat_y_get, _quaternion.Quat_y_set) + __swig_setmethods__["z"] = _quaternion.Quat_z_set + __swig_getmethods__["z"] = _quaternion.Quat_z_get + if _newclass:z = property(_quaternion.Quat_z_get, _quaternion.Quat_z_set) + __swig_setmethods__["w"] = _quaternion.Quat_w_set + __swig_getmethods__["w"] = _quaternion.Quat_w_get + if _newclass:w = property(_quaternion.Quat_w_get, _quaternion.Quat_w_set) + def __str__(*args): return _quaternion.Quat___str__(*args) + def __repr__(*args): return _quaternion.Quat___repr__(*args) + def __init__(self, *args): + _swig_setattr(self, Quat, 'this', _quaternion.new_Quat(*args)) + _swig_setattr(self, Quat, 'thisown', 1) + def __del__(self, destroy=_quaternion.delete_Quat): + try: + if self.thisown: destroy(self) + except: pass + +class QuatPtr(Quat): + def __init__(self, this): + _swig_setattr(self, Quat, 'this', this) + if not hasattr(self,"thisown"): _swig_setattr(self, Quat, 'thisown', 0) + _swig_setattr(self, Quat,self.__class__,Quat) +_quaternion.Quat_swigregister(QuatPtr) + + +trans_mult_right = _quaternion.trans_mult_right + +trans_mult_left = _quaternion.trans_mult_left + +trans_transpose = _quaternion.trans_transpose + +trans_vec_mult = _quaternion.trans_vec_mult + +trans_dump = _quaternion.trans_dump + +trans_to_quat = _quaternion.trans_to_quat + +quat_to_trans = _quaternion.quat_to_trans + +quat_copy = _quaternion.quat_copy + +quat_nrm_sqrt = _quaternion.quat_nrm_sqrt + +quat_normalize = _quaternion.quat_normalize + +quat_mult_right = _quaternion.quat_mult_right + +quat_mult_left = _quaternion.quat_mult_left + +quat_identity = _quaternion.quat_identity + +quat_conjugate = _quaternion.quat_conjugate + +quat_create = _quaternion.quat_create + +quat_from_axis_angle = _quaternion.quat_from_axis_angle + +quat_to_axis_angle = _quaternion.quat_to_axis_angle + +quat_from_euler_RzRyRx = _quaternion.quat_from_euler_RzRyRx + +quat_to_euler_RzRyRx = _quaternion.quat_to_euler_RzRyRx + +############################################## +# End of quaternion block, generated by SWIG +############################################## + Index: src/csh/make_P_P_plots.csh =================================================================== RCS file: src/csh/make_P_P_plots.csh diff -N src/csh/make_P_P_plots.csh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/make_P_P_plots.csh 5 Feb 2004 20:02:07 -0000 1.4 @@ -0,0 +1,183 @@ +#! /bin/csh -ef +# make_P_P_plots.csh +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1998,1999 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# * Original programming by Bill Eddy * +# ************************************************************/ +# +echo '#'`date` $0 +echo '# $Id: make_P_P_plots.csh,v 1.4 2004/02/05 20:02:07 welling Exp $' +# +# This script generates arrays of P-P or Q-P plots +# usage: make_P_P_plots.csh Pfile1 Pfile2 Pfile3 ... +# + +# Default range +set range = 1000 + +# Parse command line options +set plotout = "plot_P_P.ps" +set fracfit = 2 + +set errflag = 0 +while ( $#argv >= 1 && dummy$argv[1] =~ dummy-* ) + switch ( $1 ) + case '-out': + if ( $#argv < 2 ) then + set errflag = 1 + else + set plotout = $2 + shift + endif + breaksw + case '-fitdenom': + if ( $#argv < 2 ) then + set errflag = 1 + else + set fracfit = $2 + shift + endif + breaksw + case '-help': + if ( $#argv > 1 ) then + scripthelp $0 $argv[2] + else + scripthelp $0 + endif + exit 0 + breaksw + default: + set errflag = 1 + breaksw + endsw + shift +end +if ( $#argv < 1 ) then + set errflag = 1 +endif +if ($errflag != 0 || $#argv < 1 ) then + scripthelp $0 usage + exit -1 +endif + +# +# Make some scratch space, and go there. +# +if ( ${?F_TEMP} ) then + set tmpdir = ${F_TEMP}/tmp_make_P_P_plots_$$ +else + set tmpdir = ./tmp_make_P_P_plots_$$ +endif +if (! -e $tmpdir) mkdir $tmpdir +set homedir = `pwd` +cd $tmpdir +mkdir tfiles + +# +# Extract all the needed text files +# +echo "# Generating P score text files" +set quoted_names = () +foreach pfile ( $* ) + if ( ${pfile} =~ /* ) then + set input = ${pfile} + else + set input = $homedir/${pfile} + endif + set dsname = ${pfile:r} + set safename = `echo $dsname | sed 's%/%_%g'` + set ofile = tfiles/${safename}_pscores.t + set quoted_names = ( $quoted_names '"'$safename'",' ) + echo "# Processing $dsname" + mri_copy_dataset $input in + set xdim = `mri_printfield -fld images.extent.x in` + set ydim = `mri_printfield -fld images.extent.y in` + set zdim = `mri_printfield -fld images.extent.z in` + @ qdim = $xdim * $ydim * $zdim + mri_remap -order vq -len 1:$qdim in + mri_sort -ascending in sorted + set n_valid = \ + `mri_rpn_math -out junk '0,$1,dup,is_finite,if_print_1' sorted | wc -l ` + if ( $n_valid != $qdim ) then + mri_subset -d q -len $n_valid -shift 0 sorted valid + set qdim = $n_valid + else + mri_copy_dataset sorted valid + endif + mri_rpn_math -out x '$q,1,+' valid + mri_rpn_math -out junk '0,$q,$1,1,if_print_2' valid > $ofile + @ q_fitfrac = $n_valid / $fracfit + @ q_low = ( $n_valid - $q_fitfrac ) / 2 + mri_subset -d q -len $q_fitfrac -shift $q_low sorted sorted_middle + mri_subset -d q -len $q_fitfrac -shift $q_low x x_middle + mri_remap -order tqz -len ${q_fitfrac}:1:1 sorted_middle + mri_remap -order tz -len ${q_fitfrac}:1 x_middle + mri_glm -est glm_est:images sorted_middle:images x_middle:images + set intercept = `mri_rpn_math -out junk '0,$1,$v,0,==,if_print_1' glm_est` + set slope = `mri_rpn_math -out junk '0,$1,$v,1,==,if_print_1' glm_est` + set fitfile = tfiles/${safename}_fit.t + echo $intercept $slope > $fitfile +end + +# +# Here is the R script we'll use +# +cat < plot_stuff.R +namelist <- c(${quoted_names}) + +postscript(horizontal=T,file="test.ps") +op <- par(mfrow=c(2,3),pty="s"); + +for (name in namelist) { + data <- read.table(paste(name,"_pscores.t",sep="")) + fit <- read.table(paste(name,"_fit.t",sep="")) + plot(data,pch='.',main=name,ylim=c(0.0,1.0), + xlab="",ylab="") + abline(fit[1,1],fit[1,2]) +} + +print("All done!"); +par(op); + +SCRIPT_EOF + +# +# Generate the plot .ps files +# +cd tfiles +if ( ${?SPLUS} ) then + set rcommand = $SPLUS +else + set rcommand = "R --no-save" +endif +echo "# Generating plot" +${rcommand} < ../plot_stuff.R >& ../R.log +cp test.ps $homedir/$plotout +echo "# Done." + +#clean up +cd $homedir +#rm -r $tmpdir + Index: src/csh/make_cine.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/make_cine.csh,v retrieving revision 1.14 retrieving revision 1.15 diff -a -u -r1.14 -r1.15 --- src/csh/make_cine.csh 9 Sep 2003 16:25:45 -0000 1.14 +++ src/csh/make_cine.csh 11 Dec 2003 21:37:29 -0000 1.15 @@ -1,4 +1,4 @@ -#! /bin/csh -ef +#! /bin/csh -f # make_cine.csh #/************************************************************ # * * @@ -29,7 +29,7 @@ # echo '#'`date` $0 -echo '# $Id: make_cine.csh,v 1.14 2003/09/09 16:25:45 bakalj Exp $' +echo '# $Id: make_cine.csh,v 1.15 2003/12/11 21:37:29 welling Exp $' # # This script generates a cine loop from a (v)xyzt dataset. # The one argument is the name of a single scalar dataset file. Index: src/csh/make_group_anat.csh =================================================================== RCS file: src/csh/make_group_anat.csh diff -N src/csh/make_group_anat.csh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/make_group_anat.csh 16 Apr 2004 22:50:45 -0000 1.1 @@ -0,0 +1,130 @@ +#! /bin/csh -ef +# +# This script does between-group comparisons. +# +echo '#'`date` $0 +echo '# $Id: make_group_anat.csh,v 1.1 2004/04/16 22:50:45 welling Exp $' + +# Check for help command +if ( $#argv >= 1 ) then + if ( junk$argv[1] == junk-help ) then + if ( $#argv >= 2 ) then + scripthelp $0 $argv[2] + else + scripthelp $0 + endif + exit + endif +endif + +# Parse command line options +set args = `getopt m:d:h $*` +set help = "" +set mapstuff = "" + +while ($#args > 1) + switch ( $args[1] ) + case '-m' : + if ( ${?F_MAP_PATH} ) then + setenv F_MAP_PATH $args[2]':'${F_MAP_PATH} + else + setenv F_MAP_PATH $args[2] + endif + shift args; shift args; breaksw; + case '-d' : + set mapstuff = $mapstuff" "$args[2] + shift args; shift args; breaksw; + case '-h' : + set help = 1 ; shift args; breaksw; + endsw + if (junk${args[1]} == 'junk--') then + shift args; + break; + endif +end +if ($#args < 2 || dummy$help != dummy ) then + scripthelp $0 usage + exit -1 +endif + +# +# Make some scratch space, and go there. +# +if ( ${?F_TEMP} ) then + set tmpdir = ${F_TEMP}/make_group_anat_tmp_$$ +else + set tmpdir = ./make_group_anat_tmp_$$ +endif +if (! -e $tmpdir) mkdir $tmpdir +echo "Scratch directory will be " $tmpdir +set homedir = `pwd` +echo "Current directory is " $homedir +cd $tmpdir + +foreach ds_type ( Axial Inplane StrippedAxial StrippedInplane ) + echo '######## Collecting' $ds_type 'anatomical datasets ########' + set ds_list = () + + foreach subj ($args) + set axial_name = `map_name.py -d cond=1 -d file=$ds_type $subj` + if ( -e ${axial_name}.mri ) then + echo " Found axial anatomical for " $subj + set ds_list= ( $ds_list $axial_name ) + else + echo " $ds_type anatomical for $subj not found- skipping this subject!" + endif + end + + if ( ${#ds_list} != 0 ) then + + # Build the mean for this dataset + echo '######## Assembling the mean' $ds_type 'dataset ########' + set count = 0 + while ( $#ds_list ) + if ( $#ds_list > 5 ) then + set these_args = ( $ds_list[1-5] ) + set ds_list = ( $ds_list[6-] ) + else + set these_args = ( $ds_list ) + set ds_list = ( ) + endif + @ count = $count + $#these_args + switch ( ${#these_args} ) + case 1 : + mri_copy_dataset $these_args[1] tmp_sum; + breaksw; + case 2 : + mri_rpn_math -out tmp_sum '$1,$2,+' $these_args ; + breaksw; + case 3 : + mri_rpn_math -out tmp_sum '$1,$2,+,$3,+' $these_args ; + breaksw; + case 4 : + mri_rpn_math -out tmp_sum '$1,$2,+,$3,+,$4,+' $these_args ; + breaksw; + case 5 : + mri_rpn_math -out tmp_sum '$1,$2,+,$3,+,$4,+,$5,+' $these_args ; + breaksw; + endsw + if ( -e sum.mri ) then + mri_rpn_math -out tmp2_sum '$1,$2,+' sum tmp_sum + mri_copy_dataset tmp2_sum sum + else + mri_copy_dataset tmp_sum sum + endif + mri_rpn_math -out mean '$1,'$count',/' sum + end + mri_destroy_dataset sum + mri_copy_dataset mean $homedir/mean_${ds_type} + + endif + +end + +# Clean up +echo '######## Cleaning up #######' +cd $homedir +rm -r $tmpdir + +# And that's it. +echo '######## Done! #######' Index: src/csh/make_phase_cine.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/make_phase_cine.csh,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- src/csh/make_phase_cine.csh 9 Sep 2003 16:25:45 -0000 1.6 +++ src/csh/make_phase_cine.csh 11 Dec 2003 21:37:29 -0000 1.7 @@ -1,4 +1,4 @@ -#! /bin/csh -ef +#! /bin/csh -f # make_phase_cine.csh #/************************************************************ # * * @@ -28,7 +28,7 @@ # ************************************************************/ # echo '#'`date` $0 -echo '# $Id: make_phase_cine.csh,v 1.6 2003/09/09 16:25:45 bakalj Exp $' +echo '# $Id: make_phase_cine.csh,v 1.7 2003/12/11 21:37:29 welling Exp $' # # This script generates a cine loop from a (v)xyzt dataset. # The one argument is the name of a single scalar dataset file. Index: src/csh/makeps.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/makeps.csh,v retrieving revision 1.20 retrieving revision 1.21 diff -a -u -r1.20 -r1.21 --- src/csh/makeps.csh 18 Sep 2003 01:46:10 -0000 1.20 +++ src/csh/makeps.csh 11 Dec 2003 23:53:50 -0000 1.21 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -echo '#$Id: makeps.csh,v 1.20 2003/09/18 01:46:10 welling Exp $' +echo '#$Id: makeps.csh,v 1.21 2003/12/11 23:53:50 welling Exp $' echo '#'`date`$0 cd stat # convert means to postscript @@ -78,6 +78,48 @@ rm Pmapdummy.mri endif +# +# Threshold Tmaps to select a given number of voxels if requested. +# +if ( ${?F_PICKN_COUNT} ) then + set twotailed = 0 + set titlestr = "$F_PICKN_COUNT vox left tail" + if ( ${?F_PICKN_TWOTAILED} ) then + if ( ${F_PICKN_TWOTAILED} ) then + set twotailed = 1 + set titlestr = "$F_PICKN_COUNT vox either tail" + endif + endif + + echo "This is a placeholder" > Tmapdummy.mri + foreach i (Tmap*.mri) + if ( $i != Tmapdummy.mri && $i !~ *_?.mri ) then + set b = $i:t + set j = $b:r + if ( $twotailed ) then + set val = `pick_n_voxels.py -T --twotails $F_PICKN_COUNT $j` + set hival = `python -c "print repr(-1*${val})"` + echo "# Picking $F_PICKN_COUNT implies thresholding $j at T<$val or T>$hival" + overlay.csh -inmap $j.mri -inimage ${backImg} \ + -headerout ${j}_n.mri \ + -lowthresh $val -highthresh $hival \ + -mingray 64 -maxgray 191 + else + set val = `pick_n_voxels.py -T $F_PICKN_COUNT $j` + echo "# Picking $F_PICKN_COUNT implies thresholding $j at T<$val " + overlay.csh -inmap $j.mri -inimage ${backImg} \ + -headerout ${j}_n.mri \ + -lowthresh $val -highthresh 10000 \ + -mingray 64 -maxgray 191 + endif + setenv F_PS_TITLE2 "$j $titlestr" + ${F_MRI_TO_PS} ${j}_n + mv ${j}_n*.ps ../ps + endif + end + rm Tmapdummy.mri + +endif # # convert p maps to postscript Index: src/csh/map_name.py =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/map_name.py,v retrieving revision 1.7 retrieving revision 1.8 diff -a -u -r1.7 -r1.8 --- src/csh/map_name.py 28 Oct 2003 00:03:04 -0000 1.7 +++ src/csh/map_name.py 16 Apr 2004 23:05:13 -0000 1.8 @@ -15,6 +15,9 @@ # Maximum mapping depth maxDepth= 20; +# What characters delimit strings? +delimiters = ['$','@'] + # Dictionary of group directories; starts empty defaultDict= { }; mapDict= {"-":defaultDict }; @@ -145,6 +148,15 @@ if key != termKey: dict[key]= val +def hasDelimPairs( term ): + for c in delimiters: + brk= string.find(term,c) + if brk>=0: + brk2= string.find(term[brk+1:],c) + if brk2>=0: + return 1 + return 0 + def defineTerm( dict, term ): if verbose: print "defining term <%s>"%term @@ -159,30 +171,36 @@ maybeExpandDictionary(dict,"-",val) def recursiveMap( dict, term, lvl ): + mappingPass= 1 if lvl>maxDepth: - raise RuntimeError,"Recursion too deep mapping %s"%term; + raise RuntimeError,"Recursion too deep mapping %s"%term; if verbose: - print "recursively mapping <%s>"%term; - brk1= string.find( term, "$" ); - if brk1>=0: - brk2= string.find(term[brk1+1:], "$"); - if brk2<=0: - raise RuntimeError,"Unmatched $ in %s"%term; - else: - brk2= brk1 + brk2 + 1; # relative to start of term - mapResult1= recursiveMap(dict,term[brk1+1:brk2],lvl+1) - mapResult2= recursiveMap(dict,term[brk2+1:],lvl+1) - maybeExpandDictionary(dict,term[brk1+1:brk2],mapResult1) - maybeExpandDictionary(dict,term[brk2+1:],mapResult2) - result= term[0:brk1]+ mapResult1 + mapResult2 - else: - if dict.has_key(term): - result= recursiveMap(dict,dict[term],lvl+1); - maybeExpandDictionary(dict,term,result) - else: - result= term; + print "recursively mapping <%s> at level %d"%(term,lvl); + result= term + while hasDelimPairs(result): + for c in delimiters: + brk1= string.find( result, c ); + if brk1>=0: + brk2= string.find(result[brk1+1:], c); + if brk2<=0: + if lvl == 0: + raise RuntimeError,"Unmatched %s in %s"%(c,result); + else: + brk2= brk1 + brk2 + 1; # relative to start of result + mapResult1= recursiveMap(dict,result[brk1+1:brk2],lvl+1) + mapResult2= recursiveMap(dict,result[brk2+1:],lvl+1) + maybeExpandDictionary(dict,result[brk1+1:brk2],mapResult1) + maybeExpandDictionary(dict,result[brk2+1:],mapResult2) + result= result[0:brk1]+ mapResult1 + mapResult2 + if verbose: + print "level %d pass %d: <%s> has become <%s>"%\ + (lvl,mappingPass,term,result) + mappingPass= mappingPass+1 + if dict.has_key(result): + result= recursiveMap(dict,dict[term],lvl+1); + maybeExpandDictionary(dict,term,result) if verbose: - print "mapped <%s> to <%s>"%(term,result) + print "mapped <%s> to <%s> at level %d"%(term,result,lvl) return result def describeSelf(): @@ -240,7 +258,7 @@ "default", adding any key:value pairs from the command line, and finally adding any definitions from the dictionary the name of which matches mainkey. The target is then repeatedly mapped through this -dictionary, replacing the whole target or any part delimited by '$' +dictionary, replacing the whole target or any part delimited by '$' or '@' characters with the corresponding value. The string which ultimately results is the output. Index: src/csh/merge_stats.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/merge_stats.csh,v retrieving revision 1.8 retrieving revision 1.9 diff -a -u -r1.8 -r1.9 --- src/csh/merge_stats.csh 4 Oct 2003 22:06:08 -0000 1.8 +++ src/csh/merge_stats.csh 8 Apr 2004 22:21:36 -0000 1.9 @@ -59,7 +59,7 @@ set parfile = merged/par/reg3d_${dirname}.par estireg3d -xvoxel ${F_XVOXEL} -yvoxel ${F_YVOXEL} -zvoxel ${F_ZVOXEL} \ -input $align_this -align $alignto -stdv $alignto_stdv \ - -parameters $parfile + -parameters $parfile foreach statfile ( ${dirname}/stat/*.mri ) if (( $statfile !~ *_?.mri ) || ( $statfile =~ *Mean*.mri ) \ || ( $statfile =~ *Stdv*.mri )) then Index: src/csh/multi_runner.py =================================================================== RCS file: src/csh/multi_runner.py diff -N src/csh/multi_runner.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/multi_runner.py 10 Mar 2004 23:48:41 -0000 1.3 @@ -0,0 +1,190 @@ +#! /usr/bin/env python +# + +import sys +import os +import os.path +import string +import getopt +import urllib +import re +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: multi_runner.py,v 1.3 2004/03/10 23:48:41 welling Exp $" + +db_uname= None +db_passwd= None +tagString= None +infileName= None +srcDir= None +destSubdir= None + +pfileRegex= re.compile('P(\d+)\.(\d)') + +runList= [] + +def getpass(prompt = "Password: "): + import termios, sys + fd = sys.stdin.fileno() + old = termios.tcgetattr(fd) + new = termios.tcgetattr(fd) + new[3] = new[3] & ~termios.ECHO # lflags + try: + termios.tcsetattr(fd, termios.TCSADRAIN, new) + passwd = raw_input(prompt) + termios.tcsetattr(fd, termios.TCSADRAIN, old) + print("") + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old) + return passwd + +def makeAnalysisPath(spec): + global destSubdir + id, task, runnum= spec + return "/home/YODA/roushre/ANALYSIS/%02d/%s_%d/%s"%\ + (id,task,runnum,destSubdir) + +def makeDataPath(spec): + id, task, runnum= spec + return "/home/YODA/roushre/DATA/Pfiles/%02d/%s_%d"%(id,task,runnum) + +def buildAndCheckAnalysis( path, spec ): + global db_passwd, srcDir, tagString + id, task, runnum= spec + statusFlag= 1 + Message("Checking %d %s %d"%spec) + dataDir= makeDataPath(spec) + if not os.access( dataDir, os.R_OK ): + Message("Input data directory %s does not exist!"%dataDir) + return 0 + pfilesFound= 0 + for f in os.listdir(dataDir): + if pfileRegex.match(f): + pfilesFound= 1 + break + if not pfilesFound: + Message("No Pfiles found in %s!"%dataDir) + return 0 + if os.access( path, os.F_OK ): + Message("%s already exists!"%path) + return 0 + try: + os.makedirs(path) + except OSError, s: + Message("Error creating %s: %s!"%(path,s)) + homeDir= os.getcwd() + try: + os.chdir(path) + os.environ['F_DB_PASSWD']= db_passwd + argStr= "--src=%s db_uname=%s subj=%d runnum=%d task=%s tag=%s"%\ + (srcDir,db_uname,id,runnum,task,tagString) + for fname in [ "spiral.local.csh", "spiral.steps.csh", \ + "fiasco.local.csh" ]: + safeRun("customize_local.py %s %s"%(argStr,fname)) + except: + Message("An error occurred while customizing files in %s!"%path) + statusFlag= 0 + os.chdir(homeDir) + return statusFlag + +def doFiascoRun( spec ): + id, task, runnum= spec + path= makeAnalysisPath(spec) + Message("Executing %d %s %d in %s"%(id,task,runnum,path)) + homedir= os.getcwd() + try: + os.chdir(path) + safeRun("FIASCO spiral") + Message("This run succeeded.") + except: + Message("This run failed!") + os.chdir(homedir) + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ) + else: + os.system( "scripthelp %s"%sys.argv[0] ) + sys.exit() + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",\ + ["src=","db_uname=","db_passwd=","tag=",\ + "infile=","dest="]) + +except: + errorMessage("%s: Invalid command line parameter" % sys.argv[0]) + describeSelf() + sys.exit(1) + +Message(idString) + +# Parse args +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--src": + srcDir= b + if a=="--db_uname": + db_uname= b + if a=="--db_passwd": + db_passwd= b + if a=="--tag": + tagString= b + if a=="--infile": + infileName= b + if a=="--dest": + destSubdir= b + +while db_uname==None or len(db_uname)==0: + db_uname= raw_input("Database Username: ") +while db_passwd==None or len(db_passwd)==0: + db_passwd= getpass("Database Password: ") +while tagString==None or len(tagString)==0: + tagString= raw_input("Tag for this run (e.g. Analysis#12): ") +if srcDir==None: + srcDir= raw_input("Source directory (defaults to FIASCO): ") +if srcDir[0] != '/': + srcDir= os.path.join(os.getcwd(),srcDir) +while destSubdir==None or len(destSubdir)==0: + destSubdir= raw_input("Destination subdirectory (e.g. auto_7): ") +if destSubdir[0]=='/': + sys.exit("Destination subdirectory must be a 1-word relative path!") +while infileName==None or len(infileName)==0 \ + or not os.access(infileName,os.R_OK): + infileName= raw_input("Table file name: ") + +infile= file(infileName,"r") +lines= infile.readlines() +infile.close() + +for line in lines: + line= string.strip(line) + if len(line) == 0: + continue + if line[0]=='#': + continue # this is a comment + idStr,task,runnumStr = string.split(line) + id= int(idStr) + runnum= int(runnumStr) + spec= (id, task, runnum) + workPath= makeAnalysisPath(spec) + if buildAndCheckAnalysis( workPath, spec ): + runList.append( spec ) + +for spec in runList: + doFiascoRun(spec) + +print('######## All Finished! ########') Index: src/csh/normalization.csh =================================================================== RCS file: src/csh/normalization.csh diff -N src/csh/normalization.csh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/normalization.csh 4 May 2004 21:32:11 -0000 1.3 @@ -0,0 +1,104 @@ +#!/bin/csh -ef +# normalization.csh +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1995 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# * Original programming by Bill Eddy * +# ************************************************************/ +# +echo '#'`date` $0 +echo '#$Id: normalization.csh,v 1.3 2004/05/04 21:32:11 welling Exp $' + +set normscript = "generated_scripts/apply_normalize.gen_csh" +set coregscript = "generated_scripts/apply_coreg_inplane.gen_csh" + +# Do we have the necessary info +if ( ! -e ${1}.mri ) then + echo "Normalization prototype does not exist!" + exit -1 +endif +if ( ! -e $coregscript ) then + echo "Coregistration information is missing!" + exit -1 +endif + +# Check needed dirs +if ( ! -d coregistered_func) mkdir coregistered_func +if ( ! -d generated_scripts) mkdir generated_scripts + +# Build the generated normalization script +normalize_prep.py -v --oscript $normscript $1 + +# Make separate counts by condition, generating a list of files to +# normalize in the process. +pushd stat > /dev/null +set meanList = () +set stdvList = () +set countsList = () +foreach ds ( Mean_*.mri ) + set meanList = ( $meanList ${ds:r} ) + set counts_name = `echo ${ds:r} | sed 's/Mean/Counts/g'` + set countsList = ( $countsList $counts_name ) + set stdv_name = `echo ${ds:r} | sed 's/Mean/Stdv/g'` + set stdvList = ( $stdvList $stdv_name ) + mri_copy_chunk -chunk counts -chunk_out images -chunk_file .dat $ds nrm_tmp_1 + mri_remap -order xyz nrm_tmp_1 + mri_interp -constant -d x -len 64 nrm_tmp_1 nrm_tmp_2 + mri_interp -constant -d y -len 64 nrm_tmp_2 nrm_tmp_3 + mri_rpn_math -out $counts_name '$2' $ds nrm_tmp_3 + mri_destroy_dataset nrm_tmp_1 + mri_destroy_dataset nrm_tmp_2 + mri_destroy_dataset nrm_tmp_3 +end +popd > /dev/null + +# Normalize appropriate files +set dsList = ( GrandMean GrandStdv $meanList $stdvList $countsList ) +foreach ds ( $dsList ) + set stat_ds = stat/${ds:r} + set aligned_ds = coregistered_func/aligned_${ds:r} + set norm_ds = normalized_func/norm_${ds:r} + if ( ! -e ${stat_ds}.mri ) then + echo "$stat_ds does not exist; skipping!" + continue + else + echo "Processing $stat_ds" + endif + set needs_align = 0 + if ( ! -e ${aligned_ds}.mri ) then + set needs_align = 1 + else + set test_newer = \ + `test_in_subshell.csh test_newer.csh ${aligned_ds}.mri ${stat_ds}.mri` + if ( $test_newer ) set needs_align = 1 + endif + if ( $needs_align ) then + echo "Coregistering $ds" + $coregscript $stat_ds $aligned_ds tmp_normalization > /dev/null + mri_destroy_dataset tmp_normalization + endif + echo "Normalizing $ds" + $normscript $aligned_ds $norm_ds > /dev/null +end + Index: src/csh/normalize_prep.py =================================================================== RCS file: src/csh/normalize_prep.py diff -N src/csh/normalize_prep.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/normalize_prep.py 4 May 2004 21:32:11 -0000 1.4 @@ -0,0 +1,200 @@ +#! /usr/bin/env python +# +################# +# Notes- +# -afniTest needs to check for presence of adwarp in path! +################# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: normalize_prep.py,v 1.4 2004/05/04 21:32:11 welling Exp $" + +afniNormalizeCmd= "adwarp" + +afniGeneratedScript="""\ +#!/bin/csh -f +# +# This is an automatically generated script! It's only good +# for this particular special case. Don't copy it around or +# edit it unless you *really* know what you're doing! +# +# Switches: (must appear first) +# -anat : treat input as anatomical rather than functional +# +# Inputs: (after any switches) +# $1: input functional MRI dataset +# $2: output normalized functional MRI dataset +# +set typeflag = '-func' +if ( $1 == '-anat' ) then + shift args + set typeflag = '-anat' +endif +set prototype = %s +if ( ! -e ${prototype}.mri ) then + echo "Expected prototype file ${prototype}.mri not found!" + exit -1 +endif +set afni_proto = ${prototype}+tlrc +set up_to_date = 1 +if ( ! -e ${afni_proto}.HEAD ) set up_to_date = 0 +if ( { test_newer.csh ${prototype}.mri ${afni_proto}.HEAD } ) then + set up_to_date = 0 +endif +if ( ! $up_to_date ) then + pghtoafni -anat $prototype $afni_proto +endif +pghtoafni $typeflag $1 tmp_normalize+orig +%s -func NN -apar ${afni_proto} -dpar tmp_normalize+orig +smartreader -input tmp_normalize+tlrc.HEAD -out $2 +rm tmp_normalize+orig.HEAD tmp_normalize+orig.BRIK +rm tmp_normalize+tlrc.HEAD tmp_normalize+tlrc.BRIK + +""" + +def generalPrep(): + global homedir + path1= os.path.join(homedir,'normalized_anat') + path2= os.path.join(homedir,'normalized_func') + for path in [ path1, path2 ]: + if not os.access(path,os.W_OK): + os.makedirs(path) + +def afniPrep(inFname): + global homedir + global tmpdir + global oscript + + checkExeFound(afniNormalizeCmd,'AFNI') + + baseName= os.path.basename(inFname) + headName= inFname+'+tlrc.HEAD' + origName= "%s+orig"%baseName + warpName= "%s_tlrc"%baseName + finalName= os.path.join(homedir,"normalized_anat","norm_%s"%baseName) + safeRun("pghtoafni -anat %s %s"%(inFname,os.path.join(tmpdir,origName))) + os.chdir(tmpdir) + safeRun("%s -apar %s -dpar %s -prefix %s"%\ + (afniNormalizeCmd,os.path.join(homedir,headName),\ + origName,os.path.basename(warpName))) + safeRun("smartreader -i %s+tlrc.HEAD -out %s"%(warpName,finalName)) + # Now we write a shell script that implements this transformation. + scriptName= os.path.join(homedir,oscript); + ofile= open(scriptName,"w") + ofile.write(afniGeneratedScript%(finalName,afniNormalizeCmd)) + ofile.close() + safeRun("chmod u+x %s"%scriptName) + +def afniTest( inFname ): + # If there is a file with that name + '+tlrc.HEAD', they're + # using AFNI methods. + headFname= inFname+'+tlrc.HEAD' + if os.access(headFname,os.R_OK): + return 1; + else: + return 0; + +methodList= [(afniTest, afniPrep)] # we'll have more someday + +################# +# +# Main +# +################# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: normalize_prep.py,v 1.4 2004/05/04 21:32:11 welling Exp $" + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",["oscript="]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 1 : + describeSelf() + sys.exit(1) + +oscript= "apply_normalize.gen_csh" +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="--oscript": + oscript= b + +inFname= pargs[0] +inDS= MRIDataset(inFname) +inChunk= inDS.getChunk('images') + +#Check reasonableness of input +dimstr= inChunk.getValue('dimensions'); +if dimstr != "xyz": + if dimstr == "xyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +# Create a temporary directory +tmpdir= makeTempDir('tmp_normalize_prep') +homedir= os.getcwd() + +# General setup +generalPrep() + +# Figure out what game we're playing +done= 0 +for test, mthd in methodList: + if test(inFname): + try: + mthd(inFname) + done= 1 + except Exception, inst: + sys.exit("Cannot normalize from %s: %s"%(inFname,inst)) +if not done: + sys.exit("Cannot normalize from %s: can't find needed inputs"%inFname) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/parallel.PVM_finish.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/parallel.PVM_finish.csh,v retrieving revision 1.1 retrieving revision 1.2 diff -a -u -r1.1 -r1.2 --- src/csh/parallel.PVM_finish.csh 18 Jul 2003 21:27:59 -0000 1.1 +++ src/csh/parallel.PVM_finish.csh 24 Feb 2004 23:50:01 -0000 1.2 @@ -26,7 +26,7 @@ # * Original programming by Nigel Goddard & Greg Hood (PSC) * # ************************************************************/ # -# $Id: parallel.PVM_finish.csh,v 1.1 2003/07/18 21:27:59 welling Exp $ +# $Id: parallel.PVM_finish.csh,v 1.2 2004/02/24 23:50:01 welling Exp $ echo '#'`date` $0 #---------------------------------------------------------------------------* @@ -49,11 +49,16 @@ # clean up old PVM log files echo "cleaning log files from the hosts" + if ( ${?PVM_RSH} ) then + set my_rsh = $PVM_RSH + else + set my_rsh = rsh + endif foreach m ($F_PARALLEL_HOSTS) set hname = `echo $m | awk -F: '{print $1}'` echo " cleaning logs from $hname" - set d = `(${PVM_RSH} $hname "ls -l /tmp" 1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vdTPF",["mask=","twotails"]) +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 2 : + describeSelf() + sys.exit(1) + +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + if a=="-T": + tFlag= 1 + if a=="-P": + pFlag= 1 + if a=="-F": + fFlag= 1 + if a=="--mask": + maskDS= MRIDataset(b) + maskChunk= maskDS.getChunk('images') + if a=="--twotails": + foldFlag= 1 + +nTypeFlags= tFlag + pFlag + fFlag +if nTypeFlags == 0: + sys.exit("Either -T, -P, or -F must be specified!") + +if nTypeFlags>1: + sys.exit("Only specify one of -T, -P, or -F!") + +if fFlag and foldFlag: + sys.exit("The --twotails flag is incompatible with -F!"); + +nVox= string.atoi(pargs[0]) +inDS= MRIDataset(pargs[1]) +inChunk= inDS.getChunk('images') + +#Make up a temporary directory +tmpdir= makeTempDir('tmp_pickn') +homedir= os.getcwd() + +#Get relevant dimensions +xdim= inChunk.getDim("x"); +ydim= inChunk.getDim("y"); +zdim= inChunk.getDim("z"); +totpix= xdim*ydim*zdim +dimstr= inChunk.getValue('dimensions'); + +#Check reasonableness of input +if dimstr != "xyz": + if dimstr == "xyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") +if maskChunk != None: + if maskChunk.getValue('dimensions') != dimstr: + sys.exit("Dimension order of mask doesn't match that of input!") + for dim in ['v', 'x', 'y', 'z', 't']: + if maskChunk.hasValue(dim): + if maskChunk.getDim(dim) != inChunk.getDim(dim): + sys.exit("%s extent of mask doesn't match that of input!"%dim) + +#Generate sorted file +os.chdir(tmpdir) +if maskDS == None: + if foldFlag: + if pFlag: # Pmap case + safeRun("mri_rpn_math -out unsorted '1.0,$1,-,$1,dup,0.5,>,if_keep' %s"%\ + os.path.join(homedir,inDS.fname)) + elif tFlag: # Tmap case + safeRun("mri_rpn_math -out unsorted '$1,-1,1,$1,0.0,>,if_keep,*' %s"%\ + os.path.join(homedir,inDS.fname)) + else: # Fmap case + sys.exit("Unexpectedly tried to fold an Fmap!") + else: + safeRun("mri_copy_chunk -chunk images -replace %s unsorted"%os.path.join(homedir,inDS.fname)) +else: + if foldFlag: + if pFlag: # Pmap case + safeRun("mri_rpn_math -out unsorted '1.0,$1,-,$1,dup,0.5,>,if_keep,1.0,$2,0,==,if_keep' %s %s"%\ + (os.path.join(homedir,inDS.fname),\ + os.path.join(homedir,maskDS.fname))) + elif tFlag: # Tmap case + safeRun("mri_rpn_math -out unsorted '$1,-1,1,$1,0.0,>,if_keep,*,0.0,$2,0,==,if_keep' %s %s"%\ + (os.path.join(homedir,inDS.fname),\ + os.path.join(homedir,maskDS.fname))) + else: # Fmap case + sys.exit("Unexpectedly tried to fold an Fmap!") + else: + if pFlag: # Pmap case + safeRun("mri_rpn_math -out unsorted '$1,1.0,$2,0,==,if_keep' %s %s"%\ + (os.path.join(homedir,inDS.fname),\ + os.path.join(homedir,maskDS.fname))) + elif tFlag: # Tmap case + safeRun("mri_rpn_math -out unsorted '$1,0.0,$2,0,==,if_keep' %s %s"%\ + (os.path.join(homedir,inDS.fname),\ + os.path.join(homedir,maskDS.fname))) + else: # Fmap case + safeRun("mri_rpn_math -out unsorted '$1,0.0,$2,0,==,if_keep' %s %s"%\ + (os.path.join(homedir,inDS.fname),\ + os.path.join(homedir,maskDS.fname))) + + +safeRun("mri_remap -chunk images -order vq -length 1:%d unsorted"%totpix) +if fFlag: + safeRun("mri_sort unsorted sorted") # get right tail +else: + safeRun("mri_sort -asc unsorted sorted") # get left tail +safeRun("mri_subset -d q -len 1 -s %d sorted selected"%(nVox-1)) +vals= readCmdOutputToList("mri_rpn_math -out junk '0,$1,1,if_print_1' selected") +thresh= string.atof(vals[0]) +print repr(thresh) + +# Clean up +os.chdir(homedir) +removeTmpDir(tmpdir) + + Index: src/csh/rename_siemens.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/rename_siemens.csh,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- src/csh/rename_siemens.csh 25 Apr 2003 22:27:53 -0000 1.6 +++ src/csh/rename_siemens.csh 28 Jan 2004 00:30:42 -0000 1.7 @@ -15,34 +15,59 @@ echo $nfiles 'is too many for me to deal with!' exit -1 endif - set ind = 1 - while ( $ind <= $nfiles ) + set time = 1 + while ( $nfiles > 0 ) set nonomatch foreach pad ( '' '0' '00' '000' failure ) if ( $pad == failure ) then - echo Unable to find file for sequence $seqnum time $ind + echo Unable to find files for sequence $seqnum time $time exit -1 endif - set oldname = ( ${seqnum}-${pad}${ind}-*.dcm ) - if ( ${#oldname} != 1 ) then - echo "Unexpected file naming pattern " $oldname - exit -1 - endif - set oldname = ${oldname[1]} - if ( $oldname != ${seqnum}-${pad}${ind}-\*.dcm ) break + set files_this_time = ( ${seqnum}-${pad}${time}-*.dcm ) + if ( "$files_this_time" != ${seqnum}-${pad}${time}-\*.dcm ) break end - if ( $ind < 10 ) then - set istring = "000"$ind - else if ( $ind < 100 ) then - set istring = "00"$ind - else if ( $ind < 1000 ) then - set istring = "0"$ind + set num_slices = ${#files_this_time} + if ( $time < 10 ) then + set timestring = "000"$time + else if ( $time < 100 ) then + set timestring = "00"$time + else if ( $time < 1000 ) then + set timestring = "0"$time else - set istring = $ind + set timestring = $time endif - set newname = "file_"${seqnum}_${istring}.dcm - ln -s $oldname $newname - @ ind = $ind + 1 + if ( $num_slices == 1 ) then + set newname = "file_"${seqnum}_${timestring}.dcm + set oldname = ${files_this_time} + if ( ! -e $oldname ) then + echo Cannot find file $oldname ! + exit -1 + endif + ln -s $oldname $newname + else + set slice = 1 + while ( $slice <= $num_slices ) + if ( $slice < 10 ) then + set slicestring = "000"$slice + else if ( $slice < 100 ) then + set slicestring = "00"$slice + else if ( $slice < 1000 ) then + set slicestring = "0"$slice + else + set slicestring = $slice + endif + set oldname = ${seqnum}-${time}-${slice}.dcm + set newname = "file_"${seqnum}_${timestring}_${slicestring}.dcm + if ( ! -e $oldname ) then + echo Cannot find file $oldname ! + exit -1 + endif + ln -s $oldname $newname + @ slice = $slice + 1 + end + endif + @ nfiles = $nfiles - $num_slices + @ time = $time + 1 end endif end Index: src/csh/renumber_ifiles.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/renumber_ifiles.csh,v retrieving revision 1.3 retrieving revision 1.4 diff -a -u -r1.3 -r1.4 --- src/csh/renumber_ifiles.csh 12 Sep 2003 15:03:13 -0000 1.3 +++ src/csh/renumber_ifiles.csh 10 Mar 2004 23:47:52 -0000 1.4 @@ -1,4 +1,4 @@ -#!/bin/csh -f +#!/bin/csh -fx # renumber_ifiles.csh #/************************************************************ # * * @@ -27,63 +27,9 @@ # ************************************************************/ # echo '#'`date` $0 -echo '# $Id: renumber_ifiles.csh,v 1.3 2003/09/12 15:03:13 bakalj Exp $' +echo '# $Id: renumber_ifiles.csh,v 1.4 2004/03/10 23:47:52 welling Exp $' + +# This script has been converted to Python to work around some portability +# issues. +renumber_ifiles.py -foreach series ( 1 2 3 4 5 6 7 8 9 ) - if ( -d 00${series} ) then - set newdir = "series"${series}"_links" - set count = 0 - foreach block ( 00 02 04 06 08 10 01 03 05 07 09 ) - set subdir = ${block}${series} - if ( -d $subdir ) then - if ( -e $subdir/I.+++.gz || -e $subdir/I.+++.Z || -e $subdir/I.+++ ) \ - then - echo 'Found an I.+++ file in '$subdir'; failing!' - exit -1 - endif - touch $subdir/I.+++.gz - set fnames = `ls -S -r $subdir/I.???.gz` - rm $subdir/I.+++.gz - shift fnames - if ( ${#fnames} ) then - echo "Uncompressing files in ${subdir}" - foreach fname ( ${fnames} ) - gunzip ${fname} - end - endif - touch $subdir/I.+++.Z - set fnames = `ls -S -r $subdir/I.???.Z` - rm $subdir/I.+++.Z - shift fnames - if ( ${#fnames} ) then - echo "Uncompressing files in ${subdir}" - foreach fname ( ${fnames} ) - uncompress ${fname} - end - endif - touch $subdir/I.+++ - set fnames = `ls -S -r $subdir/I.???` - rm $subdir/I.+++ - shift fnames - if ( ${#fnames} ) then - echo "Linking in files in ${subdir}" - if ( ! -d ${newdir} ) mkdir ${newdir} - foreach fname ( ${fnames} ) - if ( $count < 10 ) then - set newname = I.000${count} - else if ( $count < 100 ) then - set newname = I.00${count} - else if ( $count < 1000 ) then - set newname = I.0${count} - else - set newname = I.${count} - endif - ln -s ../${fname} ${newdir}/${newname} - @ count = ${count} + 1 - end - endif - endif - end - echo "Series ${series} contains ${count} images total" - endif -end Index: src/csh/renumber_ifiles.py =================================================================== RCS file: src/csh/renumber_ifiles.py diff -N src/csh/renumber_ifiles.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/renumber_ifiles.py 8 Apr 2004 22:21:36 -0000 1.2 @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# renumber_ifiles.py +#/************************************************************ +# * * +# * Permission is hereby granted to any individual or * +# * institution for use, copying, or redistribution of * +# * this code and associated documentation, provided * +# * that such code and documentation are not sold for * +# * profit and the following copyright notice is retained * +# * in the code and documentation: * +# * Copyright (c) 1995,1996 Department of Statistics, * +# * Carnegie Mellon University * +# * * +# * This program is distributed in the hope that it will * +# * be useful, but WITHOUT ANY WARRANTY; without even the * +# * implied warranty of MERCHANTABILITY or FITNESS FOR A * +# * PARTICULAR PURPOSE. Neither Carnegie Mellon University * +# * nor any of the authors assume any liability for * +# * damages, incidental or otherwise, caused by the * +# * installation or use of this software. * +# * * +# * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * +# * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * +# * FDA FOR ANY CLINICAL USE. * +# * * +# * * +# ************************************************************/ +# +import sys +import os +import os.path +import string +import getopt +import re +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= '# $Id: renumber_ifiles.py,v 1.2 2004/04/08 22:21:36 welling Exp $' + +ifileRegex= re.compile('I\.\d\d\d') +gzIfileRegex= re.compile('I\.\d\d\d\.gz') +zIfileRegex= re.compile('I\.\d\d\d\.Z') + +############################## +# +# Main +# +############################## + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ) + else: + os.system( "scripthelp %s"%sys.argv[0] ) + sys.exit() + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd",[]) +except: + errorMessage("%s: Invalid command line parameter" % sys.argv[0]) + describeSelf() + sys.exit(1) + +Message(idString) + +# Parse args +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + +for series in xrange(1,10): + if os.access("00%d"%series,os.R_OK): + newdir = "series%d_links"%series + os.mkdir(newdir) + count = 0 + for block in [ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9 ]: + subdir = "%02d%d"%(block,series) + uncompressMsgFlag= None + if os.access(subdir,os.R_OK): + fList= os.listdir(subdir); + fList.sort(); + for f in fList: + linkMe= None + if ifileRegex.match(f): + linkMe= f; + if gzIfileRegex.match(f): + if not uncompressMsgFlag: + Message("Uncompressing some files in %s"%subdir) + uncompressMsgFlag= 1 + safeRun("gunzip %s"%os.path.join(subdir,f)) + linkMe= f[:5] + if zIfileRegex.match(f): + if not uncompressMsgFlag: + Message("Uncompressing some files in %s"%subdir) + uncompressMsgFlag= 1 + safeRun("uncompress %s"%os.path.join(subdir,f)) + linkMe= f[:5] + if linkMe: + os.symlink(os.path.join("..",subdir,linkMe), + os.path.join(newdir,"I.%04d"%count)) + count= count+1 + Message("Series %s contains %d images total"%(series,count)) Index: src/csh/spiral.defaults.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/spiral.defaults.csh,v retrieving revision 1.36 retrieving revision 1.37 diff -a -u -r1.36 -r1.37 --- src/csh/spiral.defaults.csh 4 Oct 2003 21:44:43 -0000 1.36 +++ src/csh/spiral.defaults.csh 27 Mar 2004 01:41:25 -0000 1.37 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -echo '$Id: spiral.defaults.csh,v 1.36 2003/10/04 21:44:43 bakalj Exp $' +echo '$Id: spiral.defaults.csh,v 1.37 2004/03/27 01:41:25 welling Exp $' if(! -d in)mkdir in # # @@ -418,3 +418,42 @@ # setenv F_WATCHER_LOG out/watcher.log # +# +# Coregistration +# +# Pgh MRI dataset to be used as the prototype functional data for coreg +setenv F_CRG_FUNC stat/GrandMean +# +# name of the coregistered version of F_CRG_FUNC dataset +setenv F_CRG_FUNC_COREG aligned_GrandMean +# +# Input for smartreader to generate inplane anatomical data (unset by default) +setenv F_CRG_INPL_INPUT "" +# +# smartreader options for the inplane anatomical data +setenv F_CRG_INPL_OPTS "" +# +# name of the inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL inplane +# +# name of skull-stripped inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL_STRIPPED stripped_inplane +# +# Input for smartreader to generate axial anatomical data (unset by default) +setenv F_CRG_ANAT_INPUT "" +# +# smartreader options for the axial anatomical data +setenv F_CRG_ANAT_OPTS "" +# +# name of the axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT axial +# +# name of skull-stripped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_STRIPPED stripped_axial +# +# name of coregistered and warped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_COWARPED warped_axial +# +# name of coregistered, warped axial resampled to match inplanes +setenv F_CRG_ANAT_INPL warped_axial_resampled + Index: src/csh/spiral.local.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/spiral.local.csh,v retrieving revision 1.17 retrieving revision 1.19 diff -a -u -r1.17 -r1.19 --- src/csh/spiral.local.csh 24 Sep 2003 22:55:47 -0000 1.17 +++ src/csh/spiral.local.csh 27 Mar 2004 01:41:25 -0000 1.19 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -#$Id: spiral.local.csh,v 1.17 2003/09/24 22:55:47 welling Exp $ +#$Id: spiral.local.csh,v 1.19 2004/03/27 01:41:25 welling Exp $ # # @@ -49,11 +49,6 @@ # dataset name setenv F_HEADER sample_splx5 -# Other smartreader options. See the documentation for "smartreader"; -# these are generally not necessary. -# -setenv F_READER_OPTS "" - # # Description # @@ -69,7 +64,26 @@ # lengths of dimensions for reconstruction setenv F_SPIRAL_RESOLUTION 64 -# Voxel dimensions for the final reconstructed images. +# Other reader options. See the documentation for "smartreader"; +# some common flags include '-multi' and '-auxfile' +# +setenv F_READER_OPTS "" + +# If an axial anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_ANAT_INPUT "" +setenv F_CRG_ANAT_OPTS "" + +# If an inplane anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_INPL_INPUT "" +setenv F_CRG_INPL_OPTS "" + +# Voxel dimensions for the final reconstructed functional images. # F_ZVOXEL should include the slice separation! setenv F_XVOXEL 3.125 setenv F_YVOXEL 3.125 @@ -110,6 +124,13 @@ # to be generated, and will calculate and produce overlays with the # given false discovery rate. setenv F_LOWERQ 0.05 + +# Active voxel count threshold. Uncommenting the first line will cause +# Tmap overlays to be generated showing the N voxels with strongest +# activation. Uncommenting the second line will pick these voxels +# from both tails of the distribution, rather than just the left tail +#setenv F_PICKN_COUNT 200 +#setenv F_PICKN_TWOTAILED 1 # Uncomment the following line to prevent summary information from # this run being sent to Fiasco Headquarters. This summary info is Index: src/csh/spiral.reader.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/spiral.reader.csh,v retrieving revision 1.15 retrieving revision 1.16 diff -a -u -r1.15 -r1.16 --- src/csh/spiral.reader.csh 24 Sep 2003 23:30:30 -0000 1.15 +++ src/csh/spiral.reader.csh 3 Feb 2004 20:53:48 -0000 1.16 @@ -28,7 +28,7 @@ # ************************************************************/ # echo '#'`date` $0 -echo '#$Id: spiral.reader.csh,v 1.15 2003/09/24 23:30:30 welling Exp $' +echo '#$Id: spiral.reader.csh,v 1.16 2004/02/03 20:53:48 welling Exp $' if (-e $F_DIR/$F_REFP.Z) then set ref_pfile = $F_REFP.Z @@ -49,6 +49,7 @@ set ALLPFILES = `pfileorder $ref_pfile $PFILES` +set count = 0 foreach thispfile ( $ALLPFILES ) if ( $thispfile =~ *.Z || $thispfile =~ *.z || $thispfile =~ *.gz ) then @@ -72,9 +73,16 @@ -length :::${newtdim}:: ${1}_tmp0 endif + set tdim = `mri_printfield -field samples.extent.t ${1}_tmp0` + echo $count | mri_from_ascii -order t -length 1 -chunk acq_blocks acq + mri_interp -d t -len $tdim -constant acq acq_stretch + mri_destroy_dataset acq + if ( -e ${1}_tmp.mri ) then mri_copy_chunk -chunk samples ${1}_tmp0 ${1}_tmp1 + mri_copy_chunk -chunk acq_blocks acq_stretch ${1}_tmp1 mri_destroy_dataset ${1}_tmp0 + mri_destroy_dataset acq_stretch mri_paste -d t -out ${1}_tmp2 ${1}_samples ${1}_tmp1 mri_destroy_dataset ${1}_tmp1 foreach fname ( ${1}_tmp2.* ) @@ -84,11 +92,15 @@ mri_copy_dataset ${1}_tmp0 ${1}_tmp mri_delete_chunk -chunk samples ${1}_tmp mri_copy_chunk -chunk samples ${1}_tmp0 ${1}_samples + mri_copy_chunk -chunk acq_blocks acq_stretch ${1}_samples mri_destroy_dataset ${1}_tmp0 + mri_destroy_dataset acq_stretch endif + @ count = $count + 1 end mri_copy_chunk -chunk samples ${1}_samples ${1}_tmp +mri_copy_chunk -chunk acq_blocks -replace ${1}_samples ${1}_tmp mri_destroy_dataset ${1}_samples set tdim = `mri_printfield -field samples.extent.t ${1}_tmp` set zdim = `mri_printfield -field samples.extent.z ${1}_tmp` @@ -126,13 +138,16 @@ endif mri_destroy_dataset ${1}_tmp -# Do scan reordering if required +# Do scan reordering if required. Remapping acq_blocks prevents it +# from being folded. set reorder = `mri_printfield -field samples.reorder -nofail ${1}_p` if (${#reorder} != 0) then if (${reorder} != 0) then @ wdim = ${zdim} * ${tdim} mri_remap -chunk samples -order vpsct -length ::::${wdim} ${1}_p + mri_remap -chunk acq_blocks -order q -length $tdim ${1}_p mri_scan_fold -zdm ${zdim} -reorder TRUE ${1}_p ${1} + mri_remap -chunk acq_blocks -order t -length $tdim ${1} mri_destroy_dataset ${1}_p mri_setfield -field samples.reorder -value 0 ${1} endif Index: src/csh/strip_skull.py =================================================================== RCS file: src/csh/strip_skull.py diff -N src/csh/strip_skull.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/csh/strip_skull.py 1 Apr 2004 02:05:53 -0000 1.5 @@ -0,0 +1,140 @@ +#! /usr/bin/env python +# +################# +# Notes- +################# + +import sys +import os +import os.path +import string +import getopt +from math import * +if os.environ.has_key("FIASCO"): + sys.path.append(os.environ["FIASCO"]) +from fiasco_utils import * + +idString= "$Id: strip_skull.py,v 1.5 2004/04/01 02:05:53 welling Exp $" + +afniSkullStripCmd= "3dIntracranial" + +def afniSkullStrip( flags, inChunk, outFname ): + checkExeFound( afniSkullStripCmd, 'AFNI' ) + safeRun("pghtoafni -anat %s struct+orig"%inChunk.ds.fname) + safeRun("%s -anat struct+orig -prefix strippedStruct"%afniSkullStripCmd) + safeRun("smartreader -i strippedStruct+orig.HEAD -out %s"%outFname) + + # AFNI conversion screws up corners, since AFNI doesn't understand + # skewed slicing. Copy original FIASCO corners into the output. + for cnr in [ "tlf", "trf", "tlb", "trb", "blf", "brf", "blb", "brb", \ + "ctr"]: + if inChunk.hasValue( "%s.0"%cnr ) \ + and inChunk.hasValue( "%s.1"%cnr ) \ + and inChunk.hasValue( "%s.2"%cnr ): + safeRun("mri_setfield -field %s.%s -all012 -value ' %f,%f,%f' %s"%\ + (inChunk.name,cnr,\ + inChunk.getFloat("%s.0"%cnr), inChunk.getFloat("%s.1"%cnr),\ + inChunk.getFloat("%s.2"%cnr), outFname)) + else: + safeRun("mri_setfield -field %s.%s -all012 -delete %s"%\ + (inChunk.name,cnr,outFname)) + +def realityCheck(ch): + global tmpdir + xdim= ch.getDim('x') + ydim= ch.getDim('y') + zdim= ch.getDim('z') + totdim= xdim*ydim*zdim + safeRun("mri_copy_dataset %s copy"%ch.ds.fname) + safeRun("mri_remap -order q -length %d copy"%totdim) + safeRun("mri_subsample -d q -len 1 -max copy max") + safeRun("mri_subsample -d q -len 1 -min copy min") + lines= readCmdOutputToList("mri_rpn_math -out junk '0,$1,$2,-,1,if_print_1' max min") + range= float(lines[0]) + if range==0.0: + raise Exception("Stripped dataset is constant!") + +################# +# +# Main +# +################# + +# Check for "-help" +if len(sys.argv)>1: + if sys.argv[1] == "-help": + if len(sys.argv)>2: + os.system( "scripthelp %s %s"%(sys.argv[0],sys.argv[2]) ); + else: + os.system( "scripthelp %s"%sys.argv[0] ); + sys.exit(); + +try: + (opts,pargs) = getopt.getopt(sys.argv[1:],"vd") +except: + print "%s: Invalid command line parameter" % sys.argv[0] + describeSelf(); + sys.exit() + +#Check calling syntax; parse args +if len(pargs) != 2 : + describeSelf() + sys.exit(1) + +for a,b in opts: + if a=="-v": + setVerbose(1) + if a=="-d": + setDebug(1) + +inFname= os.path.abspath(pargs[0]) +outFname= os.path.abspath(pargs[1]) +inDS= MRIDataset(inFname) +inChunk= inDS.getChunk('images') + +#Check reasonableness of input +dimstr= inChunk.getValue('dimensions'); +if dimstr != "xyz": + if dimstr == "xyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + elif dimstr == "vxyzt": + if inChunk.getDim("t") != 1: + sys.exit("Input file must have t extent 1!") + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + elif dimstr == "vxyz": + if inChunk.getDim("v") != 1: + sys.exit("Input file must have v extent 1!") + else: + sys.exit("Input file must have dimensions (v)xyz(t)!") + +# Move to a temporary directory +tmpdir= makeTempDir('tmp_strip_skull') +homedir= os.getcwd() +os.chdir(tmpdir) + +flags= "" +if (getVerbose()): + flags= flags+"-v " + +if (getDebug()): + flags= flags+"-d " + +try: + afniSkullStrip(flags,inChunk,outFname) +except Exception, inst: + sys.exit("Cannot strip skull from %s: %s"%(inChunk.ds.fname,inst)) + +# Reality check. Bad output can cause timeconsuming problems down the line, +# so it's worthwhile to make sure things have been reasonably successful. +outDS= MRIDataset(outFname) +outChunk= outDS.getChunk("images") +realityCheck(outChunk) + +# Clean up +os.chdir(homedir) +if not getDebug(): + removeTmpDir(tmpdir) + + Index: src/csh/ts.defaults.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/ts.defaults.csh,v retrieving revision 1.42 retrieving revision 1.43 diff -a -u -r1.42 -r1.43 --- src/csh/ts.defaults.csh 23 May 2003 16:24:44 -0000 1.42 +++ src/csh/ts.defaults.csh 27 Mar 2004 01:41:25 -0000 1.43 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -echo '#$Id: ts.defaults.csh,v 1.42 2003/05/23 16:24:44 welling Exp $' +echo '#$Id: ts.defaults.csh,v 1.43 2004/03/27 01:41:25 welling Exp $' if(! -d in)mkdir in # # @@ -564,3 +564,41 @@ setenv F_FAKE_TMAPS 0 +# +# Coregistration +# +# Pgh MRI dataset to be used as the prototype functional data for coreg +setenv F_CRG_FUNC stat/GrandMean +# +# name of the coregistered version of F_CRG_FUNC dataset +setenv F_CRG_FUNC_COREG aligned_GrandMean +# +# Input for smartreader to generate inplane anatomical data (unset by default) +setenv F_CRG_INPL_INPUT "" +# +# smartreader options for the inplane anatomical data +setenv F_CRG_INPL_OPTS "" +# +# name of the inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL inplane +# +# name of skull-stripped inplane anatomical Pgh MRI dataset +setenv F_CRG_INPL_STRIPPED stripped_inplane +# +# Input for smartreader to generate axial anatomical data (unset by default) +setenv F_CRG_ANAT_INPUT "" +# +# smartreader options for the axial anatomical data +setenv F_CRG_ANAT_OPTS "" +# +# name of the axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT axial +# +# name of skull-stripped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_STRIPPED stripped_axial +# +# name of coregistered and warped axial anatomical Pgh MRI dataset +setenv F_CRG_ANAT_COWARPED warped_axial +# +# name of coregistered, warped axial resampled to match inplanes +setenv F_CRG_ANAT_INPL warped_axial_resampled Index: src/csh/ts.local.csh =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/csh/ts.local.csh,v retrieving revision 1.16 retrieving revision 1.17 diff -a -u -r1.16 -r1.17 --- src/csh/ts.local.csh 7 Mar 2003 23:00:13 -0000 1.16 +++ src/csh/ts.local.csh 27 Mar 2004 01:41:25 -0000 1.17 @@ -27,7 +27,7 @@ # * Original programming by Bill Eddy * # ************************************************************/ # -# $Id: ts.local.csh,v 1.16 2003/03/07 23:00:13 welling Exp $ +# $Id: ts.local.csh,v 1.17 2004/03/27 01:41:25 welling Exp $ # # @@ -60,23 +60,41 @@ setenv F_PHYS_WINDOW 0.1587 # -# Information describing the data format. If the input data is -# a Pfile, set F_READER_DIMS to "" . +# Information describing the data format. # # number of slices -setenv F_NSLICE 4 -# number of image pairs. Reader sees twice this many images. -setenv F_NIMAGE 11 -@ READER_IMAGES = 2 * $F_NIMAGE -# Lengths of input data dimensions. -# Modify the 128 below if partial k reduces number of k-space scans -setenv F_READER_DIMS "256 128 $F_NSLICE $READER_IMAGES" +setenv F_NSLICE 2 +# +# number of images +setenv F_NIMAGE 20 +# +# If this scan is in raw binary (.raw or .ra) form, you must complete +# the F_READER_DIMS field to specify input data dimensions. Otherwise, +# set the value to "" (empty quotes). If this is a raw binary partial-k +# scan modify the 64 in the dimensions to give the number of rows acquired. +# +setenv F_READER_DIMS "128 64 $F_NSLICE $F_NIMAGE" +# +# Other reader options. See the documentation for "smartreader"; +# some common flags include '-multi' and '-auxfile' # -# Other reader options. See the documentation for "reader"; -# these are generally only needed for Pfiles. setenv F_READER_OPTS "" -# Voxel dimensions. +# If an axial anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_ANAT_INPUT "" +setenv F_CRG_ANAT_OPTS "" + +# If an inplane anatomical dataset is available, complete +# the following lines. See the documentation for "smartreader" for +# possible entries in the OPTS line. +# +setenv F_CRG_INPL_INPUT "" +setenv F_CRG_INPL_OPTS "" + +# Voxel dimensions of the final reconstructed functional images. # F_ZVOXEL should include the slice separation! setenv F_XVOXEL 0.8 setenv F_YVOXEL 1.5 Index: src/displace/displace.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/displace/displace.c,v retrieving revision 1.8 retrieving revision 1.9 diff -a -u -r1.8 -r1.9 --- src/displace/displace.c 18 Sep 2003 18:17:34 -0000 1.8 +++ src/displace/displace.c 17 Dec 2003 22:56:40 -0000 1.9 @@ -50,7 +50,7 @@ #include "fmri.h" #include "stdcrg.h" -static char rcsid[] = "$Id: displace.c,v 1.8 2003/09/18 18:17:34 bakalj Exp $"; +static char rcsid[] = "$Id: displace.c,v 1.9 2003/12/17 22:56:40 welling Exp $"; #define KEYBUF_SIZE 512 @@ -297,7 +297,8 @@ } /* Calculate mean displacement and write to parameter file */ - sum /= weight_sum; + if (weight_sum != 0.0) + sum /= weight_sum; fprintf( ofp, "%15.9lf\n", sum ); } Index: src/displace3d/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/displace3d/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- src/displace3d/Makefile 29 May 2002 21:49:04 -0000 1.2 +++ src/displace3d/Makefile 17 Mar 2004 22:10:46 -0000 1.3 @@ -11,7 +11,7 @@ PKG = displace3d PKG_MAKEBINS = $(CB)/displace3d -PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg -lm +PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm LIBFILES= $L/libmri.a $L/libpar.a $L/libbio.a $L/libarray.a $L/libmisc.a \ $L/libacct.a Index: src/estireg/estireg.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/estireg/estireg.c,v retrieving revision 1.17 retrieving revision 1.18 diff -a -u -r1.17 -r1.18 --- src/estireg/estireg.c 18 Jul 2003 21:27:59 -0000 1.17 +++ src/estireg/estireg.c 1 Mar 2004 05:42:40 -0000 1.18 @@ -61,7 +61,7 @@ #include "acct.h" -static char rcsid[] = "$Id: estireg.c,v 1.17 2003/07/18 21:27:59 welling Exp $"; +static char rcsid[] = "$Id: estireg.c,v 1.18 2004/03/01 05:42:40 welling Exp $"; void smooth_image(); void regist(); @@ -596,7 +596,7 @@ &numpar, (float *) &start_vals, (float *) regpar, mseval, &stopping_val, (float *) (&scale), &steps_per_conv_check, &max_iter, &num_iter, &num_restart, &return_cond, &max_restart, - &tcrit_sqr); + &tcrit_sqr, NULL ); if (return_cond != 0) { if (return_cond==2) Warning(1,"estireg: Nelder-Mead convergence failed!\n"); @@ -614,7 +614,7 @@ /* Returns mean squared-error between (adjusted) fixed image */ /* and (adjusted) register image, the criterion to be */ /* minimized by the Nelder-Mead minization for registration */ -float mse( float par[3] ) +float mse( float par[3], void* userHook ) { RegPars tmppar; double sse; @@ -722,7 +722,7 @@ } -void restrt( float par[3] ) +void restrt( float par[3], void* userHook ) { long x, y; Index: src/estireg3d/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/estireg3d/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- src/estireg3d/Makefile 17 May 2000 21:32:07 -0000 1.2 +++ src/estireg3d/Makefile 17 Mar 2004 00:10:09 -0000 1.3 @@ -8,18 +8,18 @@ # PKG = estireg3d -PKG_MAKEBINS = $(CB)/estireg3d +PKG_MAKEBINS = $(CB)/estireg3d $(CB)/estiwarp PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm MAKEFILES= Makefile -CSOURCE= estireg3d.c -DOCFILES= estireg3d_help.help +CSOURCE= estireg3d.c estiwarp.c +DOCFILES= estireg3d_help.help estiwarp_help.help include ../Makefile.pkg LIBFILES= $L/libmri.a $L/libpar.a $L/libbio.a $L/libarray.a $L/libmisc.a \ - $L/libacct.a + $L/libacct.a $L/libfmri.a HDRS= fmri.h mri.h par.h bio.h misc.h acct.h stdcrg.h $O/estireg3d.o: estireg3d.c @@ -30,6 +30,15 @@ $(CB)/estireg3d: $O/estireg3d.o $O/estireg3d_help.o $(LIBFILES) $(SINGLE_HELP_LD) + +$O/estiwarp.o: estiwarp.c + $(CC_RULE) + +$O/estiwarp_help.o: estiwarp_help.help + $(HELP_RULE) + +$(CB)/estiwarp: $O/estiwarp.o $O/estiwarp_help.o $(LIBFILES) + $(SINGLE_HELP_LD) releaseprep: echo "no release prep from " `pwd` Index: src/estireg3d/estireg3d.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/estireg3d/estireg3d.c,v retrieving revision 1.30 retrieving revision 1.38 diff -a -u -r1.30 -r1.38 --- src/estireg3d/estireg3d.c 16 Sep 2003 19:33:40 -0000 1.30 +++ src/estireg3d/estireg3d.c 4 May 2004 21:32:50 -0000 1.38 @@ -49,7 +49,7 @@ #include "acct.h" -static char rcsid[] = "$Id: estireg3d.c,v 1.30 2003/09/16 19:33:40 welling Exp $"; +static char rcsid[] = "$Id: estireg3d.c,v 1.38 2004/05/04 21:32:50 welling Exp $"; /* Notes- @@ -57,6 +57,8 @@ typical fMRI displacements. */ +/* Maximum free parameters */ +#define MAX_DOF 6 /* Access for 3D arrays */ #define MEM_BCK(matrix,nx,ny,nz,x,y,z) matrix[((((z)*ny)+(y))*nx)+(x)] @@ -118,8 +120,10 @@ SearchMethod outer_search_method; /* used. Technically, the quality */ int smooth_flag; /* measure used by fshrot3d is also */ int inplane_flag; /* part of the algorithm in effect */ + int trans_only_flag; + int rot_only_flag; WeightMethod weight_method; - OptMethod opt_method; + Optimizer* opt; sm_type smoother_type; /* smoother options have to be */ float smoother_bandwidth; /* packaged separately so that */ @@ -147,8 +151,7 @@ Task t; Context c; Result r; -Smoother* smoother; /* really two different global variables, - one for the Master, one for the Slave */ +Smoother* smoother; /* GLOBAL VARIABLES FOR MASTER */ @@ -163,8 +166,10 @@ FComplex* raw_prerotated; FComplex* moved_image; char* check; +ScalarFunction* targetFunc= NULL; Quat prerotation; double preshift[3]; +unsigned char** missing= NULL; /* will hold missing info */ #ifdef never FILE* tp; #endif @@ -198,10 +203,9 @@ static void estAlignNone(RegPar3D* par); void smoothImageComplex(FComplex *image); static double calcChiSqr(); -static double mse(double* guess, int npar); -static void restrt(double* guess, int npar); -static float fmse(float* guess); -static void frestrt(float* guess); +static double mse(const double* guess, const int npar, void* userHook); +static void restrt(const double* guess, const int npar, void* userHook); +static void restrtMatched(const double* guess, const int npar, void* userHook); /* FORWARD DECLARATIONS - UTILITY */ void PackContext (); @@ -212,7 +216,7 @@ void UnpackResult (); #define DEFAULT_SEARCH_ALGORITHM \ - "nosmooth,noinplane,opt=praxis,weight=smoothalign,qual=ssqr,inner=shear4,outer=shear4" + "nosmooth,noinplane,norotonly,notransonly,opt=praxis,weight=smoothalign,qual=ssqr,inner=shear4,outer=shear4" /* Smallest standard deviation contributing to weighting. This * prevents numerical noise weights from overwhelming the signal. @@ -225,15 +229,36 @@ */ #define WEIGHT_FLOOR 0.0 - -static char* optMethodName( OptMethod mthd ) +static int getCurrentNDim() { - switch (mthd) { - case OPT_NELMIN: return "nelmin"; - case OPT_NELMIN_T: return "nelmin_t"; - case OPT_PRAXIS: return "praxis"; - case OPT_NONE: return "none"; - default: return NULL; + if (c.inplane_flag) { + /* minimize in-plane only */ + if (c.rot_only_flag) { + /* 1 degree of freedom */ + return 1; + } + else if (c.trans_only_flag) { + /* 2 degrees of freedom */ + return 2; + } + else { + /* 3 degrees of freedom */ + return 3; + } + } + else { + if (c.rot_only_flag) { + /* minimize on 3 degrees of freedom */ + return 3; + } + else if (c.trans_only_flag) { + /* minimize on 3 degrees of freedom */ + return 3; + } + else { + /* minimize on all 6 degrees of freedom */ + return 6; + } } } @@ -285,13 +310,31 @@ } } -static OptMethod parseOptMethod(char* s) +static Optimizer* parseOptMethod(char* s, const int ndim) { - if (!strcasecmp(s,"nelmin")) return OPT_NELMIN; - else if (!strcasecmp(s,"nelmin_t")) return OPT_NELMIN_T; - else if (!strcasecmp(s,"praxis")) return OPT_PRAXIS; - else if (!strcasecmp(s,"none")) return OPT_NONE; - else return OPT_INVALID; + /* Two-sided 95% T cutoffs for DF up to 20 */ + static float tcrit[]= + { 0.0, 12.706176098809, 4.30263617020413, + 3.18244545308107, 2.77644502408949, 2.57058182376418, + 2.44680441622004, 2.36457539633475, 2.30597941403506, + 2.26214359559273, 2.2281309162355, 2.20098027417758, + 2.17880969240071, 2.16036657035061, 2.14478525936996, + 2.13144854260425, 2.11990457994238, 2.10981505255424, + 2.10092165066567, 2.09302376167972, 2.08596322490106 + }; + + if (ndim> (sizeof(tcrit)/sizeof(float))-1) + Abort("%s: tcrit for %d degrees of freedom is not compiled in!\n", + c.progname, ndim); + + if (!strcasecmp(s,"nelmin")) + return createNelminOptimizer(0.02,1.0); + else if (!strcasecmp(s,"nelmin_t")) + return createNelminTOptimizer(0.02,1.0,tcrit[ndim]*tcrit[ndim]); + else if (!strcasecmp(s,"praxis")) + return createPraxisOptimizer(0.000001,0.1); + else if (!strcasecmp(s,"none")) return createNoneOptimizer(); + else return NULL; } static SearchMethod parseSearchMethod(char* s) @@ -441,9 +484,11 @@ c.outer_search_method= SEARCH_INVALID; c.smooth_flag= 0; c.inplane_flag= 0; + c.rot_only_flag= 0; + c.trans_only_flag= 0; smoother= NULL; c.weight_method= WEIGHT_INVALID; - c.opt_method= OPT_INVALID; + c.opt= NULL; if (!parseAlgString(DEFAULT_SEARCH_ALGORITHM)) /* set defaults */ Abort("%s: internal error: invalid default algorithm!\n",c.progname); if (!parseAlgString(search_string)) { @@ -717,11 +762,11 @@ saveRegParams( pf, &r.reg_pars, r.t ); } - static int parseAlgString(char* search_string) { char* work; char* tok; + char* optString= NULL; work= strdup(search_string); /* make guaranteed-writable copy */ tok= strtok(work, " ,+&:;"); @@ -738,9 +783,20 @@ else if (!strcasecmp(tok,"noinplane")) { c.inplane_flag= 0; } + else if (!strcasecmp(tok,"rotonly")) { + c.rot_only_flag= 1; + } + else if (!strcasecmp(tok,"norotonly")) { + c.rot_only_flag= 0; + } + else if (!strcasecmp(tok,"transonly")) { + c.trans_only_flag= 1; + } + else if (!strcasecmp(tok,"notransonly")) { + c.trans_only_flag= 0; + } else if (!strncasecmp(tok,"opt=",4)) { - if ((c.opt_method=parseOptMethod(tok+4))==OPT_INVALID) - { free(work); return 0; } + optString= strdup(tok+4); } else if (!strncasecmp(tok,"weight=",7)) { if ((c.weight_method=parseWeightMethod(tok+7))==WEIGHT_INVALID) @@ -764,6 +820,26 @@ tok= strtok(NULL, " ,+&:;"); } + /* We need to do this last, because the other elements of the + * algorithm effect the number of degrees of freedom, which + * in turn effects the optimizer. + */ + if (optString != NULL) { + if (c.opt) c.opt->destroySelf(c.opt); + c.opt= parseOptMethod(optString,getCurrentNDim()); + if (!c.opt) { + Abort("%s: internal error: unrecognized optimizer type <%s>!\n", + c.progname, optString); + } + c.opt->setDebugLevel(c.opt, c.debugLevel); + free(optString); + } + + /* This turns out to be a good place for a necessary reality check */ + if (getCurrentNDim()>MAX_DOF) + Abort("%s: algorithm implies %d dimensions, but compiled limit is %d!\n", + c.progname,getCurrentNDim(),MAX_DOF); + free(work); return 1; } @@ -794,12 +870,24 @@ offset += strlen(scratch); if (offset>=sizeof(result)-1) return result; + if (c.rot_only_flag) strcpy(scratch,"rotonly,"); + else strcpy(scratch,"norotonly,"); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + if (c.trans_only_flag) strcpy(scratch,"transonly,"); + else strcpy(scratch,"notransonly,"); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + sprintf(scratch,"weight=%s,",weightMethodName(c.weight_method)); strncat(result,scratch,sizeof(result)-(offset+1)); offset += strlen(scratch); if (offset>=sizeof(result)-1) return result; - sprintf(scratch,"opt=%s,",optMethodName(c.opt_method)); + sprintf(scratch,"opt=%s,",c.opt->getMethodName(c.opt)); strncat(result,scratch,sizeof(result)-(offset+1)); offset += strlen(scratch); if (offset>=sizeof(result)-1) return result; @@ -874,7 +962,7 @@ /* Were all of the required dims present? */ if (offset!=strlen(dims_required)-1) { Message( "%s: dataset <%s> doesn't include dimensions \"%s\"!\n", - c.progname, dims_required ); + c.progname, dsname, dims_required ); return 0; } @@ -1022,6 +1110,7 @@ fprintf(stderr, "input file in SC = %s\n", c.input_file); #endif sInput = mri_open_dataset( c.input_file, MRI_READ ); + missing= get_missing(sInput); #ifdef never fprintf(stderr, "dx = %d, dy = %d, dz = %d\n", c.dx, c.dy, c.dz); @@ -1046,11 +1135,24 @@ } #endif + /* Based on the algorithm information in the context, build the + * ScalarFunction object that will be optimized. + */ + if (c.inner_search_method == c.outer_search_method) { + targetFunc= buildSimpleScalarFunction( mse, restrtMatched, + getCurrentNDim(), NULL ); + } + else { + targetFunc= buildSimpleScalarFunction( mse, restrt, + getCurrentNDim(), NULL ); + } + } void SlaveTask () { int i; + int all_slices_missing; if (c.debugLevel) Message("Image %ld...\n",t); @@ -1058,12 +1160,21 @@ r.t = t.t; - /* Pick a starting point and optimize */ + /* Pick a starting point */ r.reg_pars.q.x= r.reg_pars.q.y= r.reg_pars.q.z= 0.0; r.reg_pars.q.w= 1.0; r.reg_pars.mse= -1.0; r.reg_pars.x= r.reg_pars.y= r.reg_pars.z= 0.0; - estimateAlignment( &r.reg_pars); + + /* optimize if any slice is not missing */ + all_slices_missing= 1; + for (i=0; iq.x= 0.0; + par->q.y= 0.0; + par->q.z= guess[0]/(1.0+fabs(guess[0])); + par->q.w= + sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); + par->x= 0.0; + par->y= 0.0; + par->z= 0.0; + } + else if (c.trans_only_flag) { + par->q.x= 0.0; + par->q.y= 0.0; + par->q.z= 0.0; + par->q.w= 1.0; + par->x= c.dx*guess[0]; + par->y= c.dy*guess[1]; + par->z= 0.0; + } + else { + par->q.x= 0.0; + par->q.y= 0.0; + par->q.z= guess[0]/(1.0+fabs(guess[0])); + par->q.w= + sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); + par->x= c.dx*guess[1]; + par->y= c.dy*guess[2]; + par->z= 0.0; + } + } + else { + if (c.rot_only_flag) { + par->q.x= guess[0]/(1.0+fabs(guess[0])); + par->q.y= guess[1]/(1.0+fabs(guess[1])); + par->q.z= guess[2]/(1.0+fabs(guess[2])); + par->q.w= + sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); + par->x= 0.0; + par->y= 0.0; + par->z= 0.0; + } + else if (c.trans_only_flag) { + par->q.x= 0.0; + par->q.y= 0.0; + par->q.z= 0.0; + par->q.w= 1.0; + par->x= c.dx*guess[0]; + par->y= c.dy*guess[1]; + par->z= c.dz*guess[2]; + } + else { + par->q.x= guess[0]/(1.0+fabs(guess[0]));; + par->q.y= guess[1]/(1.0+fabs(guess[1]));; + par->q.z= guess[2]/(1.0+fabs(guess[2]));; + par->q.w= + sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); + par->x= c.dx*guess[3]; + par->y= c.dy*guess[4]; + par->z= c.dz*guess[5]; + } + } +} + +static int getDGuessFromPar( double* dguess, const RegPar3D* par ) +{ + if (c.inplane_flag) { + /* minimize in-plane only */ + if (c.rot_only_flag) { + /* 1 degree of freedom */ + dguess[0]= par->q.z/(1.0-fabs(par->q.z)); + } + else if (c.trans_only_flag) { + /* 2 degrees of freedom */ + dguess[0]= par->x/c.dx; + dguess[1]= par->y/c.dy; + } + else { + /* 3 degrees of freedom */ + dguess[0]= par->q.z/(1.0-fabs(par->q.z)); + dguess[1]= par->x/c.dx; + dguess[2]= par->y/c.dy; + } + } + else { + if (c.rot_only_flag) { + /* minimize on 3 degrees of freedom */ + dguess[0]= par->q.x/(1.0-fabs(par->q.x)); + dguess[1]= par->q.y/(1.0-fabs(par->q.y)); + dguess[2]= par->q.z/(1.0-fabs(par->q.z)); + } + else if (c.trans_only_flag) { + /* minimize on 3 degrees of freedom */ + dguess[0]= par->x/c.dx; + dguess[1]= par->y/c.dy; + dguess[2]= par->z/c.dz; + } + else { + /* minimize on all 6 degrees of freedom */ + dguess[0]= par->q.x/(1.0-fabs(par->q.x)); + dguess[1]= par->q.y/(1.0-fabs(par->q.y)); + dguess[2]= par->q.z/(1.0-fabs(par->q.z)); + dguess[3]= par->x/c.dx; + dguess[4]= par->y/c.dy; + dguess[5]= par->z/c.dz; + } + } + return getCurrentNDim(); +} static void estimateAlignment( RegPar3D* par) { + double dguess[MAX_DOF]; + double mse= -1.0; long x,y,z; quat_identity(&(prerotation)); @@ -1139,24 +1363,10 @@ MEM(check,c.dx,c.dy,c.dz,x,y,z)= 1; } - switch (c.opt_method) { - case OPT_NELMIN_T: - estAlignNelminT(par); - break; - case OPT_NELMIN: - estAlignNelmin(par); - break; - case OPT_PRAXIS: - estAlignPraxis(par); - break; - case OPT_NONE: - estAlignNone(par); - break; - case OPT_INVALID: - Abort( - "%s: internal error: bad optimization method in estimateAlignment!\n", - c.progname); - } + getDGuessFromPar(dguess,par); + (void)c.opt->go(c.opt, targetFunc, dguess, getCurrentNDim(), &mse); + getParFromDGuess(par,dguess); + par->mse= mse; if (c.debugLevel) { if (c.inplane_flag) { @@ -1174,265 +1384,6 @@ return; } - -static void estAlignNelminT(RegPar3D* par) -{ - int numpar; - int steps_per_conv_check = 3; -#ifdef never - int max_iter = 400, max_restart = 3; -#endif - int max_iter = 800, max_restart = 12; - int num_iter=0, num_restart=0, return_cond=0; -#ifdef never - float stopping_val = 0.1; -#endif - float stopping_val = 0.02; - float start[6]; - float scale[6]; - float guess[6]; - float tcrit_sqr; - float mseval= -1.0; - - /* Initialize minimization parameters */ - if (c.inplane_flag) { - /* minimize in-plane only; 3 degrees of freedom */ - guess[0]= start[0]= (float)(par->q.z/(1.0-fabs(par->q.z))); - guess[1]= start[1]= (float)par->x/c.dx; - guess[2]= start[2]= (float)par->y/c.dy; - scale[0]= 0.25; - scale[1]= scale[2]= 0.25; - numpar= 3; - tcrit_sqr= 3.182*3.182; /* 95% confidence on 3 degrees of freedom */ - } - else { - /* minimize on all 6 degrees of freedom */ - guess[0]= start[0]= (float)par->q.x; - guess[1]= start[1]= (float)par->q.y; - guess[2]= start[2]= (float)par->q.z; - guess[3]= start[3]= (float)par->x/c.dx; - guess[4]= start[4]= (float)par->y/c.dy; - guess[5]= start[5]= (float)par->z/c.dz; - scale[0]= scale[1]= scale[2]= 0.25; - scale[3]= scale[4]= scale[5]= 0.25; - numpar= 6; - tcrit_sqr= 2.447*2.447; /* 95% confidence on 6 degrees of freedom */ - } - - nelmin_t( fmse, frestrt, - &numpar, start, guess, &mseval, - &stopping_val, scale, &steps_per_conv_check, - &max_iter, &num_iter, &num_restart, &return_cond, &max_restart, - &tcrit_sqr); - if (return_cond != 0) { - if (c.debugLevel) Message("Alignment failed on return code %d\n", - return_cond); - if (return_cond==2) - Warning(1,"estireg3d: Nelder-Mead convergence failed!\n"); - else - Warning(1,"estireg3d: Nelder-Mead call illegal value!\n"); - Warning(1," failed at iter = %d of %d, restart= %d of %d\n", - num_iter, max_iter, num_restart, max_restart); - par->mse= -1.0; /* impossible value indicates error */ - } - else par->mse= mseval; - - if (c.inplane_flag) { - par->q.x= 0.0; - par->q.y= 0.0; - par->q.z= guess[0]/(1.0+fabs(guess[0])); - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*guess[1]; - par->y= c.dy*guess[2]; - par->z= 0.0; - } - else { - par->q.x= guess[0]; - par->q.y= guess[1]; - par->q.z= guess[2]; - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*guess[3]; - par->y= c.dy*guess[4]; - par->z= c.dz*guess[5]; - } -} - - -static void estAlignNelmin(RegPar3D* par) -{ - int numpar; - int steps_per_conv_check = 3; -#ifdef never - int max_iter = 400, max_restart = 3; -#endif - int max_iter = 800, max_restart = 12; - int num_iter=0, num_restart=0, return_cond=0; -#ifdef never - float stopping_val = 0.1; -#endif - float stopping_val = 0.02; - float start[6]; - float scale[6]; - float guess[6]; - float mseval= -1.0; - - /* Initialize minimization parameters */ - if (c.inplane_flag) { - /* minimize in-plane only; 3 degrees of freedom */ - guess[0]= start[0]= (float)(par->q.z/(1.0-fabs(par->q.z))); - guess[1]= start[1]= (float)par->x/c.dx; - guess[2]= start[2]= (float)par->y/c.dy; - scale[0]= 0.25; - scale[1]= scale[2]= 0.25; - numpar= 3; - } - else { - /* minimize on all 6 degrees of freedom */ - guess[0]= start[0]= (float)par->q.x; - guess[1]= start[1]= (float)par->q.y; - guess[2]= start[2]= (float)par->q.z; - guess[3]= start[3]= (float)par->x/c.dx; - guess[4]= start[4]= (float)par->y/c.dy; - guess[5]= start[5]= (float)par->z/c.dz; - scale[0]= scale[1]= scale[2]= 0.25; - scale[3]= scale[4]= scale[5]= 0.25; - numpar= 6; - } - - nelmin( fmse, frestrt, - &numpar, start, guess, &mseval, - &stopping_val, scale, &steps_per_conv_check, - &max_iter, &num_iter, &num_restart, &return_cond, &max_restart ); - if (return_cond != 0) { - if (c.debugLevel) Message("Alignment failed on return code %d\n", - return_cond); - if (return_cond==2) - Warning(1,"estireg3d: Nelder-Mead convergence failed!\n"); - else - Warning(1,"estireg3d: Nelder-Mead call illegal value!\n"); - Warning(1," failed at iter = %d of %d, restart= %d of %d\n", - num_iter, max_iter, num_restart, max_restart); - par->mse= -1.0; /* impossible value indicates error */ - } - else par->mse= mseval; - - if (c.inplane_flag) { - par->q.x= 0.0; - par->q.y= 0.0; - par->q.z= guess[0]/(1.0+fabs(guess[0])); - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*guess[1]; - par->y= c.dy*guess[2]; - par->z= 0.0; - } - else { - par->q.x= guess[0]; - par->q.y= guess[1]; - par->q.z= guess[2]; - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*guess[3]; - par->y= c.dy*guess[4]; - par->z= c.dz*guess[5]; - } -} - - -static void estAlignPraxis(RegPar3D* par) -{ - int numpar; - double dguess[6]; - float mseval= -1.0; - double prx_t0= 0.000001; - double prx_h0= 0.1; - static double prx_machep= 0.0; - int prx_printlvl= 0; - double dzero= 0.0; - - if (prx_machep==0.0) { - prx_machep= (2.0*DLAMCH("e")); - if (c.debugLevel) - fprintf(stderr,"estAlignPraxis: machine eps = %lg\n",prx_machep); - } - if ((1.0+prx_machep) == 1.0) - Abort("%s: precision test failed!\n",c.progname); - - /* Initialize minimization parameters */ - if (c.inplane_flag) { - /* minimize in-plane only; 3 degrees of freedom */ - dguess[0]= par->q.z/(1.0-fabs(par->q.z)); - dguess[1]= par->x/c.dx; - dguess[2]= par->y/c.dy; - numpar= 3; - } - else { - /* minimize on all 6 degrees of freedom */ - dguess[0]= par->q.x; - dguess[1]= par->q.y; - dguess[2]= par->q.z; - dguess[3]= par->x/c.dx; - dguess[4]= par->y/c.dy; - dguess[5]= par->z/c.dz; - numpar= 6; - } - - if (c.debugLevel>1) prx_printlvl= 4; - else if (c.debugLevel>0) prx_printlvl= 1; - else prx_printlvl= 0; - - par->mse= praxis(prx_t0, prx_machep, prx_h0, numpar, prx_printlvl, - dguess, mse, restrt, 0.0); - - if (c.inplane_flag) { - par->q.x= 0.0; - par->q.y= 0.0; - par->q.z= dguess[0]/(1.0+fabs(dguess[0])); - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*dguess[1]; - par->y= c.dy*dguess[2]; - par->z= 0.0; - } - else { - par->q.x= dguess[0]; - par->q.y= dguess[1]; - par->q.z= dguess[2]; - par->q.w= - sqrt(1.0-(par->q.x*par->q.x + par->q.x*par->q.x + par->q.x*par->q.x)); - par->x= c.dx*dguess[3]; - par->y= c.dy*dguess[4]; - par->z= c.dz*dguess[5]; - } -} - - -static void estAlignNone(RegPar3D* par) -{ - long x, y, z; - - /* This just produces MSEs for the input alignment */ - - /* Need to copy the raw image to the moved image for - * calcChiSqr's benefit. - */ - for (x=0; xmse= calcChiSqr(); -} - - static void saveRegParams(FILE* ofile, RegPar3D* p, long t) { fprintf(ofile, "%ld %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg\n", @@ -1644,6 +1595,7 @@ tot_weight += weight; } } + #ifdef never fprintf(tp, "1b:sse = %.14g, tot_weight = %.14g, weight = %.14g\n", sse, tot_weight, weight); fprintf(tp, "1b:tmp1 = %.14g, tmp2 = %.14g\n",tmp1, tmp2); @@ -1670,15 +1622,13 @@ fflush(tp); #endif - return sse; } - /* Returns mean squared-error between (adjusted) fixed image */ /* and (adjusted) register image, the criterion to be */ /* minimized by the minization op for registration */ -static double mse( double* guess, int npar ) +static double mse( const double* guess, const int npar, void* userHook ) { Quat q; Quat tq; @@ -1686,30 +1636,18 @@ double xshift, yshift, zshift; double chisqr; static double reallyBig= 0.0; + RegPar3D lclPar; if (reallyBig==0.0) { reallyBig= sqrt(SLAMCH("o")); } /* Unpack the input info */ - if (c.inplane_flag) { - q.x= 0.0; - q.y= 0.0; - q.z= guess[0]/(1.0+fabs(guess[0])); - q.w= sqrt(1.0 - (q.x*q.x + q.y*q.y + q.z*q.z)); - xshift= c.dx*guess[1]; - yshift= c.dy*guess[2]; - zshift= 0.0; - } - else { - q.x= guess[0]; - q.y= guess[1]; - q.z= guess[2]; - q.w= sqrt(1.0 - (q.x*q.x + q.y*q.y + q.z*q.z)); - xshift= c.dx*guess[3]; - yshift= c.dy*guess[4]; - zshift= c.dz*guess[5]; - } + getParFromDGuess(&lclPar,guess); + q= lclPar.q; + xshift= lclPar.x; + yshift= lclPar.y; + zshift= lclPar.z; /* Put up a barrier against search walking out of the home k-space cell */ if ((xshift>0.5*c.dx) || (xshift<-0.5*c.dx) @@ -1732,6 +1670,7 @@ quat_copy(&tq, &(prerotation)); quat_conjugate(&tq); quat_mult_right(&q,&tq); + quat_normalize(&q); tqshift.x= -preshift[0]; tqshift.y= -preshift[1]; tqshift.z= -preshift[2]; @@ -1743,7 +1682,7 @@ xshift += tqshift.x; yshift += tqshift.y; zshift += tqshift.z; - + #ifdef never fprintf(stderr,"Prerot is (%lg %lg %lg %lg); shift ( %lg %lg %lg )\n", prerotation.x,prerotation.y, @@ -1800,34 +1739,36 @@ } -static void restrt( double* guess, int npar ) +static void restrt( const double* guess, const int npar, void* userHook ) { + RegPar3D lclPar; Quat q; - if (c.inplane_flag) { - q.x= 0.0; - q.y= 0.0; - q.z= guess[0]/(1.0+fabs(guess[0])); - q.w= sqrt(1.0 - (q.x*q.x + q.y*q.y + q.z*q.z)); - quat_copy( &prerotation, &q ); - preshift[0]= c.dx*guess[1]; - preshift[1]= c.dy*guess[2]; - preshift[2]= 0.0; + /* Unpack the input info */ + getParFromDGuess(&lclPar,guess); + + if (c.outer_search_method == c.inner_search_method) { + /* No point in rotating the image twice by the same method; it just + * wastes time and slows convergence. We'll specify a preshift of + * 0.0 and a prerotation by 0.0 degrees, essentially making the + * prerotated image identical to the raw image. + */ + q.x= q.y= q.z= 0.0; + q.w= 1.0; + quat_copy(&prerotation,&q); + preshift[0]= preshift[1]= preshift[2]= 0.0; } else { - q.x= guess[0]; - q.y= guess[1]; - q.z= guess[2]; - q.w= sqrt(1.0 - (q.x*q.x + q.y*q.y + q.z*q.z)); - quat_copy( &prerotation, &q ); - preshift[0]= c.dx*guess[3]; - preshift[1]= c.dy*guess[4]; - preshift[2]= c.dz*guess[5]; + quat_copy(&q,&(lclPar.q)); + quat_copy(&prerotation, &q); + preshift[0]= lclPar.x; + preshift[1]= lclPar.y; + preshift[2]= lclPar.z; } if (c.debugLevel) Message("Restart! prerotation (%lg %lg %lg %lg), preshift (%lg %lg %lg)\n", - q.x,q.y,q.z,q.w, + q.x, q.y, q.z, q.w, preshift[0],preshift[1],preshift[2]); switch (c.outer_search_method) { @@ -1870,34 +1811,48 @@ Abort("%s: internal error: bad search method in restrt!\n",c.progname); } + if (c.debugLevel>1) { + /* call mse to print out value using newly prerotated volumes */ + (void)mse(guess,npar,userHook); + } if (c.smooth_flag) smoothImageComplex( raw_prerotated ); } - -static float fmse( float* guess ) +static void restrtMatched( const double* guess, const int npar, + void* userHook ) { - double dguess[6]; - int i; - for (i=0; i<6; i++) dguess[i]= (double)guess[i]; - return (float)mse( dguess, 6 ); -} + Quat q; + /* No point in rotating the image twice by the same method; it just + * wastes time and slows convergence. We'll specify a preshift of + * 0.0 and a prerotation by 0.0 degrees, essentially making the + * prerotated image identical to the raw image. + */ + q.x= q.y= q.z= 0.0; + q.w= 1.0; + quat_copy(&prerotation,&q); + preshift[0]= preshift[1]= preshift[2]= 0.0; + + if (c.debugLevel) + Message("RestartMatched! prerotation (%lg %lg %lg %lg), preshift (%lg %lg %lg)\n", + q.x, q.y, q.z, q.w, + preshift[0],preshift[1],preshift[2]); -static void frestrt( float* guess ) -{ - double dguess[6]; - int i; - for (i=0; i<6; i++) dguess[i]= (double)guess[i]; - restrt( dguess, 6 ); + if (c.debugLevel>1) { + /* call mse to print out value using newly prerotated volumes */ + (void)mse(guess,npar,userHook); + } + if (c.smooth_flag) smoothImageComplex( raw_prerotated ); } - /* UTILITY FUNCTIONS */ void PackContext () { + char* s; + #ifdef never fprintf(stderr, "in Pack: dx = %d, dy = %d, dz = %d\n", c.dx, c.dy, c.dz); #endif @@ -1914,12 +1869,14 @@ par_pkdouble(c.ly); par_pkdouble(c.lz); - par_pkint((int)c.inner_search_method); - par_pkint((int)c.outer_search_method); - par_pkint(c.smooth_flag); - par_pkint(c.inplane_flag); - par_pkint((int)c.weight_method); - par_pkint((int)c.opt_method); + s= getAlgInfoString(); + par_pkint(strlen(s)); + par_pkstr(s); /* don't free s; getAlgInfoString uses a static buffer */ + + s= c.opt->getStringRep(c.opt); + par_pkint(strlen(s)); + par_pkstr(s); + free(s); par_pkfloatarray(c.align_image, c.dx*c.dy*c.dz); par_pkfloatarray(c.weight_image, c.dx*c.dy*c.dz); @@ -1933,8 +1890,11 @@ void UnpackContext () { + char tbuf[256]; + int l; + par_upkstr(c.progname); - par_upkint(c.debugLevel); + c.debugLevel= par_upkint(); par_upkstr(c.input_file); c.dx= par_upkint(); @@ -1952,12 +1912,30 @@ Abort("%s: unable to allocate %d bytes!\n", c.progname,c.dx*c.dy*c.dz*sizeof(float)); - c.inner_search_method= (SearchMethod)par_upkint(); - c.outer_search_method= (SearchMethod)par_upkint(); - c.smooth_flag= par_upkint(); - c.inplane_flag= par_upkint(); - c.weight_method= (WeightMethod)par_upkint(); - c.opt_method= (OptMethod)par_upkint(); + /* The following block ends up building the optimizer twice, once + * when it unpacks the algorithm and then again when it unpacks + * the copy of the master's actual optimizer. We just throw the + * first one away. + */ + l= par_upkint(); + if (l > (sizeof(tbuf)-1)) + Abort("%s: cannot unpack algorithm; string rep is too long! (%d vs %d)\n", + c.progname, l, sizeof(tbuf)-1); + par_upkstr(tbuf); + if (!parseAlgString(tbuf)) + Abort("%s: internal error: master sent invalid alg string <%s>!\n", + c.progname,tbuf); + l= par_upkint(); + if (l > (sizeof(tbuf)-1)) + Abort("%s: cannot unpack optimizer; string rep is too long! (%d vs %d)\n", + c.progname, l, sizeof(tbuf)-1); + par_upkstr(tbuf); + if (c.opt != NULL) c.opt->destroySelf(c.opt); + c.opt= optimizerFromStringRep(tbuf); + if (!c.opt) + Abort("%s: internal error unpacking unrecognized optimizer <%s>!\n", + c.progname, tbuf); + c.opt->setDebugLevel(c.opt, c.debugLevel); par_upkfloatarray(c.align_image, c.dx*c.dy*c.dz); par_upkfloatarray(c.weight_image, c.dx*c.dy*c.dz); Index: src/estireg3d/estireg3d_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/estireg3d/estireg3d_help.help,v retrieving revision 1.7 retrieving revision 1.9 diff -a -u -r1.7 -r1.9 --- src/estireg3d/estireg3d_help.help 23 Oct 2000 16:22:29 -0000 1.7 +++ src/estireg3d/estireg3d_help.help 9 Mar 2004 23:26:04 -0000 1.9 @@ -124,10 +124,18 @@ "nosmooth" turns off smoothing "inplane" causes alignment only in the X-Y plane (like 2D slice - alignment. + alignment, but for the whole volume) "noinplane" causes full 3D, 6 degree of freedom alignment. + "rotonly" causes only the rotation to be aligned. + + "norotonly" turns off the "rotonly" option. + + "transonly" causes only the rotation to be aligned. + + "notransonly" turns off the "transonly" option. + "qual=[cox | sabs | ssqr | ucell]" sets the quality measure used to choose shear decompositions for some rotation algorithms. @@ -179,8 +187,8 @@ The default settings are: - "nosmooth,noinplane,opt=praxis,weight=smoothalign,qual=ssqr, - inner=shear4,outer=shear4" + "nosmooth,noinplane,norotonly,notransonly,opt=praxis, + weight=smoothalign,qual=ssqr,inner=shear4,outer=shear4" Smoothing is done with a Gaussian kernel with bandwidth 1.0 by default. *Details:Calculation @@ -209,6 +217,13 @@ This approach can fail if the inner method is not sufficiently accurate to move the estimates in the correct direction; if this happens a more accurate inner method should be used. + + In the special case that the inner and outer methods are the same, + it becomes redundant and counterproductive to move the image twice. + If the two methods match the outer operation is ignored and all + the motion is implemented by the call to the inner method in the + inner optimization loop. The outer loop still exists, however, + since it helps in escaping local minima. The -algorithm option allows control over the inner and outer methods used in this process and over some additional features. Index: src/estireg3d/estiwarp.c =================================================================== RCS file: src/estireg3d/estiwarp.c diff -N src/estireg3d/estiwarp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/estireg3d/estiwarp.c 8 Apr 2004 23:31:15 -0000 1.5 @@ -0,0 +1,1674 @@ +/************************************************************ + * * + * estiwarp.c * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * Copyright (c) 1995 Department of Statistics, * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Original programming by Joel Welling 3/00 * + * 10/02: Parallelization, Jenn Bakal * + * 3/04: estireg3d -> estiwarp, Joel Welling * + ************************************************************/ + +/* Notes- + * -clean out JENN comments! + */ + + +#include +#include +#include +#ifdef DARWIN +#include +#endif +#include +#include +#include +#include +#include +#include "../fmri/lapack.h" +#include "mri.h" +#include "fmri.h" +#include "par.h" +#include "stdcrg.h" +#include "misc.h" +#include "array.h" +#include "acct.h" + + +static char rcsid[] = "$Id: estiwarp.c,v 1.5 2004/04/08 23:31:15 welling Exp $"; + +/* Notes- + */ + +/* Maximum free parameters */ +#define MAX_DOF 16 + +/* Access for 3D arrays */ +#define MEM_BCK(matrix,nx,ny,nz,x,y,z) matrix[((((z)*ny)+(y))*nx)+(x)] +#define MEM(matrix,nx,ny,nz,x,y,z) matrix[((((x)*ny)+(y))*nz)+(z)] + +/* Linear interpolation, up to 3 steps. Scale factors are: + * + * a is 0.0 on l side of l-r direction + * b is 0.0 on d side of d-u direction + * c is 0.0 on f side of f-b direction + */ +#define LIN( l, r, a ) ( ( (a)<=0.0 ) ? (l) : ( ((a)>=1.0) ? (r) : \ + ( (l)*(1.0-(a)) + (r)*(a) ) ) ) +#define LIN2( ld, rd, lu, ru, a, b ) LIN( LIN(ld,rd,a), LIN(lu,ru,a), b ) +#define LIN3( ldf, rdf, luf, ruf, ldb, rdb, lub, rub, a, b, c ) \ + LIN( LIN2( ldf, rdf, luf, ruf, a, b ), LIN2( ldb, rdb, lub, rub, a, b ), c ) + +/* Tolerance for coord calculations (allow for numerical noise) */ +#define EPSILON 0.000001 + +typedef enum { + SEARCH_TRILIN, + SEARCH_INVALID +} SearchMethod; + +typedef enum { + WEIGHT_CONST, + WEIGHT_INV_STDV, + WEIGHT_ALIGN, + WEIGHT_SMTHALIGN, + WEIGHT_INVALID +} WeightMethod; + +typedef enum { + OPT_NELMIN, + OPT_NELMIN_T, + OPT_PRAXIS, + OPT_NONE, + OPT_INVALID +} OptMethod; + +typedef struct warppar_struct { + Transform v; + double mse; +} WarpPar; + + +typedef struct Context { + /* NOTE: any new fields added to this struct should + also be added to PackContext and UnpackContext */ + + char progname[512]; + int debugLevel; + int verbose; + + Filename input_file; /* the images to work on */ + float* align_image; /* the image to align to */ + float* weight_image; /* weight information */ + + int dx; /* # of voxels along the X dimension */ + int dy; /* # of voxels along the Y dimension */ + int dz; /* # of slices along the Z dimension */ + int dt; /* # of images along the T dimension */ + double lx; + double ly; + double lz; + + SearchMethod inner_search_method; /* this defines the algorithm to be */ + SearchMethod outer_search_method; /* used. Technically, the quality */ + int smooth_flag; /* measure used by fshrot3d is also */ + int inplane_flag; /* part of the algorithm in effect */ + WeightMethod weight_method; + Optimizer* opt; + + sm_type smoother_type; /* smoother options have to be */ + float smoother_bandwidth; /* packaged separately so that */ + float smoother_k; /* they can be sent via PVM */ + float smoother_threshold_out; +} Context; + + +typedef struct Task { + /* NOTE: any new fields added to this struct should + also be added to PackTask and UnpackTask */ + int t; /* image number to work on */ +} Task; + +typedef struct Result { + /* NOTE: any new fields added to this struct should + also be added to PackResult and UnpackResult */ + int t; + WarpPar warp_par; +} Result; + + +/* GLOBAL VARIABLES FOR MASTER & SLAVE */ +Task t; +Context c; +Result r; +Smoother* smoother; + + +/* GLOBAL VARIABLES FOR MASTER */ +FILE *pf; + +WarpPar *warppar; /* array holding the registration parameters + being computed */ + +/* GLOBAL VARIABLES FOR SLAVE */ +MRI_Dataset *sInput = NULL; +FComplex* raw_image; +FComplex* raw_prerotated; +FComplex* moved_image; +char* check; +ScalarFunction* targetFunc= NULL; +WarpPar prewarp; +Transform inv_prewarp_trans; +unsigned char** missing= NULL; /* will hold missing info */ + +/* FORWARD DECLARATIONS FOR MASTER */ +void MasterTask(int argc, char **argv); +void MasterResult(int task_number); +static int parseAlgString(char* search_string); +static char* getAlgInfoString(); +static int checkDatasetDims(char* dsname, MRI_Dataset* ds, char* chunk, + char* dims_required); +static void loadImage(float* image, MRI_Dataset* ds, int t); +static void smoothImage(float *image); +static void invertStdvImage(float *image); +static void copyImage(float *image, float* source); +static FILE* initParFile(char* parfname, char* infname, + char* alignfname, char* stdvfname, + double xv, double yv, double zv); +static void saveWarpParams(FILE* ofile, WarpPar* p, long t); + +/* FORWARD DECLARATIONS FOR SLAVE */ +void SlaveContext(); +void SlaveTask(); +void SlaveFinalize(); +static void loadImageComplex(FComplex* image, MRI_Dataset* ds, int t); +static void estimateAlignment(WarpPar* par); +static void estAlignNelminT(WarpPar* par); +static void estAlignNelmin(WarpPar* par); +static void estAlignPraxis(WarpPar* par); +static void estAlignNone(WarpPar* par); +void smoothImageComplex(FComplex *image); +static double calcChiSqr(); +static double mse(const double* guess, const int npar, void* userHook); +static void restrt(const double* guess, const int npar, void* userHook); +static void restrtMatched(const double* guess, const int npar, void* userHook); + +/* FORWARD DECLARATIONS - UTILITY */ +void PackContext (); +void UnpackContext (); +void PackTask (); +void UnpackTask (); +void PackResult (); +void UnpackResult (); + +#define DEFAULT_SEARCH_ALGORITHM \ + "nosmooth,noinplane,opt=praxis,weight=smoothalign,qual=ssqr,inner=trilin,outer=trilin" + +/* Smallest standard deviation contributing to weighting. This + * prevents numerical noise weights from overwhelming the signal. + */ +#define STDV_FLOOR 1.0 + +/* Weights below this fraction of max weight are ignored. */ +/* Non-zero values here seem to speed mse() but slow convergence by + * making the optimization surface bumpier. + */ +#define WEIGHT_FLOOR 0.0 + +static int getCurrentNDim() +{ + if (c.inplane_flag) { + return 6; + } + else { + return 12; + } +} + +static char* searchMethodName( SearchMethod mthd ) +{ + switch (mthd) { + case SEARCH_TRILIN: return "trilin"; + case SEARCH_INVALID: return "invalid interpolation!"; + default: return NULL; + } +} + +static char* weightMethodName( WeightMethod mthd ) +{ + switch (mthd) { + case WEIGHT_CONST: return "const"; + case WEIGHT_INV_STDV: return "inv-stdv"; + case WEIGHT_ALIGN: return "align"; + case WEIGHT_SMTHALIGN: return "smoothalign"; + case WEIGHT_INVALID: return "invalid weighting!"; + default: return NULL; + } +} + +static int weightMethodNeedsStdv( WeightMethod mthd ) +{ + switch (mthd) { + case WEIGHT_CONST: return 0; + case WEIGHT_INV_STDV: return 1; + case WEIGHT_ALIGN: return 0; + case WEIGHT_SMTHALIGN: return 0; + case WEIGHT_INVALID: return 0; /* well, it doesn't! */ + default: return 0; + } +} + +static char* qualMethodName( int mthd ) +{ + switch (mthd) { + case FR3D_QUAL_COX: return "cox"; + case FR3D_QUAL_SUM_ABS: return "sabs"; + case FR3D_QUAL_SUM_SQR: return "ssqr"; + case FR3D_QUAL_UNIT_CELL: return "ucell"; + case FR3D_QUAL_UNSET: return "invalid quality measure!"; + default: return NULL; + } +} + +static Optimizer* parseOptMethod(char* s, const int ndim) +{ + /* Two-sided 95% T cutoffs for DF up to 20 */ + static float tcrit[]= + { 0.0, 12.706176098809, 4.30263617020413, + 3.18244545308107, 2.77644502408949, 2.57058182376418, + 2.44680441622004, 2.36457539633475, 2.30597941403506, + 2.26214359559273, 2.2281309162355, 2.20098027417758, + 2.17880969240071, 2.16036657035061, 2.14478525936996, + 2.13144854260425, 2.11990457994238, 2.10981505255424, + 2.10092165066567, 2.09302376167972, 2.08596322490106 + }; + + if (ndim> (sizeof(tcrit)/sizeof(float))-1) + Abort("%s: tcrit for %d degrees of freedom is not compiled in!\n", + c.progname, ndim); + + if (!strcasecmp(s,"nelmin")) + return createNelminOptimizer(0.02,1.0); + else if (!strcasecmp(s,"nelmin_t")) + return createNelminTOptimizer(0.02,1.0,tcrit[ndim]*tcrit[ndim]); + else if (!strcasecmp(s,"praxis")) + return createPraxisOptimizer(0.000001,1.0); + else if (!strcasecmp(s,"none")) return createNoneOptimizer(); + else return NULL; +} + +static SearchMethod parseSearchMethod(char* s) +{ + if (!strcasecmp(s,"trilin")) return SEARCH_TRILIN; + else return SEARCH_INVALID; +} + +static WeightMethod parseWeightMethod(char* s) +{ + if (!strcasecmp(s,"const")) return WEIGHT_CONST; + else if (!strcasecmp(s,"inv-stdv")) return WEIGHT_INV_STDV; + else if (!strcasecmp(s,"align")) return WEIGHT_ALIGN; + else if (!strcasecmp(s,"smoothalign")) return WEIGHT_SMTHALIGN; + else return WEIGHT_INVALID; +} + +static int parseQualMethod(char* s) +{ + if (!strcasecmp(s,"cox")) + fshrot3d_set(FR3D_QUAL_MEASURE, FR3D_QUAL_COX); + else if (!strcasecmp(s,"sabs")) + fshrot3d_set(FR3D_QUAL_MEASURE, FR3D_QUAL_SUM_ABS); + else if (!strcasecmp(s,"ssqr")) + fshrot3d_set(FR3D_QUAL_MEASURE, FR3D_QUAL_SUM_SQR); + else if (!strcasecmp(s,"ucell")) + fshrot3d_set(FR3D_QUAL_MEASURE, FR3D_QUAL_UNIT_CELL); + else return 0; + + return 1; +} + +int main (int argc, + char **argv, + char **envp) +{ + par_process(argc, argv, envp, + MasterTask, MasterResult, + SlaveContext, SlaveTask, + SlaveFinalize, + PackContext, UnpackContext, + PackTask, UnpackTask, + PackResult, UnpackResult); +} + + +/* MASTER PROCEDURES */ + +void +MasterTask (int argc, + char **argv) +{ + MRI_Dataset *Input = NULL, *Align = NULL, *Stdv = NULL; + char infile[512], alignfile[512], stdvfile[512], parfile[512]; + char search_string[512]; + double xvoxel, yvoxel, zvoxel; + int lin_count; + struct rusage start_rusage, end_rusage; + char run_time_string[256]; + FILE *pp; + time_t tm; + long i; + + c.debugLevel=0; + c.verbose= 0; + + strcpy(c.progname, argv[0]); + + /* Print version number */ + Message( "# %s\n", rcsid ); + + /* Check to see if help was requested */ + if( ( argc > 1 ) && !strcmp( argv[1], "-help" ) ) + { + if( argc == 2 ) + Help( "selecttopic" ); + else + Help( argv[2] ); + } + + /* Initialize the smoother package and set default behaviors, in case + * smoothing is turned on. + */ + sm_init(); + sm_set_params( SM_GAUSSIAN, 1.0, 0.0, 0.0, NULL ); + + /*** Parse command line ***/ + + cl_scan( argc, argv ); + + /* Get filenames */ + cl_get( "input|i", "%option %s[%]", "input.mri", c.input_file ); + cl_get( "align|a", "%option %s[%]", "align.mri", alignfile ); + cl_get( "stdv|s", "%option %s[%]", "stdv.mri", stdvfile ); + cl_get( "parameters|p", "%option %s[%]", "warp.par", parfile ); + if (!cl_get( "x|xv|xvoxel", "%option %lf", &xvoxel )) { + fprintf(stderr,"%s: required argument xvoxel omitted.\n", c.progname); + Help("usage"); + exit(-1); + } + if (!cl_get( "y|yv|yvoxel", "%option %lf", &yvoxel )) { + fprintf(stderr,"%s: required argument yvoxel omitted.\n",c.progname); + Help("usage"); + exit(-1); + } + if (!cl_get( "z|zv|zvoxel", "%option %lf", &zvoxel )) { + fprintf(stderr,"%s: required argument zvoxel omitted.\n",c.progname); + Help("usage"); + exit(-1); + } + if (cl_present("debug")) c.debugLevel= 1; + if (cl_present("v|verbose")) c.verbose= 1; + cl_get( "algorithm|alg", "%option %s[%]", DEFAULT_SEARCH_ALGORITHM, + search_string ); + + /* Check for smoother args */ + sm_parse_cl_opts(); + sm_get_params( &c.smoother_type, &c.smoother_bandwidth, + &c.smoother_k, &c.smoother_threshold_out, NULL); + + if (cl_cleanup_check()) { + int i; + fprintf(stderr,"%s: invalid argument in command line:\n ",c.progname); + for (i=0; imaxWeight) maxWeight= fabs(c.weight_image[i]); + for (i=0; imaxWeight) maxWeight= fabs(c.weight_image[i]); + for (i=0; idestroySelf(c.opt); + c.opt= parseOptMethod(optString,getCurrentNDim()); + if (!c.opt) { + Abort("%s: internal error: unrecognized optimizer type <%s>!\n", + c.progname, optString); + } + c.opt->setDebugLevel(c.opt, c.debugLevel); + free(optString); + } + + /* This turns out to be a good place for a necessary reality check */ + if (getCurrentNDim()>MAX_DOF) + Abort("%s: algorithm implies %d dimensions, but compiled limit is %d!\n", + c.progname,getCurrentNDim(),MAX_DOF); + + free(work); + return 1; +} + +static char* getAlgInfoString() +{ + char scratch[128]; + static char result[512]; + int offset= 0; + + result[0]= '\0'; + + sprintf(scratch,"qual=%s,", + qualMethodName(fshrot3d_get(FR3D_QUAL_MEASURE))); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + if (c.smooth_flag) strcpy(scratch,"smooth,"); + else strcpy(scratch,"nosmooth,"); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + if (c.inplane_flag) strcpy(scratch,"inplane,"); + else strcpy(scratch,"noinplane,"); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + sprintf(scratch,"weight=%s,",weightMethodName(c.weight_method)); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + sprintf(scratch,"opt=%s,",c.opt->getMethodName(c.opt)); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + sprintf(scratch,"inner=%s,",searchMethodName(c.inner_search_method)); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + sprintf(scratch,"outer=%s",searchMethodName(c.outer_search_method)); + strncat(result,scratch,sizeof(result)-(offset+1)); + offset += strlen(scratch); + if (offset>=sizeof(result)-1) return result; + + return result; +} + +static int checkDatasetDims( char* dsname, MRI_Dataset* ds, char* chunk, + char* dims_required ) +{ + char* dimstr; + char buf[256]; + int i; + int offset; + + if (strlen(chunk)>200) + Abort("%s: chunk name <%s> too long!\n",chunk); + + if( !mri_has( ds, chunk ) ) { + Message( "%s: dataset <%s> has no \"%s\" chunk!", c.progname, dsname, chunk); + return 0; + } + + sprintf(buf,"%s.dimensions",chunk); + if ( !mri_has( ds, buf ) ) { + Message( "%s: dataset <%s> has no dimension string for chunk \"%s\"!\n", + c.progname, dsname, chunk ); + return 0; + } + else dimstr= mri_get_string( ds, buf ); + + offset= 0; + for (i=0; i has no info for %s!\n",buf); + return 0; + } + thisextent= mri_get_int(ds,buf); + if ((tchar=strchr(dims_required,dimstr[i])) != NULL) { + /* Make sure this is farther along dims_required than the last one */ + if (tchar-dims_required >= offset) offset= tchar-dims_required; + else { + /* Order of strings doesn't match */ + Message( "%s: dataset <%s> dimension order doesn't match \"%s\"!\n", + c.progname, dsname, dims_required ); + return 0; + } + } + else { + /* not in required string- extent must be 1 */ + if (thisextent != 1) { + Message( "%s: dataset <%s> has an inappropriate dimension %c!\n", + c.progname, dsname, dimstr[i] ); + return 0; + } + } + } + + /* Were all of the required dims present? */ + if (offset!=strlen(dims_required)-1) { + Message( "%s: dataset <%s> doesn't include dimensions \"%s\"!\n", + c.progname, dsname, dims_required ); + return 0; + } + + return 1; +} + +static void loadImage( float* image, MRI_Dataset* ds, int t ) +{ + int x; + int y; + int z; + int blocksize; + float* tmp_image; + + /* This routine reads the given image from the file, swaps it to + * z-fastest order, and returns it in the buffer supplied. Dims + * are assumed to be "xyzt" for the input dataset. + */ + blocksize= (int)(c.dx*c.dy*c.dz); + tmp_image= (float*)mri_get_chunk(ds, "images", blocksize, + t*blocksize, MRI_FLOAT); + + /* Convert to complex-valued for registration */ + for (z=0; zmax_dim) max_dim= c.dy; + if (c.dz>max_dim) max_dim= c.dz; + + if (!(scratch_in= (float*)malloc(max_dim*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n",max_dim*sizeof(float)); + if (!(scratch_out= (float*)malloc(max_dim*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n",max_dim*sizeof(float)); + + /* Smooth in X */ + for (j=0; j STDV_FLOOR) image[i]= 1.0/image[i]; + else image[i]= 0.0; + } +} + +/* Convenience routine */ +static void copyImage( float *image, float* source ) +{ + long length= c.dx*c.dy*c.dz; + long i; + for (i=0; i for writing!\n",c.progname,parfname); + } + + tm= time(NULL); + fprintf(result,"##Format: order:index_t, type:raw\n"); + fprintf(result,"##Format: names:(a00,a01,a02,a03,a10,a11,a12,a13,"); + fprintf(result,"a20,a21,a22,a23,a30,a31,a32,a33,mse)\n"); + fprintf(result,"# Alignment parameters generated %s", + asctime(localtime(&tm))); + fprintf(result,"# Input file: %s\n",infname); + fprintf(result,"# Alignment file: %s\n",alignfname); + fprintf(result,"# Stdv file: %s\n",stdvfname); + fprintf(result,"# xdim= %ld, ydim= %ld, zdim= %ld\n",c.dx,c.dy,c.dz); + fprintf(result,"# voxel size x= %g, y= %g, z= %g\n", xv, yv, zv); + fprintf(result,"# algorithm: %s\n",getAlgInfoString()); + fflush(result); + return result; +} + +static void saveWarpParams(FILE* ofile, WarpPar* p, long t) { + fprintf(ofile, + "%ld %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg %11.5lg\n", + t, + p->v[0], p->v[1], p->v[2], p->v[3], p->v[4], p->v[5], p->v[6], + p->v[7], p->v[8], p->v[9], p->v[10], p->v[11], p->v[12], p->v[13], + p->v[14],p->v[15], + p->mse); + fflush(ofile); +} + +/* SLAVE PROCEDURES */ + +void SlaveFinalize() +{ + if (sInput != NULL) mri_close_dataset(sInput); + if (raw_image != NULL) free(raw_image); + if (raw_prerotated != NULL) free(raw_prerotated); + if (moved_image != NULL) free(moved_image); + if (check != NULL) free(check); +} + +void SlaveContext () +{ + /* Open copy of input file for slaves to read. */ + sInput = mri_open_dataset( c.input_file, MRI_READ ); + missing= get_missing(sInput); + + /* Allocate image storage */ + if (!(raw_image= (FComplex*)malloc(c.dx*c.dy*c.dz*sizeof(FComplex)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(FComplex)); + if (!(raw_prerotated= (FComplex*)malloc(c.dx*c.dy*c.dz*sizeof(FComplex)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(FComplex)); + if (!(moved_image= (FComplex*)malloc(c.dx*c.dy*c.dz*sizeof(FComplex)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(FComplex)); + if (!(check= (char*)malloc(c.dx*c.dy*c.dz*sizeof(char)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(char)); + + /* Based on the algorithm information in the context, build the + * ScalarFunction object that will be optimized. + */ + if (c.inner_search_method == c.outer_search_method) { + targetFunc= buildSimpleScalarFunction( mse, restrtMatched, + getCurrentNDim(), NULL ); + } + else { + targetFunc= buildSimpleScalarFunction( mse, restrt, + getCurrentNDim(), NULL ); + } + +} + +void SlaveTask () +{ + int i; + int all_slices_missing; + + if (c.debugLevel) + Message("Image %ld...\n",t); + loadImageComplex( raw_image, sInput, t.t ); + + r.t = t.t; + + /* Pick a starting point */ + trans_identity(r.warp_par.v); + r.warp_par.mse= -1.0; + + /* optimize if any slice is not missing */ + all_slices_missing= 1; + for (i=0; iru_stime.tv_usec - start->ru_stime.tv_usec; + long s_sec= end->ru_stime.tv_sec - start->ru_stime.tv_sec; + long u_usec= end->ru_utime.tv_usec - start->ru_utime.tv_usec; + long u_sec= end->ru_utime.tv_sec - start->ru_utime.tv_sec; + + if (s_usec < 0) { + s_sec -= 1; + s_usec += 1000000; + } + if (u_usec < 0) { + u_sec -= 1; + u_usec += 1000000; + } + sprintf(time_string,"%d.%06du %d.%06ds",u_sec,u_usec,s_sec,s_usec); +} + +static void getParFromDGuess(WarpPar* par, const double* guess) +{ + int i; + if (c.inplane_flag) { + par->v[0]= guess[0]; + par->v[1]= guess[1]; + par->v[2]= 0.0; + par->v[3]= guess[2]; + par->v[4]= guess[3]; + par->v[5]= guess[4]; + par->v[6]= 0.0; + par->v[7]= guess[5]; + par->v[8]= 0.0; + par->v[9]= 0.0; + par->v[10]= 1.0; + par->v[11]= 0.0; + par->v[12]= 0.0; + par->v[13]= 0.0; + par->v[14]= 0.0; + par->v[15]= 1.0; + } + else { + par->v[0]= guess[0]; + par->v[1]= guess[1]; + par->v[2]= guess[2]; + par->v[3]= guess[3]; + par->v[4]= guess[4]; + par->v[5]= guess[5]; + par->v[6]= guess[6]; + par->v[7]= guess[7]; + par->v[8]= guess[8]; + par->v[9]= guess[9]; + par->v[10]= guess[10]; + par->v[11]= guess[11]; + par->v[12]= 0.0; + par->v[13]= 0.0; + par->v[14]= 0.0; + par->v[15]= 1.0; + } +} + +static int getDGuessFromPar( double* guess, const WarpPar* par ) +{ + if (c.inplane_flag) { + guess[0]= par->v[0]; + guess[1]= par->v[1]; + guess[2]= par->v[3]; + guess[3]= par->v[4]; + guess[4]= par->v[5]; + guess[5]= par->v[7]; + + } + else { + guess[0]= par->v[0]; + guess[1]= par->v[1]; + guess[2]= par->v[2]; + guess[3]= par->v[3]; + guess[4]= par->v[4]; + guess[5]= par->v[5]; + guess[6]= par->v[6]; + guess[7]= par->v[7]; + guess[8]= par->v[8]; + guess[9]= par->v[9]; + guess[10]= par->v[10]; + guess[11]= par->v[11]; + } + return getCurrentNDim(); +} + +static void estimateAlignment( WarpPar* par) +{ + double dguess[MAX_DOF]; + double mse= -1.0; + long x,y,z; + + trans_identity(prewarp.v); + /* The inverse of the identity is the identity */ + trans_copy(inv_prewarp_trans,prewarp.v); + + /* Update the raw_prerotated image to be identical to the raw image, + * since the initial pre-transformation is the identity. + */ + for (x=0; xgo(c.opt, targetFunc, dguess, getCurrentNDim(), &mse); + getParFromDGuess(par,dguess); + par->mse= mse; + + if (c.debugLevel) { + if (c.inplane_flag) { + Message("Alignment rslt (in-plane): this trans produces mse %lg\n", + par->mse); + trans_dump(stderr,par->v); + } + else { + Message("Alignment rslt: this trans produces mse %lg\n", + par->mse); + trans_dump(stderr,par->v); + } + } + return; +} + +/* Function to slightly blur images stored in the real part of complex data*/ +void smoothImageComplex( FComplex *image ) +{ + float *scratch_in; + float *scratch_out; + long max_dim; + long i,j,k; + + max_dim= c.dx; + if (c.dy>max_dim) max_dim= c.dy; + if (c.dz>max_dim) max_dim= c.dz; + + /* Note that we're only interested in smoothing the real part of this! */ + + if (!(scratch_in= (float*)malloc(max_dim*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n",max_dim*sizeof(float)); + if (!(scratch_out= (float*)malloc(max_dim*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n",max_dim*sizeof(float)); + + /* Smooth in X */ + for (j=0; j0.5*c.dx) || (xshift<-0.5*c.dx) + || (yshift>0.5*c.dy) || (yshift<-0.5*c.dy) + || (zshift>0.5*c.dz) || (zshift<-0.5*c.dz)) { + chisqr= reallyBig*(xshift*xshift + yshift*yshift + zshift*zshift); + if (c.debugLevel) { + Message("mse: this transform breaks cell boundary-> chisqr= %g\n", + chisqr); + trans_dump(stderr,lclPar.v); + } + } + else { + + /* Compensate for current prewarp */ + trans_mult_right(lclPar.v, inv_prewarp_trans); + + /* Move the raw data into position */ + switch (c.inner_search_method) { + case SEARCH_TRILIN: + linwarp_warp( lclPar.v, raw_prerotated, moved_image, + check, c.dx, c.dy, c.dz, c.lx, c.ly, c.lz, 0 ); + break; + case SEARCH_INVALID: + Abort("%s: internal error: bad search method in mse!\n",c.progname); + } + + chisqr= calcChiSqr(); + + if (c.debugLevel) { + Message("mse: adjusted transform:\n"); + trans_dump(stderr,lclPar.v); + Message("mse: this trans gives chisqr= %.14g\n",chisqr); + } + } + + return( chisqr ); +} + +static void restrt( const double* guess, const int npar, void* userHook ) +{ + if (c.outer_search_method == c.inner_search_method) { + restrtMatched( guess, npar, userHook ); + } + else { + WarpPar lclPar; + Transform test; + + /* Unpack the input info */ + getParFromDGuess(&lclPar,guess); + + /* Initialize the prewarp transformation and its inverse */ + trans_copy(prewarp.v,lclPar.v); + if (!trans_inverse(inv_prewarp_trans,prewarp.v)) { + Message("%s: Fatal error: cannot invert this transform:\n", + c.progname); + trans_dump(stderr,prewarp.v); + Abort("%s: transform has become non-invertible at time %d!\n", + c.progname,t.t); + } + + if (c.debugLevel) { + Message("Restart! prewarp transform follows:\n"); + trans_dump(stderr,prewarp.v); + } + + switch (c.outer_search_method) { + case SEARCH_TRILIN: + linwarp_warp( lclPar.v, raw_image, raw_prerotated, + check, c.dx, c.dy, c.dz, c.lx, c.ly, c.lz, 0 ); + break; + case SEARCH_INVALID: + Abort("%s: internal error: bad search method in restrt!\n",c.progname); + } + + if (c.debugLevel) { + /* call mse to print out value using newly prerotated volumes */ + (void)mse(guess,npar,userHook); + } + if (c.smooth_flag) smoothImageComplex( raw_prerotated ); + } + +} + +static void restrtMatched( const double* guess, const int npar, + void* userHook ) +{ + /* No point in moving the image twice by the same method; it just + * wastes time and slows convergence. We'll specify a prewarp which + * is the identity, essentially making the prewarped image + * identical to the raw image. + */ + trans_identity(prewarp.v); + /* The inverse of the identity is the identity */ + trans_copy(inv_prewarp_trans,prewarp.v); + + if (c.debugLevel) { + Message("RestartMatched! prewarp transform follows:\n"); + trans_dump(stderr,prewarp.v); + } + + if (c.debugLevel>1) { + /* call mse to print out value using newly prerotated volumes */ + (void)mse(guess,npar,userHook); + } + if (c.smooth_flag) smoothImageComplex( raw_prerotated ); +} + +/* UTILITY FUNCTIONS */ + +void +PackContext () +{ + char* s; + + par_pkstr(c.progname); + par_pkint(c.debugLevel); + par_pkint(c.verbose); + + par_pkstr(c.input_file); + par_pkint(c.dx); + par_pkint(c.dy); + par_pkint(c.dz); + par_pkint(c.dt); + par_pkdouble(c.lx); + par_pkdouble(c.ly); + par_pkdouble(c.lz); + + s= getAlgInfoString(); + par_pkint(strlen(s)); + par_pkstr(s); /* don't free s; getAlgInfoString uses a static buffer */ + + s= c.opt->getStringRep(c.opt); + par_pkint(strlen(s)); + par_pkstr(s); + free(s); + + par_pkfloatarray(c.align_image, c.dx*c.dy*c.dz); + par_pkfloatarray(c.weight_image, c.dx*c.dy*c.dz); + + par_pkint((int)c.smoother_type); + par_pkfloat(c.smoother_bandwidth); + par_pkfloat(c.smoother_k); + par_pkfloat(c.smoother_threshold_out); +} + +void +UnpackContext () +{ + char tbuf[256]; + int l; + + par_upkstr(c.progname); + c.debugLevel= par_upkint(); + c.verbose= par_upkint(); + + par_upkstr(c.input_file); + c.dx= par_upkint(); + c.dy= par_upkint(); + c.dz= par_upkint(); + c.dt= par_upkint(); + c.lx= par_upkdouble(); + c.ly= par_upkdouble(); + c.lz= par_upkdouble(); + + if (!(c.align_image= (float*)malloc(c.dx*c.dy*c.dz*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(float)); + if (!(c.weight_image= (float*)malloc(c.dx*c.dy*c.dz*sizeof(float)))) + Abort("%s: unable to allocate %d bytes!\n", + c.progname,c.dx*c.dy*c.dz*sizeof(float)); + + /* The following block ends up building the optimizer twice, once + * when it unpacks the algorithm and then again when it unpacks + * the copy of the master's actual optimizer. We just throw the + * first one away. + */ + l= par_upkint(); + if (l > (sizeof(tbuf)-1)) + Abort("%s: cannot unpack algorithm; string rep is too long! (%d vs %d)\n", + c.progname, l, sizeof(tbuf)-1); + par_upkstr(tbuf); + if (!parseAlgString(tbuf)) + Abort("%s: internal error: master sent invalid alg string <%s>!\n", + c.progname,tbuf); + l= par_upkint(); + if (l > (sizeof(tbuf)-1)) + Abort("%s: cannot unpack optimizer; string rep is too long! (%d vs %d)\n", + c.progname, l, sizeof(tbuf)-1); + par_upkstr(tbuf); + if (c.opt != NULL) c.opt->destroySelf(c.opt); + c.opt= optimizerFromStringRep(tbuf); + if (!c.opt) + Abort("%s: internal error unpacking unrecognized optimizer <%s>!\n", + c.progname, tbuf); + c.opt->setDebugLevel(c.opt, c.debugLevel); + + par_upkfloatarray(c.align_image, c.dx*c.dy*c.dz); + par_upkfloatarray(c.weight_image, c.dx*c.dy*c.dz); + + c.smoother_type= (sm_type)par_upkint(); + c.smoother_bandwidth= par_upkfloat(); + c.smoother_k= par_upkfloat(); + c.smoother_threshold_out= par_upkfloat(); +} + +void +PackTask () +{ + par_pkint(t.t); +} + +void +UnpackTask () +{ + t.t= par_upkint(); +} + +void +PackResult () +{ + par_pkint(r.t); + par_pkdoublearray((double*)&r.warp_par.v, 16); + par_pkdouble(r.warp_par.mse); +} + +void +UnpackResult () +{ + + r.t= par_upkint(); + par_upkdoublearray((double*)&r.warp_par.v, 16); + r.warp_par.mse= par_upkdouble(); + +} Index: src/estireg3d/estiwarp_help.help =================================================================== RCS file: src/estireg3d/estiwarp_help.help diff -N src/estireg3d/estiwarp_help.help --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/estireg3d/estiwarp_help.help 10 May 2004 18:02:04 -0000 1.5 @@ -0,0 +1,223 @@ +*Introduction + + estiwarp is used to estimate Affine transformations needed to + bring a set of images into registration with a standard image. + Estimation must be performed on image-space data (v.extent=1). + Input data must be organized as vxyzt or xyzt. + + To run estiwarp: + estiwarp -xvoxel xv -yvoxel yv -zvoxel zv + [-input Input-header-file] [-align Align-header-file] + [-stdv stdv-header-file] + [-parameters Registration-parameter-file] [-verbose] [-debug] + [-algorithm alg-string] + [...smoother options...] + + or: + estiwarp -help + +*Arguments:xvoxel + -xvoxel xv (-x xv) + + Specifies the voxel edge length in the x direction. This + parameter is required. Only the ratio of this parameter + with the other voxel edge length parameters is relevant. + +*Arguments:yvoxel + -yvoxel yv (-y yv) + + Specifies the voxel edge length in the y direction. This + parameter is required. Only the ratio of this parameter + with the other voxel edge length parameters is relevant. + +*Arguments:zvoxel + -zvoxel zv (-z zv) + + Specifies the voxel edge length in the z direction. This + parameter is required. Only the ratio of this parameter + with the other voxel edge length parameters is relevant. + +*Arguments:input + [-input Input-header-file] (-i Input-header-file) + + Ex: -input partialk.mri + + Specifies that the header for the input dataset is located + in Input-header-file. Default value is "input.mri". + Input-header-file is not allowed to have the same name + as Align-header-file or Stdv-header-file. + + estiwarp accepts only align real- or complex-valued images + with dimension order "vxyzt" or "xyzt" as input. + +*Arguments:align + [-align Align-header-file] (-a Align-header-file) + + Ex: -align oneimage.mri + + Specifies that the header for the align dataset is located + in Input-header-file. Default value is "align.mri". + Align-header-file is not allowed to have the same name + as Input-header-file or Stdv-header-file. This is the + "standard" data against which input images are aligned. + + estiwarp accepts only single align real- or complex-valued images + with dimension order "vxyzt", "vxyz", "xyz" or "xyzt" for this + purpose. If the t dimension is given, its extent must be 1. + +*Arguments:stdv + [-stdv Stdv-header-file] (-s Stdv-header-file) + + Ex: -align oneimagestdv.mri + + Specifies that the header for the stdv dataset is located + in -header-file. Default value is "stdv.mri", but this file + will not be opened unless the minimization algorithm (see below) + requires it. Stdv-header-file is not allowed to have the same + name as Input-header-file or Align-header-file. This is the + estimated standard error of Align-header-file. + + estiwarp accepts only single align real- or complex-valued images + with dimension order "vxyzt", "vxyz", "xyz" or "xyzt" for this + purpose. If the t dimension is given, its extent must be 1. + +*Arguments:parameters + [-parameters Registration-parameter-file] (-p Registration-parameter-file) + + Ex: -p reg.par + + Specifies that the motion correction parameters are to be + written to Registration-parameter-file. Default value is "reg3d.par". + + The format of the Registration-parameter-file is a series of + ASCII numbers of the form: + image# q_x q_y q_z q_w shift_x shift_y shift_z mse + where the q_ elements compose a unit quaternion specifying + the rotation. These 9 numbers must be separated by spaces + or tabs, but NOT carriage returns- all nine numbers must reside + on the same line. The mse entry is ignored; it is given for + compatibility with other utilities. Lines beginning with '#' + are considered to be comments and are ignored. + +*Arguments:debug + [-debug] + + Causes debugging output to be produced. + +*Arguments:verbose + [-verbose] (-v) + + Causes verbose output to be produced. + +*Arguments:algorithm + [-algorithm alg-string] (-alg alg-string) + + This option provides control of the algorithm by which motion + parameters are estimated. alg-string is a string with a number + of components separated by commas. Specific elements are: + + "smooth" turns on smoothing. Smoothing parameters can be set + using the smoother arguments described below. + + "nosmooth" turns off smoothing + + "inplane" causes alignment only in the X-Y plane (like 2D slice + alignment, but for the whole volume) + + "noinplane" causes full 3D, 6 degree of freedom alignment. + + "weight=[const | inv-stdv | align | smoothalign]" + sets the weighting scheme used in calculating the + measure minimized by the optimization, as follows: + + "const" causes the weight to be the summed squared + difference across all voxels, with all voxels + weighted equally. + + "inv-stdv" causes the voxels to be weighted according + to the inverse square of the associated standard + deviation. Voxels for which the stdv is below a + given floor (set to 1.0 at compile time) are excluded + from the measure to be minimized. + + "align" causes the voxels to be weighted according to + the absolute value of the align dataset. + + "smoothalign" causes the voxels to be weighted according + to the smoothed value of the align dataset. This is + generally used with the "nosmooth" option. + + "inner=trilin" + sets the rotation method used in the inner (fast) + optimization loop, as follows: + + "trilin" implies trilinear interpolation (currently the + only option) + + "outer=trilin" + as for the "inner" option, but refers to the outer, + shorter optimization loop for which more accuracy + is needed. + + "opt=[nelmin_t | nelmin | praxis | none]" + Controls the optimization method. Nelder-Mead + optimization, Nelder-Mead with a T-test cutoff, + Praxis, or no optimization can be selected. The + "none" option is useful for producing MSE values + for the initial unaligned data. + + + The default settings are: + "nosmooth,noinplane,opt=praxis, + weight=smoothalign,inner=trilin,outer=trilin" + Smoothing is done with a Gaussian kernel with bandwidth 1.0 by default. + +*Details:Calculation + + For each image in the input data,a two level optimization algorithm + is used to find rotation and and translation values which minimize + a measure of the difference between the image and a target image. + The target image is provided in the "align" dataset; voxelwise + estimates of the standard deviation of the target image can be + provided in the "stdv" dataset. + + The idea is that the inner level optimization provides rapid, rough + estimates of alignment parameters, and the outer level produces more + accurate values slowly. This allows a good compromise between the + speed and accuracy of the two algorithms. + + Specifically, an inner, fast method is used to produce transformed + versions of the input image for particular parameter + estimates. When the inner search algorithm produces an estimate + of the alignment parameters, slower outer method is used to produce + a version of the image data rotated and translated according to + those estimates. The inner algorithm is then restarted to estimate + transformation values necessary to align this moved image + with the target. For perfect alignment the inner algorithm will + estimate that no additional rotation or translation are needed. + This approach can fail if the inner method is not sufficiently + accurate to move the estimates in the correct direction; if this + happens a more accurate inner method should be used. + + In the special case that the inner and outer methods are the same, + it becomes redundant and counterproductive to move the image twice. + If the two methods match the outer operation is ignored and all + the motion is implemented by the call to the inner method in the + inner optimization loop. The outer loop still exists, however, + since it helps in escaping local minima. + + The -algorithm option allows control over the inner and outer + methods used in this process and over some additional features. + The input and target images can be smoothed before alignment. + The optimality measure can be calculated with or without weighting + for voxel standard deviation. + +m4include(../fmri/coordsys_help.help) + +m4include(../fmri/smoother_help.help) + +m4include(../fmri/nelmin_help.help) + +m4include(../fmri/praxis_help.help) + +m4include(../fmri/linwarp_help.help) Index: src/fmri/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/Makefile,v retrieving revision 1.29 retrieving revision 1.33 diff -a -u -r1.29 -r1.33 --- src/fmri/Makefile 10 Apr 2003 20:11:00 -0000 1.29 +++ src/fmri/Makefile 18 Mar 2004 01:31:14 -0000 1.33 @@ -12,28 +12,38 @@ linrot3d.h history.h filetypes.h frozen_header_info.h \ frozen_header_info_cnv4.h frozen_header_info_lx2.h \ frozen_header_info_prelx.h windaq_header_info.h kvhash.h \ - siemens_kspace_header_info.h + siemens_kspace_header_info.h optimizer.h linwarp.h PKG_MAKELIBS = $L/libfmri.a -PKG_MAKEBINS = $(CB)/smoother_tester $(CB)/quat_tester -PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg -lm +PKG_MAKEBINS = $(CB)/smoother_tester $(CB)/quat_tester \ + $(CB)/_quaternion.$(SHR_EXT) $(CB)/optimizer_tester +PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm MAKEFILES= Makefile CSOURCE= fft2d.c fmri.c fshrot.c polyt.c glm.c smoother.c \ smoother_tester.c parsesplit.c fft3d.c quaternion.c quat_tester.c \ fshrot3d.c linrot3d.c praxis.c history.c filetypes.c kvhash.c \ - bvls.c fmin.c + bvls.c fmin.c quaternion_wrap.c optimizer.c optimizer_tester.c \ + linwarp.c HFILES= fmri.h lapack.h glm.h smoother.h parsesplit.h quaternion.h \ fshrot3d.h linrot3d.h history.h frozen_header_info.h \ frozen_header_info_cnv4.h frozen_header_info_lx2.h \ frozen_header_info_prelx.h siemens_kspace_header_info.h \ - windaq_header_info.h filetypes.h kvhash.h + windaq_header_info.h filetypes.h kvhash.h optimizer.h linwarp.h DOCFILES= smoother_help.help fft2d_help.help fft3d_help.help \ fshrot3d_help.help linrot3d_help.help praxis_help.help \ - nelmin_help.help coordsys_help.help fmin_help.help + nelmin_help.help coordsys_help.help fmin_help.help \ + linwarp_help.help +# +# quaternion.i is a SWIG input file to generate quaternion_wrap.c . It +# won't normally be needed, but is included for completeness. +# +MISCFILES= quaternion.i + FMRI_OBJ= $O/fmri.o $O/fft2d.o $O/fshrot.o $O/polyt.o $O/glm.o \ $O/smoother.o $O/parsesplit.o $O/fft3d.o $O/quaternion.o \ $O/fshrot3d.o $O/linrot3d.o $O/praxis.o $O/history.o \ - $O/filetypes.o $O/kvhash.o $O/bvls.o $O/fmin.o + $O/filetypes.o $O/kvhash.o $O/bvls.o $O/fmin.o $O/optimizer.o \ + $O/linwarp.o include ../Makefile.pkg @@ -66,6 +76,9 @@ $O/linrot3d.o: linrot3d.c $(CC_RULE) +$O/linwarp.o: linwarp.c + $(CC_RULE) + $O/polyt.o: polyt.c $(CC_RULE) @@ -93,6 +106,15 @@ $(CB)/smoother_tester: $O/smoother_tester.o $L/libfmri.a $(SINGLE_LD) +$O/optimizer.o: optimizer.c + $(CC_RULE) + +$O/optimizer_tester.o: optimizer_tester.c + $(CC_RULE) + +$(CB)/optimizer_tester: $O/optimizer_tester.o $L/libfmri.a + $(SINGLE_LD) + $O/parsesplit.o: parsesplit.c $(CC_RULE) @@ -107,6 +129,25 @@ $O/chirprot.o: chirprot.c $(CC_RULE) + +$O/quaternion_wrap.o: quaternion_wrap.c + @echo "%%%% Compiling the Python quaternion wrapper ${@F:.o=.c} %%%%" + @cc -c \ + -I`python -c 'import sys; print sys.prefix+"/include/python"+sys.version[:3]'` \ + quaternion_wrap.c -o $@ + +quaternion_wrap.c: quaternion.i + swig -python quaternion.i + @echo '###############################################################' + @echo '######## Regenerated quaternion_wrap.c! #########' + @echo '######## You need to encorporate ./quaternion.py into #########' + @echo '######## the version of fiasco_utils.py in ../csh! #########' + @echo '###############################################################' + +$(CB)/_quaternion.$(SHR_EXT): $O/quaternion_wrap.o $O/quaternion.o $L/libmisc.a + @echo "%%%% Building shared lib ${@F} %%%%" + @$(SHR_LD) -o $@ $O/quaternion_wrap.o $O/quaternion.o -L$(L) \ + -lmisc $(LAPACK_LIBS) releaseprep: echo "no release prep from " `pwd` Index: src/fmri/fmri.h =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/fmri.h,v retrieving revision 1.19 retrieving revision 1.21 diff -a -u -r1.19 -r1.21 --- src/fmri/fmri.h 4 Apr 2003 00:47:13 -0000 1.19 +++ src/fmri/fmri.h 18 Mar 2004 01:31:14 -0000 1.21 @@ -72,18 +72,21 @@ void fqsrt( float* v, long left, long right ); /* Optimization functions (in polyt.c, praxis.c, bvls.c) */ -extern int nelmin_t(float (*fn)(), void (*rst)(), int* n, - float* start, float* mmin, float* ynewl, float* reqmin, - float* step, int* konvge, int* kcount, int* icount, - int* numres, int* ifault, int* maxres, float* tcritsqr); -extern int nelmin(float (*fn)(), void (*rst)(), int* n, - float* start, float* mmin, float* ynewl, float* reqmin, - float* step, int* konvge, int* kcount, int* icount, - int* numres, int* ifault, int* maxres); +extern int nelmin_t(float (*fn)(float*,void*), void (*rst)(float*,void*), + int* n, float* start, float* mmin, float* ynewl, + float* reqmin, float* step, int* konvge, int* kcount, + int* icount, int* numres, int* ifault, int* maxres, + float* tcritsqr, void* userHook); +extern int nelmin(float (*fn)(float*,void*), void (*rst)(float*,void*), + int* n, float* start, float* mmin, float* ynewl, + float* reqmin, float* step, int* konvge, int* kcount, + int* icount, int* numres, int* ifault, int* maxres, + void* userHook); extern double praxis(double t0, double machep, double h0, int n, int prin, - double* x, double (*f)(double*,int), - void (*reset)(double*,int), double fmin); + double* x, double (*f)(double*,int,void*), + void (*reset)(double*,int,void*), double fmin, + void* userHook); extern int bvls(long* key, long* m, long* n, double* a, double* b, double* bl, double* bu, @@ -115,11 +118,17 @@ /* Header for quaternion.c */ #include "quaternion.h" +/* Header file for optimizer.c */ +#include "optimizer.h" + /* Header for fshrot3d.c */ #include "fshrot3d.h" /* Header for linrot3d.c */ #include "linrot3d.h" + +/* Header for linwarp.c */ +#include "linwarp.h" /* Header for history stuff */ #include "history.h" Index: src/fmri/fshrot3d.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/fshrot3d.c,v retrieving revision 1.17 retrieving revision 1.18 diff -a -u -r1.17 -r1.18 --- src/fmri/fshrot3d.c 25 Sep 2003 19:45:42 -0000 1.17 +++ src/fmri/fshrot3d.c 19 Mar 2004 18:27:18 -0000 1.18 @@ -55,7 +55,7 @@ * -Note that the routine expects data presented in z-fastest order! */ -static char rcsid[] = "$Id: fshrot3d.c,v 1.17 2003/09/25 19:45:42 welling Exp $"; +static char rcsid[] = "$Id: fshrot3d.c,v 1.18 2004/03/19 18:27:18 welling Exp $"; /* How bad does cancellation have to get before we consider a quat bad? */ #define CANCELLATION_TOL 0.01 @@ -911,7 +911,7 @@ step_repairing_quat( result, q, step+1 ); else Abort( - "step_repairing_quat: could not find good soln for quaternion %f %f %f %f!", + "step_repairing_quat: could not find good soln for quaternion %f %f %f %f!\n", q->x,q->y,q->z,q->w); } Index: src/fmri/linwarp.c =================================================================== RCS file: src/fmri/linwarp.c diff -N src/fmri/linwarp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/fmri/linwarp.c 18 Mar 2004 01:31:14 -0000 1.1 @@ -0,0 +1,256 @@ +/************************************************************ + * * + * linwarp.c * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * * + * Copyright (c) 2000 Department of Statistics * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Derived from linrot3d by Joel Welling 3/2004 * + ************************************************************/ +/* Implementation of 3D rotation and shift by linear interpolation */ + +#include +#include +#include +#include +#include "mri.h" +#include "fmri.h" +#include "stdcrg.h" +#include "misc.h" + +static char rcsid[] = "$Id: linwarp.c,v 1.1 2004/03/18 01:31:14 welling Exp $"; + +/* Notes- + * + */ + +/* Accessor for 3D arrays. If this is changed, the striding math in + * the main interpolation routine must also be changed. + */ +#define MEM(matrix,nx,ny,nz,x,y,z) matrix[((((x)*ny)+(y))*nz)+(z)] + +/* Tolerance for coord calculations (allow for numerical noise) */ +#define EPSILON 0.000001 + +/* Linear interpolation, up to 3 steps. Scale factors are: + * + * a is 0.0 on l side of l-r direction + * b is 0.0 on d side of d-u direction + * c is 0.0 on f side of f-b direction + */ + + +#define LIN( l, r, a ) ( ( (a)<=0.0 ) ? (l) : ( ((a)>=1.0) ? (r) : \ + ( (l)*(1.0-(a)) + (r)*(a) ) ) ) +#define LIN2( ld, rd, lu, ru, a, b ) LIN( LIN(ld,rd,a), LIN(lu,ru,a), b ) +#define LIN3( ldf, rdf, luf, ruf, ldb, rdb, lub, rub, a, b, c ) \ + LIN( LIN2( ldf, rdf, luf, ruf, a, b ), LIN2( ldb, rdb, lub, rub, a, b ), c ) + +static int debug= 0; +static int count_calls= 0; + +void linwarp_set( int flag, int value ) +{ + switch (flag) { + case LWARP_DEBUG: { + debug= value; + } + break; + } +} + +int linwarp_get( int flag ) +{ + switch (flag) { + case LWARP_DEBUG: { + return debug; + } + /* break; -NOTREACHED- */ + default: + Abort("linwarp_get: unknown flag %d!\n",flag); + } + return 0; /* not reached */ +} + +void linwarp_set_debug( int flag ) +{ + linwarp_set( LWARP_DEBUG, flag ); +} + +void linwarp_clear_counts() +{ + count_calls= 0; +} + +void linwarp_get_counts( int* ncalls ) +{ + *ncalls= count_calls; +} + +/* + * Transform t_in values specify the warp (in mm) + * orig_image is input + * moved_image is output + * check is output; non-zero where moved_image data is valid + * nx, ny, nz are grid dimensions + * length_x, length_y, length_z are voxel edge lengths + * kspace_flag should be set if both real and imaginary parts should + * be transformed; if it's zero only the real half of the input data + * will be used. + * + * Input and output data are assumed to be ordered such that z is + * fastest in memory. + */ +void linwarp_warp( Transform t_in, + FComplex* orig_image, + FComplex* moved_image, + char* check, + long nx, long ny, long nz, + double length_x, double length_y, double length_z, + int kspace_flag) +{ + Vec4 pout; /* point in output space (grid-aligned) */ + Vec4 p; /* point in input space */ + long i, j, k; + long iout, jout, kout; + long halfx= nx/2; + long halfy= ny/2; + long halfz= nz/2; + Transform t; + Transform tTemp; + +#ifdef never + double xmin= 1000.0; + double xmax= -1000.0; + double ymin= 1000.0; + double ymax= -1000.0; + double zmin= 1000.0; + double zmax= -1000.0; +#endif + + /* Step counter */ + count_calls++; + + /* Make a version of the transform in which the voxel scale + * factors have been sucked into the matrix. Signs of terms + * are determined by relationship between grid and 3D (radiological) + * coords. + */ + trans_identity(tTemp); + tTemp[0]= length_x/(double)nx; + tTemp[5]= -length_y/(double)ny; + tTemp[10]= length_z/(double)nz; + trans_copy(t, t_in); + trans_mult_right(t,tTemp); + tTemp[0]= 1.0/tTemp[0]; + tTemp[5]= 1.0/tTemp[5]; + tTemp[10]= 1.0/tTemp[10]; + trans_mult_left(tTemp,t); + + /* Just do it */ + pout[3]= 1.0; + for (iout=0; ioutxmax) xmax= p[0]; + if (p[1]ymax) ymax= p[1]; + if (p[2]zmax) zmax= p[2]; +#endif + if ((p[0]<(-EPSILON)) || (p[0]>(double)(nx-1)) + || (p[1]<(-EPSILON)) || (p[1]>(double)(ny-1)) + || (p[2]<(-EPSILON)) || (p[2]>(double)(nz-1))) { + + /* This point maps outside the input array */ + MEM(moved_image,nx,ny,nz,iout,jout,kout).real= 0.0; + if (kspace_flag) + MEM(moved_image,nx,ny,nz,iout,jout,kout).imag= 0.0; + MEM(check,nx,ny,nz,iout,jout,kout)= 0; /* mark out */ + + } + else { + /* Valid location */ + double ax, ay, az; + FComplex* here; + + i= (int)floor( p[0] ); + if (i<0) i= 0; + ax= p[0]-i; + j= (int)floor( p[1] ); + if (j<0) j= 0; + ay= p[1]-j; + k= (int)floor( p[2] ); + if (k<0) k= 0; + az= p[2]-k; + + here= (&(MEM(orig_image,nx,ny,nz,i,j,k))); + MEM(moved_image,nx,ny,nz,iout,jout,kout).real= + LIN3( here->real, + (here + ny*nz)->real, + (here + nz)->real, + (here + ny*nz + nz)->real, + (here + 1)->real, + (here + ny*nz + 1)->real, + (here + nz + 1)->real, + (here + ny*nz + nz + 1)->real, + ax, ay, az ); + + if (kspace_flag) { + MEM(moved_image,nx,ny,nz,iout,jout,kout).imag= + LIN3( here->imag, + (here + ny*nz)->imag, + (here + nz)->imag, + (here + ny*nz + nz)->imag, + (here + 1)->imag, + (here + ny*nz + 1)->imag, + (here + nz + 1)->imag, + (here + ny*nz + nz + 1)->imag, + ax, ay, az ); + } + else { + MEM(moved_image,nx,ny,nz,iout,jout,kout).imag= 0.0; + } + + MEM(check,nx,ny,nz,iout,jout,kout)= 1; /* mark in */ + } + } + } + } +#ifdef never + fprintf(stderr,"mapping %g +#include +#include +#include +#include +#include "mri.h" +#include "fmri.h" /* Includes optimizer.h */ +#include "lapack.h" +#include "misc.h" +#include "stdcrg.h" + +static char rcsid[] = "$Id: optimizer.c,v 1.3 2004/03/19 18:27:18 welling Exp $"; + +static double praxis_machep= 0.0; + +typedef struct SSFData { + double (*value)(const double*, const int, void*); + void (*reset)(const double*, const int, void*); + void* userHook; + int n; +} SSFData; + +static void ssfDestroySelf( ScalarFunction* self ) +{ + if (self->data) free(self->data); + free(self); +} + +static double ssfValue( ScalarFunction* sf, const double* par, const int nPar ) +{ + SSFData* d= (SSFData*)(sf->data); + if (nPar != d->n) + Abort("ssfValue: dimensionalities %d and %d do not match!\n",nPar,d->n); + return d->value(par, d->n, d->userHook ); +} + +static void ssfReset( ScalarFunction* sf, const double* par, const int nPar ) +{ + SSFData* d= (SSFData*)(sf->data); + if (nPar != d->n) + Abort("ssfReset: dimensionalities %d and %d do not match!\n",nPar,d->n); + d->reset(par, d->n, d->userHook ); +} + +ScalarFunction* buildSimpleScalarFunction( + double (*value)(const double*, const int, void*), + void (*reset)(const double*, const int, void*), + const int nDim, void* userHook) +{ + ScalarFunction* result= NULL; + SSFData* d= NULL; + if (!(result=(ScalarFunction*)malloc(sizeof(ScalarFunction)))) + Abort("buildSimpleScalarFunction: unable to allocate %d bytes!\n", + sizeof(ScalarFunction)); + if (!(d=(SSFData*)malloc(sizeof(SSFData)))) + Abort("buildSimpleScalarFunction: unable to allocate %d bytes!\n", + sizeof(SSFData)); + d->value= value; + d->reset= reset; + d->n= nDim; + d->userHook= userHook; + result->data= d; + result->destroySelf= ssfDestroySelf; + result->value= ssfValue; + result->reset= ssfReset; +} + +static const char* baseGetMethodName(Optimizer* self) +{ + static const char* name= "base"; + return name; +} + +static char* baseGetStringRep(Optimizer* self) +{ + return strdup("BaseOptimizer()"); +} + +static void baseDestroySelf(Optimizer* self) +{ + if (self->data) free(self->data); + free(self); +} + +static void baseSetDebugLevel(Optimizer* self, const int lvl) +{ + self->debugLevel= lvl; +} + +static int baseGetDebugLevel(Optimizer* self) +{ + return self->debugLevel; +} + +static int baseGo(Optimizer* self, ScalarFunction* f, double* par, + const int nPar, double* best) +{ + Abort("baseGo: tried to run an instance of base Optimizer class!\n"); + return 0; +} + +Optimizer* createBaseOptimizer() +{ + Optimizer* result; + + if (!(result=(Optimizer*)malloc(sizeof(Optimizer)))) + Abort("createBaseOptimizer: unable to allocate %d bytes!\n", + sizeof(Optimizer)); + + result->data= NULL; + result->debugLevel= 0; + result->getMethodName= baseGetMethodName; + result->getStringRep= baseGetStringRep; + result->destroySelf= baseDestroySelf; + result->go= baseGo; + result->setDebugLevel= baseSetDebugLevel; + result->getDebugLevel= baseGetDebugLevel; + + return result; +} + +static const char* noneGetMethodName(Optimizer* self) +{ + static const char* name= "none"; + return name; +} + +static char* noneGetStringRep(Optimizer* self) +{ + return strdup("NoneOptimizer()"); +} + +static int noneGo(Optimizer* self, ScalarFunction* f, double* par, + const int nPar, double* best) +{ + int i; + *best= f->value(f,par,nPar); + return 1; +} + +Optimizer* createNoneOptimizer() +{ + Optimizer* result= createBaseOptimizer(); + + result->getMethodName= noneGetMethodName; + result->getStringRep= noneGetStringRep; + result->go= noneGo; +} + +typedef struct PraxisData { + double t0; + double h0; +} PraxisData; + +static const char* praxisGetMethodName(Optimizer* self) +{ + static const char* name= "praxis"; + return name; +} + +static char* praxisGetStringRep(Optimizer* self) +{ + PraxisData* pd= (PraxisData*)(self->data); + char buf[256]; + snprintf(buf,sizeof(buf), + "PraxisOptimizer(%lg,%lg)",pd->t0,pd->h0); + return strdup(buf); +} + +static double praxisValue( double* par, int nPar, + void* p) +{ + ScalarFunction* sf= (ScalarFunction*)p; + return sf->value(sf,par,nPar); +} + +static void praxisReset( double* par, int nPar, + void* p) +{ + ScalarFunction* sf= (ScalarFunction*)p; + sf->reset(sf,par,nPar); +} + +static int praxisGo(Optimizer* self, ScalarFunction* f, double* par, + const int nPar, double* best) +{ + PraxisData* pd= (PraxisData*)(self->data); + int prx_npar= nPar; + + *best= praxis(pd->t0, praxis_machep, pd->h0, prx_npar, self->debugLevel, + par, praxisValue, praxisReset, 0.0, f); +} + +Optimizer* createPraxisOptimizer(double t0, double h0) +{ + Optimizer* result= createBaseOptimizer(); + PraxisData* pd= NULL; + + if (result->data) free(result->data); + if (!(pd=(PraxisData*)malloc(sizeof(PraxisData)))) + Abort("createPraxisOptimizer: unable to allocate %d bytes!\n"); + result->data= pd; + pd->t0= t0; + pd->h0= h0; + if (praxis_machep==0.0) { + praxis_machep= (2.0*DLAMCH("e")); +#ifdef never + fprintf(stderr,"machine eps = %lg\n",praxis_machep); +#endif + } + if ((1.0+praxis_machep) == 1.0) + Abort("createPraxisOptimizer: precision test failed!\n"); + + result->getMethodName= praxisGetMethodName; + result->getStringRep= praxisGetStringRep; + result->go= praxisGo; + + return result; +} + +typedef struct NelminData { + float* startBuf; + float* valBuf; + float* scaleBuf; + double* doubleBuf; + int bufLength; + int nPar; + float scale; + float stopping_val; + ScalarFunction* sf; +} NelminData; + +static const char* nelminGetMethodName(Optimizer* self) +{ + static const char* name= "nelmin"; + return name; +} + +static char* nelminGetStringRep(Optimizer* self) +{ + NelminData* pd= (NelminData*)(self->data); + char buf[256]; + snprintf(buf,sizeof(buf), + "NelminOptimizer(%g,%g)",pd->stopping_val,pd->scale); + return strdup(buf); +} + +static float nelminValue( float* par, void* p) +{ + NelminData* d= (NelminData*)p; + int i; + for (i=0; inPar; i++) d->doubleBuf[i]= par[i]; + return (float)(d->sf->value(d->sf,d->doubleBuf,d->nPar)); +} + +static void nelminReset( float* par, void* p) +{ + NelminData* d= (NelminData*)p; + int i; + for (i=0; inPar; i++) d->doubleBuf[i]= par[i]; + d->sf->reset(d->sf,d->doubleBuf,d->nPar); +} + +static int nelminGo(Optimizer* self, ScalarFunction* f, double* par, + const int nPar, double* best) +{ + int numpar; + int steps_per_conv_check = 3; + int max_iter = 800, max_restart = 12; + int num_iter=0, num_restart=0, return_cond=0; + float mseval= -1.0; + NelminData* pd= (NelminData*)(self->data); + int lcl_npar= nPar; + int i; + int retval= 0; + + if (pd->bufLengthstartBuf) free(pd->startBuf); + if (pd->valBuf) free(pd->valBuf); + if (!(pd->startBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->valBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->scaleBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->doubleBuf=(double*)malloc(nPar*sizeof(double)))) + Abort("nelminGo: cannot allocate %d bytes!\n",nPar*sizeof(double)); + pd->bufLength= nPar; + } + + for (i=0; istartBuf[i]= pd->valBuf[i]= (float)par[i]; + pd->scaleBuf[i]= pd->scale; + } + pd->nPar= nPar; + pd->sf= f; + + nelmin( nelminValue, nelminReset, + &lcl_npar, pd->startBuf, pd->valBuf, &mseval, + &(pd->stopping_val), pd->scaleBuf, &steps_per_conv_check, + &max_iter, &num_iter, &num_restart, &return_cond, &max_restart, + pd ); + if (return_cond != 0) { + if (self->debugLevel) + Message("Nelmin optimization failed on return code %d\n",return_cond); + if (return_cond==2) + Warning(1,"nelminGo: Nelder-Mead convergence failed!\n"); + else + Warning(1,"nelminGo: Nelder-Mead call illegal value!\n"); + Warning(1," failed at iter = %d of %d, restart= %d of %d\n", + num_iter, max_iter, num_restart, max_restart); + retval= 0; + } + else retval= 1; + + *best= (double)mseval; + for (i=0; ivalBuf[i]; + return retval; +} + +Optimizer* createNelminOptimizer(double stopping_val, double scale) +{ + Optimizer* result= createBaseOptimizer(); + NelminData* pd= NULL; + + if (result->data) free(result->data); + if (!(pd=(NelminData*)malloc(sizeof(NelminData)))) + Abort("createNelminOptimizer: unable to allocate %d bytes!\n"); + result->data= pd; + pd->startBuf= NULL; + pd->valBuf= NULL; + pd->scaleBuf= NULL; + pd->bufLength= 0; + pd->nPar= 0; + pd->stopping_val= (float)stopping_val; + pd->scale= (float)scale; + + result->getMethodName= nelminGetMethodName; + result->getStringRep= nelminGetStringRep; + result->go= nelminGo; + + return result; +} + +typedef struct NelminTData { + float* startBuf; + float* valBuf; + float* scaleBuf; + double* doubleBuf; + int bufLength; + int nPar; + float scale; + float stopping_val; + float Tval; + ScalarFunction* sf; +} NelminTData; + +static const char* nelminTGetMethodName(Optimizer* self) +{ + static const char* name= "nelmin_t"; + return name; +} + +static char* nelminTGetStringRep(Optimizer* self) +{ + NelminTData* pd= (NelminTData*)(self->data); + char buf[256]; + snprintf(buf,sizeof(buf), + "NelminTOptimizer(%g,%g,%g)",pd->stopping_val,pd->scale,pd->Tval); + return strdup(buf); +} + +static float nelminTValue( float* par, void* p) +{ + NelminTData* d= (NelminTData*)p; + int i; + for (i=0; inPar; i++) d->doubleBuf[i]= par[i]; + return (float)(d->sf->value(d->sf,d->doubleBuf,d->nPar)); +} + +static void nelminTReset( float* par, void* p) +{ + NelminTData* d= (NelminTData*)p; + int i; + for (i=0; inPar; i++) d->doubleBuf[i]= par[i]; + d->sf->reset(d->sf,d->doubleBuf,d->nPar); +} + +static int nelminTGo(Optimizer* self, ScalarFunction* f, double* par, + const int nPar, double* best) +{ + int numpar; + int steps_per_conv_check = 3; + int max_iter = 800, max_restart = 12; + int num_iter=0, num_restart=0, return_cond=0; + float mseval= -1.0; + NelminTData* pd= (NelminTData*)(self->data); + int lcl_npar= nPar; + int i; + int retval= 0; + float tCritSqr= pd->Tval*pd->Tval; + + if (pd->bufLengthstartBuf) free(pd->startBuf); + if (pd->valBuf) free(pd->valBuf); + if (!(pd->startBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminTGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->valBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminTGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->scaleBuf=(float*)malloc(nPar*sizeof(float)))) + Abort("nelminTGo: cannot allocate %d bytes!\n",nPar*sizeof(float)); + if (!(pd->doubleBuf=(double*)malloc(nPar*sizeof(double)))) + Abort("nelminTGo: cannot allocate %d bytes!\n",nPar*sizeof(double)); + pd->bufLength= nPar; + } + + for (i=0; istartBuf[i]= pd->valBuf[i]= (float)par[i]; + pd->scaleBuf[i]= pd->scale; + } + pd->nPar= nPar; + pd->sf= f; + + nelmin_t( nelminTValue, nelminTReset, + &lcl_npar, pd->startBuf, pd->valBuf, &mseval, + &(pd->stopping_val), pd->scaleBuf, &steps_per_conv_check, + &max_iter, &num_iter, &num_restart, &return_cond, &max_restart, + &tCritSqr, pd ); + if (return_cond != 0) { + if (self->debugLevel) + Message("NelminT optimization failed on return code %d\n",return_cond); + if (return_cond==2) + Warning(1,"nelminTGo: Nelder-Mead convergence failed!\n"); + else + Warning(1,"nelminTGo: Nelder-Mead call illegal value!\n"); + Warning(1," failed at iter = %d of %d, restart= %d of %d\n", + num_iter, max_iter, num_restart, max_restart); + retval= 0; + } + else retval= 1; + + *best= (double)mseval; + for (i=0; ivalBuf[i]; + return retval; +} + +Optimizer* createNelminTOptimizer(double stopping_val, double scale, + double Tval) +{ + Optimizer* result= createBaseOptimizer(); + NelminTData* pd= NULL; + + if (result->data) free(result->data); + if (!(pd=(NelminTData*)malloc(sizeof(NelminTData)))) + Abort("createNelminTOptimizer: unable to allocate %d bytes!\n"); + result->data= pd; + pd->startBuf= NULL; + pd->valBuf= NULL; + pd->scaleBuf= NULL; + pd->bufLength= 0; + pd->nPar= 0; + pd->stopping_val= (float)stopping_val; + pd->scale= (float)scale; + pd->Tval= Tval; + + result->getMethodName= nelminTGetMethodName; + result->getStringRep= nelminTGetStringRep; + result->go= nelminTGo; + + return result; +} + +Optimizer* optimizerFromStringRep( const char* rep ) +{ + char* args= strchr(rep,'('); + if ( !args || (args-rep)<1 ) return NULL; + if (!strncmp(rep,"BaseOptimizer",strlen("BaseOptimizer"))) { + return createBaseOptimizer(); + } + else if (!strncmp(rep,"NoneOptimizer",strlen("NoneOptimizer"))) { + return createNoneOptimizer(); + } + else if (!strncmp(rep,"PraxisOptimizer",strlen("PraxisOptimizer"))) { + double t0; + double h0; + int n= sscanf(args,"(%lg,%lg)",&t0,&h0); + if (n==2) return createPraxisOptimizer(t0,h0); + else return NULL; + } + else if (!strncmp(rep,"NelminOptimizer",strlen("NelminOptimizer"))) { + float stopping_val; + float scale; + int n= sscanf(args,"(%g,%g)",&stopping_val,&scale); + if (n==2) return createNelminOptimizer(stopping_val,scale); + else return NULL; + } + else if (!strncmp(rep,"NelminTOptimizer",strlen("NelminTOptimizer"))) { + float stopping_val; + float scale; + float Tval; + int n= sscanf(args,"(%g,%g,%g)",&stopping_val,&scale,&Tval); + if (n==3) return createNelminTOptimizer(stopping_val,scale,Tval); + else return NULL; + } + else return NULL; +} + + Index: src/fmri/optimizer.h =================================================================== RCS file: src/fmri/optimizer.h diff -N src/fmri/optimizer.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/fmri/optimizer.h 17 Mar 2004 00:09:11 -0000 1.2 @@ -0,0 +1,68 @@ +/************************************************************ + * * + * optimizer.h * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * Copyright (c) 1998 Department of Statistics, * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Original programming by Joel Welling, 2/2004 * + ************************************************************/ +/* This package implements smoothing methods. */ + +#ifndef INCL_OPTIMIZER_H +#define INCL_OPTIMIZER_H 1 + +typedef struct ScalarFunction { + double (*value)( struct ScalarFunction* self, + const double* par, const int nPar ); + void (*reset)( struct ScalarFunction* self, const double* par, + const int nPar ); + void (*destroySelf)( struct ScalarFunction* self ); + int nPar; + void* data; +} ScalarFunction; + +typedef struct Optimizer { + const char* (*getMethodName)(struct Optimizer* self); + char* (*getStringRep)(struct Optimizer* self); + void (*setDebugLevel)(struct Optimizer* self, const int lvl); + int (*getDebugLevel)(struct Optimizer* self); + int (*go)( struct Optimizer* self, ScalarFunction* f, + double* par, const int nPar, double* best); + void (*destroySelf)(struct Optimizer* self); + int debugLevel; + void* data; +} Optimizer; + +ScalarFunction* buildSimpleScalarFunction( + double (*value)(const double*, const int, void*), + void (*reset)(const double*, const int, void*), + const int nDim, void* userHook); + +Optimizer* optimizerFromStringRep( const char* rep ); +Optimizer* createBaseOptimizer(); +Optimizer* createNoneOptimizer(); +Optimizer* createPraxisOptimizer(double t0, double h0); +Optimizer* createNelminOptimizer(double stopping_val, double scale); +Optimizer* createNelminTOptimizer(double stopping_val, double scale, double T); + +#endif /* ifndef INCL_OPTIMIZER_H */ Index: src/fmri/optimizer_tester.c =================================================================== RCS file: src/fmri/optimizer_tester.c diff -N src/fmri/optimizer_tester.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/fmri/optimizer_tester.c 1 Mar 2004 05:41:42 -0000 1.1 @@ -0,0 +1,111 @@ +/************************************************************ + * * + * optimizer_tester.c * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * * + * Copyright (c) 1999 Department of Statistics * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Original programming by Joel Welling 2/2004 * + ************************************************************/ + +#include +#include +#include +#include +#include + +typedef struct Data { + double A; + double B; + double C; + double D; +} Data; + +static double value( ScalarFunction* sf, const double* par, const int nPar ) +{ + double result; + Data* data= (Data*)(sf->data); + if (nPar != 3) + Abort("Wrong number of parameters in optimizer_tester:value()!\n"); + result= (par[0]-data->A)*(par[0]-data->A) + + (par[1]-data->B)*(par[1]-data->B) + + (par[2]-data->C)*(par[2]-data->C) + + data->D; + fprintf(stderr,"eval! %g %g %g -> %g\n",par[0],par[1],par[2],result); + + return result; +} + +static void reset( ScalarFunction* sf, const double* par, const int nPar ) +{ + Data* data= (Data*)(sf->data); + if (nPar != 3) + Abort("Wrong number of parameters in optimizer_tester:value()!\n"); + fprintf(stderr,"reset! %g %g %g\n",par[0],par[1],par[2]); +} + +static void destroy( ScalarFunction* sf ) +{ + free(sf); +} + +int main( int argc, char* argv[] ) +{ + ScalarFunction* sf= NULL; + Optimizer* opt= NULL; + Data data; + char inbuf[81]; + double par[3]; + int i; + double best; + int code; + + if (!(sf=(ScalarFunction*)malloc(sizeof(ScalarFunction*)))) + Abort("%s: unable to allocate %d bytes!\n",argv[0]); + sf->value= value; + sf->reset= reset; + sf->destroySelf= destroy; + sf->data= &data; + sf->nPar= 3; + + data.A= 3.0; + data.B= 5.0; + data.C= -1.0; + data.D= 7.0; + + printf("Enter the character encoding of an optimizer\n"); + fgets(inbuf,80,stdin); + inbuf[strlen(inbuf)-1]= '\0'; /* strip trailing newline */ + opt= optimizerFromStringRep( inbuf ); + fprintf(stderr,"Stringrep is <%s> vs. your input <%s>\n", + opt->getStringRep(opt),inbuf); + opt->setDebugLevel(opt,4); + fprintf(stderr,"debugLevel set to %d\n",opt->getDebugLevel(opt)); + for (i=0; igo(opt, sf, par, sizeof(par)/sizeof(double), &best); + fprintf(stderr,"Result code: %d\n",code); + for (i=0; idestroySelf(opt); +} Index: src/fmri/polyt.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/polyt.c,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- src/fmri/polyt.c 20 Mar 2000 20:10:58 -0000 1.6 +++ src/fmri/polyt.c 1 Mar 2004 05:41:42 -0000 1.7 @@ -37,16 +37,17 @@ #include "mri.h" #include "fmri.h" -static char rcsid[] = "$Id: polyt.c,v 1.6 2000/03/20 20:10:58 welling Exp $"; +static char rcsid[] = "$Id: polyt.c,v 1.7 2004/03/01 05:41:42 welling Exp $"; #define TTEST( val, mean, var, tcritsqr ) \ (((val-mean)*(val-mean))>(tcritsqr*var)) /* Subroutine */ -int nelmin_t(float (*fn)(), void (*rst)(), int* n, +int nelmin_t(float (*fn)(float*,void*), void (*rst)(float*,void*), int* n, float* start, float* mmin, float* ynewl, float* reqmin, float* step, int* konvge, int* kcount, int* icount, - int* numres, int* ifault, int* maxres, float* tcritsqr) + int* numres, int* ifault, int* maxres, float* tcritsqr, + void* userHook) { /* Initialized data */ @@ -162,13 +163,13 @@ /* CONSTRUCTION OF INITIAL SIMPLEX */ L1001: - (*rst)(&start[1]); + (*rst)(&start[1],userHook); i_1 = *n; for (i = 1; i <= i_1; ++i) { /* L1: */ p[i + nn * 20 - 21] = start[i]; } - z = prevylo = (*fn)(&start[1]); + z = prevylo = (*fn)(&start[1],userHook); y[nn - 1] = z; i_1 = *n; for (j = 1; j <= i_1; ++j) { @@ -179,7 +180,7 @@ /* L3: */ p[i + j * 20 - 21] = start[i]; } - z = (*fn)(&start[1]); + z = (*fn)(&start[1],userHook); y[j - 1] = z; /* L2: */ start[j] = x; @@ -216,7 +217,7 @@ if(ylo= ylo) { goto L12; @@ -258,7 +259,7 @@ p2star[i - 1] = ecoeff * pstar[i - 1] + ((float)1. - ecoeff) * pbar[i - 1]; } - y2star = (*fn)(p2star); + y2star = (*fn)(p2star,userHook); ++(*icount); /* RETAIN EXTENSION OR CONTRACTION. */ @@ -309,7 +310,7 @@ p2star[i - 1] = ccoeff * p[i + ihi * 20 - 21] + ((float)1. - ccoeff) * pbar[i - 1]; } - y2star = (*fn)(p2star); + y2star = (*fn)(p2star,userHook); ++(*icount); if (y2star <= y[ihi - 1]) { goto L10; @@ -327,7 +328,7 @@ mmin[i] = p[i + j * 20 - 21]; } /* L18: */ - y[j - 1] = (*fn)(&mmin[1]); + y[j - 1] = (*fn)(&mmin[1],userHook); } *icount += nn; goto L901; @@ -401,13 +402,13 @@ for (i = 1; i <= i_1; ++i) { del = step[i] * (float).001; mmin[i] += del; - z = (*fn)(&mmin[1]); + z = (*fn)(&mmin[1],userHook); ++(*icount); if ((z<*ynewl) && TTEST(z,dsum,sigma_dist,*tcritsqr)) { goto L25; } mmin[i] = mmin[i] - del - del; - z = (*fn)(&mmin[1]); + z = (*fn)(&mmin[1],userHook); ++(*icount); if ((z<*ynewl) && TTEST(z,dsum,sigma_dist,*tcritsqr)) { goto L25; @@ -435,10 +436,10 @@ } /* nelmin_ */ /* Subroutine */ -int nelmin(float (*fn)(), void (*rst)(), int* n, +int nelmin(float (*fn)(float*,void*), void (*rst)(float*,void*), int* n, float* start, float* mmin, float* ynewl, float* reqmin, float* step, int* konvge, int* kcount, int* icount, int* numres, - int* ifault, int* maxres) + int* ifault, int* maxres, void* userHook) { /* Initialized data */ @@ -550,13 +551,13 @@ /* CONSTRUCTION OF INITIAL SIMPLEX */ L1001: - (*rst)(&start[1]); + (*rst)(&start[1],userHook); i_1 = *n; for (i = 1; i <= i_1; ++i) { /* L1: */ p[i + nn * 20 - 21] = start[i]; } - z = prevylo = (*fn)(&start[1]); + z = prevylo = (*fn)(&start[1],userHook); y[nn - 1] = z; i_1 = *n; for (j = 1; j <= i_1; ++j) { @@ -567,7 +568,7 @@ /* L3: */ p[i + j * 20 - 21] = start[i]; } - z = (*fn)(&start[1]); + z = (*fn)(&start[1],userHook); y[j - 1] = z; /* L2: */ start[j] = x; @@ -604,7 +605,7 @@ if(ylo= ylo) { goto L12; @@ -646,7 +647,7 @@ p2star[i - 1] = ecoeff * pstar[i - 1] + ((float)1. - ecoeff) * pbar[i - 1]; } - y2star = (*fn)(p2star); + y2star = (*fn)(p2star,userHook); ++(*icount); /* RETAIN EXTENSION OR CONTRACTION. */ @@ -697,7 +698,7 @@ p2star[i - 1] = ccoeff * p[i + ihi * 20 - 21] + ((float)1. - ccoeff) * pbar[i - 1]; } - y2star = (*fn)(p2star); + y2star = (*fn)(p2star,userHook); ++(*icount); if (y2star <= y[ihi - 1]) { goto L10; @@ -715,7 +716,7 @@ mmin[i] = p[i + j * 20 - 21]; } /* L18: */ - y[j - 1] = (*fn)(&mmin[1]); + y[j - 1] = (*fn)(&mmin[1],userHook); } *icount += nn; goto L901; @@ -781,13 +782,13 @@ for (i = 1; i <= i_1; ++i) { del = step[i] * (float).001; mmin[i] += del; - z = (*fn)(&mmin[1]); + z = (*fn)(&mmin[1],userHook); ++(*icount); if (z < *ynewl) { goto L25; } mmin[i] = mmin[i] - del - del; - z = (*fn)(&mmin[1]); + z = (*fn)(&mmin[1],userHook); ++(*icount); if (z < *ynewl) { goto L25; Index: src/fmri/praxis.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/praxis.c,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- src/fmri/praxis.c 25 Sep 2000 23:43:02 -0000 1.5 +++ src/fmri/praxis.c 1 Mar 2004 05:41:42 -0000 1.6 @@ -38,7 +38,7 @@ #include #include "lapack.h" -static char rcsid[] = "$Id: praxis.c,v 1.5 2000/09/25 23:43:02 welling Exp $"; +static char rcsid[] = "$Id: praxis.c,v 1.6 2004/03/01 05:41:42 welling Exp $"; /* Maximum dimensionality of problem */ #define WORK_DIM 20 @@ -64,23 +64,27 @@ double q0[WORK_DIM]; double q1[WORK_DIM]; double qa, qb, qc, qd0, qd1, qf1; + void* userHook; } GlobalState; static int prx_minfit(int m, int n, double machep, double tol, double ab[][WORK_DIM], double* q); static void prx_min(int n, int j, int nits, double* d2, double* x1, - double* f1, int fk, double (*f)(double*,int), + double* f1, int fk, + double (*f)(double*,int,void* userHook), double* x, double t, double machep, double h, GlobalState* gs); -static double prx_flin(int n, int j, double l, double (*f)(double*,int), +static double prx_flin(int n, int j, double l, + double (*f)(double*,int,void* userHook), double* x, GlobalState* gs); static void prx_sort(int m, int n,double* d, double v[][WORK_DIM]); -static void prx_quad(int n, double (*f)(double*,int), double* x, double t, - double machep, double h, GlobalState* gs); +static void prx_quad(int n, double (*f)(double*, int, void* userHook), + double* x, double t, double machep, double h, + GlobalState* gs); static void prx_vcprnt(int option, double* v, int n); @@ -90,8 +94,9 @@ static void prx_maprnt(int option, double v[][WORK_DIM], int m, int n); double praxis(double t0, double machep, double h0, int n, int prin, - double* x, double (*f)(double*,int), void (reset)(double*,int), - double fmin) + double* x, double (*f)(double*,int,void* userHook), + void (reset)(double*,int,void* userHook), + double fmin, void* userHook) { /* REAL*8 FUNCTION PRAXIS(T0,MACHEP,H0,N,PRIN,X,F,FMIN) @@ -131,10 +136,12 @@ C QUADRATIC FORM ARE ALSO PRINTED. C X IS AN ARRAY CONTAINING ON ENTRY A GUESS OF THE POINT OF C MINIMUM, ON RETURN THE ESTIMATED POINT OF MINIMUM. - C F(X,N) IS THE FUNCTION TO BE MINIMIZED. F SHOULD BE A REAL*8 - C FUNCTION DECLARED EXTERNAL IN THE CALLING PROGRAM. + C F(X,N,userHook) IS THE FUNCTION TO BE MINIMIZED. F SHOULD BE + C A REAL*8 FUNCTION DECLARED EXTERNAL IN THE CALLING PROGRAM. + C reset(X,N,userHook) is a reset function associated with F C FMIN IS AN ESTIMATE OF THE MINIMUM, USED ONLY IN PRINTING C INTERMEDIATE RESULTS. + C userHook provided to pass additional data to F and reset C THE APPROXIMATING QUADRATIC FORM IS C Q(X') = F(X,N) + (1/2) * (X'-X)-TRANSPOSE * A * (X'-X) C WHERE X IS THE BEST ESTIMATE OF THE MINIMUM AND A IS @@ -209,6 +216,7 @@ if (illc) ldfac=0.1; kt=0; L30: /* Jump here to recover from bad problems */ + gs.userHook= userHook; gs.nl=0; gs.nf=1; t=small+fabs(t0); @@ -217,7 +225,7 @@ h=h0; if (h<100*t) h=100*t; gs.ldt=h; - gs.fx=f(x,n); + gs.fx=f(x,n,gs.userHook); /* C.....THE FIRST SET OF SEARCH DIRECTIONS V IS THE IDENTITY MATRIX..... */ @@ -247,8 +255,8 @@ C.....MINIMIZE ALONG THE FIRST DIRECTION V(*,1). C FX MUST BE PASSED TO MIN BY VALUE. */ - (*reset)(x,n); - gs.fx=f(x,n); + (*reset)(x,n,gs.userHook); + gs.fx=f(x,n,gs.userHook); gs.qf1=gs.fx; value=gs.fx; prx_min(n,0,2,&(d[0]),&s,&value,0,f,x,t,machep,h,&gs); @@ -292,7 +300,7 @@ for (j=0; jnf += 1; - return (*f)(t,n); + return (*f)(t,n,gs->userHook); } static void prx_sort(int m, int n,double* d, double v[][WORK_DIM]) @@ -843,8 +853,9 @@ } } -static void prx_quad(int n, double (*f)(double*,int), double* x, double t, - double machep, double h, GlobalState* gs) +static void prx_quad(int n, double (*f)(double*,int,void* userHook), + double* x, double t, double machep, double h, + GlobalState* gs) { /* C...QUAD LOOKS FOR THE MINIMUM OF F ALONG A CURVE DEFINED BY Q0,Q1,X... Index: src/fmri/quaternion.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/quaternion.c,v retrieving revision 1.12 retrieving revision 1.13 diff -a -u -r1.12 -r1.13 --- src/fmri/quaternion.c 2 Nov 2000 17:00:59 -0000 1.12 +++ src/fmri/quaternion.c 17 Mar 2004 00:09:11 -0000 1.13 @@ -34,8 +34,9 @@ #include #include "misc.h" #include "fmri.h" +#include "lapack.h" -static char rcsid[] = "$Id: quaternion.c,v 1.12 2000/11/02 17:00:59 welling Exp $"; +static char rcsid[] = "$Id: quaternion.c,v 1.13 2004/03/17 00:09:11 welling Exp $"; /* This package provides manipulations of unit quaternions. Much code was taken from the "Matrix and Quaternions Faq". @@ -115,6 +116,19 @@ return q_out; } +void trans_identity( Transform t_out ) +{ + int i; + for (i=0; i<16; i++) t_out[i]= 0.0; + for (i=0; i<4; i++) t_out[5*i]= 1.0; +} + +void trans_copy( Transform t_out, const Transform t_in ) +{ + int i; + for (i=0; i<16; i++) t_out[i]= t_in[i]; +} + void quat_to_trans( Transform t_out, Quat* q, double dx, double dy, double dz ) { @@ -400,6 +414,26 @@ t[4*i + j]= t[4*j +i]; t[4*j + i]= temp; }; +} + +int trans_inverse( Transform invT, const Transform t ) +{ + int four= 4; + int sixteen= 16; + double work[16]; + int pivots[4]; + int info; + + trans_copy( invT, t ); + DGETRF( &four, &four, invT, &four, pivots, &info ); + if (info>0) return 0; /* failure */ + else if (info<0) + Abort("trans_inverse: internal error; arg %d to DGETRF invalid!\n",-info); + DGETRI( &four, invT, &four, pivots, work, &sixteen, &info ); + if (info==0) return 1; /* success */ + else if (info>0) return 0; /* failure */ + else Abort("trans_inverse: internal error; arg %d to DGETRI invalid!\n",-info); + return 0; /* to keep compilers happy */ } void trans_dump( FILE* ofile, Transform t ) Index: src/fmri/quaternion.h =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/quaternion.h,v retrieving revision 1.6 retrieving revision 1.7 diff -a -u -r1.6 -r1.7 --- src/fmri/quaternion.h 19 Oct 2000 00:29:26 -0000 1.6 +++ src/fmri/quaternion.h 17 Mar 2004 00:09:11 -0000 1.7 @@ -40,11 +40,17 @@ typedef double Transform[16]; /* a homogeneous transform */ +void trans_identity( Transform t_out ); + +void trans_copy( Transform t_out, const Transform t_in ); + void trans_mult_right( Transform t, const Transform factor ); void trans_mult_left( const Transform factor, Transform t ); void trans_transpose( Transform t ); + +int trans_inverse( Transform invT, const Transform T ); void trans_vec_mult( const Transform factor, Vec4 v ); Index: src/fmri/quaternion.i =================================================================== RCS file: src/fmri/quaternion.i diff -N src/fmri/quaternion.i --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/fmri/quaternion.i 1 Mar 2004 05:36:40 -0000 1.2 @@ -0,0 +1,113 @@ +%module quaternion +%{ +#include "quaternion.h" +%} +%typemap(in) double [4] (double temp[4]) { + int i; + if (!PySequence_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a sequence"); + return NULL; + } + if (PySequence_Length($input) != 4) { + PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 4 elements"); + return NULL; + } + for (i = 0; i < 4; i++) { + PyObject *o = PySequence_GetItem($input,i); + if (PyNumber_Check(o)) { + temp[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + $1 = temp; +} +%typemap(in) Vec4 (double temp[4]) { + int i; + for (i = 0; i < 4; i++) { + PyObject *o = PySequence_GetItem($input,i); + if (PyNumber_Check(o)) { + temp[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + $1 = temp; +} +%typemap(in) double [16] (double temp[16]) { + int i; + if (!PySequence_Check($input)) { + PyErr_SetString(PyExc_ValueError,"Expected a sequence"); + return NULL; + } + if (PySequence_Length($input) != 16) { + PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 16 elements"); + return NULL; + } + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem($input,i); + if (PyNumber_Check(o)) { + temp[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + $1 = temp; +} +%typemap(in) Transform (double temp[16]) { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem($input,i); + if (PyNumber_Check(o)) { + temp[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + $1 = temp; +} +%typemap(argout) Transform { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) $1[i]); + PySequence_SetItem($input,i,o); + } +} + +%typemap(argout) Vec4 { + int i; + for (i = 0; i < 4; i++) { + PyObject *o = PyFloat_FromDouble((double) $1[i]); + PySequence_SetItem($input,i,o); + } +} + +%typemap(argout) double [ANY] { + int i; + for (i = 0; i < $1_dim0; i++) { + PyObject *o = PyFloat_FromDouble((double) $1[i]); + PyList_SetItem($input,i,o); + } +} + +%include "quaternion.h" + +%extend Quat { + char *__str__() { + static char tmp[1024]; + sprintf(tmp,"Quat(%g,%g,%g,%g)", self->x,self->y,self->z,self->w); + return tmp; + } + char *__repr__() { + static char tmp[1024]; + sprintf(tmp,"Quat(%g,%g,%g,%g)", self->x,self->y,self->z,self->w); + return tmp; + } + Quat(double x, double y, double z, double w) { + return quat_create(NULL,x,y,z,w);; + } +} Index: src/fmri/quaternion_wrap.c =================================================================== RCS file: src/fmri/quaternion_wrap.c diff -N src/fmri/quaternion_wrap.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/fmri/quaternion_wrap.c 1 Mar 2004 05:37:45 -0000 1.2 @@ -0,0 +1,1592 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.20 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGPYTHON + +#include "Python.h" + +/*************************************************************** -*- c -*- + * python/precommon.swg + * + * Rename all exported symbols from common.swg, to avoid symbol + * clashes if multiple interpreters are included + * + ************************************************************************/ + +#define SWIG_TypeRegister SWIG_Python_TypeRegister +#define SWIG_TypeCheck SWIG_Python_TypeCheck +#define SWIG_TypeCast SWIG_Python_TypeCast +#define SWIG_TypeDynamicCast SWIG_Python_TypeDynamicCast +#define SWIG_TypeName SWIG_Python_TypeName +#define SWIG_TypeQuery SWIG_Python_TypeQuery +#define SWIG_TypeClientData SWIG_Python_TypeClientData +#define SWIG_PackData SWIG_Python_PackData +#define SWIG_UnpackData SWIG_Python_UnpackData + + +/*********************************************************************** + * common.swg + * + * This file contains generic SWIG runtime support for pointer + * type checking as well as a few commonly used macros to control + * external linkage. + * + * Author : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (c) 1999-2000, The University of Chicago + * + * This file may be freely redistributed without license or fee provided + * this copyright message remains intact. + ************************************************************************/ + +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(_MSC_VER) || defined(__GNUC__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT(a) a +# define SWIGIMPORT(a) extern a +# else +# define SWIGEXPORT(a) __declspec(dllexport) a +# define SWIGIMPORT(a) extern a +# endif +# else +# if defined(__BORLANDC__) +# define SWIGEXPORT(a) a _export +# define SWIGIMPORT(a) a _export +# else +# define SWIGEXPORT(a) a +# define SWIGIMPORT(a) a +# endif +# endif +#else +# define SWIGEXPORT(a) a +# define SWIGIMPORT(a) a +#endif + +#ifdef SWIG_GLOBAL +# define SWIGRUNTIME(a) SWIGEXPORT(a) +#else +# define SWIGRUNTIME(a) static a +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +typedef struct swig_type_info { + const char *name; + swig_converter_func converter; + const char *str; + void *clientdata; + swig_dycast_func dcast; + struct swig_type_info *next; + struct swig_type_info *prev; +} swig_type_info; + +#ifdef SWIG_NOINCLUDE + +SWIGIMPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *); +SWIGIMPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *); +SWIGIMPORT(void *) SWIG_TypeCast(swig_type_info *, void *); +SWIGIMPORT(swig_type_info *) SWIG_TypeDynamicCast(swig_type_info *, void **); +SWIGIMPORT(const char *) SWIG_TypeName(const swig_type_info *); +SWIGIMPORT(swig_type_info *) SWIG_TypeQuery(const char *); +SWIGIMPORT(void) SWIG_TypeClientData(swig_type_info *, void *); +SWIGIMPORT(char *) SWIG_PackData(char *, void *, int); +SWIGIMPORT(char *) SWIG_UnpackData(char *, void *, int); + +#else + +static swig_type_info *swig_type_list = 0; + +/* Register a type mapping with the type-checking */ +SWIGRUNTIME(swig_type_info *) +SWIG_TypeRegister(swig_type_info *ti) { + swig_type_info *tc, *head, *ret, *next; + /* Check to see if this type has already been registered */ + tc = swig_type_list; + while (tc) { + if (strcmp(tc->name, ti->name) == 0) { + /* Already exists in the table. Just add additional types to the list */ + if (tc->clientdata) ti->clientdata = tc->clientdata; + head = tc; + next = tc->next; + goto l1; + } + tc = tc->prev; + } + head = ti; + next = 0; + + /* Place in list */ + ti->prev = swig_type_list; + swig_type_list = ti; + + /* Build linked lists */ + l1: + ret = head; + tc = ti + 1; + /* Patch up the rest of the links */ + while (tc->name) { + head->next = tc; + tc->prev = head; + head = tc; + tc++; + } + if (next) next->prev = head; + head->next = next; + return ret; +} + +/* Check the typename */ +SWIGRUNTIME(swig_type_info *) +SWIG_TypeCheck(char *c, swig_type_info *ty) { + swig_type_info *s; + if (!ty) return 0; /* Void pointer */ + s = ty->next; /* First element always just a name */ + do { + if (strcmp(s->name,c) == 0) { + if (s == ty->next) return s; + /* Move s to the top of the linked list */ + s->prev->next = s->next; + if (s->next) { + s->next->prev = s->prev; + } + /* Insert s as second element in the list */ + s->next = ty->next; + if (ty->next) ty->next->prev = s; + ty->next = s; + s->prev = ty; + return s; + } + s = s->next; + } while (s && (s != ty->next)); + return 0; +} + +/* Cast a pointer up an inheritance hierarchy */ +SWIGRUNTIME(void *) +SWIG_TypeCast(swig_type_info *ty, void *ptr) { + if ((!ty) || (!ty->converter)) return ptr; + return (*ty->converter)(ptr); +} + +/* Dynamic pointer casting. Down an inheritance hierarchy */ +SWIGRUNTIME(swig_type_info *) +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* Return the name associated with this type */ +SWIGRUNTIME(const char *) +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* Search for a swig_type_info structure */ +SWIGRUNTIME(swig_type_info *) +SWIG_TypeQuery(const char *name) { + swig_type_info *ty = swig_type_list; + while (ty) { + if (ty->str && (strcmp(name,ty->str) == 0)) return ty; + if (ty->name && (strcmp(name,ty->name) == 0)) return ty; + ty = ty->prev; + } + return 0; +} + +/* Set the clientdata field for a type */ +SWIGRUNTIME(void) +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_type_info *tc, *equiv; + if (ti->clientdata == clientdata) return; + ti->clientdata = clientdata; + equiv = ti->next; + while (equiv) { + if (!equiv->converter) { + tc = swig_type_list; + while (tc) { + if ((strcmp(tc->name, equiv->name) == 0)) + SWIG_TypeClientData(tc,clientdata); + tc = tc->prev; + } + } + equiv = equiv->next; + } +} + +/* Pack binary data into a string */ +SWIGRUNTIME(char *) +SWIG_PackData(char *c, void *ptr, int sz) { + static char hex[17] = "0123456789abcdef"; + int i; + unsigned char *u = (unsigned char *) ptr; + register unsigned char uu; + for (i = 0; i < sz; i++,u++) { + uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* Unpack binary data from a string */ +SWIGRUNTIME(char *) +SWIG_UnpackData(char *c, void *ptr, int sz) { + register unsigned char uu = 0; + register int d; + unsigned char *u = (unsigned char *) ptr; + int i; + for (i = 0; i < sz; i++, u++) { + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a'-10)) << 4); + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a'-10)); + *u = uu; + } + return c; +} + +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************** + * python.swg + * + * This file contains the runtime support for Python modules + * and includes code for managing global variables and pointer + * type checking. + * + * Author : David Beazley (beazley@cs.uchicago.edu) + ************************************************************************/ + +#include "Python.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SWIG_PY_INT 1 +#define SWIG_PY_FLOAT 2 +#define SWIG_PY_STRING 3 +#define SWIG_PY_POINTER 4 +#define SWIG_PY_BINARY 5 + +/* Flags for pointer conversion */ + +#define SWIG_POINTER_EXCEPTION 0x1 +#define SWIG_POINTER_DISOWN 0x2 + +/* Exception handling in wrappers */ +#define SWIG_fail goto fail + +/* Constant information structure */ +typedef struct swig_const_info { + int type; + char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_const_info; + +/* Common SWIG API */ +#define SWIG_ConvertPtr(obj, pp, type, flags) \ + SWIG_Python_ConvertPtr(obj, pp, type, flags) +#define SWIG_NewPointerObj(p, type, flags) \ + SWIG_Python_NewPointerObj(p, type, flags) +#define SWIG_MustGetPtr(p, type, argnum, flags) \ + SWIG_Python_MustGetPtr(p, type, argnum, flags) + +/* Python-specific SWIG API */ +#define SWIG_newvarlink() \ + SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) \ + SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_ConvertPacked(obj, ptr, sz, ty, flags) \ + SWIG_Python_ConvertPacked(obj, ptr, sz, ty, flags) +#define SWIG_NewPackedObj(ptr, sz, type) \ + SWIG_Python_NewPackedObj(ptr, sz, type) +#define SWIG_InstallConstants(d, constants) \ + SWIG_Python_InstallConstants(d, constants) + +#ifdef SWIG_NOINCLUDE + +SWIGIMPORT(int) SWIG_Python_ConvertPtr(PyObject *, void **, swig_type_info *, int); +SWIGIMPORT(PyObject *) SWIG_Python_NewPointerObj(void *, swig_type_info *,int own); +SWIGIMPORT(void *) SWIG_Python_MustGetPtr(PyObject *, swig_type_info *, int, int); +SWIGIMPORT(PyObject *) SWIG_Python_newvarlink(void); +SWIGIMPORT(void) SWIG_Python_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *)); +SWIGIMPORT(int) SWIG_Python_ConvertPacked(PyObject *, void *, int sz, swig_type_info *, int); +SWIGIMPORT(PyObject *) SWIG_Python_NewPackedObj(void *, int sz, swig_type_info *); +SWIGIMPORT(void) SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]); + +#else + +/* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + +typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; +} swig_globalvar; + +typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; +} swig_varlinkobject; + +static PyObject * +swig_varlink_repr(swig_varlinkobject *v) { + v = v; + return PyString_FromString(""); +} + +static int +swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) { + swig_globalvar *var; + flags = flags; + fprintf(fp,"Global variables { "); + for (var = v->vars; var; var=var->next) { + fprintf(fp,"%s", var->name); + if (var->next) fprintf(fp,", "); + } + fprintf(fp," }\n"); + return 0; +} + +static PyObject * +swig_varlink_getattr(swig_varlinkobject *v, char *n) { + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + return (*var->get_attr)(); + } + var = var->next; + } + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + return NULL; +} + +static int +swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + return (*var->set_attr)(p); + } + var = var->next; + } + PyErr_SetString(PyExc_NameError,"Unknown C global variable"); + return 1; +} + +statichere PyTypeObject varlinktype = { + PyObject_HEAD_INIT(0) + 0, + (char *)"swigvarlink", /* Type name */ + sizeof(swig_varlinkobject), /* Basic size */ + 0, /* Itemsize */ + 0, /* Deallocator */ + (printfunc) swig_varlink_print, /* Print */ + (getattrfunc) swig_varlink_getattr, /* get attr */ + (setattrfunc) swig_varlink_setattr, /* Set attr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_mapping*/ + 0, /* tp_hash */ +}; + +/* Create a variable linking object for use later */ +SWIGRUNTIME(PyObject *) +SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = 0; + result = PyMem_NEW(swig_varlinkobject,1); + varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */ + result->ob_type = &varlinktype; + result->vars = 0; + result->ob_refcnt = 0; + Py_XINCREF((PyObject *) result); + return ((PyObject*) result); +} + +SWIGRUNTIME(void) +SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v; + swig_globalvar *gv; + v= (swig_varlinkobject *) p; + gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + gv->name = (char *) malloc(strlen(name)+1); + strcpy(gv->name,name); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + v->vars = gv; +} + +/* Convert a pointer value */ +SWIGRUNTIME(int) +SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) { + swig_type_info *tc; + char *c = 0; + static PyObject *SWIG_this = 0; + int newref = 0; + PyObject *pyobj = 0; + + if (!obj) return 0; + if (obj == Py_None) { + *ptr = 0; + return 0; + } +#ifdef SWIG_COBJECT_TYPES + if (!(PyCObject_Check(obj))) { + if (!SWIG_this) + SWIG_this = PyString_FromString("this"); + pyobj = obj; + obj = PyObject_GetAttr(obj,SWIG_this); + newref = 1; + if (!obj) goto type_error; + if (!PyCObject_Check(obj)) { + Py_DECREF(obj); + goto type_error; + } + } + *ptr = PyCObject_AsVoidPtr(obj); + c = (char *) PyCObject_GetDesc(obj); + if (newref) Py_DECREF(obj); + goto cobject; +#else + if (!(PyString_Check(obj))) { + if (!SWIG_this) + SWIG_this = PyString_FromString("this"); + pyobj = obj; + obj = PyObject_GetAttr(obj,SWIG_this); + newref = 1; + if (!obj) goto type_error; + if (!PyString_Check(obj)) { + Py_DECREF(obj); + goto type_error; + } + } + c = PyString_AsString(obj); + /* Pointer values must start with leading underscore */ + if (*c != '_') { + *ptr = (void *) 0; + if (strcmp(c,"NULL") == 0) { + if (newref) { Py_DECREF(obj); } + return 0; + } else { + if (newref) { Py_DECREF(obj); } + goto type_error; + } + } + c++; + c = SWIG_UnpackData(c,ptr,sizeof(void *)); + if (newref) { Py_DECREF(obj); } +#endif + +#ifdef SWIG_COBJECT_TYPES +cobject: +#endif + + if (ty) { + tc = SWIG_TypeCheck(c,ty); + if (!tc) goto type_error; + *ptr = SWIG_TypeCast(tc,(void*) *ptr); + } + + if ((pyobj) && (flags & SWIG_POINTER_DISOWN)) { + PyObject *zero = PyInt_FromLong(0); + PyObject_SetAttrString(pyobj,(char*)"thisown",zero); + Py_DECREF(zero); + } + return 0; + +type_error: + if (flags & SWIG_POINTER_EXCEPTION) { + if (ty && c) { + char *temp = (char *) malloc(64+strlen(ty->name)+strlen(c)); + sprintf(temp,"Type error. Got %s, expected %s", c, ty->name); + PyErr_SetString(PyExc_TypeError, temp); + free((char *) temp); + } else { + PyErr_SetString(PyExc_TypeError,"Expected a pointer"); + } + } + return -1; +} + +/* Convert a pointer value, signal an exception on a type mismatch */ +SWIGRUNTIME(void *) +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { + void *result; + SWIG_Python_ConvertPtr(obj, &result, ty, flags | SWIG_POINTER_EXCEPTION); + return result; +} + +/* Convert a packed value value */ +SWIGRUNTIME(int) +SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, int sz, swig_type_info *ty, int flags) { + swig_type_info *tc; + char *c = 0; + + if ((!obj) || (!PyString_Check(obj))) goto type_error; + c = PyString_AsString(obj); + /* Pointer values must start with leading underscore */ + if (*c != '_') goto type_error; + c++; + c = SWIG_UnpackData(c,ptr,sz); + if (ty) { + tc = SWIG_TypeCheck(c,ty); + if (!tc) goto type_error; + } + return 0; + +type_error: + + if (flags) { + if (ty && c) { + char *temp = (char *) malloc(64+strlen(ty->name)+strlen(c)); + sprintf(temp,"Type error. Got %s, expected %s", c, ty->name); + PyErr_SetString(PyExc_TypeError, temp); + free((char *) temp); + } else { + PyErr_SetString(PyExc_TypeError,"Expected a pointer"); + } + } + return -1; +} + +/* Create a new pointer object */ +SWIGRUNTIME(PyObject *) +SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int own) { + PyObject *robj; + if (!ptr) { + Py_INCREF(Py_None); + return Py_None; + } +#ifdef SWIG_COBJECT_TYPES + robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, (char *) type->name, NULL); +#else + { + char result[1024]; + char *r = result; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + strcpy(r,type->name); + robj = PyString_FromString(result); + } +#endif + if (!robj || (robj == Py_None)) return robj; + if (type->clientdata) { + PyObject *inst; + PyObject *args = Py_BuildValue((char*)"(O)", robj); + Py_DECREF(robj); + inst = PyObject_CallObject((PyObject *) type->clientdata, args); + Py_DECREF(args); + if (inst) { + if (own) { + PyObject *n = PyInt_FromLong(1); + PyObject_SetAttrString(inst,(char*)"thisown",n); + Py_DECREF(n); + } + robj = inst; + } + } + return robj; +} + +SWIGRUNTIME(PyObject *) +SWIG_Python_NewPackedObj(void *ptr, int sz, swig_type_info *type) { + char result[1024]; + char *r = result; + if ((2*sz + 1 + strlen(type->name)) > 1000) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + strcpy(r,type->name); + return PyString_FromString(result); +} + +/* Install Constants */ +SWIGRUNTIME(void) +SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { + int i; + PyObject *obj; + for (i = 0; constants[i].type; i++) { + switch(constants[i].type) { + case SWIG_PY_INT: + obj = PyInt_FromLong(constants[i].lvalue); + break; + case SWIG_PY_FLOAT: + obj = PyFloat_FromDouble(constants[i].dvalue); + break; + case SWIG_PY_STRING: + obj = PyString_FromString((char *) constants[i].pvalue); + break; + case SWIG_PY_POINTER: + obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + break; + case SWIG_PY_BINARY: + obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + break; + default: + obj = 0; + break; + } + if (obj) { + PyDict_SetItemString(d,constants[i].name,obj); + Py_DECREF(obj); + } + } +} + +#endif + +/* Contract support */ + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { PyErr_SetString(PyExc_RuntimeError, (char *) msg ); goto fail; } else + +#ifdef __cplusplus +} +#endif + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_FILE swig_types[0] +#define SWIGTYPE_p_double swig_types[1] +#define SWIGTYPE_p_Quat swig_types[2] +static swig_type_info *swig_types[4]; + +/* -------- TYPES TABLE (END) -------- */ + + +/*----------------------------------------------- + @(target):= _quaternion.so + ------------------------------------------------*/ +#define SWIG_init init_quaternion + +#define SWIG_name "_quaternion" + +#include "quaternion.h" + +char *Quat___str__(Quat *self){ + static char tmp[1024]; + sprintf(tmp,"Quat(%g,%g,%g,%g)", self->x,self->y,self->z,self->w); + return tmp; + } +char *Quat___repr__(Quat *self){ + static char tmp[1024]; + sprintf(tmp,"Quat(%g,%g,%g,%g)", self->x,self->y,self->z,self->w); + return tmp; + } +Quat *new_Quat(double x,double y,double z,double w){ + return quat_create(NULL,x,y,z,w);; + } +#ifdef __cplusplus +extern "C" { +#endif +static PyObject *_wrap_Quat_x_set(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Od:Quat_x_set",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg1) (arg1)->x = arg2; + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_x_get(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat_x_get",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (double) ((arg1)->x); + + resultobj = PyFloat_FromDouble(result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_y_set(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Od:Quat_y_set",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg1) (arg1)->y = arg2; + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_y_get(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat_y_get",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (double) ((arg1)->y); + + resultobj = PyFloat_FromDouble(result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_z_set(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Od:Quat_z_set",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg1) (arg1)->z = arg2; + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_z_get(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat_z_get",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (double) ((arg1)->z); + + resultobj = PyFloat_FromDouble(result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_w_set(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Od:Quat_w_set",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg1) (arg1)->w = arg2; + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat_w_get(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat_w_get",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (double) ((arg1)->w); + + resultobj = PyFloat_FromDouble(result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat___str__(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + char *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat___str__",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (char *)Quat___str__(arg1); + + resultobj = result ? PyString_FromString(result) : Py_BuildValue((char*)""); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Quat___repr__(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + char *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Quat___repr__",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (char *)Quat___repr__(arg1); + + resultobj = result ? PyString_FromString(result) : Py_BuildValue((char*)""); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_new_Quat(PyObject *self, PyObject *args) { + PyObject *resultobj; + double arg1 ; + double arg2 ; + double arg3 ; + double arg4 ; + Quat *result; + + if(!PyArg_ParseTuple(args,(char *)"dddd:new_Quat",&arg1,&arg2,&arg3,&arg4)) goto fail; + result = (Quat *)new_Quat(arg1,arg2,arg3,arg4); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 1); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_delete_Quat(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:delete_Quat",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + free((char *) arg1); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject * Quat_swigregister(PyObject *self, PyObject *args) { + PyObject *obj; + if (!PyArg_ParseTuple(args,(char*)"O", &obj)) return NULL; + SWIG_TypeClientData(SWIGTYPE_p_Quat, obj); + Py_INCREF(obj); + return Py_BuildValue((char *)""); +} +static PyObject *_wrap_trans_mult_right(PyObject *self, PyObject *args) { + PyObject *resultobj; + double *arg1 ; + double *arg2 ; + double temp1[16] ; + double temp2[16] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:trans_mult_right",&obj0,&obj1)) goto fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj0,i); + if (PyNumber_Check(o)) { + temp1[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg1 = temp1; + } + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj1,i); + if (PyNumber_Check(o)) { + temp2[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg2 = temp2; + } + trans_mult_right(arg1,arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg1[i]); + PySequence_SetItem(obj0,i,o); + } + } + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg2[i]); + PySequence_SetItem(obj1,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_trans_mult_left(PyObject *self, PyObject *args) { + PyObject *resultobj; + double *arg1 ; + double *arg2 ; + double temp1[16] ; + double temp2[16] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:trans_mult_left",&obj0,&obj1)) goto fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj0,i); + if (PyNumber_Check(o)) { + temp1[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg1 = temp1; + } + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj1,i); + if (PyNumber_Check(o)) { + temp2[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg2 = temp2; + } + trans_mult_left(arg1,arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg1[i]); + PySequence_SetItem(obj0,i,o); + } + } + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg2[i]); + PySequence_SetItem(obj1,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_trans_transpose(PyObject *self, PyObject *args) { + PyObject *resultobj; + double *arg1 ; + double temp1[16] ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:trans_transpose",&obj0)) goto fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj0,i); + if (PyNumber_Check(o)) { + temp1[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg1 = temp1; + } + trans_transpose(arg1); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg1[i]); + PySequence_SetItem(obj0,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_trans_vec_mult(PyObject *self, PyObject *args) { + PyObject *resultobj; + double *arg1 ; + double *arg2 ; + double temp1[16] ; + double temp2[4] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:trans_vec_mult",&obj0,&obj1)) goto fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj0,i); + if (PyNumber_Check(o)) { + temp1[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg1 = temp1; + } + { + int i; + for (i = 0; i < 4; i++) { + PyObject *o = PySequence_GetItem(obj1,i); + if (PyNumber_Check(o)) { + temp2[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg2 = temp2; + } + trans_vec_mult(arg1,arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg1[i]); + PySequence_SetItem(obj0,i,o); + } + } + { + int i; + for (i = 0; i < 4; i++) { + PyObject *o = PyFloat_FromDouble((double) arg2[i]); + PySequence_SetItem(obj1,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_trans_dump(PyObject *self, PyObject *args) { + PyObject *resultobj; + FILE *arg1 = (FILE *) 0 ; + double *arg2 ; + double temp2[16] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:trans_dump",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_FILE,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj1,i); + if (PyNumber_Check(o)) { + temp2[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg2 = temp2; + } + trans_dump(arg1,arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg2[i]); + PySequence_SetItem(obj1,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_trans_to_quat(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double *arg2 ; + Quat *result; + double temp2[16] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:trans_to_quat",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj1,i); + if (PyNumber_Check(o)) { + temp2[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg2 = temp2; + } + result = (Quat *)trans_to_quat(arg1,arg2); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg2[i]); + PySequence_SetItem(obj1,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_to_trans(PyObject *self, PyObject *args) { + PyObject *resultobj; + double *arg1 ; + Quat *arg2 = (Quat *) 0 ; + double arg3 ; + double arg4 ; + double arg5 ; + double temp1[16] ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OOddd:quat_to_trans",&obj0,&obj1,&arg3,&arg4,&arg5)) goto fail; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PySequence_GetItem(obj0,i); + if (PyNumber_Check(o)) { + temp1[i] = PyFloat_AsDouble(o); + } else { + PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); + return NULL; + } + } + arg1 = temp1; + } + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + quat_to_trans(arg1,arg2,arg3,arg4,arg5); + + Py_INCREF(Py_None); resultobj = Py_None; + { + int i; + for (i = 0; i < 16; i++) { + PyObject *o = PyFloat_FromDouble((double) arg1[i]); + PySequence_SetItem(obj0,i,o); + } + } + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_copy(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *arg2 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:quat_copy",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_copy(arg1,arg2); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_nrm_sqrt(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *arg2 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:quat_nrm_sqrt",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_nrm_sqrt(arg1,(Quat const *)arg2); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_normalize(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:quat_normalize",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_normalize(arg1); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_mult_right(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *arg2 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:quat_mult_right",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_mult_right(arg1,arg2); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_mult_left(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *arg2 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:quat_mult_left",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_mult_left(arg1,arg2); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_identity(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:quat_identity",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_identity(arg1); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_conjugate(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:quat_conjugate",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_conjugate(arg1); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_create(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + double arg3 ; + double arg4 ; + int arg5 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Odddi:quat_create",&obj0,&arg2,&arg3,&arg4,&arg5)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_create(arg1,arg2,arg3,arg4,arg5); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_from_axis_angle(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + double arg3 ; + double arg4 ; + double arg5 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Odddd:quat_from_axis_angle",&obj0,&arg2,&arg3,&arg4,&arg5)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_from_axis_angle(arg1,arg2,arg3,arg4,arg5); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_to_axis_angle(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double *arg2 = (double *) 0 ; + double *arg3 = (double *) 0 ; + double *arg4 = (double *) 0 ; + double *arg5 = (double *) 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OOOOO:quat_to_axis_angle",&obj0,&obj1,&obj2,&obj3,&obj4)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj2,(void **) &arg3, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj3,(void **) &arg4, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj4,(void **) &arg5, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + quat_to_axis_angle(arg1,arg2,arg3,arg4,arg5); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_from_euler_RzRyRx(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double arg2 ; + double arg3 ; + double arg4 ; + Quat *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Oddd:quat_from_euler_RzRyRx",&obj0,&arg2,&arg3,&arg4)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Quat *)quat_from_euler_RzRyRx(arg1,arg2,arg3,arg4); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Quat, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_quat_to_euler_RzRyRx(PyObject *self, PyObject *args) { + PyObject *resultobj; + Quat *arg1 = (Quat *) 0 ; + double *arg2 = (double *) 0 ; + double *arg3 = (double *) 0 ; + double *arg4 = (double *) 0 ; + int result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OOOO:quat_to_euler_RzRyRx",&obj0,&obj1,&obj2,&obj3)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Quat,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj2,(void **) &arg3, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj3,(void **) &arg4, SWIGTYPE_p_double,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (int)quat_to_euler_RzRyRx(arg1,arg2,arg3,arg4); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + +static PyMethodDef SwigMethods[] = { + { (char *)"Quat_x_set", _wrap_Quat_x_set, METH_VARARGS }, + { (char *)"Quat_x_get", _wrap_Quat_x_get, METH_VARARGS }, + { (char *)"Quat_y_set", _wrap_Quat_y_set, METH_VARARGS }, + { (char *)"Quat_y_get", _wrap_Quat_y_get, METH_VARARGS }, + { (char *)"Quat_z_set", _wrap_Quat_z_set, METH_VARARGS }, + { (char *)"Quat_z_get", _wrap_Quat_z_get, METH_VARARGS }, + { (char *)"Quat_w_set", _wrap_Quat_w_set, METH_VARARGS }, + { (char *)"Quat_w_get", _wrap_Quat_w_get, METH_VARARGS }, + { (char *)"Quat___str__", _wrap_Quat___str__, METH_VARARGS }, + { (char *)"Quat___repr__", _wrap_Quat___repr__, METH_VARARGS }, + { (char *)"new_Quat", _wrap_new_Quat, METH_VARARGS }, + { (char *)"delete_Quat", _wrap_delete_Quat, METH_VARARGS }, + { (char *)"Quat_swigregister", Quat_swigregister, METH_VARARGS }, + { (char *)"trans_mult_right", _wrap_trans_mult_right, METH_VARARGS }, + { (char *)"trans_mult_left", _wrap_trans_mult_left, METH_VARARGS }, + { (char *)"trans_transpose", _wrap_trans_transpose, METH_VARARGS }, + { (char *)"trans_vec_mult", _wrap_trans_vec_mult, METH_VARARGS }, + { (char *)"trans_dump", _wrap_trans_dump, METH_VARARGS }, + { (char *)"trans_to_quat", _wrap_trans_to_quat, METH_VARARGS }, + { (char *)"quat_to_trans", _wrap_quat_to_trans, METH_VARARGS }, + { (char *)"quat_copy", _wrap_quat_copy, METH_VARARGS }, + { (char *)"quat_nrm_sqrt", _wrap_quat_nrm_sqrt, METH_VARARGS }, + { (char *)"quat_normalize", _wrap_quat_normalize, METH_VARARGS }, + { (char *)"quat_mult_right", _wrap_quat_mult_right, METH_VARARGS }, + { (char *)"quat_mult_left", _wrap_quat_mult_left, METH_VARARGS }, + { (char *)"quat_identity", _wrap_quat_identity, METH_VARARGS }, + { (char *)"quat_conjugate", _wrap_quat_conjugate, METH_VARARGS }, + { (char *)"quat_create", _wrap_quat_create, METH_VARARGS }, + { (char *)"quat_from_axis_angle", _wrap_quat_from_axis_angle, METH_VARARGS }, + { (char *)"quat_to_axis_angle", _wrap_quat_to_axis_angle, METH_VARARGS }, + { (char *)"quat_from_euler_RzRyRx", _wrap_quat_from_euler_RzRyRx, METH_VARARGS }, + { (char *)"quat_to_euler_RzRyRx", _wrap_quat_to_euler_RzRyRx, METH_VARARGS }, + { NULL, NULL } +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_FILE[] = {{"_p_FILE", 0, "FILE *", 0},{"_p_FILE"},{0}}; +static swig_type_info _swigt__p_double[] = {{"_p_double", 0, "double *", 0},{"_p_double"},{0}}; +static swig_type_info _swigt__p_Quat[] = {{"_p_Quat", 0, "Quat *", 0},{"_p_Quat"},{0}}; + +static swig_type_info *swig_types_initial[] = { +_swigt__p_FILE, +_swigt__p_double, +_swigt__p_Quat, +0 +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_const_info swig_const_table[] = { +{0}}; + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT(void) SWIG_init(void) { + static PyObject *SWIG_globals = 0; + static int typeinit = 0; + PyObject *m, *d; + int i; + if (!SWIG_globals) SWIG_globals = SWIG_newvarlink(); + m = Py_InitModule((char *) SWIG_name, SwigMethods); + d = PyModule_GetDict(m); + + if (!typeinit) { + for (i = 0; swig_types_initial[i]; i++) { + swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]); + } + typeinit = 1; + } + SWIG_InstallConstants(d,swig_const_table); + +} + Index: src/fmri/smoother.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/fmri/smoother.c,v retrieving revision 1.14 retrieving revision 1.15 diff -a -u -r1.14 -r1.15 --- src/fmri/smoother.c 22 Apr 2003 22:49:27 -0000 1.14 +++ src/fmri/smoother.c 1 Mar 2004 05:38:40 -0000 1.15 @@ -42,6 +42,8 @@ -At this moment, smoother->k is unused. */ +static char rcsid[] = "$Id: smoother.c,v 1.15 2004/03/01 05:38:40 welling Exp $"; + static sm_type default_type= SM_GAUSSIAN; static double default_bandwidth= 45.0; static double default_k= 60.0; Index: src/intsplit/intsplit.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/intsplit/intsplit.c,v retrieving revision 1.15 retrieving revision 1.16 diff -a -u -r1.15 -r1.16 --- src/intsplit/intsplit.c 18 Sep 2003 18:43:19 -0000 1.15 +++ src/intsplit/intsplit.c 23 Apr 2004 00:08:45 -0000 1.16 @@ -44,7 +44,7 @@ #include "stdcrg.h" #include "slist.h" -static char rcsid[] = "$Id: intsplit.c,v 1.15 2003/09/18 18:43:19 bakalj Exp $"; +static char rcsid[] = "$Id: intsplit.c,v 1.16 2004/04/23 00:08:45 welling Exp $"; typedef struct factor_info_struct { char* name; @@ -263,8 +263,7 @@ firstimage = lastimage; if( firstimage >= dt ) { - Warning( 1, "Ran out of images before condition file ended.\n"); - break; + Abort("Ran out of images before condition file ended.\n"); } /* Test for a common user error */ if (strchr(here,'-')) Index: src/ireg3d/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/ireg3d/Makefile,v retrieving revision 1.1 retrieving revision 1.3 diff -a -u -r1.1 -r1.3 --- src/ireg3d/Makefile 18 Feb 1999 01:03:04 -0000 1.1 +++ src/ireg3d/Makefile 18 Mar 2004 06:46:25 -0000 1.3 @@ -8,13 +8,13 @@ # PKG = ireg3d -PKG_MAKEBINS = $(CB)/ireg3d +PKG_MAKEBINS = $(CB)/ireg3d $(CB)/iwarp -PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg -lm +PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm MAKEFILES= Makefile -CSOURCE= ireg3d.c -DOCFILES= ireg3d_help.help +CSOURCE= ireg3d.c iwarp.c +DOCFILES= ireg3d_help.help iwarp_help.help include ../Makefile.pkg @@ -29,6 +29,15 @@ $(HELP_RULE) $(CB)/ireg3d: $O/ireg3d.o $O/ireg3d_help.o $(LIBFILES) + $(SINGLE_HELP_LD) + +$O/iwarp.o: iwarp.c + $(CC_RULE) + +$O/iwarp_help.o: iwarp_help.help + $(HELP_RULE) + +$(CB)/iwarp: $O/iwarp.o $O/iwarp_help.o $(LIBFILES) $(SINGLE_HELP_LD) releaseprep: Index: src/ireg3d/ireg3d.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/ireg3d/ireg3d.c,v retrieving revision 1.17 retrieving revision 1.20 diff -a -u -r1.17 -r1.20 --- src/ireg3d/ireg3d.c 7 Feb 2003 21:33:05 -0000 1.17 +++ src/ireg3d/ireg3d.c 18 Mar 2004 06:46:25 -0000 1.20 @@ -38,7 +38,7 @@ #include "stdcrg.h" #include "misc.h" -static char rcsid[] = "$Id: ireg3d.c,v 1.17 2003/02/07 21:33:05 welling Exp $"; +static char rcsid[] = "$Id: ireg3d.c,v 1.20 2004/03/18 06:46:25 welling Exp $"; /* Access for 3D arrays */ #define MEM_BCK(matrix,nx,ny,nz,x,y,z) matrix[((((z)*ny)+(y))*nx)+(x)] @@ -130,6 +130,7 @@ Quat q; long block_offset; int block_size; + const char* dimstr= NULL; double length_x, length_y, length_z; double xvoxel, yvoxel, zvoxel; @@ -150,7 +151,7 @@ cl_scan( argc, argv ); /* Get filenames */ - cl_get( "dataout|d", "%option %s[%]", ".dat", outfile ); + strcpy(outfile,".dat"); /* we no longer let the user set datafile name */ cl_get( "headerout|h", "%option %s[%]", "ireg3d.mri", hdrfile ); cl_get( "input|i", "%option %s[%]", "input.mri", infile ); cl_get( "parameters|p", "%option %s[%]", "reg3d.par", parfile ); @@ -234,39 +235,58 @@ Abort( "%s operates only on standard images.", argv[0] ); if( mri_has( Input, "images.dimensions" ) ) { - dv = ( !strcmp( mri_get_string( Input, "images.dimensions" ), - "vxyzt" ) )? - mri_get_int( Input, "images.extent.v" ): - ( !strcmp( mri_get_string( Input, "images.dimensions" ), "xyzt" ) )? - 1: 0; - if( ( dv < 1 ) || ( dv > 2 ) ) + dimstr= mri_get_string( Input, "images.dimensions" ); + if ( !strcmp( dimstr,"vxyzt") || !strcmp(dimstr,"vxyz") ) { + if ( mri_has( Input, "images.extent.v" ) ) { + dv= mri_get_int(Input,"images.extent.v"); + if( ( dv < 1 ) || ( dv > 2 ) ) + Abort( "%s takes only reals or complex numbers of the form (v)xyz(t).", + argv[0] ); + } + else + Abort( "%s: %s does not have the images.extent.v key.", + argv[0], infile ); + } + else if ( !strcmp( dimstr,"xyzt") || !strcmp(dimstr,"xyz") ) { + dv= 1; + } + else { Abort( "%s takes only reals or complex numbers of the form (v)xyzt.", argv[0] ); + } } else Abort( "%s does not have the images.dimensions key.", infile ); - /* Set output dataset */ - Output = mri_copy_dataset( hdrfile, Input ); - hist_add_cl( Output, argc, argv ); - mri_set_string( Output, "images.datatype", "float32" ); - mri_set_string( Output, "images.file", outfile ); - mri_set_string( Output, "images.dimensions", "vxyzt" ); - mri_set_int( Output, "images.extent.v", (int) dv ); - /* Set parameters in local variables */ - if( !mri_has( Input, "images.extent.t" ) || - !mri_has( Input, "images.extent.x" ) || + if( !mri_has( Input, "images.extent.x" ) || !mri_has( Input, "images.extent.y" ) || !mri_has( Input, "images.extent.z" ) ) Abort( "images.extent key(s) missing from header." ); - dt = mri_get_int( Input, "images.extent.t" ); dx = mri_get_int( Input, "images.extent.x" ); dy = mri_get_int( Input, "images.extent.y" ); dz = mri_get_int( Input, "images.extent.z" ); + if ( !strcmp(dimstr,"vxyzt") || !strcmp(dimstr,"xyzt") ) { + if (mri_has(Input, "images.extent.t")) + dt = mri_get_int( Input, "images.extent.t" ); + else Abort("%s: %s is missing the images.extent.t key.", + argv[0],infile); + } + else { + dt= 1; + } if( ( dt <= 0 ) || ( dx <= 0 ) || ( dy <= 0 ) || ( dz <= 0 ) ) Abort( "images.extent key(s) is non-positive." ); + /* Set output dataset */ + Output = mri_copy_dataset( hdrfile, Input ); + hist_add_cl( Output, argc, argv ); + mri_set_string( Output, "images.datatype", "float32" ); + mri_set_string( Output, "images.file", outfile ); + mri_set_string( Output, "images.dimensions", "vxyzt" ); + mri_set_int( Output, "images.extent.v", (int) dv ); + mri_set_int( Output, "images.extent.t", (int) dt ); + /* Allocate image and parameter storage */ if (!(c_image= (FComplex*)malloc(dx*dy*dz*sizeof(FComplex)))) Abort("%s: unable to allocate %d bytes!\n", @@ -286,7 +306,7 @@ } if (!(par= (RegPar3D*)malloc(dt*sizeof(RegPar3D)))) Abort("%s: unable to allocate %d bytes!\n", - dt*sizeof(Transform)); + dt*sizeof(RegPar3D)); /* Initialize registration parameters */ /* to zero in case they are missing */ @@ -462,7 +482,7 @@ } Message( "# Image registration complete.\n" ); - exit(0); + return 0; } Index: src/ireg3d/ireg3d_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/ireg3d/ireg3d_help.help,v retrieving revision 1.9 retrieving revision 1.11 diff -a -u -r1.9 -r1.11 --- src/ireg3d/ireg3d_help.help 3 Nov 2000 00:23:59 -0000 1.9 +++ src/ireg3d/ireg3d_help.help 18 Mar 2004 06:46:25 -0000 1.11 @@ -11,7 +11,7 @@ in k-space). Note that this convention assumes that images are acquired slicewise, so that complex data is reconstructed using FFTs in the X and Y directions only. Input data must be organized - as vxyzt or xyzt. It is best to use this algorithm on data that + as (v)xyz(t). It is best to use this algorithm on data that is confined to the central region of the volume; see the "Calculation" section below for details. Specifically, applying this algorithm to equivalent image space and k space data may @@ -20,7 +20,6 @@ To run ireg3d use: ireg3d -xvoxel xv -yvoxel yv -zvoxel zv [-input Input-header-file] [-headerout Output-header-file] - [-dataout Output-data-file] [-parameters Registration-parameter-file] [-debug] [-real] [-qualmeasure cox|sabs|ssqr|ucell] [-shear4 | -shear7 | -shear13 | -trilinear] Index: src/ireg3d/iwarp.c =================================================================== RCS file: src/ireg3d/iwarp.c diff -N src/ireg3d/iwarp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/ireg3d/iwarp.c 18 Mar 2004 06:46:25 -0000 1.2 @@ -0,0 +1,394 @@ +/************************************************************ + * * + * iwarp.c * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * Copyright (c) 1995 Department of Statistics, * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Original programming by Mark Fitzgerald 2-95 * + * 5-96: Pittsburgh Format, Mark Fitzgerald * + * 2-99: 3D version, Joel Welling * + * 3-04: ireg3d becomes iwarp, Joel Welling * + ************************************************************/ + +#include +#include +#include +#include +#include "mri.h" +#include "fmri.h" +#include "stdcrg.h" +#include "misc.h" + +static char rcsid[] = "$Id: iwarp.c,v 1.2 2004/03/18 06:46:25 welling Exp $"; + +/* Access for 3D arrays */ +#define MEM_BCK(matrix,nx,ny,nz,x,y,z) matrix[((((z)*ny)+(y))*nx)+(x)] +#define MEM(matrix,nx,ny,nz,x,y,z) matrix[((((x)*ny)+(y))*nz)+(z)] + +typedef struct warppar_struct { + Transform v; + double mse; +} WarpPar; + +static char* progname= NULL; +static int debug_flag= 0; +static int verbose_flag= 0; +static int trilinear_flag= 0; + + +static void initializeWarpPar( WarpPar* p ) +{ + trans_identity(p->v); + p->mse= -1.0; +} + +static void copyWarpPar( WarpPar* out, const WarpPar* in ) +{ + trans_copy(out->v, in->v); + out->mse= in->mse; +} + +static int parseOneWarp(char* line, WarpPar* p, long* t) +{ + ; + int numRead= sscanf(line, + "%ld%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg\n", + t, + &(p->v[0]), &(p->v[1]), &(p->v[2]), &(p->v[3]), + &(p->v[4]), &(p->v[5]), &(p->v[6]), &(p->v[7]), + &(p->v[8]), &(p->v[9]), &(p->v[10]), &(p->v[11]), + &(p->v[12]), &(p->v[13]), &(p->v[14]), &(p->v[15]), + &(p->mse)); + return (numRead==18); +} + +static void load_warp_params(char* parfile, WarpPar* par, long dt) +{ + FILE *fp = NULL; + char scanline[512]; + long linenum, tt; + WarpPar p; + + fp = efopen( parfile, "r" ); + linenum = -1; + while( !feof( fp ) && !ferror( fp ) ) + { + linenum++; + + /* Scan a line, ignoring comments (which begin with '#') */ + if (fgets(scanline, sizeof(scanline), fp) + && strlen(scanline)>0 && scanline[0] != '#') { + if (!parseOneWarp(scanline, &p, &tt)) { + Warning( 1, "Line %ld of %s contained an error -- Ignoring.\n", + linenum, parfile ); + } + else if( ( tt < 0 ) || ( tt >= dt ) ) { + Warning( 1, + "Image out of bounds (%ld) for line %ld of %s -- Ignoring.\n", + tt, linenum, parfile ); + } + else { + copyWarpPar(&(par[tt]),&p); + if (debug_flag) + fprintf(stderr,"%d: loaded (%g %g %g ...), mse %g\n", + tt,par[tt].v[0], par[tt].v[1], par[tt].v[2], par[tt].mse); + } + } + } + efclose( fp ); +} + +int main( int argc, char* argv[] ) +{ + + MRI_Dataset *Input = NULL, *Output = NULL; + char infile[512], hdrfile[512], parfile[512]; + long dv, dx, dy, dz, dt; + FComplex *c_image = NULL, *c_corr_image = NULL, *c_image_in= NULL; + float *image_in = NULL, *corr_image = NULL; + char* check = NULL; /* used only in linear mode */ + long x, y, t, z; + WarpPar* par= NULL; + long block_offset; + int block_size; + const char* dimstr= NULL; + double length_x, length_y, length_z; + double xvoxel, yvoxel, zvoxel; + + progname= argv[0]; + + /* Check to see if help was requested */ + if( ( argc > 1 ) && !strcmp( argv[1], "-help" ) ) + { + if( argc == 2 ) + Help( "selecttopic" ); + else + Help( argv[2] ); + } + + /*** Parse command line ***/ + + cl_scan( argc, argv ); + + /* Get filenames */ + cl_get( "headerout|h", "%option %s[%]", "iwarp.mri", hdrfile ); + cl_get( "input|i", "%option %s[%]", "input.mri", infile ); + cl_get( "parameters|p", "%option %s[%]", "warp.par", parfile ); + if (!cl_get( "x|xvoxel", "%option %lf", &xvoxel )) { + fprintf(stderr,"%s: required argument xvoxel omitted.\n",argv[0]); + Help("usage"); + exit(-1); + } + if (!cl_get( "y|yvoxel", "%option %lf", &yvoxel )) { + fprintf(stderr,"%s: required argument yvoxel omitted.\n",argv[0]); + Help("usage"); + exit(-1); + } + if (!cl_get( "z|zvoxel", "%option %lf", &zvoxel )) { + fprintf(stderr,"%s: required argument zvoxel omitted.\n",argv[0]); + Help("usage"); + exit(-1); + } + debug_flag= cl_present("debug"); + verbose_flag= cl_present("verbose|v"); + trilinear_flag= cl_present("trilinear"); + if (trilinear_flag > 1) { + fprintf(stderr,"%s: incompatible flags were specified.\n",argv[0]); + Help("usage"); + exit(-1); + } + + if (cl_cleanup_check()) { + int i; + fprintf(stderr,"%s: invalid argument in command line:\n ",argv[0]); + for (i=0; idatatype == ch->actual_datatype && - ch->little_endian == ch->actual_little_endian) + long long read_offset, write_offset; + long long count; + double *dbl; + + /* find out max element size */ + union element { + unsigned char u; + short s; + int i; + long long l; + float f; + double d; + } element; + + union pbuffer { + unsigned char *u; + short *s; + int *i; + long long *ll; + float *f; + double *d; + void *me; + } in_buffer, out_buffer; + + int saved_bio_big_endian_input; + int saved_bio_big_endian_output; + int saved_bio_error; + + in_buffer.me = calloc (N_READ, sizeof(element)); + out_buffer.me = calloc (N_READ, sizeof(element)); + + /* check if a copy operation will suffice */ + if (ch->datatype == ch->actual_datatype && + ch->little_endian == ch->actual_little_endian) { CopyBlock(f, offset, ch->actual_file, ch->actual_offset, (ch->size < ch->actual_size) ? ch->size : ch->actual_size); @@ -3942,6 +3958,9 @@ bio_big_endian_input = saved_bio_big_endian_input; bio_big_endian_output = saved_bio_big_endian_output; bio_error = saved_bio_error; + + free (in_buffer.me); + free (out_buffer.me); #undef N_READ } Index: src/libmri/mri-c.doc =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/libmri/mri-c.doc,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- src/libmri/mri-c.doc 9 Jul 2003 22:06:11 -0000 1.2 +++ src/libmri/mri-c.doc 5 Feb 2004 20:54:41 -0000 1.3 @@ -157,7 +157,7 @@ portions of very large chunks, when it would be impractical to read the entire chunk at once. mri_get_chunk manages the data buffers; the caller should not free them. The alternative call - pointer = mri_get_chunk(ds, "chunk_name", size, offset, array_type, buf); + pointer = mri_read_chunk(ds, "chunk_name", size, offset, array_type, buf); allows the caller to supply the buffer. Index: src/misc/blind_minimize.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/misc/blind_minimize.c,v retrieving revision 1.2 retrieving revision 1.5 diff -a -u -r1.2 -r1.5 --- src/misc/blind_minimize.c 17 Apr 2003 20:36:56 -0000 1.2 +++ src/misc/blind_minimize.c 17 Mar 2004 22:08:26 -0000 1.5 @@ -46,25 +46,18 @@ #include "stdcrg.h" #include "misc.h" -static char rcsid[] = "$Id: blind_minimize.c,v 1.2 2003/04/17 20:36:56 welling Exp $"; +static char rcsid[] = "$Id: blind_minimize.c,v 1.5 2004/03/17 22:08:26 welling Exp $"; /* Notes- */ #define DEFAULT_SEARCH_ALGORITHM "opt=praxis" -typedef enum { - OPT_NELMIN, - OPT_NELMIN_T, - OPT_PRAXIS, - OPT_NONE, - OPT_INVALID -} OptMethod; - /* This structure defines the algorithm to be used. */ typedef struct alg_context_struct { - OptMethod opt_method; + Optimizer* opt; + ScalarFunction* sf; } Algorithm; typedef struct par_struct { @@ -80,9 +73,8 @@ static int debug= 0; static Algorithm gblAlg; static Par gblPar; -static Par scratchPar; -static char script[512]; static double gblScale; +static char script[512]; static void par_init( Par* par ) { @@ -98,7 +90,7 @@ char* here; char* tmp; char* tok; - + double* vals= NULL; ndim= 0; here= strdup(str); while (strtok_r((ndim ? NULL : here), " :,", &tmp)) ndim++; @@ -107,34 +99,20 @@ par->ndim= ndim; par->mse= 0.0; - if (!(par->vals=(double*)malloc(ndim*sizeof(double)))) + if (!(vals=(double*)malloc(ndim*sizeof(double)))) Abort("%s: cannot allocate %d bytes!\n",ndim*sizeof(double)); free(here); here= strdup(str); i= 0; while ((tok=strtok_r((i ? NULL : here), " :,", &tmp)) != NULL ) { - par->vals[i]= atof(tok); + vals[i]= atof(tok); i++; } + par->vals= vals; free(here); } -static void par_copy( Par* out, const Par* in ) -{ - int i; - - if (out->vals) free(out->vals); - out->ndim= in->ndim; - out->mse= in->mse; - if (out->ndim>0) { - if (!(out->vals=(double*)malloc(out->ndim*sizeof(double)))) - Abort("%s: unable to allocate %d bytes!\n",out->ndim*sizeof(double)); - for (i=0; indim; i++) out->vals[i]= in->vals[i]; - } - else out->vals= NULL; -} - static void par_print( const char* hdr, Par* par, FILE* ofile ) { int i; @@ -144,24 +122,31 @@ fprintf(ofile,"-> %lg\n",par->mse); } -static char* optMethodName( OptMethod mthd ) +static Optimizer* parseOptMethod(char* s) { - switch (mthd) { - case OPT_NELMIN: return "nelmin"; - case OPT_NELMIN_T: return "nelmin_t"; - case OPT_PRAXIS: return "praxis"; - case OPT_NONE: return "none"; - default: return NULL; - } -} + /* Two-sided 95% T cutoffs for DF up to 20 */ + static float tcrit[]= { 0.0, 12.706176098809, 4.30263617020413, + 3.18244545308107, 2.77644502408949, 2.57058182376418, + 2.44680441622004, 2.36457539633475, 2.30597941403506, + 2.26214359559273, 2.2281309162355, 2.20098027417758, + 2.17880969240071, 2.16036657035061, 2.14478525936996, + 2.13144854260425, 2.11990457994238, 2.10981505255424, + 2.10092165066567, 2.09302376167972, 2.08596322490106 + }; -static OptMethod parseOptMethod(char* s) -{ - if (!strcasecmp(s,"nelmin")) return OPT_NELMIN; - else if (!strcasecmp(s,"nelmin_t")) return OPT_NELMIN_T; - else if (!strcasecmp(s,"praxis")) return OPT_PRAXIS; - else if (!strcasecmp(s,"none")) return OPT_NONE; - else return OPT_INVALID; + if (gblPar.ndim> (sizeof(tcrit)/sizeof(float))-1) + Abort("%s: tcrit for %d degrees of freedom is not compiled in!\n", + progname, gblPar.ndim); + + if (!strcasecmp(s,"nelmin")) + return createNelminOptimizer(0.02,1.0); + else if (!strcasecmp(s,"nelmin_t")) + return createNelminTOptimizer(0.02,1.0, + tcrit[gblPar.ndim]*tcrit[gblPar.ndim]); + else if (!strcasecmp(s,"praxis")) + return createPraxisOptimizer(0.000001,1.0); + else if (!strcasecmp(s,"none")) return createNoneOptimizer(); + else return NULL; } static int parseAlgString(char* search_string) @@ -174,7 +159,10 @@ while (tok != NULL) { if (!strncasecmp(tok,"opt=",4)) { - if ((gblAlg.opt_method=parseOptMethod(tok+4))==OPT_INVALID) + if (gblAlg.opt != NULL) { + gblAlg.opt->destroySelf(gblAlg.opt); + } + if ((gblAlg.opt=parseOptMethod(tok+4))==NULL) { free(work); return 0; } } else { free(work); return 0; } @@ -194,7 +182,7 @@ result[0]= '\0'; - sprintf(scratch,"opt=%s,",optMethodName(gblAlg.opt_method)); + sprintf(scratch,"opt=%s,",gblAlg.opt->getMethodName(gblAlg.opt)); strncat(result,scratch,sizeof(result)-(offset+1)); offset += strlen(scratch); if (offset>=sizeof(result)-1) return result; @@ -250,7 +238,9 @@ if (debug) { char* here; if ((here=strchr(result,'\n')) != NULL) *here= '\0'; +#ifdef never fprintf(stderr,"Child process responded <%s>\n",result); +#endif } close(myPipe[0]); } @@ -286,7 +276,7 @@ /* Returns mean squared-error between (adjusted) fixed image */ /* and (adjusted) register image, the criterion to be */ /* minimized by the minization op for registration */ -static double mse( double* guess, int npar ) +static double mse( const double* guess, const int npar, void* userHook ) { int i; Par par; @@ -295,17 +285,17 @@ Abort("%s: mse found %d parameters, not %d!\n",progname, npar, gblPar.ndim); par.ndim= npar; - par.vals= guess; + par.vals= (double*)guess; par.mse= calcChiSqr(&par); - if (debug) { - par_print("mse", &par, stderr); + if (debug) { + par_print("mse", &par, stderr); } return( par.mse ); } -static void restrt( double* guess, int npar ) +static void restrt( const double* guess, const int npar, void* userHook ) { if (debug) { Par par; @@ -314,219 +304,12 @@ Abort("%s: restrt found %d parameters, not %d!\n",progname, npar, gblPar.ndim); par.ndim= npar; - par.vals= guess; + par.vals= (double*)guess; par.mse= 0.0; par_print("restrt", &gblPar, stderr); } } -static float fmse( float* guess ) -{ - int i; - - for (i=0; i1) prx_printlvl= 4; - else if (debug>0) prx_printlvl= 1; - else prx_printlvl= 0; - - gblPar.mse= praxis(prx_t0, prx_machep, prx_h0, gblPar.ndim, prx_printlvl, - gblPar.vals, mse, restrt, 0.0); - -} - -static void optNelminT() -{ - float mseval= -1.0; - int steps_per_conv_check = 3; -#ifdef never - int max_iter = 400, max_restart = 3; -#endif - int max_iter = 800, max_restart = 12; - int num_iter=0, num_restart=0, return_cond=0; -#ifdef never - float stopping_val = 0.1; -#endif - float stopping_val = 0.02; - float* start; - float* scale; - float* guess; - float tcrit_sqr; - int i; - - /* Two-sided 95% T cutoffs for DF up to 20 */ - static float tcrit[]= { 0.0, 12.706176098809, 4.30263617020413, - 3.18244545308107, 2.77644502408949, 2.57058182376418, - 2.44680441622004, 2.36457539633475, 2.30597941403506, - 2.26214359559273, 2.2281309162355, 2.20098027417758, - 2.17880969240071, 2.16036657035061, 2.14478525936996, - 2.13144854260425, 2.11990457994238, 2.10981505255424, - 2.10092165066567, 2.09302376167972, 2.08596322490106 - }; - - if (gblPar.ndim> (sizeof(tcrit)/sizeof(float))-1) - Abort("%s: tcrit for %d degrees of freedom is not compiled in!\n", - progname, gblPar.ndim); - tcrit_sqr= tcrit[gblPar.ndim]*tcrit[gblPar.ndim]; - - if (!(start= (float*)malloc(gblPar.ndim*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", - progname, gblPar.ndim*sizeof(float)); - if (!(scale= (float*)malloc(gblPar.ndim*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", - progname, gblPar.ndim*sizeof(float)); - if (!(guess= (float*)malloc(gblPar.ndim*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", - progname, gblPar.ndim*sizeof(float)); - for (i=0; isetDebugLevel(gblAlg.opt,10); Message("# algorithm: %s\n",getAlgInfoString()); - - /* Parse the starting point */ - par_parse(&gblPar, startString); - par_copy(&scratchPar, &gblPar); /* get the sizes right */ + Message("# optimizer details: %s\n",gblAlg.opt->getStringRep(gblAlg.opt)); + gblAlg.sf= buildSimpleScalarFunction(mse,restrt,gblPar.ndim,NULL); /* Let's keep track of optimization time */ getrusage(RUSAGE_SELF,&start_rusage); /* Run the optimizaiton */ - optimize(); + (void)(gblAlg.opt->go(gblAlg.opt, gblAlg.sf, + gblPar.vals, gblPar.ndim, &(gblPar.mse))); getrusage(RUSAGE_SELF,&end_rusage); buildTimeString(run_time_string,&start_rusage,&end_rusage); Index: src/morphology/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/morphology/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -a -u -r1.1 -r1.2 --- src/morphology/Makefile 18 Mar 2003 23:58:49 -0000 1.1 +++ src/morphology/Makefile 17 Mar 2004 22:10:46 -0000 1.2 @@ -10,7 +10,7 @@ PKG = morphology PKG_MAKEBINS = $(CB)/affinemap $(CB)/follow $(CB)/pullback $(CB)/morph -PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg -lm +PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm MAKEFILES= Makefile CSOURCE= affinemap.c follow.c pullback.c morph.c Index: src/mri_util/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/Makefile,v retrieving revision 1.33 retrieving revision 1.34 diff -a -u -r1.33 -r1.34 --- src/mri_util/Makefile 7 Oct 2003 23:25:10 -0000 1.33 +++ src/mri_util/Makefile 5 Feb 2004 20:56:42 -0000 1.34 @@ -18,7 +18,8 @@ $(CB)/mri_delete_chunk $(CB)/mri_paste $(CB)/mri_sort \ $(CB)/mri_copy_dataset $(CB)/mri_destroy_dataset \ $(CB)/mri_remap $(CB)/mri_printfield $(CB)/mri_permute \ - $(CB)/mri_setfield $(CB)/mri_matmult $(CB)/mri_esa + $(CB)/mri_setfield $(CB)/mri_matmult $(CB)/mri_esa \ + $(CB)/mri_resample PKG_LIBS = -ldcdf -lfmri -lmri -lpar -lbio -lacct \ -lcrg -lmisc $(LAPACK_LIBS) -lm @@ -33,7 +34,7 @@ mri_history.c mri_copy_chunk.c mri_delete_chunk.c mri_sort.c \ mri_copy_dataset.c mri_destroy_dataset.c mri_remap.c \ mri_printfield.c mri_permute.c tumble.c mri_setfield.c \ - mri_matmult.c mri_esa.c + mri_matmult.c mri_esa.c mri_resample.c HFILES= slave_splus.h tumble.h DOCFILES= mri_complex_to_scalar_help.help mri_splus_filter_help.help \ mri_rpn_math_help.help \ @@ -48,7 +49,7 @@ mri_destroy_dataset_help.help mri_remap_help.help \ mri_printfield_help.help mri_permute_help.help \ mri_setfield_help.help mri_matmult_help.help \ - mri_esa_help.help + mri_esa_help.help mri_resample_help.help MISCFILES= bio_init.S @@ -60,6 +61,15 @@ $L/libarray.a $L/libmisc.a $L/libacct.a $L/libcrg.a HDRS= fmri.h mri.h par.h bio.h misc.h acct.h stdcrg.h slave_splus.h + +$(CB)/mri_resample: $O/mri_resample.o $O/mri_resample_help.o $(LIBFILES) + $(SINGLE_HELP_LD) + +$O/mri_resample.o: mri_resample.c + $(CC_RULE) + +$O/mri_resample_help.o: mri_resample_help.help + $(HELP_RULE) $(CB)/mri_esa: $O/mri_esa.o $O/mri_esa_help.o $(LIBFILES) $(SINGLE_HELP_LD) Index: src/mri_util/mri_esa_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_esa_help.help,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- src/mri_util/mri_esa_help.help 3 Dec 2003 20:28:36 -0000 1.5 +++ src/mri_util/mri_esa_help.help 13 Dec 2003 00:37:53 -0000 1.6 @@ -41,7 +41,8 @@ *Arguments:EigenvalueFile This output file contains the nEigen eigenvalues produced by each - solution. + solution. The eigenvalues are arranged in ascending order, that is, + smallest to largest. *Arguments:EvecFile Index: src/mri_util/mri_fft.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_fft.c,v retrieving revision 1.12 retrieving revision 1.14 diff -a -u -r1.12 -r1.14 --- src/mri_util/mri_fft.c 7 Aug 2003 20:19:28 -0000 1.12 +++ src/mri_util/mri_fft.c 17 Dec 2003 01:24:38 -0000 1.14 @@ -49,9 +49,10 @@ #define KEYBUF_SIZE 512 -static char rcsid[] = "$Id: mri_fft.c,v 1.12 2003/08/07 20:19:28 bakalj Exp $"; +static char rcsid[] = "$Id: mri_fft.c,v 1.14 2003/12/17 01:24:38 welling Exp $"; -typedef enum { RSLT_COMPLEX, RSLT_MODULUS, RSLT_PHASE, RSLT_SQMOD } ResultType; +typedef enum { + RSLT_COMPLEX, RSLT_MODULUS, RSLT_PHASE, RSLT_SQMOD, RSLT_REAL, RSLT_IMAG } ResultType; static MRI_Dataset *Input = NULL, *Output = NULL; static char selected_dim[512]= "t"; @@ -85,10 +86,11 @@ } static void calc_sizes(char* this_chunk, char* dimstr, - int* fast_blocksize_out, int* slow_blocksize_out ) { + long long* fast_blocksize_out, + long long* slow_blocksize_out ) { /* This routine will fail if selected_dim is not in dimstr! */ - int fast_blocksize; - int slow_blocksize; + long long fast_blocksize; + long long slow_blocksize; char* this_dim; fast_blocksize= 1; @@ -139,29 +141,30 @@ } static void transfer_data_scalar(char* this_chunk, - int fast_blksize, int slow_blksize, - int selected_extent_fast, - int selected_extent_slow) + long long fast_blksize, + long long slow_blksize, + long selected_extent_fast, + long selected_extent_slow) { - int in_offset= 0; - int out_offset= 0; - int islow; - int i; - int collective_blksize; - int oblock_size; + long long in_offset= 0; + long long out_offset= 0; + long long islow; + long i; + long collective_blksize; + long oblock_size; FComplex* buf= NULL; float* oblock= NULL; collective_blksize= - fast_blksize * selected_extent_fast * selected_extent_slow; + (long)(fast_blksize * selected_extent_fast * selected_extent_slow); oblock_size= collective_blksize; if (resultType==RSLT_COMPLEX) oblock_size *= 2; if (!(buf=(FComplex*)malloc(collective_blksize*sizeof(FComplex)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, collective_blksize*sizeof(FComplex)); if (!(oblock=(float*)malloc(oblock_size*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, oblock_size*sizeof(float)); for (islow=0; islow %d at %d\n", + fprintf(stderr,"block: %ld at %lld -> %ld at %lld\n", collective_blksize, in_offset, oblock_size, out_offset); in_offset += collective_blksize; @@ -209,29 +218,30 @@ } static void transfer_data_complex(char* this_chunk, - int fast_blksize, int slow_blksize, - int selected_extent_fast, - int selected_extent_slow) + long long fast_blksize, + long long slow_blksize, + long selected_extent_fast, + long selected_extent_slow) { - int in_offset= 0; - int out_offset= 0; - int islow; - int i; - int collective_blksize; - int oblock_size; + long long in_offset= 0; + long long out_offset= 0; + long long islow; + long i; + long collective_blksize; + long oblock_size; FComplex* buf= NULL; float* oblock= NULL; collective_blksize= - fast_blksize * selected_extent_fast * selected_extent_slow; + (long)(fast_blksize * selected_extent_fast * selected_extent_slow); oblock_size= collective_blksize; if (resultType==RSLT_COMPLEX) oblock_size *= 2; if (!(buf=(FComplex*)malloc(collective_blksize*sizeof(FComplex)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, collective_blksize*sizeof(FComplex)); if (!(oblock=(float*)malloc(oblock_size*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, oblock_size*sizeof(float)); for (islow=0; islow %d at %d\n", + fprintf(stderr,"block: %ld at %lld -> %ld at %lld\n", 2*collective_blksize, in_offset, oblock_size, out_offset); in_offset += 2*collective_blksize; @@ -279,33 +295,34 @@ } static void transfer_data_3d_scalar(char* this_chunk, - int fast_blksize, int slow_blksize, - int selected_extent_fast, - int selected_extent_med, - int selected_extent_slow) + long long fast_blksize, + long long slow_blksize, + long selected_extent_fast, + long selected_extent_med, + long selected_extent_slow) { - int in_offset= 0; - int out_offset= 0; - int ifast; - int islow; - int i; - int collective_blksize; - int fft_blksize; - int oblock_size; + long long in_offset= 0; + long long out_offset= 0; + long ifast; + long long islow; + long i; + long collective_blksize; + long fft_blksize; + long oblock_size; FComplex* buf= NULL; float* oblock= NULL; fft_blksize= selected_extent_fast * selected_extent_med * selected_extent_slow; - collective_blksize= fast_blksize * fft_blksize; + collective_blksize= (long)(fast_blksize * fft_blksize); oblock_size= collective_blksize; if (resultType==RSLT_COMPLEX) oblock_size *= 2; if (!(buf=(FComplex*)malloc(fft_blksize*sizeof(FComplex)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, fft_blksize*sizeof(FComplex)); if (!(oblock=(float*)malloc(oblock_size*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, oblock_size*sizeof(float)); for (islow=0; islowreal; + orunner += fast_blksize; + } + } + break; + case RSLT_IMAG: + { + float* orunner= oblock+ifast; + for (crunner= buf; crunnerimag; + orunner += fast_blksize; + } + } + break; } } mri_set_chunk( Output, this_chunk, oblock_size, out_offset, MRI_FLOAT, oblock ); if (verbose_flg) - fprintf(stderr,"block: %d at %d -> %d at %d\n", + fprintf(stderr,"block: %ld at %lld -> %ld at %lld\n", collective_blksize, in_offset, oblock_size, out_offset); in_offset += collective_blksize; @@ -378,33 +413,34 @@ } static void transfer_data_3d_complex(char* this_chunk, - int fast_blksize, int slow_blksize, - int selected_extent_fast, - int selected_extent_med, - int selected_extent_slow) + long long fast_blksize, + long long slow_blksize, + long selected_extent_fast, + long selected_extent_med, + long selected_extent_slow) { - int in_offset= 0; - int out_offset= 0; - int ifast; - int islow; - int i; - int collective_blksize; - int fft_blksize; - int oblock_size; + long long in_offset= 0; + long long out_offset= 0; + long ifast; + long long islow; + long i; + long collective_blksize; + long fft_blksize; + long oblock_size; FComplex* buf= NULL; float* oblock= NULL; fft_blksize= selected_extent_fast * selected_extent_med * selected_extent_slow; - collective_blksize= fast_blksize * fft_blksize; + collective_blksize= (long)(fast_blksize * fft_blksize); oblock_size= collective_blksize; if (resultType==RSLT_COMPLEX) oblock_size *= 2; if (!(buf=(FComplex*)malloc(fft_blksize*sizeof(FComplex)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, fft_blksize*sizeof(FComplex)); if (!(oblock=(float*)malloc(oblock_size*sizeof(float)))) - Abort("%s: unable to allocate %d bytes!\n", + Abort("%s: unable to allocate %ld bytes!\n", progname, oblock_size*sizeof(float)); for (islow=0; islowreal; + orunner += fast_blksize; + } + } + break; + case RSLT_IMAG: + { + float* orunner= oblock+ifast; + for (crunner= buf; crunnerimag; + orunner += fast_blksize; + } + } + break; } } mri_set_chunk( Output, this_chunk, oblock_size, out_offset, MRI_FLOAT, oblock ); if (verbose_flg) - fprintf(stderr,"block: %d at %d -> %d at %d\n", + fprintf(stderr,"block: %ld at %lld -> %ld at %lld\n", 2*collective_blksize, in_offset, oblock_size, out_offset); in_offset += 2*collective_blksize; @@ -480,7 +534,7 @@ static void fft_chunk_3d(char* this_chunk) { char key_buf[KEYBUF_SIZE]; char* dimstr; - int selected_extent_fast, selected_extent_med, selected_extent_slow; + long selected_extent_fast, selected_extent_med, selected_extent_slow; int chunk_complex= 0; if (strlen(selected_dim) != 3) @@ -505,12 +559,12 @@ if (verbose_flg) { if (chunk_complex) fprintf(stderr, - "selected dim extent(s) on input %d %d %d, chunk complex\n", + "selected dim extent(s) on input %ld %ld %ld, chunk complex\n", selected_extent_fast, selected_extent_med, selected_extent_slow); else fprintf(stderr, - "selected dim extent(s) on input %d %d %d, chunk scalar\n", + "selected dim extent(s) on input %ld %ld %ld, chunk scalar\n", selected_extent_fast, selected_extent_med, selected_extent_slow); } @@ -519,8 +573,8 @@ Abort("%s: attempted to FFT the complex v dimension!\n",progname); if (selected_extent_fast*selected_extent_med*selected_extent_slow > 1) { - int fast_blksize; - int slow_blksize; + long long fast_blksize; + long long slow_blksize; data_changed= 1; @@ -531,7 +585,8 @@ mri_set_string(Output, key_buf, "float32"); if (chunk_complex) { if ((resultType==RSLT_MODULUS) || (resultType==RSLT_PHASE) - || (resultType==RSLT_SQMOD)) + || (resultType==RSLT_SQMOD) || (resultType==RSLT_REAL) + || (resultType==RSLT_IMAG)) scalarize_chunk(Output,this_chunk); transfer_data_3d_complex(this_chunk, fast_blksize, slow_blksize, selected_extent_fast, selected_extent_med, @@ -556,7 +611,7 @@ static void fft_chunk(char* this_chunk) { char key_buf[KEYBUF_SIZE]; char* dimstr; - int selected_extent_fast, selected_extent_slow; + long selected_extent_fast, selected_extent_slow; int chunk_complex= 0; if (verbose_flg) fprintf(stderr,"ffting chunk <%s>\n",this_chunk); @@ -579,11 +634,11 @@ if (verbose_flg) { if (chunk_complex) fprintf(stderr, - "selected dim extent(s) on input %d %d, chunk complex\n", + "selected dim extent(s) on input %ld %ld, chunk complex\n", selected_extent_fast, selected_extent_slow); else fprintf(stderr, - "selected dim extent(s) on input %d %d, chunk scalar\n", + "selected dim extent(s) on input %ld %ld, chunk scalar\n", selected_extent_fast, selected_extent_slow); } @@ -591,8 +646,8 @@ Abort("%s: attempted to FFT the complex v dimension!\n",progname); if (selected_extent_fast*selected_extent_slow > 1) { - int fast_blksize; - int slow_blksize; + long long fast_blksize; + long long slow_blksize; data_changed= 1; @@ -603,7 +658,8 @@ mri_set_string(Output, key_buf, "float32"); if (chunk_complex) { if ((resultType==RSLT_MODULUS) || (resultType==RSLT_PHASE) - || (resultType==RSLT_SQMOD)) + || (resultType==RSLT_SQMOD) || (resultType==RSLT_REAL) + || (resultType==RSLT_IMAG)) scalarize_chunk(Output,this_chunk); transfer_data_complex(this_chunk, fast_blksize, slow_blksize, selected_extent_fast, selected_extent_slow); @@ -629,6 +685,7 @@ char* this_key; char this_chunk[KEYBUF_SIZE]; unsigned char **missing = NULL; + int count_set_type= 0; progname= argv[0]; @@ -677,24 +734,33 @@ } if (cl_present("inverse|inv")) fft_sign= -1; + count_set_type= 0; if (cl_present("complex|cpx")) { - if (cl_present("modulus|mod") || cl_present("phase|pha") || cl_present("squared_modulus|sqr")) - Abort("%s: at least two of -complex|cpx, -modulus|mod, -squared_modulus|sqr and -phase|pha are present!\n",argv[0]); + count_set_type += 1; resultType= RSLT_COMPLEX; } if (cl_present("modulus|mod")) { - if (cl_present("phase|pha")|| cl_present("squared_modulus|sqr")) - Abort("%s: at least two of -complex|cpx, -modulus|mod, -squared_modulus|sqr and -phase|pha are present!\n",argv[0]); + count_set_type += 1; resultType= RSLT_MODULUS; } if (cl_present("phase|pha")) { - if (cl_present("squared_modulus|sqr")) - Abort("%s: at least two of -complex|cpx, -modulus|mod, -squared_modulus|sqr and -phase|pha are present!\n",argv[0]); + count_set_type += 1; resultType= RSLT_PHASE; } if (cl_present("squared_modulus|sqr")) { + count_set_type += 1; resultType= RSLT_SQMOD; } + if (cl_present("real|rea")) { + count_set_type += 1; + resultType= RSLT_REAL; + } + if (cl_present("imaginary|ima")) { + count_set_type += 1; + resultType= RSLT_IMAG; + } + if (count_set_type>1) + Abort("%s: at least two of -complex|cpx, -modulus|mod, -squared_modulus|sqr -phase|pha -real|rea -imaginary|ima are present!\n",argv[0]); if (!cl_get("", "%s", infile)) { fprintf(stderr,"%s: Input file name not given.\n",argv[0]); Index: src/mri_util/mri_fft_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_fft_help.help,v retrieving revision 1.8 retrieving revision 1.9 diff -a -u -r1.8 -r1.9 --- src/mri_util/mri_fft_help.help 4 Nov 2003 22:26:52 -0000 1.8 +++ src/mri_util/mri_fft_help.help 17 Dec 2003 01:24:38 -0000 1.9 @@ -8,11 +8,11 @@ but the FFT dimensions must be adjacent in the 2-D and 3-D cases. mri_fft [-dimension Dimension] [-verbose] [-forward | -inverse] - [-complex | -modulus | -phase | -squared_modulus] + [-complex | -modulus | -phase | -squared_modulus |-real |-imaginary] infile outfile mri_fft [-d dim] [-v] [-fwd | -inv] - [-cpx | -mod | -pha | -sqr] infile outfile + [-cpx | -mod | -pha | -sqr | -rea | -ima] infile outfile *Usage:dimension @@ -55,24 +55,40 @@ [-modulus] (-mod) Specifies that the output data should be the modulus. Only one of - -complex, -modulus, -phase, or -squared_modulus can be specified; - -modulus is the default. + -complex, -modulus, -phase, -squared_modulus, -real, or + -imaginary can be specified; -modulus is the default. *Usage:phase [-phase] (-pha) Specifies that the output data should be the phase. Only one of - -complex, -modulus, -phase, or -squared_modulus can be specified; - -modulus is the default. + -complex, -modulus, -phase, -squared_modulus, -real, or + -imaginary can be specified; -modulus is the default. *Usage:squared_modulus [-squared_modulus] (-sqr) Specifies that the output data should be the squared modulus. Only - one of -complex, -modulus, -phase, or -squared_modulus can be - specified; -modulus is the default. + one of -complex, -modulus, -phase, -squared_modulus, -real, or + -imaginary can be specified; -modulus is the default. + +*Usage:real + + [-real] (-rea) + + Specifies that the output data should be the real part of the + result. Only one of -complex, -modulus, -phase, -squared_modulus, + -real, or -imaginary can be specified; -modulus is the default. + +*Usage:imaginary + + [-imaginary] (-ima) + + Specifies that the output data should be the imaginary part of the + result. Only one of -complex, -modulus, -phase, -squared_modulus, + -real, or -imaginary can be specified; -modulus is the default. *Usage:verbose Index: src/mri_util/mri_paste.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_paste.c,v retrieving revision 1.23 retrieving revision 1.25 diff -a -u -r1.23 -r1.25 --- src/mri_util/mri_paste.c 18 Sep 2003 17:49:55 -0000 1.23 +++ src/mri_util/mri_paste.c 4 May 2004 21:35:37 -0000 1.25 @@ -42,7 +42,7 @@ #define MAX_INPUT_FILES 64 #define MAX_BUF 1000000 -static char rcsid[] = "$Id: mri_paste.c,v 1.23 2003/09/18 17:49:55 bakalj Exp $"; +static char rcsid[] = "$Id: mri_paste.c,v 1.25 2004/05/04 21:35:37 welling Exp $"; typedef struct mrifile_struct { MRI_Dataset* ds; @@ -507,6 +507,7 @@ char infile[512], outfile[512], junkfile[512]; char* this_key; char this_chunk[KEYBUF_SIZE]; + char key_buf[KEYBUF_SIZE]; int i,j; progname= argv[0]; @@ -554,8 +555,8 @@ } - verbose_flg= cl_present("v"); - reallyverbose_flg= cl_present("V"); + verbose_flg= cl_present("v|verbose"); + reallyverbose_flg= cl_present("V|VERBOSE"); if (reallyverbose_flg) verbose_flg= 1; if (cl_cleanup_check()) { int i; @@ -581,10 +582,23 @@ Abort("%s: key too long!\n",progname); if (!strcmp(mri_get_string(Input[0],this_key),"[chunk]")) { safe_copy(this_chunk, this_key); - for (j=1; j\n", progname, j+1, this_chunk); - add_to_chunk(this_chunk); + safe_copy(key_buf, this_chunk); + safe_concat(key_buf,".dimensions"); + if (!mri_has(Input[0],key_buf)) + Abort("%s: first input has no %s tag!\n",progname,key_buf); + if (strchr(mri_get_string(Input[0],key_buf),*selected_dim)) { + for (j=1; j\n", + progname, j+1, this_chunk); + add_to_chunk(this_chunk); + } + else { + /* Ignore this chunk; it lacks the selected dimension. + * The copy from Input[0] has already been transcribed + * to the output. + */ + } } } Index: src/mri_util/mri_resample.c =================================================================== RCS file: src/mri_util/mri_resample.c diff -N src/mri_util/mri_resample.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/mri_util/mri_resample.c 5 Feb 2004 20:56:42 -0000 1.1 @@ -0,0 +1,326 @@ +/************************************************************ + * * + * mri_resample.c * + * * + * Permission is hereby granted to any individual or * + * institution for use, copying, or redistribution of * + * this code and associated documentation, provided * + * that such code and documentation are not sold for * + * profit and the following copyright notice is retained * + * in the code and documentation: * + * Copyright (c) 1997 Department of Statistics, * + * Carnegie Mellon University * + * * + * This program is distributed in the hope that it will * + * be useful, but WITHOUT ANY WARRANTY; without even the * + * implied warranty of MERCHANTABILITY or FITNESS FOR A * + * PARTICULAR PURPOSE. Neither Carnegie Mellon University * + * nor any of the authors assume any liability for * + * damages, incidental or otherwise, caused by the * + * installation or use of this software. * + * * + * CLINICAL APPLICATIONS ARE NOT RECOMMENDED, AND THIS * + * SOFTWARE HAS NOT BEEN EVALUATED BY THE UNITED STATES * + * FDA FOR ANY CLINICAL USE. * + * * + * * + * Original programming by Joel Welling, 5/98 * + ************************************************************/ +#include +#include +#include +#include +#include +#include +#include "mri.h" +#include "fmri.h" +#include "misc.h" +#include "stdcrg.h" + +#define KEYBUF_SIZE 512 + +static char rcsid[] = "$Id: mri_resample.c,v 1.1 2004/02/05 20:56:42 welling Exp $"; + +static MRI_Dataset *Input = NULL, *Output = NULL; +static char selected_dim[512]= ""; +static int new_extent; +static int data_changed= 0; +static char* progname; +static int const_flag= 0; +static int verbose_flag= 0; +static int debug_flag= 0; + +static void safe_copy(char* str1, char* str2) { + strncpy(str1, str2, KEYBUF_SIZE); + str1[KEYBUF_SIZE-1]= '\0'; +} + +static void safe_concat(char* str1, char* str2) { + strncat(str1, str2, (KEYBUF_SIZE-strlen(str1))-1); +} + +static int safe_get_extent(MRI_Dataset* ds, char* chunk, char* dim) +{ + char key_buf[KEYBUF_SIZE]; + char dim_buf[4]; + dim_buf[0]= *dim; + dim_buf[1]= '\0'; + safe_copy(key_buf,chunk); + safe_concat(key_buf,".extent."); + safe_concat(key_buf,dim_buf); + if (mri_has(Input,key_buf)) return mri_get_int(Input,key_buf); + else Abort("%s: input missing tag %s!\n",progname,key_buf); + return 0; /* not reached */ +} + +static void calc_sizes(char* this_chunk, char* dimstr, + long long* fast_blocksize_out, + long long* slow_blocksize_out ) { + /* This routine will fail if selected_dim is not in dimstr! */ + long long fast_blocksize; + long long slow_blocksize; + char* this_dim; + + fast_blocksize= 1; + + this_dim= dimstr; + while (*this_dim != *selected_dim) + fast_blocksize *= safe_get_extent(Input,this_chunk,this_dim++); + + this_dim++; /* step over selected dim */ + + slow_blocksize= 1; + while (*this_dim) + slow_blocksize *= safe_get_extent(Input, this_chunk, this_dim++); + + *fast_blocksize_out= fast_blocksize; + *slow_blocksize_out= slow_blocksize; +} + +static void transfer_data(char* this_chunk, + long long fast_blksize, long long slow_blksize, + int selected_extent, int new_extent, + double start, double end) +{ + long long in_offset= 0; + long long out_offset= 0; + long ifast; + long long islow; + double* ibuf= NULL; + double* obuf= NULL; + int missing_chunk= 0; + + missing_chunk= !strcmp(this_chunk,"missing"); + if (missing_chunk) + Abort("%s: I can't handle the missing chunk!\n",progname); + + if (!(obuf= (double*)malloc(fast_blksize*new_extent*sizeof(double)))) + Abort("%s: unable to allocate %d bytes!\n",progname, + fast_blksize*new_extent*sizeof(double)); + + for (islow=0; islow %lld * %d at %d\n", + shift, stride, fast_blksize, selected_extent, + in_offset, fast_blksize, new_extent, out_offset); + ibuf= mri_get_chunk(Input, this_chunk, fast_blksize*selected_extent, + in_offset, MRI_DOUBLE); + for (i=0; i=(double)(selected_extent-1)) { + for (ifast=0; ifast\n",this_chunk); + safe_copy(key_buf, this_chunk); + safe_concat(key_buf, ".dimensions"); + if (mri_has(Input,key_buf)) { + dimstr= mri_get_string(Input,key_buf); + if (debug_flag) fprintf(stderr,"dimstr %s\n",dimstr); + if (strchr(dimstr,*selected_dim)) { + safe_copy(key_buf, this_chunk); + safe_concat(key_buf, ".extent."); + safe_concat(key_buf, selected_dim); + if (mri_has(Input,key_buf)) + selected_extent= mri_get_int(Input,key_buf); + else Abort("%s: input missing tag %s!\n",progname,key_buf); + if (debug_flag) + fprintf(stderr,"selected dim extent on input %d\n",selected_extent); + if (selected_extent<2) { + /* resampling a constant- chunk was copied correctly in initial + * dataset copy. + */ + return; + } + else { + long long fast_blksize; + long long slow_blksize; + + data_changed= 1; + mri_set_int(Output, key_buf, new_extent); + calc_sizes(this_chunk, dimstr, &fast_blksize, &slow_blksize); + transfer_data(this_chunk, fast_blksize, slow_blksize, + selected_extent, new_extent, start, end); + } + } + else { + /* Chunk copied correctly in initial dataset copy */ + } + } +} + +int main( int argc, char* argv[] ) +{ + + char infile[512], outfile[512]; + char* this_key; + char this_chunk[KEYBUF_SIZE]; + char keybuf[KEYBUF_SIZE]; + double start; + double end; + + progname= argv[0]; + + /* Print version number */ + if (verbose_flag) Message( "# %s\n", rcsid ); + + /* Check to see if help was requested */ + if (testHelp(&argc, argv)) exit(0); + + /*** Parse command line ***/ + + cl_scan( argc, argv ); + + /* Get filenames */ + if (!cl_get("dimension|dim|d", "%option %s[t]",selected_dim)) { + fprintf(stderr,"%s: dimension to be interpolated not given.\n",argv[0]); + Help("usage"); + exit(-1); + } + if (strlen(selected_dim)>1) { + fprintf(stderr,"%s: Selected dim name must be 1 char long.\n",argv[0]); + Help("usage"); + exit(-1); + } + *selected_dim= tolower(*selected_dim); + if (!cl_get("length|len|l", "%option %d",&new_extent)) { + fprintf(stderr,"%s: new extent not given.\n",argv[0]); + Help("usage"); + exit(-1); + } + + if (!cl_get("start", "%option %lf",&start)) { + fprintf(stderr,"%s: start point not given.\n",argv[0]); + Help("usage"); + exit(-1); + } + + if (!cl_get("end", "%option %lf",&end)) { + fprintf(stderr,"%s: start point not given.\n",argv[0]); + Help("usage"); + exit(-1); + } + + if (!cl_get("", "%s", infile)) { + fprintf(stderr,"%s: Input file name not given.\n",argv[0]); + Help( "usage" ); + exit(-1); + } + if (!cl_get("", "%s", outfile)) { + fprintf(stderr,"%s: Output file name not given.\n",argv[0]); + Help( "usage" ); + exit(-1); + } + verbose_flag= cl_present("verbose|ver|v"); + debug_flag= cl_present("debug"); + if (cl_cleanup_check()) { + int i; + fprintf(stderr,"%s: invalid argument in command line:\n ",argv[0]); + for (i=0; i=KEYBUF_SIZE) + Abort("%s: key too long!\n",argv[0]); + if (!strcmp(mri_get_string(Input,this_key),"[chunk]")) { + strncpy(this_chunk, this_key, KEYBUF_SIZE); + this_chunk[KEYBUF_SIZE-1]= '\0'; + + safe_copy(keybuf,this_chunk); + safe_concat(keybuf,".datatype"); + if (!mri_has(Output, keybuf) + || strncmp( mri_get_string( Output, keybuf ), "float", 5 )) { + /* We will coerce the output datatype to 4-byte floats if it is + * not one of the floating types. + */ + mri_set_string( Output, keybuf, "float32" ); + } + + resample_chunk(this_chunk, start, end); + } + } + + /* Write and close data-sets */ + mri_close_dataset( Input ); + mri_close_dataset( Output ); + + if (verbose_flag) Message( "# Resampling complete.\n" ); + if (!data_changed) + Message("# Warning: input and output datasets identical!\n"); + + return 0; +} + Index: src/mri_util/mri_resample_help.help =================================================================== RCS file: src/mri_util/mri_resample_help.help diff -N src/mri_util/mri_resample_help.help --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/mri_util/mri_resample_help.help 10 May 2004 18:07:39 -0000 1.2 @@ -0,0 +1,72 @@ +*Introduction + + mri_resample resamples a Pgh MRI dataset along one dimension, + producing a new dataset with the same angular alignment as the + original but with different starting and ending values and voxel + size in the given dimension. + + To run mri_resample use: + + mri_resample -v -debug -dimension Dimension -length Length + -start Start -end End infile outfile + +*Arguments:dimension + -dimension Dimension (-dim|d Dimension) + + Specifies the dimension to be interpolated. Valid values are one + character long; case is ignored. This argument is required. + +*Arguments:length + -length Length (-len|l Length) + + Specifies the output extent of that dimension. This + argument is required. + +*Arguments:v + [-v] + + Sets verbose output + +*Arguments:debug + [-debug] + + Sets debugging output + +*Arguments:start + [-start Start] + + Specifies the starting coordinate for resampling, given as a + floating point number in voxels. The position matching the + first voxel in the input is 0.0; the position matching the + last voxel is extent-1 . Values outside the input bounds are + permitted. + +*Arguments:end + [-end End] + + Specifies the ending coordinate for resampling, given as a + floating point number in voxels. The position matching the + first voxel in the input is 0.0; the position matching the + last voxel is extent-1 . Values outside the input bounds are + permitted. + +*Arguments:infile + infile + + Specifies the input dataset. This argument is required. + +*Arguments:outfile + outfile + + Specifies the output dataset. This argument is required. + +*Details:Notes + + Chunks not containing the selected dimension are copied verbatim. + + All chunks containing the given dimension will be resampled. + (Note that this can give confusing results if the extents of the + dimension vary between chunks!) + + If interpolation produces a position outside the boundaries of + the input dataset, the nearest boundary value is used. Index: src/mri_util/mri_setfield.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_setfield.c,v retrieving revision 1.3 retrieving revision 1.5 diff -a -u -r1.3 -r1.5 --- src/mri_util/mri_setfield.c 7 Aug 2003 20:53:00 -0000 1.3 +++ src/mri_util/mri_setfield.c 7 Feb 2004 01:10:52 -0000 1.5 @@ -28,12 +28,13 @@ #include #include #include +#include #include "mri.h" #include "fmri.h" #include "misc.h" #include "stdcrg.h" -static char rcsid[] = "$Id: mri_setfield.c,v 1.3 2003/08/07 20:53:00 bakalj Exp $"; +static char rcsid[] = "$Id: mri_setfield.c,v 1.5 2004/02/07 01:10:52 welling Exp $"; int main (argc, argv) int argc; @@ -46,6 +47,8 @@ int delete_flag= 0; int fld_present= 0; int val_present= 0; + int all012_present= 0; + int allxyz_present= 0; char *s; /* Check to see if help was requested */ @@ -68,6 +71,8 @@ fld_present= cl_get( "field|fld", "%option %s", field ); val_present= cl_get( "value|val", "%option %s", value ); if (cl_present("delete|del")) delete_flag= 1; + all012_present= cl_present("all012"); + allxyz_present= cl_present("allxyz"); if(!cl_get("", "%s", infile)) { fprintf(stderr, "%s: Input file name not given.\n", argv[0]); @@ -92,8 +97,61 @@ ds = mri_open_dataset(infile, MRI_MODIFY); if (ds == NULL) Abort("%s: cannot open dataset %s for modification!\n", infile); - if (delete_flag) mri_remove(ds,field); - else mri_set_string(ds,field,value); + if (delete_flag) { + if (all012_present) { + char fullField[512]; + int i; + for (i=0; i<3; i++) { + snprintf(fullField,sizeof(fullField)-1,"%s.%d",field,i); + fullField[sizeof(fullField)-1]= '\0'; + mri_remove(ds,fullField); + } + } + else if (allxyz_present) { + char fullField[512]; + int i; + for (i=0; i<3; i++) { + snprintf(fullField,sizeof(fullField)-1,"%s.%c",field,'x'+i); + fullField[sizeof(fullField)-1]= '\0'; + mri_remove(ds,fullField); + } + } + else { + mri_remove(ds,field); + } + } + else { + if (all012_present || allxyz_present) { + char fullField[512]; + char oneVal[512]; + char* tmp; + int i; + int start= 0; + int end= strlen(value)-1; + /* Strip things like quotes and spaces. This is necessary + * because of annoying behavior on the part of clproc. + */ + while ((ispunct(value[start]) && value[start]!='-') + || isspace(value[start])) start++; + while (ispunct(value[end]) || isspace(value[start])) { + value[end]= '\0'; end--; + } + + for (i=0; i<3; i++) { + char* tok= strtok_r((i==0)?value+start:NULL,":,",&tmp); + if (!tok) Abort("%s: can't get token for value %d!\n",argv[0],i); + if (all012_present) + snprintf(fullField,sizeof(fullField)-1,"%s.%d",field,i); + else if (allxyz_present) + snprintf(fullField,sizeof(fullField)-1,"%s.%c",field,'x'+i); + fullField[sizeof(fullField)-1]= '\0'; + mri_set_string(ds,fullField,tok); + } + } + else { + mri_set_string(ds,field,value); + } + } hist_add_cl(ds, argc, argv); mri_close_dataset(ds); return(0); Index: src/mri_util/mri_setfield_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_setfield_help.help,v retrieving revision 1.2 retrieving revision 1.4 diff -a -u -r1.2 -r1.4 --- src/mri_util/mri_setfield_help.help 7 Aug 2003 20:53:11 -0000 1.2 +++ src/mri_util/mri_setfield_help.help 4 May 2004 21:35:37 -0000 1.4 @@ -4,10 +4,11 @@ a Pittsburgh MRI dataset, or to delete that field To run mri_setfield use: - mri_setfield -field Field -value Valstring Input-file + mri_setfield -field Field [-all012] [-allxyz] + -value Valstring Input-file or: - mri_setfield -input Input-header-file -field Field -delete + mri_setfield -field Field [-all012] [-allxyz] -delete Input-file or: mri_setfield -help [topic] @@ -30,7 +31,34 @@ Specifies the new value for the field. This value is handled as a string; if the field is to have a numerical value it is the user's responsibility to make sure that the given string is - parsable as a number. + parsable as a number. If -all012 or -allxyz are used, the string + must be a colon-separated list of substrings. + +*Arguments:all012 + -all012 + + Specifies that three fields should be set or deleted, + with the names field.0, field.1, and field.2. If the -delete + option is not given, values are taken from successive + comma- or colon-separated parts of the value string. In + this case the value string must be a colon-separated list, + for example "17.2:12.4:-3". This option saves multiple commands + when manipulating 3D data tags. Quotes and spaces (and other + chars for which ispunct() or isspace() returns true) are stripped from + the beginning and end of the string. + +*Arguments:allxyz + -allxyz + + Specifies that three fields should be set or deleted, + with the names field.x, field.y, and field.z. If the -delete + option is not given, values are taken from successive + comma- or color- colon-separated parts of the value string. In + this case the value string must be a colon-separated list, + for example '17.2,12.4,-3'. This option saves multiple commands + when manipulating 3D data tags. Quotes and spaces (and other + chars for which ispunct() or isspace() returns true) are stripped from + the beginning and end of the string. *Arguments:infile infile Index: src/mri_util/mri_sort.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_sort.c,v retrieving revision 1.5 retrieving revision 1.6 diff -a -u -r1.5 -r1.6 --- src/mri_util/mri_sort.c 7 Aug 2003 20:50:41 -0000 1.5 +++ src/mri_util/mri_sort.c 4 Feb 2004 22:57:33 -0000 1.6 @@ -48,7 +48,7 @@ #define KEYBUF_SIZE 512 -static char rcsid[] = "$Id: mri_sort.c,v 1.5 2003/08/07 20:50:41 bakalj Exp $"; +static char rcsid[] = "$Id: mri_sort.c,v 1.6 2004/02/04 22:57:33 welling Exp $"; static MRI_Dataset *Input = NULL, *Output = NULL; static char* progname; @@ -325,9 +325,6 @@ progname= argv[0]; - /* Print version number */ - Message( "# %s\n", rcsid ); - /* Check to see if help was requested */ if (testHelp(&argc, argv)) exit(0); @@ -369,6 +366,9 @@ /*** End command-line parsing ***/ + /* Print version number */ + if (verbose_flg) Message( "# %s\n", rcsid ); + if (!strcmp(this_chunk,"missing")) Abort("%s: it is not legal to sort the 'missing' chunk!\n",argv[0]); @@ -405,7 +405,7 @@ mri_close_dataset( Input ); mri_close_dataset( Output ); - Message( "# Sorting complete.\n" ); + if (verbose_flg) Message( "# Sorting complete.\n" ); return 0; } Index: src/mri_util/mri_subsample.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_subsample.c,v retrieving revision 1.18 retrieving revision 1.19 diff -a -u -r1.18 -r1.19 --- src/mri_util/mri_subsample.c 7 Aug 2003 20:53:49 -0000 1.18 +++ src/mri_util/mri_subsample.c 4 May 2004 21:35:37 -0000 1.19 @@ -56,7 +56,7 @@ #define KEYBUF_SIZE 512 -static char rcsid[] = "$Id: mri_subsample.c,v 1.18 2003/08/07 20:53:49 bakalj Exp $"; +static char rcsid[] = "$Id: mri_subsample.c,v 1.19 2004/05/04 21:35:37 welling Exp $"; typedef enum { SMPL_MAX, SMPL_MIN, SMPL_MEAN, SMPL_SUM, SMPL_COUNT, SMPL_CLOSEST, @@ -957,8 +957,8 @@ else if (q3_flag) smpl_method= SMPL_Q3; else if (iqr_flag) smpl_method= SMPL_IQR; - verbose_flag= cl_present("v"); - reallyverbose_flag= cl_present("V"); + verbose_flag= cl_present("v|verbose"); + reallyverbose_flag= cl_present("V|debug"); if (reallyverbose_flag) verbose_flag= 1; if (!cl_get("", "%s", infile)) { Index: src/mri_util/mri_subsample_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/mri_util/mri_subsample_help.help,v retrieving revision 1.10 retrieving revision 1.11 diff -a -u -r1.10 -r1.11 --- src/mri_util/mri_subsample_help.help 18 Sep 2003 17:41:24 -0000 1.10 +++ src/mri_util/mri_subsample_help.help 4 May 2004 21:35:37 -0000 1.11 @@ -16,7 +16,7 @@ [-shift Shift] [-base base] [-min | -max | -mean | -sum | -count | -closest | -median | -q1 | -q3 | -iqr] - [-verbose] infile outfile + [-verbose] [-debug] infile outfile *Examples @@ -173,6 +173,13 @@ Sets the verbose flag to on, which displays output to the screen showing progress. (-V shows very verbose output.) + +*Arguments:debug + [-debug] (-V) + + Ex. -debug + + Requests debugging output. *Arguments:infile infile Index: src/outlier/outlier.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/outlier/outlier.c,v retrieving revision 1.9 retrieving revision 1.10 diff -a -u -r1.9 -r1.10 --- src/outlier/outlier.c 27 Nov 2003 00:48:48 -0000 1.9 +++ src/outlier/outlier.c 16 Jan 2004 19:18:18 -0000 1.10 @@ -47,7 +47,7 @@ #include "fmri.h" #include "stdcrg.h" -static char rcsid[] = "$Id: outlier.c,v 1.9 2003/11/27 00:48:48 welling Exp $"; +static char rcsid[] = "$Id: outlier.c,v 1.10 2004/01/16 19:18:18 welling Exp $"; static char* progname= NULL; @@ -458,19 +458,19 @@ else { if (mean_supplied_flag) { /* overwrite mean with values from file */ - mri_read_chunk( Mean, "images", 2*dx*dy, z*dx*dy, MRI_DOUBLE, + mri_read_chunk( Mean, "images", 2*dx*dy, z*2*dx*dy, MRI_DOUBLE, c_mean[0] ); realign_matrix( (void **) c_mean, dy, (long) (dx*sizeof(DComplex)) ); } if (stdv_supplied_flag) { /* overwrite stdv with values from file */ - mri_read_chunk( Stdv, "images", 2*dx*dy, z*dx*dy, MRI_DOUBLE, + mri_read_chunk( Stdv, "images", 2*dx*dy, z*2*dx*dy, MRI_DOUBLE, c_stdv[0] ); realign_matrix( (void **) c_stdv, dy, (long) (dx*sizeof(DComplex) ) ); } - if (stdv_supplied_flag) { + if (iqr_supplied_flag) { /* overwrite stdv with values from file */ - mri_read_chunk( Stdv, "images", 2*dx*dy, z*dx*dy, MRI_DOUBLE, + mri_read_chunk( Stdv, "images", 2*dx*dy, z*2*dx*dy, MRI_DOUBLE, c_stdv[0] ); realign_matrix( (void **) c_stdv, dy, (long) (dx*sizeof(DComplex) ) ); /* rescale appropriately, since cutoffs are specified in stdv's */ Index: src/par_util/par_translate_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/par_util/par_translate_help.help,v retrieving revision 1.4 retrieving revision 1.5 diff -a -u -r1.4 -r1.5 --- src/par_util/par_translate_help.help 19 Oct 2000 00:25:36 -0000 1.4 +++ src/par_util/par_translate_help.help 10 May 2004 18:12:37 -0000 1.5 @@ -32,7 +32,7 @@ Ex: -o estireg3d The value of outkey is one of a set of strings specifying the - parameter format of the input file. Recognized output keys are: + parameter format of the output file. Recognized output keys are: afni3d - parameters as produced by the AFNI "3dvolreg" command estireg3d - parameters as produced by the Fiasco "estireg3d" command Index: src/reader/afni_defs.h =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/afni_defs.h,v retrieving revision 1.2 retrieving revision 1.3 diff -a -u -r1.2 -r1.3 --- src/reader/afni_defs.h 26 Jun 2003 22:12:42 -0000 1.2 +++ src/reader/afni_defs.h 14 Jan 2004 21:20:51 -0000 1.3 @@ -65,6 +65,14 @@ #define ORI_A2P_TYPE 3 /* Anterior to Posterior */ #define ORI_I2S_TYPE 4 /* Inferior to Superior */ #define ORI_S2I_TYPE 5 /* Superior to Inferior */ +#define MARKS_MAXNUM 10 +#define MARKS_MAXLAB 20 +#define MARKS_MAXHELP 256 +#define MARKS_MAXFLAG 8 +#define VIEW_ORIGINAL_TYPE 0 +#define VIEW_ACPCALIGNED_TYPE 1 +#define VIEW_TALAIRACH_TYPE 2 +#define VIEW_REGISTERED_TYPE 3 static const char* typestring_names[]= { "3DIM_HEAD_ANAT", "3DIM_HEAD_FUNC", "3DIM_GEN_ANAT", "3DIM_GEN_FUNC", Index: src/reader/afni_reader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/afni_reader.c,v retrieving revision 1.8 retrieving revision 1.12 diff -a -u -r1.8 -r1.12 --- src/reader/afni_reader.c 1 Jul 2003 21:35:22 -0000 1.8 +++ src/reader/afni_reader.c 5 May 2004 21:35:01 -0000 1.12 @@ -57,7 +57,7 @@ #include "afni_defs.h" -static char rcsid[] = "$Id: afni_reader.c,v 1.8 2003/07/01 21:35:22 welling Exp $"; +static char rcsid[] = "$Id: afni_reader.c,v 1.12 2004/05/05 21:35:01 welling Exp $"; #define SINGLE_QUOTE 0x27 @@ -71,6 +71,10 @@ typedef struct afni_data_struct { float* float_facs; int facs_length; + int flip_z; + long slicesize; + long slicesize_bytes; + long nslices; long blocksize; long blocksize_bytes; long long base_offset; @@ -331,9 +335,9 @@ } else if (!strcmp(name,"DELTA")) { checkFloatValidity(name,buf,count,3); - kvDefDouble(info,"voxel_x", buf[0]); - kvDefDouble(info,"voxel_y", buf[1]); - kvDefDouble(info,"voxel_z", buf[2]); + kvDefDouble(info,"afni.DELTA.0", buf[0]); + kvDefDouble(info,"afni.DELTA.1", buf[1]); + kvDefDouble(info,"afni.DELTA.2", buf[2]); } else if (!strcmp(name,"BRICK_FLOAT_FACS")) { int i; @@ -449,13 +453,73 @@ } } +static void rescueMissing( FileHandler* self, KVHash* info, SList* cstack ) +{ + SList* otherChunks= slist_create(); + ChunkHandlerPair* chPair= NULL; + + slist_totop(cstack); + while (!slist_empty(cstack)) { + ChunkHandlerPair* tmpPair= (ChunkHandlerPair*)slist_pop(cstack); + if (!strcmp(kvGetString(tmpPair->info,"chunkname"),"missing")) + chPair= tmpPair; + else slist_append(otherChunks, tmpPair); + } + + if (chPair != NULL) { + int len= kvGetInt(info,"dt")*kvGetInt(info,"dz"); + int* intBuf= NULL; + unsigned char* charBuf= NULL; + KVHash* subInfo= chPair->info; + FileHandler* handler= chPair->handler; + int i; + + if (!(intBuf=(int*)malloc(len*sizeof(int)))) + Abort("%s: unable to allocate %d bytes!\n", len*sizeof(int)); + if (!(charBuf=(unsigned char*)malloc(len*sizeof(unsigned char)))) + Abort("%s: unable to allocate %d bytes!\n", len*sizeof(unsigned char)); + + kvDefInt(subInfo,"dt",kvGetInt(info,"dt")); + kvDefInt(subInfo,"dz",kvGetInt(info,"dz")); + kvDefString(subInfo,"dimstr",kvGetString(info,"missing.dimensions")); + kvDefInt(subInfo,"datatype_out",MRI_UNSIGNED_CHAR); + kvDefString(subInfo,"chunkfile",""); + + FH_PROCESSHEADER( handler, subInfo, cstack ); + FH_READ( handler, subInfo, 0, len, MRI_INT, intBuf ); + FH_CLOSE( handler ); + FH_DESTROYSELF( handler ); + + for (i=0; ihandler= ramDataHandlerFactory(charBuf, len, MRI_UNSIGNED_CHAR); + } + slist_append(cstack, chPair); + + while (!slist_empty(otherChunks)) { + slist_append(cstack, slist_pop(otherChunks)); + } + slist_destroy(otherChunks,NULL); + + kvDelete(info,"missing.dimensions"); +} + static void translateSomePairs( FileHandler* self, KVHash* info, SList* cStack ) { KVHash* defs= kvGetHash(info,"definitions"); + KVHash* extNames= kvGetHash(info,"external_names"); KVIterator* kvi= NULL; AfniData* data= (AfniData*)(self->hook); + /* If a typical Fiasco missing chunk dimension string is + * present, we probably have to rescue a chunk of missing + * info from mangled form. + */ + if (kvLookup(info,"missing.dimensions") + && (!strcmp(kvGetString(info,"missing.dimensions"),"zt") + || !strcmp(kvGetString(info,"missing.dimensions"),"tz"))) + rescueMissing(self,info,cStack); + /* The TR is the only value in TAXIS_FLOATS typically used in FIASCO */ if (kvLookup(info,"afni.TAXIS_FLOATS.1")) { kvDefInt(info,"TR", @@ -493,75 +557,150 @@ kvDefString(info,"dimstr",tbuf); } - if (kvLookup(info,"afni.ORIGIN.0") && kvLookup(info,"voxel_x")) { - /* Let's calculate the volume corners and center. We're - * currently ignoring the ambiguity that the coordinate - * system might not be right-handed. + if (kvLookup(info,"afni.ORIGIN.0") && kvLookup(info,"afni.DELTA.0")) { + /* Let's calculate the volume corners and center. + * AFNI sometimes works in left-handed coordinates, so + * we have to examine the orientation of things. We must + * laboriously untangle the coordinate info for each of several + * known cases. */ double origin[3]; double vox[3]; int dx; int dy; int dz; + origin[0]= kvGetDouble(info,"afni.ORIGIN.0"); origin[1]= kvGetDouble(info,"afni.ORIGIN.1"); origin[2]= kvGetDouble(info,"afni.ORIGIN.2"); - vox[0]= kvGetDouble(info,"voxel_x"); - vox[1]= kvGetDouble(info,"voxel_y"); - vox[2]= kvGetDouble(info,"voxel_z"); + vox[0]= kvGetDouble(info,"afni.DELTA.0"); + vox[1]= kvGetDouble(info,"afni.DELTA.1"); + vox[2]= kvGetDouble(info,"afni.DELTA.2"); dx= kvGetInt(info,"dx"); dy= kvGetInt(info,"dy"); dz= kvGetInt(info,"dz"); - if (!kvLookup(info,"tlf.0")) { - kvDefDouble(info,"tlf.0",origin[0]); - kvDefDouble(info,"tlf.1",origin[1]); - kvDefDouble(info,"tlf.2",origin[2]); - kvDefString(defs,"tlf.0", "top left front X (mm), AFNI internal coords"); - kvDefString(defs,"tlf.1", "top left front Y (mm), AFNI internal coords"); - kvDefString(defs,"tlf.2", "top left front Z (mm), AFNI internal coords"); - } + if (!strcmp(kvGetString(info,"afni.ORIENT_SPECIFIC.0"), "R2L") + && !strcmp(kvGetString(info,"afni.ORIENT_SPECIFIC.1"), "A2P")) { + if (!strcmp(kvGetString(info,"afni.ORIENT_SPECIFIC.2"), "S2I")) { + /* This is the case found in +orig files generated by pghtoafni */ + if (vox[0]<=0.0 || vox[1]<=0.0 || vox[2]>=0.0) { + Abort("%s: AFNI ORIENT_SPECIFIC and DELTA tags are incompatible!\n", + progname); +#ifdef never + Warning(1,"%s: AFNI ORIENT_SPECIFIC and DELTA tags are incompatible!\n", + progname); + if (vox[0]<0.0) vox[0]= -vox[0]; + if (vox[1]<0.0) vox[1]= -vox[0]; + if (vox[2]>0.0) vox[2]= -vox[0]; +#endif + } + vox[0]= vox[0]; + vox[1]= vox[1]; + vox[2]= -vox[2]; + origin[0]= origin[0]; + origin[1]= -origin[1]; + origin[2]= -origin[2]; + data->flip_z= 0; + } + else if (!strcmp(kvGetString(info,"afni.ORIENT_SPECIFIC.2"), "I2S")) { + /* This is the case found in +tlrc files generated by adwarp */ + if (vox[0]<=0.0 || vox[1]<=0.0 || vox[2]<=0.0) { + Abort("%s: AFNI ORIENT_SPECIFIC and DELTA tags are incompatible!\n", + progname); +#ifdef never + Warning(1,"%s: AFNI ORIENT_SPECIFIC and DELTA tags are incompatible!\n", + progname); + if (vox[0]<0.0) vox[0]= -vox[0]; + if (vox[1]<0.0) vox[1]= -vox[0]; + if (vox[2]<0.0) vox[2]= -vox[0]; +#endif + } + vox[0]= vox[0]; + vox[1]= vox[1]; + vox[2]= vox[2]; + origin[0]= origin[0]; + origin[1]= -origin[1]; + origin[2]= -origin[2]-(dz-1)*vox[2]; + data->flip_z= 1; + } + else Abort("%s: nonsense AFNI coordinate system %s-%s-%s!\n", + progname,kvGetString(info,"afni.ORIENT_SPECIFIC.0"), + kvGetString(info,"afni.ORIENT_SPECIFIC.1"), + kvGetString(info,"afni.ORIENT_SPECIFIC.2")); + } + else Abort("%s: unsupported AFNI coordinate system %s-%s-%s!\n", + progname,kvGetString(info,"afni.ORIENT_SPECIFIC.0"), + kvGetString(info,"afni.ORIENT_SPECIFIC.1"), + kvGetString(info,"afni.ORIENT_SPECIFIC.2")); + + /* We want to get rid of the afni.ORIENT_SPECIFIC values, so that + * proper values will be generated if this dataset is converted + * back to AFNI coordinates. If data->flip_z has been set the + * data will be reordered on input to smartreader, so the + * original afni.ORIENT_SPECIFIC values may not hold. + */ + kvDefString(extNames,"afni.ORIENT_SPECIFIC.0",""); + kvDefString(extNames,"afni.ORIENT_SPECIFIC.1",""); + kvDefString(extNames,"afni.ORIENT_SPECIFIC.2",""); + /* Use the untangled origin and step to establish corners and + * voxel info. + */ + kvDefDouble(info,"voxel_x",vox[0]); + kvDefDouble(info,"voxel_y",vox[1]); + kvDefDouble(info,"voxel_z",vox[2]); + if (!kvLookup(info,"blb.0")) { + kvDefDouble(info,"blb.0",origin[0]); + kvDefDouble(info,"blb.1",origin[1]); + kvDefDouble(info,"blb.2",origin[2]); + kvDefString(defs,"blb.0", + "bottom left back X (mm), FIASCO internal coords"); + kvDefString(defs,"blb.1", + "bottom left back Y (mm), FIASCO internal coords"); + kvDefString(defs,"blb.2", + "bottom left back Z (mm), FIASCO internal coords"); + } if (!kvLookup(info,"trf.0")) { kvDefDouble(info,"trf.0",origin[0]+(dx-1)*vox[0]); - kvDefDouble(info,"trf.1",origin[1]); - kvDefDouble(info,"trf.2",origin[2]); + kvDefDouble(info,"trf.1",origin[1]-(dy-1)*vox[1]); + kvDefDouble(info,"trf.2",origin[2]+(dz-1)*vox[2]); kvDefString(defs,"trf.0", - "top right front X (mm), AFNI internal coords"); + "top right front X (mm), FIASCO internal coords"); kvDefString(defs,"trf.1", - "top right front Y (mm), AFNI internal coords"); + "top right front Y (mm), FIASCO internal coords"); kvDefString(defs,"trf.2", - "top right front Z (mm), AFNI internal coords"); + "top right front Z (mm), FIASCO internal coords"); } - if (!kvLookup(info,"tlb.0")) { kvDefDouble(info,"tlb.0",origin[0]); - kvDefDouble(info,"tlb.1",origin[1]+(dy-1)*vox[1]); - kvDefDouble(info,"tlb.2",origin[2]); - kvDefString(defs,"tlb.0", "top left back X (mm), AFNI internal coords"); - kvDefString(defs,"tlb.1", "top left back Y (mm), AFNI internal coords"); - kvDefString(defs,"tlb.2", "top left back Z (mm), AFNI internal coords"); + kvDefDouble(info,"tlb.1",origin[1]); + kvDefDouble(info,"tlb.2",origin[2]+(dz-1)*vox[2]); + kvDefString(defs,"tlb.0", + "top left back X (mm), FIASCO internal coords"); + kvDefString(defs,"tlb.1", + "top left back Y (mm), FIASCO internal coords"); + kvDefString(defs,"tlb.2", + "top left back Z (mm), FIASCO internal coords"); } - if (!kvLookup(info,"blf.0")) { kvDefDouble(info,"blf.0",origin[0]); - kvDefDouble(info,"blf.1",origin[1]); - kvDefDouble(info,"blf.2",origin[2]+(dz-1)*vox[2]); + kvDefDouble(info,"blf.1",origin[1]-(dy-1)*vox[1]); + kvDefDouble(info,"blf.2",origin[2]); kvDefString(defs,"blf.0", - "bottom left front X (mm), AFNI internal coords"); + "bottom left front X (mm), FIASCO internal coords"); kvDefString(defs,"blf.1", - "bottom left front Y (mm), AFNI internal coords"); + "bottom left front Y (mm), FIASCO internal coords"); kvDefString(defs,"blf.2", - "bottom left front Z (mm), AFNI internal coords"); + "bottom left front Z (mm), FIASCO internal coords"); } - if (!kvLookup(info,"ctr.0")) { kvDefDouble(info,"ctr.0",origin[0] + ((0.5*dx)-1)*vox[0]); - kvDefDouble(info,"ctr.1",origin[1] + ((0.5*dy)-1)*vox[1]); + kvDefDouble(info,"ctr.1",origin[1] - ((0.5*dy)-1)*vox[1]); kvDefDouble(info,"ctr.2",origin[2] + ((0.5*dz)-1)*vox[2]); - kvDefString(defs,"ctr.0", "center X (mm), AFNI internal coords"); - kvDefString(defs,"ctr.1", "center Y (mm), AFNI internal coords"); - kvDefString(defs,"ctr.2", "center Z (mm), AFNI internal coords"); + kvDefString(defs,"ctr.0", "center X (mm), FIASCO internal coords"); + kvDefString(defs,"ctr.1", "center Y (mm), FIASCO internal coords"); + kvDefString(defs,"ctr.2", "center Z (mm), FIASCO internal coords"); } } @@ -583,23 +722,52 @@ } else if (t1t1) kvDefString(info,"reorder_pattern", + "reversed_even/odd"); else Abort("%s: unknown slice timing pattern: %f %f %f\n",t0,t1,t2); } - else Abort("%s: unknown slice timing pattern: %f %f %f\n",t0,t1,t2); + else if (t1>t0) { + if (t1>t2) kvDefString(info,"reorder_pattern","reversed_odd/even"); + else Abort("%s: unknown slice timing pattern: %f %f %f\n", + progname,t0,t1,t2); + } + else Abort("%s: unknown slice timing pattern: %f %f %f\n", + progname,t0,t1,t2); } else if (t0 == t1 && t1 == t2) { /* Apparently no useful data was saved */ } - else Abort("%s: unknown slice timing pattern: %f %f %f\n",t0,t1,t2); + else Abort("%s: unknown slice timing pattern: %f %f %f\n", + progname,t0,t1,t2); } + /* Make a note of the slice and image sizes, for convenience + * during reading + */ + data->slicesize= kvGetInt(info,"dx")*kvGetInt(info,"dy"); + if (kvLookup(info,"dv")) data->slicesize *= kvGetInt(info,"dv"); + data->slicesize_bytes= + data->slicesize*typesize[kvGetInt(info,"datatype_in")]; + data->blocksize= data->slicesize*kvGetInt(info,"dz"); + data->blocksize_bytes= data->slicesize_bytes*kvGetInt(info,"dz"); + data->nslices= kvGetInt(info,"dz"); + data->base_offset= kvGetLong(info,"start_offset"); + if (data->facs_length != 0) { /* Somewhere along the way we've picked up scaling factors. Make * sure there are enough, and otherwise set up to apply them on * the fly. */ - long blocksize; if (kvLookup(info,"dt") && data->facs_length != kvGetInt(info,"dt")) Abort("%s: Number of AFNI scaling factors (%d) doesn't match and time series length (%d)!\n", @@ -609,15 +777,13 @@ kvDefInt(info,"handler_datatype_out",MRI_FLOAT); } - blocksize= kvGetInt(info,"dx")*kvGetInt(info,"dy")*kvGetInt(info,"dz"); - if (kvLookup(info,"dv")) blocksize *= kvGetInt(info,"dv"); - data->blocksize= blocksize; - data->blocksize_bytes= blocksize*typesize[kvGetInt(info,"datatype_in")]; - data->base_offset= kvGetLong(info,"start_offset"); - /* Force the reading process to break between timesteps */ kvDefLong(info,"skip.z",0); } + if (data->flip_z != 0) { + /* Force the reading process to break between slices */ + kvDefLong(info,"skip.y",0); + } } @@ -636,6 +802,7 @@ if (debug) fprintf(stderr,"<%s>, type %s, length %d\n", name, typestr, count); + if (!strcmp(typestr,"string-attribute")) { int i; int c; @@ -650,7 +817,9 @@ { /* discard characters */ } for (i=0; ihook); - /* We just need to point ourselves at the .BRIK file */ + /* We need to point ourselves at the .BRIK file */ afniReopen(self); - if (data->facs_length==0) { + if (data->facs_length==0 && !data->flip_z) { /* no scaling required */ baseRead( self, info, offset, n, datatype_out, obuf ); } else { - /* scaling is required. We will fiendishly do the scaling - * in place. obuf is guaranteed to be long enough for the whole - * output string, and by previous design we always scale to - * floats or doubles, never losing precision. + /* scaling and/or reordering is required. We will fiendishly do + * the scaling in place. obuf is guaranteed to be long enough for + * the whole output string, and by previous design we always scale + * to floats or doubles, never losing precision. */ - int img= (int)((offset-data->base_offset)/(data->blocksize_bytes)); - int i; - if (img*data->blocksize_bytes != offset - data->base_offset) - Abort("%s: afniRead: offset %lld is not on an image boundary!\n", + long img= (long)((offset-data->base_offset)/(data->blocksize_bytes)); + long slice= (long)((offset-(data->base_offset+img*data->blocksize_bytes)) + /(data->slicesize_bytes)); + long long reordered_offset; + long i; + if (img*data->blocksize_bytes + slice*data->slicesize_bytes + + data->base_offset != offset) + Abort("%s: afniRead: offset %lld is not on a slice boundary!\n", progname, offset); - if (n != data->blocksize) - Abort("%s: afniRead: tried to read a block of wrong length!\n", + if (n + slice*data->slicesize > data->blocksize) + Abort("%s: afniRead: tried to read across a block boundary!\n", progname); - if (kvGetInt(info,"handler_datatype_out")==MRI_FLOAT) { - float* fbuf= (float*)obuf; - switch (kvGetInt(info,"datatype_in")) { - case MRI_UNSIGNED_CHAR: - { - unsigned char* cbuf= (unsigned char*)obuf; - baseRead( self, info, offset, n, MRI_UNSIGNED_CHAR, obuf ); - for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*cbuf[i]; - } - break; - case MRI_SHORT: - { - short* sbuf= (short*)obuf; - baseRead( self, info, offset, n, MRI_SHORT, obuf ); - for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*sbuf[i]; - } - break; - case MRI_INT: - { - int* ibuf= (int*)obuf; - baseRead( self, info, offset, n, MRI_INT, obuf ); - for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*ibuf[i]; - } - break; - case MRI_FLOAT: - { - baseRead( self, info, offset, n, MRI_FLOAT, obuf ); - for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*fbuf[i]; - } - break; - case MRI_DOUBLE: - Abort("%s: afniRead: unexpectedly tried to scale double to float!\n", - progname); - break; - } + if (data->flip_z) + reordered_offset= + data->base_offset + img*data->blocksize_bytes + + (data->nslices-(slice+1))*data->slicesize_bytes; + else reordered_offset= offset; + if (data->facs_length==0) { + /* No scaling required */ + baseRead( self, info, reordered_offset, n, datatype_out, obuf ); } - else if (kvGetInt(info,"handler_datatype_out")==MRI_DOUBLE) { - double* dbuf= (double*)obuf; - switch (kvGetInt(info,"datatype_in")) { - case MRI_UNSIGNED_CHAR: - { - unsigned char* cbuf= (unsigned char*)obuf; - baseRead( self, info, offset, n, MRI_UNSIGNED_CHAR, obuf ); - for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*cbuf[i]; - } - break; - case MRI_SHORT: - { - short* sbuf= (short*)obuf; - baseRead( self, info, offset, n, MRI_SHORT, obuf ); - for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*sbuf[i]; - } - break; - case MRI_INT: - { - int* ibuf= (int*)obuf; - baseRead( self, info, offset, n, MRI_INT, obuf ); - for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*ibuf[i]; - } - break; - case MRI_FLOAT: - { - float* fbuf= (float*)obuf; - baseRead( self, info, offset, n, MRI_FLOAT, obuf ); - for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*fbuf[i]; + else { + if (kvGetInt(info,"handler_datatype_out")==MRI_FLOAT) { + float* fbuf= (float*)obuf; + switch (kvGetInt(info,"datatype_in")) { + case MRI_UNSIGNED_CHAR: + { + unsigned char* cbuf= (unsigned char*)obuf; + baseRead( self, info, reordered_offset, n, MRI_UNSIGNED_CHAR, obuf ); + for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*cbuf[i]; + } + break; + case MRI_SHORT: + { + short* sbuf= (short*)obuf; + baseRead( self, info, reordered_offset, n, MRI_SHORT, obuf ); + for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*sbuf[i]; + } + break; + case MRI_INT: + { + int* ibuf= (int*)obuf; + baseRead( self, info, reordered_offset, n, MRI_INT, obuf ); + for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*ibuf[i]; + } + break; + case MRI_FLOAT: + { + baseRead( self, info, reordered_offset, n, MRI_FLOAT, obuf ); + for (i=n-1; i>=0; i--) fbuf[i]= data->float_facs[img]*fbuf[i]; + } + break; + case MRI_DOUBLE: + Abort("%s: afniRead: unexpectedly tried to scale double to float!\n", + progname); + break; } - break; - case MRI_DOUBLE: - { - baseRead( self, info, offset, n, MRI_FLOAT, obuf ); - for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*dbuf[i]; + } + else if (kvGetInt(info,"handler_datatype_out")==MRI_DOUBLE) { + double* dbuf= (double*)obuf; + switch (kvGetInt(info,"datatype_in")) { + case MRI_UNSIGNED_CHAR: + { + unsigned char* cbuf= (unsigned char*)obuf; + baseRead( self, info, reordered_offset, n, MRI_UNSIGNED_CHAR, obuf ); + for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*cbuf[i]; + } + break; + case MRI_SHORT: + { + short* sbuf= (short*)obuf; + baseRead( self, info, reordered_offset, n, MRI_SHORT, obuf ); + for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*sbuf[i]; + } + break; + case MRI_INT: + { + int* ibuf= (int*)obuf; + baseRead( self, info, reordered_offset, n, MRI_INT, obuf ); + for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*ibuf[i]; + } + break; + case MRI_FLOAT: + { + float* fbuf= (float*)obuf; + baseRead( self, info, reordered_offset, n, MRI_FLOAT, obuf ); + for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*fbuf[i]; + } + break; + case MRI_DOUBLE: + { + baseRead( self, info, reordered_offset, n, MRI_FLOAT, obuf ); + for (i=n-1; i>=0; i--) dbuf[i]= data->float_facs[img]*dbuf[i]; + } + break; } - break; } + else Abort("%s: unexpected scaling target %s!\n", + progname, typename[kvGetInt(info,"handler_datatype_out")]); } - else Abort("%s: unexpected scaling target %s!\n", - progname, typename[kvGetInt(info,"handler_datatype_out")]); } } @@ -855,7 +1039,12 @@ data->facs_length= 0; data->float_facs= NULL; data->blocksize= 1; + data->blocksize_bytes= 1; + data->slicesize= 1; + data->slicesize_bytes= 1; + data->nslices= 1; data->base_offset= 0; + data->flip_z= 0; result->typeName= strdup( "AFNI" ); result->processHeader= processHeader; Index: src/reader/dicom_reader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/dicom_reader.c,v retrieving revision 1.13 retrieving revision 1.14 diff -a -u -r1.13 -r1.14 --- src/reader/dicom_reader.c 30 Jul 2003 22:56:11 -0000 1.13 +++ src/reader/dicom_reader.c 12 Mar 2004 00:47:15 -0000 1.14 @@ -60,7 +60,7 @@ /* DICOM header files */ #include "dicom_dict.h" -static char rcsid[] = "$Id: dicom_reader.c,v 1.13 2003/07/30 22:56:11 welling Exp $"; +static char rcsid[] = "$Id: dicom_reader.c,v 1.14 2004/03/12 00:47:15 welling Exp $"; /* Add useful things to the filehandler hook */ typedef struct dicom_data_struct { @@ -1095,6 +1095,11 @@ } kvDefString(defs,"voxel_z","Z voxel size including gap (mm)"); kvDefString(info,"dimstr","xyz"); + /* image space, so no row flipping! */ + kvDefBoolean(info,"rowflip",0); + kvDefString(info,"rowflip_pattern","none"); + kvDefString(defs,"rowflip","EPI row reversal needed"); + kvDefString(defs,"rowflip_pattern","EPI row reversal pattern"); kvDefBoolean(info,"big_endian_input",0); dz= 1; if (kvLookup(info,"dx_mosaic") && kvLookup(info,"dx")) { Index: src/reader/lx_image_reader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/lx_image_reader.c,v retrieving revision 1.11 retrieving revision 1.13 diff -a -u -r1.11 -r1.13 --- src/reader/lx_image_reader.c 6 Nov 2003 17:59:01 -0000 1.11 +++ src/reader/lx_image_reader.c 12 Mar 2004 00:47:15 -0000 1.13 @@ -54,7 +54,7 @@ #include "nr_sub.h" #include "rcn.h" -static char rcsid[] = "$Id: lx_image_reader.c,v 1.11 2003/11/06 17:59:01 welling Exp $"; +static char rcsid[] = "$Id: lx_image_reader.c,v 1.13 2004/03/12 00:47:15 welling Exp $"; #define FRZ_LXI_VALID_LOGO "IMGF" #define FRZ_LXI_VALID_LOGO_BACKWARDS "FGMI" @@ -160,6 +160,11 @@ kvDefLong(info,"start_offset",BRdInt32(hdr+FRZ_LXI_SKIP_OFF)); kvDefString(info,"dimstr","xyz"); + /* image space, so no row flipping! */ + kvDefBoolean(info,"rowflip",0); + kvDefString(info,"rowflip_pattern","none"); + kvDefString(defs,"rowflip","EPI row reversal needed"); + kvDefString(defs,"rowflip_pattern","EPI row reversal pattern"); kvDefInt(info,"dx",xdim); kvDefInt(info,"dy",BRdInt32(hdr+FRZ_LXI_YDIM_OFF)); kvDefInt(info,"dz",1); @@ -220,6 +225,9 @@ tlc[0] *= -1.0; trc[0] *= -1.0; brc[0] *= -1.0; + tlc[2] *= -1.0; + trc[2] *= -1.0; + brc[2] *= -1.0; subtractVec3( edge_lr, trc, tlc ); subtractVec3( edge_bt, trc, brc ); Index: src/reader/lx_reader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/lx_reader.c,v retrieving revision 1.24 retrieving revision 1.26 diff -a -u -r1.24 -r1.26 --- src/reader/lx_reader.c 4 Nov 2003 22:24:35 -0000 1.24 +++ src/reader/lx_reader.c 13 Apr 2004 19:34:52 -0000 1.26 @@ -85,7 +85,7 @@ #define ADD_VSUFFIX(x) x ## _cnv4 #endif -static char rcsid[] = "$Id: lx_reader.c,v 1.24 2003/11/04 22:24:35 welling Exp $"; +static char rcsid[] = "$Id: lx_reader.c,v 1.26 2004/04/13 19:34:52 welling Exp $"; /* We actually seem to have some floating point precision issues in * distinguishing the rdbm header revision numbers. @@ -109,15 +109,22 @@ double slice_tlc[3]; double slice_brc[3]; double slice_trc[3]; + double slice_blc[3]; + double slice_ctr[3]; + double tlf[3]; + double trf[3]; + double tlb[3]; + double trb[3]; double blf[3]; double brf[3]; double blb[3]; - double tlf[3]; + double brb[3]; double delta[3]; double x_norm[3]; double y_norm[3]; double z_norm[3]; - double scale; + double xscale; + double yscale; /* This routine will probably have to be updated as we learn more * about their notion of coordinate systems. @@ -126,24 +133,27 @@ getVec3(info,"slice_tlc",slice_tlc); getVec3(info,"slice_trc",slice_trc); getVec3(info,"slice_brc",slice_brc); + getVec3(info,"slice_ctr",slice_ctr); + + subtractVec3(delta,slice_ctr,slice_trc); + xplusbyVec3(slice_blc,slice_trc,delta,2.0); + defVec3(info,"slice_blc",slice_blc); subtractVec3(delta,slice_trc,slice_tlc); - scale= normVec3(delta); - if (scale==0.0) { + xscale= normVec3(delta); + if (xscale==0.0) { Warning(1,"%s: lx_reader: nonsense slice corner information!\n",progname); return; } - kvDefDouble(info, "voxel_x", scale/((double)kvGetInt(info,"dx") - 1.0)); - multVec3( x_norm, delta, 1.0/scale ); + multVec3( x_norm, delta, 1.0/xscale ); - subtractVec3(delta,slice_brc,slice_trc); - scale= normVec3(delta); - if (scale==0.0) { + subtractVec3(delta,slice_trc,slice_brc); + yscale= normVec3(delta); + if (yscale==0.0) { Warning(1,"%s: lx_reader: nonsense slice corner information!\n",progname); return; } - kvDefDouble(info, "voxel_y", scale/((double)kvGetInt(info,"dx") - 1.0)); - multVec3( y_norm, delta, 1.0/scale ); + multVec3( y_norm, delta, 1.0/yscale ); crossVec3( z_norm, x_norm, y_norm ); @@ -153,16 +163,38 @@ y_norm[0], y_norm[1], y_norm[2], z_norm[0], z_norm[1], z_norm[2]); #endif + defVec3(info,"slice_norm",z_norm); copyVec3(blb, slice_tlc); - xplusbyVec3(blf, blb, y_norm, - -(kvGetInt(info,"dy")-1)*kvGetDouble(info,"voxel_y")); - xplusbyVec3(brf, blf, x_norm, - (kvGetInt(info,"dx")-1)*kvGetDouble(info,"voxel_x")); + copyVec3(brb, slice_trc); + copyVec3(brf, slice_brc); + copyVec3(blf, slice_blc); + if ( kvLookup(info,"dx") != NULL && kvGetInt(info,"dx")!=0 ) { + if (!kvLookup(info,"voxel_x")) + kvDefDouble(info, "voxel_x", xscale/((double)kvGetInt(info,"dx") - 1.0)); + } + if ( kvLookup(info,"dy") != NULL && kvGetInt(info,"dy")!=0 ) { + if (!kvLookup(info,"voxel_y")) + kvDefDouble(info, "voxel_y", yscale/((double)kvGetInt(info,"dy") - 1.0)); + } + + /* voxel_z was defined directly from the slice info in the header */ + /* nslices is dz */ xplusbyVec3(tlf, blf, z_norm, - (kvGetInt(info,"dz")-1)*kvGetDouble(info,"voxel_z")); + (kvGetInt(info,"nslices")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(trf, brf, z_norm, + (kvGetInt(info,"nslices")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(tlb, blb, z_norm, + (kvGetInt(info,"nslices")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(trb, brb, z_norm, + (kvGetInt(info,"nslices")-1)*kvGetDouble(info,"voxel_z")); + + defVec3(info, "trf", trf); + defVec3(info, "trb", trb); + defVec3(info, "tlb", tlb); defVec3(info, "tlf", tlf); defVec3(info, "brf", brf); + defVec3(info, "brb", brb); defVec3(info, "blb", blb); defVec3(info, "blf", blf); @@ -187,6 +219,11 @@ int ierror= 0; int exnum= 0; int num_frame_shifts= 0; + double slice_tlc[3]; + double slice_trc[3]; + double slice_blc[3]; + double slice_brc[3]; + double slice_ctr[3]; /* Definitions */ defs= kvGetHash(info,"definitions"); @@ -388,44 +425,56 @@ kvDefInt(info,"index_transpose", BRdInt16(rdbhead+FRZ_RDBHEAD_RDB_HDR_TRANSPOSE_OFF)); - kvDefDouble(info,"slice_tlc.0", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_R_OFF)); + slice_tlc[0]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_R_OFF); + slice_tlc[1]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_A_OFF); + slice_tlc[2]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_S_OFF); + slice_trc[0]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_R_OFF); + slice_trc[1]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_A_OFF); + slice_trc[2]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_S_OFF); + slice_brc[0]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_R_OFF); + slice_brc[1]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_A_OFF); + slice_brc[2]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_S_OFF); + slice_ctr[0]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_R_OFF); + slice_ctr[1]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_A_OFF); + slice_ctr[2]= BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_S_OFF); + + /* The LX internal coordinate system is oriented differently from + * Fiasco's. LX has X running right-left in the images and Z + * decreasing toward the feet; Fiasco has X left-right and Z + * increasing toward the feet. + */ + slice_tlc[0] *= -1.0; + slice_trc[0] *= -1.0; + slice_brc[0] *= -1.0; + slice_ctr[0] *= -1.0; + slice_tlc[2] *= -1.0; + slice_trc[2] *= -1.0; + slice_brc[2] *= -1.0; + slice_ctr[2] *= -1.0; + + defVec3(info,"slice_tlc",slice_tlc); + defVec3(info,"slice_trc",slice_trc); + defVec3(info,"slice_brc",slice_brc); + defVec3(info,"slice_ctr",slice_ctr); + kvDefString(defs,"slice_tlc.0","slice 0 top left corner R (RAS coords)"); - kvDefDouble(info,"slice_tlc.1", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_A_OFF)); kvDefString(defs,"slice_tlc.1","slice 0 top left corner A (RAS coords)"); - kvDefDouble(info,"slice_tlc.2", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TLHC_S_OFF)); kvDefString(defs,"slice_tlc.2","slice 0 top left corner S (RAS coords)"); - kvDefDouble(info,"slice_trc.0", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_R_OFF)); kvDefString(defs,"slice_trc.0","slice 0 top right corner R (RAS coords)"); - kvDefDouble(info,"slice_trc.1", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_A_OFF)); kvDefString(defs,"slice_trc.1","slice 0 top right corner A (RAS coords)"); - kvDefDouble(info,"slice_trc.2", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_TRHC_S_OFF)); kvDefString(defs,"slice_trc.2","slice 0 top right corner S (RAS coords)"); - kvDefDouble(info,"slice_brc.0", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_R_OFF)); kvDefString(defs,"slice_brc.0","slice 0 bottom right corner R (RAS coords)"); - kvDefDouble(info,"slice_brc.1", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_A_OFF)); kvDefString(defs,"slice_brc.1","slice 0 bottom right corner A (RAS coords)"); - kvDefDouble(info,"slice_brc.2", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_BRHC_S_OFF)); kvDefString(defs,"slice_brc.2","slice 0 bottom right corner S (RAS coords)"); - kvDefDouble(info,"slice_ctr.0", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_R_OFF)); + kvDefString(defs,"slice_blc.0","slice 0 bottom left corner R (RAS coords)"); + kvDefString(defs,"slice_blc.1","slice 0 bottom left corner A (RAS coords)"); + kvDefString(defs,"slice_blc.2","slice 0 bottom left corner S (RAS coords)"); + kvDefString(defs,"slice_ctr.0","slice 0 center R (RAS coords)"); - kvDefDouble(info,"slice_ctr.1", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_A_OFF)); kvDefString(defs,"slice_ctr.1","slice 0 center A (RAS coords)"); - kvDefDouble(info,"slice_ctr.2", - BRdFloat32(imagehead + FRZ_IMAGEHEAD_CTR_S_OFF)); kvDefString(defs,"slice_ctr.2","slice 0 center S (RAS coords)"); kvDefInt(info,"pt_size", @@ -439,8 +488,6 @@ kvDefInt(info,"bl_save",0); kvDefString(defs,"bl_save","1 for Genesis, 0 for LX"); - calcVolumeBounds(info); - /* The rest of the interpretation depends on the pulse sequence */ if (!strncmp(pulse_seq,"epi",3)) { /* Interpret as EPIBOLD */ @@ -499,6 +546,11 @@ ADD_VSUFFIX(scanSplxHeader)(info, rdbhead, acq_tab, examhead, serieshead, imagehead); } + + /* Now that we know as much about the scan as possible, calculate + * the bounds of the scan volume. + */ + calcVolumeBounds(info); /* If we did any frame shifting to find the header info, adjust the * starting offset appropriately. Index: src/reader/multi_reader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/multi_reader.c,v retrieving revision 1.21 retrieving revision 1.23 diff -a -u -r1.21 -r1.23 --- src/reader/multi_reader.c 6 Nov 2003 17:59:01 -0000 1.21 +++ src/reader/multi_reader.c 6 Apr 2004 20:59:00 -0000 1.23 @@ -47,7 +47,7 @@ #include "misc.h" #include "smartreader.h" -static char rcsid[] = "$Id: multi_reader.c,v 1.21 2003/11/06 17:59:01 welling Exp $"; +static char rcsid[] = "$Id: multi_reader.c,v 1.23 2004/04/06 20:59:00 welling Exp $"; /* Notes- * -we are not checking for a situation where two subfiles have the @@ -68,7 +68,7 @@ * the value below. Also, the corner coordinates must not differ by * more than this far in the slice plane. */ -#define STEP_SIZE_MARGIN 0.00001 +#define STEP_SIZE_MARGIN 0.00005 /* A bogus FileHandler that handles multiple files data types */ @@ -325,6 +325,9 @@ slist_totop(data->kids); *d1= slice_range; *d2= slist_count(data->kids) / *d1; + if (debug) + fprintf(stderr,"slice_range= %d; count %d; thus d2= %d\n", + slice_range,slist_count(data->kids),*d2); if (slist_count(data->kids) == *d1 * *d2) { if (*d2 != 1) return 1; else return 0; @@ -362,7 +365,7 @@ if (scale!=0.0) multVec3( x_norm, delta, 1.0/scale ); else return 0; - subtractVec3(delta,brc,trc); + subtractVec3(delta,trc,brc); scale= normVec3(delta); if (scale!=0.0) multVec3( y_norm, delta, 1.0/scale ); else return 0; @@ -388,6 +391,7 @@ double y_norm[3]; double z_norm[3]; double delta[3]; + double delta_norm[3]; calcSliceOrientation( info, tlc, x_norm, y_norm, z_norm ); if (dotVec3(x_norm, x_norm_in) < ALIGNED_DOT_LIMIT) return 0; @@ -395,14 +399,33 @@ if (dotVec3(z_norm, z_norm_in) < ALIGNED_DOT_LIMIT) return 0; subtractVec3(delta, tlc, base_tlc); - if (dotVec3(delta,x_norm)>STEP_SIZE_MARGIN - || dotVec3(delta,y_norm)>STEP_SIZE_MARGIN) { + *disp= dotVec3(delta, z_norm); + copyVec3(delta_norm,delta); + normalizeVec3(delta_norm); + if (debug) { + static int checkNum= 1; /* offset by 1 to account for 1st slice */ + fprintf(stderr,"%d: Norm dot products are %f and %f on disp %f\n", + checkNum++,dotVec3(delta_norm,x_norm),dotVec3(delta_norm,y_norm), + *disp); + fprintf(stderr," delta_norm: %f %f %f\n",delta_norm[0],delta_norm[1], + delta_norm[2]); + fprintf(stderr," x_norm: %f %f %f\n",x_norm[0],x_norm[1],x_norm[2]); + fprintf(stderr," y_norm: %f %f %f\n",y_norm[0],y_norm[1],y_norm[2]); + fprintf(stderr," z_norm: %f %f %f\n",z_norm[0],z_norm[1],z_norm[2]); + fprintf(stderr," tlc: %f %f %f\n",tlc[0],tlc[1],tlc[2]); + fprintf(stderr," base_tlc: %f %f %f\n",base_tlc[0],base_tlc[1], + base_tlc[2]); + } + if (*disp < STEP_SIZE_MARGIN ) { + /* We've come back around to another copy of the first slice */ + return 1; + } + if (dotVec3(delta_norm,x_norm)>STEP_SIZE_MARGIN + || dotVec3(delta_norm,y_norm)>STEP_SIZE_MARGIN) { if (verbose_flg) fprintf(stderr,"Slice stack is skewed.\n"); return 0; } - *disp= dotVec3(delta, z_norm); - return 1; } @@ -423,9 +446,13 @@ double min_disp; double disp_ratio; double vol_tlf[3]; + double vol_tlb[3]; + double vol_trf[3]; + double vol_trb[3]; + double vol_blf[3]; double vol_blb[3]; double vol_brf[3]; - double vol_blf[3]; + double vol_brb[3]; double voxel_x; double voxel_y; @@ -525,14 +552,26 @@ copyVec3(vol_blb, base_tlc); xplusbyVec3(vol_blf, vol_blb, y_norm, -(kvGetInt(info,"dy")-1)*kvGetDouble(info,"voxel_y")); + xplusbyVec3(vol_brb, vol_blb, x_norm, + (kvGetInt(info,"dx")-1)*kvGetDouble(info,"voxel_x")); xplusbyVec3(vol_brf, vol_blf, x_norm, (kvGetInt(info,"dx")-1)*kvGetDouble(info,"voxel_x")); xplusbyVec3(vol_tlf, vol_blf, z_norm, (kvGetInt(info,"dz")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(vol_tlb, vol_blb, z_norm, + (kvGetInt(info,"dz")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(vol_trf, vol_brf, z_norm, + (kvGetInt(info,"dz")-1)*kvGetDouble(info,"voxel_z")); + xplusbyVec3(vol_trb, vol_brb, z_norm, + (kvGetInt(info,"dz")-1)*kvGetDouble(info,"voxel_z")); defVec3(info, "tlf", vol_tlf); + defVec3(info, "trf", vol_trf); + defVec3(info, "tlb", vol_tlb); + defVec3(info, "trb", vol_trb); + defVec3(info, "blf", vol_blf); defVec3(info, "brf", vol_brf); defVec3(info, "blb", vol_blb); - defVec3(info, "blf", vol_blf); + defVec3(info, "brb", vol_brb); } else { /* Reverse the order of slices within each volume */ Index: src/reader/pghtoafni.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/pghtoafni.c,v retrieving revision 1.6 retrieving revision 1.14 diff -a -u -r1.6 -r1.14 --- src/reader/pghtoafni.c 2 Oct 2003 01:12:12 -0000 1.6 +++ src/reader/pghtoafni.c 5 May 2004 21:35:01 -0000 1.14 @@ -28,7 +28,6 @@ ************************************************************/ /* Notes- - -Keep missing info? (involves changing afni_reader as well) */ #include @@ -52,11 +51,11 @@ #include "smartreader.h" #include "afni_defs.h" -static char rcsid[] = "$Id: pghtoafni.c,v 1.6 2003/10/02 01:12:12 welling Exp $"; +static char rcsid[] = "$Id: pghtoafni.c,v 1.14 2004/05/05 21:35:01 welling Exp $"; #define SINGLE_QUOTE 0x27 -/* The following tag name translations when internal tags are written +/* The following tag name translations occur when internal tags are written * to the AFNI header file. Other name translations may occur as well; * see translateNameToAfni() below. Mapping a name to the empty string * will guarantee that it will not be written; specifying a non-empty @@ -98,6 +97,10 @@ {"fov.z","pghmri.fov.z"}, {"time","pghmri.time"}, {"TE","pghmri.TE"}, + {"missing","pghmri.missing"}, + {"missing.dimstr","pghmri.missing.dimensions"}, + {"brick_max",""}, /* If set, these are stored in BRICK_STATS */ + {"brick_min",""}, /* If set, these are stored in BRICK_STATS */ {NULL, NULL} /* ends list */ }; @@ -293,8 +296,12 @@ int i; fputc(SINGLE_QUOTE,f); for (i=0; i!\n", progname, type1); - return result; + /* Maybe the command line specified a change to one feature */ + if (func_known) { + if (is_func) { + switch (oldtype) { + case THREEDIM_HEAD_ANAT: + case THREEDIM_HEAD_FUNC: + return THREEDIM_HEAD_FUNC; + break; + case THREEDIM_GEN_ANAT: + case THREEDIM_GEN_FUNC: + return THREEDIM_GEN_FUNC; + break; + } + } + else { + switch (oldtype) { + case THREEDIM_HEAD_ANAT: + case THREEDIM_HEAD_FUNC: + return THREEDIM_HEAD_ANAT; + break; + case THREEDIM_GEN_ANAT: + case THREEDIM_GEN_FUNC: + return THREEDIM_GEN_ANAT; + break; + } + } + } + else if (head_known) { + if (is_head) { + switch (oldtype) { + case THREEDIM_HEAD_ANAT: + case THREEDIM_GEN_ANAT: + return THREEDIM_HEAD_ANAT; + break; + case THREEDIM_HEAD_FUNC: + case THREEDIM_GEN_FUNC: + return THREEDIM_HEAD_FUNC; + break; + } + } + else { + switch (oldtype) { + case THREEDIM_HEAD_ANAT: + case THREEDIM_GEN_ANAT: + return THREEDIM_GEN_ANAT; + break; + case THREEDIM_HEAD_FUNC: + case THREEDIM_GEN_FUNC: + return THREEDIM_GEN_FUNC; + break; + } + } + } + else return oldtype; } } @@ -468,7 +528,9 @@ if (!func_known && kvLookup(info,"cl_input_file_name")) { char* fname= kvGetString(info,"cl_input_file_name"); if (!strncasecmp(fname,"mean",strlen("mean")) - || !strncasecmp(fname,"grandmean",strlen("grandmean"))) { + || !strncasecmp(fname,"grandmean",strlen("grandmean")) + || !strncasecmp(fname,"struct",strlen("struct")) + || !strncasecmp(fname,"strct",strlen("strct"))) { is_func= 0; } else { @@ -549,9 +611,18 @@ if (kvLookup(info,"afni.SCENE_DATA.1")) { const char* s= kvGetString(info,"afni.SCENE_DATA.1"); int result= stringTableLookup(s, func_type_names); - if (result<0) - Abort("%s: input file has unknown AFNI coord sys string <%s>!\n", - progname,s); + if (result<0) { + result= stringTableLookup(s, anat_type_names); + if (result>=0) { + Warning(1,"%s: Dataset declared functional, used to be anatomical!\n", + progname); + if (is_bucket) return FUNC_BUCK_TYPE; + else return FUNC_FIM_TYPE; + } + else + Abort("%s: input file has unknown AFNI coord sys string <%s>!\n", + progname,s); + } } else { if (is_bucket) return FUNC_BUCK_TYPE; @@ -616,6 +687,48 @@ v += TS; } } + else if (!strcasecmp(s,"reversed_even/odd")) { + double v= 0.0; + int maxEven; + int maxOdd; + if (dz % 2) { /* odd number of slices */ + maxEven= dz-1; + maxOdd= dz-2; + } + else { /* even number of slices */ + maxEven= dz-2; + maxOdd= dz-1; + } + for (i=maxEven; i>=0; i -= 2) { + vals[i]= v; + v += TS; + } + for (i=maxOdd; i>=0; i -= 2) { + vals[i]= v; + v += TS; + } + } + else if (!strcasecmp(s,"reversed_odd/even")) { + double v= 0.0; + int maxEven; + int maxOdd; + if (dz % 2) { /* odd number of slices */ + maxEven= dz-1; + maxOdd= dz-2; + } + else { /* even number of slices */ + maxEven= dz-2; + maxOdd= dz-1; + } + for (i=maxOdd; i>=0; i -= 2) { + vals[i]= v; + v += TS; + } + for (i=maxEven; i>=0; i -= 2) { + vals[i]= v; + v += TS; + } + } else Abort("%s: input file has unknown reorder pattern <%s>!\n", progname, s); } @@ -733,7 +846,7 @@ int afniType= pickAfniType(info); int afniViewType= pickAfniViewType(info); int afniFuncType= pickAfniFuncType(info, afniType); - double tlf[3]; + double blb[3]; /* Only a limited range of dimension strings are possible here, * due to checking when we made sure this file was translatable. @@ -785,13 +898,13 @@ && kvLookup(info,"voxel_z")) writeDoubleTag(info,afniHead, "DELTA", 3, kvGetDouble(info,"voxel_x"), - -kvGetDouble(info,"voxel_y"), - kvGetDouble(info,"voxel_z")); + kvGetDouble(info,"voxel_y"), + -kvGetDouble(info,"voxel_z")); else Abort("%s: input file does not contain required voxel size info!\n", progname); - if (getVec3(info,"tlf",tlf)) { - writeDoubleTag(info, afniHead, "ORIGIN", 3, tlf[0], tlf[1], tlf[2]); + if (getVec3(info,"blb",blb)) { + writeDoubleTag(info, afniHead, "ORIGIN", 3, blb[0], -blb[1], -blb[2]); } else { /* AFNI considers the origin to be the center of the top left front @@ -800,8 +913,8 @@ */ writeDoubleTag(info, afniHead, "ORIGIN", 3, -0.5*(dx-1)*kvGetDouble(info,"voxel_x"), - 0.5*(dx-1)*kvGetDouble(info,"voxel_y"), - -0.5*(dx-1)*kvGetDouble(info,"voxel_z")); + -0.5*(dy-1)*kvGetDouble(info,"voxel_y"), + 0.5*(dz-1)*kvGetDouble(info,"voxel_z")); } if (dt>1) { @@ -810,9 +923,19 @@ dt, dz, UNITS_MSEC_TYPE); writeDoubleTag(info, afniHead, "TAXIS_FLOATS", 5, 0.0, TR/1000.0, dt*TR/1000.0, - tlf[2], kvGetDouble(info,"voxel_z")); + -blb[2], -kvGetDouble(info,"voxel_z")); calcSliceTimeOffsets(info, afniHead); } + else { + /* At the moment, we only keep the min and max if there is only a + * single brick. AFNI programs will regenerate it if necessary. + */ + if (kvLookup(info,"brick_min") && kvLookup(info,"brick_max")) { + writeDoubleTag(info, afniHead, "BRICK_STATS", 2, + kvGetDouble(info,"brick_min"), + kvGetDouble(info,"brick_max")); + } + } if (kvLookup(info,"date")) { if (kvLookup(info,"time")) { @@ -830,6 +953,39 @@ (bio_big_endian_machine ? "MSB_FIRST" : "LSB_FIRST")); } +static void exportDependentRequiredTags( KVHash* info, FILE* afniHead ) +{ + /* Some AFNI tags are required if other tags are present. This + * routine is in charge of checking and fulfilling certain left-over + * requirements of that sort. + */ + KVHash* defs= kvGetHash(info,"definitions"); + KVHash* extNames= kvGetHash(info,"external_names"); + KVHash* wroteThese= kvGetHash(info,"wrote_these_already"); + int afniType= pickAfniType(info); + int afniViewType= pickAfniViewType(info); + int afniFuncType= pickAfniFuncType(info, afniType); + + /* Fake up an empty set of markers fields */ + if ( afniType==THREEDIM_HEAD_ANAT && afniViewType==VIEW_ORIGINAL_TYPE + && (!kvLookup(info,"dt") || kvGetInt(info,"dt")==1)) { + if (!kvLookup(wroteThese,"MARKS_XYZ")) + writeDoubleTag(info, afniHead, "MARKS_XYZ", 30, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0, + -999999.0, -999999.0, -999999.0, -999999.0, -999999.0); + if (!kvLookup(wroteThese,"MARKS_FLAGS")) + writeIntTag(info, afniHead, "MARKS_FLAGS", 8, 1, 1, 0, 0, 0, 0, 0, 0); + if (!kvLookup(wroteThese,"MARKS_LAB")) + writeOneTag(info, afniHead, KV_STRING,"MARKS_LAB",200, + "AC superior edge\0\0\0\0AC posterior margin\0PC inferior edge\0\0\0\0First mid-sag pt\0\0\0\0Another mid-sag pt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); + } + +} + static void transcribeSimplePair( KVHash* info, FILE* afniHead, const char* afniKey, const KVPair* p ) { @@ -1267,13 +1423,29 @@ chunkName, outName); if (outName && strlen(outName)>0) { - int nItems= kvGetInt(subInfo,"da"); - int type= kvGetInt(subInfo,"handler_datatype_out"); + int nItems; + int type; + if (!strcmp(chunkName,"missing")) { + if (strcmp(kvGetString(subInfo,"dimstr"), "zt") + && strcmp(kvGetString(subInfo,"dimstr"), "tz")) { + Abort("%s: internal error: expected missing chunk to have dimstr 'zt' or 'tz'!\n", + progname); - /* Reality check; get size and type */ - if (strcmp(kvGetString(subInfo,"dimstr"), "a")) - Abort("%s: internal error: expected chunk <%s> to have dimstr 'a'!\n", - progname, chunkName); + } + writeStringTag(info, afniHead, + translateNameToAfni(info,"missing.dimstr"), + kvGetString(subInfo,"dimstr")); + nItems= kvGetInt(subInfo,"dz")*kvGetInt(subInfo,"dt"); + type= MRI_INT; + } + else { + /* Reality check; get size and type */ + if (strcmp(kvGetString(subInfo,"dimstr"), "a")) + Abort("%s: internal error: expected chunk <%s> to have dimstr 'a'!\n", + progname, chunkName); + nItems= kvGetInt(subInfo,"da"); + type= kvGetInt(subInfo,"handler_datatype_out"); + } switch (type) { case MRI_INT: @@ -1290,7 +1462,8 @@ { double* vals; if (!(vals= (double*)malloc(nItems*sizeof(double)))) - Abort("%s: unable to allocate %d bytes!\n",nItems*sizeof(double)); + Abort("%s: unable to allocate %d bytes!\n", + nItems*sizeof(double)); FH_READ( handler, subInfo, 0, nItems, MRI_DOUBLE, vals ); writeOneTag(info, afniHead, KV_DOUBLE, outName, nItems, vals); free(vals); @@ -1386,6 +1559,8 @@ exportOtherChunks(info, chunkList, afniHead); + exportDependentRequiredTags(info, afniHead); + kvDestroy(pendingGroups); kvDestroy(pendingGroupTypes); kvDestroy(pendingGroupInternalNames); @@ -1467,6 +1642,49 @@ return result; } +#define UPDATE_BOUNDS( type ) \ + { \ + type* here= (type*)buf; \ + type* end= here+countThisBlock; \ + if (!(boundsSet)) { \ + *min= *max= (double)*here; \ + *boundsSet= 1; \ + here++; \ + countThisBlock--; \ + } \ + while (here*max) *max=(double)*here; \ + here++; \ + } \ + } + +static void updateBounds(void* buf, long countThisBlock, int type, + double* min, double* max, int* boundsSet ) +{ + switch (type) { + case MRI_UNSIGNED_CHAR: + UPDATE_BOUNDS(unsigned char); + break; + case MRI_SHORT: + UPDATE_BOUNDS(short); + break; + case MRI_INT: + UPDATE_BOUNDS(int); + break; + case MRI_FLOAT: + UPDATE_BOUNDS(float); + break; + case MRI_DOUBLE: + UPDATE_BOUNDS(double); + break; + default: + Abort("%s: Internal error: unknown datatype %d\n",progname,type); + } +} + +#undef UPDATE_BOUNDS + static void transfer( FileHandler* handler, KVHash* info, FILE* afniBrik ) { long long totalCount; @@ -1481,6 +1699,10 @@ int dz= 1; int dt= 1; int db= 1; + double min; + double max; + int maintainBoundsFlag= 0; + int boundsSet= 0; if (kvLookup(info,"dv")) dv= kvGetInt(info,"dv"); if (kvLookup(info,"dx")) dx= kvGetInt(info,"dx"); @@ -1488,6 +1710,8 @@ if (kvLookup(info,"dz")) dz= kvGetInt(info,"dz"); if (kvLookup(info,"dt")) dt= kvGetInt(info,"dt"); if (kvLookup(info,"db")) db= kvGetInt(info,"db"); + + if (dt==1) maintainBoundsFlag= 1; totalCount= dv*dx*dy*dz*dt*db; itype= kvGetInt(info,"handler_datatype_out"); @@ -1503,6 +1727,8 @@ FH_READ( handler, info, offset*typesize[itype], countThisBlock, otype, buf ); + if (maintainBoundsFlag) + updateBounds(buf, countThisBlock, otype, &min, &max, &boundsSet ); if (fwrite(buf, typesize[otype], (size_t) countThisBlock, afniBrik) != (size_t)countThisBlock) { perror("Error writing BRIK"); @@ -1512,6 +1738,11 @@ totalCount -= countThisBlock; offset += countThisBlock; } + + if (maintainBoundsFlag) { + kvDefDouble(info,"brick_max",max); + kvDefDouble(info,"brick_min",min); + } } static void addCLToHistory( KVHash* info, int argc, char* argv[] ) @@ -1666,9 +1897,9 @@ slist_totop(processedChunkList); } - exportTags(goodInfo, processedChunkList, afniHead); - transfer( fileHandler, goodInfo, afniBrik ); + + exportTags(goodInfo, processedChunkList, afniHead); /* Close output dataset */ closeOutputFiles(afniHead, afniBrik); Index: src/reader/smart_utils.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/smart_utils.c,v retrieving revision 1.3 retrieving revision 1.4 diff -a -u -r1.3 -r1.4 --- src/reader/smart_utils.c 1 Jul 2003 21:35:22 -0000 1.3 +++ src/reader/smart_utils.c 30 Apr 2004 23:49:26 -0000 1.4 @@ -51,7 +51,7 @@ #include "misc.h" #include "smartreader.h" -static char rcsid[] = "$Id: smart_utils.c,v 1.3 2003/07/01 21:35:22 welling Exp $"; +static char rcsid[] = "$Id: smart_utils.c,v 1.4 2004/04/30 23:49:26 welling Exp $"; int legitDimString( const char* str ) { @@ -186,12 +186,15 @@ Message("# Scan includes %d lines past Ky=0\n", kvGetInt(info,"overscan")); if (kvLookup(info,"voxel_x") && kvLookup(info,"voxel_y")) - Message("# Voxel X= %g mm, Y= %g mm\n", + Message("# Voxel X= %g mm, Y= %g mm", kvGetDouble(info,"voxel_x"), kvGetDouble(info,"voxel_y")); if (kvLookup(info,"slice_thickness") && kvLookup(info,"slice_gap")) - Message("# Slice thickness %g mm, gap %g mm\n", + Message("\n# Slice thickness %g mm, gap %g mm\n", kvGetDouble(info,"slice_thickness"), kvGetDouble(info,"slice_gap")); + else if (kvLookup(info,"voxel_z")) + Message(", Z= %g mm\n",kvGetDouble(info,"voxel_z")); + else Message("\n"); if (kvLookup(info,"date") && kvLookup(info,"time")) Message("# Scan acquired %s %s\n", kvGetString(info,"date"), kvGetString(info,"time")); Index: src/reader/smartreader.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/reader/smartreader.c,v retrieving revision 1.23 retrieving revision 1.25 diff -a -u -r1.23 -r1.25 --- src/reader/smartreader.c 26 Jun 2003 22:12:42 -0000 1.23 +++ src/reader/smartreader.c 19 Feb 2004 02:08:04 -0000 1.25 @@ -76,7 +76,7 @@ #include "misc.h" #include "smartreader.h" -static char rcsid[] = "$Id: smartreader.c,v 1.23 2003/06/26 22:12:42 welling Exp $"; +static char rcsid[] = "$Id: smartreader.c,v 1.25 2004/02/19 02:08:04 welling Exp $"; /* An array of data format handlers. Each of the factories in this * table must take a parameter list of the form: @@ -769,7 +769,7 @@ if (!consistency_check(chPair->info)) { Error("Consistency test failed!\n"); smart_dump(chPair->info); - Abort("%s: File format information is missing or inconstent; can't proceed!\n", + Abort("%s: File format information is missing or inconsistent; can't proceed!\n", progname); } @@ -829,7 +829,8 @@ /* Clean up */ slist_destroy(chunkStack,NULL); - fprintf(stderr,"# Data converted to standard format.\n"); + if (verbose_flg) + fprintf(stderr,"# Data converted to standard format.\n"); return 0; } Index: src/scripthelp/scripthelp_help.help =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/scripthelp/scripthelp_help.help,v retrieving revision 1.16 retrieving revision 1.27 diff -a -u -r1.16 -r1.27 --- src/scripthelp/scripthelp_help.help 24 Sep 2003 23:11:01 -0000 1.16 +++ src/scripthelp/scripthelp_help.help 4 May 2004 21:54:36 -0000 1.27 @@ -13,6 +13,524 @@ is available. You may be able to learn something by just reading the script itself. + +*afni_estireg3d.csh:Usage + + This script is used to perform 3-D motion estimation on a + set of images, producing setimates of the motion, but by + using AFNI's 3dvolreg instead of FIASCO's estireg3d. This + will cut down computation time but unfortunatly lose some + additional data computed by estireg3d. The input data must + be organized as vxyzt or xyzt. + + To run afnization use: + afnization.csh infile outfile + +*afni_estireg3d.csh:Infile + + infile + + Ex: Input_file + + The value of infile specifies the input dataset. This argument is required. + +*afni_estireg3d.csh:Outfile + + outfile + + Ex: Output_file + + The value of the outfile specifies the input dataset. This + arguement is required. + +*afni_estireg3d.csh:Details + + you can copy this over to you working directory, and edit the lines + calling 3dvolreg if you'd like. help for that can be found at: + http://afni.nimh.nih.gov/afni/doc/help/3dvolreg.html + Also when deciding to use afnization.csh you must do the following + steps: + replace epi.recon1.csh data/$F_MEANC_OUTPUT data/$F_RECON1_OUTPUT + with: epi.recon1.csh data/$F_PARTIALK_OUTPUT data/$F_RECON1_OUTPUT + + add afnization.csh data/$F_CLIP1_OUTPUT data/$F_RECON2_OUTPUT + + and then comment out estireg3d.csh, parsm3d.csh, epi.ireg3d.csh, + physio_correct.csh, mri_destroy_dataset data/$F_IREG_OUTPUT, + epi.recon2.csh, and mri_destroy_dataset data/$F_PHYS_OUTPUT + + + +*make_group_anat.csh:Usage + + make_group_anat.csh finds unweighted group means of several common + anatomical datasets: axial, inplane, stripped axial, and stripped + inplane scans. + + make_group_anat.csh [-m namemap] [-d key=value] subj1 subj2 ... + + -m namemap uses the specified mapfile (along with defaults in + F_MAP_PATH) to find subject directories. Multiple -m + options may be used. + -d key=value defines the given additional key-value pair + + or + + make_group_anat.csh -help [topic] + + All of the subjects must have been transformed into the same + coordinates, presumably Taliarach space. + +*make_group_anat.csh:Details + + This script uses map_name.py to find the anatomical datasets + associated with the file names Axial, StrippedAxial, Inplane, + and StrippedInplane (the association being defined by map_name.py's + name mapping tables). Unweighted means are constructed for all + of the subject datasets which are found; those not found are simply + excluded from the means. The output dataset names will be mean_Axial, + mean_StrippedAxial, mean_Inplane, and mean_StrippedInplane. These + files are created in the directory from which make_group_anat.csh + is run. If no subject has a dataset of a given type, no mean map + for that type will be produced. + +*convert_ifiles.py:Usage + + This script is run in a directory full of GE LX Image subdirectories + to produce Pgh MRI datasets from the images. + + convert_ifiles.py [-v] [-d] + + -v specifies verbose output + -d specifies debugging output + + or + + convert_ifiles.py -help [topic] + +*convert_ifiles.py:Details + + Suppose a scan session consists of 4 series: a setup series, an + axial structural, an inplane structural, and a functional series. + The directory containing the subdirectories with the GE image files + from this session would have a number of subdirectories with + names like 001, 002, 003, 004, 024, 044, etc., each of which would + contain some number of files with names like I.001, I.002, etc., + possibly up to I.999. The images of the functional scan might be + spread over multiple directories, for example 004, 024, 044, etc. + + When run in the directory containing these subdirectories, + convert_ifiles.py does the following: + + -renumber_ifiles.py is used to produce subdirectories containing + links to all the images for each particular series. + + -smartreader is used to generate Pgh MRI datasets for each + particular series. + + -Datasets which are identified as representing multiple times + (for example, functional datasets) have their first (guide) + volumes clipped off. + + The result is a collection of datasets named series1.mri, + series2.mri, etc., which can then be processed with Fiasco tools. + + \Note\ that if smartreader doesn't identify a long + collection of images as being a time series of volumes, manual + intervention may be required to convert the dataset from a huge + stack of slices to the correct time series. This can happen if + the slices in a stack are skewed or some are lost, for example. + +*renumber_ifiles.py:Usage + + This script is run in a directory full of GE LX Image subdirectories + to produce subdirectories of links, one subdirectory for each + series. + + renumber_ifiles.py [-v] [-d] + + -v specifies verbose output + -d specifies debugging output + + or + + renumber_ifiles.py -help [topic] + +*renumber_ifiles.py:Details + + Suppose a scan session consists of 4 series: a setup series, an + axial structural, an inplane structural, and a functional series. + The directory containing the subdirectories with the GE image files + from this session would have a number of subdirectories with + names like 001, 002, 003, 004, 024, 044, etc., each of which would + contain some number of files with names like I.001, I.002, etc., + possibly up to I.999. The images of the functional scan might be + spread over multiple directories, for example 004, 024, 044, etc. + + Running renumber_ifiles.py in the directory containing all of + these subdirectories would produce new subdirectories with the + names 'series1_links', 'series2_links', etc.. Each would contain + symbolic links with names like I.0001 (note the extra 0) linked to + the corresponding image in the appropriate original subdirectory. + These link subdirectories can then be used as input to smartreader + or other programs. + +*multi_runner.py:Usage + + This script is highly project-specific. It takes input specifying + particular datasets, uses customize_local.py to customize the Fiasco + input files for those datasets, and runs the appropriate FIASCO + command on the customized input files + + multi_runner.py [-v] [-d] [--src sourceDir] [--dest destDir] + [--tag tagString] [--db_uname dbUname] [--db_passwd dbPasswd] + [--infile inTbl] + + -v specifies verbose output + -d specifies debugging output + --src sourceDir specifies the directory name from which prototype + scripts are to be read (typically '.') + --dest destDir specifies the subdirectory name for the outputs. + The complete path to this subdirectory is project-dependent + --tag tagStr specifies an arbitrary tag by which this group of + runs will be known + --db_uname dbUname specifies a database username, for example + for mySQL + --db_passwd dbUname specifies a database username, for example + for mySQL + --infile inTbl specifies an input table with information + specifying runs, one run per line + + or + + multi_runner.py -help [topic] + +*multi_runner.py:Details + + If any required information is not provided on the command line, + the script will query the user. + + This script must be heavily customized for each new project. It + needs information about the directory structure in which datasets + reside, the table format of inTbl, and the database of information + describing individual subjects. It cooperates closely with + customize_local.py to customize the *.local.csh scripts. + +*make_P_P_plots.csh:Usage + + This script takes one or more Pmaps and generates P-P plots from + them. Multiple plots appear on a single Postscript page. + + make_P_P_plots.csh [-out file.ps] [-fitdenom n] Pmap1 [ Pmap2 [ Pmap3...] ] + + -out file.ps sets the name of the output file. The default + "plot_P_P.ps" + -fitdenom sets the fraction of the P range over which the + 'diagonal' line will be fit. For example, -fitdenom 10 + causes the line to be fit over 1/10 of the range. The + default is 2, fitting the line over the central half of the + data. + Pmap1, Pmap2, etc. are Pmap files, for example Pmap_1-2.mri . + Be sure to avoid overlayed Pmaps, like Pmap_1-2_q.mri + + or + + make_P_P_plots.csh -help [topic] + + +*coregister.py:Usage + + coregister.py implements automatic coregistration, given a + skull-stripped axial structural dataset, a skull-stripped in-plane + structural dataset, and a functional mean dataset. + + coregister.py [-v] [-d] [--oscript scriptName] + grandMean strippedInplane strippedStruct + + -v requests verbose output + -d requests debugging output + grandMean is a mean functional dataset, for example GrandMean + strippedInplane is a skull-stripped inplane structural dataset + strippedStruct is a skull-stripped axial structural dataset + + or + + coregister.py -help [topic] + +*coregister.py:Usage + + It uses coregister_struct_to_inplane.py and coregister_inplane.py. + I'm not sure what all else it's going to do. + +*coregister_struct_to_inplane.py:Usage + + coregister_struct_to_inplane.py is used to align axial structural + data to in-plane structural scan data. Its output is a generated + shell script which can be applied to any axial structural Pgh MRI + dataset to produce an inplane-aligned version. + + coregister_struct_to_inplane.py [-v] [-d] [--oscript scriptName] + strippedInplane strippedStruct + + -v requests verbose output + -d requests debugging output + --oscript scriptName specifies the name for the output shell + script which implements the alignment. The default name + is "apply_coreg_struct_to_inplane.gen_csh" + strippedInplane is a skull-stripped inplane structural dataset + strippedStruct is a skull-stripped axial structural dataset + + or + + coregister_struct_to_inplane.py -help [topic] + +*coregister_struct_to_inplane.py:Details + + The script uses the following steps to estimate the aligning + transformation: + + 1) Geometrical information stored in the input datasets is + used to calculate an initial, approximate aligning + rotation and translation. + 2) That transformation is used to produce a version of the + axial dataset in the inplane coordinate system. + 3) The inplane-aligned axial dataset is downsampled in the + Z direction, and the inplane structurals are resampled + in the X and Y directions. This produces a pair of datasets + at the same resolution and covering the same volume. + The Z extent of these datasets is actually larger than that + of the inplanes, to allow some empty space and to make a + Z dimension for which an efficient FFT is available. + 4) Using this pair of datasets, an aligning transformation is + estimated to correct for head motion between the acquisition + of the inplane and axial scans. + 5) The transformations from steps (1) and (4) are merged + analytically to produce a single transformation that does + the total alignment. + 6) A shell script is written which implements this transformation. + + The output shell script can be called as follows: + + apply_coreg_struct_to_inplane.gen_csh axialName outName resampName + + where apply_coreg_struct_to_inplane.gen_csh is the (default) script + name, axialName is an axial structural dataset, outName is the the + aligned version of the axial structurals, and resampName is + equivalent to outName but resampled to match the inplane structural + resolution. The outName and resampName datasets are translated and + rotated to have the same center and axis alignment as the inplane + structural dataset. The resampName dataset has the same corner + coordinates as the inplane structurals in the inplane coordinate + system; the outName dataset has corner coordinates appropriate to + its size in that coordinate system. + + Note that the output dataset coordinates produced are specified + in the (oblique) inplane coordinate system, and not in axial coordinates + (scanner coordinates). This means that, for example, the TLF and + TRB corners will have the same Z coordinate. + + Note that skull-stripping must be done with an outside package, for + example AFNI's 3dIntracranial. Typical commands to do so for an + inplane structural dataset called Inplane would be: + + pghtoafni -anat Inplane Inplane+orig + 3dIntracranial -anat Inplane+orig -prefix strippedInplane + smartreader -i strippedInplane+orig.HEAD -out strippedInplane + + Note also that only rotation and translation are used to do the + alignment, and that consequently the alignment estimate is limited + by the different distortions introduced by the imaging methods used + to create the input datasets. + +*coregister_inplane.py:Usage + + coregister_inplane.py is used to align functional data with in-plane + structural scan data. Its output is a generated shell script which + can be applied to any statistical Pgh MRI dataset to produce an + aligned version. + + coregister_inplane.py [-v] [-d] [--oscript scriptName] + GrandMean strippedInplane + + -v requests verbose output + -d requests debugging output + --oscript scriptName specifies the name for the output shell + script which implements the alignment. The default name + is "apply_coreg_inplane.gen_csh" + GrandMean is a functional mean dataset, typically GrandMean + strippedInplane is a skull-stripped inplane structural dataset + + or + + coregister_inplane.py -help [topic] + +*coregister_inplane.py:Details + + The script uses the following steps to estimate the aligning + transformation: + + 1) The stripped structural dataset is downsampled to the + functional resolution. + 2) 3D gradient magnitude volumes are calculated for the + functional and downsampled structural data. + 3) An aligning transformation (translation+rotation) is + estimated. + 4) The output shell script is generated. + + The output shell script can be called as follows: + + apply_coreg_inplane.gen_csh funcStat outName upsampName + + where apply_coreg_inplane.gen_csh is the (default) script name, + funcStat is a functional statistical dataset (for example Tmap_1-2), + and outName is the name of the shifted and rotated output dataset, + and upsampName is a dataset like outName but upsampled to the + inplane structural resolution. The outName and upsampName + datasets are translated and rotated to to location of the stripped + inplane structural dataset; the latter has the same voxel size and + corner coordinates as that dataset. + + Note that skull-stripping must be done with an outside package, for + example AFNI's 3dIntracranial. Typical commands to do so for an + inplane structural dataset called Inplane would be: + + pghtoafni -anat Inplane Inplane+orig + 3dIntracranial -anat Inplane+orig -prefix strippedInplane + smartreader -i strippedInplane+orig.HEAD -out strippedInplane + + Note also that only rotation and translation are used to do the + alignment, and that consequently the alignment estimate is limited + by the different distortions introduced by the imaging methods used + to create the input datasets. + +*pick_n_voxels.py:Usage + + pick_n_voxels.py takes as input a desired count of active voxels and + a Pmap or Tmap , and produces the cutoff P or T score for the requested count. + + pick_n_voxels.py [-v] [-d] [--twotails] [--mask maskDS] -T|-P|-F count mapDS + + -v requests verbose output + -d requests debugging output + --twotails includes both tails of the distribution in the count. + This is incompatible with -F + -T specifies that mapDS is a Tmap + -P specifies that mapDS is a Pmap + -F specifies that mapDS is an Fmap + --mask maskDS specifies that maskDS contains a mask for mapDS. + Only voxels within that map are counted. All voxel values + should be either 0 or 1. + count is the desired number of active voxels (an integer) + mapDS is the name of the Pgh MRI dataset containing the Tmap or Pmap + + or + + pick_n_voxels.py -help [topic] + +*pick_n_voxels.py:Details + + Without the --twotails or --mask options, this script simply sorts + the given voxel values and picks the lowest N. For Pmaps or Tmaps + sorting is done in ascending order; for Fmaps the order is descending. + + With --twotails, the values are first "folded" so that the high and + low tails of the distribution overlay each other. For Tmaps this + implies multiplying all positive values by -1. Thus if + pick_n_voxels.py returns a value V for a T threshold, V will be + negative and the high and low thresholds will be +V and -V. + For obvious reasons the --twotails option cannot be used with Fmaps. + + When --twotails is applied to Pmaps, all P values above 0.5 are + replaced by (1-P). Thus if pick_n_voxels.py returns a value V for a + P threshold, the two tails lie below P and above 1-P. + + The mask dataset is a dataset of 0 and 1 values, typically made by + thresholding the GrandMean dataset to exclude voxels outside the + brain. Masking is implemented by replacing P scores outside the mask + with 1.0, and T and F scores outside the mask with 0.0. This replacement + takes place after the folding-over of the right-hand tail if + --twotails is set. Note that this algorithm can cause problems if + the requested number of selected voxels is more than half of the + number within the mask! Fortunately this condition is obvious; all + voxels outside the mask will suddenly be selected. + + There are special floating point values in the IEEE standard for + floating point numbers which represent "not a number" or "infinite" + values; pick_n_voxels.py ignores those entries when it calculates + the P score cutoff. This means that you can mask out parts of the + input data that you would like to ignore by setting them equal to + "NaN" using (for example) mri_rpn_math. This is over and above any + masking implemented with the --mask flag. + + If you request N voxels and then count the number of voxels actually + selected, you may find a number which is 1 or 2 off from N. This + happens because of the difficulty of converting a high-precision + floating point number to base-10 ascii characters and back. This + problem is more serious with Pmaps than with Tmaps, since a lot of + the interesting P scores fall very close to the values 0.0 or 1.0. + +*pick_n_voxels.py:Example + + A shell script would typically use pick_n_voxels.csh to generate + a T score cutoff, and then mask the Tmap using that threshold. + For example, using the Fiasco "overlay" utility to highlight + the negative tail of the T distribution: + + set val = `pick_n_voxels.py -T 2000 Tmap` + + overlay.csh -inmap Tmap -inimage mean_image -headerout masked_t \ + -highthresh 10000 -lowthresh $val + + The high threshold is an unlikely T score of 10000; the low + threshold is inferred from the desired voxel count. + + Setting the high T value for a two-tailed overlay is tricky inside + a Cshell script because it involves floating point arithmetic + (multiplying a floating point number by -1). Be sure to properly + implement this if you want two-tailed overlays! + + To generate an overlay from only those voxels within the brain, one + might make a mask by thresholding the mean values for all image + voxels: + + mri_rpn_math -out mymask '$1,800,<' GrandMean + set val = `pick_n_voxels.py --mask mymask -T 2000 Tmap` + overlay.csh -inmap Tmap -inimage GrandMean -headerout masked_t \ + -highthresh 10000 -lowthresh $val + + Values can also be masked out by setting them to the IEEE value + "NaN" (meaning Not a Number). For example, + + mri_rpn_math -o Pmap_masked '$1,NaN,$2,800,>,if_keep' Pmap GrandMean + set val = `pick_n_voxels.py -P 2000 Pmap_masked` + overlay.csh -inmap Pmap -inimage GrandMean -headerout masked_p \ + -highthresh 2.0 -lowthresh $val + +*pick_n_voxels.py:Environment + + pick_n_voxels.py keeps scratch files in a temporary directory. + If the environment variable F_TEMP is defined this directory will + be ${F_TEMP}/tmp_pickn_NN (where NN is the current process ID); + otherwise ./tmp_pickn_NN will be used. The temporary directory is + deleted when pick_n_voxels.py is finished with it. + +*customize_local.py:Usage + + This script customizes the various Fiasco *.local.csh files for + a specific case. Its implementation depends on the research + project for which it is to be used, and thus it is not portable + between projects. + + customize_local.py [-v] [-d] [--src=srcDir] key1=val1 + key2=val2 ... fileToCustomize + + -v requests verbose output + -d requests debugging output + --src=srcDir means read the original file from srcDir + + if the --src option is not used, the source file will come from + the directory specified by the FIASCO environment variable. + *dataset_matches_env.py:Usage This script checks to make sure that the Fiasco environment @@ -508,13 +1026,13 @@ *false_discovery.py:Example - A shell script would typically use false_discovery.csh to generate + A shell script would typically use false_discovery.py to generate a P score cutoff, and then mask the Pmap using that threshold. For example, using the Fiasco "overlay" utility: set val = `false_discovery.py 0.15 Pmap` - overlay -inmap Pmap -inimage mean_image -headerout masked_p \ + overlay.csh -inmap Pmap -inimage mean_image -headerout masked_p \ -highthresh 2.0 -lowthresh $val The high threshold is an impossible P score of 2.0; the low Index: src/smregpar3d/Makefile =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/smregpar3d/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -a -u -r1.1 -r1.2 --- src/smregpar3d/Makefile 24 Apr 2000 20:06:10 -0000 1.1 +++ src/smregpar3d/Makefile 17 Mar 2004 22:10:46 -0000 1.2 @@ -11,7 +11,7 @@ PKG = smregpar3d PKG_MAKEBINS = $(CB)/smregpar3d -PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg -lm +PKG_LIBS = -lfmri -lmri -lpar -lbio -lacct -lmisc -lcrg $(LAPACK_LIBS) -lm MAKEFILES= Makefile CSOURCE= smregpar3d.c Index: src/smregpar3d/smregpar3d.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/smregpar3d/smregpar3d.c,v retrieving revision 1.8 retrieving revision 1.9 diff -a -u -r1.8 -r1.9 --- src/smregpar3d/smregpar3d.c 4 Feb 2003 05:33:44 -0000 1.8 +++ src/smregpar3d/smregpar3d.c 9 Apr 2004 20:32:47 -0000 1.9 @@ -39,7 +39,7 @@ #include "misc.h" #include "stdcrg.h" -static char rcsid[] = "$Id: smregpar3d.c,v 1.8 2003/02/04 05:33:44 welling Exp $"; +static char rcsid[] = "$Id: smregpar3d.c,v 1.9 2004/04/09 20:32:47 welling Exp $"; typedef struct regpar3d_struct { Quat q; @@ -376,12 +376,13 @@ } else smooth_itbl[7][temp_fixed_image]= par[1].mse; } -#ifdef never + SM_SMOOTH_GROUP( smoother, smooth_itbl, smooth_otbl, 8, dt, image_missing, 0 ); -#endif +#ifdef never SM_SMOOTH_GROUP( smoother, smooth_itbl, smooth_otbl, 8, dt, NULL, 0 ); +#endif /* Use this smoothing result as the smoothed mse */ for (t=0; t maxv) - maxv = v; - } + if (r.recon_failed) { + for (i = 0; i < c.res; ++i) + for (j = 0; j < c.res; ++j) + { + outim[i][j] = 0.0; + sh_outim[i][j] = 0; + } + } + else { + for (i = 0; i < c.res; ++i) + for (j = 0; j < c.res; ++j) + { + v = c.output_scale * outim[i][j] / (c.os_res * c.os_res); + outim[i][j] = v; + sh_outim[i][j] = v; + if (v > maxv) + maxv = v; + } + } if (c.verbosity >= VERBOSITY_TIMESTEP) Report("max=%3d", (int) maxv); Index: src/summary/summary.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/summary/summary.c,v retrieving revision 1.36 retrieving revision 1.37 diff -a -u -r1.36 -r1.37 --- src/summary/summary.c 25 Sep 2003 19:45:42 -0000 1.36 +++ src/summary/summary.c 17 Mar 2004 23:38:27 -0000 1.37 @@ -56,7 +56,7 @@ #include "stdcrg.h" #include "misc.h" -static char rcsid[] = "$Id: summary.c,v 1.36 2003/09/25 19:45:42 welling Exp $"; +static char rcsid[] = "$Id: summary.c,v 1.37 2004/03/17 23:38:27 welling Exp $"; #define PAGE_TOP 70000 #define LINE_STEP 1200 @@ -371,7 +371,7 @@ { for (z=0; zdz; z++) { readParLine(fp, getFileName(fi), 0, fi->nFields, 0, z, 0); - for (i=1; inFields; i++) + for (i=0; inFields; i++) for( t = 1; t < fi->dt; t++ ) pars[i][t][z]= pars[i][0][z]; } @@ -381,7 +381,7 @@ { for (t=0; tdt; t++) { readParLine(fp, getFileName(fi), 0, fi->nFields, t, 0, 0); - for (i=1; inFields; i++) + for (i=0; inFields; i++) for( z = 1; z < fi->dz; z++ ) pars[i][t][z]= pars[i][t][0]; } @@ -391,7 +391,7 @@ { for (t=0; tdt; t++) { readParLine(fp, getFileName(fi), 1, fi->nFields, t, 0, 0); - for (i=1; inFields; i++) + for (i=0; inFields; i++) for( z = 1; z < fi->dz; z++ ) pars[i][t][z]= pars[i][t][0]; } @@ -401,7 +401,7 @@ { for (z=0; zdz; z++) { readParLine(fp, getFileName(fi), 1, fi->nFields, 0, z, 0); - for (i=1; inFields; i++) + for (i=0; inFields; i++) for( t = 1; t < fi->dt; t++ ) pars[i][t][z]= pars[i][0][z]; } Index: src/util/libpar.c =================================================================== RCS file: /home/TINGENEK/welling/cvsroot/Fiasco/src/util/libpar.c,v retrieving revision 1.17 retrieving revision 1.21 diff -a -u -r1.17 -r1.21 --- src/util/libpar.c 30 Jul 2003 22:13:45 -0000 1.17 +++ src/util/libpar.c 4 May 2004 21:36:21 -0000 1.21 @@ -15,8 +15,8 @@ * to process the values in the Result record. * * - * Copyright (c) 1995,1996,1997,1999,2001 Pittsburgh Supercomputing - * Center + * Copyright (c) 1995,1996,1997,1999,2001,2004 Pittsburgh Supercomputing + * Center * * * This program is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the * @@ -40,6 +40,9 @@ * (ghood@psc.edu) * 3/00 - fixed bug in HandleRestart (ghood@psc.edu) * 3/01 - Converted to use either PVM or MPI (ghood@psc.edu) + * 2/04 - Fixed bug that caused ready/idle list corruption upon + * worker termination (SWang@psych.uic.edu, ghood@psc.edu, + * welling@stat.cmu.edu) * */ @@ -102,8 +105,10 @@ #undef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) +#undef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) -static char rcsid[] = "$Id: libpar.c,v 1.17 2003/07/30 22:13:45 welling Exp $"; +static char rcsid[] = "$Id: libpar.c,v 1.21 2004/05/04 21:36:21 welling Exp $"; /* the following buffer type is only used if we aren't using PVM buffers */ typedef struct Buffer { @@ -254,6 +259,9 @@ for which max_workers > 0 but which we have not yet heard from */ +static struct timeval longest_task= {0,0}; + /* run time of longest task so far */ + #if defined(PVM) typedef struct HostState { Hostname name; /* official name of the host */ @@ -1116,7 +1124,6 @@ /* record that worker n is performing the task */ if (workers[n].first_task == NULL) { - int i; workers[n].first_task = task; RemoveFromIdleList(n); } @@ -1543,6 +1550,8 @@ } /* if we get here, we didn't have a record of the worker anyway, so ignore the message */ + if (par_verbose) + Report ("Unknown Worker tid %d.\n", stid); } static void @@ -1699,14 +1708,32 @@ static void DeclareWorkerDead (int n) { - if (workers[n].second_task >= 0) + if (workers[n].second_task != NULL) RequeueTask(workers[n].second_task); - if (workers[n].first_task >= 0) + if (workers[n].first_task != NULL) RequeueTask(workers[n].first_task); RemoveFromReadyList(n); RemoveFromIdleList(n); - workers[n] = workers[n_workers - 1]; + --n_workers; + if (n != n_workers) + { + /* move the last worker into the slot formerly occupied by the + dead worker */ + workers[n] = workers[n_workers]; + if (workers[n_workers].idle) + { + RemoveFromIdleList(n_workers); + workers[n].idle = FALSE; + PutOnIdleList(n); + } + if (workers[n_workers].ready) + { + RemoveFromReadyList(n_workers); + workers[n].ready = FALSE; + PutOnReadyList(n); + } + } } static void @@ -1719,6 +1746,10 @@ int i; int dest; int oldid; + struct timeval task_start; + struct timeval task_end; + long task_sec; + long task_usec; #ifdef PTHREADS /* launch another thread that will actually execute the tasks */ @@ -1745,8 +1776,27 @@ Report("Worker received task %d\n", task_num); if (par_unpack_task != NULL) (*par_unpack_task)(); - if (par_worker_task != NULL) + if (par_worker_task != NULL) { + if (gettimeofday(&task_start, NULL) != 0) + Abort("Worker could not get time of day.\n"); (*par_worker_task)(); + if (gettimeofday(&task_end, NULL) != 0) + Abort("Worker could not get time of day.\n"); + task_sec= task_end.tv_sec-task_start.tv_sec; + task_usec= task_end.tv_usec-task_start.tv_usec; + if (task_usec<0) + { + task_sec -= 1; + task_usec += 1000000; + } + if (task_sec > longest_task.tv_sec + ||(task_sec==longest_task.tv_sec + && task_usec>longest_task.tv_usec)) + { + longest_task.tv_sec= task_sec; + longest_task.tv_usec= task_usec; + } + } if (par_master_result != NULL) { ComposeRequest(task_num, TRUE); @@ -1922,7 +1972,7 @@ #ifdef ACCT Acct(MSGWAITING); #endif - tmout.tv_sec = WORKER_RECEIVE_TIMEOUT; + tmout.tv_sec = MAX(WORKER_RECEIVE_TIMEOUT,10*(longest_task.tv_sec+1)); tmout.tv_usec = 0; bufid = pvm_trecv(-1, -1, &tmout); @@ -1952,7 +2002,7 @@ end_time.tv_sec = 0; if (gettimeofday(&end_time, NULL) != 0) Abort("Worker could not get time of day.\n"); - end_time.tv_sec += WORKER_RECEIVE_TIMEOUT; + end_time.tv_sec += MAX(WORKER_RECEIVE_TIMEOUT,10*(longest_task.tv_sec+1)); duration.tv_sec = 0; duration.tv_nsec = 10000000; /* 10 milliseconds */ do { @@ -1973,7 +2023,14 @@ current_time.tv_usec < end_time.tv_usec)); if (!flag) - Abort("Worker timed out waiting for message.\n"); + { + Report("Worker timed out waiting for message. Exiting...\n"); + PrepareToSend (); + par_pkint (my_tid); + Send (master_tid, WORKER_EXIT_MSG); + /* Fake msg so finalize will be done before exit.*/ + return (TERMINATE_MSG); + } /* a message is there; now receive it */ if (MPI_Get_count(&status, MPI_PACKED, &len) != MPI_SUCCESS) @@ -2450,6 +2507,9 @@ /* enroll in pvm */ my_tid = pvm_mytid(); + /* Collect output to the master task */ + pvm_catchout(stdout); + #if defined(T3D) || defined(T3E) /* on the T3D/E we can get our rank without using a group */ rank = pvm_get_PE(my_tid);