Mercurial > hg > minc-tools
changeset 72:88eb55ed2a4a
Initial revision
author | neelin <neelin> |
---|---|
date | Fri, 22 Jan 1993 09:00:51 +0000 |
parents | ac73ce020b77 |
children | d3c53d43b3ee |
files | conversion/scxtominc/Makefile conversion/scxtominc/isotope_list.h conversion/scxtominc/scx_file.c conversion/scxtominc/scx_file.h conversion/scxtominc/scx_header_def.h conversion/scxtominc/scxtominc.c |
diffstat | 6 files changed, 1964 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/Makefile @@ -0,0 +1,79 @@ +# -------------------------------------------------------------------- +# +# MINC Makefile +# + +# Executable names +PROGS = scxtominc +EXTRA_OBJS = scx_file.o +HEADERS = scx_file.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_EXTRA= $(EXTRA_OBJS:.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) $(EXTRA_OBJS) : $(HEADERS) + +$(LINT_LIST) $(LINT_EXTRA) : $(HEADERS) + +# How to make executables +$(PROGS) : $$@.o $(EXTRA_OBJS) $(CC_PROG_LIB) $(LIB_DIR)/$(CC_LIB) + $(CC) -o $@ $@.o $(EXTRA_OBJS) $(CC_PROG_LIB) -L$(LIB_DIR) -l$(LIBRARY) $(LDOPT) + +# how to lint the executable source +lint: $(LINT_LIST_EXE) + +$(LINT_LIST_EXE) : $$@ln $(LINT_EXTRA) $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + lint -u $(LINTFLAGS) $@ln $(LINT_EXTRA) $(LINT_PROG_LIB) $(LIB_DIR)/$(LINT_LIB) + +# Remove all derived files in this directory +clean: + $(RM) $(RM_FLAGS) $(LINT_LIST) $(PROGS) $(PROG_OBJ) + +# Dependencies for scx file routines +scx_file.o scx_file.ln : scx_header_def.h + +# How to create scx_header_def.h +scx_header_def.h : define_scx_header.perl pc5r1.drs + define_scx_header.perl scx_header_def.h pc5r1.drs +
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/isotope_list.h @@ -0,0 +1,24 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : isotope_list.h +@DESCRIPTION: Header file containing list of isotopes and their half-lives. +@METHOD : +@GLOBALS : isotope_list +@CALLS : +@CREATED : January 13, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +struct { + char *name; + double half_life; /* Half life in seconds */ +} isotope_list[] = { + {"GA-68", 68.3*60.0}, + {"C-11", 20.3*60.0}, + {"F-18", 109.8*60.0}, + {"O-15", 2.03*60.0}, + {"N-13", 9.96*60.0}, + {"GE-68", 414720*60.0}, + {"CU-64", 762*60.0}, + {"CS-137", 999999*60.0}, + {NULL, -1.0} +};
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/scx_file.c @@ -0,0 +1,472 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_file.c +@DESCRIPTION: File containing routines to read scanditronix image files +@GLOBALS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +#ifndef lint +static char rcsid[]="$Header: /private-cvsroot/minc/conversion/scxtominc/scx_file.c,v 1.1 1993-01-22 09:00:51 neelin Exp $"; +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <scx_header_def.h> +#include <scx_file.h> +#include <vax_conversions.h> + +/* Private functions */ +private void scx_get_value(unsigned char *header, long position, + scx_mnem_types type, int length, + long *lvalue, float *fvalue, char *svalue); + +/* Constants */ +#define TRUE 1 +#define FALSE 0 +#define HEADER_SIZE 2048 +#define FILE_TYPE_POSITION 0 +#define FILE_TYPE_TYPE scx_word +#define SCX_NCS "NCS" +#define SCX_SPOS "SPOS" +#define SCX_DPR "DPR" +#define SCX_FHS "FHS" +#define SCX_REC "REC" +#define SCX_DTYP "DTYP" +#define SCX_IMFM "IMFM" +#define SCX_SPOS "SPOS" +#define MAX_PIX_SIZE 2 + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_open +@INPUT : filename - name of file to open +@OUTPUT : (none) +@RETURNS : Pointer to scanditronix file descriptor or NULL if an error + occurs. +@DESCRIPTION: Routine to open a scanditronix file (for reading only), given + its pathname. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +public scx_file *scx_open(char *filename) +{ + scx_file *file; + long file_type, nslice, spos; + int i; + + /* Allocate space for a scx file structure */ + file = malloc(sizeof(scx_file)); + + /* Open the file */ + if ((file->file_pointer=fopen(filename, "rb")) == NULL) { + free(file); + return NULL; + } + + /* Read in the header */ + file->header = malloc(HEADER_SIZE); + if (fread(file->header, sizeof(char), (size_t) HEADER_SIZE, + file->file_pointer) != HEADER_SIZE) { + free(file->header); + free(file); + return NULL; + } + + /* Get the file type from the header */ + scx_get_value(file->header, FILE_TYPE_POSITION, FILE_TYPE_TYPE, 1, + &file_type, NULL, NULL); + + /* Search for the file type */ + for (i=0; (scx_file_types[i].file_type!=0) && + (file_type!=scx_file_types[i].file_type); i++) {} + if (scx_file_types[i].file_type==0) { + free(file->header); + free(file); + return NULL; + } + file->blocks = scx_file_types[i].block_list; + file->mnemonics = scx_file_types[i].mnemonic_list; + + /* Get the number of mnemonics in the header */ + for (i=0; file->mnemonics[i].name!=NULL; i++) {} + file->num_mnemonics = i; + + /* Check for a consistent header by looking at the slice positions */ + if (scx_get_mnem(file, SCX_NCS, 0, &nslice, NULL, NULL) || (nslice<=0)) { + free(file->header); + free(file); + return NULL; + } + for (i=0; i<nslice; i++) { + if (scx_get_mnem(file, SCX_SPOS, i, &spos, NULL, NULL) || + (spos<0) || (spos>nslice)) { + free(file->header); + free(file); + return NULL; + } + } + + return file; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_close +@INPUT : file - scanditronix file descriptor to close +@OUTPUT : (none) +@RETURNS : (nothing) +@DESCRIPTION: Routine to close a scanditronix file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +public void scx_close(scx_file *file) +{ + if (file==NULL) return; + (void) fclose(file->file_pointer); + free(file->header); + free(file); + + return; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_get_mnem +@INPUT : file - scanditronix file descriptor + mnem - mnemonic to find + multiplicity - index of value to get +@OUTPUT : lvalue - long integer value to return + fvalue - floating point value to return + svalue - string value to return +@RETURNS : TRUE if an error occurs, FALSE otherwise +@DESCRIPTION: Routine to get a mnemonic's value from a scanditronix file + header. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +public int scx_get_mnem(scx_file *file, char *mnem, int multiplicity, + long *lvalue, float *fvalue, char *svalue) +{ + scx_block_type *block_ptr; + scx_mnemonic_type *mnem_ptr; + long position; + + /* Check file pointer */ + if (file==NULL) return TRUE; + + /* Check for negative multiplicity */ + if (multiplicity < 0) return TRUE; + + /* Search for the mnemonic */ + for (mnem_ptr=file->mnemonics; + (mnem_ptr->name!=NULL) && (strcmp(mnem_ptr->name, mnem)!=0); + mnem_ptr++) {} + if (mnem_ptr->name==NULL) return TRUE; + + /* Check for a mnemonic not in the file (a constant). We only handle + integer constants */ + if (!mnem_ptr->in_file) { + switch (mnem_ptr->type) { + case scx_byte: + case scx_word: + case scx_long: + if (lvalue!=NULL) *lvalue = mnem_ptr->mdefault; + if (fvalue!=NULL) *fvalue = mnem_ptr->mdefault; + if (svalue!=NULL) + (void) sprintf(svalue, "%d", (int) mnem_ptr->mdefault); + break; + default: + return TRUE; + } + } + + /* Mnemonic is in file header */ + else { + + /* Calculate the position of the mnemonic by looping through + the list of parent blocks */ + position = mnem_ptr->start; + for (block_ptr = mnem_ptr->block; + (multiplicity>0) && (block_ptr!=NULL); + block_ptr = block_ptr->parent) { + position += block_ptr->length * + (multiplicity % block_ptr->multiplicity); + multiplicity /= block_ptr->multiplicity; + } + if (multiplicity > 0) return TRUE; + + /* Get the value */ + scx_get_value(file->header, position, mnem_ptr->type, mnem_ptr->length, + lvalue, fvalue, svalue); + + } + + return FALSE; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_get_value +@INPUT : header - pointer to header data + position - postion of value to read + type - type of value to get + length - number of values to get +@OUTPUT : lvalue - long integer value to return + fvalue - floating point value to return + svalue - string value to return +@RETURNS : (nothing) +@DESCRIPTION: Routine to get a mnemonic's value from a scanditronix file + header, given the position and type. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +private void scx_get_value(unsigned char *header, long position, + scx_mnem_types type, int length, + long *lvalue, float *fvalue, char *svalue) +{ + void *data; + unsigned char *bdata; + short *idata; + long *ldata; + float *fdata; + + /* Check length */ + if (length<=0) return; + + /* Get the values */ + data = malloc(length * scx_mnem_type_size[type]); + bdata = data; idata = data; ldata = data; fdata = data; + switch (type) { + case scx_byte: + case scx_string: + case scx_time: + case scx_date: + (void) memcpy(bdata, &header[position], length); + break; + case scx_word: + case scx_short_float: + get_vax_short(length, &header[position], idata); + break; + case scx_long: + get_vax_long(length, &header[position], ldata); + break; + case scx_float: + get_vax_float(length, &header[position], fdata); + } + + /* Convert the values */ + switch (type) { + case scx_byte: + if (lvalue!=NULL) *lvalue = bdata[0]; + if (fvalue!=NULL) *fvalue = bdata[0]; + if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) bdata[0]); + break; + case scx_string: + if (lvalue!=NULL) *lvalue = 0; + if (fvalue!=NULL) *fvalue = 0; + if (svalue!=NULL) { + (void) memcpy(svalue, bdata, length); + svalue[length]='\0'; + } + break; + case scx_time: + if (lvalue!=NULL) *lvalue = 0; + if (fvalue!=NULL) *fvalue = 0; + if (svalue!=NULL) { + if (length==3) + (void) sprintf(svalue, "%02d:%02d:%02d", + (int) bdata[0], (int) bdata[1], (int) bdata[2]); + else if (length==4) + (void) sprintf(svalue, "%02d:%02d:%02d.%02d", + (int) bdata[0], (int) bdata[1], + (int) bdata[2], (int) bdata[3]); + else + svalue[0]='\0'; + } + break; + case scx_date: + if (lvalue!=NULL) *lvalue = 0; + if (fvalue!=NULL) *fvalue = 0; + if (svalue!=NULL) { + if (length==3) + (void) sprintf(svalue, "%02d-%02d-%02d", + (int) bdata[0], (int) bdata[1], (int) bdata[2]); + else + svalue[0]='\0'; + } + break; + case scx_word: + if (lvalue!=NULL) *lvalue = idata[0]; + if (fvalue!=NULL) *fvalue = idata[0]; + if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) idata[0]); + break; + case scx_short_float: + if (lvalue!=NULL) *lvalue = idata[0]/100.0; + if (fvalue!=NULL) *fvalue = idata[0]/100.0; + if (svalue!=NULL) (void) sprintf(svalue, "%8g", (double) idata[0]/100.0); + break; + case scx_long: + if (lvalue!=NULL) *lvalue = ldata[0]; + if (fvalue!=NULL) *fvalue = ldata[0]; + if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) ldata[0]); + break; + case scx_float: + if (lvalue!=NULL) *lvalue = fdata[0]; + if (fvalue!=NULL) *fvalue = fdata[0]; + if (svalue!=NULL) (void) sprintf(svalue, "%8g", (double) fdata[0]); + break; + } + + free(data); + + return; + +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_get_image +@INPUT : file - scanditronix file pointer + image_num - image to get (first image is zero) +@OUTPUT : image - pointer to array into which image should be written. +@RETURNS : TRUE if an error occurs, false otherwise. +@DESCRIPTION: Routine to get an image from a scanditronix image file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 11, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +public int scx_get_image(scx_file *file, int image_num, short *image) +{ + long data_present, header_size, record_size, data_type; + long image_width, image_pos, image_npix, image_size; + long file_offset, array_offset, ipix; + int pix_size; + unsigned char *bimage; + + /* Check file pointer */ + if (file==NULL) return TRUE; + + /* Check that data is in file */ + if (scx_get_mnem(file, SCX_DPR, 0, &data_present, NULL, NULL) || + (data_present!=1)) { + return TRUE; + } + + /* Parameters for calculating image position */ + if (scx_get_mnem(file, SCX_FHS, 0, &header_size, NULL, NULL) || + scx_get_mnem(file, SCX_REC, 0, &record_size, NULL, NULL) || + scx_get_mnem(file, SCX_DTYP, 0, &data_type, NULL, NULL) || + scx_get_mnem(file, SCX_IMFM, 0, &image_width, NULL, NULL) || + scx_get_mnem(file, SCX_SPOS, image_num, &image_pos, NULL, NULL) || + (header_size<0) || (record_size<0) || (image_width<0) || + (image_pos<0)) { + return TRUE; + } + + /* Check that image is in file */ + if (image_pos<1) return TRUE; + + /* Check data type */ + switch (data_type) { + case 0: pix_size=2; break; + case 1: pix_size=1; break; + default: return TRUE; + } + + /* Calculate image size and offsets */ + image_npix = image_width * image_width; + image_size = image_npix * pix_size; + file_offset = header_size * record_size + (image_pos-1) * image_size; + array_offset = image_npix * (MAX_PIX_SIZE - pix_size); + bimage = (unsigned char *) image; + + /* Read in the image */ + if (fseek(file->file_pointer, file_offset, SEEK_SET) || + (fread(&bimage[array_offset], (size_t) pix_size, (size_t) image_npix, + file->file_pointer) != image_npix)) { + return TRUE; + } + + /* Transform the image to the right type */ + switch (pix_size) { + case 1: + for (ipix=0; ipix<image_npix; ipix++) { + image[ipix] = bimage[array_offset+ipix]; + } + break; + case 2: + get_vax_short(image_npix, image, image); + break; + default: + return TRUE; + } + + return FALSE; + +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_list_mnems +@INPUT : file - pointer to an open scanditronix file + index - counter to identify next mnemonic +@OUTPUT : mname - pointer to array into which name should be written + mmult - multiplicity of mnemonic + mtype - type of mnemonic (can be scx_long, scx_float or + scx_string) +@RETURNS : Value of mname or NULL if index out of range. +@DESCRIPTION: Routine to list the mnemonics that can be found in a scanditronix + file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 19, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +public char *scx_list_mnems(scx_file *file,int index, char *mname, + int *mmult, scx_mnem_types *mtype) +{ + scx_block_type *block_ptr; + + /* Check file pointer and index */ + if ((file == NULL) || (index < 0) || (index >= file->num_mnemonics)) + return NULL; + + /* Copy the name */ + (void) strcpy(mname, file->mnemonics[index].name); + + /* Get the multiplicity */ + *mmult = 1; + for (block_ptr = file->mnemonics[index].block; + block_ptr!=NULL; + block_ptr = block_ptr->parent) { + *mmult *= block_ptr->multiplicity; + } + + /* Get the mnemonic type */ + switch (file->mnemonics[index].type) { + case scx_byte: *mtype = scx_long; break; + case scx_string: *mtype = scx_string; break; + case scx_time: *mtype = scx_string; break; + case scx_date: *mtype = scx_string; break; + case scx_word: *mtype = scx_long; break; + case scx_short_float: *mtype = scx_float; break; + case scx_long: *mtype = scx_long; break; + case scx_float: *mtype = scx_float; break; + } + + return mname; + +} +
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/scx_file.h @@ -0,0 +1,40 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scx_file.h +@DESCRIPTION: Header file for routines that read scanditonix image files +@GLOBALS : +@CREATED : January 8, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +#ifndef public +#define public +#endif +#ifndef private +#define private static +#endif + +#ifndef SCX_FILE_HEADER_DEFINITION_H +typedef struct {int dummy;} scx_block_type; +typedef struct {int dummy;} scx_mnemonic_type; +typedef enum scx_mnem_types_enum { + scx_time, scx_byte, scx_string, scx_short_float, scx_date, scx_float, + scx_word, scx_long +} scx_mnem_types; +#endif + +typedef struct { + FILE *file_pointer; + scx_block_type *blocks; + scx_mnemonic_type *mnemonics; + int num_mnemonics; + void *header; +} scx_file; + +/* Routine declarations */ +public scx_file *scx_open(char *filename); +public void scx_close(scx_file *file); +public int scx_get_mnem(scx_file *file, char *mnem, int multiplicity, + long *lvalue, float *fvalue, char *svalue); +public int scx_get_image(scx_file *file, int image_num, short *image); +public char *scx_list_mnems(scx_file *file,int index, char *mname, + int *mmult, scx_mnem_types *mtype);
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/scx_header_def.h @@ -0,0 +1,168 @@ + +/* Header file for scanditronix file definition */ +#ifndef SCX_FILE_HEADER_DEFINITION_H +#define SCX_FILE_HEADER_DEFINITION_H + +/* Mnemonic types */ +typedef enum scx_mnem_types_enum + {scx_time, scx_byte, scx_string, scx_short_float, scx_date, scx_float, scx_word, scx_long} scx_mnem_types; +static int scx_mnem_type_size[] = + {1, 1, 1, 2, 1, 4, 2, 4}; + +/* 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 mdefault; + long start; + scx_block_type *block; +}; + + +/* Blocks for drs file with id pc_5_r_1 */ +static scx_block_type drs_block_pc_5_r_1[] = { + 1872, 1, NULL, + 4, 8, &(drs_block_pc_5_r_1[0]), + 4, 8, &(drs_block_pc_5_r_1[0]), + 18, 5, &(drs_block_pc_5_r_1[0]), + 18, 1, &(drs_block_pc_5_r_1[0]), + 87, 15, &(drs_block_pc_5_r_1[0]), + 2, 32, &(drs_block_pc_5_r_1[5]), + 4, 15, &(drs_block_pc_5_r_1[0]), + 0, 0, NULL +}; + + +/* Mnemonics for drs file with id pc_5_r_1 */ +static scx_mnemonic_type drs_mnems_pc_5_r_1[] = { + "FHS", scx_byte, 1, 0, 4, -1, &(drs_block_pc_5_r_1[0]), + "REC", scx_word, 1, 0, 512, -1, &(drs_block_pc_5_r_1[0]), + "TYP", scx_word, 1, 1, 5, 0, &(drs_block_pc_5_r_1[0]), + "NCS", scx_byte, 1, 1, 15, 2, &(drs_block_pc_5_r_1[0]), + "SITE", scx_string, 4, 1, 0, 3, &(drs_block_pc_5_r_1[0]), + "REV", scx_word, 1, 1, 1, 7, &(drs_block_pc_5_r_1[0]), + "NDET", scx_word, 1, 1, 256, 9, &(drs_block_pc_5_r_1[0]), + "NPRO", scx_word, 1, 1, 256, 11, &(drs_block_pc_5_r_1[0]), + "NMEM", scx_word, 1, 1, 48, 13, &(drs_block_pc_5_r_1[0]), + "NWOB", scx_byte, 1, 1, 5, 15, &(drs_block_pc_5_r_1[0]), + "CDI", scx_short_float, 1, 1, 0, 16, &(drs_block_pc_5_r_1[0]), + "CSZ", scx_short_float, 1, 1, 0, 18, &(drs_block_pc_5_r_1[0]), + "CSX", scx_short_float, 1, 1, 0, 20, &(drs_block_pc_5_r_1[0]), + "RID", scx_string, 10, 1, 0, 22, &(drs_block_pc_5_r_1[0]), + "RIN", scx_long, 1, 1, 0, 32, &(drs_block_pc_5_r_1[0]), + "ETN", scx_word, 1, 1, 0, 36, &(drs_block_pc_5_r_1[0]), + "PNM", scx_string, 24, 1, 0, 38, &(drs_block_pc_5_r_1[0]), + "BRN", scx_long, 1, 1, 0, 62, &(drs_block_pc_5_r_1[0]), + "ASS", scx_string, 22, 1, 0, 66, &(drs_block_pc_5_r_1[0]), + "DOC", scx_string, 22, 1, 0, 88, &(drs_block_pc_5_r_1[0]), + "DAT", scx_date, 3, 1, 0, 110, &(drs_block_pc_5_r_1[0]), + "DATY", scx_byte, 1, 1, 0, 110, &(drs_block_pc_5_r_1[0]), + "DATM", scx_byte, 1, 1, 0, 111, &(drs_block_pc_5_r_1[0]), + "DATD", scx_byte, 1, 1, 0, 112, &(drs_block_pc_5_r_1[0]), + "TIM", scx_time, 4, 1, 0, 113, &(drs_block_pc_5_r_1[0]), + "TIMH", scx_byte, 1, 1, 0, 113, &(drs_block_pc_5_r_1[0]), + "TIMM", scx_byte, 1, 1, 0, 114, &(drs_block_pc_5_r_1[0]), + "TIMS", scx_byte, 1, 1, 0, 115, &(drs_block_pc_5_r_1[0]), + "TIHU", scx_byte, 1, 1, 0, 116, &(drs_block_pc_5_r_1[0]), + "QES", scx_string, 12, 1, 0, 117, &(drs_block_pc_5_r_1[0]), + "POR", scx_string, 4, 1, 0, 129, &(drs_block_pc_5_r_1[0]), + "PAN", scx_word, 1, 1, 0, 133, &(drs_block_pc_5_r_1[0]), + "CLV", scx_short_float, 1, 1, 0, 135, &(drs_block_pc_5_r_1[0]), + "ZDI", scx_short_float, 1, 1, 0, 137, &(drs_block_pc_5_r_1[0]), + "NRV", scx_word, 1, 1, 0, 139, &(drs_block_pc_5_r_1[0]), + "NME", scx_word, 1, 1, 0, 141, &(drs_block_pc_5_r_1[0]), + "MTM", scx_float, 1, 1, 0, 143, &(drs_block_pc_5_r_1[0]), + "RPRT", scx_short_float, 1, 1, 0, 147, &(drs_block_pc_5_r_1[0]), + "ISO", scx_string, 6, 1, 0, 149, &(drs_block_pc_5_r_1[0]), + "HALF", scx_float, 1, 1, 0, 155, &(drs_block_pc_5_r_1[0]), + "CAR", scx_string, 8, 1, 0, 159, &(drs_block_pc_5_r_1[0]), + "ACT", scx_float, 1, 1, 0, 167, &(drs_block_pc_5_r_1[0]), + "INP", scx_string, 4, 1, 0, 171, &(drs_block_pc_5_r_1[0]), + "INT", scx_string, 4, 1, 0, 175, &(drs_block_pc_5_r_1[0]), + "ITM", scx_time, 3, 1, 0, 179, &(drs_block_pc_5_r_1[0]), + "ITMH", scx_byte, 1, 1, 0, 179, &(drs_block_pc_5_r_1[0]), + "ITMM", scx_byte, 1, 1, 0, 180, &(drs_block_pc_5_r_1[0]), + "ITMS", scx_byte, 1, 1, 0, 181, &(drs_block_pc_5_r_1[0]), + "COL", scx_string, 1, 1, 0, 182, &(drs_block_pc_5_r_1[0]), + "SAMP", scx_byte, 1, 1, 0, 183, &(drs_block_pc_5_r_1[0]), + "DTYP", scx_byte, 1, 1, 0, 184, &(drs_block_pc_5_r_1[0]), + "FOV", scx_byte, 1, 1, 0, 185, &(drs_block_pc_5_r_1[0]), + "PRJL", scx_word, 1, 1, 0, 186, &(drs_block_pc_5_r_1[0]), + "TILT", scx_short_float, 1, 1, 0, 188, &(drs_block_pc_5_r_1[0]), + "SLEW", scx_short_float, 1, 1, 0, 190, &(drs_block_pc_5_r_1[0]), + "ELV", scx_word, 1, 1, 0, 192, &(drs_block_pc_5_r_1[0]), + "TIW", scx_short_float, 1, 1, 0, 194, &(drs_block_pc_5_r_1[0]), + "COM", scx_string, 20, 1, 0, 196, &(drs_block_pc_5_r_1[0]), + "STYP", scx_byte, 1, 1, 0, 216, &(drs_block_pc_5_r_1[0]), + "BLAN", scx_long, 1, 1, 0, 217, &(drs_block_pc_5_r_1[0]), + "TRAN", scx_long, 1, 1, 0, 221, &(drs_block_pc_5_r_1[0]), + "PAR", scx_byte, 1, 1, 0, 225, &(drs_block_pc_5_r_1[0]), + "NORM", scx_word, 1, 1, 0, 226, &(drs_block_pc_5_r_1[0]), + "DPR", scx_byte, 1, 1, 0, 228, &(drs_block_pc_5_r_1[0]), + "TNM", scx_string, 8, 1, 0, 229, &(drs_block_pc_5_r_1[0]), + "FERR", scx_long, 1, 1, 0, 237, &(drs_block_pc_5_r_1[0]), + "FLOS", scx_float, 1, 1, 0, 241, &(drs_block_pc_5_r_1[0]), + "INVA", scx_float, 1, 1, 0, 245, &(drs_block_pc_5_r_1[0]), + "TRAT", scx_float, 1, 1, 0, 249, &(drs_block_pc_5_r_1[0]), + "TAC", scx_word, 1, 1, 0, 253, &(drs_block_pc_5_r_1[0]), + "IMFM", scx_word, 1, 1, 0, 255, &(drs_block_pc_5_r_1[0]), + "IMTP", scx_string, 10, 1, 0, 257, &(drs_block_pc_5_r_1[0]), + "IMUN", scx_string, 10, 1, 0, 267, &(drs_block_pc_5_r_1[0]), + "PXS", scx_short_float, 1, 1, 0, 277, &(drs_block_pc_5_r_1[0]), + "FFN", scx_string, 4, 1, 0, 279, &(drs_block_pc_5_r_1[0]), + "FWD", scx_short_float, 1, 1, 0, 283, &(drs_block_pc_5_r_1[0]), + "SLOT", scx_word, 1, 1, 0, 285, &(drs_block_pc_5_r_1[0]), + "CNTX", scx_string, 10, 1, 0, 287, &(drs_block_pc_5_r_1[0]), + "AGE", scx_byte, 1, 1, 0, 297, &(drs_block_pc_5_r_1[0]), + "SEX", scx_string, 1, 1, 0, 298, &(drs_block_pc_5_r_1[0]), + "MAX", scx_word, 1, 1, 0, 299, &(drs_block_pc_5_r_1[0]), + "SING", scx_float, 1, 1, 0, 335, &(drs_block_pc_5_r_1[1]), + "XRAT", scx_float, 1, 1, 0, 367, &(drs_block_pc_5_r_1[2]), + "USR", scx_float, 1, 1, 0, 399, &(drs_block_pc_5_r_1[3]), + "USI", scx_long, 1, 1, 0, 403, &(drs_block_pc_5_r_1[3]), + "USC", scx_string, 10, 1, 0, 407, &(drs_block_pc_5_r_1[3]), + "CYCL", scx_float, 1, 1, 0, 489, &(drs_block_pc_5_r_1[4]), + "CYCH", scx_float, 1, 1, 0, 493, &(drs_block_pc_5_r_1[4]), + "GTLL", scx_short_float, 1, 1, 0, 497, &(drs_block_pc_5_r_1[4]), + "GTLH", scx_short_float, 1, 1, 0, 499, &(drs_block_pc_5_r_1[4]), + "GTNR", scx_byte, 1, 1, 0, 501, &(drs_block_pc_5_r_1[4]), + "FRNR", scx_word, 1, 1, 0, 502, &(drs_block_pc_5_r_1[4]), + "DCY", scx_short_float, 1, 1, 0, 504, &(drs_block_pc_5_r_1[4]), + "NGAT", scx_byte, 1, 1, 0, 506, &(drs_block_pc_5_r_1[4]), + "STOT", scx_float, 1, 1, 0, 507, &(drs_block_pc_5_r_1[5]), + "CAL", scx_float, 1, 1, 0, 511, &(drs_block_pc_5_r_1[5]), + "MAG", scx_float, 1, 1, 0, 515, &(drs_block_pc_5_r_1[5]), + "SPOS", scx_byte, 1, 1, 0, 519, &(drs_block_pc_5_r_1[5]), + "SCA", scx_float, 1, 1, 0, 520, &(drs_block_pc_5_r_1[5]), + "RAN", scx_float, 1, 1, 0, 524, &(drs_block_pc_5_r_1[5]), + "DTC", scx_short_float, 1, 1, 0, 528, &(drs_block_pc_5_r_1[5]), + "PERX", scx_byte, 1, 1, 0, 530, &(drs_block_pc_5_r_1[6]), + "PERY", scx_byte, 1, 1, 0, 531, &(drs_block_pc_5_r_1[6]), + "OFFS", scx_float, 1, 1, 0, 1812, &(drs_block_pc_5_r_1[7]), + NULL, scx_byte, 0, 0, 0, NULL +}; + + +/* List of drs files and types */ + +static struct { + int file_type; + scx_block_type *block_list; + scx_mnemonic_type *mnemonic_list; +} scx_file_types[] = { + 5, drs_block_pc_5_r_1, drs_mnems_pc_5_r_1, + 0, NULL, NULL +}; + +#endif /* SCX_FILE_HEADER_DEFINITION_H */
new file mode 100644 --- /dev/null +++ b/conversion/scxtominc/scxtominc.c @@ -0,0 +1,1181 @@ +/* ----------------------------- MNI Header ----------------------------------- +@NAME : scxtominc +@INPUT : argc, argv - command line arguments +@OUTPUT : (none) +@RETURNS : error status +@DESCRIPTION: Converts scanditronix format files to a minc format file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 11, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ + +#ifndef lint +static char rcsid[]="$Header: /private-cvsroot/minc/conversion/scxtominc/scxtominc.c,v 1.1 1993-01-22 09:01:15 neelin Exp $"; +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <math.h> +#include <ParseArgv.h> +#include <scx_file.h> +#include <minc.h> +#include "isotope_list.h" + +/* Macro definitions */ +#define MALLOC( n_items, type ) \ + ( malloc( (size_t) (n_items) * sizeof(type) ) ) +#define REALLOC( ptr, n_items, type ) \ + ( realloc( (void *) ptr, (size_t) (n_items) * sizeof(type) ) ) +#define FREE( ptr ) \ + free( (void *) ptr ) + +/* Type declarations */ +typedef struct { + char name[8]; + int mult; + nc_type type; + void *att_vector; +} scx_mnem_list_type; + +typedef struct { + int nslices; + int low_slice; + int high_slice; + double scan_time; + double time_width; + double half_life; + double zstart; + double zstep; + char isotope[16]; + int image_size; + int ordered_file; + int *ordered_slices; +} scx_file_info_type; + +typedef struct { + int num_scx_slices; + int max_nslices; + int max_size; + float zwidth; + float xystep; + float xywidth; + long vmax; + char img_units[16]; + char patient_name[32]; + char patient_sex[8]; + long patient_age; + char study_id[40]; + char start_time[40]; + long start_year; + long start_month; + long start_day; + long start_hour; + long start_minute; + float start_seconds; + char tracer[10]; + char injection_time[40]; + long injection_hour; + long injection_minute; + float injection_seconds; + float injection_dose; + scx_mnem_list_type *mnem_list; + int num_mnems; +} scx_general_info_type; + +typedef struct { + double sort_key; + void *sort_value; +} scx_sort_type; + +/* Function declarations */ +void usage_error(char *progname); +int get_scx_file_info(int num_scx_files, char **scx_files, + int slice_range[2], + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info); +void sort_scx_slices(int sort_over_time, int num_scx_files, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info); +int sortcmp(const void *val1, const void *val2); +int setup_minc_file(int mincid, int write_byte_data, int copy_all_header, + int ndims, long count[], int num_scx_files, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info); +int write_minc_slice(double scale, int write_byte_data, + int mincid, int icvid, + int ndims,long start[], long count[], + short *image, int image_size, + long pixel_max, float image_max, + double scan_time, double time_width, double zpos); +int get_scx_slice(scx_file *scx_fp, int slice_num, + long *pixel_max, float *image_max, short *image, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info); +double decay_correction(double scan_time, double measure_time, + double start_time, double half_life); + +/* Constants */ +#define TRUE 1 +#define FALSE 0 +#define MAX_DIMS 4 +#define HOURS_PER_DAY 24 +#define MIN_PER_HOUR 60 +#define SEC_PER_MIN 60 + +/* Scanditronix mnemonics used */ +#define SCX_NCS "NCS" +#define SCX_IMFM "IMFM" +#define SCX_DATY "DATY" +#define SCX_DATM "DATM" +#define SCX_DATD "DATD" +#define SCX_TIM "TIM" +#define SCX_TIMH "TIMH" +#define SCX_TIMM "TIMM" +#define SCX_TIMS "TIMS" +#define SCX_TIHU "TIHU" +#define SCX_ITM "ITM" +#define SCX_ITMH "ITMH" +#define SCX_ITMM "ITMM" +#define SCX_ITMS "ITMS" +#define SCX_MTM "MTM" +#define SCX_ISO "ISO" +#define SCX_CLV "CLV" +#define SCX_CDI "CDI" +#define SCX_CSZ "CSZ" +#define SCX_PXS "PXS" +#define SCX_MAX "MAX" +#define SCX_IMUN "IMUN" +#define SCX_MAG "MAG" +#define SCX_FWD "FWD" +#define SCX_PNM "PNM" +#define SCX_SEX "SEX" +#define SCX_AGE "AGE" +#define SCX_RIN "RIN" +#define SCX_CAR "CAR" +#define SCX_ACT "ACT" + +/* Main program */ + +int main(int argc, char *argv[]) +{ + /* Variables for arguments */ + static int write_byte_data=TRUE; + static int sort_over_time=TRUE; + static int clobber=TRUE; + static int verbose=TRUE; + static int decay_correct=TRUE; + static int slice_range[2]={0, 9999}; + static int copy_all_header=FALSE; + + /* Argument option table */ + static ArgvInfo argTable[] = { + {"-byte", ARGV_CONSTANT, (char *) TRUE, (char *) &write_byte_data, + "Write out data as bytes (default)."}, + {"-short", ARGV_CONSTANT, (char *) FALSE, (char *) &write_byte_data, + "Write out data as short integers."}, + {"-time", ARGV_CONSTANT, (char *) TRUE, (char *) &sort_over_time, + "Keep time ordering of data (default)."}, + {"-zposition", ARGV_CONSTANT, (char *) FALSE, (char *) &sort_over_time, + "Sort data according to z position."}, + {"-decay_correct", ARGV_CONSTANT, (char *) TRUE, (char *) &decay_correct, + "Do decay correction on images (default)."}, + {"-nodecay_correct", ARGV_CONSTANT, (char *) FALSE, + (char *) &decay_correct, "Don't do decay correction."}, + {"-clobber", ARGV_CONSTANT, (char *) TRUE, (char *) &clobber, + "Overwrite existing file (default)."}, + {"-noclobber", ARGV_CONSTANT, (char *) FALSE, (char *) &clobber, + "Don't overwrite existing file."}, + {"-verbose", ARGV_CONSTANT, (char *) TRUE, (char *) &verbose, + "List files as they are converted (default)"}, + {"-quiet", ARGV_CONSTANT, (char *) FALSE, (char *) &verbose, + "Do not list files as they are converted."}, + {"-small_header", ARGV_CONSTANT, (char *) FALSE, + (char *) ©_all_header, + "Copy only basic header information (default)."}, + {"-all_header", ARGV_CONSTANT, (char *) TRUE, (char *) ©_all_header, + "Copy all scanditronix header information."}, + {"-slices", ARGV_INT, (char *) 2, (char *) slice_range, + "Range of slices to copy."}, + {NULL, ARGV_END, NULL, NULL, NULL} + }; + + /* Other variables */ + char *pname; + char *mincfile; + char **scx_files; + int num_scx_files; + scx_file_info_type *scx_file_info; + scx_general_info_type *scx_general_info; + long count[MAX_DIMS], start[MAX_DIMS]; + int ndims; + int mincid, icvid; + int islice, ifile, i, slice_num; + long pixel_max; + float image_max; + double scale; + short *image; + scx_file *scx_fp; + int status; + + /* Check arguments */ + pname = argv[0]; + if (ParseArgv(&argc, argv, argTable, 0) || (argc < 3)) { + usage_error(pname); + } + + /* Check the slice range */ + if ((slice_range[0] < 0) || (slice_range[1] < 0) || + (slice_range[1] < slice_range[0])) { + (void) fprintf(stderr, "%s: Error in slice range: %d to %d.\n", + pname, slice_range[0], slice_range[1]); + } + + /* Get file names */ + mincfile = argv[argc-1]; + argv[argc-1] = NULL; /* Null-terminate scx file list */ + num_scx_files = argc - 2; + scx_files = &argv[1]; + + /* Read the files to get basic information */ + scx_general_info=MALLOC(1, *scx_general_info); + scx_file_info = MALLOC(num_scx_files, *scx_file_info); + status=get_scx_file_info(num_scx_files, scx_files, slice_range, + scx_file_info, scx_general_info); + if (status >= 0) { + (void) fprintf(stderr, "%s: Error reading scanditronix file %s.\n", + pname, scx_files[status]); + return EXIT_FAILURE; + } + + /* Allocate space for ordered slice list if sorting over z position */ + if (!sort_over_time) { + for (ifile=0; ifile<num_scx_files; ifile++) { + scx_file_info[ifile].ordered_slices = + MALLOC(scx_file_info[ifile].nslices, int); + } + } + + /* Sort the slices */ + sort_scx_slices(sort_over_time, num_scx_files, + scx_file_info, scx_general_info); + + /* Setup the minc file using the first scanditronix file */ + if (sort_over_time && (num_scx_files>1)) { + ndims = 4; + count[0]=num_scx_files; + count[1]=scx_general_info->max_nslices; + } + else { + ndims=3; + count[0]=scx_general_info->num_scx_slices; + } + count[ndims-1] = count[ndims-2] = scx_general_info->max_size; + mincid = nccreate(mincfile, (clobber ? NC_CLOBBER : NC_NOCLOBBER)); + icvid=setup_minc_file(mincid, write_byte_data, copy_all_header, + ndims, count, num_scx_files, + scx_file_info, scx_general_info); + if (icvid==MI_ERROR) { + (void) fprintf(stderr, + "%s: Error setting up minc file %s from scx file %s.\n", + pname, mincfile, scx_files[0]); + return EXIT_FAILURE; + } + + /* Initialize minc start and count vectors */ + for (i=0; i<ndims-2; i++) count[0]=1; + (void) miset_coords(ndims, (long) 0, start); + + /* Set up values for decay correction */ + scale = 1.0; + + /* Allocate an image buffer */ + image = MALLOC(scx_general_info->max_size * scx_general_info->max_size, + short); + + /* Loop through files */ + for (ifile=0; ifile<num_scx_files; ifile++) { + + /* Open the scanditronix file */ + if ((scx_fp=scx_open(scx_files[ifile]))==NULL) { + (void) fprintf(stderr, "%s: Error re-opening file %s.\n", + pname, scx_files[0]); + return EXIT_FAILURE; + } + + /* Print log message */ + if (verbose) { + (void) fprintf(stderr, "Copying file %s.\n", scx_files[ifile]); + } + + /* Get decay correction (scan time is already measured from injection + time) */ + if (decay_correct) + scale = decay_correction(scx_file_info[ifile].scan_time, + scx_file_info[ifile].time_width, + 0.0, + scx_file_info[ifile].half_life); + else + scale = 1.0; + + /* Loop through slices */ + for (islice = 0; islice < scx_file_info[ifile].nslices; islice++) { + + /* Set the minc coordinates */ + if (sort_over_time && (num_scx_files>1)) { + start[0]=scx_file_info[ifile].ordered_file; + start[1]=islice; + } + else if (sort_over_time) + start[0]=islice; + else + start[0]=scx_file_info[ifile].ordered_slices[islice]; + count[ndims-1] = count[ndims-2] = scx_file_info[ifile].image_size; + + /* Copy the slice */ + slice_num = islice + scx_file_info[ifile].low_slice; + if (get_scx_slice(scx_fp, slice_num, &pixel_max, &image_max, + image, &scx_file_info[ifile], scx_general_info) || + write_minc_slice(scale, write_byte_data, + mincid, icvid, ndims, start, count, + image, scx_file_info[ifile].image_size, + pixel_max, image_max, + scx_file_info[ifile].scan_time, + scx_file_info[ifile].time_width, + scx_file_info[ifile].zstep * (double) slice_num + + scx_file_info[ifile].zstart)) { + (void) fprintf(stderr, "%s: Error copying slice from file %s.\n", + pname, scx_files[ifile]); + return EXIT_FAILURE; + } + + } /* End slice loop */ + + /* Close the scanditronix file */ + scx_close(scx_fp); + + } /* End file loop */ + + (void) ncclose(mincid); + + FREE(image); + if (!sort_over_time) { + for (ifile=0; ifile<num_scx_files; ifile++) { + FREE(scx_file_info[ifile].ordered_slices); + } + } + FREE(scx_file_info); + FREE(scx_general_info); + + return EXIT_SUCCESS; + +} + + +/* ----------------------------- 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 : January 11, 1993 (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(EXIT_FAILURE); +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_scx_file_info +@INPUT : num_scx_files - number of scanditronix files. + scx_files - array of scanditronix file names. + slice_range - 2-component array giving range of slices +@OUTPUT : scx_file_info - array of structures containing information + about each file. + scx_general_info - general information about the scx files. +@RETURNS : (-1) if no error occurs, otherwise, the index (in scx_file) + of the first file that could not be read. +@DESCRIPTION: Reads information from each scanditronix file given by scx_files. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 12, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int get_scx_file_info(int num_scx_files, char **scx_files, + int slice_range[2], + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info) +{ + static char *the_months[]= + {NULL, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"}; + int *num_scx_slices, *max_nslices, *max_size; + scx_file *fp; + scx_file_info_type *sfip; + long lvalue, timh, timm, tims, tihu, daty, datm, datd; + float fvalue; + char svalue[40]; + struct tm the_time; + double inj_time; + int ifile, i, imnem, imult, length; + scx_mnem_types mtype; + scx_mnem_list_type *mnem_list; + void *att_vector; + + /* Initialize number of scanditronix slices */ + num_scx_slices = &(scx_general_info->num_scx_slices); + max_nslices = &(scx_general_info->max_nslices); + max_size = &(scx_general_info->max_size); + *num_scx_slices = 0; + *max_nslices = 0; + *max_size = 0; + + /* Loop through files, reading information */ + for (ifile=0; ifile<num_scx_files; ifile++) { + + /* Open file */ + fp=scx_open(scx_files[ifile]); + if (fp==NULL) return ifile; + sfip = &scx_file_info[ifile]; + + /* Get number of slices */ + if (scx_get_mnem(fp, SCX_NCS, 0, &lvalue, NULL, NULL)) return ifile; + sfip->low_slice = 0; + sfip->high_slice = lvalue - 1; + if (slice_range[0] > sfip->low_slice) + sfip->low_slice = slice_range[0]; + if (slice_range[1] < sfip->high_slice) + sfip->high_slice = slice_range[1]; + if (sfip->low_slice > sfip->high_slice) + sfip->low_slice = sfip->high_slice; + sfip->nslices = sfip->high_slice - sfip->low_slice + 1; + *num_scx_slices += sfip->nslices; + if (sfip->nslices > *max_nslices) + *max_nslices = sfip->nslices; + + /* Get image width */ + if (scx_get_mnem(fp, SCX_IMFM, 0, &lvalue, NULL, NULL)) return ifile; + sfip->image_size = lvalue; + if (lvalue > *max_size) *max_size = lvalue; + + /* Get time (in seconds) */ + if (scx_get_mnem(fp, SCX_DATY, 0, &daty, NULL, NULL) || + scx_get_mnem(fp, SCX_DATM, 0, &datm, NULL, NULL) || + scx_get_mnem(fp, SCX_DATD, 0, &datd, NULL, NULL) || + scx_get_mnem(fp, SCX_TIMH, 0, &timh, NULL, NULL) || + scx_get_mnem(fp, SCX_TIMM, 0, &timm, NULL, NULL) || + scx_get_mnem(fp, SCX_TIMS, 0, &tims, NULL, NULL) || + scx_get_mnem(fp, SCX_TIHU, 0, &tihu, NULL, NULL)) { + return ifile; + } + the_time.tm_sec = tims; + the_time.tm_min = timm; + the_time.tm_hour = timh; + the_time.tm_mday = datd; + the_time.tm_mon = datm; + the_time.tm_year = daty; + the_time.tm_isdst= FALSE; + sfip->scan_time = + (double) mktime(&the_time) + (double) tihu/100.0; + + /* Get injection time (in seconds) (use date from before and check + for time before inj_time) */ + if (scx_get_mnem(fp, SCX_ITMH, 0, &timh, NULL, NULL) || + scx_get_mnem(fp, SCX_ITMM, 0, &timm, NULL, NULL) || + scx_get_mnem(fp, SCX_ITMS, 0, &tims, NULL, NULL)) { + return ifile; + } + the_time.tm_sec = tims; + the_time.tm_min = timm; + the_time.tm_hour = timh; + the_time.tm_isdst= FALSE; + inj_time = (double) mktime(&the_time); + + /* Set scan time to be from injection time. Check for scans over + midnight (cannot deal with scans longer than 1 day */ + sfip->scan_time -= inj_time; + if (sfip->scan_time < 0.0) + sfip->scan_time += HOURS_PER_DAY * MIN_PER_HOUR * SEC_PER_MIN; + + /* Get length of frame (in seconds) */ + if (scx_get_mnem(fp, SCX_MTM, 0, NULL, &fvalue, NULL)) + return ifile; + sfip->time_width = fvalue; + + /* Get isotope and half-life */ + if (scx_get_mnem(fp, SCX_ISO, 0, NULL, NULL, + sfip->isotope)) + return ifile; + for (i=0; isotope_list[i].name !=NULL; i++) { + if (strncmp(isotope_list[i].name, sfip->isotope, + strlen(isotope_list[i].name))==0) + break; + } + sfip->half_life = isotope_list[i].half_life; + + /* Get z start and step (correct start for non-zero first slice */ + if (scx_get_mnem(fp, SCX_CDI, 0, NULL, &fvalue, NULL)) return ifile; + sfip->zstep = fvalue; + if (scx_get_mnem(fp, SCX_CLV, 0, NULL, &fvalue, NULL)) return ifile; + sfip->zstart = fvalue + sfip->low_slice * sfip->zstep; + + /* Get general information from first scx file */ + if (ifile==0) { + if (scx_get_mnem(fp, SCX_CSZ, 0, + NULL, &scx_general_info->zwidth, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_PXS, 0, + NULL, &scx_general_info->xystep, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_FWD, 0, + NULL, &scx_general_info->xywidth, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_MAX, 0, + &scx_general_info->vmax, NULL, NULL)) + return MI_ERROR; + if ((scx_general_info->vmax<=0) || (scx_general_info->vmax>32767)) + scx_general_info->vmax=32000; + if (scx_get_mnem(fp, SCX_IMUN, 0, + NULL, NULL, scx_general_info->img_units)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_PNM, 0, + NULL, NULL, scx_general_info->patient_name)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_SEX, 0, + NULL, NULL, scx_general_info->patient_sex)) + return MI_ERROR; + if (scx_general_info->patient_sex[0]=='M') + (void) strcpy(scx_general_info->patient_sex, MI_MALE); + else if (scx_general_info->patient_sex[0]=='F') + (void) strcpy(scx_general_info->patient_sex, MI_FEMALE); + else + (void) strcpy(scx_general_info->patient_sex, MI_OTHER); + if (scx_get_mnem(fp, SCX_AGE, 0, + &scx_general_info->patient_age, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_RIN, 0, + NULL, NULL, scx_general_info->study_id)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_DATY, 0, + &scx_general_info->start_year, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_DATM, 0, + &scx_general_info->start_month, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_DATD, 0, + &scx_general_info->start_day, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_TIMH, 0, + &scx_general_info->start_hour, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_TIMM, 0, + &scx_general_info->start_minute, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_TIMS, 0, + NULL, &scx_general_info->start_seconds, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_TIHU, 0, + NULL, &fvalue, NULL)) + return MI_ERROR; + scx_general_info->start_seconds += fvalue/100.0; + if (scx_get_mnem(fp, SCX_TIM, 0, NULL, NULL, svalue)) + return MI_ERROR; + (void) sprintf(scx_general_info->start_time, "%d-%s-%d %s", + (int) scx_general_info->start_day, + the_months[scx_general_info->start_month], + (int) scx_general_info->start_year+1900, + svalue); + if (scx_get_mnem(fp, SCX_CAR, 0, + NULL, NULL, scx_general_info->tracer)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_ITM, 0, + NULL, NULL, scx_general_info->injection_time)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_ITMH, 0, + &scx_general_info->injection_hour, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_ITMM, 0, + &scx_general_info->injection_minute, NULL, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_ITMS, 0, + NULL, &scx_general_info->injection_seconds, NULL)) + return MI_ERROR; + if (scx_get_mnem(fp, SCX_ACT, 0, + NULL, &scx_general_info->injection_dose, NULL)) + return MI_ERROR; + + /* Get list of header values */ + + /* Get space for first mnemonic */ + mnem_list = MALLOC(1, *mnem_list); + + /* Loop through mnemonics */ + for (imnem=0; + scx_list_mnems(fp, imnem, mnem_list[imnem].name, + &mnem_list[imnem].mult, &mtype)!=NULL; + imnem++){ + + /* Get space for attributes (handle strings differently) */ + switch (mtype) { + case scx_string: + mnem_list[imnem].type = NC_CHAR; + length = 2; + att_vector = MALLOC(length, char); + *((char *) att_vector) = '\0'; + break; + case scx_long: + mnem_list[imnem].type = NC_LONG; + att_vector = MALLOC(mnem_list[imnem].mult, long); + break; + case scx_float: + mnem_list[imnem].type = NC_FLOAT; + att_vector = MALLOC(mnem_list[imnem].mult, float); + break; + } + + /* Loop through multiplicity */ + for (imult=0; imult < mnem_list[imnem].mult; imult++) { + if (scx_get_mnem(fp, mnem_list[imnem].name, imult, + &lvalue, &fvalue, svalue)) + return MI_ERROR; + switch (mtype) { + case scx_string: + if (imult>0) { + *((char *) att_vector + length - 2) = '\n'; + *((char *) att_vector + length - 1) = '\0'; + length += 1; + } + length += strlen(svalue); + att_vector = REALLOC(att_vector, length, char); + att_vector = strcat((char *) att_vector, svalue); + break; + case scx_long: + *(((long *) att_vector) + imult) = lvalue; + break; + case scx_float: + *(((float *) att_vector) + imult) = fvalue; + break; + } + + } /* Loop over multiplicity */ + + /* Save length of string */ + if (mtype==scx_string) { + mnem_list[imnem].mult = length; + } + + /* Save pointer to attributes */ + mnem_list[imnem].att_vector = att_vector; + + /* Get space for next mnemonic */ + mnem_list = REALLOC(mnem_list, imnem+2, *mnem_list); + } + scx_general_info->mnem_list=mnem_list; + scx_general_info->num_mnems=imnem; + + } /* If first file */ + + /* Close file */ + scx_close(fp); + + } /* Loop over files */ + + return -1; +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : sort_scx_slices +@INPUT : sort_over_time - boolean indicating whether sort should be + over time or z position. + num_scx_files - number of scanditronix files. + scx_file_info - array of scanditronix file information. + scx_general_info - general information about scx files. +@OUTPUT : scx_file_info - modified to give slice ordering information. +@RETURNS : (nothing) +@DESCRIPTION: Sorts the scanditronix slices for the output file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 12, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +void sort_scx_slices(int sort_over_time, int num_scx_files, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info) +{ + int ifile, islice, isort, num_sort, slice_num; + /* Variables for sorting */ + scx_sort_type *scx_sort; + struct { + int file; + int slice; + } *slice_ptr; + scx_file_info_type *file_ptr; + + /* Allocate array for sorting */ + num_sort = (sort_over_time) ? num_scx_files : + scx_general_info->num_scx_slices; + scx_sort = MALLOC (num_sort, *scx_sort); + + /* Are we sorting over time or z position */ + if (sort_over_time) { + /* Go through the files */ + for (ifile=0; ifile<num_scx_files; ifile++) { + scx_sort[ifile].sort_key = scx_file_info[ifile].scan_time; + scx_sort[ifile].sort_value = &scx_file_info[ifile]; + } + } + /* Otherwise we are sorting over z position */ + else { + /* Go through the files and slices */ + isort=0; + for (ifile=0; ifile<num_scx_files; ifile++) { + for (islice = 0; islice < scx_file_info[ifile].nslices; islice++) { + slice_num = islice + scx_file_info[ifile].low_slice; + scx_sort[isort].sort_key = scx_file_info[ifile].zstart + + slice_num * scx_file_info[ifile].zstep; + slice_ptr = MALLOC(1, *slice_ptr); + slice_ptr->file = ifile; + slice_ptr->slice = islice; + scx_sort[isort].sort_value = slice_ptr; + isort++; + } + } + } + + /* Sort the slices */ + qsort(scx_sort, num_sort, sizeof(*scx_sort), sortcmp); + + /* Loop through sorted list */ + for (isort=0; isort<num_sort; isort++) { + if (sort_over_time) { + file_ptr=scx_sort[isort].sort_value; + file_ptr->ordered_file = isort; + } + else { + slice_ptr = scx_sort[isort].sort_value; + ifile = slice_ptr->file; + islice = slice_ptr->slice; + scx_file_info[ifile].ordered_slices[islice] = isort; + FREE(slice_ptr); + } + } + + /* Free the sorting array */ + FREE(scx_sort); + + return; +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : sortcmp +@INPUT : val1 - first value + val2 - second value +@OUTPUT : (none) +@RETURNS : 0 if values are the same, -1 if val1->sort_key < val2->sort_key + and +1 if val1->sort_key > val2->sort_key. +@DESCRIPTION: Compares two double precision values. If they are the same, + then return 0. If val1 < val2, return -1. If val1 > val2, + return +1. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 12, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int sortcmp(const void *val1, const void *val2) +{ + + if (((scx_sort_type *)val1)->sort_key < + ((scx_sort_type *)val2)->sort_key) + return -1; + else if (((scx_sort_type *)val1)->sort_key > + ((scx_sort_type *)val2)->sort_key) + return 1; + else return 0; + +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : setup_minc_file +@INPUT : mincid - id of minc file + write_byte_data - boolean indicating whether data should be + written as bytes (TRUE) or shorts (FALSE). + copy_all_header - boolean indicating whether all of the + scanditronix header information should be copied or not. + ndims - number of dimensions for minc file + count - lengths of dimensions minc file + scx_filename - name of scanditronix file for header values + num_scx_files - number of scanditronix files. + scx_file_info - array of information on scanditronix files. + scx_general_info - general information about scx files +@OUTPUT : (nothing) +@RETURNS : Image conversion variable id or MI_ERROR if an error occurs. +@DESCRIPTION: Initializes the header of the minc file using information from + the scanditronix file and the other structures. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 12, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int setup_minc_file(int mincid, int write_byte_data, int copy_all_header, + int ndims, long count[], int num_scx_files, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info) +{ + static char *dim_names_array[]={MItime, MIzspace, MIyspace, MIxspace}; + char **dim_names; + static char *dimwidth_names_array[]={ + MItime_width, MIzspace_width, MIyspace_width, MIxspace_width}; + char **dimwidth_names; + int dim[MAX_DIMS]; + int img, imgmax, imgmin, dimvarid, widvarid, icv, varid, scx_var; + int idim, imnem; + double vrange[2]; + + /* Create the dimensions */ + dim_names = dim_names_array + MAX_DIMS - ndims; + dimwidth_names = dimwidth_names_array + MAX_DIMS - ndims; + for (idim=0; idim<ndims; idim++) { + dim[idim]=ncdimdef(mincid, dim_names[idim], count[idim]); + dimvarid=micreate_std_variable(mincid, dim_names[idim], NC_DOUBLE, + ((idim==0) && (num_scx_files>1)) ? 1 : 0, + &dim[idim]); + widvarid=micreate_std_variable(mincid, dimwidth_names[idim], NC_DOUBLE, + (strcmp(dim_names[idim], MItime)==0) ? + 1 : 0, + &dim[idim]); + + /* Add attributes to the dimension variables */ + if (strcmp(dim_names[idim], MIzspace)==0) { + if ((ndims==MAX_DIMS) || (num_scx_files==1)) { + (void) miattputdbl(mincid, dimvarid, MIstep, + scx_file_info[0].zstep); + (void) miattputdbl(mincid, dimvarid, MIstart, + scx_file_info[0].zstart); + } + (void) miattputstr(mincid, dimvarid, MIunits, "mm"); + (void) miattputstr(mincid, dimvarid, MIspacetype, MI_NATIVE); + (void) miattputdbl(mincid, widvarid, MIwidth, + (double) scx_general_info->zwidth); + (void) miattputstr(mincid, widvarid, MIunits, "mm"); + (void) miattputstr(mincid, widvarid, MIfiltertype, MI_GAUSSIAN); + } + else if ((strcmp(dim_names[idim], MIyspace)==0) || + (strcmp(dim_names[idim], MIxspace)==0)) { + (void) miattputstr(mincid, dimvarid, MIunits, "mm"); + (void) miattputdbl(mincid, dimvarid, MIstep, + (double) scx_general_info->xystep); + (void) miattputstr(mincid, dimvarid, MIspacetype, MI_NATIVE); + (void) miattputdbl(mincid, widvarid, MIwidth, + (double) scx_general_info->xywidth); + (void) miattputstr(mincid, widvarid, MIfiltertype, MI_GAUSSIAN); + } + else if (strcmp(dim_names[idim], MItime)==0) { + (void) miattputstr(mincid, dimvarid, MIunits, "seconds"); + (void) miattputstr(mincid, widvarid, MIunits, "seconds"); + } + } + + /* Create the image variable */ + if (write_byte_data) { + img=micreate_std_variable(mincid, MIimage, NC_BYTE, ndims, dim); + (void) miattputstr(mincid, img, MIsigntype, MI_UNSIGNED); + vrange[0]=0; vrange[1]=255; + } + else { + img=micreate_std_variable(mincid, MIimage, NC_SHORT, ndims, dim); + (void) miattputstr(mincid, img, MIsigntype, MI_SIGNED); + vrange[0] = -scx_general_info->vmax; + vrange[1] = scx_general_info->vmax; + } + (void) ncattput(mincid, img, MIvalid_range, NC_DOUBLE, 2, vrange); + + /* Create the image max and min variables */ + imgmax=micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, ndims-2, dim); + imgmin=micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, ndims-2, dim); + (void) miattputstr(mincid, imgmax, MIunits, + scx_general_info->img_units); + (void) miattputstr(mincid, imgmin, MIunits, + scx_general_info->img_units); + + /* Create the image conversion variable */ + icv=miicv_create(); + (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT); + (void) miicv_setdbl(icv, MI_ICV_VALID_MAX, + (double) scx_general_info->vmax); + (void) miicv_setdbl(icv, MI_ICV_VALID_MIN, + (double) -scx_general_info->vmax); + + /* Save patient info */ + varid = micreate_group_variable(mincid, MIpatient); + (void) miattputstr(mincid, varid, MIfull_name, + scx_general_info->patient_name); + (void) miattputstr(mincid, varid, MIsex, + scx_general_info->patient_sex); + (void) ncattput(mincid, varid, MIage, NC_LONG, 1, + &scx_general_info->patient_age); + + /* Save study info */ + varid = micreate_group_variable(mincid, MIstudy); + (void) miattputstr(mincid, varid, MImodality, MI_PET); + (void) miattputstr(mincid, varid, MImanufacturer, "Scanditronix"); + (void) miattputstr(mincid, varid, MIstudy_id, + scx_general_info->study_id); + (void) miattputstr(mincid, varid, MIstart_time, + scx_general_info->start_time); + (void) ncattput(mincid, varid, MIstart_year, NC_LONG, 1, + &scx_general_info->start_year); + (void) ncattput(mincid, varid, MIstart_month, NC_LONG, 1, + &scx_general_info->start_month); + (void) ncattput(mincid, varid, MIstart_day, NC_LONG, 1, + &scx_general_info->start_day); + (void) ncattput(mincid, varid, MIstart_hour, NC_LONG, 1, + &scx_general_info->start_hour); + (void) ncattput(mincid, varid, MIstart_minute, NC_LONG, 1, + &scx_general_info->start_minute); + (void) ncattput(mincid, varid, MIstart_seconds, NC_FLOAT, 1, + &scx_general_info->start_seconds); + + /* Save acquisition info */ + varid = micreate_group_variable(mincid, MIacquisition); + (void) miattputstr(mincid, varid, MIradionuclide, + scx_file_info[0].isotope); + if (scx_file_info[0].half_life > 0.0) { + (void) miattputdbl(mincid, varid, MIradionuclide_halflife, + (double) scx_file_info[0].half_life); + } + (void) miattputstr(mincid, varid, MItracer, + scx_general_info->tracer); + (void) miattputstr(mincid, varid, MIinjection_time, + scx_general_info->injection_time); + (void) ncattput(mincid, varid, MIinjection_hour, NC_LONG, 1, + &scx_general_info->injection_hour); + (void) ncattput(mincid, varid, MIinjection_minute, NC_LONG, 1, + &scx_general_info->injection_minute); + (void) ncattput(mincid, varid, MIinjection_seconds, NC_FLOAT, 1, + &scx_general_info->injection_seconds); + (void) ncattput(mincid, varid, MIinjection_dose, NC_FLOAT, 1, + &scx_general_info->injection_dose); + (void) miattputstr(mincid, varid, MIdose_units, "mCurie"); + + /* If we want all of the values from the scanditronix header, get them */ + if (copy_all_header) { + + /* Create a variable for scx mnemonics */ + scx_var = ncvardef(mincid, "scanditronix", NC_LONG, 0, NULL); + (void) miattputstr(mincid, scx_var, MIvartype, MI_GROUP); + (void) miattputstr(mincid, scx_var, MIvarid, "MNI SCX variable"); + (void) miadd_child(mincid, ncvarid(mincid, MIrootvariable), scx_var); + + /* Loop through mnemonics */ + for (imnem=0; scx_general_info->num_mnems; imnem++){ + ncattput(mincid, scx_var, + scx_general_info->mnem_list[imnem].name, + scx_general_info->mnem_list[imnem].type, + scx_general_info->mnem_list[imnem].mult, + scx_general_info->mnem_list[imnem].att_vector); + } /* Loop through mnemonics */ + } /* If copy_all_header */ + + /* Attach the icv */ + (void) ncendef(mincid); + (void) miicv_attach(icv, mincid, img); + + return icv; +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : get_scx_slice +@INPUT : scx_fp - file pointer for scanditronix file + slice_num - slice to copy + scx_file_info - information on scanditronix file. + scx_general_info - general scx file information +@OUTPUT : pixel_max - maximum pixel value + image_max - real value to which pixel_max corresponds + image - scanditronix image +@RETURNS : Returns TRUE if an error occurs. +@DESCRIPTION: Gets a scanditronix image. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 20, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int get_scx_slice(scx_file *scx_fp, int slice_num, + long *pixel_max, float *image_max, short *image, + scx_file_info_type *scx_file_info, + scx_general_info_type *scx_general_info) +{ /* ARGSUSED */ + long npix, ix, iy, y_offset, off1, off2; + short temp; + + /* Get the image from the scanditronix file */ + if (scx_get_image(scx_fp, slice_num, image)) return TRUE; + + /* Flip the scanditronix image to give positive x & y axes */ + npix = scx_file_info->image_size * scx_file_info->image_size; + for (iy=0; iy<scx_file_info->image_size/2; iy++) { + y_offset = iy * scx_file_info->image_size; + for (ix=0; ix<scx_file_info->image_size/2; ix++) { + off1 = y_offset + ix; + off2 = npix - off1 - 1; + temp = image[off1]; + image[off1] = image[off2]; + image[off2] = temp; + } + } + + /* Get image and pixel max */ + if (scx_get_mnem(scx_fp, SCX_MAG, slice_num, NULL, image_max, NULL)) + return TRUE; + if (scx_get_mnem(scx_fp, SCX_MAX, 0, pixel_max, NULL, NULL)) return TRUE; + if ((*pixel_max<=0) || (*pixel_max>32767)) *pixel_max = 32000; + + return FALSE; +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : write_minc_slice +@INPUT : scale - scale for decay correcting image + write_byte_data - boolean indicating whether data should be + written as bytes (TRUE) or shorts (FALSE). + mincid - id of minc file + icvid - id of image conversion variable + start - coordinate of slice in minc file + count - edge lengths of image to write in minc file + image - pointer to image buffer + pixel_max - maximum pixel value + image_max - real value to which pixel_max corresponds + scan_time - time of slice + time_width - time width of slice + zpos - z position of slice + scx_file_info - information on scanditronix file. + scx_general_info - general scx file information +@OUTPUT : (nothing) +@RETURNS : Returns TRUE if an error occurs. +@DESCRIPTION: Writes out the image to the minc file. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 12, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +int write_minc_slice(double scale, int write_byte_data, + int mincid, int icvid, + int ndims,long start[], long count[], + short *image, int image_size, + long pixel_max, float image_max, + double scan_time, double time_width, double zpos) +{ + double pixmin, pixmax; + long ipix, npix; + double maximum, minimum; + + /* If converting to byte data, look for pixel max/min */ + if (write_byte_data) { + + /* Search for pixel max and min */ + npix = image_size * image_size; + pixmin = pixmax = image[0]; + for (ipix=1; ipix<npix; ipix++) { + if (image[ipix]>pixmax) pixmax = image[ipix]; + if (image[ipix]<pixmin) pixmin = image[ipix]; + } + + /* Get image max and min */ + maximum = image_max * pixmax / (double) pixel_max; + minimum = image_max * pixmin / (double)pixel_max; + + /* Change valid range on icv */ + (void) miicv_detach(icvid); + (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, (double) pixmax); + (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, (double) pixmin); + (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage)); + + } + + /* Not converting data to bytes */ + else { + maximum = image_max; + minimum = -image_max; + } + maximum = maximum * scale; + minimum = minimum * scale; + + /* Write out the image */ + (void) miicv_put(icvid, start, count, image); + + /* Write out image max and min */ + (void) ncvarput1(mincid, ncvarid(mincid, MIimagemax), start, &maximum); + (void) ncvarput1(mincid, ncvarid(mincid, MIimagemin), start, &minimum); + + /* Write out time and z position */ + if (ndims==MAX_DIMS) { + (void) mivarput1(mincid, ncvarid(mincid, MItime), start, + NC_DOUBLE, NULL, &scan_time); + (void) mivarput1(mincid, ncvarid(mincid, MItime_width), start, + NC_DOUBLE, NULL, &time_width); + } + (void) mivarput1(mincid, ncvarid(mincid, MIzspace), &start[ndims-2], + NC_DOUBLE, NULL, &zpos); + + return FALSE; +} + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : decay_correction +@INPUT : scan_time - time of beginning of sample + measure_time - length of sample + start_time - time to which we should decay correct + half_life - half life of isotope +@OUTPUT : (nothing) +@RETURNS : decay correction scaling factor +@DESCRIPTION: Calculates the decay correction needed to get equivalent counts + at start_time. Correction assumes constant activity (without + decay) over measure_time. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : January 21, 1993 (Peter Neelin) +@MODIFIED : +---------------------------------------------------------------------------- */ +double decay_correction(double scan_time, double measure_time, + double start_time, double half_life) +{ + double decay; + + scan_time -= start_time; + if (half_life > 0.0) { + decay = half_life/log(2.0) * + (pow(2.0, -scan_time/half_life) - + pow(2.0, -(scan_time+measure_time)/half_life)); + if (decay!=0.0) decay = 1.0/decay; + } + else { + decay = 1.0; + } + return decay; +} +