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);
+