Mercurial > hg > minc-tools
changeset 55:a23deb019f17
Initial revision
author | neelin <neelin> |
---|---|
date | Fri, 08 Jan 1993 09:45:04 +0000 |
parents | 22d0cb5dac63 |
children | 1d6d893eadcd |
files | conversion/mnitominc/Makefile conversion/mnitominc/mnitominc.c conversion/mnitominc/mnitominc.h conversion/scxtominc/define_scx_header.perl conversion/scxtominc/pc5r1.drs progs/Proglib/Makefile progs/Proglib/ParseArgv.c progs/Proglib/ParseArgv.h progs/Proglib/vax_conversions.c progs/rawtominc/Makefile progs/rawtominc/rawtominc.c |
diffstat | 11 files changed, 2668 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/conversion/mnitominc/Makefile @@ -0,0 +1,70 @@ +# -------------------------------------------------------------------- +# +# MINC Makefile +# + +# Executable names +PROGS = mnitominc +HEADERS = $(PROGS:=.h) +PROG_LIB_DIR = ../proglib +PROG_LIB = mincprog +LIB_DIR = ../../src# directory for library +LIBRARY = minc# library +CDEFINES = -DDEBUG# cpp defines +OPT = -g# compiler options +LDOPT = -L/usr/local/lib -lnetcdf -lsun -lm -lgl_s -lm -lc_s# ld options +INCLUDES = -I. -I../proglib -I../../src -I/usr/local/include + +# For cleaning up +RM = rm +RM_FLAGS = -f + +# -------------------------------------------------------------------- + +CFLAGS = $(CDEFINES) $(INCLUDES) $(OPT)# CFLAGS and LINTFLAGS should +LINTFLAGS = $(CDEFINES) $(INCLUDES)# be same, except for -g/-O + +PROG_OBJ = $(PROGS:=.o)# list of objects +CC_LIB = lib$(LIBRARY).a# C library file +CC_PROG_LIB= $(PROG_LIB_DIR)/lib$(PROG_LIB).a# library for prog objs +LINT_LIST = $(PROG_OBJ:.o=.ln) +LINT_LIST_EXE = $(LINT_LIST:.ln=.)# list of executable names to lint +LINT_LIB = llib-l$(LIBRARY).ln# lint library file +LINT_PROG_LIB = $(PROG_LIB_DIR)/llib-l$(PROG_LIB).ln# + +# -------------------------------------------------------------------- + +.SUFFIXES: .ln# tell make to watch for .ln's + +default: $(PROGS) + +#Dependency on Makefile +$(PROG_OBJ) $(LINT_OBJS) : Makefile + +all: $(PROGS) lint + +.c.ln:# defines the rule for creating .ln + lint $(LINTFLAGS) -c $< -o $@ + +.c.o:# defines the rule for creating .o + $(CC) $(CFLAGS) -c $< -o $@ + +#Dependency of .o and .ln on .h +$(PROG_OBJ) : $(HEADERS) + +$(LINT_LIST) : $(HEADERS) + +# How to make executables +$(PROGS) : $$@.o $(CC_PROG_LIB) $(LIB_DIR)/$(CC_LIB) + $(CC) $@.o -o $@ $(CC_PROG_LIB) -L$(LIB_DIR) -l$(LIBRARY) $(LDOPT) + +# how to lint the executable source +lint: $(LINT_LIST_EXE) + +$(LINT_LIST_EXE) : $$@ln $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + lint -u $(LINTFLAGS) $@ln $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + +# Remove all derived files in this directory +clean: + $(RM) $(RM_FLAGS) $(LINT_LIST) $(PROGS) $(PROG_OBJ) +
new file mode 100644 --- /dev/null +++ b/conversion/mnitominc/mnitominc.c @@ -0,0 +1,788 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : mnitominc +@INPUT : argc, argv - command line arguments +@OUTPUT : (none) +@RETURNS : error status +@DESCRIPTION: Converts an mni format file to a minc format file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : December 7, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +#ifndef lint +static char rcsid[]="$Header: /private-cvsroot/minc/conversion/mnitominc/mnitominc.c,v 1.1 1993-01-08 09:46:55 neelin Exp $"; +#endif + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <minc.h> +#include <float.h> +#include <string.h> +#include <math.h> +#include <ParseArgv.h> +#include "mnitominc.h" + + +/* Main program */ + +main(int argc, char *argv[]) +{ + int cdfid, imgid, maxid, minid, patid, study, acqid; + int dimvar[MAX_VAR_DIMS], twidth; + long start[MAX_VAR_DIMS]; + long count[MAX_VAR_DIMS]; + long end[MAX_VAR_DIMS]; + long temp_coord[MAX_VAR_DIMS]; + int dim[MAX_VAR_DIMS]; + int fastdim; + int iframe, islice, image_num, i; + mni_header_type mni_header; + mni_image_type mni_image; + int zdim, tdim; + double last_z, diff_z, curr_diff_z, first_z; + double last_t, diff_t, curr_diff_t, first_t; + int z_regular, t_regular; + + /* Parse arguments and get header info from mni file */ + parse_args(argc, argv, &mni_header); + + /* Create the file */ + cdfid=nccreate(outfilename, (clobber ? NC_CLOBBER : NC_NOCLOBBER)); + + /* Create the dimensions */ + zdim = tdim = -1; + for (i=0; i<ndims; i++) { + dim[i] = ncdimdef(cdfid, dimname[i], dimlength[i]); + + /* Create dimension variable if mni file or for image dimensions */ + if ((mni_header.file_type==MNI_FILE_TYPE) || + (i>=ndims-IMAGE_DIMS)) { + if (dimfixed[i]) + dimvar[i] = micreate_std_variable(cdfid, dimname[i], + NC_LONG, 0, NULL); + else + dimvar[i] = micreate_std_variable(cdfid, dimname[i], + NC_DOUBLE, 1, &dim[i]); + + /* Add MIstep attribute */ + if (i==ndims-1) { + (void) miattputdbl(cdfid, dimvar[i], MIstep, xstep); + if ((mni_header.file_type == MNI_FILE_TYPE) && + (mni_header.scanner_id == MNI_STX_SCAN) && + (orientation == TRANSVERSE) && + (mni_header.npixels == 128)) { + (void) miattputdbl(cdfid, dimvar[i], MIstart, + mni_header.xstart); + } + } + else if (i==ndims-2) { + (void) miattputdbl(cdfid, dimvar[i], MIstep, ystep); + if ((mni_header.file_type == MNI_FILE_TYPE) && + (mni_header.scanner_id == MNI_STX_SCAN) && + (orientation == TRANSVERSE) && + (mni_header.npixels == 128)) { + (void) miattputdbl(cdfid, dimvar[i], MIstart, + mni_header.ystart); + } + } + else { + (void) miattputdbl(cdfid, dimvar[i], MIstep, 0.0); + (void) miattputdbl(cdfid, dimvar[i], MIstart, 0.0); + } + + /* If MItime, then create dimwidth variable */ + if (STR_EQ(dimname[i], MItime)) { + tdim=i; + if (dimfixed[i]) + twidth = micreate_std_variable(cdfid, MItime_width, + NC_LONG, 0, NULL); + else + twidth = micreate_std_variable(cdfid, MItime_width, + NC_DOUBLE, 1, &dim[i]); + (void) miattputstr(cdfid, dimvar[i], MIunits, "seconds"); + (void) miattputstr(cdfid, twidth, MIunits, "seconds"); + } + + /* If not MItime, add attribute to describe spacetype */ + else { + (void) miattputstr(cdfid, dimvar[i], MIunits, "mm"); + if (i<ndims-IMAGE_DIMS) zdim=i; + if (mni_header.scanner_id==MNI_STX_SCAN) + (void) miattputstr(cdfid, dimvar[i], MIspacetype, MI_TALAIRACH); + else + (void) miattputstr(cdfid, dimvar[i], MIspacetype, MI_NATIVE); + } + + } /* Dimension variable */ + + /* Initialize coordinate vectors */ + start[i] = 0; + count[i] = ((i<ndims-IMAGE_DIMS) ? 1 : dimlength[i]); + end[i] = dimlength[i]; + } + + /* Create the image */ + imgid=micreate_std_variable(cdfid, MIimage, + (mni_header.pix_size==1 ? NC_BYTE : NC_SHORT), + ndims, dim); + (void) miattputstr(cdfid, imgid, MIsigntype, + (mni_header.pix_size==1 ? MI_UNSIGNED : MI_SIGNED)); + (void) ncattput(cdfid, imgid, MIvalid_range, NC_DOUBLE, 2, + mni_header.valid_range); + if (mni_header.file_type==MNI_FILE_TYPE) { + maxid = micreate_std_variable(cdfid, MIimagemax, + NC_DOUBLE, ndims-IMAGE_DIMS, dim); + minid = micreate_std_variable(cdfid, MIimagemin, + NC_DOUBLE, ndims-IMAGE_DIMS, dim); + } + + /* Add patient information */ + patid=micreate_group_variable(cdfid, MIpatient); + (void) miattputstr(cdfid, patid, MIfull_name, mni_header.patient_name); + (void) miattputstr(cdfid, patid, MIidentification, + mni_header.patient_num); + + /* Add study information */ + study=micreate_group_variable(cdfid, MIstudy); + (void) miattputstr(cdfid, study, MIstart_time, mni_header.start_time); + if ((mni_header.file_type==MNI_FILE_TYPE) && + (mni_header.scanner_id!=MNI_MRI_SCAN) && + (mni_header.scanner_id!=MNI_STX_SCAN) && + (mni_header.npixels<=128)) + (void) miattputstr(cdfid, study, MImodality, MI_PET); + else if (mni_header.scanner_id!=MNI_STX_SCAN) + (void) miattputstr(cdfid, study, MImodality, MI_MRI); + + /* Add acquisition information */ + if ((mni_header.file_type==MNI_FILE_TYPE) && + (mni_header.scanner_id!=MNI_MRI_SCAN) && + (mni_header.scanner_id!=MNI_STX_SCAN) && + (mni_header.npixels<=128)) { + acqid=micreate_group_variable(cdfid, MIacquisition); + (void) miattputstr(cdfid, acqid, MIinjection_time, + mni_header.injection_time); + (void) miattputstr(cdfid, acqid, MIradionuclide, mni_header.isotope); + (void) miattputdbl(cdfid, acqid, MIinjection_dose, mni_header.dose); + (void) miattputstr(cdfid, acqid, MIdose_units, mni_header.dose_units); + } + + /* End definition mode */ + (void) ncsetfill(cdfid, NC_NOFILL); + (void) ncendef(cdfid); + + /* Get a buffer for reading images */ + mni_image.npixels=mni_header.npixels; + mni_image.image_pix=mni_image.npixels*mni_image.npixels; + mni_image.pix_size=mni_header.pix_size; + mni_image.image_size=mni_image.image_pix*mni_image.pix_size; + mni_image.image=malloc(mni_image.image_size); + + /* Loop through the images */ + fastdim=ndims-IMAGE_DIMS-1; + if (fastdim<0) fastdim=0; + z_regular = t_regular = TRUE; + for (iframe=0; iframe<nframes; iframe++) { + for (islice=0; islice<nslices; islice++) { + + /* Read in image */ + image_num = islice*nframes + iframe; + if (get_mni_image(&mni_header, &mni_image, image_num)) { + (void) fprintf(stderr, "%s: Error reading mni image.\n", pname); + exit(ERROR_STATUS); + } + + /* Write the image */ + (void) ncvarput(cdfid, imgid, start, count, mni_image.image); + + /* Write the image max and min, z position and time */ + if (mni_header.file_type==MNI_FILE_TYPE) { + (void) ncvarput1(cdfid, minid, start, &mni_image.minimum); + (void) ncvarput1(cdfid, maxid, start, &mni_image.maximum); + if ((zdim>=0) && (iframe==0)) { + (void) ncvarput1(cdfid, dimvar[zdim], + mitranslate_coords(cdfid, + imgid, start, + dimvar[zdim], + miset_coords(MAX_DIMS, 0L, temp_coord)), + &mni_image.zposition); + if (islice>0) { + curr_diff_z = mni_image.zposition - last_z; + if ((islice>1) && !dblcmp(curr_diff_z, diff_z, EPSILON)) + z_regular = FALSE; + diff_z = curr_diff_z; + } + else + first_z = mni_image.zposition; + last_z=mni_image.zposition; + } + if ((tdim>=0) && (islice==0)) { + (void) ncvarput1(cdfid, dimvar[tdim], + mitranslate_coords(cdfid, + imgid, start, + dimvar[tdim], + miset_coords(MAX_DIMS, 0L, temp_coord)), + &mni_image.time); + (void) ncvarput1(cdfid, twidth, + mitranslate_coords(cdfid, + imgid, start, + twidth, + miset_coords(MAX_DIMS, 0L, temp_coord)), + &mni_image.time_length); + if (iframe>0) { + curr_diff_t = mni_image.time - last_t; + if ((iframe>1) && !dblcmp(curr_diff_t, diff_t, EPSILON)) + t_regular = FALSE; + diff_t = curr_diff_t; + } + else + first_t = mni_image.time; + last_t=mni_image.time; + } + } + + /* Increment the counters */ + start[fastdim] += count[fastdim]; + i=fastdim; + while ((i>0) && (start[i]>=end[i])) { + start[i] = 0; + i--; + start[i] += count[i]; + } + } + } + + /* Write dimension attributes for z and t */ + if (zdim>=0) { + if (nslices>1) + diff_z = (last_z - first_z) / (double) (nslices - 1); + else + diff_z = 0.0; + (void) miattputdbl(cdfid, dimvar[zdim], MIstep, diff_z); + (void) miattputdbl(cdfid, dimvar[zdim], MIstart, first_z); + if (z_regular) + (void) miattputstr(cdfid, dimvar[zdim], MIspacing, MI_REGULAR); + else + (void) miattputstr(cdfid, dimvar[zdim], MIspacing, MI_IRREGULAR); + } + + if (tdim>=0) { + if (nframes>1) + diff_t = (last_t - first_t) / (double) (nframes - 1); + else + diff_t = 0.0; + (void) miattputdbl(cdfid, dimvar[tdim], MIstep, diff_t); + (void) miattputdbl(cdfid, dimvar[tdim], MIstart, first_t); + if (t_regular) + (void) miattputstr(cdfid, dimvar[tdim], MIspacing, MI_REGULAR); + else + (void) miattputstr(cdfid, dimvar[tdim], MIspacing, MI_IRREGULAR); + } + + /* Free the memory */ + free(mni_image.image); + + /* Close the file */ + (void) ncclose(cdfid); + + return NORMAL_STATUS; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : parse_args +@INPUT : argc - number of command line arguments + argv - array of arguments +@OUTPUT : +@RETURNS : (nothing). +@DESCRIPTION: Parses command line arguments. +@METHOD : +@GLOBALS : pname - program name + infilename - mni file to read + outfilename - minc file to write + clobber - overwrite? + dimname - names of dimensions + dimlength - lengths of dimensions + ndims - number of dimensions + orientation - orientation of dimensions + type - type of output data + signtype - sign of output data + sign - string sign of output + valid_range - valid range of output data + vrange_set - valid range used? +@CALLS : +@CREATED : December 7, 1992 +@MODIFIED : +---------------------------------------------------------------------------- */ +void parse_args(int argc, char *argv[], mni_header_type *mni_header) +{ + int i, j, npix; + + /* Parse the command line */ + pname=argv[0]; + if (ParseArgv(&argc, argv, argTable, 0)) { + usage_error(pname); + } + + /* Check number of arguments */ + if (argc!=3) + usage_error(pname); + + /* Get filenames */ + infilename = argv[1]; + outfilename = argv[2]; + + /* Get mni file header info */ + if (get_mni_header(infilename, mni_header)) { + (void) fprintf(stderr, "%s: Error reading mni file header.\n", pname); + usage_error(pname); + } + + /* Get dimensions */ + + /* Get fastest two dim sizes */ + for (i=0; i<IMAGE_DIMS; i++) + + dimlength[MAX_DIMS-i-1] = mni_header->npixels; + + /* Try to guess slowest two dim sizes if user doesn't give info */ + if ((dimlength[0]<=0) && (dimlength[1]<=0)) { + + /* If fewer than MAX_VOL_IMGS images, assume volume */ + if (mni_header->nimages<=MAX_VOL_IMGS) { + dimlength[0]=1; + dimlength[1]=mni_header->nimages; + } + + /* Otherwise, divide by DEFAULT_NSLICES to get nframes */ + else { + dimlength[1]=DEFAULT_NSLICES; + dimlength[0]=mni_header->nimages / dimlength[1]; + } + } + /* User gave nframes */ + else if ((dimlength[0]>0) && (dimlength[1]<=0)) { + dimlength[1]=mni_header->nimages / dimlength[0]; + } + /* User gave nslices */ + else if ((dimlength[0]<=0) && (dimlength[1]>0)) { + dimlength[0]=mni_header->nimages / dimlength[1]; + } + /* User gave both */ + else { + if (dimlength[0]*dimlength[1]!=mni_header->nimages) { + (void) fprintf(stderr, + "%s: <nframes>*<nslices> is not equal to # of images in file.\n", + pname); + exit(ERROR_STATUS); + } + } + + /* Check that nframes*nslices = nimages */ + if ((dimlength[0]*dimlength[1])!=mni_header->nimages) { + (void) fprintf(stderr, + "%s: Cannot work out number of slices and frames.\n", + pname); + exit(ERROR_STATUS); + } + else if ((dimlength[0]<1) || (dimlength[1]<1)) { + (void) fprintf(stderr, + "%s: Number of frames and slices must be greater than zero.\n", + pname); + exit(ERROR_STATUS); + } + + /* Get orientation */ + if (orientation == DEF_ORIENT) { + if (mni_header->orientation==MNI_CORONAL) + orientation = CORONAL; + else if (mni_header->orientation==MNI_SAGITTAL) + orientation = SAGITTAL; + else + orientation = TRANSVERSE; + } + for (i=1; i<MAX_DIMS; i++) { + dimname[i]=orientation_names[orientation][i-1]; + } + + /* Get number of dimensions and check for dimensions of length 1 */ + nframes = dimlength[0]; + nslices = dimlength[1]; + for (i=0, j=0; i<MAX_DIMS; i++) { + if ((i>=MAX_DIMS-IMAGE_DIMS) || (dimlength[i]>1)) { + dimlength[j] = dimlength[i]; + dimname[j] = dimname[i]; + dimfixed[j] = dimfixed[i]; + j++; + } + } + ndims=j; + + /* Set x,y step for stereotaxic files */ + if ((mni_header->file_type == MNI_FILE_TYPE) && + (mni_header->scanner_id == MNI_STX_SCAN)) { + npix = mni_header->npixels; + switch (orientation) { + case TRANSVERSE: + mni_header->xstep = + MNI_DIR * MNI_STX_XFOV / ((double) npix); + mni_header->ystep = + MNI_DIR * MNI_STX_YFOV / ((double) npix); + mni_header->zstep_scale = MNI_STX_ZSCALE; + mni_header->xstart = -((int) npix/2) * mni_header->xstep; + mni_header->ystart = -((int) npix/2) * mni_header->ystep; + break; + case SAGITTAL: + mni_header->xstep = + MNI_DIR * MNI_STX_YFOV / ((double) npix); + mni_header->ystep = + MNI_DIR * MNI_STX_ZFOV / ((double) npix); + mni_header->zstep_scale = MNI_STX_XSCALE; + break; + case CORONAL: + mni_header->xstep = + MNI_DIR * MNI_STX_XFOV / ((double) npix); + mni_header->ystep = + MNI_DIR * MNI_STX_ZFOV / ((double) npix); + mni_header->zstep_scale = MNI_STX_YSCALE; + break; + } + } + + /* Field of view */ + if (xstep==0.0) xstep = field_of_view; + if (ystep==0.0) ystep = field_of_view; + if (xstep==0.0) xstep = mni_header->xstep; + if (ystep==0.0) ystep = mni_header->ystep; + + return; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : usage_error +@INPUT : progname - program name +@OUTPUT : (none) +@RETURNS : (nothing) +@DESCRIPTION: Prints a usage error message and exits. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : December 7, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +void usage_error(char *progname) +{ + (void) fprintf(stderr, + "\nUsage: %s [<options>] <infile> <outfile>\n", progname); + (void) fprintf(stderr, + " %s [-help]\n\n", progname); + + exit(ERROR_STATUS); +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_mni_header +@INPUT : file - name of mni format file +@OUTPUT : mni_header - pointer to structure containing mni header info +@RETURNS : TRUE if an error occurs +@DESCRIPTION: Opens an mni format file and reads the header information +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : December 8, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int get_mni_header(char *file, mni_header_type *mni_header) +{ + char buffer[MNI_HEADER_SIZE]; + int matrix_type; + short stemp; + int i, j; + + if ((mni_header->fp=fopen(file, "r"))==NULL) { + (void) fprintf(stderr, "Cannot open file %s\n", file); + return(TRUE); + } + + /* Read in the header block */ + if (fseek(mni_header->fp, 0, SEEK_SET) || + (fread(buffer, sizeof(char), MNI_HEADER_SIZE, mni_header->fp) + !=MNI_HEADER_SIZE)) { + (void) fprintf(stderr, "Cannot read from file.\n"); + return(TRUE); + } + + /* Get interesting information */ + + /* Get offset to data */ + get_vax_short(1, &buffer[MNI_LOC_OFFSET], &(mni_header->offset)); + + /* Get number of images */ + get_vax_short(1, &buffer[MNI_LOC_NIMAGES], &(mni_header->nimages)); + + /* Get image size and file type info */ + matrix_type=buffer[MNI_LOC_MATYPE]; + switch (matrix_type) { + case '3': + mni_header->npixels=64; + mni_header->file_type=MNI_FILE_TYPE; + break; + case '4': + mni_header->npixels=64; + mni_header->file_type=NIL_FILE_TYPE; + break; + case '5': + mni_header->npixels=128; + mni_header->file_type=MNI_FILE_TYPE; + break; + case '6': + mni_header->npixels=128; + mni_header->file_type=NIL_FILE_TYPE; + break; + case '7': + mni_header->npixels=256; + mni_header->file_type=MNI_FILE_TYPE; + break; + case '8': + mni_header->npixels=256; + mni_header->file_type=NIL_FILE_TYPE; + break; + default: + (void) fprintf(stderr, "Unknown matrix format.\n"); + return(TRUE); + } + + /* Get pixel size and valid range info from file type. */ + if (mni_header->file_type==MNI_FILE_TYPE) { + mni_header->pix_size=1; + mni_header->valid_range[0]=MNI_VMIN; + mni_header->valid_range[1]=MNI_VMAX; + } + else { + mni_header->pix_size=2; + mni_header->valid_range[0]=NIL_VMIN; + mni_header->valid_range[1]=NIL_VMAX; + } + + /* Get image type */ + get_vax_short(1, &buffer[MNI_LOC_SCANNER_ID], &(mni_header->scanner_id)); + get_vax_short(1, &buffer[MNI_LOC_CORR_MASK], &stemp); + if (stemp==MNI_POSITOME_MASK) mni_header->scanner_id=MNI_POS_SCAN; + + /* Get step sizes */ + if (mni_header->file_type==MNI_FILE_TYPE) { + /* We have to deal with step for stereotaxic files after knowing + orientation (i.e. after parsing args) */ + if (mni_header->scanner_id != MNI_STX_SCAN) { + mni_header->xstep = mni_header->ystep = + MNI_DIR * MNI_FOV / ((double) mni_header->npixels); + } + } + else + mni_header->xstep = mni_header->ystep = + NIL_DIR * NIL_FOV / ((double) mni_header->npixels); + + /* Get image orientation */ + get_vax_short(1, &buffer[MNI_LOC_ORIENTATION], &(mni_header->orientation)); + + /* Get Patient name */ + for (i=0; i<MNI_PATNAM_LENGTH; i++) { + mni_header->patient_name[i]=buffer[MNI_LOC_PATNAM+i]; + if ((mni_header->patient_name[i] < MIN_VALID_CHAR) || + (mni_header->patient_name[i] > MAX_VALID_CHAR)) + mni_header->patient_name[i] = PADDING_CHAR; + } + mni_header->patient_name[i]='\0'; + + /* Get Patient number */ + for (i=0; i<MNI_PATNUM_LENGTH; i++) { + mni_header->patient_num[i]=buffer[MNI_LOC_PATNUM+i]; + if ((mni_header->patient_num[i] < MIN_VALID_CHAR) || + (mni_header->patient_num[i] > MAX_VALID_CHAR)) + mni_header->patient_num[i] = PADDING_CHAR; + } + mni_header->patient_num[i]='\0'; + + /* Get acquisition time and date */ + for (i=0, j=0; i<MNI_ACQDAT_LENGTH; i++, j++) { + mni_header->start_time[j]=buffer[MNI_LOC_ACQDAT+i]; + if ((mni_header->start_time[j] < MIN_VALID_CHAR) || + (mni_header->start_time[j] > MAX_VALID_CHAR)) + mni_header->start_time[j] = PADDING_CHAR; + } + mni_header->start_time[j++]=' '; + for (i=0; i<MNI_ACQTIM_LENGTH; i++, j++) { + mni_header->start_time[j]=buffer[MNI_LOC_ACQTIM+i]; + if ((mni_header->start_time[j] < MIN_VALID_CHAR) || + (mni_header->start_time[j] > MAX_VALID_CHAR)) + mni_header->start_time[j] = PADDING_CHAR; + } + mni_header->start_time[j]='\0'; + + /* Get isotope name */ + for (i=0; i<MNI_ISOTOPE_LENGTH; i++) { + mni_header->isotope[i]=buffer[MNI_LOC_ISOTOPE+i]; + if ((mni_header->isotope[i] < MIN_VALID_CHAR) || + (mni_header->isotope[i] > MAX_VALID_CHAR)) + mni_header->isotope[i] = PADDING_CHAR; + } + mni_header->isotope[i]='\0'; + + /* Get dose */ + for (i=0; i<MNI_DOSE_LENGTH; i++) { + mni_header->dose_string[i]=buffer[MNI_LOC_DOSE+i]; + if ((mni_header->dose_string[i] < MIN_VALID_CHAR) || + (mni_header->dose_string[i] > MAX_VALID_CHAR)) + mni_header->dose_string[i] = PADDING_CHAR; + } + mni_header->dose_string[i]='\0'; + mni_header->dose = atof(mni_header->dose_string); + (void) strcpy(mni_header->dose_units, "mCurie"); + + /* Get injection time */ + for (i=0; i<MNI_INJTIM_LENGTH; i++) { + mni_header->injection_time[i]=buffer[MNI_LOC_INJTIM+i]; + if ((mni_header->injection_time[i] < MIN_VALID_CHAR) || + (mni_header->injection_time[i] > MAX_VALID_CHAR)) + mni_header->injection_time[i] = PADDING_CHAR; + } + mni_header->injection_time[i]='\0'; + + return(FALSE); +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_mni_image +@INPUT : mni_header - pointer to structure containing file header info + and file pointer. + image_num - number of image to read (counting from zero). +@OUTPUT : mni_image - pointer to structure containing image information + (space for the image must already be allocated). +@RETURNS : TRUE if an error occurs. +@DESCRIPTION: Read an image from an mni format file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : December 8, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int get_mni_image(mni_header_type *mni_header, mni_image_type *mni_image, + int image_num) +{ + float qsc, zpos, time; + short isea, tlen; + int i, j, nrow, nread; + unsigned char *image; + double zero, denom, *valid_range; + + /* Check the image number */ + if (image_num >= mni_header->nimages) { + (void) fprintf(stderr, "Tried to read past last image.\n"); + return(TRUE); + } + + /* Read the image */ + if (fseek(mni_header->fp, mni_header->offset*BLOCK_SIZE + + image_num*mni_image->image_size, SEEK_SET)) { + (void) fprintf(stderr, "Cannot seek to image.\n"); + return(TRUE); + } + nread=fread(mni_image->image, mni_header->pix_size, mni_image->image_pix, + mni_header->fp); + if (nread<=0) { + (void) fprintf(stderr, "Cannot read image from file.\n"); + return(TRUE); + } + /* Check for read of only part of image (happens to last image of files + created by cnvmri) */ + if (nread<mni_image->image_pix) { + for (i=nread; i<mni_image->image_pix; i++) + mni_image->image[i]=0; + } + image = mni_image->image; + nrow=mni_image->npixels*mni_image->pix_size; + + /* Get interesting stuff from the image */ + if (mni_header->file_type==MNI_FILE_TYPE) { + get_vax_float(1, &image[MNI_XLOC_QSC+MNI_YLOC_QSC*nrow], &qsc); + get_vax_short(1, &image[MNI_XLOC_ISEA+MNI_YLOC_ISEA*nrow], &isea); + get_vax_float(1, &image[MNI_XLOC_ZPOS+MNI_YLOC_ZPOS*nrow], &zpos); + get_vax_float(1, &image[MNI_XLOC_TIME+MNI_YLOC_TIME*nrow], &time); + get_vax_short(1, &image[MNI_XLOC_TLEN+MNI_YLOC_TLEN*nrow], &tlen); + mni_image->minimum = (MNI_VMIN-isea) * qsc; + mni_image->maximum = (MNI_VMAX-isea) * qsc; + mni_image->zposition = ((mni_header->scanner_id != MNI_STX_SCAN) ? + zpos : + zpos * mni_header->zstep_scale); + mni_image->time = time*SEC_PER_MIN; + mni_image->time_length = tlen; + } + else { + mni_image->minimum = NIL_VMIN; + mni_image->maximum = NIL_VMAX; + mni_image->zposition = 0.0; + mni_image->time = 0.0; + mni_image->time_length = 0.0; + } + + /* Do byte swap if needed */ + if (mni_image->pix_size==2) { + get_vax_short(mni_image->image_pix, image, (short *) image); + } + + /* Zero the fruit salad */ + valid_range = mni_header->valid_range; + denom = mni_image->maximum - mni_image->minimum; + if (denom == 0.0) { + zero = valid_range[0]; + } + else { + zero = valid_range[0] - mni_image->minimum * + (valid_range[1] - valid_range[0]) / denom; + } + if (zero < valid_range[0]) zero = valid_range[0]; + if (zero > valid_range[1]) zero = valid_range[1]; + zero = rint(zero); + for (j=0; j < MNI_CORNER_YSIZE; j++) + for (i=0; i < MNI_CORNER_XSIZE; i += mni_image->pix_size) + if (mni_image->pix_size == 1) { + *((unsigned char *) &image[j*nrow+i]) = zero; + } + else if (mni_image->pix_size == 2) { + *((short *) &image[j*nrow+i]) = zero; + } + + return(FALSE); +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : dblcmp +@INPUT : dbl1 - first value + dbl2 - second value + epsilon - maximum difference +@OUTPUT : (none) +@RETURNS : TRUE if values are the same within epsilon, FALSE otherwise. +@DESCRIPTION: Compares two double precision values. If their normalized + difference is less than epsilon, then return TRUE, + otherwise FALSE. + Returns the following : + abs((dbl1-dbl2)/(dbl1+dbl2)) < epsilon +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : December 14, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int dblcmp(double dbl1, double dbl2, double epsilon) +{ + double diff, sum; + + diff = dbl1 - dbl2; + sum = dbl1 + dbl2; + diff = (diff < 0.0) ? -diff : diff; + sum = (sum < 0.0) ? -sum : sum; + if (sum==0.0) sum = 1.0; + return((diff/sum) <= epsilon); + +}
new file mode 100644 --- /dev/null +++ b/conversion/mnitominc/mnitominc.h @@ -0,0 +1,211 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : mnitominc.h +@DESCRIPTION: Header file for mnitominc +@GLOBALS : +@CALLS : +@CREATED : December 9, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +/* Some constants */ + +#define NORMAL_STATUS 0 +#define ERROR_STATUS 1 +#define TRUE 1 +#define FALSE 0 +#define MIN_VALID_CHAR ' ' +#define MAX_VALID_CHAR '\177' +#define PADDING_CHAR ' ' +#define SEC_PER_MIN 60.0 +#define EPSILON 100.0*FLT_EPSILON + +/* Constants for argument parsing */ +#define MAX_VOL_IMGS 128 +#define DEFAULT_NSLICES 15 +#define IMAGE_DIMS 2 +#define MAX_DIMS 4 +#define DEF_ORIENT -1 +#define TRANSVERSE 0 +#define SAGITTAL 1 +#define CORONAL 2 + +/* Constants for mni files */ +#define BLOCK_SIZE 512 +#define MNI_HEADER_SIZE BLOCK_SIZE +#define MNI_FILE_TYPE 1 +#define NIL_FILE_TYPE 2 +#define MNI_STX_XBRAIN 67.0 +#define MNI_STX_YBRAIN 86.0 +#define MNI_STX_ZBRAIN 75.0 +#define MNI_STX_PBRAIN 50.0 +#define MNI_STX_NPIXEL 128 +#define MNI_STX_FACTOR 100.0 +#define MNI_STX_XFOV MNI_STX_NPIXEL*MNI_STX_XBRAIN/MNI_STX_PBRAIN +#define MNI_STX_YFOV MNI_STX_NPIXEL*MNI_STX_YBRAIN/MNI_STX_PBRAIN +#define MNI_STX_ZFOV MNI_STX_NPIXEL*MNI_STX_ZBRAIN/MNI_STX_PBRAIN +#define MNI_STX_XSCALE MNI_STX_XBRAIN/MNI_STX_FACTOR +#define MNI_STX_YSCALE MNI_STX_YBRAIN/MNI_STX_FACTOR +#define MNI_STX_ZSCALE MNI_STX_ZBRAIN/MNI_STX_FACTOR +#define MNI_FOV 256.0 +#define NIL_FOV 250.0 +#define MNI_DIR (1.0) +#define NIL_DIR (-1.0) +#define MNI_VMIN 0.0 +#define MNI_VMAX 255.0 +#define NIL_VMIN 0.0 +#define NIL_VMAX 4095.0 +#define MNI_MRI_SCAN 1 +#define MNI_SCX_SCAN 2 +#define MNI_STX_SCAN 3 +#define MNI_POS_SCAN 4 +#define MNI_TRANSVERSE 100 +#define MNI_CORONAL 200 +#define MNI_SAGITTAL 300 +#define MNI_POSITOME_MASK 0 +#define MNI_CORNER_XSIZE 12 +#define MNI_CORNER_YSIZE 7 +#define MNI_LOC_OFFSET 212 +#define MNI_LOC_NIMAGES 230 +#define MNI_LOC_MATYPE 238 +#define MNI_LOC_SCANNER_ID 200 +#define MNI_LOC_ORIENTATION 204 +#define MNI_LOC_PATNAM 0 +#define MNI_PATNAM_LENGTH 23 +#define MNI_LOC_PATNUM 23 +#define MNI_PATNUM_LENGTH 14 +#define MNI_LOC_ACQDAT 42 +#define MNI_ACQDAT_LENGTH 10 +#define MNI_LOC_ACQTIM 52 +#define MNI_ACQTIM_LENGTH 10 +#define MNI_LOC_ISOTOPE 129 +#define MNI_ISOTOPE_LENGTH 14 +#define MNI_LOC_DOSE 143 +#define MNI_DOSE_LENGTH 14 +#define MNI_LOC_INJTIM 157 +#define MNI_INJTIM_LENGTH 10 +#define MNI_LOC_CORR_MASK 196 +#define MNI_XLOC_QSC 0 +#define MNI_YLOC_QSC 0 +#define MNI_XLOC_ISEA 4 +#define MNI_YLOC_ISEA 2 +#define MNI_XLOC_ZPOS 8 +#define MNI_YLOC_ZPOS 0 +#define MNI_XLOC_TIME 0 +#define MNI_YLOC_TIME 2 +#define MNI_XLOC_TLEN 4 +#define MNI_YLOC_TLEN 3 + +/* Macros */ +#define STR_EQ(s1,s2) (strcmp(s1,s2)==0) + +/* Structure containing information about orientation */ +char *orientation_names[][IMAGE_DIMS+1] = { + {MIzspace, MIyspace, MIxspace}, + {MIxspace, MIzspace, MIyspace}, + {MIyspace, MIzspace, MIxspace}, +}; + +/* Structure containing information about signs */ +char *sign_names[][6] = { + {MI_SIGNED, MI_UNSIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, + {MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, + {MI_SIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED} +}; + +/* Argument variables */ +char *pname; +char *infilename; +char *outfilename; +int clobber = TRUE; +char *dimname[MAX_VAR_DIMS] = {MItime, NULL, NULL, NULL}; +long dimlength[MAX_VAR_DIMS] = {0}; +int dimfixed[MAX_VAR_DIMS] = {FALSE, FALSE, TRUE, TRUE}; +long nframes; +long nslices; +int ndims; +int orientation = DEF_ORIENT; +double field_of_view = 0.0; +double xstep = 0.0; +double ystep = 0.0; + +/* Argument table */ +ArgvInfo argTable[] = { + {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, + "Options to specify image orientation. Default = -transverse."}, + {"-transverse", ARGV_CONSTANT, (char *) TRANSVERSE, (char *) &orientation, + "Transverse images"}, + {"-sagittal", ARGV_CONSTANT, (char *) SAGITTAL, (char *) &orientation, + "Sagittal images"}, + {"-coronal", ARGV_CONSTANT, (char *) CORONAL, (char *) &orientation, + "Coronal images"}, + {NULL, ARGV_HELP, NULL, NULL, + "Options to help specify number of slices and time frames."}, + {"-nslices", ARGV_INT, (char *) 1, (char *) &dimlength[1], + "Number of slices in volume."}, + {"-nframes", ARGV_INT, (char *) 1, (char *) &dimlength[0], + "Number of time frames."}, + {NULL, ARGV_HELP, NULL, NULL, + "Options for writing output file. Default = -clobber."}, + {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, + "Overwrite existing file"}, + {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, + "Don't overwrite existing file"}, + {NULL, ARGV_HELP, NULL, NULL, + "Other options."}, + {"-field_of_view", ARGV_FLOAT, (char *) 1, (char *) &field_of_view, + "Field of view of images (in mm)."}, + {"-xstep", ARGV_FLOAT, (char *) 1, (char *) &xstep, + "Distance between pixels in x dimension (in mm)."}, + {"-ystep", ARGV_FLOAT, (char *) 1, (char *) &ystep, + "Distance between pixels in y dimension (in mm)."}, + {NULL, ARGV_END, NULL, NULL, NULL} +}; + +/* Mni format file information */ +typedef struct { + FILE *fp; + int file_type; + short offset; + short nimages; + int npixels; + int pix_size; + double valid_range[2]; + short scanner_id; + double xstep; + double ystep; + double zstep_scale; + double xstart; + double ystart; + short orientation; + char patient_name[MNI_PATNAM_LENGTH + 1]; + char patient_num[MNI_PATNUM_LENGTH + 1]; + char start_time[MNI_ACQDAT_LENGTH + MNI_ACQTIM_LENGTH + 2]; + char isotope[MNI_ISOTOPE_LENGTH + 1]; + char dose_string[MNI_DOSE_LENGTH + 1]; + double dose; + char dose_units[10]; + char injection_time[MNI_INJTIM_LENGTH + 1]; +} mni_header_type; + +typedef struct { + unsigned char *image; + long npixels; + long image_pix; + int pix_size; + long image_size; + double minimum; + double maximum; + double zposition; + double time; + double time_length; +} mni_image_type; + +/* Function declarations */ +void parse_args(int argc, char *argv[], mni_header_type *mni_header); +void usage_error(char *progname); +int get_mni_header(char *file, mni_header_type *mni_header); +int get_mni_image(mni_header_type *mni_header, mni_image_type *mni_image, + int image_num); +int dblcmp(double dbl1, double dbl2, double epsilon); +void get_vax_short(int nvals, void *vax_value, short *mach_value); +void get_vax_float(int nvals, void *vax_value, float *mach_value); +
new file mode 100755 --- /dev/null +++ b/conversion/scxtominc/define_scx_header.perl @@ -0,0 +1,313 @@ +#! /usr/local/bin/perl +# Script to read in Scanditronix .DRS files (defining scx files) +# and convert them to a .h file containing mnemonics and offsets. +# +# Usage: +# define_scx_header.perl <header_file> <drs file> [<drs file> ...] +# + +# Constants +%types = ( + "B", "byte", + "W", "word", + "L", "long", + "F", "float", + "FS", "short_float", + "S", "string", + "B-", "date", + "B:", "time" +); +%lengths = ( + "byte", 1, + "word", 2, + "long", 4, + "float", 4, + "short_float", 2, + "string", 1, + "date", 1, + "time", 1 +); +@mnem_fields = + ("name", "type", "length", "in_file", "default", "start", "block"); +@block_fields = + ("length", "multiplicity", "parent", "start"); + +# Check arguments +if ($#ARGV<1) { + die "Usage : define_scx_header.perl <header_file> <drs file> ". + "[<drs file> ...]\n"; +} +$header_file = shift; + +# Open the header file and write initial stuff +@drs_list = (); +open(hfile, ">$header_file") || die "$0 : Cannot open file $header_file\n"; +@types = values(%types); +@lengths = (); +foreach $types (@types) {push(@lengths, $lengths{$types});} +print hfile ' +/* Header file for scanditronix file definition */ + +/* Mnemonic types */ +enum scx_mnem_types + {' . join(', ', @types) . '}; +static int scx_mnem_type_size[] = + {' . join(', ', @lengths) . '}; + +/* Block type */ +typedef struct scx_block_struct scx_block_type; +struct scx_block_struct { + int length; + int multiplicity; + scx_block_type *parent; +}; + +/* Mnemonic type */ +typedef struct scx_mnemonic_struct scx_mnemonic_type; +struct scx_mnemonic_struct { + char *name; + scx_mnem_types type; + int length; + int in_file; + long default; + long start; + scx_block_type *block; +}; + +'; + +# Loop through drs files +while ($drs_file = shift) { + +# Initialize the variables needed +undef(%mnemonics); +undef(%blocks); +$nmnems = 0; +$nblocks = 0; +$blk= -1; +@block_list = ($blk); +$position = $next_position = 0; +undef $file_type; +undef $rev; +undef $ext; + +# Open the drs file + if (!open(dfile, $drs_file)) { + print STDERR "Unable to open drs file $drs_file\n"; + next; + } + +# Loop through the lines of the drs file + while (<dfile>) { + +# Look for leading lines + if (! (defined($file_type) && defined($rev) && defined($ext))) { + if (/^\s*TYPE\S*\s+\D*(\d+)/) { + $file_type = $1; + if ($file_type == 0) {die "Illegal file type : $file_type\n";} + } + elsif (/^\s*REV\.\S*\s+\D*(\d+)/) { + $rev = $1; + } + elsif (/^\s*EXT\.\S*\s+(.*)/) { + $ext = $1; + } + } + +# Look for mnemonic lines + elsif (/^\s*[EDM]\s/) { + +# Parse the line + ($code, $mnem, $ftype, $default, $prio, @rest) = split(' '); + next if ($prio eq ""); + $nmnems++; + +# Get the mnemonic name + $mnemonics{$nmnems-1, "name"} = $mnem; + +# Is the mnemonic stored in the file + $mnemonics{$nmnems-1, "in_file"} = ($code ne "E"); + +# Get data type and length (if there is a - or : on the end, and +# the type is B, then we have a date or time) + if ( $ftype !~ /^(\d*)(B|W|L|F|FS|S|B-|B:)$/ ) {next;} + if ($1 ne "") {$mnemonics{$nmnems-1, "length"} = $1;} + else {$mnemonics{$nmnems-1, "length"} = 1;} + $mnemonics{$nmnems-1, "type"} = $types{$2}; + +# Get pre-defined values + if ($default !~ /^=(.*)$/) {next;} + $mnemonics{$nmnems-1, "default"} = $1; + +# Get block + $mnemonics{$nmnems-1, "block"} = $blk; + +# Increment position counters + if ($code ne "M") + {$position = $next_position;} + if ($code ne "E") { + $next_position = $position + + $mnemonics{$nmnems-1, "length"} * + $lengths{$mnemonics{$nmnems-1, "type"}}; + } + +# Get position of first value + if ($mnemonics{$nmnems-1, "in_file"}) + {$mnemonics{$nmnems-1, "start"} = $position;} + else + {$mnemonics{$nmnems-1, "start"} = -1;} + +# Check for file type matching first word of file + if (($position == 0) && ($code eq 'D') && + ($file_type != $mnemonics{$nmnems-1, "default"})) { + die "Type $file_type does not match first word of file (", + $mnemonics{$nmnems-1, "default"},")\n"; + } + + } + +# Look for reserved space lines + elsif (/^\s*R\s/) { + if (! /^\s*R\s+(\d+)\s+.*$/) {next;} + $next_position += $1; + } + +# Look for block definitions + elsif (/^\s*([\(\)])-/) { + +# Look for block open or close + $open = ($1 eq "("); + if ($open) { + +# Parse block open line + if (!/^\s*\(-+LEN=([^-]+)-+MULT=([^-]+)-+/) + {die "Error parsing block open\n";} + $length = $1; + $mult = $2; + if (($mult !~ /^\d+$/) || ($mult < 1)) + {die "Error in block multiplicity\n";} + if ($length !~ /^\d+$/) {$length = -1;} + if (($length < 0) && ($mult>1)) + {die "Error in block length\n";} + +# Add new block + $nblocks++; + $blk = $nblocks-1; + $blocks{$blk, "length"} = $length; + $blocks{$blk, "multiplicity"} = $mult; + $blocks{$blk, "parent"} = $block_list[$#block_list]; + $blocks{$blk, "start"} = $next_position; + push(@block_list, $blk); + + } + +# Otherwise, we have a close block + else { + +# Check for an open block + if (($nblocks<=0) || ($#block_list<=0)) + {die "Unbalanced block bounds\n";} + +# Check the block length + $block_length = $next_position - $blocks{$blk, "start"}; + if ($blocks{$blk,"length"} >= 0) { + if ($blocks{$blk,"length"} != $block_length) { + die "Actual block length not equal to given block length\n"; + } + } + else { + $blocks{$blk,"length"} = $block_length; + } + +# Move up the pointer (only changes if multiplicity is > 1) + $next_position += $blocks{$blk, "length"} * + ($blocks{$blk, "multiplicity"} - 1); + +# Pop the block + pop(@block_list); + $blk = $block_list[$#block_list]; + + } + + } # End of block + + } # End of read loop + +# Add drs file to list of files + ($drs_id = "pc_".$file_type."_r_".$rev) =~ tr/\W/_/; + if (grep(/$drs_id/, @drs_list)) { + die "Two files with the same type and revision : $drs_id\n"; + } + push(@drs_list, $drs_id); + + $block_array = 'drs_block_'.$drs_id; + $mnem_array = 'drs_mnems_'.$drs_id; + + $drs_file_types{$drs_id} = $file_type; + $drs_blocks{$drs_id} = $block_array; + $drs_mnemonics{$drs_id} = $mnem_array; + +# Write out block table for file + print hfile ' +/* Blocks for drs file with id '.$drs_id.' */ +static scx_block_type '.$block_array.'[] = { +'; + + foreach $blk (0..$nblocks-1) { + $the_block = $blocks{$blk, "parent"}; + if ($the_block < 0) {$the_block = 'NULL';} + else {$the_block = '&('.$block_array.'['.$the_block.'])';} + print hfile " " . + $blocks{$blk, "length"} . ', ' . + $blocks{$blk, "multiplicity"} . ', ' . $the_block . ",\n"; + } + print hfile " 0, 0, NULL\n};\n\n"; + +# Write out mnemonic table for file + print hfile ' +/* Mnemonics for drs file with id '.$drs_id.' */ +static scx_mnemonic_type '.$mnem_array.'[] = { +'; + + foreach $mnem (0..$nmnems-1) { + + $the_block = $mnemonics{$mnem, "block"}; + if ($the_block < 0) {$the_block = 'NULL';} + else {$the_block = '&('.$block_array.'['.$the_block.'])';} + + $the_default = $mnemonics{$mnem, "default"}; + if ($the_default eq "") {$the_default = "0";} + elsif ($mnemonics{$mnem, "type"} eq "string") + {$the_default = '(long) "'.$the_default.'"';} + + print hfile ' "' . + $mnemonics{$mnem, "name"} . '", ' . + $mnemonics{$mnem, "type"} . ', ' . + $mnemonics{$mnem, "length"} . ', ' . + $mnemonics{$mnem, "in_file"} . ', ' . + $the_default . ', ' . + $mnemonics{$mnem, "start"} . ', ' . + $the_block . ",\n"; + } + print hfile " NULL, byte, 0, 0, 0, NULL\n};\n\n"; + +} # End of loop over files + +# Write out list of file types +print hfile ' +/* List of drs files and types */ + +static struct { + int file_type; + scx_block_type *block_list; + scx_mnemonic_type *mnemonic_list; +} scx_file_types[] = { +'; + +foreach $drs_id (@drs_list) { + print hfile " $drs_file_types{$drs_id}, " . + "$drs_blocks{$drs_id}, " . + "$drs_mnemonics{$drs_id},\n"; +} + + print hfile " 0, NULL, NULL\n};\n";
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/pc5r1.drs @@ -0,0 +1,148 @@ + + TYPE: PC-5 + REV.: 1 + EXT.: .DAT + + Definition of the file header structure for + the PC4096-15WB positron camera data file. + +(---LEN=FHS--MULT=1----------------------------------------------------- +E FHS B =4 P0F ; File header size (Records) +E REC W =512 P0F ; Record size + +D TYP W =5 P0F ; Type of equipment +D NCS B =15 P0F ; Number of slices +D SITE 4S =KS P0A ; Installation site +D REV W =1 P0F ; Revision number + +D NDET W =256 P0F ; Number of detectors per ring +D NPRO W =256 P0F ; Number of projections per slice +D NMEM W =48 P0F ; Number of members in stat. proj. +D NWOB B =5 P0F ; Number of wobble bins per member +D CDI FS =6.5 P0A ; Cross-section distance (mm) +D CSZ FS =6.0 P0A ; Cross-section thickness (p) (mm) +D CSX FS =6.0 P0A ; Cross-section thickness (x) (mm) + +D RID 10S = P0A ; Run id (user def) +D RIN L = P02 ; Identification number +D ETN W = P02 ; ET-number (user def) +D PNM 24S = P02 ; Patient name +D BRN L = P02 ; Birth number +D ASS 22S = P02 ; Responsible technician +D DOC 22S = P02 ; Responsible doctor +D DAT 3B- = P0A ; Measurement date +M DATY B = P0A ; Year (B) +D DATM B = P0A ; Month (B) +D DATD B = P0A ; Day (B) +D TIM 4B: = P0A ; Measurement time +M TIMH B = P0A ; Hour +D TIMM B = P0A ; Minutes +D TIMS B = P0A ; Seconds +D TIHU B = P0A ; Hundredths of seconds +D QES 12S = P02 ; Question +D POR 4S = P02 ; Patient orientation +D PAN W = P02 ; Patient angle +D CLV FS = P0A ; Cross-section level (mm+OM) +D ZDI FS = P0A ; Z displacement (mm) +D NRV W = P02 ; Number of revolutions/min +D NME W = P02 ; Number of measurements +D MTM F = P02 ; Measuring time +D RPRT FS = P02 ; Time in s. between rates-file reports +D ISO 6S = P02 ; Isotope (eg GA-68) +D HALF F = P02 ; Halftime of isotope (user supplied) +D CAR 8S = P02 ; Carrier (eg EDTA) +D ACT F = P02 ; Injected activity +D INP 4S = P02 ; Injection place +D INT 4S = P02 ; Injection type +D ITM 3B: = P02 ; Injection time +M ITMH B = P02 ; Hour (B) +D ITMM B = P02 ; Minute (B) +D ITMS B = P02 ; Second (B) +D COL 1S = P0A ; Collimator type (' '=standard) +D SAMP B = P0A ; Sampling mode (0=stat, X=bins) +D DTYP B = P0A ; Data type (0=word, 1=byte) +D FOV B = P02 ; Field-of-view type +D PRJL W = P0A ; Projection length in members +D TILT FS = P0A ; Gantry tilt angle +D SLEW FS = P0A ; Gantry slew angle +D ELV W = P0A ; Energy level (keV) +D TIW FS = P0A ; Time window (ns) +D COM 20S = P02 ; Comments +D STYP B = P0A ; Scan type (0=em, 1=tr, 2=bl, 3=norm) +D BLAN L = P02 ; Blank scan number +D TRAN L = P02 ; Transmission scan number + +D PAR B = P0A ; Parameter file number +D NORM W = P02 ; Norm file number + +D DPR B = P0A ; Data present in file (1=present) +D TNM 8S = P02 ; Tape name (user def) + +D FERR L = P0A ; FIFO errors +D FLOS F = P0A ; FIFO loss rate +D INVA F = P0A ; Invalid count rate +D TRAT F = P0A ; Total count rate + +D TAC W = P0A ; Type of attenuation corr. +D IMFM W = P0A ; Image format (eg 128) +D IMTP 10S = P02 ; Image type (' '=activity) +D IMUN 10S = P02 ; Image scale unit (eg nCi/cc) +D PXS FS = P0A ; Pixel size (mm/pixel) +D FFN 4S = P0A ; Filter function (eg 'BOHM') +D FWD FS = P0A ; Filter width (mm) + +D SLOT W = P0F ; Slot on DAP disk +D CNTX 10S = P0A ; Context of study (user def) +D AGE B = P0A ; Patient's age +D SEX 1S = P0A ; Patient's sex +D MAX W = P02 ; Repr. of highest pixel in image + +R 34 + +(---LEN=4--MULT=8------------------------------------------------------- +D SING F = P0A ; Singles count rate per detector +)----------------------------------------------------------------------- + +(---LEN=4--MULT=8------------------------------------------------------- +D XRAT F = P0A ; Physiological input count rate +)----------------------------------------------------------------------- + + +(---LEN=18--MULT=5----------------------------------------------------- +D USR F = P02 ; User definable reals +D USI L = P02 ; User definable longwords +D USC 10S = P02 ; User definable character strings +)----------------------------------------------------------------------- + +(---LEN=18--MULT=1----------------------------------------------------- +D CYCL F = P0F ; Gate cycle time low limit +D CYCH F = P0F ; Gate cycle time high limit +D GTLL FS = P0F ; Gate low limit ( in % of cycle ) +D GTLH FS = P0F ; Gate high limit ( in % of cycle ) +D GTNR B = P0F ; Gate number +D FRNR W = P0F ; Time frame number +D DCY FS = P0F ; MTM duty cycle ( in % ) +D NGAT B = P0F ; Number of gating bins +)----------------------------------------------------------------------- + + (---LEN=87--MULT=15---------------------------------------------------- +D STOT F = P0A ; Total number of counts per slice +D CAL F = P02 ; Slice calibration factors + +D MAG F = P02 ; Image magnification +D SPOS B = P02 ; Slice image position in file +D SCA F = P02 ; Scatter per slice +D RAN F = P02 ; Randoms per slice +D DTC FS = P02 ; Dead time correction factor + + (---LEN=2--MULT=32----------------------------------------------------- +D PERX B = P02 ; Perimeter point x-coordinate +D PERY B = P02 ; Perimeter point y-coordinate + )-------------------------------------------------------------------- + )--------------------------------------------------------------------- + +(---LEN=4--MULT=15---------------------------------------------------- +D OFFS F = P02 ;Offset in image +)----------------------------------------------------------------------- + +)-----------------------------------------------------------------------
new file mode 100644 --- /dev/null +++ b/progs/Proglib/Makefile @@ -0,0 +1,62 @@ +# -------------------------------------------------------------------- +# +# MINC Makefile +# + +# Object names +OBJS = ParseArgv.o vax_conversions.o +PROG_LIB = mincprog +CDEFINES = # cpp defines +OPT = -g# compiler options +INCLUDES = -I. # include directories + +# Options for creating library +RM = rm +RM_FLAGS = -f +AR = ar +AR_FLAGS = -r +RANLIB = true + +# -------------------------------------------------------------------- + +CFLAGS = $(CDEFINES) $(INCLUDES) $(OPT)# CFLAGS and LINTFLAGS should +LINTFLAGS = $(CDEFINES) $(INCLUDES)# be same, except for -g/-O + +CC_PROG_LIB= lib$(PROG_LIB).a# library for objs +LINT_OBJS = $(OBJS:.o=.ln) +LINT_PROG_LIB = llib-l$(PROG_LIB).ln# + +# -------------------------------------------------------------------- + +.SUFFIXES: .ln# tell make to watch for .ln's + +default: $(CC_PROG_LIB) + +#Dependency on Makefile +$(OBJS) $(LINT_OBJS) : Makefile + +all: $(CC_PROG_LIB) lint + +.c.ln:# defines the rule for creating .ln + lint $(LINTFLAGS) -c $< -o $@ + +.c.o:# defines the rule for creating .o + $(CC) $(CFLAGS) -c $< -o $@ + +# How to create library +$(CC_PROG_LIB): $(OBJS) + $(RM) $(RM_FLAGS) $(CC_PROG_LIB) + $(AR) $(AR_FLAGS) $(CC_PROG_LIB) $(OBJS) + $(RANLIB) $(CC_PROG_LIB) + +# Lint +lint : $(LINT_PROG_LIB) + +# How to create lint library +$(LINT_PROG_LIB) : $(LINT_OBJS) + lint -o $(PROG_LIB) -x -u $(LINTFLAGS) $(LINT_OBJS) + +# Remove all derived files in this directory +clean: + \rm -f $(OBJS) $(LINT_OBJS) +
new file mode 100644 --- /dev/null +++ b/progs/Proglib/ParseArgv.c @@ -0,0 +1,418 @@ +/* + * ParseArgv.c -- + * + * This file contains a procedure that handles table-based + * argv-argc parsing. + * + * Copyright 1990 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * + * This file has been modified to not rely on tcl, tk or X11. + * Based on tkArgv.c from tk2.3 : +static char rcsid[] = "$Header: /private-cvsroot/minc/progs/Proglib/Attic/ParseArgv.c,v 1.1 1993-01-08 09:47:37 neelin Exp $ SPRITE (Berkeley)"; + * + * Modifications by Peter Neelin (November 27, 1992) + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ParseArgv.h> + +#define TRUE 1 +#define FALSE 0 + +/* + * Default table of argument descriptors. These are normally available + * in every application. + */ + +static ArgvInfo defaultTable[] = { + {"-help", ARGV_HELP, (char *) NULL, (char *) NULL, + "Print summary of command-line options and abort"}, + {NULL, ARGV_END, (char *) NULL, (char *) NULL, + (char *) NULL} +}; + +/* + * Forward declarations for procedures defined in this file: + */ + +static void PrintUsage _ANSI_ARGS_((ArgvInfo *argTable, int flags)); + +/* + *---------------------------------------------------------------------- + * + * ParseArgv -- + * + * Process an argv array according to a table of expected + * command-line options. See the manual page for more details. + * + * Results: + * The return value is a Boolean value with TRUE indicating an error. + * If an error occurs then an error message is printed on stderr. + * Under normal conditions, both *argcPtr and *argv are modified + * to return the arguments that couldn't be processed here (they + * didn't match the option table, or followed an ARGV_REST + * argument). + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +int +ParseArgv(argcPtr, argv, argTable, flags) + int *argcPtr; /* Number of arguments in argv. Modified + * to hold # args left in argv at end. */ + char **argv; /* Array of arguments. Modified to hold + * those that couldn't be processed here. */ + ArgvInfo *argTable; /* Array of option descriptions */ + int flags; /* Or'ed combination of various flag bits, + * such as ARGV_NO_DEFAULTS. */ +{ + register ArgvInfo *infoPtr; + /* Pointer to the current entry in the + * table of argument descriptions. */ + ArgvInfo *matchPtr; /* Descriptor that matches current argument. */ + char *curArg; /* Current argument */ + register char c; /* Second character of current arg (used for + * quick check for matching; use 2nd char. + * because first char. will almost always + * be '-'). */ + int srcIndex; /* Location from which to read next argument + * from argv. */ + int dstIndex; /* Index into argv to which next unused + * argument should be copied (never greater + * than srcIndex). */ + int argc; /* # arguments in argv still to process. */ + int length; /* Number of characters in current argument. */ + int nargs; /* Number of following arguments to get. */ + int i; + +/* Macro to optionally print errors */ +#define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf + + if (flags & ARGV_DONT_SKIP_FIRST_ARG) { + srcIndex = dstIndex = 0; + argc = *argcPtr; + } else { + srcIndex = dstIndex = 1; + argc = *argcPtr-1; + } + + while (argc > 0) { + curArg = argv[srcIndex]; + srcIndex++; + argc--; + c = curArg[1]; + length = strlen(curArg); + + /* + * Loop throught the argument descriptors searching for one with + * the matching key string. If found, leave a pointer to it in + * matchPtr. + */ + + matchPtr = NULL; + for (i = 0; i < 2; i++) { + if (i == 0) { + infoPtr = argTable; + } else { + infoPtr = defaultTable; + } + for (; infoPtr->type != ARGV_END; infoPtr++) { + if (infoPtr->key == NULL) { + continue; + } + if ((infoPtr->key[1] != c) + || (strncmp(infoPtr->key, curArg, length) != 0)) { + continue; + } + if (infoPtr->key[length] == 0) { + matchPtr = infoPtr; + goto gotMatch; + } + if (flags & ARGV_NO_ABBREV) { + continue; + } + if (matchPtr != NULL) { + FPRINTF(stderr, "ambiguous option \"%s\"\n", curArg); + return TRUE; + } + matchPtr = infoPtr; + } + } + if (matchPtr == NULL) { + + /* + * Unrecognized argument. Just copy it down, unless the caller + * prefers an error to be registered. + */ + + if (flags & ARGV_NO_LEFTOVERS) { + FPRINTF(stderr, "unrecognized argument \"%s\"\n", curArg); + } + argv[dstIndex] = curArg; + dstIndex++; + continue; + } + + /* + * Take the appropriate action based on the option type + */ + gotMatch: + infoPtr = matchPtr; + switch (infoPtr->type) { + case ARGV_CONSTANT: + *((int *) infoPtr->dst) = (int) infoPtr->src; + break; + case ARGV_INT: + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + for (i=0; i<nargs; i++) { + if (argc == 0) { + goto missingArg; + } else { + char *endPtr; + + *(((int *) infoPtr->dst)+i) = + strtol(argv[srcIndex], &endPtr, 0); + if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { + FPRINTF(stderr, + "expected integer argument for \"%s\" but got \"%s\"", + infoPtr->key, argv[srcIndex]); + return TRUE; + } + srcIndex++; + argc--; + } + } + break; + case ARGV_STRING: + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + for (i=0; i<nargs; i++) { + if (argc == 0) { + goto missingArg; + } else { + *(((char **)infoPtr->dst)+i) = argv[srcIndex]; + srcIndex++; + argc--; + } + } + break; + case ARGV_REST: + *((int *) infoPtr->dst) = dstIndex; + goto argsDone; + case ARGV_FLOAT: + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + for (i=0; i<nargs; i++) { + if (argc == 0) { + goto missingArg; + } else { + char *endPtr; + + *(((double *) infoPtr->dst)+i) = + strtod(argv[srcIndex], &endPtr); + if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { + FPRINTF(stderr, + "expected floating-point argument for \"%s\" but got\"%s\"\n", + infoPtr->key, argv[srcIndex]); + return TRUE; + } + srcIndex++; + argc--; + } + } + break; + case ARGV_FUNC: { + int (*handlerProc)(); + + handlerProc = (int (*)())infoPtr->src; + + if ((*handlerProc)(infoPtr->dst, infoPtr->key, + argv[srcIndex])) { + srcIndex += 1; + argc -= 1; + } + break; + } + case ARGV_GENFUNC: { + int (*handlerProc)(); + + handlerProc = (int (*)())infoPtr->src; + + argc = (*handlerProc)(infoPtr->dst, infoPtr->key, + argc, argv+srcIndex); + if (argc < 0) { + return TRUE; + } + break; + } + case ARGV_HELP: + PrintUsage (argTable, flags); + return TRUE; + default: + FPRINTF(stderr, "bad argument type %d in ArgvInfo", + infoPtr->type); + return TRUE; + } + } + + /* + * If we broke out of the loop because of an OPT_REST argument, + * copy the remaining arguments down. + */ + + argsDone: + while (argc) { + argv[dstIndex] = argv[srcIndex]; + srcIndex++; + dstIndex++; + argc--; + } + argv[dstIndex] = (char *) NULL; + *argcPtr = dstIndex; + return FALSE; + + missingArg: + FPRINTF(stderr, "\"%s\" option requires an additional argument\n", curArg); + return TRUE; +} + +/* + *---------------------------------------------------------------------- + * + * PrintUsage -- + * + * Generate a help string describing command-line options. + * + * Results: + * Prints on stderr (unless ARGV_NO_PRINT is specified in flags) + * a help string describing all the options in argTable, plus all those + * in the default table unless ARGV_NO_DEFAULTS is + * specified in flags. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +PrintUsage(argTable, flags) + ArgvInfo *argTable; /* Array of command-specific argument + * descriptions. */ + int flags; /* If the ARGV_NO_DEFAULTS bit is set + * in this word, then don't generate + * information for default options. */ +{ + register ArgvInfo *infoPtr; + int width, i, j, numSpaces; +#define NUM_SPACES 20 + static char spaces[] = " "; +/* char tmp[30]; */ + int nargs; + +/* Macro to optionally print errors */ +#define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf + + /* + * First, compute the width of the widest option key, so that we + * can make everything line up. + */ + + width = 4; + for (i = 0; i < 2; i++) { + for (infoPtr = i ? defaultTable : argTable; + infoPtr->type != ARGV_END; infoPtr++) { + int length; + if (infoPtr->key == NULL) { + continue; + } + length = strlen(infoPtr->key); + if (length > width) { + width = length; + } + } + } + + FPRINTF(stderr, "Command-specific options:"); + for (i = 0; ; i++) { + for (infoPtr = i ? defaultTable : argTable; + infoPtr->type != ARGV_END; infoPtr++) { + if ((infoPtr->type == ARGV_HELP) && (infoPtr->key == NULL)) { + FPRINTF(stderr, "\n%s", infoPtr->help); + continue; + } + FPRINTF(stderr, "\n %s:", infoPtr->key); + numSpaces = width + 1 - strlen(infoPtr->key); + while (numSpaces > 0) { + if (numSpaces >= NUM_SPACES) { + FPRINTF(stderr, "%s",spaces); + } else { + FPRINTF(stderr, "%s",spaces+NUM_SPACES-numSpaces); + } + numSpaces -= NUM_SPACES; + } + FPRINTF(stderr, "%s",infoPtr->help); + switch (infoPtr->type) { + case ARGV_INT: { + FPRINTF(stderr, "\n\t\tDefault value:"); + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + for (j=0; j<nargs; j++) { + FPRINTF(stderr, " %d", *(((int *) infoPtr->dst)+j)); + } + break; + } + case ARGV_FLOAT: { + FPRINTF(stderr, "\n\t\tDefault value:"); + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + for (j=0; j<nargs; j++) { + FPRINTF(stderr, " %lg", *(((double *) infoPtr->dst)+j)); + } + break; + } + case ARGV_STRING: { + char *string; + + nargs = (int) infoPtr->src; + if (nargs<1) nargs=1; + string = *((char **) infoPtr->dst); + if ((nargs==1) && (string == NULL)) break; + for (j=0; j<nargs; j++) { + string = *(((char **) infoPtr->dst)+j); + if (string != NULL) { + FPRINTF(stderr, " \"%s\"", string); + } + else { + FPRINTF(stderr, " \"%s\"", string); + } + } + + break; + } + default: { + break; + } + } + } + + if ((flags & ARGV_NO_DEFAULTS) || (i > 0)) { + break; + } + FPRINTF(stderr, "\nGeneric options for all commands:"); + } + + FPRINTF(stderr, "\n"); +}
new file mode 100644 --- /dev/null +++ b/progs/Proglib/ParseArgv.h @@ -0,0 +1,83 @@ +/* + * ParseArgv.h -- + * + * Declarations for Tk-related things that are visible + * outside of the Tk module itself. + * + * Copyright 1989-1992 Regents of the University of California. + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * This file has been modified to be used only for argv parsing without + * reference to tk, tcl or X11. Base on tk.h from tk2.3 + * $Header: /private-cvsroot/minc/progs/Proglib/Attic/ParseArgv.h,v 1.1 1993-01-08 09:48:00 neelin Exp $ SPRITE (Berkeley) + */ + +/* + * Definitions that allow this header file to be used either with or + * without ANSI C features like function prototypes. + */ + +#undef _ANSI_ARGS_ +#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) +# define _ANSI_ARGS_(x) x +#else +# define _ANSI_ARGS_(x) () +#endif + +/* + * Structure used to specify how to handle argv options. + */ + +typedef struct { + char *key; /* The key string that flags the option in the + * argv array. */ + int type; /* Indicates option type; see below. */ + char *src; /* Value to be used in setting dst; usage + * depends on type. */ + char *dst; /* Address of value to be modified; usage + * depends on type. */ + char *help; /* Documentation message describing this option. */ +} ArgvInfo; + +/* + * Legal values for the type field of a ArgvInfo: see the user + * documentation for details. + */ + +#define ARGV_CONSTANT 15 +#define ARGV_INT 16 +#define ARGV_STRING 17 +#define ARGV_REST 19 +#define ARGV_FLOAT 20 +#define ARGV_FUNC 21 +#define ARGV_GENFUNC 22 +#define ARGV_HELP 23 +#define ARGV_END 27 + +/* + * Flag bits for passing to ParseArgv: + */ + +#define ARGV_NO_DEFAULTS 0x1 +#define ARGV_NO_LEFTOVERS 0x2 +#define ARGV_NO_ABBREV 0x4 +#define ARGV_DONT_SKIP_FIRST_ARG 0x8 +#define ARGV_NO_PRINT 0x16 + + +/* + *-------------------------------------------------------------- + * + * Exported procedures and variables. + * + *-------------------------------------------------------------- + */ +extern int ParseArgv _ANSI_ARGS_((int *argcPtr, char **argv, + ArgvInfo *argTable, int flags)); +
new file mode 100644 --- /dev/null +++ b/progs/Proglib/vax_conversions.c @@ -0,0 +1,92 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : vax_conversions.c +@DESCRIPTION: File containing routines to convert machine values to vax format + values. +@METHOD : +@CREATED : December 10, 1992 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +#ifndef lint +static char rcsid[]="$Header: /private-cvsroot/minc/progs/Proglib/vax_conversions.c,v 1.1 1993-01-08 09:47:46 neelin Exp $"; +#endif + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_vax_short +@INPUT : nvals - number of values to convert + vax_value - pointer to array of shorts in vax format +@OUTPUT : mach_value - pointer to array of shorts in current machine format +@RETURNS : (nothing) +@DESCRIPTION: Converts vax short integers to short integers in the format of + the current machine. +@METHOD : +@GLOBALS : (none) +@CALLS : memcpy +@CREATED : December 10, 1992. +@MODIFIED : +---------------------------------------------------------------------------- */ +void get_vax_short(int nvals, void *vax_value, short *mach_value) +{ + int i; + char *ptr1, *ptr2, v0, v1; + +#ifdef vax + memcpy((void *) mach_value, vax_value, nvals*sizeof(short)); +#else + ptr1 = (char *) vax_value; + ptr2 = (char *) mach_value; + for (i=0; i<nvals; i++) { + v0 = ptr1[1]; + v1 = ptr1[0]; + ptr2[0] = v0; + ptr2[1] = v1; + ptr1 += sizeof(mach_value[0]); + ptr2 += sizeof(mach_value[0]); + } +#endif + + return; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_vax_float +@INPUT : nvals - number of values to convert + vax_value - pointer to array of floats in vax format +@OUTPUT : mach_value - pointer to array of floats in current machine format +@RETURNS : (nothing) +@DESCRIPTION: Converts vax floats to floats in the format of + the current machine. +@METHOD : +@GLOBALS : (none) +@CALLS : memcpy +@CREATED : December 10, 1992. +@MODIFIED : +---------------------------------------------------------------------------- */ +void get_vax_float(int nvals, void *vax_value, float *mach_value) +{ + int i; + char *ptr1, *ptr2, v0, v1; + +#ifdef vax + memcpy((void *) mach_value, vax_value, nvals*sizeof(short)); +#else + ptr1 = (char *) vax_value; + ptr2 = (char *) mach_value; + for (i=0; i<nvals; i++) { + v0 = ptr1[1]; + v1 = ptr1[0]; + ptr2[0] = v0; + ptr2[1] = v1; + v0 = ptr1[3]; + v1 = ptr1[2]; + ptr2[2] = v0; + ptr2[3] = v1; + mach_value[i] /= 4.0; + ptr1 += sizeof(mach_value[0]); + ptr2 += sizeof(mach_value[0]); + } +#endif + + return; +} +
new file mode 100644 --- /dev/null +++ b/progs/rawtominc/Makefile @@ -0,0 +1,70 @@ +# -------------------------------------------------------------------- +# +# MINC Makefile +# + +# Executable names +PROGS = rawtominc +HEADERS = +PROG_LIB_DIR = ../proglib +PROG_LIB = mincprog +LIB_DIR = ../../src# directory for library +LIBRARY = minc# library +CDEFINES = -DDEBUG# cpp defines +OPT = -g# compiler options +LDOPT = -L/usr/local/lib -lnetcdf -lsun -lm -lgl_s -lm -lc_s# ld options +INCLUDES = -I. -I../proglib -I../../src -I/usr/local/include + +# For cleaning up +RM = rm +RM_FLAGS = -f + +# -------------------------------------------------------------------- + +CFLAGS = $(CDEFINES) $(INCLUDES) $(OPT)# CFLAGS and LINTFLAGS should +LINTFLAGS = $(CDEFINES) $(INCLUDES)# be same, except for -g/-O + +PROG_OBJ = $(PROGS:=.o)# list of objects +CC_LIB = lib$(LIBRARY).a# C library file +CC_PROG_LIB= $(PROG_LIB_DIR)/lib$(PROG_LIB).a# library for prog objs +LINT_LIST = $(PROG_OBJ:.o=.ln) +LINT_LIST_EXE = $(LINT_LIST:.ln=.)# list of executable names to lint +LINT_LIB = llib-l$(LIBRARY).ln# lint library file +LINT_PROG_LIB = $(PROG_LIB_DIR)/llib-l$(PROG_LIB).ln# + +# -------------------------------------------------------------------- + +.SUFFIXES: .ln# tell make to watch for .ln's + +default: $(PROGS) + +#Dependency on Makefile +$(PROG_OBJ) $(LINT_OBJS) : Makefile + +all: $(PROGS) lint + +.c.ln:# defines the rule for creating .ln + lint $(LINTFLAGS) -c $< -o $@ + +.c.o:# defines the rule for creating .o + $(CC) $(CFLAGS) -c $< -o $@ + +#Dependency of .o and .ln on .h +$(PROG_OBJ) : $(HEADERS) + +$(LINT_LIST) : $(HEADERS) + +# How to make executables +$(PROGS) : $$@.o $(CC_PROG_LIB) $(LIB_DIR)/$(CC_LIB) + $(CC) $@.o -o $@ $(CC_PROG_LIB) -L$(LIB_DIR) -l$(LIBRARY) $(LDOPT) + +# how to lint the executable source +lint: $(LINT_LIST_EXE) + +$(LINT_LIST_EXE) : $$@ln $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + lint -u $(LINTFLAGS) $@ln $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + +# Remove all derived files in this directory +clean: + $(RM) $(RM_FLAGS) $(LINT_LIST) $(PROGS) $(PROG_OBJ) +
new file mode 100644 --- /dev/null +++ b/progs/rawtominc/rawtominc.c @@ -0,0 +1,413 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : rawtominc +@INPUT : argc, argv - command line arguments +@OUTPUT : (none) +@RETURNS : error status +@DESCRIPTION: Converts a raw volume of data values (read from standard input) + to a minc format file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : September 25, 1992 (Peter Neelin) +@MODIFIED : December 2, 1992 (P.N.) + - changed to parse argv with ParseArgv +---------------------------------------------------------------------------- */ + +#ifndef lint +static char rcsid[]="$Header: /private-cvsroot/minc/progs/rawtominc/rawtominc.c,v 1.1 1993-01-08 09:45:04 neelin Exp $"; +#endif + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <minc.h> +#include <float.h> +#include <ParseArgv.h> + +/* Some constants */ + +#define NORMAL_STATUS 0 +#define ERROR_STATUS 1 +#define MIN_DIMS 2 +#define MAX_DIMS 4 +#define TRANSVERSE 0 +#define SAGITTAL 1 +#define CORONAL 2 +#define TIME_FAST 3 +#define DEF_TYPE 0 +#define DEF_SIGN 0 +#define SIGNED 1 +#define UNSIGNED 2 +#define TRUE 1 +#define FALSE 0 + +/* Macros */ +#define STR_EQ(s1,s2) (strcmp(s1,s2)==0) + +/* Function declarations */ +void parse_args(int argc, char *argv[]); +void usage_error(char *pname); + +/* Structure containing information about orientation */ +char *orientation_names[][MAX_DIMS] = { + {MItime, MIzspace, MIyspace, MIxspace}, + {MItime, MIxspace, MIzspace, MIyspace}, + {MItime, MIyspace, MIzspace, MIxspace}, + {MIzspace, MItime, MIyspace, MIxspace} +}; + +/* Structure containing information about signs */ +char *sign_names[][6] = { + {MI_SIGNED, MI_UNSIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, + {MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED, MI_SIGNED}, + {MI_SIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED, MI_UNSIGNED} +}; + +/* Argument variables */ +char *pname; +char *filename; +int clobber=TRUE; +char *dimname[MAX_VAR_DIMS]; +long dimlength[MAX_VAR_DIMS]; +int ndims; +int orientation = TRANSVERSE; +nc_type type = NC_BYTE; +int signtype = DEF_SIGN; +char *sign; +double valid_range[2] = {0.0, -1.0}; +int vrange_set; +nc_type otype = DEF_TYPE; +int osigntype = DEF_SIGN; +char *osign; +double ovalid_range[2] = {0.0, -1.0}; +int ovrange_set; + +/* Argument table */ +ArgvInfo argTable[] = { + {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, + "Options to specify input dimension order (from slowest to fastest)."}, + {NULL, ARGV_HELP, (char *) NULL, (char *) NULL, + " Default = -transverse."}, + {"-transverse", ARGV_CONSTANT, (char *) TRANSVERSE, (char *) &orientation, + "Transverse images : [[time] z] y x"}, + {"-sagittal", ARGV_CONSTANT, (char *) SAGITTAL, (char *) &orientation, + "Sagittal images : [[time] x] z y"}, + {"-coronal", ARGV_CONSTANT, (char *) CORONAL, (char *) &orientation, + "Coronal images : [[time] y] z x"}, + {"-time", ARGV_CONSTANT, (char *) TIME_FAST, (char *) &orientation, + "Time ordered images : [[z] time] y x"}, + {NULL, ARGV_HELP, NULL, NULL, + "Options to specify input data type. Default = -byte."}, + {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &type, + "Byte values"}, + {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &type, + "Short integer values"}, + {"-long", ARGV_CONSTANT, (char *) NC_LONG, (char *) &type, + "Long integer values"}, + {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &type, + "Single-precision floating point values"}, + {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &type, + "Double-precision floating point values"}, + {NULL, ARGV_HELP, NULL, NULL, + "Options for sign of input data. Default = -signed (-unsigned for byte)."}, + {"-signed", ARGV_CONSTANT, (char *) SIGNED, (char *) &signtype, + "Signed values"}, + {"-unsigned", ARGV_CONSTANT, (char *) UNSIGNED, (char *) &signtype, + "Unsigned values"}, + {NULL, ARGV_HELP, NULL, NULL, + "Other input value options."}, + {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range, + "Valid range of input values (default = full range)."}, + {NULL, ARGV_HELP, NULL, NULL, + "Options for type of output minc data. Default = input data type"}, + {"-obyte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &otype, + "Byte values"}, + {"-oshort", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &otype, + "Short integer values"}, + {"-olong", ARGV_CONSTANT, (char *) NC_LONG, (char *) &otype, + "Long integer values"}, + {"-ofloat", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &otype, + "Single-precision floating point values"}, + {"-odouble", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &otype, + "Double precision floating point values"}, + {NULL, ARGV_HELP, NULL, NULL, + "Options for sign of output minc data."}, + {NULL, ARGV_HELP, NULL, NULL, + " Default = -signed (-unsigned for byte data)"}, + {"-osigned", ARGV_CONSTANT, (char *) SIGNED, (char *) &osigntype, + "Signed values"}, + {"-ounsigned", ARGV_CONSTANT, (char *) UNSIGNED, (char *) &osigntype, + "Unsigned values"}, + {NULL, ARGV_HELP, NULL, NULL, + "Other output value options."}, + {"-orange", ARGV_FLOAT, (char *) 2, (char *) ovalid_range, + "Valid range of output minc values."}, + {NULL, ARGV_HELP, NULL, NULL, + "Options for writing output file. Default = -clobber."}, + {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, + "Overwrite existing file"}, + {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, + "Don't overwrite existing file"}, + {NULL, ARGV_END, NULL, NULL, NULL} +}; + +/* Main program */ + +main(int argc, char *argv[]) +{ + int do_norm, do_vrange; + int cdfid, imgid, maxid, minid; + int icv; + long start[MAX_VAR_DIMS]; + long count[MAX_VAR_DIMS]; + long end[MAX_VAR_DIMS]; + int dim[MAX_VAR_DIMS]; + void *image; + double *dimage; + float *fimage; + double imgmax, imgmin, value; + long image_size, image_pix, nread, fastdim; + int pix_size; + int i, j; + FILE *instream; + + /* Parse arguments */ + parse_args(argc, argv); + + /* Do normalization if input type is float */ + do_norm = (( type==NC_FLOAT) || ( type==NC_DOUBLE)); + + /* Find max and min for vrange if output type is float */ + do_vrange = do_norm && (( otype==NC_FLOAT) || ( otype==NC_DOUBLE)); + + /* Create an icv */ + icv=miicv_create(); + (void) miicv_setint(icv, MI_ICV_TYPE, type); + (void) miicv_set(icv, MI_ICV_SIGN, sign); + if (vrange_set) { + (void) miicv_setdbl(icv, MI_ICV_VALID_MIN, valid_range[0]); + (void) miicv_setdbl(icv, MI_ICV_VALID_MAX, valid_range[1]); + } + if (do_norm) { + (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE); + (void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE); + } + + /* Create the file */ + cdfid=nccreate(filename, (clobber ? NC_CLOBBER : NC_NOCLOBBER)); + + /* Create the dimensions */ + for (i=0; i<ndims; i++) { + dim[i] = ncdimdef(cdfid, dimname[i], dimlength[i]); + (void) micreate_std_variable(cdfid, dimname[i], + NC_LONG, 0, NULL); + start[i]=0; + count[i]= ((i<ndims-2) ? 1 : dimlength[i]); + end[i]=dimlength[i]; + } + + /* Create the image */ + imgid=micreate_std_variable(cdfid, MIimage, otype, ndims, dim); + (void) miattputstr(cdfid, imgid, MIsigntype, osign); + if (ovrange_set) + (void) ncattput(cdfid, imgid, MIvalid_range, NC_DOUBLE, 2, ovalid_range); + if (do_norm) { + maxid = micreate_std_variable(cdfid, MIimagemax, + NC_DOUBLE, ndims-2, dim); + minid = micreate_std_variable(cdfid, MIimagemin, + NC_DOUBLE, ndims-2, dim); + } + + /* End definition mode */ + (void) ncendef(cdfid); + + /* Attach the icv */ + (void) miicv_attach(icv, cdfid, imgid); + + /* Get a buffer for reading images */ + image_pix=dimlength[ndims-1]*dimlength[ndims-2]; + pix_size=nctypelen(type); + image_size=image_pix*pix_size; + image=malloc(image_size); + + /* Loop through the images */ + instream=stdin; + fastdim=ndims-2-1; + if (fastdim<0) fastdim=0; + if (do_vrange) { + ovalid_range[0]=DBL_MAX; + ovalid_range[1]=(-DBL_MAX); + } + fimage = image; dimage = image; + + while (start[0] < end[0]) { + + /* Read in image */ + nread=fread(image, pix_size, image_pix, instream); + if (nread!=image_pix) { + (void) fprintf(stderr, "%s: Premature end of file.\n", pname); + exit(ERROR_STATUS); + } + + /* Search for max and min for float and double */ + if (do_norm) { + imgmax=(-DBL_MAX); + imgmin=DBL_MAX; + for (j=0; j<image_pix; j++) { + switch (type) { + case NC_DOUBLE: + value=dimage[j]; break; + case NC_FLOAT: + value=fimage[j]; break; + } + if (value<imgmin) imgmin=value; + if (value>imgmax) imgmax=value; + } + if (do_vrange) { + if (imgmin<ovalid_range[0]) ovalid_range[0]=imgmin; + if (imgmax>ovalid_range[1]) ovalid_range[1]=imgmax; + } + + /* Write the image max and min */ + (void) mivarput1(cdfid, minid, start, NC_DOUBLE, NULL, &imgmin); + (void) mivarput1(cdfid, maxid, start, NC_DOUBLE, NULL, &imgmax); + } + + /* Write the image */ + (void) miicv_put(icv, start, count, image); + + /* Increment the counters */ + start[fastdim] += count[fastdim]; + i=fastdim; + while ((i>0) && (start[i]>=end[i])) { + start[i] = 0; + i--; + start[i] += count[i]; + } + } + + /* Free the memory */ + free(image); + + /* Write the valid max and min */ + if (do_vrange) { + (void) ncattput(cdfid, imgid, MIvalid_range, NC_DOUBLE, 2, ovalid_range); + } + + /* Close the file */ + (void) ncclose(cdfid); + + return NORMAL_STATUS; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : parse_args +@INPUT : argc - number of command line arguments + argv - array of arguments +@OUTPUT : +@RETURNS : (nothing). +@DESCRIPTION: Parses command line arguments. +@METHOD : +@GLOBALS : pname - program name + filename - file to write + clobber - overwrite? + dimname - names of dimensions + dimlength - lengths of dimensions + ndims - number of dimensions + orientation - orientation of dimensions + type - type of input data + signtype - sign of input data + sign - string sign of input + valid_range - valid range of input data + vrange_set - valid range used? + otype - type of output data + osigntype - sign of output data + osign - string sign of output + ovalid_range - valid range of output data + ovrange_set - valid range used? +@CALLS : +@CREATED : December 3, 1992 +@MODIFIED : +---------------------------------------------------------------------------- */ +void parse_args(int argc, char *argv[]) +{ + char *ptr; + int i; + + /* Parse the command line */ + pname=argv[0]; + if (ParseArgv(&argc, argv, argTable, 0)) { + usage_error(pname); + } + + /* Check dimensions */ + ndims = argc - 2; + if ((ndims<MIN_DIMS)||(ndims>MAX_DIMS)) { + usage_error(pname); + } + + /* Get filename */ + filename = argv[1]; + + /* Get dimensions */ + for (i=0; i<ndims; i++) { + dimlength[i] = strtol(argv[2+i], &ptr, 0); + if ((ptr==argv[2+i]) || (*ptr!=0)) { + usage_error(pname); + } + dimname[i]=orientation_names[orientation][i+MAX_DIMS-ndims]; + } + + /* Set types and signs */ + if ((otype==DEF_TYPE) && (osigntype==DEF_TYPE)) + osigntype=signtype; + if (otype==DEF_TYPE) otype=type; + sign = sign_names[signtype][type]; + osign = sign_names[osigntype][otype]; + + /* Check valid ranges */ + vrange_set=(valid_range[0]<valid_range[1]); + ovrange_set=(ovalid_range[0]<ovalid_range[1]); + if ((otype==type) && (STR_EQ(osign,sign))) { + if (!ovrange_set && vrange_set) { + ovalid_range[0]=valid_range[0]; + ovalid_range[1]=valid_range[1]; + ovrange_set = TRUE; + } + if (ovrange_set && !vrange_set) { + valid_range[0]=ovalid_range[0]; + valid_range[1]=ovalid_range[1]; + vrange_set = TRUE; + } + } + + /* Always write valid range for floating point values */ + if ((otype==NC_FLOAT) || (otype==NC_DOUBLE)) { + ovalid_range[0]=0.0; + ovalid_range[1]=1.0; + ovrange_set=TRUE; + } + + return; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : usage_error +@INPUT : progname - program name +@OUTPUT : (none) +@RETURNS : (nothing) +@DESCRIPTION: Prints a usage error message and exits. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : September 25, 1992 (Peter Neelin) +@MODIFIED : December 2, 1992 (P.N.) +---------------------------------------------------------------------------- */ +void usage_error(char *progname) +{ + (void) fprintf(stderr, "\nUsage: %s [<options>] <filename> ", progname); + (void) fprintf(stderr, "[[<size4>] <size3>] <size2> <size1>\n"); + (void) fprintf(stderr, " %s [-help]\n\n", progname); + + exit(ERROR_STATUS); +}