char *RCSid="$Id: parse_files.c,v 1.1 2000/01/14 22:49:16 jwm Exp $"; /*********************************************************************** parse_files.c Description: Parse the directory entries for the various file types supported by the exchange format. The routines defined in this module are: Modules included: parse_comment_entry() Parse directory entries for a comment file and fill exch_cmnt_t data structure. parse_ct_entry() Parse directory entries for a CT scan file and fill ctscan_t data structure. parse_mr_entry() currently not implemented (Stub only) parse_us_entry() currently not implemented (Stub only) parse_anat_entry() Parse directory entries for anatomic structure files and fill structure_t data structure. parse_beam_entry() Parse directory entries for beam geometry and fill the beamgeom_t data structure. parse_seed_entry() Parse directory entries for seed geometry parse_film_entry() Parse directory entries for digital film files and fill the film_t data structure. parse_dose_entry() Parse directory entries for dose files and fill the dosedist_t data structure. parse_dvh_entry() Parse directory entries for DVH files and fill the dvh_t data structure. ************************ Revision History: $Log: parse_files.c,v $ * Revision 1.1 2000/01/14 22:49:16 jwm * Remove comments originating in other development trees * * Revision 1.0 2000/01/14 22:34:49 jwm * Initial revision * ================================================================== */ /* Include Files */ #include #include #include #include #include #include #include #include "sitedata.h" /* ONLY DECLARE THE EXTERNAL EXISTENCE OF THE KEYS */ #define NOT_MAIN #include "exchkeys.h" #include "patexchange.h" /* */ /**************************************************************************** parse_comment_entry() *************************************************************************** Functional Description: Parses all directory entries involved in comment files and puts appropriate information into the exch_cmnt_t structure. **************************************************************************/ int parse_comment_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ exch_cmnt_t *comment, /* COMMENT NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { *done = 1; return( SUCCESS ); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid COMMENT keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekWRITER: comment->writer = temp_buf2; break; case ekDATEWRITTEN: comment->date = temp_buf2; break; case ekUNITNUMBER: comment->unitnum = temp_buf2; break; case ekFILEOFORIGIN: comment->fileoforigin = temp_buf2; break; case ekCOMMENTDESCRIPTION: comment->description = temp_buf2; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Error. Invalid key for comment node" ); aapm_status( eAAPM_ERROR, aapm_log_string ); sprintf( aapm_log_string, " Key: %s", key_list[key] ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } } /* ALL IS WELL */ return( SUCCESS ); } /************************* End of parse_comment_entry() ******************/ /* */ /**************************************************************************** parse_ct_entry() *************************************************************************** Functional Description: Parses directory entries dedicated to ct scans and puts appropriate information into the ctscan_t data structure. **************************************************************************/ int parse_ct_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ ctscan_t *ctscan, /* CT NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ int temp_int; /* TEMPORARY INTEGER STORAGE */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { tape->offset = buf_ptr; *done = 1; /* ENSURE ALL REQUIRED KEYS HAVE BEEN USED */ return( key_check_ct( ctscan )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid CT SCAN keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekUNITNUMBER: ctscan->unit_number = temp_buf2; break; case ekSCANTYPE: /* SCAN ORIENTATION */ /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); ctscan->ct_flags.scan_f = 1; free( (void *)temp_buf2 ); if ( value != evTRANSVERSE ) { sprintf( aapm_log_string, "Invalid CT type (orientation)'%s'", key_value[value] ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } ctscan->scan_type = eTRANSVERSE; break; case ekCTOFFSET: ctscan->ct_offset = atoi( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.offset_f = 1; break; case ekGRID1UNITS: ctscan->pixel_width = atof( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.grid1_f = 1; break; case ekGRID2UNITS: ctscan->pixel_length = atof( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.grid2_f = 1; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evTWOSCOMP ) { sprintf( aapm_log_string, "Invalid CT pixel representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } ctscan->number_type = eTWOSCOMP; ctscan->ct_flags.number_f = 1; break; case ekBYTESPERPIXEL: if ( (temp_int = atoi( temp_buf2 )) != 2 ) { sprintf( aapm_log_string, "Wrong number of bytes per pixel (%d)", temp_int ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } ctscan->bytes_per_pixel = temp_int; ctscan->ct_flags.bytes_f = 1; free( (void *)temp_buf2 ); break; case ekNUMBEROFDIMENSIONS: if ( (temp_int = atoi( temp_buf2 )) != 2 ) { sprintf( aapm_log_string, "Error. Wrong number of ct dimensions (%d)", temp_int ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } ctscan->num_dimensions = temp_int; ctscan->ct_flags.num_dim_f = 1; free( (void *)temp_buf2 ); break; case ekSIZEOFDIMENSION1: ctscan->dimension_1 = atoi( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.siz_dim1_f = 1; break; case ekSIZEOFDIMENSION2: ctscan->dimension_2 = atoi( temp_buf2 ); ctscan->ct_flags.siz_dim2_f = 1; free( (void *)temp_buf2 ); break; case ekZVALUE: ctscan->z_value = atof( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.z_value_f = 1; break; case ekXOFFSET: ctscan->x_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.x_offset_f = 1; break; case ekYOFFSET: ctscan->y_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.y_offset_f = 1; break; case ekCTAIR: ctscan->ct_air = atoi( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.ct_air_f = 1; break; case ekCTWATER: ctscan->ct_water = atoi( temp_buf2 ); free( (void *)temp_buf2 ); ctscan->ct_flags.ct_water_f = 1; break; case ekSITEOFINTEREST: ctscan->site = temp_buf2; break; case ekSCANDESCRIPTION: ctscan->description = temp_buf2; break; case ekSCANNERTYPE: ctscan->scanner_type = temp_buf2; break; case ekHEADIN: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evIN: /* HEAD IN */ ctscan->head = eHEAD_IN; break; case evOUT: /* HEAD OUT */ ctscan->head = eHEAD_OUT; break; default: sprintf( aapm_log_string, "Error. Illegal IN/OUT orientation '%s' assuming head in", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); ctscan->head = eHEAD_IN; /* HEAD IN */ break; } free( (void *)temp_buf2 ); break; case ekPOSITIONINSCAN: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evNOSEUP: /* NOSE UP */ ctscan->position = eNOSEUP; break; case evNOSEDOWN: /* NOSE DOWN */ ctscan->position = eNOSEDOWN; break; case evLEFTSIDEDOWN: /* LEFT SIDE DOWN */ ctscan->position = eLEFTSIDEDOWN; break; case evRIGHTSIDEDOWN: /* RIGHT SIDE DOWN */ ctscan->position = eRIGHTSIDEDOWN; break; default: sprintf( aapm_log_string, "Illegal Position In Scan orientation '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); break; } free( (void *)temp_buf2 ); break; case ekPATIENTATTITUDE: ctscan->attitude = temp_buf2; break; case ekTAPEOFORIGIN: ctscan->tape_of_origin = temp_buf2; break; case ekSCANID: ctscan->scan_id = temp_buf2; break; case ekSCANNUMBER: ctscan->scan_number = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekSCANDATE: ctscan->scan_date = temp_buf2; break; case ekSCANFILENAME: ctscan->scan_file = temp_buf2; break; case ekSLICETHICKNESS: ctscan->slice_thick = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekCTSCALE: ctscan->ct_scale = temp_buf2; break; case ekDISTRUSTABOVE: ctscan->distrust = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekSTUDYNUMBEROFORIGIN: ctscan->study_number = temp_buf2; break; case ekIMAGESOURCE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evSECONDARYCAPTURE ) { sprintf( aapm_log_string, "Invalid CT Image Source '%s'", key_value[value] ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } ctscan->image_source = eSECONDARYCAPTURE; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Invalid key for CT scans%s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } } /* ENSURE ALL REQUIRED KEYS HAVE BEEN USED */ return( key_check_ct( ctscan )); } /************************ End of parse_ct_entry() ************************/ /* */ /*********************************************************************** parse_mrus_entry() ********************************************************************** Functional Description: Parses directory entries dedicated to MR or US scans and puts appropriate information into the mrusscan_t data structure. *********************************************************************/ int parse_mrus_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ mrusscan_t *mrusscan, /* MR/US NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ int temp_int; /* TEMPORARY INTEGER STORAGE */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { tape->offset = buf_ptr; *done = 1; /* ENSURE ALL REQUIRED KEYS HAVE BEEN USED */ return( key_check_mrus( mrusscan )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid MR/US SCAN keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekSCANTYPE: /* SCAN ORIENTATION */ /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); mrusscan->mrus_flags.scan_f = 1; free( (void *)temp_buf2 ); if ( value != evTRANSVERSE ) { sprintf( aapm_log_string, "Invalid MR/US type (orientation)'%s'", key_value[value] ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } mrusscan->scan_type = eTRANSVERSE; break; case ekPIXELOFFSET: mrusscan->offset = atoi( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.offset_f = 1; break; case ekGRID1UNITS: mrusscan->pixel_width = atof( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.grid1_f = 1; break; case ekGRID2UNITS: mrusscan->pixel_length = atof( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.grid2_f = 1; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evTWOSCOMP ) { sprintf( aapm_log_string, "Invalid MR/US pixel representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } mrusscan->number_type = eTWOSCOMP; mrusscan->mrus_flags.number_f = 1; break; case ekBYTESPERPIXEL: if ( (temp_int = atoi( temp_buf2 )) != 2 ) { sprintf( aapm_log_string, "Wrong number of bytes per pixel (%d)", temp_int ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } mrusscan->bytes_per_pixel = temp_int; mrusscan->mrus_flags.bytes_f = 1; free( (void *)temp_buf2 ); break; case ekNUMBEROFDIMENSIONS: if ( (temp_int = atoi( temp_buf2 )) != 2 ) { sprintf( aapm_log_string, "Error. Wrong number of MR/US dimensions (%d)", temp_int ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } mrusscan->num_dimensions = temp_int; mrusscan->mrus_flags.num_dim_f = 1; free( (void *)temp_buf2 ); break; case ekSIZEOFDIMENSION1: mrusscan->dimension_1 = atoi( temp_buf2 ); mrusscan->mrus_flags.siz_dim1_f = 1; free( (void *)temp_buf2 ); break; case ekSIZEOFDIMENSION2: mrusscan->dimension_2 = atoi( temp_buf2 ); mrusscan->mrus_flags.siz_dim2_f = 1; free( (void *)temp_buf2 ); break; case ekZVALUE: mrusscan->z_value = atof( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.z_value_f = 1; break; case ekXOFFSET: mrusscan->x_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.x_offset_f = 1; break; case ekYOFFSET: mrusscan->y_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); mrusscan->mrus_flags.y_offset_f = 1; break; case ekSCANDATE: mrusscan->scan_date = temp_buf2; break; case ekIMAGESOURCE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evSECONDARYCAPTURE ) { sprintf( aapm_log_string, "Invalid MR/US Image Source '%s'", key_value[value] ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } mrusscan->image_source = eSECONDARYCAPTURE; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Invalid key for MR/US scans%s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } } /* ENSURE ALL REQUIRED KEYS HAVE BEEN USED */ return( key_check_mrus( mrusscan )); } /************************** End of parse_mrus_entry() *****************/ /* */ /*************************************************************************** parse_anat_entry() ************************************************************************** Functional Description: Parses directory entries dedicated to anatomic structures into the structure_t data structure. **************************************************************************/ int parse_anat_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ structure_t *structure, /* STRUCTURE NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { *done = 1; /* CHECK THAT ALL REQUIRED KEYS SET */ return( key_check_anat( structure )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid STRUCTURE keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekDATEWRITTEN: structure->date = temp_buf2; break; case ekWRITER: structure->writer = temp_buf2; break; case ekUNITNUMBER: structure->unit_number = temp_buf2; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evCHARACTER ) { sprintf( aapm_log_string, "Invalid contour representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } structure->number_type = eCHARACTER; structure->struct_flags.number_f = 1; break; case ekSTRUCTURENAME: structure->struct_name = temp_buf2; structure->struct_flags.struct_name_f = 1; break; case ekSTRUCTUREFORMAT: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evSCANBASED ) { sprintf( aapm_log_string, "Invalid contour basing: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } structure->stype = eSCANBASED; structure->struct_flags.base_f = 1; break; case ekNUMBEROFSCANS: structure->num_scans = atoi( temp_buf2 ); free( (void *)temp_buf2 ); structure->struct_flags.n_scans_f = 1; break; case ekMAXIMUMNUMBERSCANS: structure->max_scans = atoi( temp_buf2 ); free( (void *)temp_buf2 ); structure->struct_flags.max_scans_f = 1; break; case ekMAXIMUMPOINTSPERSEGMENT: structure->max_pts_segment = atoi( temp_buf2 ); free( (void *)temp_buf2 ); structure->struct_flags.max_pts_f = 1; break; case ekMAXIMUMSEGMENTSPERSCAN: structure->max_seg_scan = atoi( temp_buf2 ); free( (void *)temp_buf2 ); structure->struct_flags.max_seg_f = 1; break; case ekSTRUCTUREEDITION: structure->edition = temp_buf2; break; case ekSTRUCTURECOLOR: structure->color = temp_buf2; break; case ekSTRUCTUREDESCRIPTION: structure->description = temp_buf2; break; case ekSTUDYNUMBEROFORIGIN: structure->study_num = atoi( temp_buf2 ); free( temp_buf2 ); break; case ekORIENTATIONOFSTRUCTURE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evTRANSVERSE ) { sprintf( aapm_log_string, "Invalid contour basing '%s'", key_value[ value ] ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } structure->orientation = eTRANSVERSE; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; } } /* CHECK THAT ALL REQUIRED KEYS SET */ return( key_check_anat( structure )); } /************************* End of parse_anat_entry() *********************/ /* */ /**************************************************************************** parse_beam_entry() *************************************************************************** Functional Description: Parses directory entries dedicated to beam geometry. **************************************************************************/ int parse_beam_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ beamgeom_t *beam, /* BEAM NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { tape->offset = buf_ptr; *done = 1; /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_beam( beam )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid BEAM keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekBEAMNUMBER: beam->beam_number = atoi( temp_buf2 ); beam->beam_flags.beam_num_f = 1; free( (void *)temp_buf2 ); break; case ekBEAMMODALITY: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evXRAY: /* PHOTON BEAM */ beam->modality = eXRAY_BEAM; break; case evELECTRON: /* ELECTRON BEAM */ beam->modality = eELECTRON_BEAM; break; case evPROTON: /* PROTON BEAM */ beam->modality = ePROTON_BEAM; break; case evNEUTRON: /* NEUTRON BEAM */ beam->modality = eNEUTRON_BEAM; break; default: sprintf( aapm_log_string, "Invalid beam modality '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); beam->beam_flags.modality_f = 1; break; case ekBEAMENERGYMEV: beam->beam_energy = atof( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.energy_f = 1; break; case ekBEAMDESCRIPTION: beam->description = temp_buf2; beam->beam_flags.beam_des_f = 1; break; case ekRXDOSEPERTXGY: beam->rx_dose_per_tx = atof( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.dose_p_tx_f = 1; break; case ekNUMBEROFTX: beam->number_of_treatments = atoi( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.number_tx_f = 1; break; case ekFRACTIONGROUPID: beam->fraction_group_id = temp_buf2; beam->beam_flags.fraction_id_f = 1; break; case ekBEAMTYPE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evSTATIC: /* STATIC BEAM */ beam->beamtype = eSTATIC; break; case evARC: /* ARC BEAM */ beam->beamtype = eARC; break; default: sprintf( aapm_log_string, "Error. Invalid beam type '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); beam->beam_flags.beamtype_f = 1; break; case ekHEADIN: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evIN: /* HEAD IN */ beam->orientation = eHEAD_IN; break; case evOUT: /* HEAD OUT */ beam->orientation = eHEAD_OUT; break; default: sprintf( aapm_log_string, "Error. Illegal beam IN/OUT orientation '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); break; case ekPLANIDOFORIGIN: beam->plan_id_of_origin = temp_buf2; beam->beam_flags.plan_id_f = 1; break; case ekCOLLIMATORTYPE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evSYMMETRIC: /* SYMMETRIC COLLIMATORS */ beam->collimator = eSYMMETRIC; break; case evASYMMETRIC: /* ASYMMETRIC COLLIMATORS */ beam->collimator = eASYMMETRIC; break; case evASYMMETRIC_X: /* ASYMMETRIC IN X COLLIMATORS */ beam->collimator = eASYMMETRIC_X; break; case evASYMMETRIC_Y: /* ASYMMETRIC IN Y COLLIMATORS */ beam->collimator = eASYMMETRIC_Y; break; default: sprintf( aapm_log_string, "Error. Invalid collimator type '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); beam->beam_flags.coll_typ_f = 1; break; case ekAPERTURETYPE: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evBLOCK: /* APERTURE DEFINED BY BLOCK */ beam->aperture = eBLOCK_PORT; break; case evMLC_X: /* MLC IN X */ beam->aperture = eMLC_X_AXIS; break; case evMLC_Y: /* MLC IN Y */ beam->aperture = eMLC_Y_AXIS; break; case evMLC_XY: /* MLC IN X AND Y */ beam->aperture = eMLC_XY_AXIS; break; case evCOLLIMATOR: /* COLLIMATOR ONLY */ beam->aperture = eCOLLIMATOR; break; default: sprintf( aapm_log_string, "Error. Invalid aperture type '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); beam->beam_flags.aper_typ_f = 1; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evCHARACTER ) { sprintf( aapm_log_string, "Invalid beam representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } beam->number_type = eCHARACTER; beam->beam_flags.number_f = 1; break; case ekAPERTUREDESCRIPTION: beam->aperture_description = temp_buf2; beam->beam_flags.aper_des_f = 1; break; case ekCOLLIMATORANGLE: beam->collimator_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.coll_ang_f = 1; break; case ekGANTRYANGLE: beam->gantry_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.gantry_ang_f = 1; break; case ekCOUCHANGLE: beam->couch_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.couch_ang_f = 1; break; case ekNOMINALISOCENTERDIST: beam->nominal_isocenter_dist = atof( temp_buf2 ); free( (void *)temp_buf2 ); beam->beam_flags.iso_dist_f = 1; break; case ekAPERTUREID: beam->aperture_id = temp_buf2; break; case ekWEDGEANGLE: beam->wedge_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekWEDGEROTATIONANGLE: beam->wedge_rotation_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekARCANGLE: beam->arc_angle = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekCOMPENSATOR: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); switch( value ) { case evNONE: beam->compensator = eNO_CF; break; case ev1D_X: beam->compensator = e1DX_CF; break; case ev1D_Y: beam->compensator = e1DY_CF; break; case ev2D: beam->compensator = e2D_CF; break; case ev3D: beam->compensator = e3D_CF; break; default: sprintf( aapm_log_string, "Illegal compensating filter type '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Invalid key for beam geometry: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); break; } } /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_beam( beam )); } /************************* End of parse_beam_entry() *********************/ /* */ /*********************************************************************** parse_seed_entry() ********************************************************************** Functional Description: Parses directory entries dedicated to seed geometry. *********************************************************************/ int parse_seed_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ seeddata_t *seedgeom, /* SEED NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { tape->offset = buf_ptr; *done = 1; /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_seed( seedgeom )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid SEED keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekSEEDMODEL: seedgeom->seed_model = temp_buf2; seedgeom->seed_flags.model_f = 1; break; case ekSEEDISOTOPE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch (value ) { case evI125: seedgeom->isotope = eI125; break; case evPD103: seedgeom->isotope = ePD103; break; default: sprintf(aapm_log_string,"Invalid seed isotope '%s'",temp_buf2); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } free( temp_buf2 ); seedgeom->seed_flags.isotope_f = 1; break; case ekSEEDSTRENGTH: seedgeom->strength = atof(temp_buf2); free( temp_buf2 ); seedgeom->seed_flags.strength_f = 1; break; case ekSEEDSTRENGTHUNITS: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch (value ) { case evMCI: seedgeom->units = eMCI; break; case evCGYCM2PERHR: seedgeom->units = eCGYCM2PERHR; break; default: sprintf(aapm_log_string,"Invalid seed strength units '%s'", temp_buf2); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } free( temp_buf2 ); seedgeom->seed_flags.units_f = 1; break; case ekDATEOFIMPLANT: seedgeom->date = temp_buf2; seedgeom->seed_flags.date_f = 1; break; case ekNUMBEROFSEEDS: seedgeom->nseeds = atoi( temp_buf2 ); free( temp_buf2 ); seedgeom->seed_flags.nseeds_f = 1; break; case ekNUMBERREPRESENTATION: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( temp_buf2 ); if ( value != evCHARACTER ) { sprintf( aapm_log_string, "Invalid seed number representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } seedgeom->number_type = eCHARACTER; seedgeom->seed_flags.number_f = 1; break; case ekPLANIDOFORIGIN: seedgeom->plan_id_of_origin = temp_buf2; seedgeom->seed_flags.plan_id_f = 1; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Invalid key for seed geometry: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); break; } } /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_seed( seedgeom )); } /************************* End of parse_seed_entry() *********************/ /* */ /**************************************************************************** parse_film_entry() *************************************************************************** Functional Description: Parses directory entries dedicated to digital film image files. **************************************************************************/ int parse_film_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ film_t *film, /* FILM NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; /* INITIALIZE THE BEAM NUMBER TO TRAP ORPHAN FILMS */ film->beam_number = -1; /* PROCESS ENTRIES UNTIL NEXT IMAGE STUMBLED UPON */ for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { tape->offset = buf_ptr; *done = 1; /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_film( film )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid DIGITAL FILM keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekBEAMNUMBER: film->beam_number = atoi( temp_buf2 ); film->film_flags.beam_num_f = 1; free( (void *)temp_buf2 ); break; case ekBEAMDESCRIPTION: film->beam_description = temp_buf2; film->film_flags.beam_des_f = 1; break; case ekFILMNUMBER: film->film_number = atoi( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.film_num_f = 1; break; case ekFILMDATE: film->film_date = temp_buf2; film->film_flags.film_date_f = 1; break; case ekFILMTYPE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evDRR: /* IMAGE IS DRR */ film->type = eDRR; break; case evSIMULATOR: /* IMAGE IS SIM FILM */ film->type = eSIMULATOR; break; case evPORT: /* IMAGE IS PORT FILM */ film->type = exPORT; break; default: sprintf( aapm_log_string, "Error. Invalid film type '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); film->film_flags.film_type_f = 1; break; case ekNUMBEROFDIMENSIONS: film->number_of_dimensions = atoi( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.num_dim_f = 1; break; case ekSIZEOFDIMENSION1: film->size_of_dimension1 = atof( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.siz_dim1_f = 1; break; case ekSIZEOFDIMENSION2: film->size_of_dimension2 = atof( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.siz_dim2_f = 1; break; case ekGRID1UNITS: film->grid_1_units = atof( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.grid1_f = 1; break; case ekGRID2UNITS: film->grid_2_units = atof( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.grid2_f = 1; break; case ekSOURCEIMAGEDISTANCE: film->source_image_distance = atof( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.src_img_dis_f = 1; break; case ekNUMBERREPRESENTATION: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); /* ENSURE THAT THE NUMBER TYPE IS SUPPORTED */ if ( value != evTWOSCOMP && value != evUNSIGNEDBYTE ) { sprintf( aapm_log_string, "Invalid film pixel number representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } if ( value == evTWOSCOMP ) film->number_type = eTWOSCOMP; else film->number_type = eUNSIGNEDBYTE; film->film_flags.number_f = 1; break; case ekBYTESPERPIXEL: /* BYTES PER PIXEL IN IMAGE */ film->bytes_per_pixel = atoi( temp_buf2 ); free( (void *)temp_buf2 ); film->film_flags.bytes_f = 1; break; case ekXOFFSET: film->x_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekYOFFSET: film->y_offset = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekFILMDESCRIPTION: film->film_description = temp_buf2; film->film_flags.filmdesc_f = 1; break; case ekFILMSOURCE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evFILM: /* DIGITIZED FILM */ film->source = exFILM; break; case evONLINE: /* ONLINE IMAGE */ film->source = eONLINE; break; case evCOMPUTED: /* COMPUTED IMAGE (DRR) */ film->source = eCOMPUTED_IMAGE; break; default: sprintf( aapm_log_string, "Error. Invalid film source '%s'", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); break; case ekUNITNUMBER: film->unit_number = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekODSCALE: film->od_scale = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekBITSPERPIXEL: film->bits_per_pixel = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekCOLLIMATORANGLE: film->collimator_angle = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; } } /* CHECK THAT ALL REQUIRED KEYS USED */ return( key_check_film( film )); } /************************ End of parse_film_entry() **********************/ /* */ /**************************************************************************** parse_dose_entry() *************************************************************************** Functional Description: Parses directory entries dedicated to dose distributions and puts the appropriate information into the dosedist_t data structure. **************************************************************************/ int parse_dose_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ dosedist_t *dose, /* DOSE NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ int temp_int; /* TEMP INT STORAGE */ /* INITIALIZE THE DOSE SCALE VALUE SINCE IT HAS A DEFAULT VALUE */ dose->dose_scale = 1.0; /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { *done = 1; /* CHECK KEY WORDS USED AND RETURN OK IF ALL REQUIRED ONES USED */ return( key_check_dose( dose )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid DOSE keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekDATEWRITTEN: dose->date = temp_buf2; break; case ekWRITER: dose->writer = temp_buf2; break; case ekUNITNUMBER: dose->unit_number = temp_buf2; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); if ( value != evCHARACTER ) { sprintf( aapm_log_string, "Invalid dose representation: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } free( (void *)temp_buf2 ); dose->number_type = eCHARACTER; dose->dose_flags.number_f = 1; break; case ekDOSENUMBER: dose->dose_number = atoi( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.dose_num_f = 1; break; case ekDOSETYPE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evPHYSICAL: dose->dose_flavor = ePHYSICAL; break; case evEFFECTIVE: dose->dose_flavor = eEFFECTIVE; break; case evLET: dose->dose_flavor = eLET; break; case evOER: dose->dose_flavor = eOER; break; case evERROR: dose->dose_flavor = eERROR; break; default: sprintf( aapm_log_string, "Invalid dose type: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); dose->dose_flags.dose_type_f = 1; break; case ekDOSEUNITS: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evGRAYS: case evCGE: /* Cobalt Gray Equivalent */ dose->dose_units = eGRAYS; break; case evRADS: dose->dose_units = eRADS; break; case evCGYS: dose->dose_units = eCGYS; break; case evPERCENT: dose->dose_units = ePERCENT; break; case evRELATIVE: dose->dose_units = eRELATIVE; break; default: sprintf( aapm_log_string, "Invalid dose units (%s)", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } dose->dose_flags.dose_unit_f = 1; free( (void *)temp_buf2 ); break; case ekORIENTATIONOFDOSE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); switch( value ) { case evTRANSVERSE: dose->orientation = eTRANSVERSE; break; case evSAGITTAL: dose->orientation = eSAGITTAL; break; case evCORONAL: dose->orientation = eCORONALL; break; default: sprintf( aapm_log_string, "Invalid dose orientation: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } dose->dose_flags.orientat_f = 1; break; case ekNUMBEROFDIMENSIONS: if ( (temp_int = atoi( temp_buf2 )) != 3 ) { sprintf( aapm_log_string, "Error. Wrong number of dose dimensions (%d)", temp_int ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } dose->num_dimensions = temp_int; dose->dose_flags.num_dim_f = 1; free( (void *)temp_buf2 ); break; case ekSIZEOFDIMENSION1: if ( (dose->num_horiz_pts = atoi( temp_buf2 )) < 2 ) { sprintf( aapm_log_string, "Incorrect horizontal dose matrix count (%d)", dose->num_horiz_pts ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } free( (void *)temp_buf2 ); dose->dose_flags.siz_dim1_f = 1; break; case ekSIZEOFDIMENSION2: if ( (dose->num_vert_pts = atoi( temp_buf2 )) < 2 ) { sprintf( aapm_log_string, "Incorrect vertical dose matrix count (%d)", dose->num_vert_pts ); aapm_status( eAAPM_ERROR, aapm_log_string ); free( (void *)temp_buf2 ); return( FAILURE ); } free( (void *)temp_buf2 ); dose->dose_flags.siz_dim2_f = 1; break; case ekSIZEOFDIMENSION3: if ( (dose->num_planes = atoi( temp_buf2 )) < 2 ) { sprintf( aapm_log_string, "Incorrect dose matrix plane count (%d-%s) forcing to 2", dose->num_planes, temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); dose->num_planes = 2; } free( (void *)temp_buf2 ); dose->dose_flags.siz_dim3_f = 1; break; case ekCOORD1OFFIRSTPOINT: dose->first_coord = atof( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.coord1_f = 1; break; case ekCOORD2OFFIRSTPOINT: dose->second_coord = atof( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.coord2_f = 1; break; case ekHORIZONTALGRIDINTERVAL: dose->horiz_step = atof( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.horiz_f = 1; break; case ekVERTICALGRIDINTERVAL: dose->vert_step = atof( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.vert_f = 1; break; case ekDOSEDESCRIPTION: dose->description = temp_buf2; break; case ekDOSEEDITION: dose->edition = temp_buf2; break; case ekPLANNUMBEROFORIGIN: dose->plan_num = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekPLANEDITIONOFORIGIN: dose->plan_edition = temp_buf2; break; case ekSTUDYNUMBEROFORIGIN: dose->study_num = atoi( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekVERSIONNUMBEROFPROGRAM: dose->version = temp_buf2; break; case ekXCOORDOFNORMALIZNPOINT: dose->norm_pt.x = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekYCOORDOFNORMALIZNPOINT: dose->norm_pt.y = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekZCOORDOFNORMALIZNPOINT: dose->norm_pt.z = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekDOSEATNORMALIZNPOINT: dose->norm_dose = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; case ekDOSEERROR: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); switch( value ) { case evNOMINAL: dose->dose_error = eNOM_DOSE; break; case evMINIMUM: dose->dose_error = eMIN_DOSE; break; case evMAXIMUM: dose->dose_error = eMAX_DOSE; break; default: sprintf( aapm_log_string, "Invalid dose error type: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } break; case ekNUMBEROFTX: dose->number_of_treatments = atoi( temp_buf2 ); free( (void *)temp_buf2 ); dose->dose_flags.num_tx_f = 1; break; case ekFRACTIONGROUPID: dose->fraction_group_id = temp_buf2; dose->dose_flags.fraction_id_f = 1; break; case ekDOSESCALE: dose->dose_scale = atof( temp_buf2 ); free( (void *)temp_buf2 ); break; default: sprintf( aapm_log_string, "Invalid key for dose files: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; } } /* CHECK KEY WORDS USED AND RETURN OK IF ALL REQUIRED ONES USED */ return( key_check_dose( dose )); } /************************ End of parse_dose_entry() **********************/ /* */ /**************************************************************************** parse_dvh_entry() *************************************************************************** Functional Description: Parses directory entries dedicated to dose-volume histograms and puts the appropriate information into the dvh_t data structure. **************************************************************************/ int parse_dvh_entry ( tapedir_t *tape, /* TAPE DIRECTORY STRUCTURE */ dvh_t *dvh, /* DOSE NODE TO FILL */ int *done /* FLAG TO SIGNAL END OF DIRECTORY */ ) { char temp_buf[MAX_LINE_LENGTH]; /* TEMP STRING STORAGE */ char *temp_buf2; /* TEMP STRING STORAGE */ int buf_ptr; /* LOCAL DATA BLOCK OFFSET INDEX */ int key; /* NUMBER OF KEY OF ENTRY */ int value; /* NUMBER OF KEY VALUE ENTRY */ /* INITIALIZE THE DOSE SCALE VALUE SINCE IT HAS A DEFAULT VALUE */ dvh->dose_scale = 1.0; dvh->volume_scale = 1.0; /* INITIALIZE THE BUFFER POINTER */ buf_ptr = tape->offset; for(key = ekUNDEFINEDKEY; key != ekIMAGENUMBER; ) { /* UPDATE OFFSET SINCE LAST ENTRY WAS NOT ekIMAGENUMBER */ tape->offset = buf_ptr; if ( extract_line( tape->block_data, &buf_ptr, tape->data_size, temp_buf, MAX_LINE_LENGTH ) == FAILURE ) { *done = 1; /* CHECK KEY WORDS USED AND RETURN OK IF ALL REQUIRED ONES USED */ return( key_check_dvh( dvh )); } /* IGNORE BLANK LINES */ if ( strlen( temp_buf ) == 0 ) continue; /* PARSE THE ENTRY */ if ( (key = parse_key( temp_buf, key_list, NUM_KEYS, &temp_buf2 )) < 0 ) { *strchr( temp_buf, (int)':' ) = '\0'; sprintf( aapm_log_string, "Invalid DVH keyword: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); continue; } /* ASSIGN THE APPROPRIATE FIELD */ switch( key ) { case ekIMAGENUMBER: break; case ekSTRUCTURENAME: dvh->struct_name = temp_buf2; dvh->dvh_flags.name_f = 1; break; case ekPLANIDOFORIGIN: dvh->plan_id_of_origin = temp_buf2; dvh->dvh_flags.plan_id_f = 1; break; case ekDOSEUNITS: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); switch( value ) { case evGRAYS: case evCGE: /* Cobalt Gray Equivalent */ dvh->dose_units = eGRAYS; break; case evRADS: dvh->dose_units = eRADS; dvh->dose_scale /= 100.; break; case evCGYS: dvh->dose_units = eCGYS; dvh->dose_scale /= 100.; break; default: sprintf( aapm_log_string, "Invalid DVH dose units (%s)", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } free( (void *)temp_buf2 ); dvh->dvh_flags.dose_unit_f = 1; break; case ekDOSETYPE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); switch( value ) { case evPERCENT: dvh->dose_flavor = ePERCENT; dvh->dose_scale /= 100.; break; case evRELATIVE: dvh->dose_flavor = eRELATIVE; break; case evABSOLUTE: dvh->dose_flavor = eABSOLUTE; break; default: sprintf( aapm_log_string, "Invalid DVH dose type: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } dvh->dvh_flags.dose_flav_f = 1; break; case ekVOLUMETYPE: value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); switch( value ) { case evPERCENT: dvh->volume_flavor = ePERCENT; dvh->volume_scale /= 100.; break; case evRELATIVE: dvh->volume_flavor = eRELATIVE; break; case evABSOLUTE: dvh->volume_flavor = eABSOLUTE; break; default: sprintf( aapm_log_string, "Invalid DVH volume type: %s", temp_buf2 ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } dvh->dvh_flags.vol_flav_f = 1; break; case ekNUMBEROFPAIRS: dvh->number_of_pairs = atoi( temp_buf2 ); free( (void *)temp_buf2 ); dvh->dvh_flags.num_pairs_f = 1; break; case ekMAXIMUMNUMBERPAIRS: dvh->maximum_number_of_pairs = atoi( temp_buf2 ); free( (void *)temp_buf2 ); dvh->dvh_flags.max_pairs_f = 1; break; case ekNUMBERREPRESENTATION: /* PARSE THE KEY VALUE */ value = parse_value( temp_buf2, key_value, NUM_KEY_VALS ); free( (void *)temp_buf2 ); if ( value != evCHARACTER ) { sprintf( aapm_log_string, "Invalid DVH dose representation" ); aapm_status( eAAPM_ERROR, aapm_log_string ); return( FAILURE ); } dvh->number_type = eCHARACTER; dvh->dvh_flags.number_f = 1; break; case ekDOSESCALE: dvh->dose_scale *= atof( temp_buf2 ); free( (void *)temp_buf2 ); dvh->dvh_flags.dose_scale_f = 1; break; case ekVOLUMESCALE: dvh->volume_scale *= atof( temp_buf2 ); free( (void *)temp_buf2 ); dvh->dvh_flags.vol_scale_f = 1; break; case ekDATEOFDVH: dvh->date = temp_buf2; break; case ekUNDEFINEDKEY: /* DON'T DO ANYTHING. MUST BE A BLANK LINE */ break; default: sprintf( aapm_log_string, "Invalid key for DVH files: %s", temp_buf ); aapm_status( eAAPM_ERROR, aapm_log_string ); break; } } /* CHECK KEY WORDS USED AND RETURN OK IF ALL REQUIRED ONES USED */ return( key_check_dvh( dvh )); } /************************** End of parse_dvh_entry() **********************/ /************************* End of parse_files.c ***************************/