Mercurial > hg > minc-tools
changeset 1188:cc6ff7e9fda9
Initial revision
author | neelin <neelin> |
---|---|
date | Mon, 07 Dec 1998 19:37:33 +0000 |
parents | 84670a501005 |
children | b3d939a5ac3d |
files | conversion/mri_to_minc/gedicom_to_minc.pl |
diffstat | 1 files changed, 267 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/conversion/mri_to_minc/gedicom_to_minc.pl @@ -0,0 +1,267 @@ +# Subroutines for GE mri machines, version 6.x dicom + +# Routine to initialize tape drive +sub gedicom_initialize_tape_drive { + &cleanup_and_die("gedicom_to_minc does not support tape reading.\n",1); +} + +# Routine to get a string from the header +sub acr_find_string { + if (scalar(@_) != 3) { + die "Argument error in numaris3_find_string"; + } + local(*header, $group, $element) = @_; + + local($grstr) = sprintf("0x%04x", $group); + local($elstr) = sprintf("0x%04x", $element); + + return $header{$grstr, $elstr, 'string'}; +} + +# Routine to get an array of values from the header +sub acr_find_numeric { + local(@values) = split(/\\/, &acr_find_string(@_)); + foreach $value (@values) { + $value += 0; + } + return (scalar(@values) > 1) ? @values : $values[0]; +} + +# Routine to get an integer from the header +sub acr_find_int { + if (scalar(@_) != 3) { + die "Argument error in numaris3_find_int"; + } + local(*header, $group, $element) = @_; + + local($grstr) = sprintf("0x%04x", $group); + local($elstr) = sprintf("0x%04x", $element); + + return $header{$grstr, $elstr, 'short'}; +} + +# Routine to convert world coordinates +sub convert_coordinates { + local(@coords) = @_; + $coords[0] *= -1; + $coords[1] *= -1; + return @coords; +} + +# Routine to compute a dot product +sub vector_dot_product { + local(*vec1, *vec2) = @_; + local($result, $i); + $result = 0; + for $i (0..2) { + $result += $vec1[$i] * $vec2[$i]; + } + return $result; +} + +# Routine to compute a vector cross product +sub vector_cross_product { + local(*vec1, *vec2) = @_; + local(@result); + $#result = 2; + $result[0] = $vec1[1] * $vec2[2] - $vec1[2] * $vec2[1]; + $result[1] = $vec1[2] * $vec2[0] - $vec1[0] * $vec2[2]; + $result[2] = $vec1[0] * $vec2[1] - $vec1[1] * $vec2[0]; + return @result; +} + +# Subroutine to read the headers +sub gedicom_read_headers { + + # Set constants for reading file + local($header_maxid) = "0x0029"; + local($expected_manufacturer) = "GE MEDICAL SYSTEMS"; + + # Check arguements + if (scalar(@_) != 2) { + &cleanup_and_die("Argument error in gedicom_read_headers",1); + } + local($filename, *header) = @_; + + # Dump the header + local($group, $element, $data); + open(DUMP, "dump_acr_nema $filename $header_maxid|"); + while (<DUMP>) { + chop; + if (/^\s*(0x[\da-f]{4,4})\s+(0x[\da-f]{4,4})\s+length = \d+ :(.*)$/) { + $group = $1; + $element = $2; + $data = $3; + if ($data =~ /string = "(.*)"$/) { + $header{$group, $element, 'string'} = $1; + } + if ($data =~ /short = (\d+)/) { + $header{$group, $element, 'short'} = $1; + } + } + } + close(DUMP); + + # Check the return status + if ($? != 0) { + warn "Error dumping header for file $filename"; + return 1; + } + + # Check for magic in header + local($manufacturer) = &acr_find_string(*header, 0x8, 0x70); + if ($manufacturer ne $expected_manufacturer) { + warn "Unrecognized manufacturer \"$manufacturer\" - " . + "expected \"$expected_manufacturer\"\n"; + return 1; + } + + return 0; +} + +# Routine to get Numaris 3 file info +sub gedicom_read_file_info { + if (scalar(@_) != 3) { + &cleanup_and_die("Argument error in read_file_info",1); + } + local($filename, *file_info, *specific_file_info) = @_; + + # Get headers + local(%header); + undef(%header); + if (&gedicom_read_headers($filename, *header)) { + return 1; + } + + # Get interesting values + $file_info{'numechos'} = &acr_find_numeric(*header, 0x21, 0x107e); + if ($file_info{'numechos'} <= 0) {$file_info{'numechos'} = 1;} + $file_info{'exam'} = &acr_find_string(*header, 0x20, 0x10); + $file_info{'series'} = &acr_find_numeric(*header, 0x20, 0x11); + $file_info{'image'} = &acr_find_numeric(*header, 0x20, 0x13); + + $file_info{'echo'} = &acr_find_numeric(*header, 0x18, 0x86); + $file_info{'width'} = &acr_find_int(*header, 0x28, 0x11); + $file_info{'height'} = &acr_find_int(*header, 0x28, 0x10); + local($bits_alloc) = &acr_find_int(*header, 0x28, 0x100); + if ($bits_alloc != 16) { + warn "Wrong number of bits allocated per image ($bits_alloc)\n"; + return 1; + } + $file_info{'pixel_size'} = 2; + $file_info{'patient_name'} = &acr_find_string(*header, 0x10, 0x10); + + # Get slice position and orientation (row and column vectors) + local(@position) = + &convert_coordinates(&acr_find_numeric(*header, 0x20, 0x32)); + if (scalar(@position) != 3) { + warn "************** Error reading slice position ***************\n"; + } + local(@array) = &acr_find_numeric(*header, 0x20, 0x37); + if (scalar(@array) != 6) { + warn "************* Error reading slice orientation *************\n"; + } + local(@column) = &convert_coordinates(@array[0..2]); + local(@row) = &convert_coordinates(@array[3..5]); + + # Figure out normal and orientation + local(@normal) = + &vector_cross_product(*column, *row); + local($norm_r) = &abs($normal[0]); + local($norm_a) = &abs($normal[1]); + local($norm_s) = &abs($normal[2]); + local($plane) = 'transverse'; + local($max) = $norm_s; + if ($norm_r > $max) { + $plane = 'sagittal'; + $max = $norm_r; + } + if ($norm_a > $max) { + $plane = 'coronal'; + $max = $norm_a; + } + $file_info{'orientation'} = $plane; + + # Get coordinate information + local(@col_dircos, @row_dircos, @slc_dircos); + ($file_info{'rowstep'}, $file_info{'colstep'}) = + &acr_find_numeric(*header, 0x28, 0x30); + if (length($file_info{'rowstep'}) <= 0) { + $file_info{'colstep'} = $file_info{'rowstep'} = 1; + } + $file_info{'colstep'} *= -1.0; + $file_info{'rowstep'} *= -1.0; + @col_dircos = &get_dircos(@column); + @row_dircos = &get_dircos(@row); + @slc_dircos = &get_dircos(@normal); + $file_info{'slicepos'} = &vector_dot_product(*position, *slc_dircos); + $file_info{'colstart'} = &vector_dot_product(*position, *col_dircos); + $file_info{'rowstart'} = &vector_dot_product(*position, *row_dircos); + $file_info{'col_dircos_x'} = $col_dircos[0]; + $file_info{'col_dircos_y'} = $col_dircos[1]; + $file_info{'col_dircos_z'} = $col_dircos[2]; + $file_info{'row_dircos_x'} = $row_dircos[0]; + $file_info{'row_dircos_y'} = $row_dircos[1]; + $file_info{'row_dircos_z'} = $row_dircos[2]; + $file_info{'slc_dircos_x'} = $slc_dircos[0]; + $file_info{'slc_dircos_y'} = $slc_dircos[1]; + $file_info{'slc_dircos_z'} = $slc_dircos[2]; + + # Get other info + $file_info{'tr'} = &acr_find_numeric(*header, 0x18, 0x80)/1000; + $file_info{'te'} = &acr_find_numeric(*header, 0x18, 0x81)/1000; + $file_info{'ti'} = &acr_find_numeric(*header, 0x18, 0x82)/1000; + $file_info{'mr_flip'} = &acr_find_numeric(*header, 0x18, 0x1314); + ($file_info{'patient_age'} = &acr_find_string(*header, 0x10, 0x1010)) + =~ s/\D//g; + local($sex_flag) = &acr_find_string(*header, 0x10, 0x40); + if ($sex_flag eq 'M ') { + $file_info{'patient_sex'} = "male__"; + } + elsif ($sex_flag eq 'F ') { + $file_info{'patient_sex'} = "female"; + } + $file_info{'patient_id'} = &acr_find_string(*header, 0x10, 0x20); + $file_info{'institution'} = &acr_find_string(*header, 0x8, 0x80); + local($study_date, $study_time); + ($study_date = &acr_find_string(*header, 0x8, 0x22)) =~ s/\./-/g; + $study_time = &acr_find_string(*header, 0x8, 0x32); + $file_info{'start_time'} = "$study_date $study_time"; + + # Get specific file info + local($compression_code) = &acr_find_string(*header, 0x28, 0x60); + if (($compression_code ne "NONE") && ($compression_code ne "")) { + warn "File is compressed\n"; + return 1; + } + $specific_file_info{'pixel_data_group'} = "0x7fe0"; + $specific_file_info{'pixel_data_element'} = "0x10"; + + return 0; +} + +# Routine to get return command that will extract image +sub gedicom_get_image_cmd { + if (scalar(@_) != 2) { + &cleanup_and_die("Argument error in gedicom_get_image_cmd",1); + } + local($cur_file, *specific_file_info) = @_; + + local($cmd) = + "extract_acr_nema " . + $cur_file . " " . + $specific_file_info{'pixel_data_group'} . " " . + $specific_file_info{'pixel_data_element'} . " " . + " | byte_swap "; + + return $cmd; +} + +# MAIN PROGRAM + +*initialize_tape_drive = *gedicom_initialize_tape_drive; +*read_file_info = *gedicom_read_file_info; +*get_image_cmd = *gedicom_get_image_cmd; + +&mri_to_minc(@ARGV); +