/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filename: m-matrix.c * * * * UTIL C-source: Medical Image Conversion Utility * * * * purpose : CTI source for handling ECAT 6.4 files * * * * project : (X)MedCon by Erik Nolf * * * * Notes : Source code addapted from CTI PET Systems, Inc. * * Original code 2.6 10/19/93 Copyright 1989-1993 * * * * Changed code for swapping & the use of our data types * * with machine independency as target * * * * Put "mdc" prefix on functions and structs to prevent * * naming conflicts with other tools based on CTI code * * * * Added functions for ECAT 7 reading support * * * * Original CTI Authors listed: * * E. Phearson * * L. Davis * * Yaorong * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: m-matrix.c,v 1.28 2007/05/21 20:16:13 enlf Exp $ */ /* Copyright (C) 1997-2007 by Erik Nolf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** H E A D E R S ****************************************************************************/ #include "m-depend.h" #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #ifndef _WIN32 #include #endif #endif #include "medcon.h" /*************************************************************************** D E F I N E S ***************************************************************************/ struct ExpMatDir { int matnum; int strtblk; int endblk; int matstat; float anatloc; }; /**************************************************************************** F U N C T I O N S ****************************************************************************/ /*********************************************************/ FILE *mdc_mat_open( fname, fmode) char *fname, *fmode; { FILE *fptr; fptr = fopen(fname, fmode); return (fptr); } /*********************************************************/ void mdc_mat_close( fptr) FILE *fptr; { MdcCloseFile( fptr); } /*********************************************************/ Int32 mdc_mat_rblk( fptr, blkno, bufr, nblks) FILE *fptr; Int32 blkno, nblks; Uint8 *bufr; { fseek( fptr, (blkno-1)*MdcMatBLKSIZE, 0); fread( bufr, 1, (unsigned)(nblks*MdcMatBLKSIZE), fptr); if (ferror(fptr)) return (-1); return (0); } /*********************************************************/ Int32 mdc_mat_list( fptr, mlist, lmax) FILE *fptr; struct Mdc_MatDir mlist[]; Int32 lmax; { Int32 blk, num_entry, num_stored, i; Int32 nxtblk, matnum, strtblk, endblk, matstat; Int32 dirbufr[MdcMatBLKSIZE/4]; Uint8 bytebufr[MdcMatBLKSIZE]; blk = MdcMatFirstDirBlk; num_entry = 0; num_stored = 0; while(1) { mdc_mat_rblk( fptr, blk, bytebufr,1); if ( MdcHostBig() ) { MdcSWAB( (Uint8 *)bytebufr, (Uint8 *)dirbufr, MdcMatBLKSIZE); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, MdcMatBLKSIZE/2); }else{ memcpy(dirbufr, bytebufr, MdcMatBLKSIZE); } /* nfree = dirbufr[0]; */ nxtblk = dirbufr[1]; /* prvblk = dirbufr[2]; */ /* nused = dirbufr[3]; */ for (i=4; iframe = matnum&0xFFF; matval->plane = (matnum>>16)&0xFF; matval->gate = (matnum>>24)&0x3F; matval->data = (matnum>>30)&0x3; matval->bed = (matnum>>12)&0xF; return 0; } */ /******************************************************** new version supporting 512 planes, 1024 planes, 8 data types */ Int32 mdc_mat_numcod( frame, plane, gate, data, bed) Int32 frame, plane, gate, data, bed; { Int32 matnum8data16bed64gate1024plane512frame, loPlane, hiPlane = 0, loData, hiData = 0; hiPlane = (plane & 0x300); loPlane = (plane & 0xFF); loData = (data & 0x3); hiData = (data & 0x4); matnum8data16bed64gate1024plane512frame = ((frame & 0x1FF) | ((bed & 0xF) << 12) | ((loPlane << 16) | (hiPlane << 1)) | ((gate & 0x3F) << 24) | ((loData << 30) | (hiData << 9))); return (matnum8data16bed64gate1024plane512frame); } /******************************************************** new version supporting 512 planes, 1024 planes, 8 data types */ Int32 mdc_mat_numdoc( matnum, matval) Int32 matnum; struct Mdc_Matval *matval; { Int32 loPlane, hiPlane = 0, loData, hiData = 0; matval->frame = matnum & 0x1FF; loPlane = (matnum >> 16) & 0xFF; hiPlane = (matnum >> 1) & 0x300; matval->plane = loPlane | hiPlane; matval->gate = (matnum >> 24) & 0x3F; loData = (matnum >> 30) & 0x3; hiData = (matnum >> 9) & 0x4; matval->data = loData | hiData; matval->bed = (matnum >> 12) & 0xF; return 0; } /*********************************************************/ Int32 mdc_mat_lookup( fptr, matnum, entry) FILE *fptr; Int32 matnum; struct Mdc_MatDir *entry; { Int32 blk, i; Int32 nxtblk, matnbr, strtblk, endblk, matstat; Int32 dirbufr[MdcMatBLKSIZE/4]; Uint8 bytebufr[MdcMatBLKSIZE]; blk = MdcMatFirstDirBlk; while(1) { mdc_mat_rblk( fptr, blk, bytebufr,1); if ( MdcHostBig() ) { MdcSWAB( (Uint8 *)bytebufr, (Uint8 *)dirbufr, MdcMatBLKSIZE); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, MdcMatBLKSIZE/2); }else{ memcpy(dirbufr, bytebufr, MdcMatBLKSIZE); } /* nfree = dirbufr[0]; */ nxtblk = dirbufr[1]; /* prvblk = dirbufr[2]; */ /* nused = dirbufr[3]; */ for (i=4; imatnum = matnbr; entry->strtblk = strtblk; entry->endblk = endblk; entry->matstat = matstat; return (1); } } blk = nxtblk; if (blk == MdcMatFirstDirBlk) break; } return (0); } /*********************************************************/ Int32 mdc_mat_lookup7( fptr, matnum, entry) FILE *fptr; Int32 matnum; struct Mdc_MatDir *entry; { Int32 blk, i; Int32 nxtblk, matnbr, strtblk, endblk, matstat; Int32 dirbufr[MdcMatBLKSIZE/4]; Uint8 bytebufr[MdcMatBLKSIZE]; blk = MdcMatFirstDirBlk; while(1) { mdc_mat_rblk( fptr, blk, bytebufr,1); if ( ! MdcHostBig() ) { MdcSWAB( (Uint8 *)bytebufr, (Uint8 *)dirbufr, MdcMatBLKSIZE); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, MdcMatBLKSIZE/2); }else{ memcpy(dirbufr, bytebufr, MdcMatBLKSIZE); } /* nfree = dirbufr[0]; */ nxtblk = dirbufr[1]; /* prvblk = dirbufr[2]; */ /* nused = dirbufr[3]; */ for (i=4; imatnum = matnbr; entry->strtblk = strtblk; entry->endblk = endblk; entry->matstat = matstat; return (1); } } blk = nxtblk; if (blk == MdcMatFirstDirBlk) break; } return (0); } /*********************************************************/ Int32 mdc_mat_read_main_header( fptr, h) FILE *fptr; Mdc_Main_header *h; { Int16 b[256]; char *bb; Int32 err, i; err = mdc_mat_rblk(fptr,1,(Uint8 *)b,1);/* read main header at block 1*/ if (err) return(err); bb = (char *)b; strncpy( h->original_file_name, bb+28, 20); strncpy( h->node_id, bb+56, 10); strncpy( h->isotope_code, bb+78, 8); strncpy( h->radiopharmaceutical, bb+90, 32); strncpy( h->study_name, bb+162, 12); strncpy( h->patient_id, bb+174, 16); strncpy( h->patient_name, bb+190, 32); h->patient_sex = bb[222]; strncpy( h->patient_age, bb+223, 10); strncpy( h->patient_height, bb+233, 10); strncpy( h->patient_weight, bb+243, 10); h->patient_dexterity = bb[253]; strncpy( h->physician_name, bb+254, 32); strncpy( h->operator_name, bb+286, 32); strncpy( h->study_description, bb+318, 32); strncpy( h->facility_name, bb+356, 20); strncpy( h->user_process_code, bb+462, 10); if (MdcHostBig()) MdcSWAB( (Uint8 *)b, (Uint8 *)b, MdcMatBLKSIZE); h->sw_version = b[24]; h->data_type = b[25]; h->system_type = b[26]; h->file_type = b[27]; h->scan_start_day = b[33]; h->scan_start_month = b[34]; h->scan_start_year = b[35]; h->scan_start_hour = b[36]; h->scan_start_minute = b[37]; h->scan_start_second = b[38]; h->isotope_halflife=mdc_get_vax_float((Uint16 *)b, 43); h->gantry_tilt = mdc_get_vax_float((Uint16 *)b, 61); h->gantry_rotation = mdc_get_vax_float((Uint16 *)b, 63); h->bed_elevation = mdc_get_vax_float((Uint16 *)b, 65); h->rot_source_speed = b[67]; h->wobble_speed = b[68]; h->transm_source_type = b[69]; h->axial_fov = mdc_get_vax_float((Uint16 *)b, 70); h->transaxial_fov = mdc_get_vax_float((Uint16 *)b, 72); h->transaxial_samp_mode = b[74]; h->coin_samp_mode = b[75]; h->axial_samp_mode = b[76]; h->calibration_factor=mdc_get_vax_float((Uint16 *)b, 77); h->calibration_units = b[79]; h->compression_code = b[80]; h->acquisition_type = b[175]; h->bed_type = b[176]; h->septa_type = b[177]; h->num_planes = b[188]; h->num_frames = b[189]; h->num_gates = b[190]; h->num_bed_pos = b[191]; h->init_bed_position=mdc_get_vax_float((Uint16 *)b, 192); for (i=0; i<15; i++) h->bed_offset[i] = mdc_get_vax_float((Uint16 *)b, 194+2*i); h->plane_separation = mdc_get_vax_float((Uint16 *)b, 224); h->lwr_sctr_thres = b[226]; h->lwr_true_thres = b[227]; h->upr_true_thres = b[228]; h->collimator = mdc_get_vax_float((Uint16 *)b, 229); h->acquisition_mode = b[236]; return (0); } /*********************************************************/ Int32 mdc_mat_read_matrix_data( fptr, blk, nblks, bufr) FILE *fptr; Int32 blk, nblks; Int16 bufr[]; { Int32 error ; Mdc_Main_header h ; error = mdc_mat_read_main_header(fptr, &h) ; if(error) return(error) ; error = mdc_mat_read_mat_data(fptr, blk, nblks, (Uint8 *)bufr, h.data_type) ; return (error); } /*********************************************************/ Int32 mdc_mat_read_main_header7( fptr, h) FILE *fptr; Mdc_Main_header7 *h; { Int16 b[256]; char *bb; Int32 err, i; err = mdc_mat_rblk(fptr,1,(Uint8 *)b,1);/* read main header at block 1*/ if (err) return(err); bb = (char *)b; memcpy( h->magic_number ,bb ,14); memcpy( h->original_file_name ,bb+14 ,32); memcpy(&h->sw_version ,bb+46 , 2); MdcSWAP(h->sw_version); memcpy(&h->system_type ,bb+48 , 2); MdcSWAP(h->system_type); memcpy(&h->file_type ,bb+50 , 2); MdcSWAP(h->file_type); memcpy( h->serial_number ,bb+52 ,10); memcpy(&h->scan_start_time ,bb+62 , 4); MdcSWAP(h->scan_start_time); memcpy( h->isotope_name ,bb+66 , 8); memcpy(&h->isotope_halflife ,bb+74 , 4); MdcSWAP(h->isotope_halflife); memcpy( h->radiopharmaceutical ,bb+78 ,32); memcpy(&h->gantry_tilt ,bb+110, 4); MdcSWAP(h->gantry_tilt); memcpy(&h->gantry_rotation ,bb+114, 4); MdcSWAP(h->gantry_rotation); memcpy(&h->bed_elevation ,bb+118, 4); MdcSWAP(h->bed_elevation); memcpy(&h->intrinsic_tilt ,bb+122, 4); MdcSWAP(h->intrinsic_tilt); memcpy(&h->wobble_speed ,bb+126, 2); MdcSWAP(h->wobble_speed); memcpy(&h->transm_source_type ,bb+128, 2); MdcSWAP(h->transm_source_type); memcpy(&h->distance_scanned ,bb+130, 4); MdcSWAP(h->distance_scanned); memcpy(&h->transaxial_fov ,bb+134, 4); MdcSWAP(h->transaxial_fov); memcpy(&h->angular_compression ,bb+138, 2); MdcSWAP(h->angular_compression); memcpy(&h->coin_samp_mode ,bb+140, 2); MdcSWAP(h->coin_samp_mode); memcpy(&h->axial_samp_mode ,bb+142, 2); MdcSWAP(h->axial_samp_mode); memcpy(&h->ecat_calibration_factor,bb+144,4); MdcSWAP(h->ecat_calibration_factor); memcpy(&h->calibration_units ,bb+148, 2); MdcSWAP(h->calibration_units); memcpy(&h->calibration_units_label,bb+150,2); MdcSWAP(h->calibration_units_label); memcpy(&h->compression_code ,bb+152, 2); MdcSWAP(h->compression_code); memcpy( h->study_type ,bb+154,12); memcpy( h->patient_id ,bb+166,16); memcpy( h->patient_name ,bb+182,32); memcpy( h->patient_sex ,bb+214, 1); memcpy( h->patient_dexterity ,bb+215, 1); memcpy(&h->patient_age ,bb+216, 4); MdcSWAP(h->patient_age); memcpy(&h->patient_height ,bb+220, 4); MdcSWAP(h->patient_height); memcpy(&h->patient_weight ,bb+224, 4); MdcSWAP(h->patient_weight); memcpy(&h->patient_birth_date ,bb+228, 4); MdcSWAP(h->patient_birth_date); memcpy( h->physician_name ,bb+232,32); memcpy( h->operator_name ,bb+264,32); memcpy( h->study_description ,bb+296,32); memcpy(&h->acquisition_type ,bb+328, 2); MdcSWAP(h->acquisition_type); memcpy(&h->patient_orientation ,bb+330, 2); MdcSWAP(h->patient_orientation); memcpy( h->facility_name ,bb+332,20); memcpy(&h->num_planes ,bb+352, 2); MdcSWAP(h->num_planes); memcpy(&h->num_frames ,bb+354, 2); MdcSWAP(h->num_frames); memcpy(&h->num_gates ,bb+356, 2); MdcSWAP(h->num_gates); memcpy(&h->num_bed_pos ,bb+358, 2); MdcSWAP(h->num_bed_pos); memcpy(&h->init_bed_position ,bb+360, 4); MdcSWAP(h->init_bed_position); memcpy( h->bed_position ,bb+364,60); for (i=0; i<15; i++) MdcSWAP(h->bed_position[i]); memcpy(&h->plane_separation ,bb+424, 4); MdcSWAP(h->plane_separation); memcpy(&h->lwr_sctr_thres ,bb+428, 2); MdcSWAP(h->lwr_sctr_thres); memcpy(&h->lwr_true_thres ,bb+430, 2); MdcSWAP(h->lwr_true_thres); memcpy(&h->upr_true_thres ,bb+432, 2); MdcSWAP(h->upr_true_thres); memcpy( h->user_process_code ,bb+434,10); memcpy(&h->acquisition_mode ,bb+444, 2); MdcSWAP(h->acquisition_mode); memcpy(&h->bin_size ,bb+446, 4); MdcSWAP(h->bin_size); memcpy(&h->branching_fraction ,bb+450, 4); MdcSWAP(h->branching_fraction); memcpy(&h->dose_start_time ,bb+454, 4); MdcSWAP(h->dose_start_time); memcpy(&h->dosage ,bb+458, 4); MdcSWAP(h->dosage); memcpy(&h->well_counter_corr_factor,bb+462,4); MdcSWAP(h->well_counter_corr_factor); memcpy( h->data_units ,bb+466,32); memcpy(&h->septa_state ,bb+498, 2); MdcSWAP(h->septa_state); memcpy( h->fill_cti ,bb+500,12); return (0); } /*******************************************************************/ /* May 90, PLuk - Now reads VAX or Sun matrix files. */ Int32 mdc_mat_read_mat_data( fptr, strtblk, nblks, dptr, dtype) FILE *fptr; Int32 strtblk, nblks, dtype; Uint8 *dptr; { Int32 i, error; error = mdc_mat_rblk( fptr, strtblk, dptr, nblks); if (error) return(error); switch( dtype) { case 1: /* byte format...no translation necessary */ break; case 2: /* Vax I*2 */ if (MdcHostBig()) MdcSWAB((Uint8 *)dptr, (Uint8 *)dptr, 512*nblks); break; case 3: /* Vax I*4 */ if (MdcHostBig()) { MdcSWAB( (Uint8 *)dptr, (Uint8 *)dptr, 512*nblks); MdcSWAW( (Uint16 *)dptr, (Uint16 *)dptr, 256*nblks); } break; case 4: /* Vax R*4 */ if (MdcHostBig()) MdcSWAB( (Uint8 *)dptr, (Uint8 *)dptr, 512*nblks); for (i=0; idata_type = b[63]; h->dimension_1 = b[66]; h->dimension_2 = b[67]; h->smoothing = b[68]; h->processing_code = b[69]; h->sample_distance = mdc_get_vax_float((Uint16 *)b, 73); h->isotope_halflife = mdc_get_vax_float((Uint16 *)b, 83); h->frame_duration_sec = b[85]; h->gate_duration = mdc_get_vax_long((Uint16 *)b, 86); h->r_wave_offset = mdc_get_vax_long((Uint16 *)b, 88); h->scale_factor = mdc_get_vax_float((Uint16 *)b, 91); h->scan_min = b[96]; h->scan_max = b[97]; h->prompts = mdc_get_vax_long((Uint16 *)b, 98); h->delayed = mdc_get_vax_long((Uint16 *)b, 100); h->multiples = mdc_get_vax_long((Uint16 *)b, 102); h->net_trues = mdc_get_vax_long((Uint16 *)b, 104); for (i=0; i<16; i++) { h->cor_singles[i] = mdc_get_vax_float((Uint16 *)b, 158+2*i); h->uncor_singles[i] = mdc_get_vax_float((Uint16 *)b, 190+2*i);} h->tot_avg_cor = mdc_get_vax_float((Uint16 *)b, 222); h->tot_avg_uncor = mdc_get_vax_float((Uint16 *)b, 224); h->total_coin_rate = mdc_get_vax_long((Uint16 *)b, 226); h->frame_start_time = mdc_get_vax_long((Uint16 *)b, 228); h->frame_duration = mdc_get_vax_long((Uint16 *)b, 230); h->loss_correction_fctr = mdc_get_vax_float((Uint16 *)b, 232); for (i=0; i<8; i++) h->phy_planes[i] = mdc_get_vax_long((Uint16 *)b, 234+(2*i)); return (0); } /*********************************************************/ Int32 mdc_mat_read_scan_subheader7( fptr, blknum, h) FILE *fptr; Int32 blknum; Mdc_Scan_subheader7 *h; { Int16 b[256]; Int32 err; char *bb; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)b, 1); if (err) return(err); bb = (char *)b; memcpy(&h->data_type ,bb , 2); MdcSWAP(h->data_type); memcpy(&h->num_dimensions ,bb+ 2, 2); MdcSWAP(h->num_dimensions); memcpy(&h->num_r_elements ,bb+ 4, 2); MdcSWAP(h->num_r_elements); memcpy(&h->num_angles ,bb+ 6, 2); MdcSWAP(h->num_angles); memcpy(&h->corrections_applied ,bb+ 8, 2); MdcSWAP(h->corrections_applied); memcpy(&h->num_z_elements ,bb+ 10, 2); MdcSWAP(h->num_z_elements); memcpy(&h->ring_difference ,bb+ 12, 2); MdcSWAP(h->ring_difference); memcpy(&h->x_resolution ,bb+ 14, 4); MdcSWAP(h->x_resolution); memcpy(&h->y_resolution ,bb+ 18, 4); MdcSWAP(h->y_resolution); memcpy(&h->z_resolution ,bb+ 22, 4); MdcSWAP(h->z_resolution); memcpy(&h->w_resolution ,bb+ 26, 4); MdcSWAP(h->w_resolution); return (0); } /*********************************************************/ Int32 mdc_mat_read_image_subheader( fptr, blknum, h) FILE *fptr; Int32 blknum; Mdc_Image_subheader *h; { Int16 b[256]; Int32 i, err; char *bb; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)b, 1); if (err) return(err); bb = (char *)b; strncpy( h->annotation, bb+420, 40); if (MdcHostBig()) MdcSWAB( (Uint8 *)b, (Uint8 *)b, MdcMatBLKSIZE); h->data_type = b[63]; h->num_dimensions = b[64]; h->dimension_1 = b[66]; h->dimension_2 = b[67]; h->x_origin = mdc_get_vax_float((Uint16 *)b, 80); h->y_origin = mdc_get_vax_float((Uint16 *)b, 82); h->recon_scale = mdc_get_vax_float((Uint16 *)b, 84); h->quant_scale = mdc_get_vax_float((Uint16 *)b, 86); h->image_min = b[88]; h->image_max = b[89]; h->pixel_size = mdc_get_vax_float((Uint16 *)b, 92); h->slice_width = mdc_get_vax_float((Uint16 *)b, 94); h->frame_duration = mdc_get_vax_long((Uint16 *)b, 96); h->frame_start_time = mdc_get_vax_long((Uint16 *)b, 98); h->slice_location = b[100]; h->recon_start_hour = b[101]; h->recon_start_minute = b[102]; h->recon_start_sec = b[103]; h->gate_duration = mdc_get_vax_long((Uint16 *)b, 104); h->filter_code = b[118]; h->scan_matrix_num = mdc_get_vax_long((Uint16 *)b, 119); h->norm_matrix_num = mdc_get_vax_long((Uint16 *)b, 121); h->atten_cor_matrix_num = mdc_get_vax_long((Uint16 *)b, 123); h->image_rotation = mdc_get_vax_float((Uint16 *)b, 148); h->plane_eff_corr_fctr = mdc_get_vax_float((Uint16 *)b, 150); h->decay_corr_fctr = mdc_get_vax_float((Uint16 *)b, 152); h->loss_corr_fctr = mdc_get_vax_float((Uint16 *)b, 154); h->intrinsic_tilt = mdc_get_vax_float((Uint16 *)b, 156); h->processing_code = b[188]; h->quant_units = b[190]; h->recon_start_day = b[191]; h->recon_start_month = b[192]; h->recon_start_year = b[193]; h->ecat_calibration_fctr = mdc_get_vax_float((Uint16 *)b, 194); h->well_counter_cal_fctr = mdc_get_vax_float((Uint16 *)b, 196); for (i=0; i<6; i++) h->filter_params[i] = mdc_get_vax_float((Uint16 *)b, 198+2*i); return (0); } /*********************************************************/ Int32 mdc_mat_read_image_subheader7( fptr, blknum, h) FILE *fptr; Int32 blknum; Mdc_Image_subheader7 *h; { Int16 b[256]; Int32 i, err; char *bb; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)b, 1); if (err) return(err); bb = (char *)b; memcpy(&h->data_type ,bb , 2); MdcSWAP(h->data_type); memcpy(&h->num_dimensions ,bb+ 2, 2); MdcSWAP(h->num_dimensions); memcpy(&h->x_dimension ,bb+ 4, 2); MdcSWAP(h->x_dimension); memcpy(&h->y_dimension ,bb+ 6, 2); MdcSWAP(h->y_dimension); memcpy(&h->z_dimension ,bb+ 8, 2); MdcSWAP(h->z_dimension); memcpy(&h->x_offset ,bb+ 10, 4); MdcSWAP(h->x_offset); memcpy(&h->y_offset ,bb+ 14, 4); MdcSWAP(h->y_offset); memcpy(&h->z_offset ,bb+ 18, 4); MdcSWAP(h->z_offset); memcpy(&h->recon_zoom ,bb+ 22, 4); MdcSWAP(h->recon_zoom); memcpy(&h->scale_factor ,bb+ 26, 4); MdcSWAP(h->scale_factor); memcpy(&h->image_min ,bb+ 30, 2); MdcSWAP(h->image_min); memcpy(&h->image_max ,bb+ 32, 2); MdcSWAP(h->image_max); memcpy(&h->x_pixel_size ,bb+ 34, 4); MdcSWAP(h->x_pixel_size); memcpy(&h->y_pixel_size ,bb+ 38, 4); MdcSWAP(h->y_pixel_size); memcpy(&h->z_pixel_size ,bb+ 42, 4); MdcSWAP(h->z_pixel_size); memcpy(&h->frame_duration ,bb+ 46, 4); MdcSWAP(h->frame_duration); memcpy(&h->frame_start_time ,bb+ 50, 4); MdcSWAP(h->frame_start_time); memcpy(&h->filter_code ,bb+ 54, 2); MdcSWAP(h->filter_code); memcpy(&h->x_resolution ,bb+ 56, 4); MdcSWAP(h->x_resolution); memcpy(&h->y_resolution ,bb+ 60, 4); MdcSWAP(h->y_resolution); memcpy(&h->z_resolution ,bb+ 64, 4); MdcSWAP(h->z_resolution); memcpy(&h->num_r_elements ,bb+ 68, 4); MdcSWAP(h->num_r_elements); memcpy(&h->num_angles ,bb+ 72, 4); MdcSWAP(h->num_angles); memcpy(&h->z_rotation_angle ,bb+ 76, 4); MdcSWAP(h->z_rotation_angle); memcpy(&h->decay_corr_fctr ,bb+ 80, 4); MdcSWAP(h->decay_corr_fctr); memcpy(&h->processing_code ,bb+ 84, 4); MdcSWAP(h->processing_code); memcpy(&h->gate_duration ,bb+ 88, 4); MdcSWAP(h->gate_duration); memcpy(&h->r_wave_offset ,bb+ 92, 4); MdcSWAP(h->r_wave_offset); memcpy(&h->num_accepted_beats ,bb+ 96, 4); MdcSWAP(h->num_accepted_beats); memcpy(&h->filter_cutoff_frequency,bb+100, 4); MdcSWAP(h->filter_cutoff_frequency); memcpy(&h->filter_resolution ,bb+104, 4); MdcSWAP(h->filter_resolution); memcpy(&h->filter_ramp_slope ,bb+108, 4); MdcSWAP(h->filter_ramp_slope); memcpy(&h->filter_order ,bb+112, 2); MdcSWAP(h->filter_order); memcpy(&h->filter_scatter_fraction,bb+114, 4); MdcSWAP(h->filter_scatter_fraction); memcpy(&h->filter_scatter_slope ,bb+118, 4); MdcSWAP(h->filter_scatter_slope); memcpy( h->annotation ,bb+122,40); memcpy(&h->mt_1_1 ,bb+162, 4); MdcSWAP(h->mt_1_1); memcpy(&h->mt_1_2 ,bb+166, 4); MdcSWAP(h->mt_1_2); memcpy(&h->mt_1_3 ,bb+170, 4); MdcSWAP(h->mt_1_3); memcpy(&h->mt_2_1 ,bb+174, 4); MdcSWAP(h->mt_2_1); memcpy(&h->mt_2_2 ,bb+178, 4); MdcSWAP(h->mt_2_2); memcpy(&h->mt_2_3 ,bb+182, 4); MdcSWAP(h->mt_2_3); memcpy(&h->mt_3_1 ,bb+186, 4); MdcSWAP(h->mt_3_1); memcpy(&h->mt_3_2 ,bb+190, 4); MdcSWAP(h->mt_3_2); memcpy(&h->mt_3_3 ,bb+194, 4); MdcSWAP(h->mt_3_3); memcpy(&h->rfilter_cutoff ,bb+198, 4); MdcSWAP(h->rfilter_cutoff); memcpy(&h->rfilter_resolution ,bb+202, 4); MdcSWAP(h->rfilter_resolution); memcpy(&h->rfilter_code ,bb+206, 2); MdcSWAP(h->rfilter_code); memcpy(&h->rfilter_order ,bb+208, 2); MdcSWAP(h->rfilter_order); memcpy(&h->zfilter_cutoff ,bb+210, 4); MdcSWAP(h->zfilter_cutoff); memcpy(&h->zfilter_resolution ,bb+214, 4); MdcSWAP(h->zfilter_resolution); memcpy(&h->zfilter_code ,bb+218, 2); MdcSWAP(h->zfilter_code); memcpy(&h->zfilter_order ,bb+220, 2); MdcSWAP(h->zfilter_order); memcpy(&h->mt_1_4 ,bb+222, 4); MdcSWAP(h->mt_1_4); memcpy(&h->mt_2_4 ,bb+226, 4); MdcSWAP(h->mt_2_4); memcpy(&h->mt_3_4 ,bb+230, 4); MdcSWAP(h->mt_3_4); memcpy(&h->scatter_type ,bb+234, 2); MdcSWAP(h->scatter_type); memcpy(&h->recon_type ,bb+236, 2); MdcSWAP(h->recon_type); memcpy(&h->recon_views ,bb+238, 2); MdcSWAP(h->recon_views); memcpy( h->fill_cti ,bb+240,174); for (i=0; i<87; i++) MdcSWAP(h->fill_cti[i]); memcpy( h->fill_user ,bb+414,96); for (i=0; i<48; i++) MdcSWAP(h->fill_user[i]); return (0); } /*********************************************************/ float mdc_get_vax_float( bufr, off) Uint16 bufr[]; Int32 off; { Uint16 t1, t2; union {Uint32 t3; float t4;} test; if (bufr[off]==0 && bufr[off+1]==0) return(0.0); t1 = bufr[off] & 0x80ff; t2=(((bufr[off])&0x7f00)+0xff00)&0x7f00; test.t3 = (t1+t2)<<16; test.t3 =test.t3+bufr[off+1]; return(test.t4); } /*********************************************************/ Int32 mdc_get_vax_long( bufr, off) Uint16 bufr[]; Int32 off; { return ((bufr[off+1]<<16)+bufr[off]); } Mdc_Mat_dir mdc_mat_read_dir( fptr, selector) FILE *fptr; Uint8 *selector; { Int32 i, n, blk, nxtblk, ndblks, bufr[128]; Mdc_Mat_dir dir; blk = MdcMatFirstDirBlk; nxtblk = 0; for (ndblks=0; nxtblk != MdcMatFirstDirBlk; ndblks++) { mdc_mat_rblk( fptr, blk, (Uint8 *)bufr, 1); if (MdcHostBig()) { MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, 8); MdcSWAW( (Uint16 *)bufr, (Uint16 *)bufr, 4); } nxtblk = bufr[1]; blk = nxtblk; } dir = (Mdc_Mat_dir) malloc( sizeof(struct mdc_matdir)); dir->nmats = 0; dir->nmax = 31 * ndblks; dir->entry = (struct Mdc_MatDir *) malloc( 31*ndblks*sizeof( struct Mdc_MatDir)); for (n=0, nxtblk=0, blk=MdcMatFirstDirBlk; nxtblk != MdcMatFirstDirBlk; blk = nxtblk) { mdc_mat_rblk( fptr, blk, (Uint8 *)bufr, 1); if (MdcHostBig()) { MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, 512); MdcSWAW( (Uint16 *)bufr, (Uint16 *)bufr, 256); } nxtblk = bufr[1]; for (i=4; ientry[n].matnum = bufr[i++]; dir->entry[n].strtblk = bufr[i++]; dir->entry[n].endblk = bufr[i++]; dir->entry[n].matstat = bufr[i++]; if (dir->entry[n].matnum != 0) dir->nmats++; } } return dir; } /*********************************************************/ Int32 mdc_mat_wblk( fptr, blkno, bufr, nblks) FILE *fptr; Int32 blkno, nblks; Uint8 *bufr; { Int32 err; /* seek to position in file */ err=fseek( fptr, (blkno-1)*MdcMatBLKSIZE, 0); if (err) return(-1); /* write matrix data */ err=fwrite( bufr, 1, (unsigned)nblks*MdcMatBLKSIZE, fptr); if (err != nblks*MdcMatBLKSIZE) return(-1); if (ferror(fptr)) return (-1); return (0); } FILE *mdc_mat_create( fname, mhead) char *fname; Mdc_Main_header *mhead; { FILE *fptr; Int32 i, *bufr; fptr = mdc_mat_open( fname, "wb+"); if (!fptr) return fptr; mdc_mat_write_main_header( fptr, mhead); bufr = (Int32 *) malloc( MdcMatBLKSIZE); for (i=0; i<128; i++) bufr[i] = 0; bufr[0] = 31; bufr[1] = 2; if (MdcHostBig()) { MdcSWAW( (Uint16 *)bufr, (Uint16 *)bufr, 256); MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, 512); } mdc_mat_wblk( fptr, MdcMatFirstDirBlk, (Uint8 *)bufr, 1); free( bufr); return (fptr); } Int32 mdc_mat_enter( fptr, matnum, nblks) FILE *fptr; Int32 matnum, nblks; { Int32 dirblk, dirbufr[128], i, nxtblk, busy, oldsize; dirblk = MdcMatFirstDirBlk; mdc_mat_rblk( fptr, dirblk, (Uint8 *)dirbufr, 1); if (MdcHostBig()) { MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); } 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; if (MdcHostBig()) { MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); } mdc_mat_wblk( fptr, dirblk, (Uint8 *)dirbufr, 1); if (MdcHostBig()) { MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); } 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] != MdcMatFirstDirBlk) { dirblk = dirbufr[1]; mdc_mat_rblk( fptr, dirblk, (Uint8 *)dirbufr, 1); if (MdcHostBig()) { MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); } } else { dirbufr[1] = nxtblk; if (MdcHostBig()) { MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); } mdc_mat_wblk( fptr, dirblk, (Uint8 *)dirbufr, 1); dirbufr[0] = 31; dirbufr[1] = MdcMatFirstDirBlk; 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 (MdcHostBig()) { MdcSWAW( (Uint16 *)dirbufr, (Uint16 *)dirbufr, 256); MdcSWAB( (Uint8 *)dirbufr, (Uint8 *)dirbufr, 512); } mdc_mat_wblk( fptr, dirblk, (Uint8 *)dirbufr, 1); return (nxtblk); } Int32 mdc_mat_write_image( fptr, matnum, header, data, data_size) FILE *fptr; Int32 matnum; Mdc_Image_subheader *header; Uint16 *data; Int32 data_size; { Int32 nxtblk, size, error ; size = (data_size+511)/512; nxtblk = mdc_mat_enter( fptr, matnum, size); mdc_mat_write_image_subheader( fptr, nxtblk, header); error = mdc_write_matrix_data(fptr, nxtblk+1, size, (Uint8 *)data, header->data_type) ; return(error) ; } Int32 mdc_mat_write_scan( fptr, matnum, header, data, data_size) FILE *fptr; Int32 matnum; Mdc_Scan_subheader *header; Uint16 *data; Int32 data_size; { Int32 nxtblk, size, error ; size = (data_size+511)/512; nxtblk = mdc_mat_enter( fptr, matnum, size); mdc_mat_write_scan_subheader( fptr, nxtblk, header); error = mdc_write_matrix_data(fptr, nxtblk+1, size, (Uint8 *)data, header->data_type) ; return(error) ; } Int32 mdc_mat_write_attn( fptr, matnum, header, data, data_size) FILE *fptr; Int32 matnum; Mdc_Attn_subheader *header; float *data; Int32 data_size; { Int32 nxtblk, size, error ; size = (data_size+511)/512; nxtblk = mdc_mat_enter( fptr, matnum, size); mdc_mat_write_attn_subheader( fptr, nxtblk, header); error = mdc_write_matrix_data (fptr, nxtblk+1, size, (Uint8 *)data, header->data_type) ; return(error) ; } Int32 mdc_mat_write_norm( fptr, matnum, header, data, data_size) FILE *fptr; Int32 matnum; Mdc_Norm_subheader *header; float *data; Int32 data_size; { Int32 nxtblk, size, error ; size = (data_size+511)/512; nxtblk = mdc_mat_enter( fptr, matnum, size); mdc_mat_write_norm_subheader( fptr, nxtblk, header); error = mdc_write_matrix_data(fptr, nxtblk+1, size, (Uint8 *)data, header->data_type) ; return(error) ; } Int32 mdc_mat_write_idata( fptr, blk, data, size) FILE *fptr; Int32 blk, size; Uint8 *data; { Uint8 bufr[512]; Int32 i, nbytes, nblks; nblks = (size+511)/512; for (i=0; i ranges[1][0]) return (0); if (ranges[0][1] != -1) if (m.plane < ranges[0][1] || m.plane > ranges[1][1]) return (0); if (ranges[0][2] != -1) if (m.gate < ranges[0][2] || m.gate > ranges[1][2]) return (0); if (ranges[0][3] != -1) if (m.data < ranges[0][3] || m.data > ranges[1][3]) return (0); if (ranges[0][4] != -1) if (m.bed < ranges[0][4] || m.bed > ranges[1][4]) return (0); return (matnum); } Int32 mdc_decode_selector( s1, ranges) char *s1; Int32 ranges[2][5]; { char xword[16]; Int32 i; mdc_fix_selector( s1, s1); for (i=0;i<5;i++) /* set all ranges to all (-1) */ { ranges[0][i]=ranges[1][i]=-1; s1 = mdc_nex_word( s1, xword); if (xword[0] == '*') continue; else if (strchr(xword,':')) sscanf(xword,"%d:%d",&ranges[0][i],&ranges[1][i]); else { sscanf(xword,"%d",&ranges[0][i]); ranges[1][i]=ranges[0][i]; }; } return 0; } Int32 mdc_str_find( s1, s2) char *s1, *s2; { Int32 i, j, k; for (i=0;s1[i];i++) { for (j=i,k=0; s2[k]!='\0' && s1[j]==s2[k]; j++, k++) ; if (s2[k]=='\0') return (i); } return (-1); } Int32 mdc_str_replace( s1, s2, s3, s4) char *s1, *s2, *s3, *s4; { Int32 nf=0, n; *s1 = '\0'; while (1) { if ((n=mdc_str_find(s2, s3))==-1) { strcat(s1, s2); return (nf); } else { strncat(s1, s2, (unsigned)n); strcat(s1, s4); s2+= n+strlen(s3); nf++; } } } Int32 mdc_string_replace( s1, s2, s3, s4) char *s1, *s2, *s3, *s4; { char temp[256]; strcpy(temp, s2); while (mdc_str_replace(s1, temp, s3, s4) > 0) strcpy(temp, s1); return 0; } Int32 mdc_fix_selector( s1, s2) char *s1, *s2; { char temp[256]; mdc_string_replace(temp, s2, "," , " "); mdc_string_replace(s1, temp, "..", ":"); mdc_string_replace(temp, s1, ".", ":"); mdc_string_replace(s1, temp, "-", ":"); mdc_string_replace(temp, s1, "**", "*"); mdc_string_replace(s1, temp, " ", " "); mdc_string_replace(temp, s1, " :", ":"); mdc_string_replace(s1, temp, ": ", ":"); return 0; } char* mdc_nex_word(s, w) char *s, *w; { while (*s && *s!=' ') *w++=*s++; *w='\0'; if (*s) s++; return (s); } /********************************************************/ /* HOSTFTOVAXF */ /********************************************************/ Int32 mdc_hostftovaxf(float f_orig, Uint16 number[]) { /* convert from host float to vax float */ union { Uint16 t[2]; float t4; } test ; Uint16 exp; number[0] = 0; number[1] = 0; test.t4 = f_orig; if (test.t4 == 0.0) return 0; if (!MdcHostBig()) MdcSWAW((Uint16 *)test.t, (Uint16 *)test.t,2); number[1] = test.t[1]; exp = ((test.t[0] & 0x7f00) + 0x0100) & 0x7f00; test.t[0] = (test.t[0] & 0x80ff) + exp; number[0] = test.t[0]; return 0; } /*********************************************************/ Int32 mdc_mat_write_main_header( fptr, header) FILE *fptr; Mdc_Main_header *header; { Uint8 *bbufr; Int16 bufr[256]; Int32 err,i; for (i=0; i<256; i++) bufr[i] = 0; bbufr = (Uint8 *) bufr; bufr[24] = header->sw_version; bufr[25] = header->data_type; bufr[26] = header->system_type; bufr[27] = header->file_type; bufr[33] = header->scan_start_day; bufr[34] = header->scan_start_month; bufr[35] = header->scan_start_year; bufr[36] = header->scan_start_hour; bufr[37] = header->scan_start_minute; bufr[38] = header->scan_start_second; mdc_hostftovaxf (header->isotope_halflife, (Uint16 *)&bufr[43]); mdc_hostftovaxf (header->gantry_tilt, (Uint16 *)&bufr[61]); mdc_hostftovaxf (header->gantry_rotation, (Uint16 *)&bufr[63]); mdc_hostftovaxf (header->bed_elevation, (Uint16 *)&bufr[65]); bufr[67] = header->rot_source_speed; bufr[68] = header->wobble_speed; bufr[69] = header->transm_source_type; mdc_hostftovaxf (header->axial_fov, (Uint16 *)&bufr[70]); mdc_hostftovaxf (header->transaxial_fov, (Uint16 *)&bufr[72]); bufr[74] = header->transaxial_samp_mode; bufr[75] = header->coin_samp_mode; bufr[76] = header->axial_samp_mode; mdc_hostftovaxf (header->calibration_factor,(Uint16 *)&bufr[77]); bufr[79] = header->calibration_units; bufr[80] = header->compression_code; bufr[175] = header->acquisition_type; bufr[176] = header->bed_type; bufr[177] = header->septa_type; bufr[188] = header->num_planes; bufr[189] = header->num_frames; bufr[190] = header->num_gates; bufr[191] = header->num_bed_pos; mdc_hostftovaxf (header->init_bed_position,(Uint16 *)&bufr[192]); for (i=0; i<15; i++) { mdc_hostftovaxf (header->bed_offset[i],(Uint16 *)&bufr[194+2*i]); } mdc_hostftovaxf (header->plane_separation,(Uint16 *)&bufr[224]); bufr[226] = header->lwr_sctr_thres; bufr[227] = header->lwr_true_thres; bufr[228] = header->upr_true_thres; mdc_hostftovaxf (header->collimator,(Uint16 *)&bufr[229]); bufr[236] = header->acquisition_mode; if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, MdcMatBLKSIZE); memcpy( bbufr+28, header->original_file_name, 20); /* write the node_id - character string */ memcpy( bbufr+56, header->node_id, 10); /* write the isotope code - char string */ memcpy( bbufr+78, header->isotope_code, 8); /* write the radiopharmaceutical - char string */ memcpy( bbufr+90, header->radiopharmaceutical, 32); /* study_name - char string */ memcpy( bbufr+162, header->study_name, 12); /* patient_id - char string */ memcpy( bbufr+174, header->patient_id, 16); /* patient_name - char string */ memcpy( bbufr+190, header->patient_name, 32); /* patient_sex - char */ bbufr[222] = header->patient_sex; /* patient_age - char string */ memcpy( bbufr+223, header->patient_age, 10); /* patient_height - char string */ memcpy( bbufr+233, header->patient_height, 10); /* patient_weight - char string */ memcpy( bbufr+243, header->patient_weight, 10); /* patient_dexterity - char */ bbufr[253] = header->patient_dexterity; /* physician_name - char string */ memcpy( bbufr+254, header->physician_name, 32); /* operator_name - char string */ memcpy( bbufr+286, header->operator_name, 32); /* study_description - char string */ memcpy( bbufr+318, header->study_description, 32); /* facility_name */ memcpy( bbufr+356, header->facility_name, 20); /* user_process_code - char string */ memcpy( bbufr+462, header->user_process_code, 10); err = mdc_mat_wblk( fptr, 1, (Uint8 *)bufr, 1); /* write main header at block 1 */ if (err) return(err); return (0); } /*********************************************************/ Int32 mdc_mat_write_image_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Image_subheader *header; { Uint8 *bbufr; Int16 bufr[256]; Int32 i, err; for (i=0; i<256; i++) bufr[i] = 0; bbufr = (Uint8 *) bufr; /* transfer subheader information */ bufr[63] = header->data_type; bufr[64] = header->num_dimensions; bufr[66] = header->dimension_1; bufr[67] = header->dimension_2; mdc_hostftovaxf(header->x_origin,(Uint16 *)&bufr[80]); mdc_hostftovaxf(header->y_origin,(Uint16 *)&bufr[82]); mdc_hostftovaxf(header->recon_scale,(Uint16 *)&bufr[84]); mdc_hostftovaxf(header->quant_scale,(Uint16 *)&bufr[86]); bufr[88] = header->image_min; bufr[89] = header->image_max; mdc_hostftovaxf(header->pixel_size,(Uint16 *)&bufr[92]); mdc_hostftovaxf(header->slice_width,(Uint16 *)&bufr[94]); mdc_hostltovaxl(header->frame_duration,(Uint16 *)&bufr[96]); mdc_hostltovaxl(header->frame_start_time,(Uint16 *)&bufr[98]); bufr[100] = header->slice_location; bufr[101] = header->recon_start_hour; bufr[102] = header->recon_start_minute; bufr[103] = header->recon_start_sec; mdc_hostltovaxl(header->gate_duration,(Uint16 *)&bufr[104]); bufr[118] = header->filter_code; mdc_hostltovaxl(header->scan_matrix_num,(Uint16 *)&bufr[119]); mdc_hostltovaxl(header->norm_matrix_num,(Uint16 *)&bufr[121]); mdc_hostltovaxl(header->atten_cor_matrix_num,(Uint16 *)&bufr[123]); mdc_hostftovaxf(header->image_rotation,(Uint16 *)&bufr[148]); mdc_hostftovaxf(header->plane_eff_corr_fctr,(Uint16 *)&bufr[150]); mdc_hostftovaxf(header->decay_corr_fctr,(Uint16 *)&bufr[152]); mdc_hostftovaxf(header->loss_corr_fctr,(Uint16 *)&bufr[154]); mdc_hostftovaxf(header->intrinsic_tilt,(Uint16 *)&bufr[156]); bufr[188] = header->processing_code; bufr[190] = header->quant_units; bufr[191] = header->recon_start_day; bufr[192] = header->recon_start_month; bufr[193] = header->recon_start_year; mdc_hostftovaxf(header->ecat_calibration_fctr,(Uint16 *)&bufr[194]); mdc_hostftovaxf(header->well_counter_cal_fctr,(Uint16 *)&bufr[196]); for (i=0; i<6; i++) mdc_hostftovaxf(header->filter_params[i],(Uint16 *)&bufr[198+2*i]); /* swap the bytes */ if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, MdcMatBLKSIZE); strcpy ((char *)(bbufr+420), header->annotation); /* write to matrix file */ err = mdc_mat_wblk( fptr, blknum, bbufr, 1); if (err) return(err); return(0); } /*********************************************************/ Int32 mdc_hostltovaxl( in, out) Int32 in; Uint16 out[2]; { out[0]=(in&0x0000FFFF); out[1]=(in&0xFFFF0000)>>16; return 0; } /*********************************************************/ Int32 mdc_mat_write_scan_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Scan_subheader *header; { Int16 bufr[256]; Int32 i, err; for (i=0; i<256; bufr[i++]=0); bufr[0] = 256; bufr[1] = 1; bufr[2] = 22; bufr[3] = -1; bufr[4] = 25; bufr[5] = 62; bufr[6] = 79; bufr[7] = 106; bufr[24] = 37; bufr[25] = -1; bufr[61] = 17; bufr[62] = -1; bufr[78] = 27; bufr[79] = -1; bufr[105] = 52; bufr[106] = -1; bufr[63] = header->data_type; bufr[66] = header->dimension_1; /* x dimension */ bufr[67] = header->dimension_2; /* y_dimension */ bufr[68] = header->smoothing; bufr[69] = header->processing_code; mdc_hostftovaxf(header->sample_distance,(Uint16 *)&bufr[73]); mdc_hostftovaxf(header->isotope_halflife,(Uint16 *)&bufr[83]); bufr[85] = header->frame_duration_sec; mdc_hostltovaxl(header->gate_duration,(Uint16 *)&bufr[86]); mdc_hostltovaxl(header->r_wave_offset,(Uint16 *)&bufr[88]); mdc_hostftovaxf(header->scale_factor,(Uint16 *)&bufr[91]); bufr[96] = header->scan_min; bufr[97] = header->scan_max; mdc_hostltovaxl(header->prompts,(Uint16 *)&bufr[98]); mdc_hostltovaxl(header->delayed,(Uint16 *)&bufr[100]); mdc_hostltovaxl(header->multiples,(Uint16 *)&bufr[102]); mdc_hostltovaxl(header->net_trues,(Uint16 *)&bufr[104]); for (i=0; i<16; i++) { mdc_hostftovaxf(header->cor_singles[i],(Uint16 *)&bufr[158+2*i]); mdc_hostftovaxf(header->uncor_singles[i],(Uint16 *)&bufr[190+2*i]); }; mdc_hostftovaxf(header->tot_avg_cor,(Uint16 *)&bufr[222]); mdc_hostftovaxf(header->tot_avg_uncor,(Uint16 *)&bufr[224]); mdc_hostltovaxl(header->total_coin_rate,(Uint16 *)&bufr[226]); /* total coin rate */ mdc_hostltovaxl(header->frame_start_time,(Uint16 *)&bufr[228]); mdc_hostltovaxl(header->frame_duration,(Uint16 *)&bufr[230]); mdc_hostftovaxf(header->loss_correction_fctr,(Uint16 *)&bufr[232]); for (i=0; i<8; i++) mdc_hostltovaxl(header->phy_planes[i],(Uint16 *)&bufr[234+2*i]); if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, MdcMatBLKSIZE); err = mdc_mat_wblk( fptr, blknum, (Uint8 *)bufr, 1); return (err); } Int32 mdc_mat_write_attn_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Attn_subheader *header; { Int16 bufr[256]; Int32 i,err; for (i=0; i<256; bufr[i++]=0); bufr[0] = 256; bufr[1] = 1; bufr[2] = 22; bufr[3] = -1; bufr[4] = 25; bufr[5] = 62; bufr[6] = 79; bufr[7] = 106; bufr[24] = 37; bufr[25] = -1; bufr[61] = 17; bufr[62] = -1; bufr[78] = 27; bufr[79] = -1; bufr[105] = 52; bufr[106] = -1; bufr[63] = header->data_type; bufr[64] = header->attenuation_type; bufr[66] = header->dimension_1; bufr[67] = header->dimension_2; mdc_hostftovaxf( header->scale_factor,(Uint16 *)&bufr[91]); mdc_hostftovaxf( header->x_origin,(Uint16 *)&bufr[93]); mdc_hostftovaxf( header->y_origin,(Uint16 *)&bufr[95]); mdc_hostftovaxf( header->x_radius,(Uint16 *)&bufr[97]); mdc_hostftovaxf( header->y_radius,(Uint16 *)&bufr[99]); mdc_hostftovaxf( header->tilt_angle,(Uint16 *)&bufr[101]); mdc_hostftovaxf( header->attenuation_coeff,(Uint16 *)&bufr[103]); mdc_hostftovaxf( header->sample_distance,(Uint16 *)&bufr[105]); if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, 512); err = mdc_mat_wblk( fptr, blknum, (Uint8 *)bufr, 1); return (err); } Int32 mdc_mat_write_norm_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Norm_subheader *header; { Int16 bufr[256]; Int32 i,err; for (i=0; i<256; bufr[i++]=0); bufr[0] = 256; bufr[1] = 1; bufr[2] = 22; bufr[3] = -1; bufr[4] = 25; bufr[5] = 62; bufr[6] = 79; bufr[7] = 106; bufr[24] = 37; bufr[25] = -1; bufr[61] = 17; bufr[62] = -1; bufr[78] = 27; bufr[79] = -1; bufr[105] = 52; bufr[106] = -1; bufr[63] = header->data_type; bufr[66] = header->dimension_1; bufr[67] = header->dimension_2; mdc_hostftovaxf( header->scale_factor,(Uint16 *)&bufr[91]); bufr[93] = header->norm_hour; bufr[94] = header->norm_minute; bufr[95] = header->norm_second; bufr[96] = header->norm_day; bufr[97] = header->norm_month; bufr[98] = header->norm_year; mdc_hostftovaxf( header->fov_source_width,(Uint16 *)&bufr[99]); mdc_hostftovaxf( header->ecat_calib_factor,(Uint16 *)&bufr[101]); if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, 512); err = mdc_mat_wblk( fptr, blknum, (Uint8 *)bufr, 1); return (err); } Int32 mdc_mat_read_attn_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Attn_subheader *header; { Int16 bufr[256]; Int32 err; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)bufr, 1); if (err) return(err); if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, MdcMatBLKSIZE); header->data_type = bufr[63]; header->attenuation_type = bufr[64]; header->dimension_1 = bufr[66]; header->dimension_2 = bufr[67]; header->scale_factor = mdc_get_vax_float((Uint16 *)bufr, 91); header->x_origin = mdc_get_vax_float((Uint16 *)bufr, 93); header->y_origin = mdc_get_vax_float((Uint16 *)bufr, 95); header->x_radius = mdc_get_vax_float((Uint16 *)bufr, 97); header->y_radius = mdc_get_vax_float((Uint16 *)bufr, 99); header->tilt_angle = mdc_get_vax_float((Uint16 *)bufr, 101); header->attenuation_coeff = mdc_get_vax_float((Uint16 *)bufr, 103); header->sample_distance = mdc_get_vax_float((Uint16 *)bufr, 105); return (0); } Int32 mdc_mat_read_attn_subheader7( fptr, blknum, h) FILE *fptr; Int32 blknum; Mdc_Attn_subheader7 *h; { Int16 b[256]; Int32 err, i; char *bb; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)b, 1); if (err) return(err); bb = (char *)b; memcpy(&h->data_type ,bb , 2); MdcSWAP(h->data_type); memcpy(&h->num_dimensions ,bb+ 2, 2); MdcSWAP(h->num_dimensions); memcpy(&h->attenuation_type ,bb+ 4, 2); MdcSWAP(h->attenuation_type); memcpy(&h->num_r_elements ,bb+ 6, 2); MdcSWAP(h->num_r_elements); memcpy(&h->num_angles ,bb+ 8, 2); MdcSWAP(h->num_angles); memcpy(&h->num_z_elements ,bb+ 10, 2); MdcSWAP(h->num_z_elements); memcpy(&h->ring_difference ,bb+ 12, 2); MdcSWAP(h->ring_difference); memcpy(&h->x_resolution ,bb+ 14, 4); MdcSWAP(h->x_resolution); memcpy(&h->y_resolution ,bb+ 18, 4); MdcSWAP(h->y_resolution); memcpy(&h->z_resolution ,bb+ 22, 4); MdcSWAP(h->z_resolution); memcpy(&h->w_resolution ,bb+ 26, 4); MdcSWAP(h->w_resolution); memcpy(&h->scale_factor ,bb+ 30, 4); MdcSWAP(h->scale_factor); memcpy(&h->x_offset ,bb+ 34, 4); MdcSWAP(h->x_offset); memcpy(&h->y_offset ,bb+ 38, 4); MdcSWAP(h->y_offset); memcpy(&h->x_radius ,bb+ 42, 4); MdcSWAP(h->x_radius); memcpy(&h->y_radius ,bb+ 46, 4); MdcSWAP(h->y_radius); memcpy(&h->tilt_angle ,bb+ 50, 4); MdcSWAP(h->tilt_angle); memcpy(&h->attenuation_coeff ,bb+ 54, 4); MdcSWAP(h->attenuation_coeff); memcpy(&h->attenuation_min ,bb+ 58, 4); MdcSWAP(h->attenuation_min); memcpy(&h->attenuation_max ,bb+ 62, 4); MdcSWAP(h->attenuation_max); memcpy(&h->skull_thickness ,bb+ 66, 4); MdcSWAP(h->skull_thickness); memcpy(&h->num_xtra_atten_coeff ,bb+ 70, 2); MdcSWAP(h->num_xtra_atten_coeff); memcpy(&h->xtra_atten_coeff ,bb+ 72, 32); for (i=0; i<8; i++) MdcSWAP(h->xtra_atten_coeff[i]); memcpy(&h->edge_finding_threshold,bb+104, 4); MdcSWAP(h->edge_finding_threshold); memcpy(&h->storage_order ,bb+108, 2); MdcSWAP(h->storage_order); memcpy(&h->span ,bb+110, 2); MdcSWAP(h->span); memcpy(&h->z_elements ,bb+112,128); for (i=0; i<64; i++) MdcSWAP(h->z_elements[i]); memcpy(&h->fill_unused ,bb+240,172); for (i=0; i<86; i++) MdcSWAP(h->fill_unused[i]); memcpy(&h->fill_user ,bb+412,100); for (i=0; i<50; i++) MdcSWAP(h->fill_user[i]); return (0); } Int32 mdc_mat_read_norm_subheader( fptr, blknum, header) FILE *fptr; Int32 blknum; Mdc_Norm_subheader *header; { Int16 bufr[256]; Int32 err; err = mdc_mat_rblk( fptr, blknum, (Uint8 *)bufr, 1); if (err) return(err); if (MdcHostBig()) MdcSWAB( (Uint8 *)bufr, (Uint8 *)bufr, MdcMatBLKSIZE); header->data_type = bufr[63]; header->dimension_1 = bufr[66]; header->dimension_2 = bufr[67]; header->scale_factor = mdc_get_vax_float((Uint16 *)bufr, 91); header->norm_hour = bufr[93]; header->norm_minute = bufr[94]; header->norm_second = bufr[95]; header->norm_day = bufr[96]; header->norm_month = bufr[97]; header->norm_year = bufr[98]; header->fov_source_width = mdc_get_vax_float((Uint16 *)bufr, 99); header->ecat_calib_factor = mdc_get_vax_float((Uint16 *)bufr, 101); return (0); } /* Following function was copied from CTI-source file 'matrix_extra.c' */ /* and slightly modified ... */ Int32 mdc_write_matrix_data(fptr, strtblk, nblks, dptr, dtype) FILE *fptr; Int32 strtblk, nblks, dtype; Uint8 *dptr; { Int32 err; switch (dtype) { case 1: /* byte format...no * translation necessary */ err = mdc_mat_wblk(fptr, strtblk, dptr, nblks); break; case 2: /* Vax I*2 */ err = mdc_mat_write_idata(fptr, strtblk, (Uint8 *)dptr, 512 * nblks); break; case 4: /* Vax R*4 */ err = mdc_mat_write_fdata(fptr, strtblk, (float *)dptr, 512 * nblks); break; case 5: /* IEEE R*4 */ err = mdc_mat_wblk(fptr, strtblk, dptr, nblks); break; case 6: /* 68K I*2 */ err = mdc_mat_wblk(fptr, strtblk, dptr, nblks); break; case 7: /* 68K I*4 */ err = mdc_mat_wblk(fptr, strtblk, dptr, nblks); break; default: /* something * else...treat as Vax * I*2 */ err = mdc_mat_write_idata(fptr, strtblk, (Uint8 *)dptr, 512 * nblks); break; } return (err); } /* code from mat_get_spec.c */ Int32 mdc_mat_get_spec (char *file, Int32 *num_frames, Int32 *num_planes, Int32 *num_gates, Int32 *num_bed) { struct Mdc_MatDir matrixlist[5000]; FILE *fptr; Int32 status, num_matrices, i; struct Mdc_Matval matnum; /* initialization */ status = 0; *num_frames = 0; *num_planes = 0; *num_gates = 0; *num_bed = 0; /* open the specified file */ fptr = mdc_mat_open (file, "r"); if (fptr != NULL) { /* get the matrix entries */ num_matrices = mdc_mat_list( fptr, matrixlist, 5000); for (i=0; i *num_frames) (*num_frames)++; if (matnum.plane > *num_planes) (*num_planes)++; if (matnum.gate > *num_gates) (*num_gates)++; if (matnum.bed > *num_bed) (*num_bed)++; } /* bed is zero based in the matrix number, but all numbers returned */ /* from this function will be one based */ (*num_bed)++; mdc_mat_close (fptr); } else status = 1; return(status); } /* code from sort_order.c */ static int mdc_compare_anatloc(const void *vi, const void *vj) { struct ExpMatDir *i, *j; i = (struct ExpMatDir *)vi; j = (struct ExpMatDir *)vj; if (i->anatloc < j->anatloc) return (-1); if (i->anatloc > j->anatloc) return (1); return (0); } /* matrix list by anatomical position */ void mdc_anatomical_sort (struct Mdc_MatDir matrix_list[], Int32 num_matrices, Mdc_Main_header *mhead, Int32 num_bed_pos) { struct Mdc_Matval matval; Int32 i, plane, bed; float bed_pos[16], plane_separation; struct ExpMatDir exp_matlist[5000]; bed_pos[0] = 0.0; for (i=1; i < num_bed_pos; i++) bed_pos[i] = mhead->bed_offset[i-1]; plane_separation = mhead->plane_separation; /* if plane separation not filled in main header, use plane number to sort */ if (plane_separation == 0.0) plane_separation = 1.0; for (i=0; i < num_matrices; i++) { mdc_mat_numdoc (matrix_list[i].matnum, &matval); plane = matval.plane; bed = matval.bed; exp_matlist[i].matnum = matrix_list[i].matnum; exp_matlist[i].strtblk = matrix_list[i].strtblk; exp_matlist[i].endblk = matrix_list[i].endblk; exp_matlist[i].matstat = matrix_list[i].matstat; exp_matlist[i].anatloc = bed_pos[bed]+(plane-1)*plane_separation; } qsort(exp_matlist,(unsigned)num_matrices ,sizeof(struct ExpMatDir) ,mdc_compare_anatloc); for (i=0; i < num_matrices; i++) { matrix_list[i].matnum = exp_matlist[i].matnum; matrix_list[i].strtblk = exp_matlist[i].strtblk; matrix_list[i].endblk = exp_matlist[i].endblk; matrix_list[i].matstat = exp_matlist[i].matstat; } } static int mdc_compmatdir(const void *vi, const void *vj) { struct Mdc_MatDir *i, *j; i = (struct Mdc_MatDir *)vi; j = (struct Mdc_MatDir *)vj; return((i->matnum - j->matnum)); } void mdc_matnum_sort(struct Mdc_MatDir mlist[], Int32 num_entry) { qsort(mlist,(unsigned)num_entry, sizeof(struct Mdc_MatDir), mdc_compmatdir); } /* sort by planes varying first */ void mdc_plane_sort (struct Mdc_MatDir matrix_list[], Int32 num_matrices) { struct Mdc_Matval matval; Int32 i, frame, plane, bed; struct ExpMatDir exp_matlist[5000]; for (i=0; i < num_matrices; i++) { mdc_mat_numdoc (matrix_list[i].matnum, &matval); plane = matval.plane; frame = matval.frame; bed = matval.bed; exp_matlist[i].matnum = matrix_list[i].matnum; exp_matlist[i].strtblk = matrix_list[i].strtblk; exp_matlist[i].endblk = matrix_list[i].endblk; exp_matlist[i].matstat = matrix_list[i].matstat; exp_matlist[i].anatloc = (float)(frame*1000 + plane*10 + bed); } qsort (exp_matlist,(unsigned)num_matrices ,sizeof(struct ExpMatDir) ,mdc_compare_anatloc); for (i=0; i < num_matrices; i++) { matrix_list[i].matnum = exp_matlist[i].matnum; matrix_list[i].strtblk = exp_matlist[i].strtblk; matrix_list[i].endblk = exp_matlist[i].endblk; matrix_list[i].matstat = exp_matlist[i].matstat; } }