#include "ecat_write.h" #include "machine_indep.h" #define MatBLKSIZE 512 #define MatFirstDirBlk 2 #define NameLen 32 #define IDLen 16 #define OK 0 #define ERROR -1 #define V7 70 char* dstypecode[NumDataSetTypes] = { "u","s","i","a","n","pm","v8","v","p8","p","i8","S","S8","N", "FS"}; static char* magicNumber = "MATRIX"; struct MatDir { int matnum; int strtblk; int endblk; int matstat; }; struct matdir { int nmats, nmax; struct MatDir *entry; }; typedef struct matdirblk { int nfree, nextblk, prvblk, nused ; struct MatDir matdir[31] ; } MatDirBlk ; FILE *mat_create(const char *fname,Main_header *mhead); FILE *mat_open( const char *fname, char *fmode); int mat_write_main_header(FILE *fptr, Main_header *header); int map_main_header(char *bufr,Main_header *header); int mat_wblk(FILE *fptr,int blkno, char *bufr,int nblks); MatDirList *mat_read_directory(MatrixFile *mptr); MatDirBlk *mat_rdirblk(MatrixFile *file, int blknum); int write_host_data(MatrixFile *mptr, int matnum, MatrixData *data); int matrix_find(MatrixFile *matfile, int matnum,struct MatDir *matdir); int mat_enter(FILE *fptr, Main_header *mhptr, int matnum, int nblks); int insert_mdir(struct MatDir matdir, MatDirList *dirlist); int mat_write_image_subheader(FILE *fptr, Main_header *mhptr,int blknum, Image_subheader *header); int map_image_header(char *buf, Image_subheader *header); int matrix_freelist(MatDirList *matdirlist); void swaw( short *from, short *to, int length); int mat_close(FILE *fptr); int mat_rblk(FILE *fptr, int blkno, char *bufr, int nblks); MatrixFile *matrix_create(const char *fname, Main_header * proto_mhptr) { MatrixFile *mptr = NULL; FILE *fptr, *mat_create(); matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; fptr = mat_create(fname, proto_mhptr); if (!fptr) return( NULL ); mptr = (MatrixFile *) calloc(1, sizeof(MatrixFile)); if (!mptr) { fclose( fptr ); return( NULL ); } mptr->fptr = fptr; mptr->fname = (char *) malloc(strlen(fname) + 1); if (!mptr->fname) { free( mptr ); fclose( fptr ); return( NULL ); } strcpy(mptr->fname, fname); mptr->mhptr = (Main_header *) malloc(sizeof(Main_header)); if (!mptr->mhptr) { free( mptr->fname ); free( mptr ); fclose( fptr ); return( NULL ); } memcpy(mptr->mhptr, proto_mhptr, sizeof(Main_header)); mptr->dirlist = mat_read_directory(mptr); if (!mptr->dirlist) { free( mptr->fname ); free( mptr->mhptr ); free( mptr ); fclose( fptr ); return( NULL ); } return mptr; } FILE *mat_create(const char *fname,Main_header *mhead) { FILE *fptr; int bufr[MatBLKSIZE/sizeof(int)]; int ret; fptr = mat_open( fname, "w+"); if (!fptr) return( NULL ); ret = mat_write_main_header( fptr, mhead ); if( ret != 0 ) { mat_close( fptr); return( NULL ); } memset(bufr,0,MatBLKSIZE); bufr[0] = 31; bufr[1] = 2; ret = write_matrix_data(fptr,MatFirstDirBlk,1,(char*)bufr,SunLong); if( ret != 0 ) { mat_close( fptr); return( NULL ); } return (fptr); } FILE *mat_open( const char *fname, char *fmode) { FILE *fopen(), *fptr; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; fptr = fopen(fname, fmode); return (fptr); } int mat_write_main_header(FILE *fptr, Main_header *header) { char bufr[MatBLKSIZE]; map_main_header(bufr, header); return mat_wblk(fptr, 1, bufr, 1); /* write main header at block 1 */ } int map_main_header(char *bufr,Main_header *header) { int i = 0, j = 0; char mn[20]; /* set magic number */ sprintf(mn,"%s%d%s", magicNumber,header->sw_version, dstypecode[header->file_type]); bufWrite(mn, bufr, &i, 14); /* copy buffer into struct */ bufWrite(header->original_file_name, bufr, &i, NameLen); bufWrite_s(header->sw_version, bufr, &i); bufWrite_s(header->system_type, bufr, &i); bufWrite_s(header->file_type, bufr, &i); bufWrite(header->serial_number, bufr, &i, 10); bufWrite_u(header->scan_start_time, bufr, &i); bufWrite(header->isotope_code, bufr, &i, 8); bufWrite_f(header->isotope_halflife, bufr, &i); bufWrite(header->radiopharmaceutical, bufr, &i, NameLen); bufWrite_f(header->gantry_tilt, bufr, &i); bufWrite_f(header->gantry_rotation, bufr, &i); bufWrite_f(header->bed_elevation, bufr, &i); bufWrite_f(header->intrinsic_tilt, bufr, &i); bufWrite_s(header->wobble_speed, bufr, &i); bufWrite_s(header->transm_source_type, bufr, &i); bufWrite_f(header->distance_scanned, bufr, &i); bufWrite_f(header->transaxial_fov, bufr, &i); bufWrite_s(header->angular_compression, bufr, &i); bufWrite_s(header->coin_samp_mode, bufr, &i); bufWrite_s(header->axial_samp_mode, bufr, &i); bufWrite_f(header->calibration_factor, bufr, &i); bufWrite_s(header->calibration_units, bufr, &i); bufWrite_s(header->calibration_units_label, bufr, &i); bufWrite_s(header->compression_code, bufr, &i); bufWrite(header->study_name, bufr, &i, 12); bufWrite(header->patient_id, bufr, &i, IDLen); bufWrite(header->patient_name, bufr, &i, NameLen); bufWrite(header->patient_sex, bufr, &i, 1); bufWrite(header->patient_dexterity, bufr, &i, 1); bufWrite_f(header->patient_age, bufr, &i); bufWrite_f(header->patient_height, bufr, &i); bufWrite_f(header->patient_weight, bufr, &i); bufWrite_i(header->patient_birth_date, bufr, &i); bufWrite(header->physician_name, bufr, &i, NameLen); bufWrite(header->operator_name, bufr, &i, NameLen); bufWrite(header->study_description, bufr, &i, NameLen); bufWrite_s(header->acquisition_type, bufr, &i); bufWrite_s(header->patient_orientation, bufr, &i); bufWrite(header->facility_name, bufr, &i, 20); bufWrite_s(header->num_planes, bufr, &i); bufWrite_s(header->num_frames, bufr, &i); bufWrite_s(header->num_gates, bufr, &i); bufWrite_s(header->num_bed_pos, bufr, &i); bufWrite_f(header->init_bed_position, bufr, &i); for(j = 0; j < 15; j++) bufWrite_f(header->bed_offset[j], bufr, &i); bufWrite_f(header->plane_separation, bufr, &i); bufWrite_s(header->lwr_sctr_thres, bufr, &i); bufWrite_s(header->lwr_true_thres, bufr, &i); bufWrite_s(header->upr_true_thres, bufr, &i); bufWrite(header->user_process_code, bufr, &i, 10); bufWrite_s(header->acquisition_mode, bufr, &i); bufWrite_f(header->bin_size, bufr, &i); bufWrite_f(header->branching_fraction, bufr, &i); bufWrite_u(header->dose_start_time, bufr, &i); bufWrite_f(header->dosage, bufr, &i); bufWrite_f(header->well_counter_factor, bufr, &i); bufWrite(header->data_units, bufr, &i, 32); bufWrite_s(header->septa_state, bufr, &i); return 1; } int mat_wblk(FILE *fptr,int blkno, char *bufr,int nblks) { int err; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; /* seek to position in file */ err = fseek(fptr, (blkno - 1) * MatBLKSIZE, 0); if (err) return (ERROR); /* write matrix data */ err = fwrite(bufr, 1, nblks * MatBLKSIZE, fptr); if (err == -1) return (ERROR); if (err != nblks * MatBLKSIZE) { matrix_errno = MAT_WRITE_ERROR; return (ERROR); } return (0); } MatDirList *mat_read_directory(MatrixFile *mptr) { struct MatDir matdir; MatDirList *dirlist; MatDirBlk *matdirblk; int i, blknum; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; dirlist = (MatDirList *) calloc(1, sizeof(MatDirList)); if (dirlist == NULL) return (NULL); blknum = MatFirstDirBlk; do { matdirblk = mat_rdirblk(mptr, blknum); if (matdirblk == NULL) { free(dirlist); return (NULL); } for (i = 0; i < matdirblk->nused; i++) { matdir.matnum = matdirblk->matdir[i].matnum; matdir.strtblk = matdirblk->matdir[i].strtblk; matdir.endblk = matdirblk->matdir[i].endblk; matdir.matstat = matdirblk->matdir[i].matstat; insert_mdir(matdir, dirlist); } blknum = matdirblk->nextblk; free(matdirblk); } while (blknum != MatFirstDirBlk); return (dirlist); } MatDirBlk *mat_rdirblk(MatrixFile *file, int blknum) { MatDirBlk *matdirblk; int i, j, err, ndirs; int dirbufr[MatBLKSIZE / 4]; FILE *fptr = file->fptr; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; matdirblk = (MatDirBlk *) malloc(MatBLKSIZE); if (matdirblk == NULL) return (NULL); err = read_matrix_data(fptr, blknum, 1, (char *) dirbufr, SunLong); if (err == ERROR) { free(matdirblk); return (NULL); } matdirblk->nfree = dirbufr[0]; matdirblk->nextblk = dirbufr[1]; matdirblk->prvblk = dirbufr[2]; matdirblk->nused = dirbufr[3]; if (matdirblk->nused > 31) { matrix_errno = MAT_INVALID_DIRBLK; free(matdirblk); return (NULL); } ndirs = (MatBLKSIZE / 4 - 4) / 4; for (i = 0; i < ndirs; i++) { matdirblk->matdir[i].matnum = 0; matdirblk->matdir[i].strtblk = 0; matdirblk->matdir[i].endblk = 0; matdirblk->matdir[i].matstat = 0; } for (i = 0; i < matdirblk->nused; i++) { j = i + 1; matdirblk->matdir[i].matnum = dirbufr[j * 4 + 0]; matdirblk->matdir[i].strtblk = dirbufr[j * 4 + 1]; matdirblk->matdir[i].endblk = dirbufr[j * 4 + 2]; matdirblk->matdir[i].matstat = dirbufr[j * 4 + 3]; } return (matdirblk); } int matrix_write(MatrixFile *mptr, int matnum,MatrixData *data) { int slice ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (mptr == NULL) matrix_errno = MAT_READ_FROM_NILFPTR ; else if (mptr->mhptr == NULL) matrix_errno = MAT_NOMHD_FILE_OBJECT ; else if (data->shptr == NULL) matrix_errno = MAT_NIL_SHPTR ; else if (data->data_ptr == NULL) matrix_errno = MAT_NIL_DATA_PTR ; if (matrix_errno != OK) return (ERROR) ; return write_host_data(mptr, matnum, data); } int write_host_data(MatrixFile *mptr, int matnum, MatrixData *data) { struct MatDir matdir, dir_entry ; Image_subheader *imagesub ; int status, blkno, nblks ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; status = OK ; nblks = (data->data_size+511)/512; if (matrix_find(mptr, matnum, &matdir) == ERROR) { blkno = mat_enter(mptr->fptr, mptr->mhptr, matnum, nblks) ; if( blkno == ERROR ) return( ERROR ); dir_entry.matnum = matnum ; dir_entry.strtblk = blkno ; /*le 24 Avril 2001, j'ai enleve le -1*/ dir_entry.endblk = dir_entry.strtblk + nblks /*- 1*/ ; dir_entry.matstat = 1 ; insert_mdir(dir_entry, mptr->dirlist) ; matdir = dir_entry ; } imagesub = (Image_subheader *) data->shptr ; if (imagesub == NULL) { imagesub = (Image_subheader *) calloc(1, MatBLKSIZE); data->shptr = imagesub; } /* use MatrixData info */ imagesub->x_pixel_size = data->pixel_size; imagesub->y_pixel_size = data->y_size; imagesub->z_pixel_size = data->z_size; imagesub->num_dimensions = 3; imagesub->x_dimension = data->xdim; imagesub->y_dimension = data->ydim; imagesub->z_dimension = data->zdim; imagesub->image_max = (int)(data->data_max/data->scale_factor); imagesub->image_min = (int)(data->data_min/data->scale_factor); imagesub->scale_factor = data->scale_factor; imagesub->data_type = data->data_type; if( mat_write_image_subheader(mptr->fptr,mptr->mhptr,matdir.strtblk, imagesub) == ERROR ) return( ERROR ); status = write_matrix_data(mptr->fptr, matdir.strtblk+1, nblks, data->data_ptr, imagesub->data_type) ; if( status == ERROR ) return( ERROR ); return(status) ; } int matrix_find(MatrixFile *matfile, int matnum,struct MatDir *matdir) { MatDirNode *node ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (matfile == NULL) return(ERROR) ; if (matfile->dirlist == NULL) return(ERROR) ; node = matfile->dirlist->first ; while (node != NULL) { if (node->matnum == matnum) { matdir->matnum = node->matnum ; matdir->strtblk = node->strtblk ; matdir->endblk = node->endblk ; matdir->matstat = node->matstat ; break ; } node = node->next ; } if (node != NULL) return(OK) ; else return(ERROR) ; } int mat_enter(FILE *fptr, Main_header *mhptr, int matnum, int nblks) { int dirblk, dirbufr[128], i, nxtblk, busy, oldsize; short sw_version = mhptr->sw_version; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; dirblk = MatFirstDirBlk; if( fseek(fptr, 0, 0) ) return( ERROR ); /* * nfs locks are very time consuming lockf( fileno(fptr), F_LOCK, 0); */ if (read_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); busy = 1; while (busy) { nxtblk = dirblk + 1; for (i = 4; i < 128; i += 4) { if (dirbufr[i] == 0) { busy = 0; break; } else if (dirbufr[i] == matnum) { oldsize = dirbufr[i + 2] - dirbufr[i + 1] + 1; if (oldsize < nblks) { dirbufr[i] = 0xFFFFFFFF; write_matrix_data(fptr, dirblk, 1, (char*)dirbufr, SunLong); nxtblk = dirbufr[i + 2] + 1; } else { nxtblk = dirbufr[i + 1]; dirbufr[0]++; dirbufr[3]--; busy = 0; break; } } else { nxtblk = dirbufr[i + 2] + 1; } } if (!busy) break; if (dirbufr[1] != MatFirstDirBlk) { dirblk = dirbufr[1]; if (read_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); } else { dirbufr[1] = nxtblk; if (write_matrix_data(fptr, dirblk, 1, (char *) dirbufr, SunLong) == ERROR) return (ERROR); dirbufr[0] = 31; dirbufr[1] = MatFirstDirBlk; dirbufr[2] = dirblk; dirbufr[3] = 0; dirblk = nxtblk; for (i = 4; i < 128; i++) dirbufr[i] = 0; } } dirbufr[i] = matnum; dirbufr[i + 1] = nxtblk; dirbufr[i + 2] = nxtblk + nblks; dirbufr[i + 3] = 1; dirbufr[0]--; dirbufr[3]++; if (write_matrix_data(fptr, dirblk, 1, (char*)dirbufr, SunLong) == ERROR) return (ERROR); if( fseek(fptr, 0, 0) ) return( ERROR ); /* * nfs locks are very time consuming lockf( fileno(fptr), F_UNLOCK, 0); */ return (nxtblk); } int insert_mdir(struct MatDir matdir, MatDirList *dirlist) { MatDirNode *node ; matrix_errno = MAT_OK; matrix_errtxt[0] = '\0'; if (dirlist == NULL) { dirlist = (MatDirList *) malloc(sizeof(MatDirList)) ; if (dirlist == NULL) return(ERROR) ; dirlist->nmats = 0 ; dirlist->first = NULL ; dirlist->last = NULL ; } node = (MatDirNode *) malloc(sizeof(MatDirNode)) ; if (node == NULL) return(ERROR) ; node->matnum = matdir.matnum ; node->strtblk = matdir.strtblk ; node->endblk = matdir.endblk ; node->matstat = matdir.matstat; node->next = NULL ; if (dirlist->first == NULL) /* if list was empty, add first node */ { dirlist->first = node ; dirlist->last = node ; dirlist->nmats = 1 ; } else { (dirlist->last)->next = node ; dirlist->last = node ; ++(dirlist->nmats) ; } return OK; } int mat_write_image_subheader(FILE *fptr, Main_header *mhptr,int blknum, Image_subheader *header) { char buf[MatBLKSIZE]; map_image_header(buf, header); return mat_wblk(fptr, blknum, buf, 1); } int map_image_header(char *buf, Image_subheader *header) { int i = 0; bufWrite_s(header->data_type, buf, &i); bufWrite_s(header->num_dimensions, buf, &i); bufWrite_s(header->x_dimension, buf, &i); bufWrite_s(header->y_dimension, buf, &i); bufWrite_s(header->z_dimension, buf, &i); bufWrite_f(header->z_offset, buf, &i); bufWrite_f(header->x_offset, buf, &i); bufWrite_f(header->y_offset, buf, &i); bufWrite_f(header->recon_zoom, buf, &i); bufWrite_f(header->scale_factor, buf, &i); bufWrite_s(header->image_min, buf, &i); bufWrite_s(header->image_max, buf, &i); bufWrite_f(header->x_pixel_size, buf, &i); bufWrite_f(header->y_pixel_size, buf, &i); bufWrite_f(header->z_pixel_size, buf, &i); bufWrite_u(header->frame_duration, buf, &i); bufWrite_u(header->frame_start_time, buf, &i); bufWrite_s(header->filter_code, buf, &i); bufWrite_f(header->x_resolution, buf, &i); bufWrite_f(header->y_resolution, buf, &i); bufWrite_f(header->z_resolution, buf, &i); bufWrite_f(header->num_r_elements, buf, &i); bufWrite_f(header->num_angles, buf, &i); bufWrite_f(header->z_rotation_angle, buf, &i); bufWrite_f(header->decay_corr_fctr, buf, &i); bufWrite_i(header->processing_code, buf, &i); bufWrite_u(header->gate_duration, buf, &i); bufWrite_i(header->r_wave_offset, buf, &i); bufWrite_i(header->num_accepted_beats, buf, &i); bufWrite_f(header->filter_cutoff_frequency, buf, &i); bufWrite_f(header->filter_resolution, buf, &i); bufWrite_f(header->filter_ramp_slope, buf, &i); bufWrite_s(header->filter_order, buf, &i); bufWrite_f(header->filter_scatter_fraction, buf, &i); bufWrite_f(header->filter_scatter_slope, buf, &i); bufWrite(header->annotation, buf, &i, 40); bufWrite_f(header->mt_1_1, buf, &i); bufWrite_f(header->mt_1_2, buf, &i); bufWrite_f(header->mt_1_3, buf, &i); bufWrite_f(header->mt_2_1, buf, &i); bufWrite_f(header->mt_2_2, buf, &i); bufWrite_f(header->mt_2_3, buf, &i); bufWrite_f(header->mt_3_1, buf, &i); bufWrite_f(header->mt_3_2, buf, &i); bufWrite_f(header->mt_3_3, buf, &i); bufWrite_f(header->rfilter_cutoff, buf, &i); bufWrite_f(header->rfilter_resolution, buf, &i); bufWrite_s(header->rfilter_code, buf, &i); bufWrite_s(header->rfilter_order, buf, &i); bufWrite_f(header->zfilter_cutoff, buf, &i); bufWrite_f(header->zfilter_resolution, buf, &i); bufWrite_s(header->zfilter_code, buf, &i); bufWrite_s(header->zfilter_order, buf, &i); bufWrite_f(header->mt_1_4, buf, &i); bufWrite_f(header->mt_2_4, buf, &i); bufWrite_f(header->mt_3_4, buf, &i); bufWrite_s(header->scatter_type, buf, &i); bufWrite_s(header->recon_type, buf, &i); bufWrite_s(header->recon_views, buf, &i); return 1; } int matrix_close(MatrixFile *mptr) { int status = OK; matrix_errno = MAT_OK; if (mptr->fname) strcpy(matrix_errtxt,mptr->fname); else matrix_errtxt[0] = '\0'; if (mptr == NULL) return status; if (mptr->mhptr != NULL) free(mptr->mhptr) ; if (mptr->dirlist != NULL) matrix_freelist(mptr->dirlist) ; if (mptr->fptr) status = fclose(mptr->fptr); if (mptr->fname) free(mptr->fname); free(mptr); return status; } int matrix_freelist(MatDirList *matdirlist) { MatDirNode *node, *next ; if (matdirlist == NULL) return OK; if (matdirlist->first != NULL) { node = matdirlist->first ; do { next = node->next ; free(node) ; node = next ; } while(next != NULL) ; } free(matdirlist) ; return OK; } int mat_numcod(int frame, int plane, int gate, int data, int bed) { return ((frame)|((bed&0xF)<<12)|((plane&0xFF)<<16)|(((plane&0x300)>>8)<<9)| ((gate&0x3F)<<24)|((data&0x3)<<30)|((data&0x4)<<9)); } void swaw( short *from, short *to, int length) { short int temp; int i; for (i=0;i check if byte count less than (nblks-1) (M. Sibomana 23-oct-1997) */ else if( err < (nblks-1)*MatBLKSIZE ) { matrix_errno = MAT_READ_ERROR; return( ERROR ); } return( 0 ); }