changeset 1548:a5e748f9c8e9

Initial revision
author leili <leili>
date Fri, 15 Aug 2003 19:52:55 +0000
parents 35cf668141e6
children b0914f99a1b7 1d0c45b189b6
files conversion/dicomserver_sonata/Makefile conversion/dicomserver_sonata/dcm2mnc.c conversion/dicomserver_sonata/dcm2mnc2.c conversion/dicomserver_sonata/dicom_element_defs.c conversion/dicomserver_sonata/dicom_element_defs.h conversion/dicomserver_sonata/dicom_prototypes.h conversion/dicomserver_sonata/dicomreader.c conversion/dicomserver_sonata/dicomserver-debug.c conversion/dicomserver_sonata/dicomserver-nondebug.c conversion/dicomserver_sonata/dicomserver-nondebug2.c conversion/dicomserver_sonata/dicomserver.h conversion/dicomserver_sonata/ext_element_defs.h conversion/dicomserver_sonata/minc_file.c conversion/dicomserver_sonata/modify_group_list.c conversion/dicomserver_sonata/open_connection.c conversion/dicomserver_sonata/parse_dicom_groups.c conversion/dicomserver_sonata/progress.c conversion/dicomserver_sonata/project_file.c conversion/dicomserver_sonata/reply.c conversion/dicomserver_sonata/save_transferred_object.c conversion/dicomserver_sonata/siemens_dicom_read.c conversion/dicomserver_sonata/siemens_dicom_send.c conversion/dicomserver_sonata/siemens_dicom_to_minc.c conversion/dicomserver_sonata/siemens_dicom_to_minc.h conversion/dicomserver_sonata/siemens_header_table.h conversion/dicomserver_sonata/siemens_include/STC_Common_Status.h conversion/dicomserver_sonata/siemens_include/ds_date.h conversion/dicomserver_sonata/siemens_include/ds_functions.h conversion/dicomserver_sonata/siemens_include/ds_head_acr_groups_types.h conversion/dicomserver_sonata/siemens_include/ds_head_basic_types.h conversion/dicomserver_sonata/siemens_include/ds_head_constants.h conversion/dicomserver_sonata/siemens_include/ds_head_image_text_type.h conversion/dicomserver_sonata/siemens_include/ds_head_shadow_groups_types.h conversion/dicomserver_sonata/siemens_include/ds_head_type.h conversion/dicomserver_sonata/siemens_include/ds_include_files.h conversion/dicomserver_sonata/siemens_include/ds_messages.h conversion/dicomserver_sonata/siemens_include/ds_transformation.h conversion/dicomserver_sonata/siemens_include/ds_transformation_control.h conversion/dicomserver_sonata/siemens_to_dicom.c conversion/dicomserver_sonata/spi_element_defs.h conversion/dicomserver_sonata/string_to_filename.c conversion/dicomserver_sonata/use_the_files.c conversion/dicomserver_sonata/valid_element_ids
diffstat 43 files changed, 18448 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/Makefile
@@ -0,0 +1,38 @@
+# --------------------------------------------------------------------
+#
+# MINC Makefile
+# Written by leili Nov. 2002
+#
+
+ROOT = ../../minc
+ACR_LIB_DIR = ../Acr_nema
+include $(ACR_LIB_DIR)/Make_acrdefs
+include $(ROOT)/Make_machine_specific
+include $(ROOT)/Make_configuration
+
+# Executable names
+# Couple of things have been added by Leili on April 30, 2003
+# dicomserver-nondebug-test , save_transferred_object_test.o
+PROGS    = dicomserver-nondebug dcm2mnc dicomserver-debug dicomserver-nondebug2 dicomserver-nondebug-old
+EXTRA_OBJS = dicom_element_defs.o open_connection.o reply.o \
+             save_transferred_object.o use_the_files.o \
+             siemens_dicom_to_minc.o siemens_dicom_read.o minc_file.o \
+             string_to_filename.o project_file.o \
+             parse_dicom_groups.o siemens_to_dicom.o progress.o
+HEADERS  = dicomserver.h dicom_prototypes.h dicom_element_defs.h \
+           spi_element_defs.h siemens_dicom_to_minc.h
+CDEFINES = -DDEBUG#                        cpp defines
+INCLUDES = -I/usr/include -I. -I$(ACR_LIB_DIR) -I$(PROG_LIB_DIR) \
+	            -I$(VOLIO_LIB_DIR)/Include -Isiemens_include \
+	            -I$(MINC_LIB_DIR) -I$(NETCDF_INCLUDE_DIR)
+LDOPT    = $(CC_ACR_LIB) $(PROG_LDOPT)
+MANSECT  = 1
+#MANPAGES = $(PROGS).$(MANSECT)
+
+include $(ROOT)/progs/Make_progs
+
+dicomserver-debug.o: dicomserver-nondebug.c
+dicomserver-nondebug.o: dicomserver-nondebug.c
+#Added by Leili
+dicomserver-nondebug2.o: dicomserver-nondebug2.c
+dicomserver-nondebug-old.o: dicomserver-nondebug-old.c
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dcm2mnc.c
@@ -0,0 +1,880 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dcm2mnc.c
+@DESCRIPTION: Program to convert dicom files to minc
+@GLOBALS    : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+ * $Log: dcm2mnc.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.5  2002/04/26 12:02:50  rhoge
+ * updated usage statement for new forking defaults
+ *
+ * Revision 1.4  2002/04/26 11:32:48  rhoge
+ * made forking default
+ *
+ * Revision 1.3  2002/03/23 13:17:53  rhoge
+ * added support for Bourget network pushed dicom files, cleaned up
+ * file check and read_numa4_dicom vr check/assignment
+ *
+ * Revision 1.2  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.1  2002/03/22 03:50:02  rhoge
+ * new name for standalone dicom to minc converter
+ *
+ * Revision 1.3  2002/03/22 00:38:08  rhoge
+ * Added progress bar, wait for children at end, updated feedback statements
+ *
+ * Revision 1.2  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.1  2001/12/31 17:26:21  rhoge
+ * adding file to repository- compiles without warning and converts non-mosaic
+ * Numa 4 files. 
+ * Will probably not work for Numa 3 files yet.
+ *
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/dcm2mnc.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "dicomserver.h"
+
+extern char *minc_history; // Global for minc history
+char *pname; // program name
+File_Type file_type = UNDEF ; // type of input files
+char command_line[512];
+int N4_OFFSET;
+
+// function prototypes
+private int ima_sort_function(const void *entry1, const void *entry2);
+private int dcm_sort_function(const void *entry1, const void *entry2);
+private int print_file_info( int ix, Data_Object_Info *info);
+public int progress(long index, int end, char *message);
+
+#define EXTREME_LOGGING 10 
+
+int Do_logging = 0;
+int Fork = 1;
+int Debug = 0;
+int Anon = 0;
+int UserIdStr = 0;
+char IdStr[512];
+int UserName = 0;
+char Name[512];
+
+// Do we keep files or are they temporary?
+// (now this is overridden by Cleanup)
+static int Keep_files = 
+#ifndef KEEP_FILES
+   FALSE;
+#else
+   TRUE;
+#endif
+
+// Globals for handling connection timeouts
+// (obsolete?)
+int Connection_timeout = FALSE;
+Acr_File *Alarmed_afp = NULL;
+
+int main(int argc, char *argv[])
+{
+   long ifile;
+   long max_group;
+
+   Acr_Group group_list;
+   int exit_status;
+   char **file_list;
+   char **acq_file_list;
+   Data_Object_Info **file_info_list;
+   Data_Object_Info **acq_file_info_list;
+   int num_files, num_files_alloc;
+   int num_acq_files;
+   FILE *fptemp;
+   char last_file_name[256]; // delete?
+   char *project_name = NULL;
+   int process_files, have_extra_file;
+   pid_t parent_pid, child_pid;
+   int statptr;
+
+   int ix;
+   int UseArgDir = 1;
+   char OutDir[128];
+   int List = 0;
+   int Cleanup = 0;
+   // Added by leili
+   Acr_Element element;
+   char model_name[256];
+   char patient_name[256];
+   char patient_id[256];
+   char reg_time[256];
+   char reg_date[256];
+   char out_dir[256];
+   char temp_name[256];
+   char *temp_dir;
+   static char file_prefix_string[L_tmpnam+1] = "dicomserver";
+   char *file_prefix = file_prefix_string;
+   //double study_id;
+   //int acquisition_id, image_id, study_time, study_date;
+
+   /* Get server process id */
+   parent_pid = getpid();
+
+   /* Create minc history string */
+   {
+      char *string;
+      string = "dicomserver";
+      minc_history = time_stamp(1, &string);
+   }
+
+   /* get program name */
+
+   pname = argv[0];
+
+   if (argc<2) {
+     usage();
+   }
+
+   /* Added by leili to test the temp_dir */
+   // temp_dir = NULL;
+   //if (! Keep_files){
+   // temp_dir = tempnam(NULL, NULL);
+   //if(mkdir(temp_dir, (mode_t) 0777)){
+   //   (void) fprintf(stderr, 
+   //         "%s: Unable to create directory for temporary files.\n",
+   //                     pname);
+   //   perror(pname);
+   //   exit(EXIT_FAILURE);
+   // }
+   // printf("Temp directory for the dcm files:%s",temp_dir);
+   // (void) strcpy(file_prefix, temp_dir);
+   // (void) strcat(file_prefix, "/dicom");
+   //} 
+
+  /* read in all the input pars and file names */
+
+   for (ix = 1; ix<argc; ix++) {
+
+     if (!strncmp(argv[ix],"-help",5)) { 
+       usage();
+     } 
+     else if (!strncmp(argv[ix],"-log",4)) { 
+       ix++;
+       Do_logging = atoi(argv[ix]);
+     }
+     else if (!strncmp(argv[ix],"-fork",5)) { 
+       printf("Forking is now default; -fork option is no longer needed\n");
+       Fork = 1;
+     } 
+     else if (!strncmp(argv[ix],"-nofork",7)) { 
+       Fork = 0;
+     } 
+     else if (!strncmp(argv[ix],"-debug",4)) { 
+       Debug = 1;
+     } 
+     else if (!strncmp(argv[ix],"-anon",5)) { 
+       Anon = 1;
+     } 
+     else if (!strncmp(argv[ix],"-idstr",6)) { 
+       ix++;
+       strcpy(IdStr,argv[ix]);
+       UserIdStr = 1;
+     } 
+     else if (!strncmp(argv[ix],"-descr",6)) { 
+       ix++;
+       strcpy(Name,argv[ix]);
+       UserName = 1;
+     } 
+     else if (!strncmp(argv[ix],"-list",5)) { 
+       List = 1;
+     } 
+     else if (!strncmp(argv[ix],"-cleanup",6)) { 
+       Cleanup = 1;
+     } 
+     else if (!strncmp(argv[ix],"-cmd",4)) { 
+       ix++;
+       strcpy(command_line,argv[ix]);
+     } 
+     else if (!strncmp(argv[ix],"-",1)) { 
+       (void) fprintf(stderr,"ERROR:  input arg `%s' not recognized\n",
+		      argv[ix]);
+       exit(EXIT_FAILURE);
+     }
+     else { /* assume rest of args are the file names and destination */
+
+       /* Get space for file lists */
+       if (List) {
+	 num_files = argc - ix;
+       } else {
+	 num_files = argc - ix - 1; // last arg is output dir
+       }
+       file_list = MALLOC((size_t) num_files * sizeof(*file_list));
+       file_info_list = MALLOC(num_files * sizeof(*file_info_list));
+
+       ifile = 0;
+       for ( ; ix < argc - 1; ix++) {
+	 file_list[ifile] = strdup(argv[ix]);
+	 ifile++;
+       }
+       
+       if (List) {
+	 // if listing, last input arg will be an input file
+	 file_list[ifile] = strdup(argv[argc-1]);
+       } else {
+	 // otherwise, last input arg will be output directory
+	 strcpy(OutDir,argv[argc-1]); 
+	 (void) strcat(OutDir, "/"); // make sure path ends with slash
+       }
+     }
+   } // end of loop over input args
+
+   // if List, then no point in forking
+
+   if (List) {
+     Fork = 0;
+   }
+
+   /* figure out what kind of files we have -
+    * supported types are:
+    *
+    *  IMA (Siemens .ima format - Numaris 3.5)
+    *  N4DCM (Siemens DICOM - Numaris 4)
+    *
+    * if not all same type, return an error */
+
+   // note - checking that all files are the same type
+   // is quite slow so the hard-coded default is now
+   // to break out of this check once a file type is 
+   // established.  Generally users have only one file 
+   // type in a directory.
+
+   // we start by assuming N4DCM with no offset - we find that
+   // the file is IMA or has an offset (the 128 byte + DICM offset
+   // seen on Syngo CD's and exports) then the appropriate flag will
+   // be set.
+
+   printf("Checking file types...   ");
+
+   file_type = N4DCM; // default
+   N4_OFFSET = 0; 
+
+   // printf(" The Manufacturer Model is %s:\n ", SPI_Manufacturer_model);
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char dicm_test_string[5];
+
+     fptemp = fopen(file_list[ifile], "r");
+    
+     if (fptemp == NULL) {
+       fprintf(stderr,"Error opening file %s!\n",file_list[ifile]);
+       exit(EXIT_FAILURE);
+     }
+
+     /* Numaris 4 DICOM CD/Export file? if so, bytes 129-132 will 
+	contain the string `DICM' */
+
+     fseek(fptemp,128,SEEK_SET);
+     fread(dicm_test_string,1,4,fptemp);
+     dicm_test_string[4] = (char) '\0';       
+   
+     // Added by leili to make the program works for data form the old vision system 
+     // To do this, we should figure out the manufacturer model from the dicom header
+     // if the machine is the old vision, create the output directory
+     // then call the dicom_to_minc script to do the conversion
+      group_list = read_siemens_dicom(file_list[ifile],100);
+      element = acr_find_group_element(group_list, ACR_Manufacturer_model);
+      if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), model_name,
+                         sizeof(model_name));}
+    
+      if ((element == NULL) || (strlen(model_name) == 0))
+         (void) strcpy(model_name, "unknown");
+      printf(" The model_name is %s\n", model_name);
+
+      printf("\nacq_file_info_list[ifile]->study_id: \t%.6f",
+                       acq_file_info_list[ifile]->study_id);
+      printf("\nthe ifile is: %d", ifile);
+  
+      printf("\nacq_file_info_list[ifile]->study_date: \t%d", 
+                       acq_file_info_list[ifile]->study_date);
+ 
+      printf("\nacq_file_info_list[ifile]->study_time: \t%d", 
+                       acq_file_info_list[ifile]->study_time);
+            
+  
+      if ((strcmp(model_name, "sonatavision") == 0) && (!strncmp(dicm_test_string,"DICM",4))){
+        file_type = N4DCM;
+        N4_OFFSET = 1; 
+        printf("assuming remaining files are Syngo DICOM (CD/Export).\n");
+        (void) fclose(fptemp);
+        break; // break out of file checking loop
+       
+       }else if ((strcmp(model_name, "magnetom_vision") == 0)|| ((strcmp(model_name, "unknown")) == 0)) {
+        file_type = IMA;
+        printf("assuming remaining files are IMA!\n");
+        (void) fclose(fptemp);
+        break; // break out of file checking loop 
+       }else {
+        file_type = N4DCM;
+        N4_OFFSET = 0; 
+        printf("assuming remaining files are Syngo DICOM.\n");
+        (void) fclose(fptemp);
+        break; // break out of file checking loop
+       } // end of file type check
+        
+     (void) fclose(fptemp);
+   } // end of loop over files to check for mixed file types
+
+    // now loop over all files, getting basic info on each
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char message[20];
+     sprintf(message,"Parsing %d files",num_files);
+     if (!Debug) {
+       progress(ifile, num_files, message);
+     }
+
+     // allocate space for the current entry to file_info_list
+     file_info_list[ifile] = MALLOC(sizeof(*file_info_list[ifile]));
+     file_info_list[ifile]->file_index = ifile;
+
+     if (file_type == N4DCM) {
+
+       // read up to but not including pixel data
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(file_list[ifile], max_group);
+
+     } else if (file_type == IMA) {
+       // Added by leili for the conversion of dicom data from the old vision machine
+       //strcat(out_dir, "/data/fmri/transfer/images/");
+       group_list = read_siemens_dicom(file_list[ifile],100);   
+
+       
+        
+       element = acr_find_group_element(group_list, ACR_Patient_name);
+       if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), patient_name,
+                         sizeof(patient_name));
+       }
+       if ((element == NULL) || (strlen(patient_name) == 0))
+         (void) strcpy(patient_name, "unknown");
+           
+       strcat(out_dir, patient_name);
+       strcat(out_dir, "_");
+     
+       element = acr_find_group_element(group_list, ACR_Patient_identification);
+       if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), patient_id,
+                         sizeof(patient_id));
+       }
+       if ((element == NULL) || (strlen(patient_id) == 0))
+         (void) strcpy(patient_id, "unknown");
+      
+       strcat(out_dir, patient_id);
+       strcat(out_dir, "_");
+      
+       element = acr_find_group_element(group_list, ACR_Study_date);
+       if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), reg_date,
+                         sizeof(reg_date));
+       }
+       if ((element == NULL) || (strlen(reg_date) == 0))
+         (void) strcpy(patient_id, "unknown");
+       
+       strcat(out_dir, reg_date);
+       strcat(out_dir, "_");
+      
+       element = acr_find_group_element(group_list, ACR_Study_time);
+       if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), reg_time,
+                         sizeof(reg_time));
+       }
+       if ((element == NULL) || (strlen(reg_time) == 0))
+         (void) strcpy(patient_id, "unknown");
+       
+       strcat(out_dir, reg_time);
+
+       mkdir(out_dir,(mode_t) 0777);
+       // this part works fine but it's an ugly code!!! Perhaps a better solution than the system call?
+       strcat(temp_name,"/software/source/dicomserver_test/conversion/dicomserver/dicom_to_minc");
+       strcat(temp_name," ");
+       //strcat(temp_name,out_dir);
+       strcat(temp_name, "/data/fmri/transfer/images/leili");
+       strcat(temp_name,"/.");
+       strcat(temp_name," ");
+       strcat(temp_name,"-compress");
+       strcat(temp_name," ");
+       strcat(temp_name,"-inputdir");
+       strcat(temp_name, " ");
+       //strcat(temp_name,temp_dir);
+       strcat(temp_name, "/software/source/dicomserver_test/conversion/dicomserver/dicom_data/Numaris_3/IMAS");
+       strcat(temp_name,"/.");
+       printf(" the temp_name is : %s\n", temp_name);
+       system (temp_name);
+       exit(0);
+     }
+
+     // get some preliminary info from group_list
+     // (which should have been `corrected' in read_xxxx_dicom
+     parse_dicom_groups(group_list, file_info_list[ifile]);
+
+     // put the file name into the info list
+     file_info_list[ifile]->file_name = strdup(file_list[ifile]);
+
+     /* print out info about file */
+     print_file_info(ifile,file_info_list[ifile]);
+
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+   } // end of loop over files to get basic info
+
+   printf("Sorting files...   ");
+
+   if (file_type == N4DCM) {
+     // sort the files based on acquisition number
+     qsort(file_info_list, num_files, sizeof(file_info_list[0]),
+	   dcm_sort_function);
+
+   } else if (file_type == IMA) {
+     // sort the files based on file name
+     // (could also use dcm_sort_function, but would have 
+     // to use ACR_Image instead of ACR_Acquisition
+     qsort(file_list, num_files, sizeof(file_list[0]),
+	   ima_sort_function);
+   }
+
+   printf("Done sorting files.\n");
+
+   /* Get space for acquisition file lists */
+   num_files_alloc = FILE_ALLOC_INCREMENT;
+   acq_file_list = MALLOC((size_t) num_files_alloc * sizeof(*acq_file_list));
+   acq_file_info_list = MALLOC(num_files_alloc * sizeof(*acq_file_info_list));
+
+   /* Loop over files, processing by acquisition */ 
+
+   if (List) {
+     printf("Listing files by series...\n");
+   } else {
+     printf("Processing files, one series at a time...\n");
+   }
+
+   num_acq_files = 1;
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     // Wait for any children that have finished 
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) > 0) {}
+
+     // If there are children, slow down the processing
+     if (child_pid == 0) {
+       (void) sleep((unsigned int) SERVER_SLEEP_TIME);
+     }
+
+     /* Set flags indicating whether we should do anything with the files
+	and whether the file lists contain an extra file */
+     process_files = FALSE;
+     have_extra_file = FALSE;
+
+     /* Extend acquisition file list if necessary */
+     if (num_acq_files >= num_files_alloc) {
+       num_files_alloc = num_acq_files + FILE_ALLOC_INCREMENT;
+       acq_file_list = REALLOC(acq_file_list, 
+			   num_files_alloc * sizeof(*acq_file_list));
+       acq_file_info_list = 
+	 REALLOC(acq_file_info_list, 
+		 num_files_alloc * sizeof(*acq_file_info_list));
+     }
+     acq_file_list[num_acq_files-1] = NULL;
+     acq_file_info_list[num_acq_files-1] = 
+       MALLOC(sizeof(*acq_file_info_list[num_acq_files-1]));
+
+     acq_file_list[num_acq_files-1] = strdup(file_info_list[ifile]->file_name);
+
+     if (file_type == N4DCM) {
+       /* read up to but not including pixel data */
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(acq_file_list[num_acq_files-1],max_group);
+       
+     } else if (file_type == IMA) {
+       group_list = siemens_to_dicom(acq_file_list[num_acq_files-1], TRUE);
+       if (group_list == NULL) {
+	 fprintf(stderr,"Error reading groups from file %s!\n",
+		 acq_file_list[num_acq_files-1]);
+	 exit(EXIT_FAILURE);
+       } 
+     }
+     parse_dicom_groups(group_list, acq_file_info_list[num_acq_files-1]);
+
+     // put the file name into the info list
+     acq_file_info_list[num_acq_files-1]->file_name = 
+       strdup(acq_file_list[num_acq_files-1]);
+
+     // print some file info (junk)
+     print_file_info(num_acq_files,acq_file_info_list[num_acq_files-1]);
+
+     // Check whether we have reached the end of a group of files
+     if (num_acq_files > 1) {
+       if ((acq_file_info_list[num_acq_files-1]->study_id != 
+	    acq_file_info_list[0]->study_id) ||
+	   (acq_file_info_list[num_acq_files-1]->acq_id != 
+	    acq_file_info_list[0]->acq_id)) {
+
+	 process_files = TRUE;
+	 have_extra_file = TRUE;
+       } else if (ifile == num_files-1) {
+	 // we're at the last file
+	 process_files = TRUE;
+       }
+     }
+     
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+     // Use the files if we have a complete acquisition
+     if (process_files) {
+
+       // Check for file from next acquisition
+       if (have_extra_file) num_acq_files--;
+
+       if (List) {
+
+	 printf("Series %4d: %30s  (%4d files)\n",
+		acq_file_info_list[0]->acq_id,
+		acq_file_info_list[0]->protocol_name,
+		num_acq_files);
+
+       } else {
+	 
+	 printf("Converting data for series %d (%s:  %d files)...\n",
+		acq_file_info_list[0]->acq_id,
+		acq_file_info_list[0]->protocol_name,
+		num_acq_files);
+       }
+
+       if (Fork) {
+	 // Fork child to process the files
+	 child_pid = fork();
+       } else {
+	 child_pid = 0;
+       }
+
+       if (child_pid > 0) {      // Parent process
+	 // printf("[Parent]: Forked process to create minc file.\n");
+       }                         // Error forking
+       else if (child_pid < 0) {
+	 fprintf(stderr, 
+		 "Error forking child to create minc file\n");
+	 return;
+       }
+       else {                    // Child process
+
+	 if (!List) {
+
+	   // process the files (same function as server)
+	   use_the_files(project_name, num_acq_files, acq_file_list, 
+			 acq_file_info_list,UseArgDir,OutDir);
+
+	   // Print message about child finishing
+	   printf("-File creation complete for Series %d.\n",
+		  acq_file_info_list[0]->acq_id);
+	 
+	   // Clean up files, if needed
+	   if (Cleanup) {
+	     if (num_acq_files > 0) {
+	       printf("-Removing input files...  ");
+	       cleanup_files(num_acq_files, acq_file_list);
+	       printf("Done removing input files.\n");
+	     }
+	   }
+	 }
+
+	 if (Fork) {
+	   // Exit from child, if forked
+	   exit(EXIT_SUCCESS);
+	 }
+	 
+       }         // End of child process
+
+       // ----------------------------------------------------
+       // if we get here we must be the parent, who goes 
+       // along happily continuing to eat files
+       // ----------------------------------------------------
+
+       // Reset the lists for a new series
+       free_list(num_acq_files, acq_file_list, acq_file_info_list); 
+
+       // check to see if the last series ended by
+       // running into a new series:
+       if (have_extra_file) {
+	 // move most recent file info to first entry in array,
+	 // in preparation for next series
+
+	 // note that num_acq_files has already been decremented,
+	 // so we do not need to subtract 1 to convert to array index
+	 acq_file_list[0] = acq_file_list[num_acq_files];
+	 acq_file_info_list[0] = acq_file_info_list[num_acq_files];
+
+	 acq_file_list[num_acq_files] = NULL;
+	 acq_file_info_list[num_acq_files] = NULL;
+       }
+       //       num_acq_files = (have_extra_file ? 1 : 0);
+       num_acq_files = (have_extra_file ? 2 : 1);
+     } else {  
+       // we're not processing the files yet - just increment counter
+       num_acq_files++;
+     }
+   }        // end of loop over files
+
+   // Wait for child processes if we've been forking.
+   // We sleep in the checking loop to reduce parent CPU usage
+   if (Fork) {
+     printf("-(waiting for child processes to finish...)\n");
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) >= 0) {sleep(1);}
+   }
+
+   if (List) {
+     printf("Done listing files.\n");
+   } else {
+     printf("Done processing files.\n");
+   }
+
+   /* Save name of first file in last set */
+   if ((num_acq_files > 0) && (acq_file_list[0] != NULL)) {
+      last_file_name[sizeof(last_file_name) - 1] = '\0';
+      (void) strncpy(last_file_name,acq_file_list[0],sizeof(last_file_name)-1);
+   }
+   else {
+      last_file_name[0] = '\0';
+   }
+
+   FREE(acq_file_list);
+   FREE(acq_file_info_list);
+   
+   /* Print final message */
+
+   exit_status = EXIT_SUCCESS;
+
+   exit(exit_status);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : cleanup_files
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Removes files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void cleanup_files(int num_files, char *file_list[])
+{
+   int i;
+
+   //   if (Keep_files) return;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         (void) remove(file_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_list
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free
+              the arrays themselves.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list)
+{
+   int i;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         FREE(file_list[i]);
+      }
+      if (file_info_list[i] != NULL) {
+         FREE(file_info_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : ima_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two ima file names
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int ima_sort_function(const void *entry1, const void *entry2)
+{
+
+  char * const *value1 = entry1;
+  char * const *value2 = entry2;
+
+  int session1,series1,image1;
+  int session2,series2,image2;
+  
+  sscanf(*value1,"%d-%d-%d.ima",&session1,&series1,&image1);
+  sscanf(*value2,"%d-%d-%d.ima",&session2,&series2,&image2);
+  
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dcm_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two dcm series numbers
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int dcm_sort_function(const void *entry1, const void *entry2)
+{
+
+  Data_Object_Info **file_info_list1 = (Data_Object_Info **) entry1;
+  Data_Object_Info **file_info_list2 = (Data_Object_Info **) entry2;
+
+  // make a sort-able session ID number:  date.time
+  double session1 = (*file_info_list1)->study_date +
+    (*file_info_list1)->study_time / 1e6;
+  double session2 = (*file_info_list2)->study_date +
+    (*file_info_list2)->study_time / 1e6;
+
+  // series index
+  int series1 = (*file_info_list1)->acq_id;
+  int series2 = (*file_info_list2)->acq_id;
+
+  // frame index
+  int frame1 = (*file_info_list1)->dyn_scan_number;
+  int frame2 = (*file_info_list2)->dyn_scan_number;
+
+  // image index
+  int image1 = (*file_info_list1)->global_image_number;
+  int image2 = (*file_info_list2)->global_image_number;
+
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (frame1 < frame2) return -1;
+  else if (frame1 > frame2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+private int print_file_info( int ix, Data_Object_Info *info) {
+
+  if (!Debug) {
+    return 0;
+  }
+
+  // printf("SPI_Parameter_file_name = %s\n",
+  //  acr_find_string(group_list, SPI_Parameter_file_name, ""));
+  // printf("SPI_Order_of_slices                 = %s\n",
+  //  acr_find_string(group_list, SPI_Order_of_slices, ""));
+  
+  printf("%4s  %18s\n %15s %8s %6s %8s %8s %3s %3s %3s %3s %3s %3s %4s %4s %4s %5s %16s\n",
+	 "ix","file","study id","date","time","serialno","acq",
+	 "nec","iec","ndy","idy","nsl","isl","acol","rcol","mrow","img#",
+	 "seq");
+  
+  /*       ix  file stu  dat tim  sn acq nec iec ndy idy nsl isl */
+  printf("%4d: %18s:\n %.6f %8d %6d %8d %8d %3d %3d %3d %3d %3d %3d %4d %4d %4d %5d %16s\n\n",
+	 ix,
+	 info->file_name,
+	 info->study_id,
+	 info->study_date,
+	 info->study_time,
+	 info->scanner_serialno,
+	 info->acq_id,
+	 info->num_echoes,
+	 info->echo_number,
+	 info->num_dyn_scans,
+	 info->dyn_scan_number,
+	 info->num_slices_nominal,
+	 info->slice_number,
+	 info->acq_cols,
+	 info->rec_cols,
+	 info->num_mosaic_rows,
+	 info->global_image_number,
+	 info->sequence_name);
+  
+}
+
+void usage (void) {
+  fprintf(stderr,
+	  "\nUsage:  dcm2mnc [options] file1 file2 file3 ... destdir\n");
+  fprintf(stderr,"\noptions:\n");
+  fprintf(stderr,"  -help           : print this informative message\n");
+  fprintf(stderr,"  -list           : print list of series (don't create files)\n");
+  fprintf(stderr,"  -anon           : exclude subject name from file header\n");
+  fprintf(stderr,"  -descr <str>    : use str as session descriptor (default = patient initials)\n");
+  fprintf(stderr,"  -idstr <str>    : use str as subject id string (default = patient ID)\n");
+  fprintf(stderr,"  -log <0|1|2|3>  : set logging level (default=0)\n");
+  fprintf(stderr,"  -cleanup        : delete input files when done (careful!)\n");
+  fprintf(stderr,"  -cmd <prog>     : apply prog to output files (e.g. gzip)\n");
+  fprintf(stderr,"  -fork           : fork subprocesses to create minc files (now default)\n");
+  fprintf(stderr,"  -nofork         : don't fork subprocs, do show progress for individual files\n");
+  fprintf(stderr,"  -debug          : print debugging info\n");
+  fprintf(stderr,"\n");
+  fprintf(stderr,"Files are named according to the following convention:\n\n");
+  fprintf(stderr,"  Directory:  descr-idstr-scanner-serialno-date-time/\n");
+  fprintf(stderr,"  Files:      descr-idstr-scanner-serialno-date-time-series-modality.mnc\n\n");
+
+  exit(EXIT_FAILURE);
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dcm2mnc2.c
@@ -0,0 +1,764 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dcm2mnc.c
+@DESCRIPTION: Program to convert dicom files to minc
+@GLOBALS    : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+ * $Log: dcm2mnc2.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.5  2002/04/26 12:02:50  rhoge
+ * updated usage statement for new forking defaults
+ *
+ * Revision 1.4  2002/04/26 11:32:48  rhoge
+ * made forking default
+ *
+ * Revision 1.3  2002/03/23 13:17:53  rhoge
+ * added support for Bourget network pushed dicom files, cleaned up
+ * file check and read_numa4_dicom vr check/assignment
+ *
+ * Revision 1.2  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.1  2002/03/22 03:50:02  rhoge
+ * new name for standalone dicom to minc converter
+ *
+ * Revision 1.3  2002/03/22 00:38:08  rhoge
+ * Added progress bar, wait for children at end, updated feedback statements
+ *
+ * Revision 1.2  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.1  2001/12/31 17:26:21  rhoge
+ * adding file to repository- compiles without warning and converts non-mosaic
+ * Numa 4 files. 
+ * Will probably not work for Numa 3 files yet.
+ *
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/dcm2mnc2.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include "dicomserver.h"
+
+extern char *minc_history; // Global for minc history
+char *pname; // program name
+File_Type file_type = UNDEF ; // type of input files
+char command_line[512];
+int N4_OFFSET;
+
+// function prototypes
+private int ima_sort_function(const void *entry1, const void *entry2);
+private int dcm_sort_function(const void *entry1, const void *entry2);
+private int print_file_info( int ix, Data_Object_Info *info);
+public int progress(long index, int end, char *message);
+
+#define EXTREME_LOGGING 10 
+
+int Do_logging = 0;
+int Fork = 1;
+int Debug = 0;
+int Anon = 0;
+int UserIdStr = 0;
+char IdStr[512];
+int UserName = 0;
+char Name[512];
+
+// Do we keep files or are they temporary?
+// (now this is overridden by Cleanup)
+static int Keep_files = 
+#ifndef KEEP_FILES
+   FALSE;
+#else
+   TRUE;
+#endif
+
+// Globals for handling connection timeouts
+// (obsolete?)
+int Connection_timeout = FALSE;
+Acr_File *Alarmed_afp = NULL;
+
+int main(int argc, char *argv[])
+{
+   long ifile;
+   long max_group;
+
+   Acr_Group group_list;
+   int exit_status;
+   char **file_list;
+   char **acq_file_list;
+   Data_Object_Info **file_info_list;
+   Data_Object_Info **acq_file_info_list;
+   int num_files, num_files_alloc;
+   int num_acq_files;
+   FILE *fptemp;
+   char last_file_name[256]; // delete?
+   char *project_name = NULL;
+   int process_files, have_extra_file;
+   pid_t parent_pid, child_pid;
+   int statptr;
+
+   int ix;
+   int UseArgDir = 1;
+   char OutDir[128];
+   int List = 0;
+   int Cleanup = 0;
+
+   /* Get server process id */
+   parent_pid = getpid();
+
+   /* Create minc history string */
+   {
+      char *string;
+      string = "dicomserver";
+      minc_history = time_stamp(1, &string);
+   }
+
+   /* get program name */
+
+   pname = argv[0];
+
+   if (argc<2) {
+     usage();
+   }
+
+  /* read in all the input pars and file names */
+
+   for (ix = 1; ix<argc; ix++) {
+
+     if (!strncmp(argv[ix],"-help",5)) { 
+       usage();
+     } 
+     else if (!strncmp(argv[ix],"-log",4)) { 
+       ix++;
+       Do_logging = atoi(argv[ix]);
+     }
+     else if (!strncmp(argv[ix],"-fork",5)) { 
+       printf("Forking is now default; -fork option is no longer needed\n");
+       Fork = 1;
+     } 
+     else if (!strncmp(argv[ix],"-nofork",7)) { 
+       Fork = 0;
+     } 
+     else if (!strncmp(argv[ix],"-debug",4)) { 
+       Debug = 1;
+     } 
+     else if (!strncmp(argv[ix],"-anon",5)) { 
+       Anon = 1;
+     } 
+     else if (!strncmp(argv[ix],"-idstr",6)) { 
+       ix++;
+       strcpy(IdStr,argv[ix]);
+       UserIdStr = 1;
+     } 
+     else if (!strncmp(argv[ix],"-descr",6)) { 
+       ix++;
+       strcpy(Name,argv[ix]);
+       UserName = 1;
+     } 
+     else if (!strncmp(argv[ix],"-list",5)) { 
+       List = 1;
+     } 
+     else if (!strncmp(argv[ix],"-cleanup",6)) { 
+       Cleanup = 1;
+     } 
+     else if (!strncmp(argv[ix],"-cmd",4)) { 
+       ix++;
+       strcpy(command_line,argv[ix]);
+     } 
+     else if (!strncmp(argv[ix],"-",1)) { 
+       (void) fprintf(stderr,"ERROR:  input arg `%s' not recognized\n",
+		      argv[ix]);
+       exit(EXIT_FAILURE);
+     }
+     else { /* assume rest of args are the file names and destination */
+
+       /* Get space for file lists */
+       if (List) {
+	 num_files = argc - ix;
+       } else {
+	 num_files = argc - ix - 1; // last arg is output dir
+       }
+       file_list = MALLOC((size_t) num_files * sizeof(*file_list));
+       file_info_list = MALLOC(num_files * sizeof(*file_info_list));
+
+       ifile = 0;
+       for ( ; ix < argc - 1; ix++) {
+	 file_list[ifile] = strdup(argv[ix]);
+	 ifile++;
+       }
+       
+       if (List) {
+	 // if listing, last input arg will be an input file
+	 file_list[ifile] = strdup(argv[argc-1]);
+       } else {
+	 // otherwise, last input arg will be output directory
+	 strcpy(OutDir,argv[argc-1]); 
+	 (void) strcat(OutDir, "/"); // make sure path ends with slash
+       }
+     }
+   } // end of loop over input args
+
+   // if List, then no point in forking
+
+   if (List) {
+     Fork = 0;
+   }
+
+   /* figure out what kind of files we have -
+    * supported types are:
+    *
+    *  IMA (Siemens .ima format - Numaris 3.5)
+    *  N4DCM (Siemens DICOM - Numaris 4)
+    *
+    * if not all same type, return an error */
+
+   // note - checking that all files are the same type
+   // is quite slow so the hard-coded default is now
+   // to break out of this check once a file type is 
+   // established.  Generally users have only one file 
+   // type in a directory.
+
+   // we start by assuming N4DCM with no offset - we find that
+   // the file is IMA or has an offset (the 128 byte + DICM offset
+   // seen on Syngo CD's and exports) then the appropriate flag will
+   // be set.
+
+   printf("Checking file types...   ");
+
+   file_type = N4DCM; // default
+   N4_OFFSET = 0; 
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char dicm_test_string[5];
+
+     fptemp = fopen(file_list[ifile], "r");
+     if (fptemp == NULL) {
+       fprintf(stderr,"Error opening file %s!\n",file_list[ifile]);
+       exit(EXIT_FAILURE);
+     }
+
+     /* Numaris 4 DICOM CD/Export file? if so, bytes 129-132 will 
+	contain the string `DICM' */
+
+     fseek(fptemp,128,SEEK_SET);
+     fread(dicm_test_string,1,4,fptemp);
+     dicm_test_string[4] = (char) '\0';
+
+     if (!strncmp(dicm_test_string,"DICM",4)) {
+
+       file_type = N4DCM;
+       N4_OFFSET = 1; 
+       printf("assuming remaining files are Syngo DICOM (CD/Export).\n");
+       (void) fclose(fptemp);
+       break; // break out of file checking loop
+
+     } else if (strstr(file_list[ifile],".ima")!=NULL) {
+
+       file_type = IMA;
+       printf("assuming remaining files are IMA!\n");
+       (void) fclose(fptemp);
+       break; // break out of file checking loop
+
+     } else {
+       // assume `regular' dicom (no offset)
+       file_type = N4DCM;
+       N4_OFFSET = 0; 
+       printf("assuming remaining files are Syngo DICOM.\n");
+       (void) fclose(fptemp);
+       break; // break out of file checking loop
+     } // end of file type check
+
+     (void) fclose(fptemp);
+   } // end of loop over files to check for mixed file types
+
+   // now loop over all files, getting basic info on each
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char message[20];
+     sprintf(message,"Parsing %d files",num_files);
+     if (!Debug) {
+       progress(ifile, num_files, message);
+     }
+
+     // allocate space for the current entry to file_info_list
+     file_info_list[ifile] = MALLOC(sizeof(*file_info_list[ifile]));
+     file_info_list[ifile]->file_index = ifile;
+
+     if (file_type == N4DCM) {
+
+       // read up to but not including pixel data
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(file_list[ifile], max_group);
+
+     } else if (file_type == IMA) {
+       group_list = siemens_to_dicom(file_list[ifile], TRUE);
+       if (group_list == NULL) {
+	 fprintf(stderr,"Error reading groups from file %s!\n",
+		 file_list[ifile]);
+	 exit(EXIT_FAILURE);
+       }
+     }
+
+     // get some preliminary info from group_list
+     // (which should have been `corrected' in read_xxxx_dicom
+     parse_dicom_groups(group_list, file_info_list[ifile]);
+
+     // put the file name into the info list
+     file_info_list[ifile]->file_name = strdup(file_list[ifile]);
+
+     /* print out info about file */
+     print_file_info(ifile,file_info_list[ifile]);
+
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+   } // end of loop over files to get basic info
+
+   printf("Sorting files...   ");
+
+   if (file_type == N4DCM) {
+     // sort the files based on acquisition number
+     qsort(file_info_list, num_files, sizeof(file_info_list[0]),
+	   dcm_sort_function);
+
+   } else if (file_type == IMA) {
+     // sort the files based on file name
+     // (could also use dcm_sort_function, but would have 
+     // to use ACR_Image instead of ACR_Acquisition
+     qsort(file_list, num_files, sizeof(file_list[0]),
+	   ima_sort_function);
+   }
+
+   printf("Done sorting files.\n");
+
+   /* Get space for acquisition file lists */
+   num_files_alloc = FILE_ALLOC_INCREMENT;
+   acq_file_list = MALLOC((size_t) num_files_alloc * sizeof(*acq_file_list));
+   acq_file_info_list = MALLOC(num_files_alloc * sizeof(*acq_file_info_list));
+
+   /* Loop over files, processing by acquisition */ 
+
+   if (List) {
+     printf("Listing files by series...\n");
+   } else {
+     printf("Processing files, one series at a time...\n");
+   }
+
+   num_acq_files = 1;
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     // Wait for any children that have finished 
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) > 0) {}
+
+     // If there are children, slow down the processing
+     if (child_pid == 0) {
+       (void) sleep((unsigned int) SERVER_SLEEP_TIME);
+     }
+
+     /* Set flags indicating whether we should do anything with the files
+	and whether the file lists contain an extra file */
+     process_files = FALSE;
+     have_extra_file = FALSE;
+
+     /* Extend acquisition file list if necessary */
+     if (num_acq_files >= num_files_alloc) {
+       num_files_alloc = num_acq_files + FILE_ALLOC_INCREMENT;
+       acq_file_list = REALLOC(acq_file_list, 
+			   num_files_alloc * sizeof(*acq_file_list));
+       acq_file_info_list = 
+	 REALLOC(acq_file_info_list, 
+		 num_files_alloc * sizeof(*acq_file_info_list));
+     }
+     acq_file_list[num_acq_files-1] = NULL;
+     acq_file_info_list[num_acq_files-1] = 
+       MALLOC(sizeof(*acq_file_info_list[num_acq_files-1]));
+
+     acq_file_list[num_acq_files-1] = strdup(file_info_list[ifile]->file_name);
+
+     if (file_type == N4DCM) {
+       /* read up to but not including pixel data */
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(acq_file_list[num_acq_files-1],max_group);
+       
+     } else if (file_type == IMA) {
+       group_list = siemens_to_dicom(acq_file_list[num_acq_files-1], TRUE);
+       if (group_list == NULL) {
+	 fprintf(stderr,"Error reading groups from file %s!\n",
+		 acq_file_list[num_acq_files-1]);
+	 exit(EXIT_FAILURE);
+       } 
+     }
+     parse_dicom_groups(group_list, acq_file_info_list[num_acq_files-1]);
+
+     // put the file name into the info list
+     acq_file_info_list[num_acq_files-1]->file_name = 
+       strdup(acq_file_list[num_acq_files-1]);
+
+     // print some file info (junk)
+     print_file_info(num_acq_files,acq_file_info_list[num_acq_files-1]);
+
+     // Check whether we have reached the end of a group of files
+     if (num_acq_files > 1) {
+       if ((acq_file_info_list[num_acq_files-1]->study_id != 
+	    acq_file_info_list[0]->study_id) ||
+	   (acq_file_info_list[num_acq_files-1]->acq_id != 
+	    acq_file_info_list[0]->acq_id)) {
+
+	 process_files = TRUE;
+	 have_extra_file = TRUE;
+       } else if (ifile == num_files-1) {
+	 // we're at the last file
+	 process_files = TRUE;
+       }
+     }
+     
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+     // Use the files if we have a complete acquisition
+     if (process_files) {
+
+       // Check for file from next acquisition
+       if (have_extra_file) num_acq_files--;
+
+       if (List) {
+
+	 printf("Series %4d: %30s  (%4d files)\n",
+		acq_file_info_list[0]->acq_id,
+		acq_file_info_list[0]->protocol_name,
+		num_acq_files);
+
+       } else {
+	 
+	 printf("Converting data for series %d (%s:  %d files)...\n",
+		acq_file_info_list[0]->acq_id,
+		acq_file_info_list[0]->protocol_name,
+		num_acq_files);
+       }
+
+       if (Fork) {
+	 // Fork child to process the files
+	 child_pid = fork();
+       } else {
+	 child_pid = 0;
+       }
+
+       if (child_pid > 0) {      // Parent process
+	 // printf("[Parent]: Forked process to create minc file.\n");
+       }                         // Error forking
+       else if (child_pid < 0) {
+	 fprintf(stderr, 
+		 "Error forking child to create minc file\n");
+	 return;
+       }
+       else {                    // Child process
+
+	 if (!List) {
+
+	   // process the files (same function as server)
+	   use_the_files(project_name, num_acq_files, acq_file_list, 
+			 acq_file_info_list,UseArgDir,OutDir);
+
+	   // Print message about child finishing
+	   printf("-File creation complete for Series %d.\n",
+		  acq_file_info_list[0]->acq_id);
+	 
+	   // Clean up files, if needed
+	   if (Cleanup) {
+	     if (num_acq_files > 0) {
+	       printf("-Removing input files...  ");
+	       cleanup_files(num_acq_files, acq_file_list);
+	       printf("Done removing input files.\n");
+	     }
+	   }
+	 }
+
+	 if (Fork) {
+	   // Exit from child, if forked
+	   exit(EXIT_SUCCESS);
+	 }
+	 
+       }         // End of child process
+
+       // ----------------------------------------------------
+       // if we get here we must be the parent, who goes 
+       // along happily continuing to eat files
+       // ----------------------------------------------------
+
+       // Reset the lists for a new series
+       free_list(num_acq_files, acq_file_list, acq_file_info_list); 
+
+       // check to see if the last series ended by
+       // running into a new series:
+       if (have_extra_file) {
+	 // move most recent file info to first entry in array,
+	 // in preparation for next series
+
+	 // note that num_acq_files has already been decremented,
+	 // so we do not need to subtract 1 to convert to array index
+	 acq_file_list[0] = acq_file_list[num_acq_files];
+	 acq_file_info_list[0] = acq_file_info_list[num_acq_files];
+
+	 acq_file_list[num_acq_files] = NULL;
+	 acq_file_info_list[num_acq_files] = NULL;
+       }
+       //       num_acq_files = (have_extra_file ? 1 : 0);
+       num_acq_files = (have_extra_file ? 2 : 1);
+     } else {  
+       // we're not processing the files yet - just increment counter
+       num_acq_files++;
+     }
+   }        // end of loop over files
+
+   // Wait for child processes if we've been forking.
+   // We sleep in the checking loop to reduce parent CPU usage
+   if (Fork) {
+     printf("-(waiting for child processes to finish...)\n");
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) >= 0) {sleep(1);}
+   }
+
+   if (List) {
+     printf("Done listing files.\n");
+   } else {
+     printf("Done processing files.\n");
+   }
+
+   /* Save name of first file in last set */
+   if ((num_acq_files > 0) && (acq_file_list[0] != NULL)) {
+      last_file_name[sizeof(last_file_name) - 1] = '\0';
+      (void) strncpy(last_file_name,acq_file_list[0],sizeof(last_file_name)-1);
+   }
+   else {
+      last_file_name[0] = '\0';
+   }
+
+   FREE(acq_file_list);
+   FREE(acq_file_info_list);
+   
+   /* Print final message */
+
+   exit_status = EXIT_SUCCESS;
+
+   exit(exit_status);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : cleanup_files
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Removes files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void cleanup_files(int num_files, char *file_list[])
+{
+   int i;
+
+   //   if (Keep_files) return;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         (void) remove(file_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_list
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free
+              the arrays themselves.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list)
+{
+   int i;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         FREE(file_list[i]);
+      }
+      if (file_info_list[i] != NULL) {
+         FREE(file_info_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : ima_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two ima file names
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int ima_sort_function(const void *entry1, const void *entry2)
+{
+
+  char * const *value1 = entry1;
+  char * const *value2 = entry2;
+
+  int session1,series1,image1;
+  int session2,series2,image2;
+  
+  sscanf(*value1,"%d-%d-%d.ima",&session1,&series1,&image1);
+  sscanf(*value2,"%d-%d-%d.ima",&session2,&series2,&image2);
+  
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dcm_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two dcm series numbers
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int dcm_sort_function(const void *entry1, const void *entry2)
+{
+
+  Data_Object_Info **file_info_list1 = (Data_Object_Info **) entry1;
+  Data_Object_Info **file_info_list2 = (Data_Object_Info **) entry2;
+
+  // make a sort-able session ID number:  date.time
+  double session1 = (*file_info_list1)->study_date +
+    (*file_info_list1)->study_time / 1e6;
+  double session2 = (*file_info_list2)->study_date +
+    (*file_info_list2)->study_time / 1e6;
+
+  // series index
+  int series1 = (*file_info_list1)->acq_id;
+  int series2 = (*file_info_list2)->acq_id;
+
+  // frame index
+  int frame1 = (*file_info_list1)->dyn_scan_number;
+  int frame2 = (*file_info_list2)->dyn_scan_number;
+
+  // image index
+  int image1 = (*file_info_list1)->global_image_number;
+  int image2 = (*file_info_list2)->global_image_number;
+
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (frame1 < frame2) return -1;
+  else if (frame1 > frame2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+private int print_file_info( int ix, Data_Object_Info *info) {
+
+  if (!Debug) {
+    return 0;
+  }
+
+  // printf("SPI_Parameter_file_name = %s\n",
+  //  acr_find_string(group_list, SPI_Parameter_file_name, ""));
+  // printf("SPI_Order_of_slices                 = %s\n",
+  //  acr_find_string(group_list, SPI_Order_of_slices, ""));
+  
+  printf("%4s  %18s\n %15s %8s %6s %8s %8s %3s %3s %3s %3s %3s %3s %4s %4s %4s %5s %16s\n",
+	 "ix","file","study id","date","time","serialno","acq",
+	 "nec","iec","ndy","idy","nsl","isl","acol","rcol","mrow","img#",
+	 "seq");
+  
+  /*       ix  file stu  dat tim  sn acq nec iec ndy idy nsl isl */
+  printf("%4d: %18s:\n %.6f %8d %6d %8d %8d %3d %3d %3d %3d %3d %3d %4d %4d %4d %5d %16s\n\n",
+	 ix,
+	 info->file_name,
+	 info->study_id,
+	 info->study_date,
+	 info->study_time,
+	 info->scanner_serialno,
+	 info->acq_id,
+	 info->num_echoes,
+	 info->echo_number,
+	 info->num_dyn_scans,
+	 info->dyn_scan_number,
+	 info->num_slices_nominal,
+	 info->slice_number,
+	 info->acq_cols,
+	 info->rec_cols,
+	 info->num_mosaic_rows,
+	 info->global_image_number,
+	 info->sequence_name);
+  
+}
+
+void usage (void) {
+  fprintf(stderr,
+	  "\nUsage:  dcm2mnc [options] file1 file2 file3 ... destdir\n");
+  fprintf(stderr,"\noptions:\n");
+  fprintf(stderr,"  -help           : print this informative message\n");
+  fprintf(stderr,"  -list           : print list of series (don't create files)\n");
+  fprintf(stderr,"  -anon           : exclude subject name from file header\n");
+  fprintf(stderr,"  -descr <str>    : use str as session descriptor (default = patient initials)\n");
+  fprintf(stderr,"  -idstr <str>    : use str as subject id string (default = patient ID)\n");
+  fprintf(stderr,"  -log <0|1|2|3>  : set logging level (default=0)\n");
+  fprintf(stderr,"  -cleanup        : delete input files when done (careful!)\n");
+  fprintf(stderr,"  -cmd <prog>     : apply prog to output files (e.g. gzip)\n");
+  fprintf(stderr,"  -fork           : fork subprocesses to create minc files (now default)\n");
+  fprintf(stderr,"  -nofork         : don't fork subprocs, do show progress for individual files\n");
+  fprintf(stderr,"  -debug          : print debugging info\n");
+  fprintf(stderr,"\n");
+  fprintf(stderr,"Files are named according to the following convention:\n\n");
+  fprintf(stderr,"  Directory:  descr-idstr-scanner-serialno-date-time/\n");
+  fprintf(stderr,"  Files:      descr-idstr-scanner-serialno-date-time-series-modality.mnc\n\n");
+
+  exit(EXIT_FAILURE);
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicom_element_defs.c
@@ -0,0 +1,23 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicom_element_defs.c
+@DESCRIPTION: Element definitions for DICOM
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#define GLOBAL_ELEMENT_DEFINITION
+
+#include <dicomserver.h>
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicom_element_defs.h
@@ -0,0 +1,154 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicom_element_defs.h
+@DESCRIPTION: Element definitions for dicom
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+/* Define standard UID's */
+#define FAVORITE_ABSTRACT_SYNTAX       ACR_MR_IMAGE_STORAGE_UID
+#define ACR_MR_IMAGE_STORAGE_UID       "1.2.840.10008.5.1.4.1.1.4"
+#define ACR_EXPLICIT_VR_BIG_END_UID    "1.2.840.10008.1.2.2"
+#define ACR_EXPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2.1"
+#define ACR_IMPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2"
+#define ACR_APPLICATION_CONTEXT_UID    "1.2.840.10008.3.1.1.1"
+
+/* Define constants for accepting association */
+#define ACR_ASSOC_RJ_CALLED_AP_TITLE_UNREC 7
+#define ACR_ASSOC_RJ_NO_REASON 1
+#define ACR_ASSOC_RJ_PERM 1
+#define ACR_ASSOC_RJ_USER 1
+#define ACR_ASSOC_PR_CN_ACCEPT 0
+#define ACR_ASSOC_PR_CN_REJECT 1
+#define ACR_PDU_ITEM_USER_INFORMATION 0x50
+
+/* Define group numbers  */
+#define ACR_MESSAGE_GID 0
+#define ACR_ACTUAL_IMAGE_GID 0x7fe0
+
+/* Define commands */
+#define ACR_C_STORE_RQ    0x0001
+#define ACR_C_STORE_RSP   0x8001
+#define ACR_C_ECHO_RQ     0x0030
+#define ACR_C_ECHO_RSP    0x8030
+
+/* Define dataset type */
+#define ACR_NULL_DATASET 0x0101
+
+/* Define status codes */
+#define ACR_SUCCESS 0x0000
+
+/* Define data object types */
+#define ACR_IMAGE_OBJECT 0x0000
+#define ACR_OTHER_OBJECT 0x0100
+
+/* Define acr-nema constants */
+#define ACR_MODALITY_MR "MR"
+
+/* Element id's for DICOM */
+GLOBAL_ELEMENT(ACR_Affected_SOP_class_UID    , 0x0000, 0x0002, UI);
+GLOBAL_ELEMENT(ACR_Command                   , 0x0000, 0x0100, US);
+GLOBAL_ELEMENT(ACR_Message_id                , 0x0000, 0x0110, US);
+GLOBAL_ELEMENT(ACR_Message_id_brt            , 0x0000, 0x0120, US);
+GLOBAL_ELEMENT(ACR_Priority                  , 0x0000, 0x0700, US);
+GLOBAL_ELEMENT(ACR_Dataset_type              , 0x0000, 0x0800, US);
+GLOBAL_ELEMENT(ACR_Status                    , 0x0000, 0x0900, US);
+GLOBAL_ELEMENT(ACR_Affected_SOP_instance_UID , 0x0000, 0x1000, UI);
+GLOBAL_ELEMENT(ACR_Move_originator_AE_title  , 0x0000, 0x1031, AE);
+
+GLOBAL_ELEMENT(ACR_Image_type            , 0x0008, 0x0008, CS);
+GLOBAL_ELEMENT(ACR_Study_date            , 0x0008, 0x0020, DA);
+GLOBAL_ELEMENT(ACR_Series_date           , 0x0008, 0x0021, DA);
+GLOBAL_ELEMENT(ACR_Acquisition_date      , 0x0008, 0x0022, DA);
+GLOBAL_ELEMENT(ACR_Study_time            , 0x0008, 0x0030, TM);
+GLOBAL_ELEMENT(ACR_Series_time           , 0x0008, 0x0031, TM);
+GLOBAL_ELEMENT(ACR_Acquisition_time      , 0x0008, 0x0032, TM);
+GLOBAL_ELEMENT(ACR_Modality              , 0x0008, 0x0060, CS);
+GLOBAL_ELEMENT(ACR_Manufacturer          , 0x0008, 0x0070, LO);
+GLOBAL_ELEMENT(ACR_Institution_id        , 0x0008, 0x0080, LO);
+GLOBAL_ELEMENT(ACR_Referring_physician   , 0x0008, 0x0090, PN);
+GLOBAL_ELEMENT(ACR_Station_id            , 0x0008, 0x1010, SH);
+GLOBAL_ELEMENT(ACR_Procedure_description , 0x0008, 0x1030, LO);
+GLOBAL_ELEMENT(ACR_Performing_physician  , 0x0008, 0x1050, PN);
+GLOBAL_ELEMENT(ACR_Operators_name        , 0x0008, 0x1070, PN);
+GLOBAL_ELEMENT(ACR_Manufacturer_model    , 0x0008, 0x1090, LO);
+
+GLOBAL_ELEMENT(ACR_Patient_name          , 0x0010, 0x0010, PN);
+GLOBAL_ELEMENT(ACR_Patient_identification, 0x0010, 0x0020, LO);
+GLOBAL_ELEMENT(ACR_Patient_birth_date    , 0x0010, 0x0030, DA);
+GLOBAL_ELEMENT(ACR_Patient_sex           , 0x0010, 0x0040, CS);
+GLOBAL_ELEMENT(ACR_Patient_age           , 0x0010, 0x1010, AS);
+GLOBAL_ELEMENT(ACR_Patient_weight        , 0x0010, 0x1030, DS);
+
+GLOBAL_ELEMENT(ACR_Scanning_sequence     , 0x0018, 0x0020, CS);
+GLOBAL_ELEMENT(ACR_MR_acquisition_type   , 0x0018, 0x0023, CS);
+GLOBAL_ELEMENT(ACR_Sequence_name         , 0x0018, 0x0024, CS);
+GLOBAL_ELEMENT(ACR_Slice_thickness       , 0x0018, 0x0050, DS);
+GLOBAL_ELEMENT(ACR_Repetition_time       , 0x0018, 0x0080, DS);
+GLOBAL_ELEMENT(ACR_Echo_time             , 0x0018, 0x0081, DS);
+GLOBAL_ELEMENT(ACR_Inversion_time        , 0x0018, 0x0082, DS);
+GLOBAL_ELEMENT(ACR_Nr_of_averages        , 0x0018, 0x0083, DS);
+GLOBAL_ELEMENT(ACR_Imaging_frequency     , 0x0018, 0x0084, DS);
+GLOBAL_ELEMENT(ACR_Imaged_nucleus        , 0x0018, 0x0085, SH);
+GLOBAL_ELEMENT(ACR_Echo_number           , 0x0018, 0x0086, IS);
+GLOBAL_ELEMENT(ACR_Magnetic_field_strength,0x0018, 0x0087, DS);
+GLOBAL_ELEMENT(ACR_Spacing_between_slices, 0x0018, 0x0088, DS);
+GLOBAL_ELEMENT(ACR_Number_of_phase_encoding_steps, 0x0018, 0x0089, IS);
+GLOBAL_ELEMENT(ACR_Echo_train_length     , 0x0018, 0x0091, IS);
+GLOBAL_ELEMENT(ACR_Percent_sampling      , 0x0018, 0x0093, DS);
+GLOBAL_ELEMENT(ACR_Percent_phase_field_of_view, 0x0018, 0x0094, DS);
+GLOBAL_ELEMENT(ACR_Pixel_bandwidth       , 0x0018, 0x0095, DS);
+GLOBAL_ELEMENT(ACR_Device_serial_number  , 0x0018, 0x1000, LO);
+GLOBAL_ELEMENT(ACR_Software_versions     , 0x0018, 0x1020, LO);
+GLOBAL_ELEMENT(ACR_Protocol_name         , 0x0018, 0x1030, LO);
+GLOBAL_ELEMENT(ACR_Receiving_coil        , 0x0018, 0x1250, SH);
+GLOBAL_ELEMENT(ACR_Transmitting_coil     , 0x0018, 0x1251, SH);
+GLOBAL_ELEMENT(ACR_Acquisition_matrix    , 0x0018, 0x1310, US);
+GLOBAL_ELEMENT(ACR_Phase_encoding_direction, 0x0018, 0x1312, CS);
+GLOBAL_ELEMENT(ACR_Flip_angle            , 0x0018, 0x1314, DS);
+GLOBAL_ELEMENT(ACR_SAR                   , 0x0018, 0x1316, DS);
+GLOBAL_ELEMENT(ACR_Acq_comments          , 0x0018, 0x4000, LT);
+GLOBAL_ELEMENT(ACR_Patient_position      , 0x0018, 0x5100, CS);
+
+GLOBAL_ELEMENT(ACR_Study                 , 0x0020, 0x0010, SH);
+GLOBAL_ELEMENT(ACR_Series                , 0x0020, 0x0011, IS);
+GLOBAL_ELEMENT(ACR_Acquisition           , 0x0020, 0x0012, IS);
+GLOBAL_ELEMENT(ACR_Image                 , 0x0020, 0x0013, IS);
+GLOBAL_ELEMENT(ACR_Image_position_patient, 0x0020, 0x0032, DS);
+GLOBAL_ELEMENT(ACR_Image_orientation_patient,
+	                                   0x0020, 0x0037, DS);
+GLOBAL_ELEMENT(ACR_Acquisitions_in_series, 0x0020, 0x1001, IS);
+
+GLOBAL_ELEMENT(ACR_Rows                  , 0x0028, 0x0010, US);
+GLOBAL_ELEMENT(ACR_Columns               , 0x0028, 0x0011, US);
+GLOBAL_ELEMENT(ACR_Pixel_size            , 0x0028, 0x0030, DS);
+GLOBAL_ELEMENT(ACR_Bits_allocated        , 0x0028, 0x0100, US);
+GLOBAL_ELEMENT(ACR_Bits_stored           , 0x0028, 0x0101, US);
+GLOBAL_ELEMENT(ACR_Smallest_pixel_value  , 0x0028, 0x0106, US);
+GLOBAL_ELEMENT(ACR_Largest_pixel_value   , 0x0028, 0x0107, US);
+GLOBAL_ELEMENT(ACR_Image_location        , 0x0028, 0x0200, US);
+GLOBAL_ELEMENT(ACR_Window_centre         , 0x0028, 0x1050, DS);
+GLOBAL_ELEMENT(ACR_Window_width          , 0x0028, 0x1051, DS);
+
+//GLOBAL_ELEMENT(ACR_Pixel_data, ACR_ACTUAL_IMAGE_GID, 0x0010, UNKNOWN);
+GLOBAL_ELEMENT(ACR_Pixel_data            , 0x7fe0, 0x0010, OW);
+
+#include <spi_element_defs.h>
+#include <ext_element_defs.h>
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicom_prototypes.h
@@ -0,0 +1,82 @@
+public void timeout_handler(int sig);
+public Acr_Group skip_command_groups(Acr_Group group_list);
+public void cleanup_files(int num_files, char *file_list[]);
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list);
+public int create_minc_file(char *minc_file, int clobber, 
+                            General_Info *general_info,
+                            char *file_prefix, char **output_file_name,
+			    Loop_Type loop_type);
+public void setup_minc_variables(int mincid, General_Info *general_info,
+				 Loop_Type loop_type);
+public void save_minc_image(int icvid, General_Info *general_info, 
+                            File_Info *file_info, Image_Data *image);
+public void close_minc_file(int icvid);
+public void open_connection(int argc, char *argv[], 
+                            Acr_File **afpin, Acr_File **afpout);
+public int read_project_file(char *project_name, 
+                             char *file_prefix, 
+                             int *output_uid, int *output_gid,
+                             char *command_line, int maxlen_command);
+public void get_project_option_string(char *project_option_string,
+                                      int maxlen_project_option);
+public Acr_Message associate_reply(Acr_Message input_message, 
+                                   char **project_name,
+                                   int *pres_context_id,
+                                   Acr_byte_order *byte_order,
+                                   Acr_VR_encoding_type *vr_encoding,
+                                   long *maximum_length);
+public Acr_Message associate_reply_reject(Acr_Message input_message, 
+                                          int reason);
+public Acr_Message release_reply(Acr_Message input_message);
+public Acr_Message abort_reply(Acr_Message input_message);
+public Acr_Message data_reply(Acr_Message input_message);
+public void save_transferred_object(Acr_Group group_list, char *file_prefix,
+                                    char **new_file_name,
+                                    Data_Object_Info *data_info);
+public void get_file_info(Acr_Group group_list, File_Info *file_info,
+                          General_Info *general_info);
+public void get_identification_info(Acr_Group group_list, 
+                                    double *study_id, int *acq_id, 
+                                    int *rec_num, int *image_type);
+public void get_intensity_info(Acr_Group group_list, File_Info *file_info);
+public void get_coordinate_info(Acr_Group group_list, File_Info *file_info,
+                                Orientation *orientation,
+                                World_Index volume_to_world[VOL_NDIMS],
+                                int sizes[VOL_NDIMS],
+                                double dircos[VOL_NDIMS][WORLD_NDIMS],
+                                double steps[VOL_NDIMS],
+                                double starts[VOL_NDIMS],
+                                double coordinate[WORLD_NDIMS]);
+public void convert_numa3_coordinate(double coordinate[WORLD_NDIMS]);
+public void convert_dicom_coordinate(double coordinate[WORLD_NDIMS]);
+public void get_general_header_info(Acr_Group group_list, 
+                                    General_Info *general_info);
+public double convert_time_to_seconds(double dicom_time);
+public void get_siemens_dicom_image(Acr_Group group_list, Image_Data *image);
+public int siemens_dicom_to_minc(int num_files, char *file_list[], 
+                        char *minc_file, int clobber,
+                        char *file_prefix, char **output_file_name);
+public Acr_Group read_siemens_dicom(char *filename, int max_group);
+public void free_info(General_Info *general_info, File_Info *file_info, 
+                      int num_files);
+public int search_list(int value, int list[], int list_length, 
+                       int starting_point);
+public void usage(void);
+public void sort_dimensions(General_Info *general_info);
+public int dimension_sort_function(const void *v1, const void *v2);
+public void string_to_filename(char *string, char *filename, int maxlen);
+public void use_the_files(char *project_name,
+                          int num_files, char *file_list[], 
+                          Data_Object_Info *data_info[],
+			  int UseArgDir,char *OutDir);
+public Acr_Group siemens_to_dicom(char *filename, int read_image);
+
+// MGH specific stuff
+public void string_to_initials(char *string, char *filename, int maxlen);
+
+// Numaris 4 specific stuff
+public Acr_Group read_numa4_dicom(char *filename, int max_group);
+public char *prot_find_string(Acr_Element Protocol, char *Field);
+public char *dump_protocol_text(Acr_Element Protocol);
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicomreader.c
@@ -0,0 +1,639 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicomreader.c
+@DESCRIPTION: Program to convert dicom files to minc
+@GLOBALS    : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+ * $Log: dicomreader.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.3  2002/03/22 00:38:08  rhoge
+ * Added progress bar, wait for children at end, updated feedback statements
+ *
+ * Revision 1.2  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.1  2001/12/31 17:26:21  rhoge
+ * adding file to repository- compiles without warning and converts non-mosaic
+ * Numa 4 files. 
+ * Will probably not work for Numa 3 files yet.
+ *
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/dicomreader.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include "dicomserver.h"
+
+extern char *minc_history; /* Global for minc history */
+char *pname; /* program name */
+File_Type file_type = UNDEF ; /* type of input files */
+
+/* function prototypes */
+private int ima_sort_function(const void *entry1, const void *entry2);
+private int dcm_sort_function(const void *entry1, const void *entry2);
+private int print_file_info( int ix, Data_Object_Info *info);
+public int progress(long index, int end, char *message);
+
+#define EXTREME_LOGGING 10 /* rhoge */
+
+/* Do we do logging? */
+int Do_logging = 0;
+int NoFork = 0;
+
+/* Do we keep files or are they temporary? */
+static int Keep_files = 
+#ifndef KEEP_FILES
+   FALSE;
+#else
+   TRUE;
+#endif
+
+/* Globals for handling connection timeouts */
+int Connection_timeout = FALSE;
+Acr_File *Alarmed_afp = NULL;
+
+int main(int argc, char *argv[])
+{
+   long ifile;
+   long max_group;
+
+   Acr_Group group_list;
+   int exit_status;
+   char **file_list;
+   char **acq_file_list;
+   Data_Object_Info **file_info_list;
+   Data_Object_Info **acq_file_info_list;
+   int num_files, num_files_alloc;
+   int num_acq_files;
+   FILE *fptemp;
+   char last_file_name[256]; // delete?
+   char *project_name = NULL;
+   int process_files, have_extra_file;
+   pid_t parent_pid, child_pid;
+   int statptr;
+
+   /* added by rhoge */
+   int ix;
+   int UseArgDir = 1;
+   char OutDir[128];
+
+   /* Get server process id */
+   parent_pid = getpid();
+
+   /* Create minc history string */
+   {
+      char *string;
+      string = "dicomserver";
+      minc_history = time_stamp(1, &string);
+   }
+
+   /* get program name */
+
+   pname = argv[0];
+
+   if (argc<2) {
+     usage();
+   }
+
+  /* read in all the input pars and file names */
+
+   for (ix = 1; ix<argc; ix++) {
+
+     if (!strncmp(argv[ix],"-help",5)) { 
+       usage();
+     } 
+     else if (!strncmp(argv[ix],"-log",4)) { 
+       ix++;
+       Do_logging = atoi(argv[ix]);
+     }
+     else if (!strncmp(argv[ix],"-nofork",5)) { 
+       NoFork = 1;
+     } 
+     else if (!strncmp(argv[ix],"-",1)) { 
+       (void) fprintf(stderr,"ERROR:  input arg `%s' not recognized\n",
+		      argv[ix]);
+       exit(EXIT_FAILURE);
+     }
+     else { /* assume rest of args are the file names and destination */
+
+       /* Get space for file lists */
+       num_files = argc - ix - 1;
+       file_list = MALLOC((size_t) num_files * sizeof(*file_list));
+       file_info_list = MALLOC(num_files * sizeof(*file_info_list));
+
+       ifile = 0;
+       for ( ; ix < argc - 1; ix++) {
+	 file_list[ifile] = strdup(argv[ix]);
+	 ifile++;
+       }
+       strcpy(OutDir,argv[argc-1]); 
+       (void) strcat(OutDir, "/"); /* make sure path ends with slash */
+     }
+   } // end of loop over input args
+
+   /* figure out what kind of files we have -
+    * supported types are:
+    *
+    *  SIEMENS_SPI (Siemens .ima format - Numaris 3.5)
+    *  SIEMENS_DCM (Siemens DICOM - Numaris 4)
+    *
+    * if not all same type, return an error */
+
+   printf("Checking file types...   ");
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char dicm_test_string[5];
+
+     fptemp = fopen(file_list[ifile], "r");
+     if (fptemp == NULL) {
+       fprintf(stderr,"Error opening file %s!\n",file_list[ifile]);
+       exit(EXIT_FAILURE);
+     }
+
+     /* Numaris 4 DICOM file? if so, bytes 129-132 will 
+	contain the string `DICM' */
+
+     fseek(fptemp,128,SEEK_SET);
+     fread(dicm_test_string,1,4,fptemp);
+     dicm_test_string[4] = (char) '\0';
+
+     if (!strncmp(dicm_test_string,"DICM",4)) {
+       if (file_type == IMA) {
+	 fprintf(stderr,"ERROR:  mixed file types\n");
+	 exit(EXIT_FAILURE);
+       } else {
+	 file_type = N4DCM;
+	 // should make check of all files optional
+	 if (1) {
+	   printf("assuming remaining files are N4DICOM!\n");
+	   break; // break out of file checking loop
+	 } else {
+	   progress(ifile, num_files, "Checking file types");
+	 }
+       }
+     } else if (strstr(file_list[ifile],".ima")!=NULL) {
+       if (file_type == N4DCM) {
+	 fprintf(stderr,"ERROR:  mixed file types\n");
+	 exit(EXIT_FAILURE);
+       } else {
+	 file_type = IMA;
+       }
+     } else {
+       fprintf(stderr,"ERROR:  File %s is unkown type\n",file_list[ifile]);
+       exit(EXIT_FAILURE);
+     } // end of file type check
+
+     (void) fclose(fptemp);
+   } // end of loop over files to check for mixed file types
+
+   // now loop over all files, getting basic info on each
+
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     char message[20];
+     sprintf(message,"Parsing %d files",num_files);
+     progress(ifile, num_files, message);
+
+     // allocate space for the current entry to file_info_list
+     file_info_list[ifile] = MALLOC(sizeof(*file_info_list[ifile]));
+     file_info_list[ifile]->file_index = ifile;
+
+     if (file_type == N4DCM) {
+
+       // read up to but not including pixel data
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(file_list[ifile], max_group);
+
+     } else if (file_type == IMA) {
+       group_list = siemens_to_dicom(file_list[ifile], TRUE);
+       if (group_list == NULL) {
+	 fprintf(stderr,"Error reading groups from file %s!\n",
+		 file_list[ifile]);
+	 exit(EXIT_FAILURE);
+       }
+     }
+
+     // get some preliminary info from group_list
+     // (which should have been `corrected' in read_xxxx_dicom
+     parse_dicom_groups(group_list, file_info_list[ifile]);
+
+     // put the file name into the info list
+     file_info_list[ifile]->file_name = strdup(file_list[ifile]);
+
+     /* print out info about file */
+     print_file_info(ifile,file_info_list[ifile]);
+
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+   } // end of loop over files to get basic info
+
+   printf("Sorting files...   ");
+
+   if (file_type == N4DCM) {
+     // sort the files based on acquisition number
+     qsort(file_info_list, num_files, sizeof(file_info_list[0]),
+	   dcm_sort_function);
+
+   } else if (file_type == IMA) {
+     // sort the files based on file name
+     // (could also use dcm_sort_function, but would have 
+     // to use ACR_Image instead of ACR_Acquisition
+     qsort(file_list, num_files, sizeof(file_list[0]),
+	   ima_sort_function);
+   }
+
+   printf("Done sorting files.\n");
+
+   /* Get space for acquisition file lists */
+   num_files_alloc = FILE_ALLOC_INCREMENT;
+   acq_file_list = MALLOC((size_t) num_files_alloc * sizeof(*acq_file_list));
+   acq_file_info_list = MALLOC(num_files_alloc * sizeof(*acq_file_info_list));
+
+   /* Loop over files, processing by acquisition */ 
+
+   printf("Processing files, one series at a time...\n");
+
+   num_acq_files = 1;
+   for (ifile = 0; ifile < num_files; ifile++) {
+
+     // Wait for any children that have finished 
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) > 0) {}
+
+     // If there are children, slow down the processing
+     if (child_pid == 0) {
+       (void) sleep((unsigned int) SERVER_SLEEP_TIME);
+     }
+
+     /* Set flags indicating whether we should do anything with the files
+	and whether the file lists contain an extra file */
+     process_files = FALSE;
+     have_extra_file = FALSE;
+
+     /* Extend acquisition file list if necessary */
+     if (num_acq_files >= num_files_alloc) {
+       num_files_alloc = num_acq_files + FILE_ALLOC_INCREMENT;
+       acq_file_list = REALLOC(acq_file_list, 
+			   num_files_alloc * sizeof(*acq_file_list));
+       acq_file_info_list = 
+	 REALLOC(acq_file_info_list, 
+		 num_files_alloc * sizeof(*acq_file_info_list));
+     }
+     acq_file_list[num_acq_files-1] = NULL;
+     acq_file_info_list[num_acq_files-1] = 
+       MALLOC(sizeof(*acq_file_info_list[num_acq_files-1]));
+
+     acq_file_list[num_acq_files-1] = strdup(file_info_list[ifile]->file_name);
+
+     if (file_type == N4DCM) {
+       /* read up to but not including pixel data */
+       max_group = ACR_ACTUAL_IMAGE_GID - 1;
+       group_list = read_numa4_dicom(acq_file_list[num_acq_files-1],max_group);
+       
+     } else if (file_type == IMA) {
+       group_list = siemens_to_dicom(acq_file_list[num_acq_files-1], TRUE);
+       if (group_list == NULL) {
+	 fprintf(stderr,"Error reading groups from file %s!\n",
+		 acq_file_list[num_acq_files-1]);
+	 exit(EXIT_FAILURE);
+       } 
+     }
+     parse_dicom_groups(group_list, acq_file_info_list[num_acq_files-1]);
+
+     // put the file name into the info list
+     acq_file_info_list[num_acq_files-1]->file_name = 
+       strdup(acq_file_list[num_acq_files-1]);
+
+     // print some file info (junk)
+     print_file_info(num_acq_files,acq_file_info_list[num_acq_files-1]);
+
+     // Check whether we have reached the end of a group of files
+     if (num_acq_files > 1) {
+       if ((acq_file_info_list[num_acq_files-1]->study_id != 
+	    acq_file_info_list[0]->study_id) ||
+	   (acq_file_info_list[num_acq_files-1]->acq_id != 
+	    acq_file_info_list[0]->acq_id)) {
+
+	 process_files = TRUE;
+	 have_extra_file = TRUE;
+       } else if (ifile == num_files-1) {
+	 // we're at the last file
+	 process_files = TRUE;
+       }
+     }
+     
+     // Delete the group list now that we're done with it
+     acr_delete_group_list(group_list);
+
+     // Use the files if we have a complete acquisition
+     if (process_files) {
+
+       // Check for file from next acquisition
+       if (have_extra_file) num_acq_files--;
+
+       printf("Converting data for series %d (%s:  %d files)...\n",
+	      acq_file_info_list[0]->acq_id,
+	      acq_file_info_list[0]->protocol_name,
+	      num_acq_files);
+
+       if (NoFork) {
+	 child_pid = 0;
+       } else {
+	 // Fork child to process the files
+	 child_pid = fork();
+       }
+
+       if (child_pid > 0) {      // Parent process
+	 // printf("[Parent]: Forked process to create minc file.\n");
+       }                         // Error forking
+       else if (child_pid < 0) {
+	 fprintf(stderr, 
+		 "Error forking child to create minc file\n");
+	 return;
+       }
+       else {                    // Child process
+
+	 // process the files (same function as server)
+	 use_the_files(project_name, num_acq_files, acq_file_list, 
+		       acq_file_info_list,UseArgDir,OutDir);
+
+	 // Print message about child finishing
+	 if (NoFork) {
+	   //printf("[Parent]: Minc creation process finished.\n");
+	   printf("File creation complete for Series %d.\n",
+		  acq_file_info_list[0]->acq_id);
+	 } else {
+	   //printf("[Child]: Minc creation process finished.\n");
+	   printf("  File creation complete for Series %d.\n",
+		  acq_file_info_list[0]->acq_id);
+	 }
+
+	 if (!NoFork) {
+	   // Exit from child, if forked
+	   exit(EXIT_SUCCESS);
+	 }
+	 
+       }         // End of child process
+
+       // ----------------------------------------------------
+       // if we get here we must be the parent, who goes 
+       // along happily continuing to eat files
+       // ----------------------------------------------------
+
+       // Reset the lists for a new series
+       free_list(num_acq_files, acq_file_list, acq_file_info_list); 
+
+       // check to see if the last series ended by
+       // running into a new series:
+       if (have_extra_file) {
+	 // move most recent file info to first entry in array,
+	 // in preparation for next series
+
+	 // note that num_acq_files has already been decremented,
+	 // so we do not need to subtract 1 to convert to array index
+	 acq_file_list[0] = acq_file_list[num_acq_files];
+	 acq_file_info_list[0] = acq_file_info_list[num_acq_files];
+
+	 acq_file_list[num_acq_files] = NULL;
+	 acq_file_info_list[num_acq_files] = NULL;
+       }
+       //       num_acq_files = (have_extra_file ? 1 : 0);
+       num_acq_files = (have_extra_file ? 2 : 1);
+     } else {  
+       // we're not processing the files yet - just increment counter
+       num_acq_files++;
+     }
+   }        // end of loop over files
+
+   // Wait for child processes if we've been forking.
+   // We sleep in the checking loop to reduce parent CPU usage
+   if (!NoFork) {
+     printf("  (waiting for child processes to finish...)\n");
+     while ((child_pid=wait3(&statptr, WNOHANG, NULL)) >= 0) {sleep(1);}
+   }
+   printf("Done processing files.\n");
+
+   /* Save name of first file in last set */
+   if ((num_acq_files > 0) && (acq_file_list[0] != NULL)) {
+      last_file_name[sizeof(last_file_name) - 1] = '\0';
+      (void) strncpy(last_file_name,acq_file_list[0],sizeof(last_file_name)-1);
+   }
+   else {
+      last_file_name[0] = '\0';
+   }
+
+   /* Clean up files, if needed */
+   if (0) {
+     if (num_acq_files > 0) {
+       cleanup_files(num_acq_files, acq_file_list);
+       free_list(num_acq_files, acq_file_list, acq_file_info_list);
+       num_acq_files = 0;
+     }
+   }
+   FREE(acq_file_list);
+   FREE(acq_file_info_list);
+   
+   /* Print final message */
+
+   exit_status = EXIT_SUCCESS;
+
+   exit(exit_status);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : cleanup_files
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Removes files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void cleanup_files(int num_files, char *file_list[])
+{
+   int i;
+
+   if (Keep_files) return;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         (void) remove(file_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_list
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free
+              the arrays themselves.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list)
+{
+   int i;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         FREE(file_list[i]);
+      }
+      if (file_info_list[i] != NULL) {
+         FREE(file_info_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : ima_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two ima file names
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int ima_sort_function(const void *entry1, const void *entry2)
+{
+
+  char * const *value1 = entry1;
+  char * const *value2 = entry2;
+
+  int session1,series1,image1;
+  int session2,series2,image2;
+  
+  sscanf(*value1,"%d-%d-%d.ima",&session1,&series1,&image1);
+  sscanf(*value2,"%d-%d-%d.ima",&session2,&series2,&image2);
+  
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dcm_sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two dcm series numbers
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int dcm_sort_function(const void *entry1, const void *entry2)
+{
+
+  Data_Object_Info **file_info_list1 = (Data_Object_Info **) entry1;
+  Data_Object_Info **file_info_list2 = (Data_Object_Info **) entry2;
+
+  // make a sort-able session ID number:  date.time
+  double session1 = (*file_info_list1)->study_date +
+    (*file_info_list1)->study_time / 1e6;
+  double session2 = (*file_info_list2)->study_date +
+    (*file_info_list2)->study_time / 1e6;
+
+  // series index
+  int series1 = (*file_info_list1)->acq_id;
+  int series2 = (*file_info_list2)->acq_id;
+
+  // frame index
+  int frame1 = (*file_info_list1)->dyn_scan_number;
+  int frame2 = (*file_info_list2)->dyn_scan_number;
+
+  // image index
+  int image1 = (*file_info_list1)->global_image_number;
+  int image2 = (*file_info_list2)->global_image_number;
+
+  if (session1 < session2) return -1;
+  else if (session1 > session2) return 1;
+  else if (series1 < series2) return -1;
+  else if (series1 > series2) return 1;
+  else if (frame1 < frame2) return -1;
+  else if (frame1 > frame2) return 1;
+  else if (image1 < image2) return -1;
+  else if (image1 > image2) return 1;
+  else return 0;
+}
+
+private int print_file_info( int ix, Data_Object_Info *info) {
+
+  return 0;
+
+  // printf("SPI_Parameter_file_name = %s\n",
+  //  acr_find_string(group_list, SPI_Parameter_file_name, ""));
+  // printf("SPI_Order_of_slices                 = %s\n",
+  //  acr_find_string(group_list, SPI_Order_of_slices, ""));
+  
+  printf("%4s  %18s %15s %8s %6s %8s %8s %3s %3s %3s %3s %3s %3s %4s %4s %4s %5s %16s\n",
+	 "ix","file","study id","date","time","serialno","acq",
+	 "nec","iec","ndy","idy","nsl","isl","acol","rcol","mrow","img#",
+	 "seq");
+  
+  /*       ix  file stu  dat tim  sn acq nec iec ndy idy nsl isl */
+  printf("%4d: %18s %.6f %8d %6d %8d %8d %3d %3d %3d %3d %3d %3d %4d %4d %4d %5d %16s\n\n",
+	 ix,
+	 info->file_name,
+	 info->study_id,
+	 info->study_date,
+	 info->study_time,
+	 info->scanner_serialno,
+	 info->acq_id,
+	 info->num_echoes,
+	 info->echo_number,
+	 info->num_dyn_scans,
+	 info->dyn_scan_number,
+	 info->num_slices_nominal,
+	 info->slice_number,
+	 info->acq_cols,
+	 info->rec_cols,
+	 info->num_mosaic_rows,
+	 info->global_image_number,
+	 info->sequence_name);
+  
+}
+
+void usage (void) {
+  fprintf(stderr,
+	  "\nUsage:  dicomreader [options] file1 file2 file3 ... destdir\n");
+  fprintf(stderr,"\noptions:\n");
+  fprintf(stderr,"  -help           : print this informative message\n");
+  fprintf(stderr,"  -log <0|1|2|3>  : set logging level (default=0)\n");
+  fprintf(stderr,"  -nofork         : don't fork to create minc files\n");
+  exit(EXIT_FAILURE);
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicomserver-debug.c
@@ -0,0 +1,12 @@
+#if 0
+#  define DO_INPUT_TRACING
+#endif
+
+#if 1
+#  define KEEP_FILES
+#endif
+
+#if 0
+#  define DO_HIGH_LOGGING
+#endif
+#include "dicomserver-nondebug.c"
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicomserver-nondebug.c
@@ -0,0 +1,926 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicomserver.c
+@DESCRIPTION: Program to receive images from Siemens Vision.
+@GLOBALS    : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+
+Modified by R. Hoge Feb. 2000 to handle acquisition loop dynamic scans
+on Siemens Sonata system
+
+ * $Log: dicomserver-nondebug.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.9  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.8  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.7  2001/08/29 20:55:53  rhoge
+ * added -help option
+ *
+ * Revision 1.6  2001/07/19 17:43:46  rhoge
+ * added -nofork command line option to prevent forking
+ *
+ * Revision 1.5  2001/02/26 13:37:59  rhoge
+ * redirect sderr to /dev/null if no logging - prevents hangups due to
+ * printfs dumping text into connection stream?
+ *
+ * Revision 1.4  2001/02/26 06:17:42  rhoge
+ * changed tmp dir assignment to be consistent, always uses stdio.h stuff.
+ * also added command-line flags for destination dir, logging level, and
+ * retention of dicom files (are put in dest dir - must be specified)
+ *
+ * Revision 1.3  2000/12/14 21:14:58  rhoge
+ * added macro (NO_FORK) to prevent forking if uncommented
+ *
+ * Revision 1.2  2000/12/13 13:22:18  rhoge
+ * experimental changes to forking code for minc file creation - should
+ * be no change
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:55  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.2  1997/07/10  17:35:35  neelin
+ * Changed error handling and fixed message deletion.
+ *
+ * Revision 4.1  1997/07/08  23:15:09  neelin
+ * Added support for C_ECHO command.
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.2  1997/03/11  13:10:48  neelin
+ * Working version of dicomserver.
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/dicomserver-nondebug.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <dicomserver.h>
+
+/* Global for minc history */
+extern char *minc_history;
+
+/* State of server. Note that DISCONNECTING is used for a high-level
+   protocol error and TERMINATING is used for a low-level error or
+   end of input */
+typedef enum {
+   WAITING_FOR_ASSOCIATION, WAITING_FOR_DATA, DISCONNECTING, TERMINATING
+} Server_state;
+
+/* stuff added by rhoge */
+
+#define EXTREME_LOGGING 10 /* rhoge */
+
+/* Do we do logging? */
+/********************/
+//int Do_logging = 0;    /* Belong to rhoge, commented out by leili*/
+/*added by Leili:*/
+int Do_logging = 
+#ifndef DO_HIGH_LOGGING
+  LOW_LOGGING;
+# else
+  HIGH_LOGGING;
+# endif 
+/******************/
+
+/* Changed by leili from False to True */
+int Fork = TRUE;
+/*****************/
+
+/* Do we keep files or are they temporary? */
+static int Keep_files = 
+#ifndef KEEP_FILES
+   FALSE;
+#else
+   TRUE;
+#endif
+/******************/
+/* added by Leili */
+/* In what directory do we run? */
+static char *run_dir = "/data/fmri/transfer/tmp";
+/******************/
+
+/* Globals for handling connection timeouts */
+int Connection_timeout = FALSE;
+Acr_File *Alarmed_afp = NULL;
+File_Type file_type = N4DCM ; /* type of input files */
+int N4_OFFSET;
+char *pname;
+int main(int argc, char *argv[])
+{
+   char *pname;
+   Acr_File *afpin, *afpout;
+   Acr_Status status;
+   Server_state state;
+   int acr_command;
+   Acr_Group group_list;
+   Acr_Message input_message, output_message;
+   int exit_status;
+   char exit_string[256];
+   char **file_list;
+   Data_Object_Info **file_info_list;
+   int num_files, num_files_alloc;
+   static char file_prefix_string[L_tmpnam+1] = "dicomserver";
+   char *file_prefix = file_prefix_string;
+   //Added by Leili 
+   char *file_prefix2 = "/usr/local/dicom_keep/"; 
+   char *temp_dir;
+   int continue_looping;
+   FILE *fptemp;
+   char last_file_name[256];
+   char *project_name = NULL;
+   char logfilename[256];
+   int pdu_type;
+   int process_files, have_extra_file;
+   Acr_byte_order byte_order;
+   Acr_VR_encoding_type vr_encoding;
+   int pres_context_id;
+   long maximum_length;
+   pid_t server_pid, child_pid;
+   int statptr;
+
+   /* added by rhoge */
+   int ix;
+   int UseArgDir = 0;
+   char OutDir[128];
+
+   /* Get server process id */
+   server_pid = getpid();
+   
+   /*************************/
+   
+   /* Change to tmp directory -
+      note that this will be default file destination if no aetitle
+      or command-line specification are received (rhoge) */
+   /* commented out by leili */
+   
+   //(void) chdir(P_tmpdir); 
+   
+   /* added by leili */
+   /* change to tmp directory */
+   if (run_dir != NULL) {
+    (void) chdir(run_dir);
+     } 
+   /*****************************/
+
+   /* Create minc history string */
+   {
+      char *string;
+      string = "dicomserver";
+      minc_history = time_stamp(1, &string);
+   }
+
+   /* read in all the input pars and file names */
+
+   for (ix = 1; ix<argc; ix++) { 
+    
+      if (!strncmp(argv[ix],"-destdir",8)) { 
+       ix++; 
+       UseArgDir = 1; 
+       strcpy(OutDir,argv[ix]);  
+        (void) strcat(OutDir, "/");  /* make sure path ends with slash */  
+    }    
+        else if (!strncmp(argv[ix],"-log",4)) { 
+         ix++; 
+         Do_logging = atoi(argv[ix]); 
+       } 
+      else if (!strncmp(argv[ix],"-fork",5)) {  
+        Fork = TRUE; 
+      } 
+      else if (!strncmp(argv[ix],"-keep_dcm",9)) {  
+        Keep_files = TRUE; 
+      } 
+      else if (!strncmp(argv[ix],"-help",9)) {  
+         (void) fprintf(stderr,"Usage:  dicomserver [<options>]\nOptions:\n\t-log <n>\n\t-fork\n\t-keep_dcm\n\t-help\n"); 
+         exit(EXIT_SUCCESS); 
+       } 
+       else { 
+         (void) fprintf(stderr,"Usage:  dicomserver [<options>]\nOptions:\n\t-log <n>\n\t-fork\n\t-keep_dcm\n\t-help\n"); 
+         exit(EXIT_FAILURE); 
+	 } 
+	 }
+   
+   /* Re-open stderr if we are logging */
+   if (Do_logging > NO_LOGGING) {
+      (void) sprintf(logfilename, "/data/fmri/transfer/logs/dicomserver-%d.log", 
+                     (int) getpid());
+      (void) freopen(logfilename, "w", stderr);
+      setbuf(stderr, NULL);
+   } else {
+      (void) sprintf(logfilename, "/dev/null");
+      (void) freopen(logfilename, "w", stderr);
+      setbuf(stderr, NULL);
+   }
+
+   // set up type of connection (Syngo?)
+   file_type = N4DCM; // default
+   N4_OFFSET = 0; 
+
+   /* Print message at start */
+   pname = argv[0];
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "%s: Started dicom server.\n", pname);
+   }
+
+   /* Make connection */
+   open_connection(argc, argv, &afpin, &afpout);
+   
+
+   /* Check that the connection was made */
+   if ((afpin == NULL) || (afpout == NULL)) {
+      (void) fprintf(stderr, "%s: Error opening connection.\n", pname);
+      exit(EXIT_FAILURE);
+   }
+   
+     
+
+   /* Print connection message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "%s: Connection accepted.\n", pname);
+   }
+
+#ifdef DO_INPUT_TRACING
+   /* Enable input tracing */
+   acr_dicom_enable_trace(afpin);
+   acr_dicom_enable_trace(afpout);
+#endif
+
+   /* Create file prefix. Create the temporary file to avoid file name 
+      clashes */
+   /*****************************/
+   /* Commented out by leili */ 
+   //temp_dir = NULL;
+   //if ( !Keep_files) {
+   //   (void) tmpnam(file_prefix);
+   //   if (mkdir(file_prefix, (mode_t) 0777)) {
+   //      (void) fprintf(stderr, 
+   //         "%s: Unable to create directory for temporary files.\n",
+   //                     pname);
+   //      perror(pname);
+   //      exit(EXIT_FAILURE);
+   //   }
+   //   temp_dir = strdup(file_prefix);
+   //   (void) strcat(file_prefix, "/dicom");
+   //}
+   
+   // else {
+   //  file_prefix=strdup(OutDir);
+
+   //  if (mkdir(file_prefix, (mode_t) 0777)) {
+   //    (void) fprintf(stderr, 
+   //         "Directory %s exists...\n",file_prefix);
+   //   }
+   //  temp_dir = strdup(file_prefix);
+   //   (void) strcat(file_prefix, "/dicom");
+   // }
+   /****************************/
+   /* Added by Leili           */
+   temp_dir = NULL;
+   if (! Keep_files){
+     //temp_dir = tempnam(run_dir, NULL);
+    temp_dir = tempnam(run_dir, NULL);
+    if(mkdir(temp_dir, (mode_t) 0777)){
+      (void) fprintf(stderr, 
+            "%s: Unable to create directory for temporary files.\n",
+                        pname);
+      perror(pname);
+      exit(EXIT_FAILURE);
+    }
+    (void)strcpy(file_prefix, temp_dir);
+    (void) strcat(file_prefix, "/");
+    //(void) strcat(file_prefix, "/dicom");
+   } 
+   /*****************************/
+   (void) fprintf(stderr, "About to begin the space allocation \n"); /* Leili */
+
+   /* Get space for file lists */
+   num_files_alloc = FILE_ALLOC_INCREMENT;
+   file_list = MALLOC((size_t) num_files_alloc * sizeof(*file_list));
+   file_info_list = MALLOC(num_files_alloc * sizeof(*file_info_list));
+    
+   
+   /* Loop while reading messages */
+   state = WAITING_FOR_ASSOCIATION;
+   continue_looping = TRUE;
+   num_files = 0;
+
+   (void) fprintf(stderr, "About to start reading a message \n"); /* Leili */
+   while (continue_looping) {
+
+      /* Wait for any children that have finished */
+      while ((child_pid=wait3(&statptr, WNOHANG, NULL)) > 0) {}
+
+      /* If there are children, slow down the processing */
+      (void) fprintf(stderr, "If we have children, slow down \n"); /* Leili */
+      if (child_pid == 0) {
+         (void) sleep((unsigned int) SERVER_SLEEP_TIME);
+      }
+      (void) fprintf(stderr, "Start reading the message\n"); /* Leili */
+      /* Read in the message */
+      Alarmed_afp = afpin;
+      (void) signal(SIGALRM, timeout_handler);
+      (void) alarm(CONNECTION_TIMEOUT);
+  
+   if (Do_logging > HIGH_LOGGING) 
+     fprintf(stderr,"\nWaiting for dicom message...\n"); /* rhoge */
+      
+   /* chokes here at end of asynchronous transfer */
+      status=acr_input_dicom_message(afpin, &input_message); 
+      (void) fprintf(stderr, "The status of the message is: %s \n", acr_status_string(status)); /* Leili */ 
+
+      if (Do_logging > HIGH_LOGGING) { /* rhoge */
+	fprintf(stderr,"\nGot message.\n");
+	fprintf(stderr,"\nCalling `alarm'...\n");
+      }
+
+      (void) alarm(0);
+
+      if (Do_logging > HIGH_LOGGING) 
+	fprintf(stderr,"\nAlarm called.\n"); /* rhoge */
+      
+      (void) fprintf(stderr,"Checking for an error  \n"); /* Leili */
+      /* Check for error */
+      if (status != ACR_OK) {
+         continue_looping = FALSE;
+         state = TERMINATING;
+         break;
+      }
+
+      /* Set flags indicating whether we should do anything with the files
+         and whether the file lists contain an extra file */
+      process_files = FALSE;
+      have_extra_file = FALSE;
+      /* Get group list */
+      group_list = acr_get_message_group_list(input_message);
+      
+      /* Get PDU type. Default is data transfer */
+      pdu_type = acr_find_short(group_list, DCM_PDU_Type, ACR_PDU_DATA_TF);
+      (void) fprintf(stderr,"We got the pdu and it is: %d\n", pdu_type); /* Leili */
+  
+
+      /* Deal with PDU state */
+      switch (pdu_type) {
+      
+      /* Associate request */
+      case ACR_PDU_ASSOC_RQ:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\n Associate request is ACR_PDU_ASSOC_RQ\n");
+
+         if (state != WAITING_FOR_ASSOCIATION) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Work out reply and get connection info */
+         (void) fprintf(stderr,"About to go to reply program\n"); /* Leili */
+         output_message = associate_reply(input_message, &project_name, 
+                                          &pres_context_id, &byte_order,
+                                          &vr_encoding, &maximum_length);
+	 (void) fprintf(stderr,"We finished with the reply program\n"); /* Leili */
+
+         /* Modify the input and output streams according to the 
+            connection info */
+         acr_set_byte_order(afpin, byte_order);
+         acr_set_vr_encoding(afpin, vr_encoding);
+         acr_set_byte_order(afpout, byte_order);
+         acr_set_vr_encoding(afpout, vr_encoding);
+         acr_set_dicom_pres_context_id(afpout, pres_context_id);
+         acr_set_dicom_maximum_length(afpout, maximum_length);
+
+         /* Get ready for files */
+         num_files = 0;
+         state = WAITING_FOR_DATA;
+
+         break;
+
+      /* Release */
+      case ACR_PDU_REL_RQ:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\nAssociate request is ACR_PDU_REL_RQ\n");
+
+         if (state != WAITING_FOR_DATA) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+         output_message = release_reply(input_message);
+         state = TERMINATING;
+         process_files = TRUE;
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,
+		   "\nReceived release request; process flag set.\n");
+
+         break;
+
+      /* Abort */
+      case ACR_PDU_ABORT_RQ:
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,"\nAssociate request is ACR_PDU_ABORT_RQ\n");
+
+         output_message = abort_reply(input_message);
+         state = TERMINATING;
+         break;
+
+      /* Data transfer */
+      case ACR_PDU_DATA_TF:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,"\nAssociate request is ACR_PDU_DATA_TF\n");
+
+         /* Check state */
+         if (state != WAITING_FOR_DATA) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Check command and compose a reply */
+         acr_command = acr_find_short(group_list, ACR_Command, -1);
+         switch (acr_command) {
+         case ACR_C_STORE_RQ:
+         case ACR_C_ECHO_RQ:
+            output_message = data_reply(input_message);
+            break;
+         default:
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Carry on only if we have a store command */
+         if (acr_command != ACR_C_STORE_RQ) break;
+
+         /* Get rid of the command groups */
+         group_list = skip_command_groups(group_list);
+
+         /* Was the data attached to the command? If not, read in the next
+            message - it should contain the data */
+         if (group_list == NULL) {
+
+            /* Delete the previous message */
+            if (input_message != NULL)
+               acr_delete_message(input_message);
+
+            /* Read the data and check the status */
+            Alarmed_afp = afpin;
+            (void) signal(SIGALRM, timeout_handler);
+            (void) alarm(CONNECTION_TIMEOUT);
+            status=acr_input_dicom_message(afpin, &input_message);
+            (void) alarm(0);
+            if (status != ACR_OK) {
+               state = DISCONNECTING;
+               break;
+            }
+
+            /* Check that we have a data PDU */
+            group_list = acr_get_message_group_list(input_message);
+            if (acr_find_short(group_list, DCM_PDU_Type, ACR_PDU_DATA_TF)
+                != ACR_PDU_DATA_TF) {
+               status = ACR_HIGH_LEVEL_ERROR;
+               state = DISCONNECTING;
+               break;
+            }
+
+            /* Skip command groups and check for no data */
+            group_list = skip_command_groups(group_list);
+            if (group_list == NULL) break;
+
+         }
+         (void) fprintf(stderr,"End of while loop, we are out of the loop \n"); /* Leili */
+
+         /* Extend file list if necessary */
+         if (num_files >= num_files_alloc) {
+            num_files_alloc = num_files + FILE_ALLOC_INCREMENT;
+            file_list = REALLOC(file_list, 
+                                num_files_alloc * sizeof(*file_list));
+            file_info_list = 
+               REALLOC(file_info_list, 
+                       num_files_alloc * sizeof(*file_info_list));
+         }
+         file_list[num_files] = NULL;
+         file_info_list[num_files] = 
+            MALLOC(sizeof(*file_info_list[num_files]));
+
+         /* Save the object */
+         //save_transferred_object(group_list, 
+         //                        file_prefix, &file_list[num_files],
+         //                        file_info_list[num_files]);
+         /* Added by leili */
+         save_transferred_object(group_list, 
+                                 file_prefix2, &file_list[num_files],
+                                 file_info_list[num_files]);
+         
+         (void) fprintf(stderr,"Finished saving transfered object number %d \n", (num_files)+1); /* Leili */
+         num_files++;
+
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "   Copied %s\n", file_list[num_files-1]);
+         }
+         (void) fprintf(stderr,"Number of files are: %d \n", num_files); /* Leili */
+
+	 if (Do_logging > HIGH_LOGGING) { /* rhoge */
+	   fprintf(stderr,
+		   "About to check if we're done file group\n");
+
+	   fprintf(stderr,"\nnum_files: \t%d",num_files);
+	   fprintf(stderr,"\nfile_info_list[num_files-1]->study_id: \t%.6f",
+		   file_info_list[num_files-1]->study_id);
+	   fprintf(stderr,"\nfile_info_list[0]->study_id: \t%.6f",
+		   file_info_list[0]->study_id);
+	   fprintf(stderr,"\nfile_info_list[num_files-1]->acq_id: \t%d",
+		   file_info_list[num_files-1]->acq_id);
+	   fprintf(stderr,"\nfile_info_list[0]->acq_id: \t%d",
+		   file_info_list[0]->acq_id);
+
+	 }	 
+
+         /* Check whether we have reached the end of a group of files */
+         if (num_files > 1) {
+            if ((file_info_list[num_files-1]->study_id != 
+                 file_info_list[0]->study_id) ||
+                (file_info_list[num_files-1]->acq_id != 
+                 file_info_list[0]->acq_id)) {
+               process_files = TRUE;
+               have_extra_file = TRUE;
+
+	       if (Do_logging > HIGH_LOGGING) /* rhoge */
+		 fprintf(stderr,
+			 "\nend of file group detected, process flag set.\n");
+            }
+         }
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,
+		   "\ndone checking for end of file group\n");
+
+         break;
+
+         /* Unknown command */
+         default:
+
+	   if (Do_logging > HIGH_LOGGING) /* rhoge */
+	     fprintf(stderr,"\nAssociate request is default (an error)\n");
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+
+      }        /* End of switch on pdu_type */
+      
+      (void) fprintf(stderr,"We break and came out since we didn't have the store command\n"); /* Leili */
+
+      /* Delete input message */
+      if (input_message != NULL)
+         acr_delete_message(input_message);
+
+      /* Use the files if we have a complete acquisition */
+      if (process_files) {
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\nEntered the `process files' block...\n");
+
+         /* Log the fact */
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "\nCopied one acquisition.\n");
+         }
+
+         /* Check for file from next acquisition */
+         if (have_extra_file) num_files--;
+
+	 /* uncomment to prevent forking */
+	 /* #define NO_FORK */
+
+	 if (Fork) {
+	   /* Fork child to process the files */
+	   child_pid = fork();
+	 } else {
+	   child_pid = 0;
+	 }
+
+         if (child_pid > 0) {      /* Parent process */
+            if (Do_logging >= LOW_LOGGING) {
+               (void) fprintf(stderr, 
+                              "Forked process to create minc files.\n");
+            }
+
+         }                         /* Error forking */
+         else if (child_pid < 0) {
+            (void) fprintf(stderr, 
+                           "Error forking child to create minc file\n");
+            return;
+         }
+         else {                    /* Child process */
+	     /*******************************************/
+             /* Added by Leili                          */
+	     /* Close file descriptors to avoid buffering problems.
+                STDERR is sometimes left open, therefore this command 
+                maybe needed */    
+	     if(Fork){
+              int fd;
+              for(fd=getdtablesize()-1; fd>= 0; fd--) {
+		if(fd != 2){
+                  (void) close(fd);
+                }
+              }
+             }
+             /******************************************/ 
+	     /* Do something with the files */
+             (void) fprintf(stderr, "We are about to do something with the files.\n"); /* Leili */
+             (void) fprintf(stderr, "The project name is:%s\n", project_name); /* Leili */
+             (void) fprintf(stderr, "The pname is:%s\n", pname); /* Leili */
+	     use_the_files(project_name, num_files, file_list, 
+			   file_info_list,UseArgDir,OutDir);
+             
+ 
+            /* Remove the temporary files */
+            cleanup_files(num_files, file_list);
+
+            /* Remove the temporary directory if the server has finished */
+	    /* (this does not seem to work all the time) */
+            if ((temp_dir != NULL) && (kill(server_pid, 0) != 0)) {
+               cleanup_files(1, &temp_dir);
+            }
+
+            /* Print message about child finishing */
+            if (Do_logging >= LOW_LOGGING) {
+               (void) fprintf(stderr, "Minc creation process finished.\n");
+            }
+
+	    if (Fork) {
+	      /* Exit from child */
+	      exit(EXIT_SUCCESS);
+	    }
+
+         }         /* End of child process */
+
+         /* Put blank line in log file */
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "\n");
+         }
+
+         /* Reset the lists */
+         free_list(num_files, file_list, file_info_list);
+         if (have_extra_file) {
+            file_list[0] = file_list[num_files];
+            file_info_list[0] = file_info_list[num_files];
+            file_list[num_files] = NULL;
+            file_info_list[num_files] = NULL;
+         }
+         num_files = (have_extra_file ? 1 : 0);
+      } // end of if(process files)
+
+      if (Do_logging > HIGH_LOGGING) /* rhoge */
+	fprintf(stderr,
+		"\n just passed `process files' loop\n");
+
+      /* Check for disconnection */
+      if (state == DISCONNECTING) {
+         continue_looping = FALSE;
+         break;
+      }
+
+      /* Send reply */
+      Alarmed_afp = afpout;
+      (void) signal(SIGALRM, timeout_handler);
+      (void) alarm(CONNECTION_TIMEOUT);
+      status = acr_output_dicom_message(afpout, output_message);
+      (void) alarm(0);
+
+      /* Delete output message */
+      if (output_message != NULL)
+         acr_delete_message(output_message);
+
+      if (status != ACR_OK) {
+         state = TERMINATING;
+         break;
+      }
+
+      if (Do_logging > HIGH_LOGGING) /* rhoge */
+	fprintf(stderr,
+		"\nbottom of loop over messages\n");
+
+   }        /* End of loop over messages */
+
+   if (Do_logging > HIGH_LOGGING) /* rhoge */
+     fprintf(stderr,
+	     "\njust out of loop over messages\n");
+
+   /* Free the input and output streams */
+   acr_close_dicom_file(afpin);
+   acr_close_dicom_file(afpout);
+
+   /* Save name of first file in last set transferred */
+   if ((num_files > 0) && (file_list[0] != NULL)) {
+      last_file_name[sizeof(last_file_name) - 1] = '\0';
+      (void) strncpy(last_file_name, file_list[0], sizeof(last_file_name)-1);
+   }
+   else {
+      last_file_name[0] = '\0';
+   }
+
+   /* Clean up files, if needed */
+   if (num_files > 0) {
+      cleanup_files(num_files, file_list);
+      free_list(num_files, file_list, file_info_list);
+      num_files = 0;
+   }
+   FREE(file_list);
+   FREE(file_info_list);
+   
+   /* Remove the file prefix directory (this only happens if it is empty). */
+   cleanup_files(1, &temp_dir);
+   FREE(temp_dir);
+
+   /* Check for connection timeout */
+   if (Connection_timeout) {
+      (void) fprintf(stderr, "Connection timed out.\n");
+   }
+
+   /* Print final message */
+   if ((status == ACR_OK) || (status == ACR_END_OF_INPUT)) {
+      (void) sprintf(exit_string, "Finished transfer.");
+      exit_status = EXIT_SUCCESS;
+   }
+   else {
+      (void) sprintf(exit_string, "%s. Disconnecting.", 
+                     acr_status_string(status));
+      exit_status = EXIT_FAILURE;
+   }
+   (void) fprintf(stderr, "The logging set to be %d\n", Do_logging); /* Leili */
+   (void) fprintf(stderr, "The status of the message is: %s \n", acr_status_string(status)); /* Leili */
+
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "\n%s: %s\n", pname, exit_string);
+   }
+
+   if ((status != ACR_OK) && (status != ACR_END_OF_INPUT)) {
+      if (SYSTEM_LOG != NULL) {
+         if ((fptemp = fopen(SYSTEM_LOG, "w")) != NULL) {
+            if ((int) strlen(last_file_name) > 0) {
+               (void) fprintf(fptemp, "%s: File \"%s\"\n",
+                              pname, last_file_name);
+            }
+            (void) fprintf(fptemp, "%s: %s\n", pname, exit_string);
+            (void) fclose(fptemp);
+         }
+      }
+   }
+
+   /* Free the project_name string */
+   if (project_name != NULL) FREE(project_name);
+
+   exit(exit_status);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : timeout_handler
+@INPUT      : 
+@OUTPUT     : (none)
+@RETURNS    : 
+@DESCRIPTION: Routine to handle connection timeouts.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : March 10, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+/* ARGSUSED */
+public void timeout_handler(int sig)
+{
+   Connection_timeout = TRUE;
+   if (Alarmed_afp != NULL) {
+      acr_dicom_set_eof(Alarmed_afp);
+   }
+   return;
+}
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : skip_command_groups
+@INPUT      : group_list
+@OUTPUT     : (none)
+@RETURNS    : Pointer to head of group list
+@DESCRIPTION: Skips over command groups in a group list, returning the rest
+              of the list.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : March 7, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Group skip_command_groups(Acr_Group group_list)
+{
+   while ((group_list != NULL) &&
+          ((acr_get_group_group(group_list) == DCM_PDU_GRPID) ||
+           (acr_get_group_group(group_list) == ACR_MESSAGE_GID))) {
+      group_list = acr_get_group_next(group_list);
+   }
+
+   return group_list;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : cleanup_files
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Removes files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void cleanup_files(int num_files, char *file_list[])
+{
+   int i;
+
+   if (Keep_files) return;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         (void) remove(file_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_list
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free
+              the arrays themselves.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list)
+{
+   int i;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         FREE(file_list[i]);
+      }
+      if (file_info_list[i] != NULL) {
+         FREE(file_info_list[i]);
+      }
+   }
+
+   return;
+}
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicomserver-nondebug2.c
@@ -0,0 +1,1080 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicomserver.c
+@DESCRIPTION: Program to receive images from Siemens Vision.
+@GLOBALS    : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+
+Modified by R. Hoge Feb. 2000 to handle acquisition loop dynamic scans
+on Siemens Sonata system
+
+ * $Log: dicomserver-nondebug2.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.9  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.8  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.7  2001/08/29 20:55:53  rhoge
+ * added -help option
+ *
+ * Revision 1.6  2001/07/19 17:43:46  rhoge
+ * added -nofork command line option to prevent forking
+ *
+ * Revision 1.5  2001/02/26 13:37:59  rhoge
+ * redirect sderr to /dev/null if no logging - prevents hangups due to
+ * printfs dumping text into connection stream?
+ *
+ * Revision 1.4  2001/02/26 06:17:42  rhoge
+ * changed tmp dir assignment to be consistent, always uses stdio.h stuff.
+ * also added command-line flags for destination dir, logging level, and
+ * retention of dicom files (are put in dest dir - must be specified)
+ *
+ * Revision 1.3  2000/12/14 21:14:58  rhoge
+ * added macro (NO_FORK) to prevent forking if uncommented
+ *
+ * Revision 1.2  2000/12/13 13:22:18  rhoge
+ * experimental changes to forking code for minc file creation - should
+ * be no change
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:55  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.2  1997/07/10  17:35:35  neelin
+ * Changed error handling and fixed message deletion.
+ *
+ * Revision 4.1  1997/07/08  23:15:09  neelin
+ * Added support for C_ECHO command.
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.2  1997/03/11  13:10:48  neelin
+ * Working version of dicomserver.
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/dicomserver-nondebug2.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <dicomserver.h>
+
+/* Global for minc history */
+extern char *minc_history;
+
+/* State of server. Note that DISCONNECTING is used for a high-level
+   protocol error and TERMINATING is used for a low-level error or
+   end of input */
+typedef enum {
+   WAITING_FOR_ASSOCIATION, WAITING_FOR_DATA, DISCONNECTING, TERMINATING
+} Server_state;
+
+/* stuff added by rhoge */
+
+#define EXTREME_LOGGING 10 /* rhoge */
+
+
+/* Do we do logging? */
+/********************/
+//int Do_logging = 0;    /* Belong to rhoge, commented out by leili*/
+/*added by Leili:*/
+int Do_logging = 
+#ifndef DO_HIGH_LOGGING
+  LOW_LOGGING;
+# else
+  HIGH_LOGGING;
+# endif 
+/******************/
+
+/* Changed by leili from False to True */
+int Fork = TRUE;
+/*****************/
+
+/* Do we keep files or are they temporary? */
+static int Keep_files = 
+#ifndef KEEP_FILES
+   FALSE;
+#else
+   TRUE;
+#endif
+/******************/
+/* added by Leili */
+/* In what directory do we run? */
+static char *run_dir = "/var/tmp";
+/******************/
+
+/* Globals for handling connection timeouts */
+int Connection_timeout = FALSE;
+Acr_File *Alarmed_afp = NULL;
+File_Type file_type = N4DCM ; /* type of input files */
+int N4_OFFSET;
+char *pname;
+int main(int argc, char *argv[])
+{
+   char *pname;
+   Acr_File *afpin, *afpout;
+   Acr_Status status;
+   Server_state state;
+   int acr_command;
+   Acr_Group group_list;
+   Acr_Message input_message, output_message;
+   int exit_status;
+   char exit_string[256];
+   char **file_list;
+   Data_Object_Info **file_info_list;
+   int num_files, num_files_alloc;
+   static char file_prefix_string[L_tmpnam+1] = "dicomserver";
+   char *file_prefix = file_prefix_string;
+   char *temp_dir;
+   int continue_looping;
+   FILE *fptemp;
+   char last_file_name[256];
+   char *project_name = NULL;
+   char logfilename[256];
+   int pdu_type;
+   int process_files, have_extra_file;
+   Acr_byte_order byte_order;
+   Acr_VR_encoding_type vr_encoding;
+   int pres_context_id;
+   long maximum_length;
+   pid_t server_pid, child_pid;
+   int statptr;
+
+   /* added by rhoge */
+   int ix;
+   int UseArgDir = 0;
+   char OutDir[128];
+   /******************/
+   /* Added by Leili */
+   long ifile;
+   Acr_Element element;
+   char model_name[256];
+   char patient_name[256];
+   char patient_id[256];
+   char reg_time[256];
+   char reg_date[256];
+   char out_dir[256];
+   char temp_name[256];
+  
+   /***********************/ 
+   /* Get server process id */
+   server_pid = getpid();
+   
+   /*************************/
+   
+   /* Change to tmp directory -
+      note that this will be default file destination if no aetitle
+      or command-line specification are received (rhoge) */
+   /* commented out by leili */
+   
+   //(void) chdir(P_tmpdir); 
+   
+   /* added by leili */
+   /* change to tmp directory */
+   if (run_dir != NULL) {
+    (void) chdir(run_dir);
+     } 
+   /*****************************/
+
+   /* Create minc history string */
+   {
+      char *string;
+      string = "dicomserver";
+      minc_history = time_stamp(1, &string);
+   }
+
+   /* read in all the input pars and file names */
+
+   for (ix = 1; ix<argc; ix++) { 
+    
+      if (!strncmp(argv[ix],"-destdir",8)) { 
+       ix++; 
+       UseArgDir = 1; 
+       strcpy(OutDir,argv[ix]);  
+        (void) strcat(OutDir, "/");  /* make sure path ends with slash */  
+    }    
+        else if (!strncmp(argv[ix],"-log",4)) { 
+         ix++; 
+         Do_logging = atoi(argv[ix]); 
+       } 
+      else if (!strncmp(argv[ix],"-fork",5)) {  
+        Fork = TRUE; 
+      } 
+      else if (!strncmp(argv[ix],"-keep_dcm",9)) {  
+        Keep_files = TRUE; 
+      } 
+      else if (!strncmp(argv[ix],"-help",9)) {  
+         (void) fprintf(stderr,"Usage:  dicomserver [<options>]\nOptions:\n\t-log <n>\n\t-fork\n\t-keep_dcm\n\t-help\n"); 
+         exit(EXIT_SUCCESS); 
+       } 
+       else { 
+         (void) fprintf(stderr,"Usage:  dicomserver [<options>]\nOptions:\n\t-log <n>\n\t-fork\n\t-keep_dcm\n\t-help\n"); 
+         exit(EXIT_FAILURE); 
+	 } 
+	 }
+   
+   /* Re-open stderr if we are logging */
+   if (Do_logging > NO_LOGGING) {
+      (void) sprintf(logfilename, "dicomserver-%d.log", 
+                     (int) getpid());
+      (void) freopen(logfilename, "w", stderr);
+      setbuf(stderr, NULL);
+   } else {
+      (void) sprintf(logfilename, "/dev/null");
+      (void) freopen(logfilename, "w", stderr);
+      setbuf(stderr, NULL);
+   }
+
+   // set up type of connection (Syngo?)
+   file_type = N4DCM; // default
+   N4_OFFSET = 0; 
+
+   /* Print message at start */
+   pname = argv[0];
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "%s: Started dicom server.\n", pname);
+   }
+
+   /* Make connection */
+   open_connection(argc, argv, &afpin, &afpout);
+   
+
+   /* Check that the connection was made */
+   if ((afpin == NULL) || (afpout == NULL)) {
+      (void) fprintf(stderr, "%s: Error opening connection.\n", pname);
+      exit(EXIT_FAILURE);
+   }
+   
+     
+
+   /* Print connection message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "%s: Connection accepted.\n", pname);
+   }
+
+#ifdef DO_INPUT_TRACING
+   /* Enable input tracing */
+   acr_dicom_enable_trace(afpin);
+   acr_dicom_enable_trace(afpout);
+#endif
+
+   /* Create file prefix. Create the temporary file to avoid file name 
+      clashes */
+   /*****************************/
+   /* Commented out by leili */ 
+   //temp_dir = NULL;
+   //if ( !Keep_files) {
+   //   (void) tmpnam(file_prefix);
+   //   if (mkdir(file_prefix, (mode_t) 0777)) {
+   //      (void) fprintf(stderr, 
+   //         "%s: Unable to create directory for temporary files.\n",
+   //                     pname);
+   //      perror(pname);
+   //      exit(EXIT_FAILURE);
+   //   }
+   //   temp_dir = strdup(file_prefix);
+   //   (void) strcat(file_prefix, "/dicom");
+   //}
+   
+   // else {
+   //  file_prefix=strdup(OutDir);
+
+   //  if (mkdir(file_prefix, (mode_t) 0777)) {
+   //    (void) fprintf(stderr, 
+   //         "Directory %s exists...\n",file_prefix);
+   //   }
+   //  temp_dir = strdup(file_prefix);
+   //   (void) strcat(file_prefix, "/dicom");
+   // }
+   /****************************/
+   /* Added by Leili           */
+   temp_dir = NULL;
+   if (! Keep_files){
+    temp_dir = tempnam(NULL, NULL);
+    if(mkdir(temp_dir, (mode_t) 0777)){
+      (void) fprintf(stderr, 
+            "%s: Unable to create directory for temporary files.\n",
+                        pname);
+      perror(pname);
+      exit(EXIT_FAILURE);
+    }
+    (void) fprintf(stderr, "Temp directory for the dcm files:%s",temp_dir);
+    (void) strcpy(file_prefix, temp_dir);
+    (void) strcat(file_prefix, "/dicom");
+   } 
+   /*****************************/
+   (void) fprintf(stderr, "About to begin the space allocation \n"); /* Leili */
+
+   /* Get space for file lists */
+   num_files_alloc = FILE_ALLOC_INCREMENT;
+   file_list = MALLOC((size_t) num_files_alloc * sizeof(*file_list));
+   file_info_list = MALLOC(num_files_alloc * sizeof(*file_info_list));
+    
+   
+   /* Loop while reading messages */
+   state = WAITING_FOR_ASSOCIATION;
+   continue_looping = TRUE;
+   num_files = 0;
+
+   (void) fprintf(stderr, "About to start reading a message \n"); /* Leili */
+   while (continue_looping) {
+
+      /* Wait for any children that have finished */
+      while ((child_pid=wait3(&statptr, WNOHANG, NULL)) > 0) {}
+
+      /* If there are children, slow down the processing */
+      (void) fprintf(stderr, "If we have children, slow down \n"); /* Leili */
+      if (child_pid == 0) {
+         (void) sleep((unsigned int) SERVER_SLEEP_TIME);
+      }
+      (void) fprintf(stderr, "Start reading the message\n"); /* Leili */
+      /* Read in the message */
+      Alarmed_afp = afpin;
+      (void) signal(SIGALRM, timeout_handler);
+      (void) alarm(CONNECTION_TIMEOUT);
+  
+      if (Do_logging > HIGH_LOGGING) 
+       fprintf(stderr,"\nWaiting for dicom message...\n"); /* rhoge */
+      
+   /* chokes here at end of asynchronous transfer */
+      status=acr_input_dicom_message(afpin, &input_message); 
+      (void) fprintf(stderr, "The status of the message is: %s \n", acr_status_string(status)); /* Leili */ 
+
+      if (Do_logging > HIGH_LOGGING) { /* rhoge */
+	fprintf(stderr,"\nGot message.\n");
+	fprintf(stderr,"\nCalling `alarm'...\n");
+      }
+
+      (void) alarm(0);
+
+      if (Do_logging > HIGH_LOGGING) 
+	fprintf(stderr,"\nAlarm called.\n"); /* rhoge */
+      
+      (void) fprintf(stderr,"Checking for an error  \n"); /* Leili */
+      /* Check for error */
+      if (status != ACR_OK) {
+         continue_looping = FALSE;
+         state = TERMINATING;
+         break;
+      }
+
+      /* Set flags indicating whether we should do anything with the files
+         and whether the file lists contain an extra file */
+      process_files = FALSE;
+      have_extra_file = FALSE;
+      /* Get group list */
+      group_list = acr_get_message_group_list(input_message);
+      
+      /* Get PDU type. Default is data transfer */
+      pdu_type = acr_find_short(group_list, DCM_PDU_Type, ACR_PDU_DATA_TF);
+      (void) fprintf(stderr,"We got the pdu and it is: %d\n", pdu_type); /* Leili */
+  
+
+      /* Deal with PDU state */
+      switch (pdu_type) {
+      
+      /* Associate request */
+      case ACR_PDU_ASSOC_RQ:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\n Associate request is ACR_PDU_ASSOC_RQ\n");
+
+         if (state != WAITING_FOR_ASSOCIATION) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Work out reply and get connection info */
+         (void) fprintf(stderr,"About to go to reply program\n"); /* Leili */
+         output_message = associate_reply(input_message, &project_name, 
+                                          &pres_context_id, &byte_order,
+                                          &vr_encoding, &maximum_length);
+	 (void) fprintf(stderr,"We finished with the reply program\n"); /* Leili */
+
+         /* Modify the input and output streams according to the 
+            connection info */
+         acr_set_byte_order(afpin, byte_order);
+         acr_set_vr_encoding(afpin, vr_encoding);
+         acr_set_byte_order(afpout, byte_order);
+         acr_set_vr_encoding(afpout, vr_encoding);
+         acr_set_dicom_pres_context_id(afpout, pres_context_id);
+         acr_set_dicom_maximum_length(afpout, maximum_length);
+
+         /* Get ready for files */
+         num_files = 0;
+         state = WAITING_FOR_DATA;
+
+         break;
+
+      /* Release */
+      case ACR_PDU_REL_RQ:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\nAssociate request is ACR_PDU_REL_RQ\n");
+
+         if (state != WAITING_FOR_DATA) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+         output_message = release_reply(input_message);
+         state = TERMINATING;
+         process_files = TRUE;
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,
+		   "\nReceived release request; process flag set.\n");
+
+         break;
+
+      /* Abort */
+      case ACR_PDU_ABORT_RQ:
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,"\nAssociate request is ACR_PDU_ABORT_RQ\n");
+
+         output_message = abort_reply(input_message);
+         state = TERMINATING;
+         break;
+
+      /* Data transfer */
+      case ACR_PDU_DATA_TF:
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,"\nAssociate request is ACR_PDU_DATA_TF\n");
+
+         /* Check state */
+         if (state != WAITING_FOR_DATA) {
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Check command and compose a reply */
+         acr_command = acr_find_short(group_list, ACR_Command, -1);
+         switch (acr_command) {
+         case ACR_C_STORE_RQ:
+         case ACR_C_ECHO_RQ:
+            output_message = data_reply(input_message);
+            break;
+         default:
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+         }
+
+         /* Carry on only if we have a store command */
+         if (acr_command != ACR_C_STORE_RQ) break;
+
+         /* Get rid of the command groups */
+         group_list = skip_command_groups(group_list);
+
+         /* Was the data attached to the command? If not, read in the next
+            message - it should contain the data */
+         if (group_list == NULL) {
+
+            /* Delete the previous message */
+            if (input_message != NULL)
+               acr_delete_message(input_message);
+
+            /* Read the data and check the status */
+            Alarmed_afp = afpin;
+            (void) signal(SIGALRM, timeout_handler);
+            (void) alarm(CONNECTION_TIMEOUT);
+            status=acr_input_dicom_message(afpin, &input_message);
+            (void) alarm(0);
+            if (status != ACR_OK) {
+               state = DISCONNECTING;
+               break;
+            }
+
+            /* Check that we have a data PDU */
+            group_list = acr_get_message_group_list(input_message);
+            if (acr_find_short(group_list, DCM_PDU_Type, ACR_PDU_DATA_TF)
+                != ACR_PDU_DATA_TF) {
+               status = ACR_HIGH_LEVEL_ERROR;
+               state = DISCONNECTING;
+               break;
+            }
+
+            /* Skip command groups and check for no data */
+            group_list = skip_command_groups(group_list);
+            if (group_list == NULL) break;
+
+         }
+         (void) fprintf(stderr,"End of while loop, we are out of the loop \n"); /* Leili */
+
+         /* Extend file list if necessary */
+         if (num_files >= num_files_alloc) {
+            num_files_alloc = num_files + FILE_ALLOC_INCREMENT;
+            file_list = REALLOC(file_list, 
+                                num_files_alloc * sizeof(*file_list));
+            file_info_list = 
+               REALLOC(file_info_list, 
+                       num_files_alloc * sizeof(*file_info_list));
+         }
+         file_list[num_files] = NULL;
+         file_info_list[num_files] = 
+            MALLOC(sizeof(*file_info_list[num_files]));
+
+         /* Save the object */
+         save_transferred_object(group_list, 
+                                 file_prefix, &file_list[num_files],
+                                 file_info_list[num_files]);
+         (void) fprintf(stderr,"Finished saving transfered object number %d \n", (num_files)+1); /* Leili */
+         num_files++;
+
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "   Copied %s\n", file_list[num_files-1]);
+         }
+         (void) fprintf(stderr,"Number of files are: %d \n", num_files); /* Leili */
+
+	 if (Do_logging > HIGH_LOGGING) { /* rhoge */
+	   fprintf(stderr,
+		   "About to check if we're done file group\n");
+
+	   fprintf(stderr,"\nnum_files: \t%d",num_files);
+	   fprintf(stderr,"\nfile_info_list[num_files-1]->study_id: \t%.6f",
+		   file_info_list[num_files-1]->study_id);
+	   fprintf(stderr,"\nfile_info_list[0]->study_id: \t%.6f",
+		   file_info_list[0]->study_id);
+	   fprintf(stderr,"\nfile_info_list[num_files-1]->acq_id: \t%d",
+		   file_info_list[num_files-1]->acq_id);
+	   fprintf(stderr,"\nfile_info_list[0]->acq_id: \t%d",
+		   file_info_list[0]->acq_id);
+
+	 }	 
+
+         /* Check whether we have reached the end of a group of files */
+         if (num_files > 1) {
+            if ((file_info_list[num_files-1]->study_id != 
+                 file_info_list[0]->study_id) ||
+                (file_info_list[num_files-1]->acq_id != 
+                 file_info_list[0]->acq_id)) {
+               process_files = TRUE;
+               have_extra_file = TRUE;
+
+	       if (Do_logging > HIGH_LOGGING) /* rhoge */
+		 fprintf(stderr,
+			 "\nend of file group detected, process flag set.\n");
+            }
+         }
+
+	 if (Do_logging > HIGH_LOGGING) /* rhoge */
+	   fprintf(stderr,
+		   "\ndone checking for end of file group\n");
+
+         break;
+
+         /* Unknown command */
+         default:
+
+	   if (Do_logging > HIGH_LOGGING) /* rhoge */
+	     fprintf(stderr,"\nAssociate request is default (an error)\n");
+            status = ACR_HIGH_LEVEL_ERROR;
+            state = DISCONNECTING;
+            break;
+
+      }        /* End of switch on pdu_type */
+      
+      (void) fprintf(stderr,"We break and came out since we didn't have the store command\n"); /* Leili */
+
+      /* Delete input message */
+      if (input_message != NULL)
+         acr_delete_message(input_message);
+
+      /* Use the files if we have a complete acquisition */
+      if (process_files) {
+
+	if (Do_logging > HIGH_LOGGING) /* rhoge */
+	  fprintf(stderr,"\nEntered the `process files' block...\n");
+
+         /* Log the fact */
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "\nCopied one acquisition.\n");
+         }
+
+         /* Check for file from next acquisition */
+         if (have_extra_file) num_files--;
+
+	 /* uncomment to prevent forking */
+	 /* #define NO_FORK */
+
+	 if (Fork) {
+	   /* Fork child to process the files */
+	   child_pid = fork();
+	 } else {
+	   child_pid = 0;
+	 }
+
+         if (child_pid > 0) {      /* Parent process */
+            if (Do_logging >= LOW_LOGGING) {
+               (void) fprintf(stderr, 
+                              "Forked process to create minc files.\n");
+            }
+
+         }                         /* Error forking */
+         else if (child_pid < 0) {
+            (void) fprintf(stderr, 
+                           "Error forking child to create minc file\n");
+            return;
+         }
+         else {                    /* Child process */
+	 /*************************************************/
+         /* Added by Leili                                */
+	 /* Close file descriptors to avoid buffering problems.
+            STDERR is sometimes left open, therefore this command 
+            maybe needed */    
+	     if(Fork){
+              int fd;
+              for(fd=getdtablesize()-1; fd>= 0; fd--) {
+		if(fd != 2){
+                  (void) close(fd);
+                }
+              }
+             }
+	/*******************************************************/ 
+        /* Added by leili to check the manfucaturer model names */
+        printf("Checking file types...   ");
+
+        for (ifile = 0; ifile < num_files; ifile++) {
+         char dicm_test_string[5];
+         fptemp = fopen(file_list[ifile], "r");
+    
+        if (fptemp == NULL) {
+         fprintf(stderr,"Error opening file %s!\n",file_list[ifile]);
+         exit(EXIT_FAILURE);
+        } 
+
+        /* Numaris 4 DICOM CD/Export file? if so, bytes 129-132 will 
+	contain the string `DICM' */
+
+        fseek(fptemp,128,SEEK_SET);
+        fread(dicm_test_string,1,4,fptemp);
+        dicm_test_string[4] = (char) '\0';       
+   
+        // Added by leili to make the program works for data form the old vision system 
+        // To do this, we should figure out the manufacturer model from the dicom header
+        // if the machine is the old vision, create the output directory
+        // then call the dicom_to_minc script to do the conversion
+        group_list = read_siemens_dicom(file_list[ifile],100);
+        element = acr_find_group_element(group_list, ACR_Manufacturer_model);
+        if (element != NULL) {
+         string_to_filename(acr_get_element_string(element), model_name,
+                         sizeof(model_name));}
+    
+        if ((element == NULL) || (strlen(model_name) == 0))
+         (void) strcpy(model_name, "unknown");
+        (void) fprintf(stderr," The model_name is %s\n", model_name);    
+        //*************************************************************
+       	//(void) fprintf(stderr,"\nfile_info_list[num_files-1]->study_id: \t%.6f",
+        //               file_info_list[num_files-1]->study_id);
+	 (void)  fprintf(stderr,"\nfile_info_list[0]->study_id: \t%.6f",
+                       file_info_list[0]->study_id);
+        
+         (void) fprintf(stderr,"\nfile_info_list[num_files-1]->study_date: \t%5d", 
+                       file_info_list[num_files-1]->study_date);
+
+         (void) fprintf(stderr,"\nfile_info_list[num_files-1]->study_time: \t%5d", 
+                       file_info_list[num_files-1]->study_time); 
+         
+	if ((strcmp(model_name, "sonatavision") == 0) && (!strncmp(dicm_test_string,"DICM",4)) || 
+                           ((file_info_list[0]->study_id > 20020601.0000) && (!strncmp(dicm_test_string,"DICM",4)))){
+         file_type = N4DCM;
+         N4_OFFSET = 1; 
+         (void) fprintf(stderr,"assuming remaining files are Syngo DICOM (CD/Export).\n");
+         (void) fclose(fptemp);
+         break; // break out of file checking loop
+       
+        }else if ((strcmp(model_name, "magnetom_vision") == 0) || (file_info_list[0]->study_id <= 20020601.0000)) {
+	  file_type = IMA;
+         (void) fprintf(stderr,"assuming remaining files are IMA!\n");
+         (void) fclose(fptemp);
+         break; // break out of file checking loop 
+        }else {
+         file_type = N4DCM;
+         N4_OFFSET = 0; 
+         (void) fprintf(stderr,"assuming remaining files are Syngo DICOM.\n");
+         (void) fclose(fptemp);
+         break; // break out of file checking loop
+        } // end of file type check
+        
+       (void) fclose(fptemp);
+       } // end of loop over files to check for mixed file types
+
+       if (file_type == N4DCM) {
+       // read up to but not including pixel data
+       (void) fprintf(stderr, "We are about to do something with the files.\n"); /* Leili */
+       (void) fprintf(stderr, "The project name is:%s\n", project_name); /* Leili */
+       (void) fprintf(stderr, "The pname is:%s\n", pname); /* Leili */
+        use_the_files(project_name, num_files, file_list, 
+			   file_info_list,UseArgDir,OutDir);
+       }
+       /******************************************************************************/
+      /* Added by leili for the conversion of dicom data from the old vision machine */
+      else if (file_type == IMA) {       
+       strcat(out_dir, "/data/fmri/transfer/images/");
+       (void) sprintf(out_dir,"/data/fmri/transfer/images/MagnetomVision_%f",file_info_list[0]->study_id);  
+       group_list = read_siemens_dicom(file_list[ifile],100);    
+        
+       element = acr_find_group_element(group_list, ACR_Patient_name);
+       if (element != NULL) {
+          string_to_filename(acr_get_element_string(element), patient_name,
+                         sizeof(patient_name));
+          strcat(out_dir, "_");  
+          strcat(out_dir, patient_name);
+          strcat(out_dir, "_");   
+       }
+       if ((element == NULL) || (strlen(patient_name) == 0))
+          (void) strcpy(patient_name, "unknown");
+       
+     
+       element = acr_find_group_element(group_list, ACR_Patient_identification);
+       if (element != NULL) {
+          string_to_filename(acr_get_element_string(element), patient_id,
+                         sizeof(patient_id));
+          strcat(out_dir, patient_id);
+          strcat(out_dir, "_");
+       }
+       if ((element == NULL) || (strlen(patient_id) == 0))
+           (void) strcpy(patient_id, "unknown");
+      
+      
+       element = acr_find_group_element(group_list, ACR_Study_date);
+       if (element != NULL) {
+           string_to_filename(acr_get_element_string(element), reg_date,
+                         sizeof(reg_date));
+          strcat(out_dir, reg_date);
+          strcat(out_dir, "_");
+       }
+       if ((element == NULL) || (strlen(reg_date) == 0))
+           (void) strcpy(reg_date, "unknown");
+       
+      
+       element = acr_find_group_element(group_list, ACR_Study_time);
+       if (element != NULL) {
+           string_to_filename(acr_get_element_string(element), reg_time,
+                         sizeof(reg_time));
+           strcat(out_dir, reg_time);
+       }
+       if ((element == NULL) || (strlen(reg_time) == 0))
+           (void) strcpy(reg_time, "unknown");
+             
+
+       mkdir(out_dir,(mode_t) 0777);
+            
+       //execl("/sbin/cat", "/sbin/cat", "/usr/local/mni/bin", NULL);
+       //system ("set path=($path /usr/local/mni/bin)");  
+
+       // this part works fine but it's pretty ugly!!! Perhaps a better solution to the system call?
+       strcat(temp_name,"/software/source/dicomserver_test/conversion/dicomserver/dicom_to_minc");
+       //strcat(temp_name,"/usr/local/mni/bin/dicom_to_minc");
+       strcat(temp_name," ");
+       strcat(temp_name,out_dir);
+       //strcat(temp_name,"/.");
+       strcat(temp_name," ");
+       strcat(temp_name,"-compress");
+       strcat(temp_name, " ");
+       strcat(temp_name,"-inputdir");
+       strcat(temp_name, " ");
+       strcat(temp_name,temp_dir);
+       //strcat(temp_name,"/.");
+       (void) fprintf(stderr," The temp_name is: %s\n", temp_name);
+       system (temp_name);
+       /* Remove the temporary files */
+       cleanup_files(num_files, file_list);
+
+       /* Remove the temporary directory if the server has finished */
+       cleanup_files(1, &temp_dir);
+       exit(0);
+       }
+ 
+       /* Remove the temporary files */
+       cleanup_files(num_files, file_list);
+
+       /* Remove the temporary directory if the server has finished */
+       /* (this does not seem to work all the time) */
+        if ((temp_dir != NULL) && (kill(server_pid, 0) != 0)) {
+           cleanup_files(1, &temp_dir);
+        }
+
+       /* Print message about child finishing */
+        if (Do_logging >= LOW_LOGGING) {
+           (void) fprintf(stderr, "Minc creation process finished.\n");
+        }
+
+        if (Fork) {
+	  /* Exit from child */
+	  exit(EXIT_SUCCESS);
+	}
+
+         }         /* End of child process */
+
+         /* Put blank line in log file */
+         if (Do_logging >= LOW_LOGGING) {
+            (void) fprintf(stderr, "\n");
+         }
+
+         /* Reset the lists */
+         free_list(num_files, file_list, file_info_list);
+         if (have_extra_file) {
+            file_list[0] = file_list[num_files];
+            file_info_list[0] = file_info_list[num_files];
+            file_list[num_files] = NULL;
+            file_info_list[num_files] = NULL;
+         }
+         num_files = (have_extra_file ? 1 : 0);
+      } // end of if(process files)
+
+      if (Do_logging > HIGH_LOGGING) /* rhoge */
+	fprintf(stderr,
+		"\n just passed `process files' loop\n");
+
+      /* Check for disconnection */
+      if (state == DISCONNECTING) {
+         continue_looping = FALSE;
+         break;
+      }
+
+      /* Send reply */
+      Alarmed_afp = afpout;
+      (void) signal(SIGALRM, timeout_handler);
+      (void) alarm(CONNECTION_TIMEOUT);
+      status = acr_output_dicom_message(afpout, output_message);
+      (void) alarm(0);
+
+      /* Delete output message */
+      if (output_message != NULL)
+         acr_delete_message(output_message);
+
+      if (status != ACR_OK) {
+         state = TERMINATING;
+         break;
+      }
+
+      if (Do_logging > HIGH_LOGGING) /* rhoge */
+	fprintf(stderr,
+		"\nbottom of loop over messages\n");
+
+   }        /* End of loop over messages */
+
+   if (Do_logging > HIGH_LOGGING) /* rhoge */
+     fprintf(stderr,
+	     "\njust out of loop over messages\n");
+
+   /* Free the input and output streams */
+   acr_close_dicom_file(afpin);
+   acr_close_dicom_file(afpout);
+
+   /* Save name of first file in last set transferred */
+   if ((num_files > 0) && (file_list[0] != NULL)) {
+      last_file_name[sizeof(last_file_name) - 1] = '\0';
+      (void) strncpy(last_file_name, file_list[0], sizeof(last_file_name)-1);
+   }
+   else {
+      last_file_name[0] = '\0';
+   }
+
+   /* Clean up files, if needed */
+   if (num_files > 0) {
+      cleanup_files(num_files, file_list);
+      free_list(num_files, file_list, file_info_list);
+      num_files = 0;
+   }
+   FREE(file_list);
+   FREE(file_info_list);
+   
+   /* Remove the file prefix directory (this only happens if it is empty). */
+   cleanup_files(1, &temp_dir);
+   FREE(temp_dir);
+
+   /* Check for connection timeout */
+   if (Connection_timeout) {
+      (void) fprintf(stderr, "Connection timed out.\n");
+   }
+
+   /* Print final message */
+   if ((status == ACR_OK) || (status == ACR_END_OF_INPUT)) {
+      (void) sprintf(exit_string, "Finished transfer.");
+      exit_status = EXIT_SUCCESS;
+   }
+   else {
+      (void) sprintf(exit_string, "%s. Disconnecting.", 
+                     acr_status_string(status));
+      exit_status = EXIT_FAILURE;
+   }
+   (void) fprintf(stderr, "The logging set to be %d\n", Do_logging); /* Leili */
+   (void) fprintf(stderr, "The status of the message is: %s \n", acr_status_string(status)); /* Leili */
+
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "\n%s: %s\n", pname, exit_string);
+   }
+
+   if ((status != ACR_OK) && (status != ACR_END_OF_INPUT)) {
+      if (SYSTEM_LOG != NULL) {
+         if ((fptemp = fopen(SYSTEM_LOG, "w")) != NULL) {
+            if ((int) strlen(last_file_name) > 0) {
+               (void) fprintf(fptemp, "%s: File \"%s\"\n",
+                              pname, last_file_name);
+            }
+            (void) fprintf(fptemp, "%s: %s\n", pname, exit_string);
+            (void) fclose(fptemp);
+         }
+      }
+   }
+
+   /* Free the project_name string */
+   if (project_name != NULL) FREE(project_name);
+
+   exit(exit_status);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : timeout_handler
+@INPUT      : 
+@OUTPUT     : (none)
+@RETURNS    : 
+@DESCRIPTION: Routine to handle connection timeouts.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : March 10, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+/* ARGSUSED */
+public void timeout_handler(int sig)
+{
+   Connection_timeout = TRUE;
+   if (Alarmed_afp != NULL) {
+      acr_dicom_set_eof(Alarmed_afp);
+   }
+   return;
+}
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : skip_command_groups
+@INPUT      : group_list
+@OUTPUT     : (none)
+@RETURNS    : Pointer to head of group list
+@DESCRIPTION: Skips over command groups in a group list, returning the rest
+              of the list.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : March 7, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Group skip_command_groups(Acr_Group group_list)
+{
+   while ((group_list != NULL) &&
+          ((acr_get_group_group(group_list) == DCM_PDU_GRPID) ||
+           (acr_get_group_group(group_list) == ACR_MESSAGE_GID))) {
+      group_list = acr_get_group_next(group_list);
+   }
+
+   return group_list;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : cleanup_files
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Removes files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void cleanup_files(int num_files, char *file_list[])
+{
+   int i;
+
+   if (Keep_files) return;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         (void) remove(file_list[i]);
+      }
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_list
+@INPUT      : num_files - number of files in list
+              file_list - array of file names
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Frees up things pointed to in pointer arrays. Does not free
+              the arrays themselves.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_list(int num_files, char **file_list, 
+                      Data_Object_Info **file_info_list)
+{
+   int i;
+
+   for (i=0; i < num_files; i++) {
+      if (file_list[i] != NULL) {
+         FREE(file_list[i]);
+      }
+      if (file_info_list[i] != NULL) {
+         FREE(file_info_list[i]);
+      }
+   }
+
+   return;
+}
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/dicomserver.h
@@ -0,0 +1,158 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dicomserver.h
+@DESCRIPTION: Header file that includes things needed for dicomserver.
+@METHOD     : 
+@GLOBALS    : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+
+ * $Log: dicomserver.h,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.5  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.4  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.3  2000/12/14 21:17:34  rhoge
+ * cleanup of log messages
+ *
+ * Revision 1.2  2000/12/14 21:15:58  rhoge
+ * added ACQ and MEAS constants as flags for type of (non-standard)
+ * dynamic scan looping
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ * added num_slices_nominal to Data_Object_Info
+ * (for support of acquisition loop scans)
+ *
+ * Revision 6.1  1999/10/29 17:51:55  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.2  1997/03/11  13:10:48  neelin
+ * Working version of dicomserver.
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <memory.h>
+#include <limits.h>
+#ifdef FLT_DIG
+#  undef FLT_DIG
+#endif
+#ifdef DBL_DIG
+#  undef DBL_DIG
+#endif
+#ifdef DBL_MIN
+#  undef DBL_MIN
+#endif
+#ifdef DBL_MAX
+#  undef DBL_MAX
+#endif
+#include <float.h>
+#include <minc_def.h>
+#include <time_stamp.h>
+#include <acr_nema.h>
+#include <dicom_element_defs.h>
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#define FILE_ALLOC_INCREMENT 10
+
+/* Connection timeout length in seconds */
+/* Changed to 10 min instead of 5 by Leili */
+#define CONNECTION_TIMEOUT (60*10)
+
+/* Time to sleep between image reads when a child process is running.
+   This prevents the server from outrunning its children. */
+
+#define SERVER_SLEEP_TIME 3
+
+/* Define logging constants */
+#define NO_LOGGING   0
+#define LOW_LOGGING  1
+#define HIGH_LOGGING 2
+
+/* added by rhoge for ACQ and MEAS loop handling */
+typedef enum { NONE = 0 , ACQ , MEAS } Loop_Type;
+
+/* supported file types */
+typedef enum { UNDEF, IMA, N3DCM, N4DCM } File_Type;
+
+/* File containing defaults for dicomserver */
+#define OUTPUT_DEFAULT_FILE_DIR "/usr/local/lib"
+#define OUTPUT_DEFAULT_FILE_PREFIX "dicomserver."
+
+/* System log file (set to NULL for no logging of error) */
+#define SYSTEM_LOG "/dev/log"
+
+/* Type for carrying around object information */
+typedef struct {
+  int file_index;
+  char *file_name;
+  double study_id; // yyyymmdd.hhmmss
+  int study_date;
+  int study_time;
+  int scanner_serialno;
+  int acq_id;
+  int rec_num;
+  int image_type;
+  int num_echoes;
+  int echo_number;
+  int num_dyn_scans;
+  int dyn_scan_number;
+  int global_image_number;
+  int num_slices_nominal;
+  int slice_number;
+  int acq_rows;
+  int acq_cols;
+  int rec_rows;
+  int rec_cols;
+  int num_mosaic_rows;
+  int num_mosaic_cols;
+  int num_slices_in_file;
+  char sequence_name[256];
+  char protocol_name[256];
+
+} Data_Object_Info;
+
+/* Define macro for array size */
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
+
+#include <siemens_dicom_to_minc.h>
+#include <dicom_prototypes.h>
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/ext_element_defs.h
@@ -0,0 +1,30 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : ext_element_defs.h
+@DESCRIPTION: Element definitions for extra elements needed for mosaics, etc.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : December 2001 (Rick Hoge)
+@MODIFIED   : 
+@COPYRIGHT  :
+              Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+/* Element id's for EXT */
+GLOBAL_ELEMENT(EXT_Mosaic_rows                        , 0x0023, 0x0001, LO);
+GLOBAL_ELEMENT(EXT_Mosaic_columns                     , 0x0023, 0x0002, LO);
+GLOBAL_ELEMENT(EXT_Slices_in_file                     , 0x0023, 0x0003, LO);
+GLOBAL_ELEMENT(EXT_Sub_image_rows                     , 0x0023, 0x0004, US);
+GLOBAL_ELEMENT(EXT_Sub_image_columns                  , 0x0023, 0x0005, US);
+GLOBAL_ELEMENT(EXT_MrProt_dump                        , 0x0023, 0x0006, LO);
+GLOBAL_ELEMENT(EXT_Diffusion_b_value                  , 0x0023, 0x0007, LO);
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/minc_file.c
@@ -0,0 +1,1025 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : minc_file.c
+@DESCRIPTION: Code to do minc file handling.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: minc_file.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.12  2002/04/29 15:24:53  rhoge
+ * removed (mode_t) cast in minc_file - would not build on SGI's
+ *
+ * Revision 1.11  2002/04/08 17:26:34  rhoge
+ * added additional sequence info to minc header
+ *
+ * Revision 1.10  2002/03/27 18:57:50  rhoge
+ * added diffusion b value
+ *
+ * Revision 1.9  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.8  2002/03/19 22:10:16  rhoge
+ * removed time sorting for N4DCM mosaics - time is random for mosaics
+ *
+ * Revision 1.7  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.6  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.5  2001/02/26 22:22:37  rhoge
+ * added scanner serial number to minc file naming
+ *
+ * Revision 1.4  2001/02/26 13:38:22  rhoge
+ * made `existing directory' warning conditional on logging
+ *
+ * Revision 1.3  2000/12/15 01:04:46  rhoge
+ * make sure acquisition_id (series no) is 6 digit hhmmss string for meas loop
+ *
+ * Revision 1.2  2000/12/14 21:19:22  rhoge
+ * added code to compute time spacing if measurement loop dynamic
+ * scanning has been detected
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:55  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+#include <ctype.h>
+extern int Do_logging;
+
+/* Global for minc history (sorry, but it was kludged in afterwards) */
+char *minc_history = NULL;
+int Anon;
+char IdStr[512];
+int UserIdStr;
+char Name[512];
+int UserName;
+
+/* Define mri dimension names */
+static char *mri_dim_names[] = {
+   NULL, "echo_time", MItime, "phase_number", "chemical_shift", NULL};
+
+/* Macros */
+#define STRLEN(s) ((int) strlen(s))
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : create_minc_file
+@INPUT      : minc_file - name of file to create. If NULL, a name is 
+                 generated internally.
+              clobber - if TRUE, any existing file will be overwritten.
+              general_info - information for creating the file.
+              file_prefix - string providing any directory or prefix 
+                 for internally generated filename (if it is a directory,
+                 then it must contain the last "/")
+@OUTPUT     : output_file_name - returns a pointer to an internal area
+                 containing the file name of the created file if minc_file
+                 is NULL, or simply a pointer to minc_file. If NULL, then
+                 nothing is returned.
+@RETURNS    : id of image conversion variable (MI_ERROR in case of error).
+@DESCRIPTION: Routine to create the minc file.
+@METHOD     : 
+@GLOBALS    : 
+CALLS       : 
+@CREATED    : November 26, 1993 (Peter Neelin)
+@MODIFIED   : rhoge - modified to create directory for session
+---------------------------------------------------------------------------- */
+public int create_minc_file(char *minc_file, int clobber, 
+                            General_Info *general_info,
+                            char *file_prefix, char **output_file_name,
+			    Loop_Type loop_type)
+{
+   static char temp_name[256];
+   char patient_name[256];
+   char patient_id[256];
+   char scanner_model[256];
+   char serial_no[256];
+   char reg_time[256];
+   char temp_str[256];
+   int ix;
+   char *filename;
+   int minc_clobber;
+   int mincid, icvid;
+   Mri_Index imri;
+   char scan_label[MRI_NDIMS][20];
+
+   /* added by rhoge for study directory, new naming conventions: */
+
+   char full_path[256];
+
+   /* Prefixes for creating file name */
+   static char *scan_prefix[MRI_NDIMS] = 
+      {"sl", "e", "d", "p", "cs"};
+
+   /* Turn off fatal errors */
+   ncopts = NCOPTS_DEFAULT;
+
+   /* Create the file name if needed */
+   if (minc_file != NULL) {
+      filename = minc_file;
+   }
+   else {
+      /* Get patient name */
+      /******************************************/
+      /* Changed by Leili from "string_to_initials" to "string_to_filename" */
+      /* based on people's request at MNI */ 
+      if (UserName) {
+	strcpy(patient_name,Name);
+      } else {
+	string_to_filename(general_info->patient.name, patient_name,
+			   sizeof(patient_name));
+      }
+
+      if (STRLEN(patient_name) == 0) {
+	(void) strcpy(patient_name, "no_name");
+      }
+      /*****************************************/
+      /* Commented out by Leili,based on the request of people at MNI*/
+      /* Get patient ID */
+      //if (UserIdStr) {
+      //	strcpy(patient_id,IdStr);
+      //} else {
+      //	string_to_initials(general_info->patient.identification, patient_id,
+      //			   sizeof(patient_id));
+      //}
+      //if (STRLEN(patient_id) == 0) {
+      //	(void) strcpy(patient_id, "no_id");
+      //}
+      /********************************************/
+      /* Commented out by Leili,based on the request of people at MNI*/
+      /* Get Scanner model */
+      //string_to_filename(general_info->study.model, 
+      //			 scanner_model,
+      //                   sizeof(scanner_model));
+      //if (STRLEN(scanner_model) == 0) {
+      //   (void) strcpy(scanner_model, "no_scanner");
+      //}
+
+      /* Get Scanner serial number */
+      //string_to_filename(general_info->study.serial_no, 
+      //			 serial_no,
+      //                   sizeof(serial_no));
+      //if (STRLEN(serial_no) == 0) {
+      //   (void) strcpy(serial_no, "no_serial_no");
+      //}
+
+      /* get rid of magnetom prefix, if present */
+
+      //if (!strncmp(scanner_model,"magnetom_",9)) {
+      //	for (ix=0; ix<strlen(scanner_model)+1; ix++) {
+      //	  scanner_model[ix]=scanner_model[ix+9];
+      //	}
+      //}
+      /******************************************/
+      /* Get Study Time */
+      string_to_filename(general_info->patient.reg_time, temp_str,
+			 sizeof(temp_str));
+      /* truncate to first 6 chars (hhmmss) */
+      strncpy(reg_time, temp_str, 6);
+      if (STRLEN(reg_time) == 0) {
+         (void) strcpy(reg_time, "no_time");
+      }
+      reg_time[6]='\0'; /* terminate with null (strncpy does not) */
+
+      /* Get strings for echo number, etc. */
+      for (imri=0; imri < MRI_NDIMS; imri++) {
+         if ((general_info->size[imri] < general_info->total_size[imri]) &&
+             (general_info->size[imri] == 1)) {
+            (void) sprintf(scan_label[imri], "%s%d", scan_prefix[imri],
+                           general_info->default_index[imri]);
+         }
+         else {
+            (void) strcpy(scan_label[imri], "");
+         }
+      }
+
+      /* rhoge:  add session directory to prefix */
+      
+      (void) strcpy(full_path,file_prefix);
+
+      /* Changed by leili, omitted the scanner info, changed - to _ , and get rid off the patients ID */
+      (void) sprintf(temp_name, "%s_%s_%s/",
+		     patient_name,
+		     //patient_id,
+		     //scanner_model,
+		     //serial_no,
+		     general_info->patient.reg_date,
+		     reg_time);
+      strcat(full_path,temp_name);
+
+
+      /* if measurement loop, make sure that acquisition_id is
+	 a 6 digit (hhmmss) string with leading zero if needed */
+
+      if (loop_type == MEAS) {
+
+	(void) sprintf(general_info->study.acquisition_id, "%06d",
+		       general_info->acq_id);
+
+      }
+
+      /* Create file name */
+      /* changed by leili, omitted the scanner info, changed - to _ */
+      (void) sprintf(temp_name, "%s%s_%s_%s_%s%s%s%s%s%s_mri.mnc", 
+                     full_path,
+                     patient_name,
+                     //patient_id,
+                     //scanner_model,
+		     //serial_no,
+                     general_info->patient.reg_date,
+                     reg_time,
+                     general_info->study.acquisition_id,
+                     scan_label[SLICE],
+                     scan_label[ECHO],
+                     scan_label[TIME],
+                     scan_label[PHASE],
+                     scan_label[CHEM_SHIFT]);
+      filename = temp_name;
+
+      if (Do_logging > HIGH_LOGGING) { /* rhoge */
+	fprintf(stderr,"\nminc file name:  %s\n",filename);
+	fprintf(stderr,"\nfile prefix:     %s\n",full_path);
+	fprintf(stderr,"\npatient_name:    %s\n",patient_name);
+	fprintf(stderr,"\nstudy_id:        %s\n",
+		general_info->study.study_id);
+	fprintf(stderr,"\nacquisition_id:  %s\n",
+		general_info->study.acquisition_id);
+
+	fprintf(stderr,"\nRegistration date:  %s\n",
+		general_info->patient.reg_date);
+	fprintf(stderr,"\nRegistration time:  %s\n",
+		general_info->patient.reg_time);
+      }
+   }
+
+   /* create the session directory if none exists */
+
+   if (mkdir(full_path, 0777) &&
+       (Do_logging > HIGH_LOGGING)) {
+     (void) fprintf(stderr, "Directory %s exists...\n",full_path);
+   }
+
+   /* Set output file name */
+   if (output_file_name != NULL)
+      *output_file_name = filename;
+
+   /* Set the clobber value */
+   if (clobber) minc_clobber = NC_CLOBBER;
+   else minc_clobber = NC_NOCLOBBER;
+
+   /* Create the file */
+   mincid = micreate(filename, minc_clobber);
+   if (mincid == MI_ERROR) return MI_ERROR;
+
+   /* Set up variables */
+   setup_minc_variables(mincid, general_info,loop_type);
+
+   /* Put the file in data mode */
+   (void) ncsetfill(mincid, NC_NOFILL);
+   if (ncendef(mincid) == MI_ERROR) {
+      return MI_ERROR;
+   }
+
+   /* Create the icv */
+   icvid = miicv_create();
+
+   /* Set the type and range */
+   (void) miicv_setint(icvid, MI_ICV_TYPE, NC_SHORT);
+   if (general_info->is_signed)
+      (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_SIGNED);
+   else
+      (void) miicv_setstr(icvid, MI_ICV_SIGN, MI_UNSIGNED);
+   (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, general_info->pixel_min);
+   (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, general_info->pixel_max);
+
+   /* Attach the icv */
+   (void) miicv_attach(icvid, mincid, ncvarid(mincid, MIimage));
+
+   return icvid;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : setup_minc_variables
+@INPUT      : mincid
+              general_info
+@OUTPUT     : general_info
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to setup minc variables.
+@METHOD     : 
+@GLOBALS    : 
+CALLS       : 
+@CREATED    : November 26, 1993 (Peter Neelin)
+@MODIFIED   :
+---------------------------------------------------------------------------- */
+public void setup_minc_variables(int mincid, General_Info *general_info,
+				 Loop_Type loop_type)
+{
+   Mri_Index imri;
+   Volume_Index ivol;
+   World_Index iworld;
+   int ndims;
+   int dim[MAX_VAR_DIMS];
+   long dimsize;
+   char *dimname;
+   int varid, imgid, dicomvar;
+   double valid_range[2];
+   char name[MAX_NC_NAME];
+   int index;
+   int regular;
+   double separation, diff;
+   Acr_Group cur_group;
+   Acr_Element cur_element;
+   int length;
+   char *data;
+   nc_type datatype;
+   int is_char;
+   int ich;
+
+   /* stuff added by rhoge */
+   double sum;
+   double avg;
+
+   /* Define the spatial dimension names */
+   static char *spatial_dimnames[WORLD_NDIMS] = {MIxspace, MIyspace, MIzspace};
+
+   /* Create the dimensions from slowest to fastest */
+
+   ndims=0;
+   /* Create the non-spatial dimensions (from slowest to fastest) */
+   for (imri=MRI_NDIMS-1; (int) imri > SLICE; imri--) {
+
+     /* for the TIME dimension, check if we have acquisition-loop
+	dynamic scan OR a `corrected' dynamic scan */
+
+     if ( (imri==TIME) &&
+	  ((loop_type!=NONE) || (general_info->acq.num_dyn_scans>1)) ) { 
+
+       /* for Siemens scans using the signal averaging loop for
+	  multiple time points we use the TR as the time step */
+
+       dimsize = general_info->size[TIME];
+       if (general_info->size[TIME] > 1) {
+         dimname = mri_dim_names[TIME];
+         dim[ndims] = ncdimdef(mincid, dimname, dimsize);
+
+	 varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 1, 
+					 &dim[ndims]);
+	 (void) miattputstr(mincid, varid, MIspacing, MI_REGULAR);
+	 (void) miattputstr(mincid, varid, MIunits, "s");
+	 if (loop_type == MEAS) {
+	   /* if Meas loop, time step is not equal to TR, and
+	      frames should have time values (rhoge) */
+	   sum = 0.0;
+	   for (index=1; index < general_info->size[TIME]; index++) {
+	     
+	     sum += general_info->coordinates[TIME][1]-
+	       general_info->coordinates[TIME][0];
+
+	   }
+	   /* compute mean */
+	   avg = sum/general_info->size[TIME];
+	   (void) miattputdbl(mincid, varid, MIstep,avg);
+
+	   /* check for uniformity of spacing */
+	   regular = TRUE;
+	   for (index=1; index < general_info->size[TIME]; index++) {
+	     diff = general_info->coordinates[TIME][1]-
+	       general_info->coordinates[TIME][0] - avg;
+	     
+	     if (diff < 0.0) diff = -diff;
+	     if (separation != 0.0) diff /= avg;
+	     if (diff > COORDINATE_EPSILON) {
+               regular = FALSE;
+               break;
+	     }
+	   }
+	   if (regular)
+	     (void) miattputstr(mincid, varid, MIspacing, MI_REGULAR);
+	   else 
+	     (void) miattputstr(mincid, varid, MIspacing, MI_IRREGULAR);
+	 } else {
+
+	   /* assume ACQ loop and use TR for time step */
+	   (void) miattputdbl(mincid, varid, MIstep,
+			      general_info->acq.rep_time);
+	 }
+	 (void) miattputdbl(mincid, varid, MIstart,0);
+
+         general_info->image_index[TIME] = ndims;
+         ndims++;
+       }
+
+     } else { /* NORMAL CODE */
+
+       dimsize = general_info->size[imri];
+       if (general_info->size[imri] > 1) {
+         dimname = mri_dim_names[imri];
+         dim[ndims] = ncdimdef(mincid, dimname, dimsize);
+         if (imri == TIME) {
+	   varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 1, 
+					 &dim[ndims]);
+	   (void) miattputstr(mincid, varid, MIunits, "s");
+         }
+         else if (imri == ECHO) {
+	   varid = ncvardef(mincid, dimname, NC_DOUBLE, 1, &dim[ndims]);
+	   (void) miattputstr(mincid, varid, MIvartype, MI_DIMENSION);
+	   (void) miattputstr(mincid, varid, MIspacing, MI_IRREGULAR);
+	   (void) miattputstr(mincid, varid, MIunits, "s");
+         }
+         general_info->image_index[imri] = ndims;
+         ndims++;
+       }
+     }
+   }
+
+   /* Next the spatial dimensions */
+   for (ivol=0; ivol < VOL_NDIMS; ivol++) {
+      switch (ivol) {
+      case VSLICE: 
+         dimsize = general_info->size[SLICE];
+         iworld = general_info->slice_world;
+         break;
+      case VROW: 
+         dimsize = general_info->nrows;
+         iworld = general_info->row_world;
+         break;
+      case VCOLUMN: 
+         dimsize = general_info->ncolumns;
+         iworld = general_info->column_world;
+         break;
+      }
+      dimname = spatial_dimnames[iworld];
+      dim[ndims] = ncdimdef(mincid, dimname, dimsize);
+      if (ivol == VSLICE) {
+         varid = micreate_std_variable(mincid, dimname, NC_DOUBLE, 
+                                       1, &dim[ndims]);
+         /* Check for regular slices */
+         regular = TRUE;
+         separation = general_info->step[general_info->slice_world];
+         for (index=1; index < general_info->size[SLICE]; index++) {
+            diff = general_info->coordinates[SLICE][index] -
+               general_info->coordinates[SLICE][index-1] - separation;
+            if (diff < 0.0) diff = -diff;
+            if (separation != 0.0) diff /= separation;
+            if (diff > COORDINATE_EPSILON) {
+               regular = FALSE;
+               break;
+            }
+         }
+         if (regular)
+            (void) miattputstr(mincid, varid, MIspacing, MI_REGULAR);
+      }
+      else
+         varid = micreate_std_variable(mincid, dimname, NC_LONG, 0, NULL);
+      (void) miattputdbl(mincid, varid, MIstep, 
+                         general_info->step[iworld]);
+      (void) miattputdbl(mincid, varid, MIstart, 
+                         general_info->start[iworld]);
+      (void) miattputstr(mincid, varid, MIspacetype, MI_NATIVE);
+      (void) ncattput(mincid, varid, MIdirection_cosines, 
+                      NC_DOUBLE, WORLD_NDIMS,
+                      general_info->dircos[iworld]);
+      if (ivol == VSLICE) {
+         general_info->image_index[SLICE] = ndims;
+      }
+      ndims++;
+   }
+
+   /* Set up image variable */
+   imgid = micreate_std_variable(mincid, MIimage, general_info->datatype,
+                                 ndims, dim);
+   if (general_info->is_signed)
+      (void) miattputstr(mincid, imgid, MIsigntype, MI_SIGNED);
+   else
+      (void) miattputstr(mincid, imgid, MIsigntype, MI_UNSIGNED);
+   valid_range[0] = general_info->pixel_min;
+   valid_range[1] = general_info->pixel_max;
+   (void) ncattput(mincid, imgid, MIvalid_range, NC_DOUBLE, 2, valid_range);
+   (void) miattputstr(mincid, imgid, MIcomplete, MI_FALSE);
+
+   /* Create image max and min variables */
+   varid = micreate_std_variable(mincid, MIimagemin, NC_DOUBLE, ndims-2, dim);
+   if (STRLEN(general_info->units) > 0)
+      (void) miattputstr(mincid, varid, MIunits, general_info->units);
+   varid = micreate_std_variable(mincid, MIimagemax, NC_DOUBLE, ndims-2, dim);
+   if (STRLEN(general_info->units) > 0)
+      (void) miattputstr(mincid, varid, MIunits, general_info->units);
+
+   /* Create the patient variable */
+   varid = micreate_group_variable(mincid, MIpatient);
+   if (STRLEN(general_info->patient.name) > 0)
+     if (Anon) {
+       (void) miattputstr(mincid, varid, MIfull_name, 
+			  "anonymous");
+     } else {
+       (void) miattputstr(mincid, varid, MIfull_name, 
+			  general_info->patient.name);
+     }
+   if (STRLEN(general_info->patient.identification) > 0)
+      (void) miattputstr(mincid, varid, MIidentification, 
+                         general_info->patient.identification);
+   if (STRLEN(general_info->patient.birth_date) > 0)
+      (void) miattputstr(mincid, varid, MIbirthdate, 
+                         general_info->patient.birth_date);
+   if (STRLEN(general_info->patient.age) > 0)
+      (void) miattputstr(mincid, varid, "age", 
+                         general_info->patient.age);
+   if (STRLEN(general_info->patient.sex) > 0)
+      (void) miattputstr(mincid, varid, MIsex, 
+                         general_info->patient.sex);
+   if (general_info->patient.weight != -DBL_MAX) 
+      (void) miattputdbl(mincid, varid, MIweight, 
+                         general_info->patient.weight);
+
+   /* Create the study variable */
+   varid = micreate_group_variable(mincid, MIstudy);
+
+   /* rhoge: fixed date/time to reflect study */
+   if (STRLEN(general_info->patient.reg_date) > 0)
+      (void) miattputstr(mincid, varid, "start_date", 
+                         general_info->patient.reg_date);
+   if (STRLEN(general_info->patient.reg_time) > 0)
+      (void) miattputstr(mincid, varid, "start_time", 
+                         general_info->patient.reg_time);
+   if (STRLEN(general_info->study.modality) > 0)
+      (void) miattputstr(mincid, varid, MImodality, 
+                         general_info->study.modality);
+   if (STRLEN(general_info->study.manufacturer) > 0)
+      (void) miattputstr(mincid, varid, "manufacturer", 
+                         general_info->study.manufacturer);
+   if (STRLEN(general_info->study.model) > 0)
+      (void) miattputstr(mincid, varid, "model", 
+                         general_info->study.model);
+   if (general_info->study.field_value != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "field_value", 
+                         general_info->study.field_value);
+   if (STRLEN(general_info->study.software_version) > 0)
+      (void) miattputstr(mincid, varid, "software_version", 
+                         general_info->study.software_version);
+   if (STRLEN(general_info->study.serial_no) > 0)
+      (void) miattputstr(mincid, varid, "serial_no", 
+                         general_info->study.serial_no);
+   if (STRLEN(general_info->study.calibration_date) > 0)
+      (void) miattputstr(mincid, varid, "calibration_date", 
+                         general_info->study.calibration_date);
+   if (STRLEN(general_info->study.institution) > 0)
+      (void) miattputstr(mincid, varid, MIinstitution, 
+                         general_info->study.institution);
+   if (STRLEN(general_info->study.station_id) > 0)
+      (void) miattputstr(mincid, varid, MIstation_id, 
+                         general_info->study.station_id);
+   if (STRLEN(general_info->study.referring_physician) > 0)
+      (void) miattputstr(mincid, varid, MIreferring_physician, 
+                         general_info->study.referring_physician);
+
+   if (STRLEN(general_info->study.performing_physician) > 0)
+      (void) miattputstr(mincid, varid, "performing_physician", 
+                         general_info->study.referring_physician);
+   if (STRLEN(general_info->study.operator) > 0)
+      (void) miattputstr(mincid, varid, "operator", 
+                         general_info->study.operator);
+
+   if (STRLEN(general_info->study.procedure) > 0)
+      (void) miattputstr(mincid, varid, MIprocedure, 
+                         general_info->study.procedure);
+   if (STRLEN(general_info->study.study_id) > 0)
+      (void) miattputstr(mincid, varid, MIstudy_id, 
+                         general_info->study.study_id);
+
+   /* Create acquisition variable */
+   varid = micreate_group_variable(mincid, MIacquisition);
+   if (STRLEN(general_info->study.acquisition_id) > 0)
+      (void) miattputstr(mincid, varid, "acquisition_id", 
+                         general_info->study.acquisition_id);
+   if (STRLEN(general_info->study.start_time) > 0)
+      (void) miattputstr(mincid, varid, MIstart_time, 
+                         general_info->study.start_time);
+
+   if (STRLEN(general_info->acq.scan_seq) > 0)
+      (void) miattputstr(mincid, varid, MIscanning_sequence, 
+                         general_info->acq.scan_seq);
+
+   if (STRLEN(general_info->acq.seq_owner) > 0)
+      (void) miattputstr(mincid, varid, "seq_owner", 
+                         general_info->acq.seq_owner);
+
+   if (STRLEN(general_info->acq.seq_descr) > 0)
+      (void) miattputstr(mincid, varid, "seq_description", 
+                         general_info->acq.seq_descr);
+
+
+   if (STRLEN(general_info->acq.protocol_name) > 0)
+      (void) miattputstr(mincid, varid, "protocol_name", 
+                         general_info->acq.protocol_name);
+   if (STRLEN(general_info->acq.receive_coil) > 0)
+      (void) miattputstr(mincid, varid, "receive_coil", 
+                         general_info->acq.receive_coil);
+   if (STRLEN(general_info->acq.transmit_coil) > 0)
+      (void) miattputstr(mincid, varid, "transmit_coil", 
+                         general_info->acq.transmit_coil);
+
+   if (general_info->acq.rep_time != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, MIrepetition_time, 
+                         general_info->acq.rep_time);
+   if ((general_info->acq.echo_time != -DBL_MAX) &&
+       (general_info->size[ECHO] <= 1))
+      (void) miattputdbl(mincid, varid, MIecho_time, 
+                         general_info->acq.echo_time);
+   if (general_info->acq.echo_number != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "echo_number", 
+                         general_info->acq.echo_number);
+   if (general_info->acq.inv_time != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, MIinversion_time, 
+                         general_info->acq.inv_time);
+   if (general_info->acq.flip_angle != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "flip_angle", 
+                         general_info->acq.flip_angle);
+   if (general_info->acq.slice_thickness != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "slice_thickness", 
+                         general_info->acq.slice_thickness);
+   if (general_info->acq.num_slices != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "num_slices", 
+                         general_info->acq.num_slices);
+   if (general_info->acq.b_value != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "b_value", 
+                         general_info->acq.b_value);
+
+   /* add number of dynamic scans (rhoge) */
+   /* this will be relevant if we are receiving siemens scans that
+      have been `cleaned up' (and hence have the correct number of
+      dynamic scans inserted) */
+
+   if (general_info->acq.num_dyn_scans != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "num_dyn_scans", 
+                         general_info->acq.num_dyn_scans);
+
+   if (general_info->acq.num_avg != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, MInum_averages, 
+                         general_info->acq.num_avg);
+
+   if (general_info->acq.scan_dur != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "scan_duration", 
+                         general_info->acq.scan_dur);
+
+   if (general_info->acq.ky_lines != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "ky_lines", 
+                         general_info->acq.ky_lines);
+
+   if (general_info->acq.kymax_ix != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "kymax_ix", 
+                         general_info->acq.kymax_ix);
+
+   if (general_info->acq.kymin_ix != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "kymin_ix", 
+                         general_info->acq.kymin_ix);
+
+   if (general_info->acq.kz_lines != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "kz_lines", 
+                         general_info->acq.kz_lines);
+
+   if (general_info->acq.dummy_scans != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "dummy_excitations", 
+                         general_info->acq.dummy_scans);
+   if (general_info->acq.imaging_freq != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, MIimaging_frequency, 
+                         general_info->acq.imaging_freq);
+   if (STRLEN(general_info->acq.imaged_nucl) > 0)
+      (void) miattputstr(mincid, varid, MIimaged_nucleus, 
+                         general_info->acq.imaged_nucl);
+
+   if (general_info->acq.adc_voltage != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "adc_voltage", 
+                         general_info->acq.adc_voltage);
+
+   if (general_info->acq.adc_offset != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "adc_offset", 
+                         general_info->acq.adc_offset);
+
+   if (general_info->acq.transmit_ampl != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "transmit_ampl", 
+                         general_info->acq.transmit_ampl);
+
+   if (general_info->acq.rec_amp_gain != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "rec_amp_gain", 
+                         general_info->acq.rec_amp_gain);
+
+   if (general_info->acq.rec_preamp_gain != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "rec_preamp_gain", 
+                         general_info->acq.rec_preamp_gain);
+
+   if (general_info->acq.win_center != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "window_center", 
+                         general_info->acq.win_center);
+
+   if (general_info->acq.win_width != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "window_width", 
+                         general_info->acq.win_width);
+
+   if (general_info->acq.gy_ampl != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "gy_ampl", 
+                         general_info->acq.gy_ampl);
+
+   if (general_info->acq.gx_ampl != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "gx_ampl", 
+                         general_info->acq.gx_ampl);
+
+   if (general_info->acq.gz_ampl != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "gz_ampl", 
+                         general_info->acq.gz_ampl);
+
+   if (general_info->acq.num_phase_enc_steps != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "num_phase_enc_steps", 
+                         general_info->acq.num_phase_enc_steps);
+   if (general_info->acq.percent_sampling != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "percent_sampling", 
+                         general_info->acq.percent_sampling);
+   if (general_info->acq.percent_phase_fov != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "percent_phase_fov", 
+                         general_info->acq.percent_phase_fov);
+   if (general_info->acq.pixel_bandwidth != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "pixel_bandwidth", 
+                         general_info->acq.pixel_bandwidth);
+   if (STRLEN(general_info->acq.phase_enc_dir) > 0)
+      (void) miattputstr(mincid, varid, "phase_enc_dir", 
+                         general_info->acq.phase_enc_dir);
+   if (general_info->acq.sar != -DBL_MAX)
+      (void) miattputdbl(mincid, varid, "SAR", 
+                         general_info->acq.sar);
+   if (STRLEN(general_info->acq.mr_acq_type) > 0)
+      (void) miattputstr(mincid, varid, "mr_acq_type", 
+                         general_info->acq.mr_acq_type);
+   if (STRLEN(general_info->acq.image_type) > 0)
+      (void) miattputstr(mincid, varid, "image_type", 
+                         general_info->acq.image_type);
+
+   if (STRLEN(general_info->acq.comments) > 0)
+      (void) miattputstr(mincid, varid, MIcomments, 
+                         general_info->acq.comments);
+
+   // this is Siemens Numaris 4 specific!
+   if (STRLEN(general_info->acq.MrProt) > 0)
+      (void) miattputstr(mincid, varid, "MrProt_dump", 
+                         general_info->acq.MrProt);
+
+   /* Create the dicom info variable */
+   varid = ncvardef(mincid, "dicominfo", NC_LONG, 0, NULL);
+   (void) miattputstr(mincid, varid, MIvartype, MI_GROUP);
+   (void) miattputstr(mincid, varid, MIvarid, 
+                      "MNI DICOM information variable");
+   (void) miadd_child(mincid, ncvarid(mincid, MIrootvariable), varid);
+   if (STRLEN(general_info->image_type_string) > 0)
+      (void) miattputstr(mincid, varid, "image_type", 
+                         general_info->image_type_string);
+   (void) miattputdbl(mincid, varid, "window_min", general_info->window_min);
+   (void) miattputdbl(mincid, varid, "window_max", general_info->window_max);
+
+   /* Put group info in header */
+   cur_group = general_info->group_list;
+   dicomvar = ncvardef(mincid, DICOM_ROOT_VAR, NC_LONG, 0, NULL);
+   (void) miattputstr(mincid, dicomvar, MIvartype, MI_GROUP);
+   (void) miattputstr(mincid, dicomvar, MIvarid, "MNI DICOM variable");
+   (void) miadd_child(mincid, ncvarid(mincid, MIrootvariable), dicomvar);
+   while (cur_group != NULL) {
+
+      /* Create variable for group */
+      (void) sprintf(name, "dicom_0x%04x", acr_get_group_group(cur_group));
+      varid = ncvardef(mincid, name, NC_LONG, 0, NULL);
+      (void) miattputstr(mincid, varid, MIvartype, MI_GROUP);
+      (void) miattputstr(mincid, varid, MIvarid, "MNI DICOM variable");
+      (void) miadd_child(mincid, dicomvar, varid);
+
+      /* Loop through elements of group */
+      cur_element = acr_get_group_element_list(cur_group);
+      while (cur_element != NULL) {
+         (void) sprintf(name, "el_0x%04x", 
+                        acr_get_element_element(cur_element));
+         is_char = TRUE;
+         length = acr_get_element_length(cur_element);
+         data = acr_get_element_data(cur_element);
+         for (ich=0; ich < length; ich++) {
+            if (!isprint((int) data[ich])) {
+               is_char = FALSE;
+               break;
+            }
+         }
+         if (is_char)
+            datatype = NC_CHAR;
+         else
+            datatype = NC_BYTE;
+         ncattput(mincid, varid, name, datatype, length, data);
+         
+         cur_element = acr_get_element_next(cur_element);
+      }
+      cur_group = acr_get_group_next(cur_group);
+   }
+
+   /* Create the history attribute */
+   if (minc_history != NULL) {
+      (void) miattputstr(mincid, NC_GLOBAL, MIhistory, minc_history);
+   }
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : save_minc_image
+@INPUT      : icvid
+              general_info
+              file_info
+              image
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to save the image in the minc file
+@METHOD     : 
+@GLOBALS    : 
+CALLS       : 
+@CREATED    : November 26, 1993 (Peter Neelin)
+@MODIFIED   :
+---------------------------------------------------------------------------- */
+public void save_minc_image(int icvid, General_Info *general_info, 
+                            File_Info *file_info, Image_Data *image)
+{
+   int mincid, imgid;
+   long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS];
+   int file_index, array_index;
+   int idim;
+   Mri_Index imri;
+   char *dimname;
+   unsigned short pvalue, pmax, pmin;
+   double dvalue, maximum, minimum, scale, offset;
+   long ipix, imagepix;
+
+   /* Get the minc file id */
+   (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid);
+   (void) miicv_inqint(icvid, MI_ICV_VARID, &imgid);
+
+   /* Create start and count variables */
+   idim = 0;
+   for (imri=MRI_NDIMS-1; (int) imri >= 0; imri--) {
+      if (general_info->image_index[imri] >= 0) {
+         file_index = general_info->image_index[imri];
+         if (general_info->size[imri] > 1) {
+            array_index = search_list(file_info->index[imri], 
+                                      general_info->indices[imri],
+                                      general_info->size[imri],
+                                      general_info->search_start[imri]);
+            if (array_index < 0) array_index = 0;
+            general_info->search_start[imri] = array_index;
+         }
+         else {
+            array_index = 0;
+         }
+         start[file_index] = array_index;
+         count[file_index] = 1;
+         idim++;
+      }
+   }
+   start[idim] = 0;
+   start[idim+1] = 0;
+   count[idim] = general_info->nrows;
+   count[idim+1] = general_info->ncolumns;
+
+   /* Write out slice position */
+   switch (general_info->slice_world) {
+   case XCOORD: dimname = MIxspace; break;
+   case YCOORD: dimname = MIyspace; break;
+   case ZCOORD: dimname = MIzspace; break;
+   default: dimname = MIzspace;
+   }
+   (void) mivarput1(mincid, ncvarid(mincid, dimname), 
+                    &start[general_info->image_index[SLICE]], 
+                    NC_DOUBLE, NULL, &file_info->coordinate[SLICE]);
+
+   /* Write out time of slice, if needed */
+   if (general_info->size[TIME] > 1) {
+      (void) mivarput1(mincid, ncvarid(mincid, mri_dim_names[TIME]), 
+                       &start[general_info->image_index[TIME]], 
+                       NC_DOUBLE, NULL, &file_info->coordinate[TIME]);
+   }
+
+   /* Write out echo time of slice, if needed */
+   if (general_info->size[ECHO] > 1) {
+      (void) mivarput1(mincid, ncvarid(mincid, mri_dim_names[ECHO]), 
+                       &start[general_info->image_index[ECHO]], 
+                       NC_DOUBLE, NULL, &file_info->coordinate[ECHO]);
+   }
+
+   /* Search image for max and min */
+   imagepix = general_info->nrows * general_info->ncolumns;
+   pmax = 0;
+   pmin = USHRT_MAX;
+   for (ipix=0; ipix < imagepix; ipix++) {
+      pvalue = image->data[ipix];
+      if (pvalue > pmax) pmax = pvalue;
+      if (pvalue < pmin) pmin = pvalue;
+   }
+
+   /* Re-scale the images */
+   if (pmax > pmin)
+      scale = (general_info->pixel_max - general_info->pixel_min) /
+         ((double) pmax - (double) pmin);
+   else
+      scale = 0.0;
+
+   offset = general_info->pixel_min - scale * (double) pmin;
+   for (ipix=0; ipix < imagepix; ipix++) {
+     dvalue = image->data[ipix];
+     image->data[ipix] = dvalue * scale + offset;
+   }
+
+   /* Calculate new intensity max and min */
+   if (general_info->pixel_max > general_info->pixel_min)
+      scale = (file_info->slice_max - file_info->slice_min) /
+         (general_info->pixel_max - general_info->pixel_min);
+   else
+      scale = 0.0;
+
+   // debugging info for slice intensity scaling
+   //   printf("general_info->pixel_max = %10.2f    file_info->slice_max = %10.2f    pmax = %u\n",general_info->pixel_max,file_info->slice_max,pmax);
+
+   offset = file_info->slice_min - scale * general_info->pixel_min;
+   minimum = (double) pmin * scale + offset;
+   maximum = (double) pmax * scale + offset;
+
+   /* Write out the max and min values */
+   (void) mivarput1(mincid, ncvarid(mincid, MIimagemin), start, NC_DOUBLE,
+                    NULL, &minimum);
+   (void) mivarput1(mincid, ncvarid(mincid, MIimagemax), start, NC_DOUBLE,
+                    NULL, &maximum);
+
+   /* Write out the image */
+   (void) miicv_put(icvid, start, count, image->data);
+
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : close_minc_file
+@INPUT      : icvid - value returned by create_minc_file
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to close the minc file.
+@METHOD     : 
+@GLOBALS    : 
+CALLS       : 
+@CREATED    : November 30, 1993 (Peter Neelin)
+@MODIFIED   :
+---------------------------------------------------------------------------- */
+public void close_minc_file(int icvid)
+{
+   int mincid;
+
+   /* Get the minc file id */
+   (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid);
+
+   /* Write out the complete attribute */
+   (void) miattputstr(mincid, ncvarid(mincid, MIimage), MIcomplete, MI_TRUE);
+
+   /* Close the file */
+   (void) miclose(mincid);
+
+   (void) miicv_free(icvid);
+
+   return;
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/modify_group_list.c
@@ -0,0 +1,157 @@
+public void multi_image_modify_group_list(Acr_Group group_list, Acr_Element *big_image,Acr_Element *small_image,int iimage)
+{
+   int irow, ibyte, idim, nbyte;
+   int isub, jsub;
+   char *new, *old;
+   long old_offset, new_offset;
+   double position[3], distance;
+   double old_position[3], old_step[3], normal[3];
+   char string[256];
+
+   int slices_in_file;
+   int num_mosaic_rows;
+   int num_mosaic_cols;
+   int pixel_size;
+   long new_image_size;
+   Acr_Element element;
+   int big_cols, big_rows;
+   int small_cols, small_rows;
+   void *data;
+   double RowColVec[6];
+   double dircos[VOL_NDIMS][WORLD_NDIMS];
+
+   // get info about file:
+
+   slices_in_file=acr_find_int(group_list, EXT_Slices_in_file, 999);
+   num_mosaic_rows=acr_find_int(group_list,EXT_Mosaic_rows, 999);
+   num_mosaic_cols = acr_find_int(group_list,EXT_Mosaic_columns,999);
+
+   // Check the image number
+   if ((iimage < 0) || (iimage > slices_in_file)) {
+      (void) fprintf(stderr, "Invalid image number to send: %d of %d\n",iimage, slices_in_file);
+      exit(EXIT_FAILURE);
+   }
+
+   // Figure out the sub-image indices
+   isub = iimage % num_mosaic_rows;
+   jsub = iimage / num_mosaic_cols;
+
+   // Get pointers:
+   
+   old = acr_get_element_data(*big_image);
+   new = acr_get_element_data(*small_image);
+
+   /* Copy the image */
+   nbyte = small_cols * pixel_size;
+   for (irow=0; irow < small_rows; irow++) {
+      old_offset = isub * small_cols +(jsub * small_rows + irow) * big_rows;
+      old_offset *= pixel_size;
+      new_offset = (irow * small_cols) * pixel_size;
+      for (ibyte=0; ibyte < nbyte; ibyte++) {
+         new[new_offset + ibyte] = old[old_offset + ibyte];
+      }
+   }
+
+   /* Reset the byte order and VR encoding. This will be modified on each
+      send according to what the connection needs. */
+   acr_set_element_byte_order(*small_image,acr_get_element_byte_order(*big_image));
+   acr_set_element_vr_encoding(*small_image,acr_get_element_vr_encoding(*big_image));
+
+   // Update the slice index
+   acr_insert_numeric(&group_list, SPI_Current_slice_number,(double) (iimage + 1));
+
+   if (file_type == N3DCM || file_type == IMA) {
+     // get the image normals
+     element = acr_find_group_element(group_list, SPI_Image_normal);
+     acr_get_element_numeric_array(element, 3, normal);
+
+     // get the old image position
+     element = acr_find_group_element(group_list, SPI_Image_position);
+     acr_get_element_numeric_array(element, 3, old_position);
+
+   } else {
+     element = acr_find_group_element(group_list,ACR_Image_orientation_patient);
+     acr_get_element_numeric_array(element, 6, RowColVec);
+
+     memcpy(dircos[VCOLUMN],RowColVec,sizeof(RowColVec[0])*3);
+     memcpy(dircos[VROW],&RowColVec[3],sizeof(RowColVec[0])*3);
+
+     convert_dicom_coordinate(dircos[VROW]);
+     convert_dicom_coordinate(dircos[VCOLUMN]);
+
+     //     dircos[VSLICE][0] = 
+     normal[0] = dircos[VCOLUMN][1] * dircos[VROW][2] - dircos[VCOLUMN][2] * dircos[VROW][1];
+
+     //     dircos[VSLICE][1] = 
+     normal[1] = dircos[VCOLUMN][2] * dircos[VROW][0] - dircos[VCOLUMN][0] * dircos[VROW][2];
+
+     //     dircos[VSLICE][2] = 
+     normal[2] = dircos[VCOLUMN][0] * dircos[VROW][1] - dircos[VCOLUMN][1] * dircos[VROW][0];
+
+     element = acr_find_group_element(group_list, ACR_Image_position_patient);
+     acr_get_element_numeric_array(element, WORLD_NDIMS, old_position);
+     convert_dicom_coordinate(old_position);
+
+   }
+
+   printf("here1\n");
+
+   /* Update the position */
+   distance = 0.0;
+   for (idim=0; idim < 3; idim++) {
+      position[idim] = old_position[idim] + (double) iimage * old_step[idim];
+      distance += position[idim] * normal[idim];
+   }
+
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g",position[0], position[1], position[2]);
+   acr_insert_string(&group_list, SPI_Image_position, string);
+   
+   // call function to fix DICOM header to match Siemens header
+   update_coordinate_info(group_list);
+
+}
+
+public int multi_image_init(Acr_Group group_list, Acr_Element *big_image, Acr_Element *small_image)
+
+{
+  int big_cols, big_rows;
+  int small_cols, small_rows;
+  int num_mosaic_rows;
+  int num_mosaic_cols;
+  int pixel_size;
+  long new_image_size;
+  void *data;
+  int group_id, element_id;
+
+  // Steal the image element from the group list
+  *big_image = acr_find_group_element(group_list, ACR_Image);
+  
+  group_id = acr_get_element_group(*big_image);
+  element_id = acr_get_element_element(*big_image);
+  acr_group_steal_element(acr_find_group(group_list, group_id),*big_image);
+  
+  // Add a small image, if needed
+  
+  big_cols = acr_find_int(group_list, ACR_Columns, 1) * num_mosaic_cols;
+  big_rows = acr_find_int(group_list, ACR_Rows, 1) * num_mosaic_rows;
+  
+  small_cols = acr_find_int(group_list, ACR_Columns, 1);
+  small_rows = acr_find_int(group_list, ACR_Rows, 1);
+  
+  pixel_size = 
+    (acr_find_int(group_list, ACR_Bits_allocated, 16)-1) / 8 + 1;
+  
+  new_image_size = acr_find_int(group_list, ACR_Columns, 1) * acr_find_int(group_list, ACR_Rows, 1) * pixel_size;
+  
+  data = malloc((size_t) new_image_size);
+  
+  *small_image = acr_create_element(group_id, element_id,acr_get_element_vr(*big_image),new_image_size, data);
+  
+  acr_set_element_vr(*small_image,acr_get_element_vr(*big_image));
+  acr_set_element_byte_order(*small_image,acr_get_element_byte_order(*big_image));
+  acr_set_element_vr_encoding(*small_image,acr_get_element_vr_encoding(*big_image));
+  acr_insert_element_into_group_list(&group_list, *small_image);
+
+  return 0;  
+}
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/open_connection.c
@@ -0,0 +1,206 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : open_connection.c
+@DESCRIPTION: File containing routines to open a decnet connection.
+@GLOBALS    : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: open_connection.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:56  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+ * Revision 3.0  1995/05/15  19:31:44  neelin
+ * Release of minc version 0.3
+ *
+ * Revision 2.5  1995/02/14  18:12:26  neelin
+ * Added project names and defaults files (using volume name).
+ * Added process id to log file name.
+ * Moved temporary files to subdirectory.
+ *
+ * Revision 2.4  1995/02/09  13:51:26  neelin
+ * Mods for irix 5 lint.
+ *
+ * Revision 2.3  1995/02/08  19:31:47  neelin
+ * Moved ARGSUSED statements for irix 5 lint.
+ *
+ * Revision 2.2  1994/12/07  09:45:59  neelin
+ * Fixed called to ioctl to get rid of type mismatch warning messages.
+ *
+ * Revision 2.1  94/12/07  08:20:10  neelin
+ * Added support for irix 5 decnet.
+ * 
+ * Revision 2.0  94/09/28  10:35:32  neelin
+ * Release of minc version 0.2
+ * 
+ * Revision 1.5  94/09/28  10:34:50  neelin
+ * Pre-release
+ * 
+ * Revision 1.4  94/01/18  14:23:41  neelin
+ * Changed bzero to memset.
+ * 
+ * Revision 1.3  93/11/30  14:42:13  neelin
+ * Copies to minc format.
+ * 
+ * Revision 1.2  93/11/25  13:26:55  neelin
+ * Working version.
+ * 
+ * Revision 1.1  93/11/23  14:11:54  neelin
+ * Initial revision
+ * 
+@COPYRIGHT  :
+              Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <signal.h>
+#include <dicomserver.h>
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : connection_okay
+@INPUT      : sockfd - input file descriptor which might be a socket
+@OUTPUT     : (none)
+@RETURNS    : TRUE if connection is okay, FALSE otherwise
+@DESCRIPTION: Checks whether the connection is allowed. Looks at sockfd
+              to find out if remote host is allowed to connect. If sockfd
+              is a file and not a socket, then the connection is allowed.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 20, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int connection_okay(int sockfd)
+{
+   struct sockaddr_in us, them;
+   int status;
+   int namelen;
+   extern int Do_logging;
+
+   /* Get our own id. If sockfd is a file, then its okay. Check that we
+      have an internet connection. */
+   namelen = sizeof(us);
+   if (getsockname(sockfd, &us, &namelen) != 0) {
+      if (errno == ENOTSOCK) 
+         return TRUE;
+      else {
+         (void) fprintf(stderr, "Unable to get our own host address.\n");
+         return FALSE;
+      }
+   }
+   else if (us.sin_family != AF_INET) {
+      (void) fprintf(stderr, "Connection is not from network.\n");
+      return FALSE;
+   }
+
+   /* Try to get id of host at other end of connection */
+   namelen = sizeof(us);
+   status = getpeername(sockfd, &them, &namelen);
+   if (status != 0) {
+      (void) fprintf(stderr, "Unable to check connection source.\n");
+      return FALSE;
+   }
+
+   /* */
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "Connection from %s ", inet_ntoa(them.sin_addr));
+   }
+
+   /* modified by rhoge to relax network restriction from class C to B */
+
+   /* Compare the addresses. Make sure that we have the same IP domain
+      assuming class B structure. */
+   if ((us.sin_addr.s_addr & IN_CLASSB_NET) != 
+       (them.sin_addr.s_addr & IN_CLASSB_NET)) {
+      if (Do_logging >= LOW_LOGGING) {
+	(void) fprintf(stderr,"Request not from same IP domain (class B)\n");
+	(void) fprintf(stderr,"Our   ip address:  %d\n",us.sin_addr.s_addr);
+	(void) fprintf(stderr,"Their ip address:  %d\n",them.sin_addr.s_addr);
+	(void) fprintf(stderr,"CLASSB mask:       %d\n",IN_CLASSB_NET);
+	(void) fprintf(stderr, 
+		       "Connection from %s ", inet_ntoa(them.sin_addr));
+	(void) fprintf(stderr, "refused.\n");
+      }
+      /*      return FALSE; */
+   }
+
+   /* Log a warning if hosts not from same class C network */
+   if ((us.sin_addr.s_addr & IN_CLASSC_NET) != 
+       (them.sin_addr.s_addr & IN_CLASSC_NET)) {
+      if (Do_logging >= LOW_LOGGING) {
+          (void) fprintf(stderr,"Request not from same IP domain (class C)\n");
+	  (void) fprintf(stderr, 
+			 "Connection from %s ", inet_ntoa(them.sin_addr));
+      }
+   }
+
+   if (Do_logging >= LOW_LOGGING) {
+      (void) fprintf(stderr, "accepted.\n");
+   }
+
+   return TRUE;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : open_connection
+@INPUT      : argc - number of command-line arguments
+              argv - array of command-line arguments
+@OUTPUT     : afpin - Acr file pointer for input
+              afpout - Acr file pointer for output
+@RETURNS    : (nothing)
+@DESCRIPTION: Opens the connection for reading writing dicom messages.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+/* ARGSUSED */
+public void open_connection(int argc, char *argv[], 
+                            Acr_File **afpin, Acr_File **afpout)
+{
+   /* Set default file pointers */
+   *afpin = *afpout = NULL;
+
+   /* Check for a valid connection */
+   if (!connection_okay(fileno(stdin))) return;
+
+   /* Open the connection */
+   *afpin=acr_initialize_dicom_input(stdin, 0, acr_stdio_read);
+   *afpout=acr_initialize_dicom_output(stdout, 0, acr_stdio_write);
+
+   /* Ignore SIGPIPE errors in case connection gets closed when we are
+      doing output */
+   (void) signal(SIGPIPE, SIG_IGN);
+}
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/parse_dicom_groups.c
@@ -0,0 +1,128 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : parse_dicom_groups.c
+@DESCRIPTION: Routine to parse dicom file - replicates postconditions
+              of save_transferred_object.c
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+ * $Log: parse_dicom_groups.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.2  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.1  2001/12/31 17:27:01  rhoge
+ * adding file to repository - works for numa4 non-mos files now
+ *
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : parse_dicom_groups
+@INPUT      : group_list - list of acr-nema groups that make up object
+@OUTPUT     : data_info - information about data object
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to parse dicom object
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : June 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void parse_dicom_groups(Acr_Group group_list, Data_Object_Info *data_info)
+{
+   Acr_Group group;
+   Acr_Element element;
+   char patient_name[256];
+
+   unsigned short AcqMat[4];
+   unsigned short freq_rows;
+   unsigned short freq_cols;
+   unsigned short phase_rows;
+   unsigned short phase_cols;
+
+   int maxlen = sizeof(Cstring) - 1;
+
+   // Get info to construct unique identifiers for study, series/acq
+   // for file processing
+   get_identification_info(group_list,
+                           &(data_info->study_id), &(data_info->acq_id),
+                           &(data_info->rec_num), &(data_info->image_type));
+
+   // Get number of echos, echo number, number of dynamic scans and 
+   // dynamic_scan_number
+   data_info->num_echoes =
+      acr_find_int(group_list, SPI_Number_of_echoes, 999);
+   data_info->echo_number =
+      acr_find_int(group_list, ACR_Echo_number, 999);
+   data_info->num_dyn_scans =
+      acr_find_int(group_list, ACR_Acquisitions_in_series, 999);
+   data_info->dyn_scan_number =
+      acr_find_int(group_list, ACR_Acquisition, 999);
+   data_info->global_image_number =
+      acr_find_int(group_list, ACR_Image, 999);
+
+   /* rhoge:
+      new info added to data_info by rhoge: nominal number of slices;
+      this is used in detection of a stream of files with the same
+      acquisition ID number in which there are more files than
+      slices.  If the number of signal averages is greater than one,
+      we will assume that this means the acquisition loop was used for
+      dynamic scanning.  
+
+      WARNINGS:  the same thing may need to be done with `number of
+      partitions' for it to work with 3D scans  */
+
+   data_info->num_slices_nominal =
+      acr_find_int(group_list, SPI_Number_of_slices_nominal, 999);
+   data_info->slice_number = 999;
+
+   // identification info needed to generate unique session id
+   // for file names
+   data_info->study_date =
+     acr_find_int(group_list, ACR_Study_date, 999); 
+   data_info->study_time =
+     acr_find_int(group_list, ACR_Study_time, 999); 
+   data_info->scanner_serialno =
+     acr_find_int(group_list, ACR_Device_serial_number, 999); 
+
+   // identification info needed to determine if mosaics used 
+
+   element = acr_find_group_element(group_list,ACR_Acquisition_matrix);
+   acr_get_element_short_array(element,4,AcqMat);
+
+   freq_rows = AcqMat[0];
+   freq_cols = AcqMat[1];
+
+   phase_rows = AcqMat[2];
+   phase_cols = AcqMat[3];
+
+   // rows in acq matrix is larger of freq rows and freq columns:
+   data_info->acq_rows = ( freq_rows > freq_cols ? freq_rows : freq_cols );
+   // all images are square, at this time
+   data_info->acq_cols = data_info->acq_rows;
+
+   data_info->rec_rows = acr_find_int(group_list,ACR_Rows, 999);
+   data_info->rec_cols = acr_find_int(group_list,ACR_Columns, 999);
+
+   data_info->num_mosaic_rows=acr_find_int(group_list,EXT_Mosaic_rows, 999);
+   data_info->num_mosaic_cols=acr_find_int(group_list,EXT_Mosaic_columns,999);
+   data_info->num_slices_in_file=
+     acr_find_int(group_list,EXT_Slices_in_file,999);
+
+   // sequence, protocol names (useful for debugging):
+
+   (void) strncpy(data_info->sequence_name,
+		  acr_find_string(group_list,ACR_Sequence_name,""),maxlen);
+   (void) strncpy(data_info->protocol_name,
+		  acr_find_string(group_list,ACR_Protocol_name,""),maxlen);
+
+   return;
+
+}
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/progress.c
@@ -0,0 +1,54 @@
+
+// This function prints a text progress bar within a term window
+// Input arguments assume a for loop starting at zero:
+//
+//      for (index =  0; index < end; index++) { ...
+
+#include <stdio.h>
+#include <math.h>
+
+int progress(long index, int end, char *message) {
+
+  int ix;
+  int width = 50;
+  int nchars;
+
+  if (index == 0) {
+
+    if (strlen(message) > 20) {
+      // truncate message if too long
+      message[20] = '\0';
+    }
+
+    printf("%-20s |<--",message);
+    for (ix = 0; ix < width; ix++) { 
+      printf(" ");
+    }
+    printf("|");
+    for (ix = 0; ix < width+1; ix++) { 
+      printf("\b");
+    }
+  } else if ((index > 0) && (index < end)) {
+
+    nchars = (((float)index/(float)(end-1)) * width) - 
+      floor(((float)(index-1)/(float)(end-1)) * width);
+
+    for (ix = 0; ix < nchars; ix++) {
+      printf("\b->");
+      (void) fflush(stdout);
+    }
+
+    // print terminating newline at end if we're done
+    if (index == end-1) {
+      printf("\n");
+    }
+  } else {
+    fprintf(stderr,"PROGRESS:  bad input indices!\n");
+    return 0;
+  }
+}
+
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/project_file.c
@@ -0,0 +1,214 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : project_file.c
+@DESCRIPTION: Code to do manipulate the project files (files containing
+              info on what to do with files for each project).
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: project_file.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:56  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <dicomserver.h>
+
+/* Function prototypes */
+/************************************************/
+/* Commented out by rhoge, put back in by leili */
+ int gethostname (char *name, size_t  namelen); 
+/************************************************/
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : read_project_file
+@INPUT      : project_name - name to use for project file
+@OUTPUT     : file_prefix - string used as prefix for output files 
+                 (can be NULL)
+              output_uid - uid for created files (can be NULL). Set to 
+                 INT_MIN if file not found.
+              output_gid - gid for created files (can be NULL). Set to
+                 INT_MIN if file not found.
+              command_line - command to execute on new file (can be NULL)
+              maxlen_command - maximum length for command_line
+@RETURNS    : TRUE if an error occurs, FALSE otherwise.
+@DESCRIPTION: Routine to read in default information for a given project.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 14, 1995 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int read_project_file(char *project_name, 
+                             char *file_prefix, 
+                             int *output_uid, int *output_gid,
+                             char *command_line, int maxlen_command)
+{
+   char project_string[256];
+   char output_default_file[256];
+   char temp_file_prefix[256];
+   int temp_uid, temp_gid;
+   char temp_command_line[4];
+   int ichar, ochar;
+   int length, index;
+   FILE *fp;
+   char string[512];
+   int project_name_given;
+
+   /* Check that the user actually wants return values */
+   if (file_prefix == NULL) file_prefix = temp_file_prefix;
+   if (output_uid == NULL) output_uid = &temp_uid;
+   if (output_gid == NULL) output_gid = &temp_gid;
+   if ((command_line == NULL) || (maxlen_command <= 0)) {
+      command_line = temp_command_line;
+      maxlen_command = sizeof(temp_command_line);
+   }
+
+   /* Set some default values */
+   file_prefix[0] = '\0';
+   command_line[0] = '\0';
+   *output_uid = *output_gid = INT_MIN;
+
+   /* Copy the project name, removing spaces */
+   if (project_name != NULL)
+      length = strlen(project_name);
+   else
+      length = 0;
+   for (ichar=0, ochar=0; 
+        (ichar < length) && (ochar < sizeof(project_string)-1);
+        ichar++) {
+      if (isprint((int) project_name[ichar]) && 
+          !isspace((int) project_name[ichar])) {
+         project_string[ochar] = (char) toupper((int) project_name[ichar]);
+         ochar++;
+      }
+   }
+   project_string[ochar] = '\0';
+
+   /* Get the host name if there is no project string */
+   project_name_given = (strlen(project_string) > (size_t) 0);
+   if (!project_name_given)
+      (void) gethostname(project_string, sizeof(project_string) - 1);
+   (void) sprintf(output_default_file, "%s/%s%s", 
+                  OUTPUT_DEFAULT_FILE_DIR, OUTPUT_DEFAULT_FILE_PREFIX,
+                  project_string);
+
+   /* Open and read the defaults file - if it isn't there then return TRUE
+      if the caller gave a project name */
+   if ((fp=fopen(output_default_file, "r")) == NULL) {
+      return project_name_given;
+   }
+   if (fgets(string, (int) sizeof(string), fp) == NULL) {
+      return TRUE;
+   }
+   if (sscanf(string, "%s %d %d", file_prefix, output_uid, output_gid) != 3) {
+      return TRUE;
+   }
+   (void) fgets(command_line, maxlen_command, fp);
+   index = strlen(command_line) - 1;
+   if ((index >= 0) && (command_line[index] == '\n'))
+      command_line[index] = '\0';
+   (void) fclose(fp);
+
+   return FALSE;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_project_option_string
+@INPUT      : (none)
+@OUTPUT     : project_option_string - string containing list of options
+                 for project name
+              maxlen_project_option - maximum length for the string (including
+                 '\0' at end)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to get a list of possibilities for the project name
+              (looking for appropriately named files).
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 14, 1995 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_project_option_string(char *project_option_string,
+                                      int maxlen_project_option)
+{
+   DIR *dirp;
+   struct dirent *dp;
+   int length;
+   char *name, *filler;
+   int compare_length;
+
+   /* Set up the string */
+   if (maxlen_project_option > 0) {
+      project_option_string[0] = '\0';
+      length = 1;
+   }
+
+   /* Open directory */
+   if ((dirp = opendir(OUTPUT_DEFAULT_FILE_DIR)) == NULL)
+      return;
+
+   /* Loop through directory entries */
+   compare_length = strlen(OUTPUT_DEFAULT_FILE_PREFIX);
+   while ((dp = readdir(dirp)) != NULL) {
+
+      /* Check for an entry with the right prefix */
+      if (strncmp(OUTPUT_DEFAULT_FILE_PREFIX, 
+                  dp->d_name, compare_length) == 0) {
+
+         /* Check for an uppercase letter */
+         if ((strlen(dp->d_name) > (size_t) compare_length) &&
+             (isupper(dp->d_name[compare_length]))) {
+            name = &dp->d_name[compare_length];
+
+            /* Check that we can read the project file */
+            if (!read_project_file(name, NULL, NULL, NULL, NULL, 0)) {
+               if (length > 1)
+                  filler = ", ";
+               else
+                  filler = "";
+               if ((strlen(name) + length + strlen(filler)) 
+                   < (size_t) maxlen_project_option) {
+                  (void) strcat(strcat(project_option_string, filler), name);
+                  length += strlen(filler) + strlen(name);
+               }
+            }        /* We can read the project file */
+            
+         }        /* Found uppercase letter */
+         
+      }        /* Found file matching prefix */
+
+   }        /* Loop over files */
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/reply.c
@@ -0,0 +1,617 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : reply.c
+@DESCRIPTION: Routines for dealing with dicom messages.
+@GLOBALS    : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: reply.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.2  2001/02/26 06:14:39  rhoge
+ * modified to allow target directory to be passed as AE title (only 16 chars)
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.3  1999/10/29 17:51:57  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.2  1999/08/05 20:01:16  neelin
+ * Check for broken Siemens software using a list of implementation UIDs.
+ *
+ * Revision 6.1  1998/05/19  19:27:43  neelin
+ * Test for Siemens Vision machine by looking for implementation uid
+ * rather than AE title
+ *
+ * Revision 6.0  1997/09/12  13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.1  1997/07/08  23:15:09  neelin
+ * Added support for C_ECHO command.
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+
+extern int Do_logging;
+
+/* List of implementation UIDs for Siemens Vision scanners with broken 
+   handling of transfer syntax. These should be in ascending order of
+   software version, since the UID for version VB33A is used to identify 
+   a change in element use. */
+static char *SPI_Vision_Implementation_UIDs[] = {
+   "2.16.840.1.113669.2.931128",
+   "1.3.12.2.1107.5.1995.1",          /* Version VB33A */
+   /* Added By Leili  */
+   "1.3.12.2.1107.5.2",               /* Version MREASE_VA21A */ 
+   NULL
+};
+/* Index into above array for version VB33A */
+#define SPI_VISION_VB33A_INDEX 1
+/* Global to indicate whether we have a pre VB33A version */
+int SPI_Vision_version_pre33A = TRUE;
+
+/* Macros */
+#define SAVE_SHORT(group, elid, value) \
+   acr_group_add_element(group, \
+      acr_create_element_short(elid, (unsigned short) (value)))
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : uid_equal
+@INPUT      : uid1
+              uid2
+@OUTPUT     : (nothing)
+@RETURNS    : TRUE if uid's are equal, FALSE otherwise
+@DESCRIPTION: Responds to READYq message
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 21, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int uid_equal(char *uid1, char *uid2)
+{
+   int len1, len2, i;
+
+   len1 = strlen(uid1);
+   len2 = strlen(uid2);
+
+   /* Skip leading blanks */
+   while (isspace(*uid1)) {uid1++;}
+   while (isspace(*uid2)) {uid2++;}
+
+   /* Skip trailing blanks */
+   for (i=len1-1; (i >= 0) && isspace(uid1[i]); i++) {}
+   if (isspace(uid1[i+1])) uid1[i+1] = '\0';
+   for (i=len2-1; (i >= 0) && isspace(uid1[i]); i++) {}
+   if (isspace(uid1[i+1])) uid1[i+1] = '\0';
+
+   /* Compare the strings */
+   return (strcmp(uid1, uid2) == 0);
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : make_message
+@INPUT      : group_list
+@OUTPUT     : (nothing)
+@RETURNS    : output message.
+@DESCRIPTION: Convert a group list into a message.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 24, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private Acr_Message make_message(Acr_Group group_list)
+{
+   Acr_Group next_group, group;
+   Acr_Message output_message;
+
+   /* Create the output message */
+   output_message = acr_create_message();
+
+   /* Loop through groups, adding them to the message */
+   group = group_list;
+   while (group != NULL) {
+      next_group = acr_get_group_next(group);
+      acr_set_group_next(group, NULL);
+      acr_message_add_group(output_message, group);
+      group = next_group;
+   }
+
+   return output_message;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : associate_reply
+@INPUT      : input_message
+@OUTPUT     : project_name - name to use for project file
+              pres_context_id - presentation context id to use for output. If
+                 this is < 0, then an error occurred.
+              byte_order - byte order to use for messages
+              vr_encoding - VR encoding to use for messages
+              maximum_length - maximum length of output PDU's
+@RETURNS    : output_message
+@DESCRIPTION: Responds to an associate request message
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Message associate_reply(Acr_Message input_message, 
+                                   char **project_name,
+                                   int *pres_context_id,
+                                   Acr_byte_order *byte_order,
+                                   Acr_VR_encoding_type *vr_encoding,
+                                   long *maximum_length)
+{
+   Acr_Group group, input_group;
+   Acr_Element element, item, subitem, sublist;
+   Acr_Element out_item, out_subitem, out_sublist, out_list;
+   /***********************************/
+   /* Added by Leili */
+   Acr_Element my_element_test;
+   /***********************************/
+   int found_best;
+   int best_pres_context_id, cur_pres_context_id;
+   int best_transfer_syntax_priority;
+   int use_implicit_little_endian;
+   char *best_abstract_syntax, *best_transfer_syntax, *cur_syntax;
+   int impuid;
+
+   /* Print log message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "\n\nReceived associate request message:\n");
+      acr_dump_message(stderr, input_message);
+   }
+
+   /* Set default presentation context id to flag error */
+   *pres_context_id = -1;
+
+   /* Free project_name string if needed */
+   if (*project_name != NULL) FREE(*project_name);
+
+   /* Get the group list */
+   input_group = acr_get_message_group_list(input_message);
+      
+   /* Get the project name from the DICOM application name */
+   *project_name = strdup(acr_find_string(input_group, 
+                                          DCM_PDU_Called_Ap_title, ""));
+       
+   /* Check that the project file is okay. If it is not found, try the host
+      name */
+
+   /* changed by rhoge so as not to clobber the aetitle in the
+      unlikely event that it is being used to pass a file name (starts
+      with `/' or `~') - this functionality is of limited usefulness, since 
+      the AE title can not be longer than 16 characters */
+
+   if (read_project_file(*project_name, NULL, NULL, NULL, NULL, 0)
+       && !(!strncmp(*project_name,"/",1)||!strncmp(*project_name,"~",1))) { 
+     FREE(*project_name);
+     *project_name = NULL;
+     if (read_project_file(*project_name, NULL, NULL, NULL, NULL, 0)) {
+       return associate_reply_reject(input_message, 
+				     ACR_ASSOC_RJ_CALLED_AP_TITLE_UNREC);
+     }
+   }
+     
+   /* Check for Siemens Vision implementation that lies about its 
+      transfer syntaxes */
+
+     /**********************************************/
+     /* The if and else statement is commented out by leili */
+     // if (0) {
+
+     use_implicit_little_endian = FALSE;
+     for (impuid=0; SPI_Vision_Implementation_UIDs[impuid] != NULL; impuid++) {
+       if (uid_equal(acr_find_string(input_group, 
+				     DCM_PDU_Implementation_class_uid, ""),
+		     SPI_Vision_Implementation_UIDs[impuid])) {
+         use_implicit_little_endian = TRUE;
+         (void) fprintf(stderr, "just made the implicit little endian true\n ");
+	   SPI_Vision_version_pre33A = (impuid < SPI_VISION_VB33A_INDEX);
+         break;
+       }
+     }
+     // } else {
+     
+     //use_implicit_little_endian = FALSE;
+
+     //}
+     /**********************************************/
+
+     
+   /* Get maximum length */
+   *maximum_length = acr_find_long(input_group, DCM_PDU_Maximum_length, 0L);
+
+   /* Get presentation context list */
+   best_pres_context_id = -1;
+   best_abstract_syntax = NULL;
+   element = 
+      acr_find_group_element(input_group, DCM_PDU_Presentation_context_list);
+   if ((element == NULL) || !acr_element_is_sequence(element)) {
+      (void) fprintf(stderr, "No presentation context list found\n");
+      return associate_reply_reject(input_message, ACR_ASSOC_RJ_NO_REASON);
+   }
+   
+   /* Loop over presentation contexts */
+   found_best = FALSE;
+   for (item = (Acr_Element) acr_get_element_data(element);
+        (item != NULL) && acr_element_is_sequence(item) && !found_best;
+        item = acr_get_element_next(item)) {
+
+      /* Get presentation context info */
+      sublist = (Acr_Element) acr_get_element_data(item);
+
+      /* Get abstract syntax */
+      subitem = acr_find_element_id(sublist, 
+                                    DCM_PDU_Abstract_syntax);
+      if (subitem == NULL) continue;
+      cur_syntax = acr_get_element_string(subitem);
+
+      /* Check whether this is either MR abstract syntax or we have
+         already found one (we take the first one if we cannot find
+         the one that we want) */
+      if (uid_equal(cur_syntax, FAVORITE_ABSTRACT_SYNTAX))
+         found_best = TRUE;
+      else if (best_abstract_syntax != NULL) 
+         continue;
+
+      /* Save the abstract syntax */
+      best_abstract_syntax = cur_syntax;
+      /* Get presentation context id */
+      subitem = acr_find_element_id(sublist, 
+                                    DCM_PDU_Presentation_context_id);
+      if (subitem != NULL)
+         best_pres_context_id = acr_get_element_short(subitem);
+      else {
+         (void) fprintf(stderr, 
+                        "No presentation context - internal error\n");
+         return associate_reply_reject(input_message, ACR_ASSOC_RJ_NO_REASON);
+      }
+
+      /* Look for an appropriate transfer syntax */
+      best_transfer_syntax = NULL;
+      best_transfer_syntax_priority = 0;
+      for (subitem = sublist;
+           subitem != NULL;
+           subitem=acr_find_element_id(acr_get_element_next(subitem), 
+                                       DCM_PDU_Transfer_syntax)) {
+
+         /* Check for syntaxes in descending order of preference */
+         cur_syntax = acr_get_element_string(subitem);
+         if (uid_equal(cur_syntax, ACR_EXPLICIT_VR_BIG_END_UID)) {
+            if (best_transfer_syntax_priority < 3) {
+               best_transfer_syntax_priority = 3;
+               best_transfer_syntax = cur_syntax;
+            }
+         }
+         else if (uid_equal(cur_syntax, ACR_EXPLICIT_VR_LITTLE_END_UID)) {
+            if (best_transfer_syntax_priority < 2) {
+               best_transfer_syntax_priority = 2;
+               best_transfer_syntax = cur_syntax;
+            }
+         }
+         else if (uid_equal(cur_syntax, ACR_IMPLICIT_VR_LITTLE_END_UID)) {
+            if (best_transfer_syntax_priority < 1) {
+               best_transfer_syntax_priority = 1;
+               best_transfer_syntax = cur_syntax;
+            }
+         }
+
+      }         /* Loop over transfer syntaxes */
+   
+   }            /* Loop over presentation contexts */
+       
+
+   /* Check for machines that lie about their ability to do 
+      different transfer syntaxes */
+   if (use_implicit_little_endian) {
+      best_transfer_syntax = ACR_IMPLICIT_VR_LITTLE_END_UID;
+   }
+
+
+   /* Check that we found something useful */
+   if ((best_pres_context_id < 0) || (best_abstract_syntax == NULL) ||
+       (best_transfer_syntax == NULL)) {
+      (void) fprintf(stderr, 
+                     "Did not find understandable presentation context\n");
+      return associate_reply_reject(input_message, ACR_ASSOC_RJ_NO_REASON);
+   }
+   
+   /****************************************************************************/
+   /* Set the transfer syntax information */
+   /* This part was commented out by rick, put it back in the program by leili */
+
+     if (uid_equal(best_transfer_syntax, ACR_EXPLICIT_VR_BIG_END_UID)) {
+         *byte_order = ACR_BIG_ENDIAN;
+         *vr_encoding = ACR_EXPLICIT_VR;
+      }
+      else if (uid_equal(best_transfer_syntax, ACR_EXPLICIT_VR_LITTLE_END_UID)) {
+      
+      /****************************************/
+      /* this two lines were in rick's version */
+  
+      *byte_order = ACR_LITTLE_ENDIAN;
+      *vr_encoding = ACR_EXPLICIT_VR;
+      /******************************************/
+         }
+         else if (uid_equal(best_transfer_syntax, ACR_IMPLICIT_VR_LITTLE_END_UID)) {
+            *byte_order = ACR_LITTLE_ENDIAN;
+            *vr_encoding = ACR_IMPLICIT_VR;
+         }
+         else {
+            (void) fprintf(stderr, 
+                           "Did not understand transfer syntax.\n");
+            return associate_reply_reject(input_message, ACR_ASSOC_RJ_NO_REASON);
+         }
+    
+     /*************************************************************************/
+   /* Create the reply */
+   group = acr_create_group(DCM_PDU_GRPID);
+
+   /* Save the PDU type */
+   SAVE_SHORT(group, DCM_PDU_Type, ACR_PDU_ASSOC_AC);
+
+   /* Save the caller and calling AE titles */
+   acr_group_add_element(group,
+      acr_create_element_string(DCM_PDU_Called_Ap_title,
+         acr_find_string(input_group, DCM_PDU_Called_Ap_title, "")));
+
+   /****************************************/
+   /* Added by Leili */
+   my_element_test =acr_create_element_string(DCM_PDU_Called_Ap_title,acr_find_string(input_group, DCM_PDU_Called_Ap_title, ""));
+   (void) fprintf(stderr, "This is the called Ap_title: %s \n", my_element_test->data_pointer);
+   /*****************************************/
+ 
+   acr_group_add_element(group,
+      acr_create_element_string(DCM_PDU_Calling_Ap_title,
+         acr_find_string(input_group, DCM_PDU_Calling_Ap_title, "")));
+
+   /****************************************/
+   /* Added by Leili */
+   my_element_test =acr_create_element_string(DCM_PDU_Calling_Ap_title,acr_find_string(input_group, DCM_PDU_Calling_Ap_title, ""));
+   (void) fprintf(stderr, "This is the calling Ap_title: %s \n", my_element_test->data_pointer);
+   /*****************************************/
+
+   /* Add the application context name */
+   acr_group_add_element(group,
+      acr_create_element_string(DCM_PDU_Application_context,
+         acr_find_string(input_group, DCM_PDU_Application_context, 
+                         ACR_APPLICATION_CONTEXT_UID)));
+
+   /* Loop over presentation contexts */
+   item = (Acr_Element) 
+      acr_get_element_data
+         (acr_find_group_element(input_group, 
+                                 DCM_PDU_Presentation_context_list));
+   out_list = NULL;
+   for (;(item != NULL); item = acr_get_element_next(item)) {
+
+      if (!acr_element_is_sequence(item)) continue;
+
+      /* Get presentation context info */
+      sublist = (Acr_Element) acr_get_element_data(item);
+
+      /* Save the id */
+      subitem = acr_find_element_id(sublist, 
+                                    DCM_PDU_Presentation_context_id);
+      if (subitem == NULL) continue;
+      cur_pres_context_id = acr_get_element_short(subitem);
+
+      /* Create the presentation context */
+      out_sublist = NULL;
+      out_subitem = acr_create_element_short(DCM_PDU_Presentation_context_id,
+                                             cur_pres_context_id);
+      out_sublist = acr_element_list_add(out_sublist, out_subitem);
+
+      /* Accept or reject */
+      out_subitem = acr_create_element_short(DCM_PDU_Result,
+         ((cur_pres_context_id == best_pres_context_id) ?
+          ACR_ASSOC_PR_CN_ACCEPT : ACR_ASSOC_PR_CN_REJECT));
+      out_sublist = acr_element_list_add(out_sublist, out_subitem);
+        
+      /* Add the transfer syntax */
+      out_subitem = acr_create_element_string(DCM_PDU_Transfer_syntax,
+                                              best_transfer_syntax);
+      out_sublist = acr_element_list_add(out_sublist, out_subitem);
+
+      /* Add this context to the list */
+      out_item = 
+         acr_create_element_sequence(DCM_PDU_Presentation_context_reply, 
+                                     out_sublist);
+      out_list = acr_element_list_add(out_list, out_item);
+   }
+
+   /* Create the presentation context list element */
+   element = 
+      acr_create_element_sequence(DCM_PDU_Presentation_context_reply_list, 
+                                  out_list);
+   acr_group_add_element(group, element);
+
+   /* Add the user information */
+   acr_group_add_element(group, 
+                         acr_create_element_long(DCM_PDU_Maximum_length, 0L));
+
+   /* Set the presentation context id to indicate success */
+   *pres_context_id = best_pres_context_id;
+
+   return make_message(group);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : associate_reply_reject
+@INPUT      : input_message
+@OUTPUT     : reason
+@RETURNS    : output_message
+@DESCRIPTION: Responds to an associate request message with a rejection
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 21, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+/* ARGSUSED */
+public Acr_Message associate_reply_reject(Acr_Message input_message, 
+                                          int reason)
+{
+   Acr_Group group;
+
+   /* Create the reply */
+   group = acr_create_group(DCM_PDU_GRPID);
+
+   /* Save the PDU type */
+   SAVE_SHORT(group, DCM_PDU_Type, ACR_PDU_ASSOC_RJ);
+
+   /* Give the result, source and reason */
+   SAVE_SHORT(group, DCM_PDU_Result, ACR_ASSOC_RJ_PERM);
+   SAVE_SHORT(group, DCM_PDU_Source, ACR_ASSOC_RJ_USER);
+   SAVE_SHORT(group, DCM_PDU_Reason, reason);
+
+   return make_message(group);
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : release_reply
+@INPUT      : input_message
+@OUTPUT     : (nothing)
+@RETURNS    : output_message
+@DESCRIPTION: Responds to READYq message
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Message release_reply(Acr_Message input_message)
+{
+   Acr_Group group;
+
+   /* Print log message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "\n\nReceived release request message:\n");
+      acr_dump_message(stderr, input_message);
+   }
+
+   /* Create the reply */
+   group = acr_create_group(DCM_PDU_GRPID);
+
+   /* Save the PDU type */
+   SAVE_SHORT(group, DCM_PDU_Type, ACR_PDU_REL_RP);
+
+   return make_message(group);
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : abort_reply
+@INPUT      : input_message
+@OUTPUT     : (nothing)
+@RETURNS    : output_message
+@DESCRIPTION: Responds to GCENDq message
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Message abort_reply(Acr_Message input_message)
+{
+   Acr_Group group;
+
+   /* Print log message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "\n\nReceived abort message:\n");
+      acr_dump_message(stderr, input_message);
+   }
+
+   /* Create the reply */
+   group = acr_copy_group_list(acr_get_message_group_list(input_message));
+
+   return make_message(group);
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : data_reply
+@INPUT      : input_message
+              file_prefix
+@OUTPUT     : new_file_name (must be freed by caller)
+@RETURNS    : output_message
+@DESCRIPTION: Responds to SENDq message
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 22, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Message data_reply(Acr_Message input_message)
+{
+   Acr_Group group, input_group;
+   int reply_command;
+   
+
+   /* Print log message */
+   if (Do_logging >= HIGH_LOGGING) {
+      (void) fprintf(stderr, "\n\nReceived data message:\n");
+      acr_dump_message(stderr, input_message);
+   }
+
+   /* Get the input group list */
+   input_group = acr_get_message_group_list(input_message);
+
+
+   /* Figure out the reply that we need */
+   switch (acr_find_short(input_group, ACR_Command, -1)) {
+   case ACR_C_STORE_RQ:
+      reply_command = ACR_C_STORE_RSP; break;
+   case ACR_C_ECHO_RQ:
+      reply_command = ACR_C_ECHO_RSP; break;
+   default:
+      reply_command = ACR_C_ECHO_RSP; break;
+   }
+
+   /* Create the reply */
+   group = acr_create_group(ACR_MESSAGE_GID);
+
+   /* Save appropriate stuff */
+   acr_group_add_element(group,
+      acr_create_element_string(ACR_Affected_SOP_class_UID, 
+         acr_find_string(input_group, ACR_Affected_SOP_class_UID, "")));
+   SAVE_SHORT(group, ACR_Command, reply_command);
+   SAVE_SHORT(group, ACR_Message_id_brt, 
+              acr_find_short(input_group, ACR_Message_id, 0));
+   SAVE_SHORT(group, ACR_Dataset_type, ACR_NULL_DATASET);
+   SAVE_SHORT(group, ACR_Status, ACR_SUCCESS);
+   if (reply_command == ACR_C_STORE_RSP) {
+      acr_group_add_element(group,
+         acr_create_element_string(ACR_Affected_SOP_instance_UID, 
+            acr_find_string(input_group, ACR_Affected_SOP_instance_UID, "")));
+   }
+   
+   return make_message(group);
+
+}
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/save_transferred_object.c
@@ -0,0 +1,192 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : save_transferred_object.c
+@DESCRIPTION: Routine to save data object.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: save_transferred_object.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.2  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:58  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+extern int Do_logging;
+
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : save_transferred_object
+@INPUT      : group_list - list of acr-nema groups that make up object
+              file_prefix - prefix for file names
+@OUTPUT     : new_file_name - name for newly created file
+              data_info - information about data object
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to save the object in a file.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 24, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void save_transferred_object(Acr_Group group_list, char *file_prefix2,
+                                    char **new_file_name,
+                                    Data_Object_Info *data_info)
+{
+   Acr_Group group;
+   Acr_Element element;
+   char temp_name[256];
+   char patient_name[256];
+   double study_id;
+   int acquisition_id, image_id;
+   Acr_File *afp;
+   FILE *fp;
+   Acr_Status status;
+   Acr_VR_encoding_type vr_encoding;
+   Acr_byte_order byte_order;
+   static int file_counter = 0;
+   /* Added by Leili */
+   char full_path[256];
+
+   /* Get the VR encoding state and byte order */
+   element = acr_get_group_element_list(group_list);
+  
+
+   vr_encoding = acr_get_element_vr_encoding(element);
+
+   byte_order = acr_get_element_byte_order(element);
+
+   /* Get data info */
+   get_identification_info(group_list,
+                           &(data_info->study_id), &(data_info->acq_id),
+                           &(data_info->rec_num), &(data_info->image_type));
+
+   /* Get number of echos, echo number, number of dynamic scans and 
+      dynamic_scan_number */
+   data_info->num_echoes =
+      acr_find_int(group_list, SPI_Number_of_echoes, 1);
+   data_info->echo_number =
+      acr_find_int(group_list, ACR_Echo_number, 1);
+   data_info->num_dyn_scans =
+      acr_find_int(group_list, ACR_Acquisitions_in_series, 1);
+   data_info->dyn_scan_number =
+      acr_find_int(group_list, ACR_Series, 1);
+
+   /* rhoge:
+      new info added to data_info by rhoge: nominal number of slices;
+      this is used in detection of a stream of files with the same
+      acquisition ID number in which there are more files than
+      slices.  If the number of signal averages is greater than one,
+      we will assume that this means the acquisition loop was used for
+      dynamic scanning.  
+
+      WARNINGS:  the same thing may need to be done with `number of
+      partitions' for it to work with 3D scans  */
+
+   data_info->num_slices_nominal =
+      acr_find_int(group_list, SPI_Number_of_slices_nominal, 1);
+
+   /* Look for patient name */
+   element = acr_find_group_element(group_list, ACR_Patient_name);
+   if (element != NULL) {
+      string_to_filename(acr_get_element_string(element), patient_name,
+                         sizeof(patient_name));
+   }
+   if ((element == NULL) || (strlen(patient_name) == 0))
+      (void) strcpy(patient_name, "unknown");
+
+   /* Look for study and image numbers */
+   study_id = data_info->study_id;
+   acquisition_id = data_info->acq_id;
+   image_id = acr_find_int(group_list, ACR_Image, 0);
+
+   /* Added by Leili */
+   //(void) strcpy(full_path, "/software/source/dicomserver_test/");
+   (void) strcpy(full_path, file_prefix2);
+   //(void) strcat(full_path, file_prefix);
+   (void) sprintf(temp_name, "dicom-%s-%f/", patient_name, study_id);
+   strcat (full_path, temp_name);
+   /* Create the new file name */
+   /* The %s ---> full_path is added by Leili to the begining of the temp_name */
+   (void) sprintf(temp_name, "%s%s-%04d-%s_%f_%d_%d.dcm", 
+                  full_path,"dicom", file_counter++, patient_name, study_id, 
+                  acquisition_id, image_id);
+
+   /* Added by Leili */
+   /* create the session directory if none exists */
+   if (mkdir(full_path, 0777) && (Do_logging> 2)) {
+      (void) fprintf(stderr, "Directory %s exists ...\n", full_path);
+   }
+
+   /* Create the file and write out the data */
+   fp = fopen(temp_name, "w");
+   if (fp == NULL) {
+      (void) fprintf(stderr, "Error opening file for write: %s\n",
+                     temp_name);
+   }
+   else {
+      /* Set up the output stream */
+      afp = acr_file_initialize(fp, 0, acr_stdio_write);
+      acr_set_vr_encoding(afp, vr_encoding);
+      acr_set_byte_order(afp, byte_order);
+
+      /* Loop over groups */
+      group = group_list;
+      status = ACR_OK;
+      while ((group != NULL) && (status == ACR_OK)) {
+
+         /* Write out the group */
+         status = acr_output_group(afp, group);
+         if (status != ACR_OK) {
+            (void) fprintf(stderr, "Error writing file %s\n",
+                           temp_name);
+         }
+         group = acr_get_group_next(group);
+
+      }
+
+      /* Close the file */
+      acr_file_free(afp);
+      (void) fclose(fp);
+   }
+
+   /* Copy the name */
+   *new_file_name = strdup(temp_name);   
+   return;
+
+}
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_dicom_read.c
@@ -0,0 +1,1196 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_dicom_read.c
+@DESCRIPTION: Code to read siemens dicom files and get info from them.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: siemens_dicom_read.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.12  2002/05/01 21:29:34  rhoge
+ * removed MrProt from minc header - encountered files with large strings,
+ * causing seg faults
+ *
+ * Revision 1.11  2002/04/26 03:27:03  rhoge
+ * fixed MrProt problem - replaced fixed lenght char array with malloc
+ *
+ * Revision 1.10  2002/04/08 17:26:34  rhoge
+ * added additional sequence info to minc header
+ *
+ * Revision 1.9  2002/03/27 18:57:50  rhoge
+ * added diffusion b value
+ *
+ * Revision 1.8  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.7  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.6  2000/12/14 21:33:13  rhoge
+ * code modifications to restore measurement loop support that was broken
+ * by changes to support acqusition loop scanning
+ *
+ * Revision 1.5  2000/12/13 13:25:36  rhoge
+ * removed dummy printf from convert_time_to_seconds - turns out that
+ * buggy behaviour was an optimization problem
+ *
+ * Revision 1.4  2000/12/12 19:27:52  rhoge
+ * changed atof(acr_find_string) back to acr_find_double after realizing
+ * that these functions assume string representation
+ *
+ * Revision 1.3  2000/12/12 14:43:22  rhoge
+ * fixed syntax error (dangling comment symbol) from removal of debug
+ * printfs - compiles now
+ *
+ * Revision 1.2  2000/12/11 20:01:44  rhoge
+ * fixed code for frame time computation - ACR vals are strings.  Also
+ * inserted dummy fprintf statement in convert_time_to_seconds as this
+ * seems to salvage Linux problems
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ * -now always use ACR_Series for run number (seemed to be
+ *  problems with test introduced in 6.1)
+ * -added code to detect use of acquisition loop and also to handle
+ *  `corrected' siemens acq loop scans
+ * -changed code to use registration time instead of scan time for 
+ *  session id
+ * -got rid of extraneous acquisition id digit
+ * -added technical information about data acquisition
+ *
+ * Revision 6.2  1999/10/29 17:51:58  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.1  1999/08/05 20:00:34  neelin
+ * Get acquisition id from series or study element, depending on the
+ * version of the Siemens software.
+ *
+ * Revision 6.0  1997/09/12  13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.1  1997/09/10  19:36:13  neelin
+ * Small fix to set default direction cosines when they are absent from the
+ * dicom data.
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.1  1997/06/13  12:51:21  neelin
+ * Changed definition of time index and acquisition id to match change
+ * in Siemens dicom software.
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.2  1997/03/11  13:10:48  neelin
+ * Working version of dicomserver.
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+#include <math.h>
+
+extern int SPI_Vision_version_pre33A;
+File_Type file_type;
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_file_info
+@INPUT      : group_list - input data
+@OUTPUT     : file_info - file-specific info
+              general_info - general information about files
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to extract information from a group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 25, 1993 (Peter Neelin)
+@MODIFIED   : Modified Feb. 2000 by Rick Hoge to handle Acquisition loop mode
+            : if assume_acq_loop is FALSE the other added variables don't 
+            : matter 
+---------------------------------------------------------------------------- */
+public void get_file_info(Acr_Group group_list, File_Info *file_info,
+                          General_Info *general_info)
+{
+   Mri_Index imri;
+   World_Index iworld, jworld;
+   Volume_Index ivolume;
+   int nrows, ncolumns, spatial_sizes[VOL_NDIMS];
+   double study_id;
+   int acq_id, rec_num;
+   int cur_index;
+   int index;
+   int number_of_3D_partitions;
+   Orientation orientation;
+   World_Index volume_to_world[VOL_NDIMS];
+   double coordinate[WORLD_NDIMS], dircos[VOL_NDIMS][WORLD_NDIMS];
+   double steps[VOL_NDIMS], starts[VOL_NDIMS], slice_index;
+   Acr_Element_Id mri_index_list[MRI_NDIMS];
+   Acr_Element_Id mri_total_list[MRI_NDIMS];
+
+   // Array of elements for mri dimensions
+   mri_index_list[SLICE] = SPI_Current_slice_number;
+   mri_index_list[ECHO] = ACR_Echo_number;
+   // dicom time element may be different on old systems
+   mri_index_list[TIME] = ACR_Acquisition;
+   mri_index_list[PHASE] = NULL;
+   mri_index_list[CHEM_SHIFT] = NULL;
+   mri_total_list[SLICE] = SPI_Number_of_slices_nominal;
+   mri_total_list[ECHO] = SPI_Number_of_echoes;
+   mri_total_list[TIME] = ACR_Acquisitions_in_series;
+   mri_total_list[PHASE] = NULL;
+   mri_total_list[CHEM_SHIFT] = NULL;
+
+   // Get image dimensions
+   nrows = acr_find_short(group_list, ACR_Rows, 0);
+   ncolumns = acr_find_short(group_list, ACR_Columns, 0);
+   spatial_sizes[VROW] = nrows;
+   spatial_sizes[VCOLUMN] = ncolumns;
+   spatial_sizes[VSLICE] = 1;
+
+   // Get intensity information
+   get_intensity_info(group_list, file_info);
+
+   // Check for necessary values not found
+   if ((nrows <= 0) || (ncolumns <= 0) ||
+       (file_info->bits_stored <= 0) ||
+       (file_info->bits_alloc <= 0)) {
+      file_info->valid = FALSE;
+      return;
+   }
+
+   // Get study, acq, rec, image type id's
+   get_identification_info(group_list, &study_id, &acq_id, &rec_num, NULL);
+
+   // Get number of 3D partitions for working out number of slices
+   number_of_3D_partitions = 
+      acr_find_int(group_list, SPI_Number_of_3D_raw_partitions_nominal, 1);
+   if (number_of_3D_partitions < 1)
+      number_of_3D_partitions = 1;
+
+   // Get indices for image in current file
+   for (imri=0; imri < MRI_NDIMS; imri++) {
+     
+     if (mri_index_list[imri] != NULL) {
+       file_info->index[imri] = 
+	 /* note that for TIME this will use ACR_Acqusition,
+	    which does not work for measurement loop scans */
+	 acr_find_int(group_list, mri_index_list[imri], 1);
+     }
+     else {
+       file_info->index[imri] = 1;
+     }
+   }
+
+   // Get coordinate information
+   get_coordinate_info(group_list, file_info, &orientation, volume_to_world,
+                       spatial_sizes, dircos, steps, starts, coordinate);
+
+   // Replace slice index with slice position in hundredths of millimetres if
+   //   we have more than one partition
+   if (number_of_3D_partitions > 1 | 1) { // ALWAYS USE POSITION (rhoge)
+      slice_index = file_info->coordinate[SLICE] * 100.0;
+      if (slice_index >= 0.0) {
+         slice_index += 0.5;
+      } else {
+         slice_index -= 0.5;
+      }
+      slice_index = (int) slice_index;
+      file_info->index[SLICE] = slice_index;
+   }
+
+   // Set up general info on first pass
+   if (!general_info->initialized) {
+
+      // Get row and columns sizes
+      general_info->nrows = nrows;
+      general_info->ncolumns = ncolumns;
+
+      // Save the study, acquisition, reconstruction and image type 
+      //   identifiers
+      general_info->study_id = study_id;
+      general_info->acq_id = acq_id;
+      general_info->rec_num = rec_num;
+
+      // No image type is available 
+      // (rhoge:  no longer true?)
+      general_info->image_type_string[0] = '\0';
+
+      /* Get dimension information */
+      for (imri=0; imri < MRI_NDIMS; imri++) {
+
+	/* Gets sizes */
+	general_info->size[imri] = 1;
+	if (mri_total_list[imri] != NULL) {
+	  general_info->total_size[imri] = 
+	    acr_find_int(group_list, mri_total_list[imri], 1);
+	} else {
+	  general_info->total_size[imri] = 1;
+	}
+
+	if (general_info->total_size[imri] < 1) {
+	  general_info->total_size[imri] = 1;
+	}
+
+	/* Check for 3D partitions for slice dimensions */
+	if (imri == SLICE) {
+	  general_info->total_size[imri] *= number_of_3D_partitions;
+	}
+
+	/* Set initial values */
+	general_info->default_index[imri] = file_info->index[imri];
+	general_info->image_index[imri] = -1;
+	
+	/* Allocate space for index and coordinate arrays if total_size > 1.
+	   Set the first values. */
+	if (general_info->total_size[imri] > 1) {
+	  general_info->indices[imri] = 
+	    MALLOC(general_info->total_size[imri] * sizeof(int));
+	  general_info->coordinates[imri] = 
+	    MALLOC(general_info->total_size[imri] * sizeof(double));
+	  for (index=0; index < general_info->total_size[imri]; index++) {
+	    general_info->indices[imri][index] = -1;
+	    general_info->coordinates[imri][index] = 0;
+	  }
+	  general_info->search_start[imri] = 0;
+	  general_info->indices[imri][0] = file_info->index[imri];
+	  general_info->coordinates[imri][0] = file_info->coordinate[imri];
+	}
+      }          /* Loop over dimensions */
+
+      /* Get spatial coordinate information */
+      general_info->slice_world = volume_to_world[VSLICE];
+      general_info->row_world = volume_to_world[VROW];
+      general_info->column_world = volume_to_world[VCOLUMN];
+      for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+         iworld = volume_to_world[ivolume];
+         general_info->step[iworld] = steps[ivolume];
+         general_info->start[iworld] = starts[ivolume];
+         for (jworld=0; jworld < WORLD_NDIMS; jworld++) {
+            general_info->dircos[volume_to_world[ivolume]][jworld]
+               = dircos[ivolume][jworld];
+         }
+      }
+
+      /* Set data type and range */
+      if (file_info->bits_alloc <= 8)
+         general_info->datatype = NC_BYTE;
+      else
+         general_info->datatype = NC_SHORT;
+      general_info->is_signed = ((general_info->datatype == NC_SHORT) &&
+                                 (file_info->bits_stored < 16));
+      general_info->pixel_min = file_info->pixel_min;
+      general_info->pixel_max = file_info->pixel_max;
+
+      /* Save display window info */
+      general_info->window_min = file_info->window_min;
+      general_info->window_max = file_info->window_max;
+
+      /* Get the rest of the header information */
+      get_general_header_info(group_list, general_info);
+
+      /* Copy the group list */
+      general_info->group_list = acr_copy_group_list(group_list);
+
+      /* Set initialized flag */
+      general_info->initialized = TRUE;
+
+   }           /* Set up file info */
+   /* Update general info and validate file on later passes */
+   else { //--
+
+     /* Check for consistent data type */
+     if (((general_info->datatype == NC_BYTE) &&
+	  (file_info->bits_alloc > 8)) || 
+	 ((general_info->datatype == NC_SHORT) &&
+	  (file_info->bits_alloc <= 8))) {
+       file_info->valid = FALSE;
+       return;
+     }
+     
+     /* Check row and columns sizes */
+     if ((nrows != general_info->nrows) &&
+	 (ncolumns != general_info->ncolumns))  {
+       file_info->valid = FALSE;
+       return;
+     }
+     
+     /* Check study and acquisition id's */
+     if ((general_info->study_id != study_id) ||
+	 (general_info->acq_id != acq_id)) {
+       file_info->valid = FALSE;
+       return;
+     }
+     
+     /* Look to see if indices have changed */
+     for (imri=0; imri < MRI_NDIMS; imri++) {
+       
+       /* Get current index */
+       cur_index = file_info->index[imri];
+       
+       /* Check whether this index is in the list */
+       if (general_info->size[imri] == 1) {
+	 index = 
+	   ((cur_index == general_info->default_index[imri]) ? 0 : -1);
+       }
+       else {
+	 index = search_list(cur_index, general_info->indices[imri],
+			     general_info->size[imri],
+			     general_info->search_start[imri]);
+       }
+       
+       /* If it is not, then add it */
+       if (index < 0) {
+	 
+	 /* Check whether we can add a new index */
+	 if (general_info->size[imri] >= general_info->total_size[imri]) {
+	   file_info->valid = FALSE;
+	   return;
+	 }
+	 
+	 /* Add the index and coordinate to the lists */
+	 index = general_info->size[imri];
+	 general_info->search_start[imri] = index;
+	 general_info->indices[imri][index] = cur_index;
+	 general_info->coordinates[imri][index] = 
+	   file_info->coordinate[imri];
+	 general_info->size[imri]++;
+	 
+       }
+     }              /* Loop over Mri_Index */
+
+     // note that number of slices will be wrong here for mosaics
+     // we add some other mosaic-relevant fields...
+
+     general_info->num_mosaic_rows =
+       acr_find_int(group_list,EXT_Mosaic_rows,1);
+     general_info->num_mosaic_cols =
+       acr_find_int(group_list,EXT_Mosaic_columns,1);
+     general_info->num_slices_in_file = 
+       acr_find_int(group_list,EXT_Slices_in_file,1);
+     general_info->sub_image_rows =
+       acr_find_short(group_list,EXT_Sub_image_rows,
+		      acr_find_short(group_list, ACR_Rows, 0));
+     general_info->sub_image_columns =
+       acr_find_short(group_list,EXT_Sub_image_columns,
+		      acr_find_short(group_list, ACR_Rows, 0));
+
+     // Update display window info
+     if (general_info->window_min > file_info->window_min) 
+       general_info->window_min = file_info->window_min;
+     if (general_info->window_max < file_info->window_max)
+       general_info->window_max = file_info->window_max;
+     
+   }  // Update general info for this file
+
+   // If we get to here, then we have a valid file
+   file_info->valid = TRUE;
+   return;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_identification_info
+@INPUT      : group_list - input data
+@OUTPUT     : study_id
+              acq_id
+              rec_num
+              image_type
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to get image identification information.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_identification_info(Acr_Group group_list, 
+                                    double *study_id, int *acq_id, 
+                                    int *rec_num, int *image_type)
+{
+   int number_of_frames;
+   int number_of_averages;
+
+   if (study_id != NULL) {
+     // generate a study ID number from date & time:  yyyymmdd.hhmmss
+     // (should be unique enough for our application)
+     *study_id = (((float)acr_find_int(group_list, ACR_Study_date, 0)) +
+       ((float)acr_find_int(group_list, ACR_Study_time, 0))/1e6);
+   }
+   if (acq_id != NULL) {
+
+     *acq_id = acr_find_int(group_list, ACR_Series, 0);
+
+      number_of_frames = 
+         acr_find_int(group_list, ACR_Acquisitions_in_series, 1);
+
+      number_of_averages = 
+         acr_find_int(group_list, ACR_Nr_of_averages, 1);
+
+      /* Determine if measurement loop was used (rhoge) -
+
+	 if so, we replace the different series numbers with
+	 ACR_Study_time, which is the same for all frames in a run.
+	 This will aid in grouping the files later on.  
+
+	 Criteria used for identification of meast loop:
+
+	 1) more than one dynamic scan
+
+	 2) number of dynamic scans NOT equal to nominal number of signal
+	 averages (if they're equal, we assume acquisition loop scan)
+
+	 WARNING:  it is possible that someone might use the
+	 measurement loop do serial scans which each have multiple signal
+	 averages.  If NSA = the number of measts. in this case, then
+	 the scan will not be recognized as a Meast loop scan and the
+	 different frames will be placed in different series.  To fix
+	 this, we'd really need to look at the series numbers of
+	 future and past files.  It's also unlikely to happen but I'm
+	 sure it will... 
+
+         This also means we should NOT correct the number of signal
+	 averages on the sending side */
+
+
+      /*      if ((number_of_frames > 1) || (*acq_id == 0)) { (orig test) */
+
+      if ( (file_type == N3DCM) &&
+	   (number_of_frames > 1) &&
+	   (number_of_frames != number_of_averages)) { 
+
+         *acq_id = acr_find_int(group_list, ACR_Study_time, 0);
+
+      }
+   }
+   if (rec_num != NULL)
+      *rec_num = 0;
+   if (image_type != NULL)
+      *image_type = 0;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_intensity_info
+@INPUT      : group_list - input data
+@OUTPUT     : file_info - file-specific info
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to get intensity information from a group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_intensity_info(Acr_Group group_list, File_Info *file_info)
+{
+   double window_centre, window_width;
+
+   /* Get pixel storage information */
+   file_info->bits_alloc = acr_find_short(group_list, ACR_Bits_allocated, 0);
+   file_info->bits_stored = acr_find_short(group_list, ACR_Bits_stored, 0);
+
+#ifdef USE_DICOM_PIXEL_MIN_MAX
+
+   // Get pixel value information
+   // I think this might wrongly assume that the ACR values min/max
+   // apply to the whole volume - it actually appears that they apply
+   // to the current slice.
+
+   file_info->pixel_min = 
+     acr_find_short(group_list, ACR_Smallest_pixel_value, 0);
+
+   file_info->pixel_max = acr_find_short(group_list,ACR_Largest_pixel_value, 
+                                         (1 << file_info->bits_stored) - 1);
+
+#else
+
+   // for now, use bits_stored to determine dynamic range
+   // DICOM info on largest pixel applies to first slice, 
+   // not whole volume - this caused problems (roundoff?)
+   // in Siemens Numaris 4 scans
+
+   file_info->pixel_min = 0;
+   file_info->pixel_max = (1 << file_info->bits_stored) - 1;
+
+#endif
+
+   file_info->slice_min = file_info->pixel_min;
+   file_info->slice_max = file_info->pixel_max;
+
+   /* Get window min and max */
+   window_centre = (file_info->slice_max + file_info->slice_min) / 2.0;
+   window_width  = file_info->slice_max - file_info->slice_min;
+   window_centre = 
+      acr_find_double(group_list, ACR_Window_centre, window_centre);
+   window_width = 
+      acr_find_double(group_list, ACR_Window_width, window_width);
+   file_info->window_min = window_centre - window_width / 2.0;
+   file_info->window_max = window_centre + window_width / 2.0; 
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_coordinate_info
+@INPUT      : group_list - input data
+              sizes - size of each spatial dimension
+@OUTPUT     : file_info - file-specific info
+              volume_to_world - volume index to world coordinate index mapping
+              dircos - direction cosines for spatial dimensions
+              steps - step sizes for spatial dimensions
+              starts - start positions for spatial dimensions (for a slice)
+              coordinate - coordinate of centre of slice
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to get coordinate information for a slice from 
+              a group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_coordinate_info(Acr_Group group_list, File_Info *file_info,
+                                Orientation *orientation,
+                                World_Index volume_to_world[VOL_NDIMS],
+                                int sizes[VOL_NDIMS],
+                                double dircos[VOL_NDIMS][WORLD_NDIMS],
+                                double steps[VOL_NDIMS],
+                                double starts[VOL_NDIMS],
+                                double coordinate[WORLD_NDIMS])
+{
+   Volume_Index ivolume;
+   World_Index iworld;
+   Acr_Element_Id dircos_elid[VOL_NDIMS];
+   Acr_Element element;
+   int found_dircos[VOL_NDIMS], found_coordinate;
+   double frame_time, start_time;
+   double magnitude, largest, centre;
+   double darray[2];
+   static Orientation orientation_list[WORLD_NDIMS] = 
+      {SAGITTAL, CORONAL, TRANSVERSE};
+
+   // row/column unit vectors in public dicom element
+   double RowColVec[6];
+
+   if (file_type == N3DCM || file_type == IMA) {
+
+     /* Set direction cosine element ids. Note that the reversal of rows and
+	columns is intentional - their idea of the meaning of theses labels is
+	different from ours. (Their row vector points along the row and not
+	along the row dimension.) */
+     dircos_elid[VSLICE] = SPI_Image_normal;
+     dircos_elid[VROW] = SPI_Image_column;
+     dircos_elid[VCOLUMN] = SPI_Image_row;
+     
+     // Get direction cosines
+     for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+       found_dircos[ivolume] = FALSE;
+       element = acr_find_group_element(group_list, dircos_elid[ivolume]);
+       if (element == NULL) continue;
+       if (acr_get_element_numeric_array(element, WORLD_NDIMS, dircos[ivolume])
+	   != WORLD_NDIMS) continue;
+       // negate the X and Z coordinates
+       convert_numa3_coordinate(dircos[ivolume]);
+       found_dircos[ivolume] = TRUE;
+     }
+   } else {
+     // in normal dicom file, you just have row and column unit vectors
+     
+     // read in row/col vectors:
+     element = acr_find_group_element(group_list,
+				      ACR_Image_orientation_patient);
+     
+     acr_get_element_numeric_array(element, 6, RowColVec);
+
+     memcpy(dircos[VCOLUMN],RowColVec,sizeof(RowColVec[0])*3);
+     memcpy(dircos[VROW],&RowColVec[3],sizeof(RowColVec[0])*3);
+     found_dircos[VCOLUMN] = TRUE;
+     found_dircos[VROW] = TRUE;
+
+     convert_dicom_coordinate(dircos[VROW]);
+     convert_dicom_coordinate(dircos[VCOLUMN]);
+
+     // slice direction unit vector is cross product of row, col vectors:
+     dircos[VSLICE][0] = 
+       dircos[VCOLUMN][1] * dircos[VROW][2] -
+       dircos[VCOLUMN][2] * dircos[VROW][1];
+
+     dircos[VSLICE][1] = 
+       dircos[VCOLUMN][2] * dircos[VROW][0] -
+       dircos[VCOLUMN][0] * dircos[VROW][2];
+
+     dircos[VSLICE][2] = 
+       dircos[VCOLUMN][0] * dircos[VROW][1] -
+       dircos[VCOLUMN][1] * dircos[VROW][0];
+     found_dircos[VSLICE] = TRUE;
+
+     // slice does not need to be converted because 
+     // it was computed as the cross product of two
+     // corrected vectors
+     // convert_dicom_coordinate(dircos[VSLICE]);
+
+   }
+
+   // Normalize the direction cosines
+   for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+      magnitude = 0.0;
+      for (iworld=0; iworld < WORLD_NDIMS; iworld++) {
+         magnitude += dircos[ivolume][iworld] * dircos[ivolume][iworld];
+      }
+      if (magnitude <= 0) {
+         found_dircos[ivolume] = FALSE;
+         continue;
+      }
+      magnitude = sqrt(magnitude);
+      for (iworld=0; iworld < WORLD_NDIMS; iworld++) {
+         dircos[ivolume][iworld] /= magnitude;
+      }
+   }
+
+   // If we don't find direction cosines, then assume transverse volume
+   if (!found_dircos[VSLICE] || !found_dircos[VROW] || 
+       !found_dircos[VCOLUMN]) {
+      for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+         for (iworld=0; iworld < WORLD_NDIMS; iworld++) {
+            dircos[ivolume][iworld] = 
+               ((ivolume == (WORLD_NDIMS-iworld-1)) ? -1.0 : 0.0);
+         }
+      }
+   }
+
+   // Figure out volume index to world index mapping and sign of direction
+   // cosines - the code below figures out the primary direction in x,y,z
+   // of each volume coordinate (row,col,slice)
+   for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+      largest = -1.0;
+      for (iworld=0; iworld < WORLD_NDIMS; iworld++) {
+         magnitude = dircos[ivolume][iworld];
+         if (magnitude < 0.0) magnitude = -magnitude;
+         if (magnitude > largest) {
+            largest = magnitude;
+            volume_to_world[ivolume] = iworld;
+         }
+      }
+   }
+
+   // Get orientation (depends on primary direction of slice normal)
+   *orientation = orientation_list[volume_to_world[VSLICE]];
+
+   // Get step information
+   for (ivolume=0; ivolume < sizeof(darray)/sizeof(darray[0]); ivolume++)
+      darray[ivolume] = -DBL_MAX;
+   // note ACR_Pixel_size should now be called Pixel_spacing
+   element = acr_find_group_element(group_list, ACR_Pixel_size);
+   if (element != NULL)
+      (void) acr_get_element_numeric_array(element, 
+         sizeof(darray)/sizeof(darray[0]), darray);
+   if (darray[0] == -DBL_MAX) darray[0] = 1.0;
+   if (darray[1] == -DBL_MAX) darray[1] = darray[0];
+   steps[VCOLUMN] = darray[0];
+   steps[VROW] = darray[1];  // anisotropic resolution?
+
+   // steps[VSLICE] = acr_find_double(group_list, ACR_Slice_thickness, 1.0);
+   steps[VSLICE] = acr_find_double(group_list,ACR_Spacing_between_slices,1.0);
+
+   /* Make sure that direction cosines point the right way (dot product
+      of direction cosine and axis is positive) and that step has proper
+      sign */
+   for (ivolume = 0; ivolume < VOL_NDIMS; ivolume++) {
+      iworld = volume_to_world[ivolume];
+      if (dircos[ivolume][iworld] < 0.0) {
+         steps[ivolume] *= -1.0;
+         for (iworld = 0; iworld < WORLD_NDIMS; iworld++) {
+            dircos[ivolume][iworld] *= -1.0;
+         }
+      }
+   }
+
+   if (file_type == N3DCM || file_type == IMA) {
+
+     // Find 3D coordinate of slice - SPI_Image_position gives
+     // the *centre* of the slice!
+     element = acr_find_group_element(group_list, SPI_Image_position);
+     if ((element == NULL) ||
+	 (acr_get_element_numeric_array(element, WORLD_NDIMS, coordinate) 
+	  != WORLD_NDIMS)) {
+       found_coordinate = FALSE;
+       for (iworld=0; iworld < WORLD_NDIMS; iworld++)
+         coordinate[iworld] = 0.0;
+     } else {
+       found_coordinate = TRUE;
+     }
+     
+     convert_numa3_coordinate(coordinate);
+     
+     // Work out start positions in volume coordinates
+     for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+       
+       if (found_coordinate && found_dircos[VSLICE] && found_dircos[VROW] &&
+	   found_dircos[VCOLUMN]) {
+         centre = 
+	   coordinate[XCOORD] * dircos[ivolume][XCOORD] +
+	   coordinate[YCOORD] * dircos[ivolume][YCOORD] +
+	   coordinate[ZCOORD] * dircos[ivolume][ZCOORD];
+       }
+       else {
+         centre = 0.0;
+       }
+       starts[ivolume] = centre -
+	 (steps[ivolume] * (sizes[ivolume] - 1.0) / 2.0);
+     }
+     
+   } else { // normal dicom
+     
+     // Find 3D coordinate of slice - ACR_Image_position_patient gives
+     // the *corner* of the slice!
+     element = acr_find_group_element(group_list, ACR_Image_position_patient);
+     if ((element == NULL) ||
+	 (acr_get_element_numeric_array(element, WORLD_NDIMS, coordinate) 
+	  != WORLD_NDIMS)) {
+       found_coordinate = FALSE;
+       for (iworld=0; iworld < WORLD_NDIMS; iworld++)
+         coordinate[iworld] = 0.0;
+     } else {
+       found_coordinate = TRUE;
+     }
+     
+     convert_dicom_coordinate(coordinate);
+
+     // Work out start positions in volume coordinates
+     for (ivolume=0; ivolume < VOL_NDIMS; ivolume++) {
+       
+       if (found_coordinate && found_dircos[VSLICE] && found_dircos[VROW] &&
+	   found_dircos[VCOLUMN]) {
+	 starts[ivolume] = 
+	   coordinate[XCOORD] * dircos[ivolume][XCOORD] +
+	   coordinate[YCOORD] * dircos[ivolume][YCOORD] +
+	   coordinate[ZCOORD] * dircos[ivolume][ZCOORD];
+       }
+       else {
+	 starts[ivolume] = 0.0;
+       }
+     }
+
+   }
+
+   // Find position along each dimension
+   file_info->coordinate[SLICE] = starts[VSLICE];
+   file_info->coordinate[ECHO] = 
+      acr_find_double(group_list, ACR_Echo_time, 0.0) / (double) MS_PER_SECOND;
+
+   // time section (rhoge)
+   // now assume that time has been fixed when file was read
+
+   start_time = acr_find_double(group_list,ACR_Series_time, 0.0);
+   frame_time = 
+     acr_find_double(group_list, ACR_Acquisition_time, 0.0); 
+   start_time = convert_time_to_seconds(start_time);
+   frame_time = convert_time_to_seconds(frame_time) - start_time;
+
+   // check for case where scan starts right before midnight,
+   // but frame is after midnight
+   if (frame_time < 0.0) frame_time += (double) SECONDS_PER_DAY;
+   file_info->coordinate[TIME] = frame_time;
+
+   /* end of time section */
+
+   file_info->coordinate[PHASE] = 0.0;
+   file_info->coordinate[CHEM_SHIFT] = 0.0;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : convert_numa3_coordinate
+@INPUT      : coordinate
+@OUTPUT     : coordinate
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to convert a coordinate to the correct orientation
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : made version specific to Numaris 3 SPI data (rhoge)
+---------------------------------------------------------------------------- */
+public void convert_numa3_coordinate(double coordinate[WORLD_NDIMS])
+{
+  coordinate[XCOORD] = -coordinate[XCOORD];
+  coordinate[ZCOORD] = -coordinate[ZCOORD];
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : convert_dicom_coordinate
+@INPUT      : coordinate
+@OUTPUT     : coordinate
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to convert a coordinate to the correct orientation
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : made new dicom version (rhoge)
+---------------------------------------------------------------------------- */
+public void convert_dicom_coordinate(double coordinate[WORLD_NDIMS])
+{
+   coordinate[XCOORD] = -coordinate[XCOORD];
+   coordinate[YCOORD] = -coordinate[YCOORD];
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_general_header_info
+@INPUT      : group_list - input data
+@OUTPUT     : general_info - general information about files
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to extract general header information from a group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_general_header_info(Acr_Group group_list, 
+                                    General_Info *general_info)
+{
+   int maxlen, length;
+   char *string, *ptr;
+
+   /* Maximum length for strings */
+   maxlen = sizeof(Cstring) - 1;
+
+   /* Get intensity units */
+   (void) strncpy(general_info->units, "", maxlen);
+
+   /* Get patient info */
+   (void) strncpy(general_info->patient.name,
+                  acr_find_string(group_list, ACR_Patient_name, ""), maxlen);
+   (void) strncpy(general_info->patient.identification,
+      acr_find_string(group_list, ACR_Patient_identification, ""), maxlen);
+   (void) strncpy(general_info->patient.birth_date,
+      acr_find_string(group_list, ACR_Patient_birth_date, ""), maxlen);
+   (void) strncpy(general_info->patient.age,
+      acr_find_string(group_list, ACR_Patient_age, ""), maxlen);
+   string = acr_find_string(group_list, ACR_Patient_sex, "");
+   if (*string == 'M') 
+      (void) strncpy(general_info->patient.sex, MI_MALE, maxlen);
+   else if (*string == 'F') 
+      (void) strncpy(general_info->patient.sex, MI_FEMALE, maxlen);
+   else if (*string == 'O') 
+      (void) strncpy(general_info->patient.sex, MI_OTHER, maxlen);
+   else 
+      (void) strncpy(general_info->patient.sex, "", maxlen);
+   general_info->patient.weight = 
+      acr_find_double(group_list, ACR_Patient_weight, -DBL_MAX);
+   /* added by rhoge - registration timing info */
+   (void) strncpy(general_info->patient.reg_date,
+      acr_find_string(group_list, ACR_Study_date, ""), maxlen);
+   (void) strncpy(general_info->patient.reg_time, 
+      acr_find_string(group_list, ACR_Study_time, ""), maxlen);
+
+   /* Get study info */
+   (void) strncpy(general_info->study.start_time, 
+      acr_find_string(group_list, ACR_Study_date, ""), maxlen - 1);
+   length = strlen(general_info->study.start_time);
+   general_info->study.start_time[length] = ' ';
+   length++;
+   (void) strncpy(&general_info->study.start_time[length], 
+      acr_find_string(group_list, ACR_Study_time, ""), maxlen - length);
+   string = acr_find_string(group_list, ACR_Modality, "");
+   if (strcmp(string, ACR_MODALITY_MR) == 0)
+      (void) strncpy(general_info->study.modality, MI_MRI, maxlen);
+   (void) strncpy(general_info->study.manufacturer, 
+      acr_find_string(group_list, ACR_Manufacturer, ""), maxlen);
+   (void) strncpy(general_info->study.model, 
+      acr_find_string(group_list, ACR_Manufacturer_model, ""), maxlen);
+   general_info->study.field_value = 
+      acr_find_double(group_list, ACR_Magnetic_field_strength, -DBL_MAX);
+   (void) strncpy(general_info->study.software_version, 
+      acr_find_string(group_list, ACR_Software_versions, ""), maxlen);
+   (void) strncpy(general_info->study.serial_no, 
+      acr_find_string(group_list, ACR_Device_serial_number, ""), maxlen);
+   (void) strncpy(general_info->study.calibration_date, 
+      acr_find_string(group_list, SPI_Calibration_date, ""), maxlen);
+   (void) strncpy(general_info->study.institution, 
+      acr_find_string(group_list, ACR_Institution_id, ""), maxlen);
+   (void) strncpy(general_info->study.station_id, 
+      acr_find_string(group_list, ACR_Station_id, ""), maxlen);
+   (void) strncpy(general_info->study.referring_physician, 
+      acr_find_string(group_list, ACR_Referring_physician, ""), maxlen);
+   (void) strncpy(general_info->study.performing_physician, 
+      acr_find_string(group_list, ACR_Performing_physician, ""), maxlen);
+   (void) strncpy(general_info->study.operator, 
+      acr_find_string(group_list, ACR_Operators_name, ""), maxlen);
+   (void) strncpy(general_info->study.procedure, 
+      acr_find_string(group_list, ACR_Procedure_description, ""), maxlen);
+   (void) sprintf(general_info->study.study_id, "%.6f",general_info->study_id);
+   /*   acquisition id modified by rhoge to get rid of first digit that 
+	is not required for identification of run */
+   /*   (void) sprintf(general_info->study.acquisition_id, "%d_%d",
+	acr_find_int(group_list, ACR_Series, 0), general_info->acq_id); */
+   (void) sprintf(general_info->study.acquisition_id, "%d",
+		  general_info->acq_id);
+
+   /* Get acquisition information */
+   /*   string = acr_find_string(group_list, SPI_Sequence_file_name, "");
+	ptr = string + strlen(string) - 1;
+	while ((ptr > string) && (*ptr != '/')) {ptr--;}
+	if ((ptr >= string) && (*ptr == '/')) string = ptr + 1;
+	(void) strncpy(general_info->acq.scan_seq, string, maxlen);
+	ptr = general_info->acq.scan_seq;
+	while (*ptr != '\0') {
+	if (*ptr == '.') *ptr = '\0';
+	ptr++;
+	} */
+
+   (void) strncpy(general_info->acq.scan_seq, 
+      acr_find_string(group_list, ACR_Sequence_name, ""), maxlen);
+   (void) strncpy(general_info->acq.seq_owner, 
+      acr_find_string(group_list, SPI_Sequence_file_owner, ""), maxlen);
+   (void) strncpy(general_info->acq.seq_descr, 
+      acr_find_string(group_list, SPI_Sequence_description, ""), maxlen);
+   (void) strncpy(general_info->acq.protocol_name, 
+      acr_find_string(group_list, ACR_Protocol_name, ""), maxlen);
+   (void) strncpy(general_info->acq.receive_coil, 
+      acr_find_string(group_list, ACR_Receiving_coil, ""), maxlen);
+   (void) strncpy(general_info->acq.transmit_coil, 
+      acr_find_string(group_list, ACR_Transmitting_coil, ""), maxlen);
+   general_info->acq.rep_time = 
+      acr_find_double(group_list, ACR_Repetition_time, -DBL_MAX);
+   if (general_info->acq.rep_time != -DBL_MAX)
+      general_info->acq.rep_time /= 1000.0;
+   general_info->acq.echo_time = 
+      acr_find_double(group_list, ACR_Echo_time, -DBL_MAX);
+   if (general_info->acq.echo_time != -DBL_MAX)
+      general_info->acq.echo_time /= 1000.0;
+   general_info->acq.echo_number = 
+      acr_find_double(group_list, ACR_Echo_number, -DBL_MAX);
+   general_info->acq.inv_time = 
+      acr_find_double(group_list, ACR_Inversion_time, -DBL_MAX);
+   if (general_info->acq.inv_time != -DBL_MAX)
+      general_info->acq.inv_time /= 1000.0;
+   general_info->acq.b_value = 
+      acr_find_double(group_list, EXT_Diffusion_b_value, -DBL_MAX);
+   general_info->acq.flip_angle = 
+      acr_find_double(group_list, ACR_Flip_angle, -DBL_MAX);
+   general_info->acq.slice_thickness = 
+      acr_find_double(group_list, ACR_Slice_thickness, -DBL_MAX);
+   general_info->acq.num_slices = 
+      acr_find_double(group_list, SPI_Number_of_slices_nominal, -DBL_MAX);
+   general_info->acq.num_dyn_scans = 
+      acr_find_double(group_list, ACR_Acquisitions_in_series, -DBL_MAX);
+   general_info->acq.num_avg = 
+      acr_find_double(group_list, ACR_Nr_of_averages, -DBL_MAX);
+   general_info->acq.scan_dur = 
+      acr_find_double(group_list, SPI_Total_measurement_time_cur, -DBL_MAX);
+   general_info->acq.ky_lines = 
+      acr_find_double(group_list, SPI_Number_of_fourier_lines_current, 
+		      -DBL_MAX);
+   general_info->acq.kymax_ix = 
+      acr_find_double(group_list, SPI_Number_of_fourier_lines_after_zero, 
+		      -DBL_MAX);
+   general_info->acq.kymin_ix = 
+      acr_find_double(group_list, SPI_First_measured_fourier_line, 
+		      -DBL_MAX);
+   general_info->acq.kz_lines = 
+      acr_find_double(group_list, SPI_Number_of_3d_raw_part_cur, 
+		      -DBL_MAX);
+   general_info->acq.dummy_scans = 
+      acr_find_double(group_list, SPI_Number_of_prescans, 
+		      -DBL_MAX);
+   general_info->acq.imaging_freq = 
+      acr_find_double(group_list, ACR_Imaging_frequency, -DBL_MAX);
+   if (general_info->acq.imaging_freq != -DBL_MAX)
+      general_info->acq.imaging_freq *= 1e6;
+   (void) strncpy(general_info->acq.imaged_nucl,
+      acr_find_string(group_list, ACR_Imaged_nucleus, ""), maxlen);
+   general_info->acq.adc_voltage = 
+      acr_find_double(group_list, SPI_ADC_voltage, -DBL_MAX);
+   general_info->acq.adc_offset = 
+      acr_find_double(group_list, SPI_ADC_offset, -DBL_MAX);
+   general_info->acq.transmit_ampl = 
+      acr_find_double(group_list, SPI_Transmitter_amplitude, -DBL_MAX);
+   general_info->acq.rec_amp_gain = 
+      acr_find_double(group_list, SPI_Receiver_amplifier_gain, -DBL_MAX);
+   general_info->acq.rec_preamp_gain = 
+      acr_find_double(group_list, SPI_Receiver_preamplifier_gain, -DBL_MAX);
+   general_info->acq.win_center = 
+      acr_find_double(group_list, SPI_Window_center, -DBL_MAX);
+   general_info->acq.win_width = 
+      acr_find_double(group_list, SPI_Window_width, -DBL_MAX);
+   general_info->acq.gy_ampl = 
+      acr_find_double(group_list, SPI_Phase_gradient_amplitude, -DBL_MAX);
+   general_info->acq.gx_ampl = 
+      acr_find_double(group_list, SPI_Readout_gradient_amplitude, -DBL_MAX);
+   general_info->acq.gz_ampl = 
+     acr_find_double(group_list, SPI_Selection_gradient_amplitude, -DBL_MAX);
+
+   general_info->acq.num_phase_enc_steps = 
+     acr_find_double(group_list, ACR_Number_of_phase_encoding_steps, -DBL_MAX);
+   general_info->acq.percent_sampling = 100 * 
+     acr_find_double(group_list, ACR_Percent_sampling, -DBL_MAX);
+   general_info->acq.percent_phase_fov = 100 *
+     acr_find_double(group_list, ACR_Percent_phase_field_of_view, -DBL_MAX);
+   general_info->acq.pixel_bandwidth = 
+     acr_find_double(group_list, ACR_Pixel_bandwidth, -DBL_MAX);
+   general_info->acq.sar = 
+     acr_find_double(group_list, ACR_SAR, -DBL_MAX);
+   strncpy(general_info->acq.mr_acq_type,
+	   acr_find_string(group_list,ACR_MR_acquisition_type,""),4);
+   strncpy(general_info->acq.image_type,
+	   acr_find_string(group_list,ACR_Image_type,""),128);
+
+   strncpy(general_info->acq.phase_enc_dir, 
+	   acr_find_string(group_list,ACR_Phase_encoding_direction,""),3);
+   (void) strncpy(general_info->acq.comments, "", maxlen);
+   // Siemens Numaris 4 specific!
+
+   if (0) { // this causes problems with large MrProt fields
+     //     printf("allocating %d bytes for MrProt...\n",
+     //	    strlen(acr_find_string(group_list, EXT_MrProt_dump, "")));
+     general_info->acq.MrProt =
+       MALLOC(strlen(acr_find_string(group_list, EXT_MrProt_dump, "")) * 
+	      sizeof(char));
+     (void) strcpy(general_info->acq.MrProt, 
+		   acr_find_string(group_list, EXT_MrProt_dump, ""));
+   } else {
+     general_info->acq.MrProt =
+       MALLOC(strlen("disabled")*sizeof(char));
+     (void) strcpy(general_info->acq.MrProt, "disabled");
+   }
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : convert_time_to_seconds
+@INPUT      : dicom_time
+@OUTPUT     : (none)
+@RETURNS    : real time in seconds from beginning of day
+@DESCRIPTION: Routine to convert dicom seconds (decimal hhmmss.xxxxx) to 
+              real seconds since the start of day.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public double convert_time_to_seconds(double dicom_time)
+{
+   /* Constants */
+#define DICOM_SECONDS_PER_HOUR 10000.0
+#define DICOM_SECONDS_PER_MINUTE 100.0
+
+  /* Variables */
+  double real_time, Hours, Minutes, Seconds;
+
+  /* Get the components of the time */
+
+  Hours = (int) (dicom_time / (double) DICOM_SECONDS_PER_HOUR);
+  dicom_time -= Hours * DICOM_SECONDS_PER_HOUR;
+  Minutes = (int) (dicom_time / (double) DICOM_SECONDS_PER_MINUTE);
+  dicom_time -= Minutes * (double) DICOM_SECONDS_PER_MINUTE;
+  Seconds = dicom_time;
+
+  /* Work out the number of seconds */
+
+  real_time = (Hours * 3600.0) + (Minutes * 60.0) + Seconds;
+
+  return real_time;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_siemens_dicom_image
+@INPUT      : group_list - input data
+@OUTPUT     : image - image data structure (user must free data)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to get an image from a group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 25, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void get_siemens_dicom_image(Acr_Group group_list, Image_Data *image)
+{
+
+   /* Variables */
+   Acr_Element element;
+   int nrows, ncolumns;
+   int bits_alloc;
+   int bits_stored;
+   int image_group;
+   void *data = NULL;
+   long imagepix, ipix;
+   struct Acr_Element_Id elid;
+   nc_type datatype;
+
+   /* Get the image information */
+   bits_alloc = acr_find_short(group_list, ACR_Bits_allocated, 0);
+   bits_stored = acr_find_short(group_list, ACR_Bits_stored, bits_alloc);
+   nrows = acr_find_short(group_list, ACR_Rows, 0);
+   ncolumns = acr_find_short(group_list, ACR_Columns, 0);
+   image_group = acr_find_short(group_list, ACR_Image_location, 
+   				ACR_ACTUAL_IMAGE_GID);
+
+   /* Figure out type */
+   if (bits_alloc > CHAR_BIT)
+      datatype = NC_SHORT;
+   else 
+      datatype = NC_BYTE;
+
+   /* Set image info */
+   image->nrows = nrows;
+   image->ncolumns = ncolumns;
+   imagepix = nrows * ncolumns;
+   image->data = (unsigned short *) MALLOC(imagepix * sizeof(short));
+   image->free = TRUE;
+
+   /* Get image pointer */
+   elid.group_id = image_group;
+   elid.element_id = SPI_IMAGE_ELEMENT;
+   element = acr_find_group_element(group_list, &elid);
+   if (element == NULL) {
+      (void) memset(image->data, 0, imagepix * sizeof(short));
+      return;
+   }
+   data = acr_get_element_data(element);
+
+   /* Convert the data according to type */
+
+   /* Look for byte data */
+   if (datatype == NC_BYTE) {
+      for (ipix=0; ipix < imagepix; ipix++) {
+         image->data[ipix] = *((unsigned char *) data + ipix);
+      }
+   }
+   else {
+
+      /* Look for unpacked short data */
+      if (bits_alloc == nctypelen(datatype) * CHAR_BIT) {
+         acr_get_short(acr_get_element_byte_order(element), 
+                       nrows*ncolumns, data, image->data);
+      }
+
+      /* Fill with zeros in any other case */
+      else {
+         (void) memset(image->data, 0, imagepix * sizeof(short));
+      }
+   }
+
+   return;
+}
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_dicom_send.c
@@ -0,0 +1,1404 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_dicom_send.c
+@DESCRIPTION: Program to convert siemens vision internal format files to
+              dicom and send them to a remote server.
+@METHOD     : 
+@GLOBALS    : 
+@CREATED    : July 8, 1997 (Peter Neelin) re-write by Rick Hoge
+@MODIFIED   : $Log: siemens_dicom_send.c,v $
+@MODIFIED   : Revision 1.1  2003-08-15 19:52:55  leili
+@MODIFIED   : Initial revision
+@MODIFIED   :
+@MODIFIED   : Revision 1.9  2001/10/19 13:08:39  rhoge
+@MODIFIED   : - fixed problem for single slice acq loop scans in siemens_dicom_send
+@MODIFIED   : - added diffusion pulse seq in ima2mnc, restored hard-coded path
+@MODIFIED   :
+@MODIFIED   : Revision 1.8  2001/04/19 19:33:10  rhoge
+@MODIFIED   : added multi-echo support, basic testing.  Changed TEST to MYDEBUG
+@MODIFIED   :
+@MODIFIED   : Revision 1.7  2000/12/17 01:04:40  rhoge
+@MODIFIED   : clean up log format
+@MODIFIED   :
+@MODIFIED   : Revision 1.6  2000/12/17 01:02:58  rhoge
+@MODIFIED   : Made some debugging statements conditional on TEST macro, 
+@MODIFIED   : in course of changes to restore Sun function after 
+@MODIFIED   : byte-aligmnent fixes (padding) for Linux port
+@MODIFIED   :
+@MODIFIED   : Revision 1.5  2000/12/14 22:56:40  rhoge
+@MODIFIED   : removed DBL_MAX - not defined on sun (replaced with 1.0 in
+@MODIFIED   : acr_find_double, line 502)
+@MODIFIED   :
+@MODIFIED   : Revision 1.4  2000/12/11 20:04:35  rhoge
+@MODIFIED   : got rid of printf statements for time correction
+@MODIFIED   :
+@MODIFIED   : Revision 1.3  2000/12/11 19:27:25  rhoge
+@MODIFIED   : fix for leading zeros if hms less than two digits in time
+@MODIFIED   :
+@MODIFIED   : Revision 1.2  2000/12/11 17:43:01  rhoge
+@MODIFIED   : added frame time correction - code compiles and runs, but order
+@MODIFIED   : problem may not yet be fixed
+@MODIFIED   :
+@MODIFIED   : Revision 1.1.1.1  2000/11/30 02:05:54  rhoge
+@MODIFIED   : imported sources to CVS repository on amoeba
+@MODIFIED   :
+ *
+ * Revision 1.9  1999/08/03  17:42:55  neelin
+ * Added ability to handle multiple input directories.
+ *
+ * Revision 1.8  1998/11/17  16:13:29  neelin
+ * Changes to log messages to ensure that 100 percent is only displayed
+ * when transfer is complete.
+ *
+ * Revision 1.7  1998/11/17  14:49:22  neelin
+ * Modified help comment.
+ *
+ * Revision 1.6  1998/11/17  14:00:12  neelin
+ * Changed logging to print percentage with overstrike for terminals.
+ *
+ * Revision 1.5  1998/11/16  19:48:43  neelin
+ * Added support for breaking up mosaic images and sending the pieces one
+ * at a time.
+ *
+ * Revision 1.4  1998/11/13  16:02:09  neelin
+ * Modifications to support packed images and asynchronous transfer.
+ *
+ * Revision 1.3  1998/02/20  17:37:55  neelin
+ * Removed debugging statements.
+ *
+ * Revision 1.2  1997/11/04  14:31:30  neelin
+ * *** empty log message ***
+ *
+ * Revision 1.1  1997/08/11  12:50:53  neelin
+ * Initial revision
+ *
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/siemens_dicom_send.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <stdio.h>
+#include <math.h> /* for slice position hacks */
+#include <stdlib.h>
+#include <limits.h>
+#include <dirent.h>
+#include <string.h>
+#include <malloc.h>
+#include <ParseArgv.h>
+
+#include <acr_nema.h>
+#include <dicom_client_routines.h>
+
+/* Constants */
+#ifndef public
+#  define public
+#endif
+#ifndef private
+#  define private static
+#endif
+#ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define EXIT_FAILURE 1
+#endif
+#define ALLOC_INCREMENT 100
+#define LOG_PERCENT (2.0)
+
+/* Dicom definitions */
+#define ACR_MR_IMAGE_STORAGE_UID       "1.2.840.10008.5.1.4.1.1.4"
+#define ACR_IMPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2"
+#define ACR_EXPLICIT_VR_LITTLE_END_UID "1.2.840.10008.1.2.1"
+#define ACR_EXPLICIT_VR_BIG_END_UID    "1.2.840.10008.1.2.2"
+#define MY_AE_TITLE "MGH_CLIENT"
+
+/* rhoge: debugging definitions */
+/* #define MYDEBUG */
+
+/* Define element id's */
+
+DEFINE_ELEMENT(static, ACR_Slice_thickness            , 0x0018, 0x0050, DS);
+DEFINE_ELEMENT(static, ACR_Rows                       , 0x0028, 0x0010, US);
+DEFINE_ELEMENT(static, ACR_Columns                    , 0x0028, 0x0011, US);
+DEFINE_ELEMENT(static, ACR_Pixel_size                 , 0x0028, 0x0030, DS);
+DEFINE_ELEMENT(static, ACR_Bits_allocated             , 0x0028, 0x0100, US);
+DEFINE_ELEMENT(static, ACR_Image                      , 0x7fe0, 0x0010, OW);
+
+DEFINE_ELEMENT(static, SPI_Sequence_File_Name         , 0x0019, 0x1511, LT);
+DEFINE_ELEMENT(static, SPI_Image_position             , 0x0021, 0x1160, DS);
+DEFINE_ELEMENT(static, SPI_Image_normal               , 0x0021, 0x1161, DS);
+DEFINE_ELEMENT(static, SPI_Image_distance             , 0x0021, 0x1163, DS);
+DEFINE_ELEMENT(static, SPI_Current_slice_number       , 0x0021, 0x1342, IS);
+DEFINE_ELEMENT(static, SPI_Slice_distance_factor      , 0x0021, 0x1344, DS);
+
+/* added by rhoge for acquisition loop with mosaic overflow
+ * note:  on the Sonata, {acquisition,run,series,scan} is called 
+ * Study in the header! beware of confusion... */
+
+DEFINE_ELEMENT(static, ACR_Study                      , 0x0020, 0x0010, IS);
+DEFINE_ELEMENT(static, ACR_Series                     , 0x0020, 0x0011, IS);
+DEFINE_ELEMENT(static, ACR_Acquisitions_in_series     , 0x0020, 0x1001, IS);
+DEFINE_ELEMENT(static, ACR_Echo_number                , 0x0018, 0x0086, IS);
+
+DEFINE_ELEMENT(static, SPI_Number_of_averages         , 0x0018, 0x0083, DS);
+DEFINE_ELEMENT(static, SPI_Number_of_slices_nom       , 0x0021, 0x1340, IS);
+DEFINE_ELEMENT(static, SPI_Number_of_slices_cur       , 0x0021, 0x1341, IS);
+DEFINE_ELEMENT(static, SPI_Number_of_fourier_lines_nominal,0x0019, 0x1220, IS);
+DEFINE_ELEMENT(static, SPI_Number_of_echoes           , 0x0021, 0x1370, IS);
+
+DEFINE_ELEMENT(static, ACR_Study_time            , 0x0008, 0x0030, TM);
+DEFINE_ELEMENT(static, ACR_Repetition_time       , 0x0018, 0x0080, DS);
+DEFINE_ELEMENT(static, ACR_Acquisition_time      , 0x0008, 0x0032, TM);
+
+/* Typedefs */
+typedef struct {
+   int key;
+   char *name;
+   int dirindex;
+} Sort_entry;
+
+typedef struct {
+   int packed;
+   int mosaic_seq;
+   int size[2];
+   int big[2];
+   int grid[2];
+   int pixel_size;
+   Acr_Element big_image;
+   Acr_Element small_image;
+   int sub_images;
+   int first_image;
+   double normal[3];
+   double step[3];
+   double position[3];
+} Multi_Image;
+
+typedef struct Mosaic_Info {
+   char *match_string;
+   int size[2];
+   struct Mosaic_Info *next;
+} *Mosaic_Info;
+
+/* Function prototypes */
+public Acr_Group siemens_to_dicom(char *filename, int read_image);
+public void update_coordinate_info(Acr_Group group_list);
+public int process_mosaic_args(char *dst, char *key, int argc, char **argv);
+public Mosaic_Info get_mosaic_info(Mosaic_Info mosaic_info_list, 
+                                   char *protocol);
+public int get_directory(char *dst, char *key, char *nextarg);
+public void get_file_names(int num_dirs, char **directory_list, 
+                           int patient_number,
+                           int first_image, int last_image,
+                           int *num_files, char ***file_list,
+                           int **file_dirindex_list);
+private int sort_function(const void *entry1, const void *entry2);
+public void free_file_names(char *fullpath, char *file_list[], int num_files);
+public int multi_image_init(Acr_Group group_list, 
+                            Multi_Image *multi_image);
+public void multi_image_modify_group_list(Acr_Group group_list, 
+                                          Multi_Image *multi_image,
+                                          int iimage);
+public void multi_image_cleanup(Acr_Group group_list, 
+                                Multi_Image *multi_image);
+
+/* Variables for argument parsing */
+Mosaic_Info mosaic_info_list = NULL;
+int max_outstanding = 10;
+char **directory_list = NULL;
+int num_dirs = 0;
+int num_dirs_alloc = 0;
+
+/* Argument table */
+ArgvInfo argTable[] = {
+   {"-mosaic", ARGV_GENFUNC, (char *) process_mosaic_args, 
+       (char *) &mosaic_info_list,
+       "Add a mosaic protocol and subimage size to the list.\n"
+"\tUsage: -mosaic <protocol string> <m> <n>\n"
+"\tIf the protocol name begins with a /, then an exact match is done.\n"
+"\tIf it contains an extension, then a match on filename alone is done.\n"
+"\tOtherwise, a prefix match is done.\n"
+"\tParent directories can be specified for a prefix match.\n"
+"\tExamples:\n"
+"\t\t-mosaic /home/user/protcols/mosaic/myproto64_version1.ekc 64 64\n"
+"\t\t-mosaic myproto64 64 64\n"
+"\t\t-mosaic myproto64_version1.ekc 64 64\n"
+"\t\t-mosaic mosaic/myproto64_ 64 64\n"
+"\t\t-mosaic mosaic/myproto64_version1.ekc 64 64\n"
+"\t\t-mosaic mosaic/ 64 64\n"
+ },
+   {"-directory", ARGV_FUNC, (char *) get_directory, (char *) NULL,
+       "Specify a directory to search (instead of positional option)."},
+   {"-max_outstanding", ARGV_INT, (char *) 1, (char *) &max_outstanding,
+       "Specify max outstanding replies for asynchronous transfer."},
+   {(char *) NULL, ARGV_END, (char *) NULL, (char *) NULL,
+       (char *) NULL}
+};
+
+/* Main program */
+
+int main(int argc, char *argv[])
+{
+   Acr_Group group_list;
+   char *pname;
+   char *host;
+   char *port;
+   char *AEtitle;
+   int  iarg;
+   int  patient_number;
+   int  first_image;
+   int  last_image;
+   char **file_list;
+   int *file_dirindex_list;
+   int ifile, num_files, idir;
+   Acr_File *afpin, *afpout;
+   char *fullpath;
+   int maxlength, maxdirlength, len;
+   int iimage;
+   Multi_Image multi_image;
+   char *log_separator;
+   int needed_args;
+
+   /* stuff added by rhoge for acquisition loop with mosaic overflow */
+
+   int idim;
+   int imosaic;
+   int iecho;
+   int num_mosaics;
+   int acqframe;
+   int num_acqframes;
+   int num_echos;
+   int echo;
+   int num_slices;
+   int num_sub_images;
+   int nimages;
+   int num_special_files;
+   int num_mosaic_elements;
+   double top_slice_position[3];
+   int current_series;
+   int current_slice_index;
+   double scan_start_time;
+   double start_time_sec;
+   double start_hours;
+   double start_minutes;
+   double start_seconds;
+   double frame_hours;
+   double frame_minutes;
+   double frame_seconds;
+   double frame_hours_oflow;
+   double frame_minutes_oflow;
+   double frame_seconds_oflow;
+   double rel_frame_time_sec;
+   double abs_frame_time_sec;
+   char   abs_frame_time_hms[100];
+   
+
+   /* Check arguments. */
+   /* Ugly hack here to keep backwards compatibility, but also allow -directory
+      specification. needed_args stores the minimum number of args needed,
+      depending on whether the -directory option was specified. */
+   pname = argv[0];
+   if (ParseArgv(&argc, argv, argTable, 0) || 
+       (argc < (needed_args = (directory_list == NULL ? 6:5))) || 
+       (argc > needed_args+2)) {
+      (void) fprintf(stderr, 
+         "Usage: %s host port AEtitle [directory] patient_num [first [last]]\n", 
+                     pname);
+      return EXIT_FAILURE;
+   }
+   iarg=1;
+   host = argv[iarg++];
+   port = argv[iarg++];
+   AEtitle = argv[iarg++];
+   if (directory_list == NULL) {
+      num_dirs_alloc = 1;
+      directory_list = malloc(sizeof(*directory_list) * num_dirs_alloc);
+      directory_list[num_dirs] = argv[iarg++];
+      num_dirs++;
+   }
+   patient_number = atoi(argv[iarg++]);
+   first_image = ((argc < needed_args+1) ? 0 : atoi(argv[iarg++]));
+   last_image = ((argc < needed_args+2) ? INT_MAX : atoi(argv[iarg++]));
+
+   /* Check range */
+   if ((last_image < first_image) || (first_image < 0)) {
+      (void) fprintf(stderr, 
+         "Bad range of images: use +ve values with last >= first\n");
+      return EXIT_FAILURE;
+   }
+
+   /* Get file names */
+   get_file_names(num_dirs, directory_list, 
+                  patient_number, first_image, last_image, 
+                  &num_files, &file_list, &file_dirindex_list);
+   if (num_files <= 0) {
+      (void) fprintf(stderr, "No files to send.\n");
+      return EXIT_FAILURE;
+   }
+
+   
+   /* Get space for file names */
+   maxlength = 0;
+   for (ifile = 0; ifile < num_files; ifile++) { 
+      len = strlen(file_list[ifile]);
+      if (len > maxlength) maxlength = len;
+   }
+   maxdirlength = 0;
+   for (idir = 0; idir < num_dirs; idir++) {
+      len = strlen(directory_list[idir]);
+      if (len > maxdirlength) maxdirlength = len;
+   }
+   fullpath = malloc(maxdirlength + maxlength + 2);
+
+   /* Make dicom connection */
+   if (!acr_open_dicom_connection(host, port, AEtitle, MY_AE_TITLE,
+                                  ACR_MR_IMAGE_STORAGE_UID,
+				  ACR_IMPLICIT_VR_LITTLE_END_UID,
+                                  &afpin, &afpout)) {
+      free_file_names(fullpath, file_list, num_files);
+      return EXIT_FAILURE;
+   }
+
+   /* Set maximum number of outstanding responses */
+   acr_set_client_max_outstanding(afpin, max_outstanding);
+
+   /* Loop over the input files, sending them one at a time */
+
+   ifile = 0;
+
+   while (ifile < num_files) {
+
+     /* get next dicom group */
+
+     /************** START of group read unit - function? ********/
+
+     /* Get file name */
+     idir = file_dirindex_list[ifile];
+     (void) sprintf(fullpath, "%s/%s", 
+		    directory_list[idir], file_list[ifile]);
+     
+     printf("processing file %s (%d of %d)\n",
+	    file_list[ifile],
+	    ifile+1,num_files);
+     (void) fflush(stdout);
+
+     /* Read data */
+     group_list = siemens_to_dicom(fullpath, TRUE);
+     if (group_list == NULL) continue;
+
+     /* Look for multi-image files (many images in one) */
+     num_mosaic_elements = multi_image_init(group_list, &multi_image);
+
+#ifdef MYDEBUG
+     printf("num_mosaic_elements = %d\n",num_mosaic_elements); 
+#endif
+
+     /************** END of group read unit - function? ********/
+
+     /* determine number of `acqframes' */
+
+     if (multi_image.mosaic_seq) {
+
+       num_acqframes = acr_find_int(group_list,
+				    SPI_Number_of_averages, 1);
+     } else {
+       num_acqframes = 1;
+     }
+
+#ifdef MYDEBUG
+     printf("num_acqframes = %d\n",num_acqframes); 
+#endif
+
+     /* determine real number of slices */
+
+     num_slices = acr_find_int(group_list, SPI_Number_of_slices_cur, 1);
+
+     num_echos = acr_find_int(group_list, SPI_Number_of_echoes, 1);
+
+#ifdef MYDEBUG
+     printf("num_echos = %d\n",num_echos); 
+#endif
+
+     /* determine number of mosaics per volume */
+
+     num_mosaics = (int)ceil((float)num_slices/(float)num_mosaic_elements);
+
+     /* determine total number of `special' files expected for this
+        series */
+
+     num_special_files = num_acqframes * num_mosaics * num_echos;
+
+#ifdef MYDEBUG
+     printf("num_mosaics = %d\n",num_mosaics);
+     printf("num_special_files = %d\n",num_special_files);
+#endif
+
+     current_series =
+       acr_find_int(group_list, ACR_Study, 0);
+
+#ifdef MYDEBUG
+     printf("current_series = %d\n",current_series);
+#endif
+
+     /* add loop for echos, since diffusion scans may use echo loop
+	for multiple encodings.  Loop order will usually be 
+	acq, mosaic/slice, echo */
+
+     for (iecho = 0;  iecho < num_echos; iecho++) {
+
+       for (imosaic = 0;  imosaic < num_mosaics; imosaic++) {
+
+	 current_slice_index = 
+	   acr_find_int(group_list, SPI_Current_slice_number, 1);
+	 
+#ifdef MYDEBUG
+     printf("current_slice_index = %d\n",current_slice_index);
+#endif
+
+	 for (acqframe = 0; acqframe < num_acqframes; acqframe++) {
+	   
+	   /* check if we hit a new series or slice unexpectedly early -
+	      this indicates an aborted run */
+	   
+	   if ( acr_find_int(group_list,ACR_Study,0) !=
+		current_series ) {
+	     
+	     /* if we hit a new SERIES too early, that's it.  We break
+		out of all loops (acqframe and imosaic), clean up the
+		group, and start over again at the top of
+		while(ifile<num_files).  Note that we *don't* decrement
+		ifile as the group will be re-read at the top of the
+		while loop with the correct file index as-is.  */
+	     
+	     printf("WARNING:  new series too early; assuming aborted run for series %d.\n",current_series);
+	     
+	     acqframe = num_acqframes;
+	     imosaic = num_mosaics;
+	     multi_image_cleanup(group_list, &multi_image);
+	     acr_delete_group_list(group_list);
+	     break;
+	     
+	   } else if ( acr_find_int(group_list, SPI_Current_slice_number, 1) !=
+		       current_slice_index ) {
+	     
+	     /* if we hit a new SLICE too early, we've passed the last
+		frame in an overflow situation.  We then bump up the
+		mosaic index, reset the frame counter (we're now at the
+		first frame of the next overflow mosaic), and update the
+		current slice index */
+	     
+	     printf("WARNING:  new mosaic too early; assuming aborted run for series %d.\n",current_series);
+	     
+	     imosaic++;
+	     acqframe = 0;
+	     current_slice_index = 
+	       acr_find_int(group_list, SPI_Current_slice_number, 1);
+	     
+	   }
+	   
+	   /* debug statements for diffusion/echo loop scans? */
+#ifdef MYDEBUG
+	   printf("slice = %d\n",
+		  acr_find_int(group_list, SPI_Current_slice_number, 1));
+	   
+	   printf("echo = %d\n",
+		  acr_find_int(group_list, ACR_Echo_number, 1));
+#endif
+	   
+	   /******* process .ima file ********/
+	   
+	   /******** START of acquisition loop correction section *******/
+	   
+	   /* note:  we _could_ correct the number of signal averages,
+	      but this may be useful on the receive side so we'll leave
+	      it equal to the number of dynamic scans */
+	   
+	   /* also, we only want to do this if looks like there really
+	      are multiple acqframes (the acquisition loop has been used
+	      for dynamic scanning).  Otherwise, we could clobber  valid
+	      dynamic scan info for a measurement loop scan */
+	   
+	   if (num_acqframes>1) {
+	     
+	     /* Number of dynamic scans */
+	     acr_insert_numeric(&group_list, ACR_Acquisitions_in_series,
+				num_acqframes);
+	     
+	     /* now we have to fix the frame times, since these may be used
+		in sorting the frames at the receive end */
+	     
+	     /* start of scanning run */
+	     scan_start_time = 
+	       atof(acr_find_string(group_list, ACR_Study_time, ""));
+	     
+	     /* extract hours, minutes, seconds */
+	     start_hours = (int) (scan_start_time/(double)10000);
+	     scan_start_time -= start_hours * (10000.0);
+	     start_minutes = (int) (scan_start_time/(double)100);
+	     scan_start_time -= start_minutes * (100.0);
+	     start_seconds = scan_start_time;
+	     
+	     /* convert start time to seconds from start of day */
+	     start_time_sec = 
+	       start_hours*3600.0 +
+	       start_minutes*60.0 +
+	       start_seconds;
+	     
+	     /* compute frame time (from start) based on TR */
+	     rel_frame_time_sec = acqframe * 
+	       (acr_find_double(group_list, ACR_Repetition_time,1.0)/1000);
+	     
+	     /* now add times in seconds to get absolute frame time */
+	     abs_frame_time_sec = rel_frame_time_sec + start_time_sec;
+	     
+	     /* convert absolute frame time in sec back to hms */
+	     frame_hours     = floor(abs_frame_time_sec/3600.0);
+	     abs_frame_time_sec  -= frame_hours * 3600.0;
+	     frame_minutes   = floor(abs_frame_time_sec/60.0);
+	     abs_frame_time_sec  -= frame_minutes * 60.0;
+	     frame_seconds   = abs_frame_time_sec;
+	     
+	     /* check for day overflow (hours>23)*/
+	     frame_hours = ((int)frame_hours)%24;
+	     
+	     /* write frame time to string */
+	     sprintf(abs_frame_time_hms,"%02.0f%02.0f%06.3f",
+		     frame_hours,
+		     frame_minutes,
+		     frame_seconds);
+	     
+	     /* now write the proper frame time into the group */
+	     
+	     acr_insert_string(&group_list, ACR_Acquisition_time, 
+			       abs_frame_time_hms);
+	     
+	     /* current frame index */
+	     acr_insert_numeric(&group_list, ACR_Series,acqframe);
+	     
+	   }
+	   
+	   /******** END of acquisition loop correction section *******/
+	   
+	   /* determine number of sub-images in mosaic */
+	   
+	   if (multi_image.mosaic_seq) {
+	     
+	     if (imosaic == num_mosaics-1) {
+	       
+	       num_sub_images = num_slices-(num_mosaics-1)*num_mosaic_elements;
+	       
+	     } else {
+	       
+	       num_sub_images = num_mosaic_elements;
+	       
+	     }
+
+#ifdef MYDEBUG
+     printf("num_sub_images = %d\n",num_sub_images); 
+#endif
+	     
+	   } else { /* non-mosaic */
+	     
+	     num_sub_images = 1;
+	     
+	   }
+	   
+	   /********* Start of slice position correction Section ********/
+	   
+	   if (multi_image.mosaic_seq && num_sub_images > 1) {
+	     
+	     /* before 7:00pm Tuesday, March 28 2000: 
+		
+		position of first mosaic was ok, but overflow was either
+		off by number of overflow slices (for interleaved
+		excitation order) or correct (for ascending) */
+	     
+	     /* after 7:00pm Tuesday, March 28 2000: 
+		
+		position of .ima file is that of LAST slice in mosaic
+		this must be corrected to give FIRST slice.
+		
+		This was originally done so that SPI_Current_slice_number
+		would give the number of slices in the mosaic.
+		Unfortunately, this only works for ascending order on the
+		new system.  The SPL could therefore be modified to just
+		assign the position of the first sub-mosaic to the .ima
+		file.  This would probably be more consistent with other
+		sites */
+	     
+	     /* note that the code below depends *only* on the slice
+		position of the first mosaic being equal to that of the
+		last slice, so it should work for either case (it is
+		the slice position of subsequent `overflow' mosaics that
+		has been variable) */
+	     
+	     if (imosaic==0) {
+	       
+	       for (idim=0; idim < 3; idim++) {
+		 multi_image.position[idim] -= 
+		   (double) (num_sub_images-1) * multi_image.step[idim];
+		 
+		 top_slice_position[idim]=multi_image.position[idim];
+	       }
+	       
+	     } else {
+	       
+	       for (idim=0; idim < 3; idim++) {
+		 multi_image.position[idim] = 
+		   top_slice_position[idim] +
+		   (double)imosaic*(double)num_mosaic_elements*
+		   multi_image.step[idim];
+	       }
+	     }
+	   } /* end of if (multi_image.mosaic_seq) */
+	   
+	   /********* End of slice position correction Section ********/
+	   
+	   /* Now send all the sub-images */
+	   for (iimage=0; iimage < num_sub_images; iimage++) {
+	     
+	     
+	     /* Modify the group list for this image */
+	     multi_image_modify_group_list(group_list, &multi_image, iimage);
+	     
+	     /* correct slice index if mosaic */
+	     if (multi_image.mosaic_seq) {
+	       
+	       acr_insert_numeric(&group_list, SPI_Current_slice_number,
+				  imosaic*num_mosaic_elements+iimage+1);
+	       
+	     }
+	     
+	     /* Send the image */
+	     if (!acr_send_group_list(afpin, afpout, group_list, 
+				      ACR_MR_IMAGE_STORAGE_UID)) {
+	       multi_image_cleanup(group_list, &multi_image);
+	       acr_delete_group_list(group_list);
+	       acr_close_dicom_connection(afpin, afpout);
+	       free_file_names(fullpath, file_list, num_files);
+	       return EXIT_FAILURE;
+	     }
+	     
+	   }
+	   
+	   /* Clean up */
+	   
+	   multi_image_cleanup(group_list, &multi_image);
+	   
+	   acr_delete_group_list(group_list);
+	   
+	   ifile++;
+	   
+	   if (ifile == num_files) {
+	     
+	     /* we've hit the last file - let's get out of here!  (this
+		might happen if the last run in the file list is
+		aborted) */
+	     
+	     acqframe = num_acqframes;
+	     imosaic = num_mosaics;
+	     break;
+	     
+	     
+	   } else if (num_special_files > 1) {	 
+	     
+	     /* get next dicom group */
+	     
+	     /************** START of group read unit - function? ********/
+	     
+	     /* Get file name */
+	     idir = file_dirindex_list[ifile];
+	     (void) sprintf(fullpath, "%s/%s", 
+			    directory_list[idir], file_list[ifile]);
+	     
+	     printf("processing file %s (%d of %d)\n",
+		    file_list[ifile],
+		    ifile+1,num_files);
+	     (void) fflush(stdout);
+	     
+	     /* Read data */
+	     group_list = siemens_to_dicom(fullpath, TRUE);
+	     if (group_list == NULL) continue;
+	     
+	     /* Look for multi-image files (many images in one) */
+	     num_mosaic_elements = multi_image_init(group_list, &multi_image);
+	     
+	     /************** END of group read unit - function? ********/
+	     
+	   } /* end of if (num_special_files > 1) */
+	   
+	 } /* end of loop over acqframes */
+	 
+       } /* end of loop over mosaics */
+       
+     } /* end of loop over echos */
+     
+   } /* end of loop over files */
+
+
+   (void) printf("Done sending files.\n");
+   (void) fflush(stdout);
+
+   /* Release the association and free stuff*/
+   acr_close_dicom_connection(afpin, afpout);
+
+   free_file_names(fullpath, file_list, num_files);
+
+   return EXIT_SUCCESS;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : process_mosaic_args
+@INPUT      : dst - arguments from ParseArgv
+              key
+              argc
+              argv
+@OUTPUT     : argv
+@RETURNS    : Number of arguments left
+@DESCRIPTION: Routine to process the arguments for the -mosaic option.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 13, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int process_mosaic_args(char *dst, char *key, int argc, char **argv)
+{
+   Mosaic_Info *mosaic_info_list, tail, new;
+   char *match_string;
+   char *ptr;
+   int size[2];
+   int iarg;
+
+   /* Get pointer to mosaic info list */
+   mosaic_info_list = (Mosaic_Info *) dst;
+
+   /* Check number of arguments */
+   if (argc < 3) {
+      (void) fprintf(stderr, "\"%s\" option requires 3 arguments\n", key);
+      return -1;
+   }
+
+   /* Get arguments */
+   match_string = argv[0];
+   if (match_string == NULL) {
+      (void) fprintf(stderr, "Null string passed to \"%s\"\n", key);
+      return -1;
+   }
+   size[0] = strtol(argv[1], &ptr, 0);
+   if ((ptr == argv[1]) || (size[0] < 1)) {
+      (void) fprintf(stderr, "\"%s\" takes a positive integer (%s)\n",
+                     key, argv[1]);
+      return -1;
+   }
+   size[1] = strtol(argv[2], &ptr, 0);
+   if ((ptr == argv[2]) || (size[1] < 1)) {
+      (void) fprintf(stderr, "\"%s\" takes a positive integer (%s)\n",
+                     key, argv[2]);
+      return -1;
+   }
+
+   /* Update the argv list. We copy one extra element, to get the NULL */
+   argc -= 3;
+   for (iarg = 0; iarg <= argc; iarg++) {
+      argv[iarg] = argv[iarg+3];
+   }
+
+   /* Create a new entry and save the values */
+   new = (Mosaic_Info) malloc(sizeof(*new));
+   new->match_string = match_string;
+   new->size[0] = size[0];
+   new->size[1] = size[1];
+   new->next = NULL;
+
+   /* Add the entry to the list */
+   if (*mosaic_info_list == NULL) {
+      *mosaic_info_list = new;
+   }
+   else {
+      tail = *mosaic_info_list;
+      while (tail->next != NULL) {
+         tail = tail->next;
+      }
+      tail->next = new;
+   }
+
+   return argc;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_mosaic_info
+@INPUT      : mosaic_info_list - pointer to beginning of list
+              protocol - protocol name
+@OUTPUT     : (none)
+@RETURNS    : Pointer to matching mosaic info structure or NULL
+@DESCRIPTION: Routine to find a mosaic info structure that matches the
+              given protocol name. If none is found, then NULL is returned.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 13, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Mosaic_Info get_mosaic_info(Mosaic_Info mosaic_info_list, 
+                                   char *protocol)
+{
+#define DIRECTORY_SEP '/'
+#define EXTENSION_SEP '.'
+
+   Mosaic_Info info;
+   char *ptr;
+   int have_extension;
+   int num_dirs;
+   int nchars_to_match;
+   int protolen;
+
+   /* Loop over list */
+   for (info=mosaic_info_list; info != NULL; info = info->next) {
+
+      /* Check for an exact match */
+      if (info->match_string[0] == DIRECTORY_SEP) {
+         if (strcmp(protocol, info->match_string) == 0) {
+            break;
+         }
+      }
+
+      /* Otherwise look for a match with part of the protocol string */
+      else {
+
+         /* Figure out how many directories are given in the match string
+            and whether there is an extension */
+         have_extension = FALSE;
+         num_dirs = 0;
+         for (ptr = &info->match_string[strlen(info->match_string)];
+              ptr != info->match_string;
+              ptr--) {
+
+            /* Extension can only occur on filename part */
+            if ((num_dirs == 0) && (*ptr == EXTENSION_SEP)) {
+               have_extension = TRUE;
+            }
+
+            /* Count directory separators, but ignore repeats */
+            if ((*ptr == DIRECTORY_SEP) && (*(ptr+1) != DIRECTORY_SEP)) {
+               num_dirs++;
+            }
+         }
+
+         /* Figure out where to start match on protocol string by counting
+            directories */
+         for (ptr = &protocol[strlen(protocol)-1]; ptr != protocol; ptr--) {
+            if ((*ptr == DIRECTORY_SEP) && (*(ptr+1) != DIRECTORY_SEP)) {
+               num_dirs--;
+            }
+            if (num_dirs < 0) break;
+         }
+         if (*ptr == DIRECTORY_SEP) ptr++;
+
+         /* Match whole string or just prefix, depending on extension */
+         nchars_to_match = strlen(info->match_string);
+         protolen = strlen(ptr);
+         if (have_extension && (protolen > nchars_to_match)) {
+            nchars_to_match = protolen;
+         }
+
+         /* Do the match */
+         if (strncmp(ptr, info->match_string, nchars_to_match) == 0) {
+            break;
+         }
+
+      }    /* If exact match, else */
+
+   }      /* End of loop */
+
+   /* Return the match */
+   return info;
+
+}
+
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_directory
+@INPUT      : dst - client data passed by ParseArgv
+              key - matching key in argv
+              nextarg - argument following key in argv
+@OUTPUT     : (none)
+@RETURNS    : TRUE since nextarg is used.
+@DESCRIPTION: Gets directory name from command line and adds it to the list.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : August 3, 1999 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int get_directory(char *dst, char *key, char *nextarg)
+     /* ARGSUSED */
+{
+   /* Check for a following argument */
+   if (nextarg == NULL) {
+      (void) fprintf(stderr, 
+                     "\"%s\" option requires an additional argument\n",
+                     key);
+      exit(EXIT_FAILURE);
+   }
+
+   /* Check whether we need more space for the directory name */
+   if (num_dirs >= num_dirs_alloc) {
+      num_dirs_alloc += 10;
+      if (directory_list == NULL)
+         directory_list = malloc(sizeof(*directory_list) * num_dirs_alloc);
+      else
+         directory_list = realloc(directory_list,
+                                  sizeof(*directory_list) * num_dirs_alloc);
+   }
+
+   /* Add the new directory */
+   directory_list[num_dirs] = nextarg;
+   num_dirs++;
+
+   return TRUE;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : get_file_names
+@INPUT      : num_dirs - number of directories in list
+              directory_list - list of directories in which to look
+              patient_number - number found at beginning of file name
+              first_image - first number in range
+              last_image - last number in range
+@OUTPUT     : num_files - number of files found
+              file_list - list of files to be sentn
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to find all files in directory and of the
+              form "<patient number>-<scan number>-<image number>.ima" and 
+              with <image number> in the range given by first_image and
+              last_image. The files are sorted by image number.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : July 11, 1997 (Peter Neelin)
+@MODIFIED   : August 3, 1999 (P.N.)
+---------------------------------------------------------------------------- */
+public void get_file_names(int num_dirs, char **directory_list, 
+                           int patient_number,
+                           int first_image, int last_image,
+                           int *num_files, char ***file_list,
+                           int **file_dirindex_list)
+{
+   DIR *dir;
+   struct dirent *dirent;
+   char *filename;
+   int patid, acqid, imgid;
+   char ch;
+   Sort_entry *sorting_files;
+   int num_entries, num_alloc, ifile, idir;
+
+   /* Set initial values */
+   *num_files = 0;
+   *file_list = NULL;
+   *file_dirindex_list = NULL;
+
+   /* Set up array for file names */
+   num_entries = 0;
+   num_alloc = ALLOC_INCREMENT;
+   sorting_files = malloc(sizeof(*sorting_files) * num_alloc);
+
+   /* Loop over directories */
+   for (idir=0; idir < num_dirs; idir++) {
+
+      /* Open the directory and find appropriate files */
+      if ((dir = opendir(directory_list[idir])) == NULL) {
+         (void) fprintf(stderr, "Error opening directory \"%s\": ", 
+                        directory_list[idir]);
+         perror(NULL);
+         continue;
+      }
+
+      /* Loop over entries */
+      while ((dirent = readdir(dir)) != NULL) {
+
+         /* Get filename */
+         filename = dirent->d_name;
+
+         /* Parse the file name */
+         if (sscanf(filename, "%d-%d-%d.ima%c", 
+                    &patid, &acqid, &imgid, &ch) != 3) 
+            continue;
+
+         /* Check that we want this file */
+         if ((patid != patient_number) || (imgid < first_image) ||
+             (imgid > last_image)) 
+            continue;
+
+         /* Add more space if needed */
+         if (num_entries >= num_alloc) {
+            num_alloc += ALLOC_INCREMENT;
+            sorting_files = realloc(sorting_files, 
+                                    sizeof(*sorting_files) * num_alloc);
+         }
+
+         /* Add the entry and its number for sorting */
+         sorting_files[num_entries].key = imgid;
+         sorting_files[num_entries].name = strdup(dirent->d_name);
+         sorting_files[num_entries].dirindex = idir;
+
+         /* Increment the number of entries */
+         num_entries++;
+
+      }     /* End of loop over files in directory */
+
+      /* Close the directory */
+      (void) closedir(dir);
+
+   }     /* End of loop over directories */
+
+   /* Check the number of entries */
+   if (num_entries <= 0) return;
+
+   /* Sort the files */
+   qsort(sorting_files, num_entries, sizeof(sorting_files[0]),
+         sort_function);
+
+   /* Copy the file names into an array */
+   *num_files = num_entries;
+   *file_list = malloc(sizeof(**file_list) * (num_entries + 1));
+   *file_dirindex_list = malloc(sizeof(**file_dirindex_list) 
+                                * (num_entries + 1));
+   (*file_list)[num_entries] = NULL;
+   (*file_dirindex_list)[num_entries] = -1;
+   for (ifile=0; ifile < num_entries; ifile++) {
+      (*file_list)[ifile] = sorting_files[ifile].name;
+      (*file_dirindex_list)[ifile] = sorting_files[ifile].dirindex;
+   }
+
+   /* Free the sorting structure */
+   free(sorting_files);
+
+   return;
+}
+
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : sort_function
+@INPUT      : entry1
+              entry2
+@OUTPUT     : (none)
+@RETURNS    : -1, 0, 1 for lt, eq, gt
+@DESCRIPTION: Function to compare two numbers for sorting files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : July 11, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+private int sort_function(const void *entry1, const void *entry2)
+{
+   int value1, value2;
+
+   value1 = ((Sort_entry *) entry1)->key;
+   value2 = ((Sort_entry *) entry2)->key;
+
+   if (value1 < value2) return -1;
+   else if (value1 > value2) return 1;
+   else return 0;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_file_names
+@INPUT      : fullpath
+              file_list
+              num_files
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to free file name strings
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : September 19, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void free_file_names(char *fullpath, char *file_list[], int num_files)
+{
+   int ifile;
+
+   free(fullpath);
+   for (ifile=0; ifile < num_files; ifile++) {
+      free(file_list[ifile]);
+   }
+   free(file_list);
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : multi_image_init
+@INPUT      : group_list - group list as read in from file
+@OUTPUT     : multi_image - structure containing information to be used
+                 for modifying group list in loop over images
+@RETURNS    : number of images to be processed
+@DESCRIPTION: Routine to set up loop over multiple images in an input file.
+@METHOD     : 
+@GLOBALS    : mosaic_info_list
+@CALLS      : 
+@CREATED    : November 6, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int multi_image_init(Acr_Group group_list, 
+                            Multi_Image *multi_image)
+{
+   int group_id, element_id;
+   int last_image, grid_size;
+   long new_image_size;
+   void *data;
+   Acr_Element element;
+   char string[256];
+   int idim;
+   double pixel_spacing[2], separation;
+   char *protocol;
+   Mosaic_Info mosaic_info;
+
+   /* Find the protocol name and look for a mosaic info structure */
+   protocol = acr_find_string(group_list, SPI_Sequence_File_Name, "");
+   mosaic_info = get_mosaic_info(mosaic_info_list, protocol);
+
+   /* Check whether we need to do anything */
+   multi_image->mosaic_seq = (mosaic_info != NULL);
+   multi_image->packed = (mosaic_info != NULL);
+
+   if (!multi_image->packed) return 1;
+
+   /* Get some basic image information */
+   multi_image->big[0] = acr_find_int(group_list, ACR_Columns, 1);
+   multi_image->big[1] = acr_find_int(group_list, ACR_Rows, 1);
+   multi_image->pixel_size = 
+      (acr_find_int(group_list, ACR_Bits_allocated, 16)-1) / 8 + 1;
+
+   /* Get the image size */
+   multi_image->size[0] = mosaic_info->size[0];
+   multi_image->size[1] = mosaic_info->size[1];
+
+   /* Get the grid shape, checking that it is not too big if specified */
+   multi_image->grid[0] = multi_image->big[0] / multi_image->size[0];
+   multi_image->grid[1] = multi_image->big[1] / multi_image->size[1];
+   if ((multi_image->grid[0] < 1) || (multi_image->grid[0] < 1)) {
+      (void) fprintf(stderr, "Grid too small: %d x %d\n",
+                     multi_image->grid[0], multi_image->grid[1]);
+      exit(EXIT_FAILURE);
+   }
+
+   /* Check whether we need to do anything (1x1 grid may be the whole image) */
+   grid_size = multi_image->grid[0] * multi_image->grid[1];
+   if ((grid_size == 1) &&
+       (multi_image->size[0] == multi_image->big[0]) &&
+       (multi_image->size[1] == multi_image->big[1])) {
+     /* had to remove this as now ANY images acquired with 
+	the mosaic sequence need special treatment */
+     multi_image->packed = FALSE;
+      return 1;
+   }
+
+   /* Steal the image element from the group list */
+   multi_image->big_image = acr_find_group_element(group_list, ACR_Image);
+
+   if (multi_image->big_image == NULL) {
+      (void) fprintf(stderr, "Couldn't find an image\n");
+      exit(EXIT_FAILURE);
+   }
+   group_id = acr_get_element_group(multi_image->big_image);
+   element_id = acr_get_element_element(multi_image->big_image);
+   acr_group_steal_element(acr_find_group(group_list, group_id),
+                           multi_image->big_image);
+
+   /* Add a small image */
+   new_image_size = 
+      multi_image->size[0] * multi_image->size[1] * multi_image->pixel_size;
+   data = malloc((size_t) new_image_size);
+   multi_image->small_image = 
+      acr_create_element(group_id, element_id,
+                         acr_get_element_vr(multi_image->big_image),
+                         new_image_size, data);
+   acr_set_element_vr(multi_image->small_image,
+      acr_get_element_vr(multi_image->big_image));
+   acr_set_element_byte_order(multi_image->small_image,
+      acr_get_element_byte_order(multi_image->big_image));
+   acr_set_element_vr_encoding(multi_image->small_image,
+      acr_get_element_vr_encoding(multi_image->big_image));
+   acr_insert_element_into_group_list(&group_list, multi_image->small_image);
+
+   /* Update the pixel size */
+   acr_insert_short(&group_list, ACR_Rows, multi_image->size[1]);
+   acr_insert_short(&group_list, ACR_Columns, multi_image->size[0]);
+
+   /* Get image image index info */
+   last_image = acr_find_int(group_list, SPI_Current_slice_number, 1);
+
+   /* sub_images is now just the number of mosaic elements, even if
+      they don't all contain slices */
+
+   multi_image->sub_images = multi_image->grid[0] * multi_image->grid[1];
+
+   /* NOTE:  multi_image->first_image is unkown now, since last_image
+      is no longer necessarily correct.  We update slice numbers in
+      main() now.
+
+      multi_image->first_image = last_image -
+	 multi_image->sub_images + 1; */
+
+   /* Fiddle the pixel size */
+   element = acr_find_group_element(group_list, ACR_Pixel_size);
+   if ((element != NULL) &&
+       (acr_get_element_numeric_array(element, 2, pixel_spacing) == 2)) {
+      pixel_spacing[0] *= 
+         (double) multi_image->big[0] / (double) multi_image->size[0];
+      pixel_spacing[1] *= 
+         (double) multi_image->big[1] / (double) multi_image->size[1];
+      (void) sprintf(string, "%.15g\\%.15g", 
+                     pixel_spacing[0], pixel_spacing[1]);
+      acr_insert_string(&group_list, ACR_Pixel_size, string);
+   }
+
+   /* Get step between slices */
+   separation = acr_find_double(group_list, ACR_Slice_thickness, 1.0) *
+      (1.0 + acr_find_double(group_list, SPI_Slice_distance_factor,
+			     0.0));
+
+   element = acr_find_group_element(group_list, SPI_Image_normal);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, 3, multi_image->normal) != 3)) {
+      multi_image->normal[0] = 0.0;
+      multi_image->normal[1] = 0.0;
+      multi_image->normal[2] = 1.0;
+   }
+   for (idim=0; idim < 3; idim++) {
+      multi_image->step[idim] = separation * multi_image->normal[idim];
+   }
+
+   /* Get position and correct to first slice */
+   element = acr_find_group_element(group_list, SPI_Image_position);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, 3, 
+                                      multi_image->position) != 3)) {
+      multi_image->position[0] = 0.0;
+      multi_image->position[1] = 0.0;
+      multi_image->position[2] = 0.0;
+   }
+
+   /* sub_images may be wrong here if there is overflow, so I'm
+      commenting this out and moving this step to a point in main()
+      where multi_image->sub_images has been corrected */
+
+   /*   for (idim=0; idim < 3; idim++) {
+	multi_image->position[idim] -= 
+	(double) (multi_image->sub_images-1) * multi_image->step[idim];
+	} */
+
+   /* Return number of sub-images in this image */
+   return multi_image->sub_images;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : multi_image_modify_group_list
+@INPUT      : group_list - group list as read in from file
+              multi_image - structure containing information to be used
+                 for modifying group list in loop over images
+              iimage - image number to process (counting from zero).
+@OUTPUT     : group_list
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to modify the group list to use a new image.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 6, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void multi_image_modify_group_list(Acr_Group group_list, 
+                                          Multi_Image *multi_image,
+                                          int iimage)
+{
+   int irow, ibyte, idim, nbyte;
+   int isub, jsub;
+   char *new, *old;
+   long old_offset, new_offset;
+   double position[3], distance;
+   char string[256];
+
+   /* Check whether we need to do anything */
+   if (!multi_image->packed) return;
+
+   /* Check the image number */
+   if ((iimage < 0) || (iimage > multi_image->sub_images)) {
+      (void) fprintf(stderr, "Invalid image number to send: %d of %d\n",
+                     iimage, multi_image->sub_images);
+      exit(EXIT_FAILURE);
+   }
+
+   /* Figure out the sub-image indices */
+   isub = iimage % multi_image->grid[0];
+   jsub = iimage / multi_image->grid[0];
+
+   /* Get pointers */
+   old = acr_get_element_data(multi_image->big_image);
+   new = acr_get_element_data(multi_image->small_image);
+
+   /* Copy the image */
+   nbyte = multi_image->size[0] * multi_image->pixel_size;
+   for (irow=0; irow < multi_image->size[1]; irow++) {
+      old_offset = isub * multi_image->size[0] +
+         (jsub * multi_image->size[1] + irow) * multi_image->big[0];
+      old_offset *= multi_image->pixel_size;
+      new_offset = (irow * multi_image->size[0]) * multi_image->pixel_size;
+      for (ibyte=0; ibyte < nbyte; ibyte++) {
+         new[new_offset + ibyte] = old[old_offset + ibyte];
+      }
+   }
+
+   /* Reset the byte order and VR encoding. This will be modified on each
+      send according to what the connection needs. */
+   acr_set_element_byte_order(multi_image->small_image,
+      acr_get_element_byte_order(multi_image->big_image));
+   acr_set_element_vr_encoding(multi_image->small_image,
+      acr_get_element_vr_encoding(multi_image->big_image));
+
+   /* Update the index */
+   acr_insert_numeric(&group_list, SPI_Current_slice_number, 
+                      (double) (iimage + multi_image->first_image));
+
+   /* Update the position */
+   distance = 0.0;
+   for (idim=0; idim < 3; idim++) {
+      position[idim] = multi_image->position[idim] + 
+         (double) iimage * multi_image->step[idim];
+      distance += position[idim] * multi_image->normal[idim];
+   }
+
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g",
+                  position[0], position[1], position[2]);
+   acr_insert_string(&group_list, SPI_Image_position, string);
+   acr_insert_numeric(&group_list, SPI_Image_distance, distance);
+   update_coordinate_info(group_list);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : multi_image_cleanup
+@INPUT      : group_list - group list as read in from file
+              multi_image - structure containing information to be used
+                 for modifying group list in loop over images
+@OUTPUT     : multi_image
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to clean up after doing multi-image stuff.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 6, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void multi_image_cleanup(Acr_Group group_list, 
+                                Multi_Image *multi_image)
+/* ARGSUSED */
+{
+
+   if (!multi_image->packed) return;
+
+   acr_delete_element(multi_image->big_image);
+}
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_dicom_to_minc.c
@@ -0,0 +1,1287 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_dicom_to_minc.c
+@DESCRIPTION: Code to convert a list of Siemens dicom files to minc 
+              format.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: siemens_dicom_to_minc.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.18  2002/09/26 15:24:33  rhoge
+ * Before was only skipping time sort for multi-slice N4 mosaics.  Turns out
+ * this was also causing failure on single-slice scans.
+ * Changed slices>1 to slices>0 so that now N4 dicom scans never get sorted
+ * on their (apparently nonsensical) time value.  The if statement should
+ * really be reworked, and should keep an eye on this.  Seems like EPI
+ * time series sequences never sort properly on 'time'.
+ *
+ * Revision 1.17  2002/09/25 17:25:43  rhoge
+ * changed public void's to public int's
+ *
+ * Revision 1.16  2002/05/08 19:32:40  rhoge
+ * fixed handling of diffusion scans with separate series for each average
+ *
+ * Revision 1.15  2002/05/01 21:29:34  rhoge
+ * removed MrProt from minc header - encountered files with large strings,
+ * causing seg faults
+ *
+ * Revision 1.14  2002/04/30 12:36:35  rhoge
+ * fixes to handle current (and hopefully final) diffusion sequence
+ *
+ * Revision 1.13  2002/04/26 03:27:03  rhoge
+ * fixed MrProt problem - replaced fixed lenght char array with malloc
+ *
+ * Revision 1.12  2002/04/08 03:40:56  rhoge
+ * fixed mosaic extraction for non-square scans and 3D scans.
+ * added some new dicom elements
+ *
+ * Revision 1.11  2002/03/27 19:38:08  rhoge
+ * small comment change
+ *
+ * Revision 1.10  2002/03/27 18:57:50  rhoge
+ * added diffusion b value
+ *
+ * Revision 1.9  2002/03/23 13:17:53  rhoge
+ * added support for Bourget network pushed dicom files, cleaned up
+ * file check and read_numa4_dicom vr check/assignment
+ *
+ * Revision 1.8  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.7  2002/03/21 13:31:56  rhoge
+ * updated comments
+ *
+ * Revision 1.6  2002/03/19 22:10:16  rhoge
+ * removed time sorting for N4DCM mosaics - time is random for mosaics
+ *
+ * Revision 1.5  2002/03/19 13:13:56  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.4  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.3  2000/12/14 21:37:11  rhoge
+ * log message cleanup
+ *
+ * Revision 1.2  2000/12/14 21:36:22  rhoge
+ * changes to restore measurement loop support that was broken by changes
+ * to provide acquisition loop support
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ * -now support Siemens acquisition loop scans with and without correction
+ *  on sending side
+ *
+ * Revision 6.1  1999/10/29 17:51:59  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+
+extern int Do_logging;
+char *pname;
+File_Type file_type; /* type of input files */
+int Fork;
+int N4_OFFSET;
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_dicom_to_minc
+@INPUT      : num_files - number of image files
+              file_list - list of file names
+              minc_file - name of output minc file (NULL means make one
+                 up)
+              clobber - if TRUE, then open the output with NC_CLOBBER
+              file_prefix - string providing any directory or prefix 
+                 for internally generated filename (if it is a directory,
+                 then it must contain the last "/")
+@OUTPUT     : output_file_name - returns a pointer to an internal area
+                 containing the file name of the created file if minc_file
+                 is NULL, or simply a pointer to minc_file. If NULL, then
+                 nothing is returned.
+@RETURNS    : EXIT_SUCCESS if no error, EXIT_FAILURE on error.
+@DESCRIPTION: Routine to convert a list of Siemens dicom files to minc 
+              format.
+@METHOD     : 
+@GLOBALS    : Do_logging
+@CALLS      : 
+@CREATED    : November 25, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int siemens_dicom_to_minc(int num_files, char *file_list[], 
+                        char *minc_file, int clobber,
+                        char *file_prefix, char **output_file_name)
+{
+   Acr_Group group_list;
+   int max_group;
+   File_Info *file_info;
+   General_Info general_info;
+   General_Info general_info_orig;
+   Image_Data image;
+   int icvid;
+   int ifile;
+   Mri_Index imri;
+   char *out_file_name;
+   int isep;
+
+   // variables added by rhoge
+
+   int num_files_expected;
+   int num_avg_nominal;
+   int num_frames_nominal;
+   int idim;
+   int frame;
+   int num_frames;
+   int index;
+   Loop_Type loop_type = NONE;
+   int subimage;
+   int iimage;
+   int num_images_allocated;
+   Acr_Element big_image;
+   Acr_Element small_image;
+   Multi_Image multi_image;
+
+   /* Allocate space for the file information */
+   file_info = MALLOC(num_files * sizeof(*file_info));
+   num_images_allocated = num_files;
+
+   // Last group needed for first pass
+   //   max_group = ACR_ACTUAL_IMAGE_GID - 1;
+   // we now have to read up to and including the image, 
+   // since image pointers are needed in multi_image_init
+   max_group = ACR_ACTUAL_IMAGE_GID;
+
+   /* Add all control characters as numeric array separators to handle 
+      odd behaviour with Siemens dicom files */
+   for (isep=0; isep < 31; isep++) {
+      (void) acr_element_numeric_array_separator(isep);
+   }
+
+   /* Initialize some values for general info */
+   general_info.initialized = FALSE;
+   general_info.group_list = NULL;
+   for (imri=0; imri < MRI_NDIMS; imri++) {
+      general_info.indices[imri] = NULL;
+      general_info.coordinates[imri] = NULL;
+   }
+
+   // Loop through file list getting information
+   // (note that we have to duplicate the handling
+   // of multiple images per file in this loop
+   // to accumulate dimension sizes correctly)
+
+   // need separate counter for images, since some files may
+   // contain more than one image!
+   iimage = 0;
+
+   for (ifile=0; ifile < num_files; ifile++) {
+
+     if (!Fork) {
+       progress(ifile, num_files, "-Parsing series info");
+     }
+
+     // Read the file
+     if (file_type == N4DCM) {
+       group_list = read_numa4_dicom(file_list[ifile], max_group);
+     } else if (file_type == IMA) {
+       group_list = read_siemens_dicom(file_list[ifile], max_group);
+     }
+
+     // initialize big and small images, if mosaic
+     if (acr_find_int(group_list, EXT_Slices_in_file,1)>1) {
+
+       multi_image_init(group_list, &multi_image);
+
+       // if multi images in file, extend file_info list
+
+       num_images_allocated += 
+	 acr_find_int(group_list, EXT_Slices_in_file,1) - 1;
+
+       file_info = REALLOC(file_info, 
+			   num_images_allocated * sizeof(*file_info));
+
+     }
+
+     // loop over subimages in mosaic
+     for(subimage = 0; 
+     	 subimage < acr_find_int(group_list, EXT_Slices_in_file,1);
+     	 subimage++) {
+
+       // Modify the group list for this image if mosaic
+       if (acr_find_int(group_list, EXT_Slices_in_file,1)>1) {
+	 multi_image_modify_group_list(group_list,&multi_image,subimage);
+       }
+
+       // Get file-specific information
+       get_file_info(group_list, &file_info[iimage], &general_info);
+
+       // increment iimage here
+       iimage++;
+     }
+
+     // Delete the group list
+     acr_delete_group_list(group_list);
+     // cleanup multi_image struct if used
+     if (general_info.num_slices_in_file > 1) {
+       multi_image_cleanup(group_list, &multi_image);
+     }
+
+   }
+
+   // Sort the dimensions
+   sort_dimensions(&general_info);
+
+   // Create the output file
+   if (general_info.initialized) {
+      icvid = create_minc_file(minc_file, clobber, &general_info,
+                               file_prefix, &out_file_name,
+			       loop_type);
+   }
+   if (output_file_name != NULL)
+      *output_file_name = out_file_name;
+
+   // Check that we found the general info and that the minc file was
+   // created okay
+   if ((!general_info.initialized) || (icvid == MI_ERROR)) {
+      if (general_info.initialized) {
+         (void) fprintf(stderr, "Error creating minc file %s.\n",
+                        out_file_name);
+      }
+      free_info(&general_info, file_info, num_files);
+      FREE(file_info);
+      return EXIT_FAILURE;
+   }
+
+   if (Do_logging > HIGH_LOGGING) { /* rhoge */
+     fprintf(stderr,"\nAbout to enter minc write loop...\n");
+   }	  
+
+
+   // Loop through the files again and put images into the minc file
+   iimage = 0;
+   for (ifile=0; ifile < num_files; ifile++) {
+
+     if (!Fork) {
+       progress(ifile, num_files, "-Creating minc file");
+     }
+
+     // Check that we have a valid file 
+     if (!file_info[ifile].valid) {
+       continue;
+     }
+     
+     // Read the file 
+     if (file_type == N4DCM) {
+       group_list = read_numa4_dicom(file_list[ifile], max_group);
+     } else if (file_type == IMA) {
+       group_list = read_siemens_dicom(file_list[ifile], max_group);
+     }
+
+     // initialize big and small images, if mosaic
+     if (general_info.num_slices_in_file > 1) {
+       multi_image_init(group_list, &multi_image);
+     }
+
+     // loop over subimages in mosaic
+     for(subimage = 0; 
+	 subimage < general_info.num_slices_in_file; 
+	 subimage++) {
+
+       // Modify the group list for this image if mosaic
+       if (general_info.num_slices_in_file > 1) {
+	 multi_image_modify_group_list(group_list,&multi_image,subimage);
+       }
+       
+       // Get image
+       get_siemens_dicom_image(group_list, &image);
+       
+       // Save the image and any other information
+       save_minc_image(icvid, &general_info, &file_info[iimage], &image);
+
+       // increment image counter
+       iimage++;
+       
+     }
+     
+     // Delete the group list
+     acr_delete_group_list(group_list);
+     // cleanup multi_image struct if used
+     if (general_info.num_slices_in_file > 1) {
+       multi_image_cleanup(group_list, &multi_image);
+     }
+     
+     /* Free the image data */
+     if ((image.data != NULL) && (image.free)) FREE(image.data);
+     
+   }
+
+   /* Close the output file */
+   close_minc_file(icvid);
+
+   /* Free the general_info and file_info stuff */
+   free_info(&general_info, file_info, num_files);
+   FREE(file_info);
+
+   return EXIT_SUCCESS;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : read_siemens_dicom
+@INPUT      : filename - name of siemens dicom file to read
+              max_group - maximum group number to read
+@OUTPUT     : (none)
+@RETURNS    : group list read in from file
+@DESCRIPTION: Routine to read in a group list from a file.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 25, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Group read_siemens_dicom(char *filename, int max_group)
+{
+   FILE *fp;
+   Acr_File *afp;
+   Acr_Group group_list;
+   Acr_byte_order byte_order;
+   Acr_VR_encoding_type vr_encoding;
+
+   /* Open the file */
+   fp = fopen(filename, "r");
+   if (fp == NULL) {
+     fprintf(stderr,"Error opening file %s!\n",filename);
+     return NULL;
+   }
+
+   /* Connect to input stream */
+   afp=acr_file_initialize(fp, 0, acr_stdio_read);
+
+   /* should be:  if file type is numa 4 dicom, and if read from file
+      with first 128 bytes blank, then do required skipping and setup */
+
+   if (1) {
+
+     /* set byte ordering to explicit LE */
+
+     byte_order = ACR_LITTLE_ENDIAN;
+     vr_encoding = ACR_EXPLICIT_VR;
+     acr_set_byte_order(afp, byte_order);
+     acr_set_vr_encoding(afp, vr_encoding);
+
+     /* skip 1st 128 bytes - are empty in storage class 
+	+ DICM (4 chars) 128+4 = 132 bytes to skip */
+
+     acr_skip_input_data(afp, 132);
+
+   }
+
+   /* Read in group list */
+   (void) acr_input_group_list(afp, &group_list, max_group);
+
+   /* Close the file */
+   acr_file_free(afp);
+   (void) fclose(fp);
+
+   return group_list;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : read_numa4_dicom
+@INPUT      : filename - name of siemens Numaris 4 `dicom' file to read
+              max_group - maximum group number to read
+@OUTPUT     : (none)
+@RETURNS    : group list read in from file
+@DESCRIPTION: Routine to read in a group list from a file.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : December 18, 2001 (Rick Hoge)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Group read_numa4_dicom(char *filename, int max_group)
+{
+   FILE *fp;
+   Acr_File *afp;
+   Acr_Group group_list;
+   Acr_byte_order byte_order;
+   Acr_VR_encoding_type vr_encoding;
+
+   // needed for group repair - some essential info
+   // only available in ascii dump of MrProt structure
+   Acr_Element Protocol; 
+   Acr_Element element;
+
+   int mosaic_rows, mosaic_cols;
+   short subimage_size[4];
+   int subimage_rows, subimage_cols;
+   int num_slices, num_partitions;
+   char *field_ptr;
+   int num_encodings, enc_ix;
+   int average, files_per_average;
+
+   // Open the file
+   fp = fopen(filename, "r");
+   if (fp == NULL) {
+     fprintf(stderr,"Error opening file %s!\n",filename);
+     return NULL;
+   }
+
+   // Connect to input stream
+   afp=acr_file_initialize(fp, 0, acr_stdio_read);
+
+   /* should be:  if file type is numa 4 dicom, and if read from file
+      with first 128 bytes blank, then do required skipping and setup */
+
+   // set byte ordering to explicit LE
+   
+   byte_order = ACR_LITTLE_ENDIAN;
+   // vr_encoding = ACR_EXPLICIT_VR;  // CD format
+   // vr_encoding = ACR_IMPLICIT_VR;  // Bourget format
+
+   vr_encoding = acr_get_vr_encoding(afp); // doesn't seem to work on Export/CD
+   acr_set_byte_order(afp, byte_order);
+   acr_set_vr_encoding(afp, vr_encoding);
+
+   if (N4_OFFSET) {
+     // skip 1st 128 bytes - are empty in Syngo CD/Local Export files
+     // DICM (4 chars) 128+4 = 132 bytes to skip
+     vr_encoding = ACR_EXPLICIT_VR;  // CD format
+     acr_set_vr_encoding(afp, vr_encoding);
+     acr_skip_input_data(afp, 132);
+   } 
+   // Read in group list
+   (void) acr_input_group_list(afp, &group_list, max_group);
+
+   // Close the file
+   acr_file_free(afp);
+   (void) fclose(fp);
+
+   // now fix the group list to provide essential info
+   // via standard dicom elements
+   // (this lets the rest of the code be more reusable)
+
+   // Note that these parameters are mostly dimension lengths,
+   // and are not usually supplied in standard DICOM implementations.
+   // We could do without them, except that the use of mosaics for
+   // multi-slice data makes at least the number of slices necessary.
+   // For such elements, we will spoof our own `private' entries
+   // using Numaris 3.5 coordinates.  These should not be used elsewhere
+   // in the code unless there's no other way!  Basically things
+   // should be done as follows:
+
+   // 1) use actual element in public dicom group, if possible
+   // 2) if not, then get info from MrProt and insert as 
+   //    correct public dicom element
+   // 3) if no public element exists, use an SPI element (careful!)
+   // 4) if no SPI element exists, use and EXT element (careful!)
+
+   // WOULD RETURN HERE FOR NORMAL DICOM
+
+   // read in Protocol group
+   Protocol = acr_find_group_element(group_list,SPI_Protocol);
+
+   // add number of dynamic scans:
+   acr_insert_numeric(&group_list, ACR_Acquisitions_in_series,
+	      atoi((char*)prot_find_string(Protocol,"lRepetitions"))+1);
+
+   // add number of echoes:
+   acr_insert_numeric(&group_list, SPI_Number_of_echoes,
+	      atoi((char*)prot_find_string(Protocol,"lContrasts")));
+
+   // add receiving coil (for some reason this isn't in generic groups)
+   acr_insert_string(&group_list, ACR_Receiving_coil,
+	      prot_find_string(Protocol,
+		       "sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tCoilID"));
+   // add MrProt dump
+   acr_insert_string(&group_list,EXT_MrProt_dump,dump_protocol_text(Protocol));
+
+   // add number of slices:
+   // (called `Partitions' for 3D)
+   num_slices = atoi((char*)prot_find_string(Protocol,"sSliceArray.lSize"));
+   num_partitions = 
+     atoi((char*)prot_find_string(Protocol,"sKSpace.lPartitions"));
+   // NOTE:  for some reason, lPartitions > 1 even for 2D scans
+   // (e.g. EPI, scouts)
+
+   if (!strncmp(acr_find_string(group_list,ACR_MR_acquisition_type,
+					   ""),"3D",2)) {
+     // use partitions if 3D
+     // (note that this gets more complicated if the 3D scan
+     //  is mosaiced - see below)
+
+     acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal,
+			1);
+     acr_insert_numeric(&group_list, SPI_Number_of_3D_raw_partitions_nominal,
+     			num_partitions);
+   } else {
+     // use slices for 2D
+     acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal,num_slices);
+     acr_insert_numeric(&group_list, 
+			SPI_Number_of_3D_raw_partitions_nominal,1);
+   }
+
+   // now figure out mosaic rows and columns, and put in EXT shadow group
+
+   // check for interpolation - not supported for mosaics yet
+   if (strcmp(prot_find_string(Protocol,"sKSpace.uc2DInterpolation"),"0")){
+     // if interpolated image, assume no mosaic
+     acr_insert_numeric(&group_list, EXT_Mosaic_rows, 1);
+     acr_insert_numeric(&group_list, EXT_Mosaic_columns, 1);
+     acr_insert_numeric(&group_list, EXT_Slices_in_file, 1);
+
+   } else {
+     // compute mosaic rows and columns
+
+     // here is a hack to handle non-square mosaiced images
+     // WARNING:  as far as I can tell, the phase-encoding dir
+     // (row/col) is reversed for mosaic EPI scans (don't know
+     // if this is a mosaic thing, an EPI thing, or whatever)
+
+     // get the array of sizes:
+     //    freq row/freq col/phase row/phase col
+     element = acr_find_group_element(group_list, ACR_Acquisition_matrix);
+     acr_get_element_short_array(element, 4, subimage_size);
+
+     // get subimage dimensions, assuming the OPPOSITE of the
+     // reported phase-encode direction!!
+     if (!strncmp(acr_find_string(group_list,ACR_Phase_encoding_direction,""),
+		"COL",3)) {
+
+       subimage_rows = subimage_size[3];
+       subimage_cols = subimage_size[0];
+
+     } else if (!strncmp(acr_find_string(group_list,
+                ACR_Phase_encoding_direction,""),"ROW",3)) {
+
+       subimage_rows = subimage_size[2];
+       subimage_cols = subimage_size[1];
+
+     }
+
+     mosaic_rows = acr_find_int(group_list,ACR_Rows, 1)/subimage_rows;
+     mosaic_cols = acr_find_int(group_list,ACR_Columns, 1)/subimage_cols;
+
+     acr_insert_numeric(&group_list, EXT_Mosaic_rows,mosaic_rows);
+     acr_insert_numeric(&group_list, EXT_Mosaic_columns,mosaic_cols);
+
+     if (mosaic_rows * mosaic_cols > 1) {
+
+       // if 3D mosaiced scan, write number of partitions to number of 
+       // slices in dicom group  THIS LOOKS REDUNDANT!!!
+       if (!strncmp(acr_find_string(group_list,ACR_MR_acquisition_type,
+				    ""),"3D",2)) {
+	 acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal,
+			    num_partitions);
+       }
+
+       // assume any mosaiced file contains all slices
+       // (we now support mosaics for 2D and 3D acquisitions,
+       //  so we may need to use partitions instead of slices)
+       
+       if (!strncmp(acr_find_string(group_list,ACR_MR_acquisition_type,""),
+		    "2D",2)) {
+	 acr_insert_numeric(&group_list, EXT_Slices_in_file, num_slices);
+	 acr_insert_numeric(&group_list, 
+			    SPI_Number_of_slices_nominal,num_slices);
+       } else if (!strncmp(acr_find_string(group_list,ACR_MR_acquisition_type,
+					   ""),"3D",2)) {
+	 acr_insert_numeric(&group_list, EXT_Slices_in_file, 
+			    num_partitions);
+	 acr_insert_numeric(&group_list, SPI_Number_of_slices_nominal, 
+			    num_partitions);
+	 // also have to provide slice spacing - in case of 3D it's same
+	 // as slice thickness (and not provided in dicom header!)
+	 acr_insert_numeric(&group_list, ACR_Spacing_between_slices,
+		    acr_find_double(group_list,ACR_Slice_thickness,1.0));
+       }
+     } else {
+       acr_insert_numeric(&group_list, EXT_Slices_in_file, 1);
+     }
+
+     // correct the rows and columns values -
+     // these will reflect those of the subimages in the mosaics
+     // NOT the total image dimensions
+     acr_insert_short(&group_list, EXT_Sub_image_columns,subimage_cols);
+     acr_insert_short(&group_list, EXT_Sub_image_rows,subimage_rows);
+
+     // should also correct the image position here?
+
+   }
+
+   // correct dynamic scan info if diffusion scan:
+   //
+   // assumptions:
+   //
+   //  - diffusion protocol indicated by sDiffusion.ucMode = 0x4
+   //  - there are 7 shots for DTI (b=0 + 6 encodings)
+   //  - b=0 scan has sequence name "ep_b0"
+   //  - encoded scans have seq names "ep_b700#1, ep_b700#2, ..." etc.
+   //
+   // actions:
+   // 
+   //  - change number of dynamic scans to 7
+   //  - modify dynamic scan index to encoding index
+
+   if (!strcmp(prot_find_string(Protocol,"sDiffusion.ucMode"),"0x4")) {
+
+     // try to get b value
+     acr_insert_numeric(&group_list, 
+			EXT_Diffusion_b_value,
+			atoi((char*)prot_find_string(Protocol,
+					     "sDiffusion.alBValue[1]")));
+
+     // if all averages in one series:
+     if (!strcmp(prot_find_string(Protocol,"ucOneSeriesForAllMeas"),"0x1")){
+
+       num_encodings = 7; // for now assume 7 shots in diffusion scan
+
+       // number of 'time points'
+       acr_insert_numeric(&group_list, ACR_Acquisitions_in_series, 
+			  num_encodings*
+			  acr_find_double(group_list,ACR_Nr_of_averages,1));
+
+       // time index of current scan:
+
+       // In the current scheme, the unencoded
+       // scan has a sequence name like "ep_b0" while the subsequent
+       // six diffusion encodings have names like "ep_b700#1"
+       // we could use this to come up with indices for an encoding dimension
+       field_ptr=strstr(acr_find_string(group_list,ACR_Sequence_name,""),"#");
+       if (field_ptr == NULL) {
+	 enc_ix = 0;
+       } else {
+	 enc_ix = atoi(field_ptr+sizeof(char));
+       }
+
+       // however with the current sequence, we get usable
+       // time indices from floor(global_image_num/num_slices)
+       acr_insert_numeric(&group_list, ACR_Acquisition, 
+			  (acr_find_int(group_list, ACR_Image, 1)-1) / 
+			  num_slices);
+
+     } else { // averages in different series - no special handling needed?
+
+       num_encodings = 7; // for now assume 7 shots in diffusion scan
+
+       // number of 'time points'
+       acr_insert_numeric(&group_list, ACR_Acquisitions_in_series,
+			  num_encodings);
+
+       // For multi-series scans, we DO USE THIS BECAUSE global
+       // image number may be broken!!
+       field_ptr=strstr(acr_find_string(group_list,ACR_Sequence_name,""),"#");
+       if (field_ptr == NULL) {
+	 enc_ix = 0;
+       } else {
+	 enc_ix = atoi(field_ptr+sizeof(char));
+       }
+
+       acr_insert_numeric(&group_list, ACR_Acquisition, enc_ix);
+
+       
+     }
+   } // end of diffusion scan handling
+
+   return group_list;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : free_info
+@INPUT      : general_info
+              file_info
+              num_files
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to free contents of general and file info structures.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 26, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+/* ARGSUSED */
+public void free_info(General_Info *general_info, File_Info *file_info, 
+                      int num_files)
+{
+   Mri_Index imri;
+
+   /* Free the general info pointers */
+   for (imri=0; imri < MRI_NDIMS; imri++) {
+      if (general_info->indices[imri] != NULL) {
+         FREE(general_info->indices[imri]);
+      }
+      if (general_info->coordinates[imri] != NULL) {
+         FREE(general_info->coordinates[imri]);
+      }
+   }
+
+   /* Free the group list */
+   if (general_info->group_list != NULL) {
+      acr_delete_group_list(general_info->group_list);
+  }
+
+   return;
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : search_list
+@INPUT      : value
+              list
+              list_length
+              starting_point - point from which search should start
+@OUTPUT     : (none)
+@RETURNS    : Index in list where value is found, or -1 is value not found.
+@DESCRIPTION: Routine to search a list for a value, returning the index
+              into the list. If the value is not found, then -1 is returned.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int search_list(int value, int list[], int list_length, 
+                       int starting_point)
+{
+   int index;
+
+   /* Check list length and starting point */
+   if (list_length <= 0) return -1;
+   if ((starting_point >= list_length) || (starting_point < 0)) {
+      starting_point = 0;
+   }
+
+   /* Loop over indices, wrapping at the end of the list */
+   index = starting_point;
+   do {
+      if (list[index] == value) return index;
+      index++;
+      if (index >= list_length) index = 0;
+   } while (index != starting_point);
+
+   /* If we get to here, we didn't find the value */
+   return -1;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : sort_dimensions
+@INPUT      : general_info
+@OUTPUT     : general_info
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to sort the MRI dimensions according to their 
+              coordinates. It also fills in the step and start values for 
+              the SLICE dimension.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void sort_dimensions(General_Info *general_info)
+{
+   Mri_Index imri;
+   Sort_Element *sort_array;
+   int nvalues, ival, jval;
+   int reverse_array;
+
+   /* Sort the dimensions, if needed */
+   for (imri = 0; imri < MRI_NDIMS; imri++) {
+      if (general_info->size[imri] > 1 &&
+	  !((file_type == N4DCM) && // don't sort on time for N4 mosaics!
+	    (imri == TIME) && 
+	    (general_info->num_slices_in_file > 0))) { // also fails on 1 slice
+
+         /* Set up the array for sorting */
+         nvalues = general_info->size[imri];
+         sort_array = MALLOC(nvalues * sizeof(*sort_array));
+         for (ival=0; ival < nvalues; ival++) {
+            sort_array[ival].identifier = general_info->indices[imri][ival];
+            sort_array[ival].original_index = ival;
+            sort_array[ival].value = general_info->coordinates[imri][ival];
+         }
+
+         /* Sort the array */
+         qsort((void *) sort_array, (size_t) nvalues, sizeof(*sort_array), 
+               dimension_sort_function);
+
+         /* Figure out if we should reverse the array to keep something 
+            similar to the original ordering */
+         reverse_array = (sort_array[0].original_index > 
+                          sort_array[nvalues-1].original_index);
+
+         /* Copy the information back into the appropriate arrays */
+         for (ival=0; ival < nvalues; ival++) {
+            jval = (reverse_array ? nvalues - ival - 1 : ival);
+            general_info->indices[imri][ival] = sort_array[jval].identifier;
+            general_info->coordinates[imri][ival] = sort_array[jval].value;
+         }
+
+         /* Free the array */
+         FREE(sort_array);
+
+         /* Update slice step and start */
+         if (imri == SLICE) {
+            if (general_info->coordinates[imri][0] != 
+                general_info->coordinates[imri][nvalues-1]) {
+               general_info->step[general_info->slice_world] = 
+                  (general_info->coordinates[imri][nvalues-1] -
+                   general_info->coordinates[imri][0]) / 
+                      ((double) general_info->size[imri] - 1.0);
+            }
+            general_info->start[general_info->slice_world] =
+               general_info->coordinates[imri][0];
+         }
+
+      }       /* If size > 1 */
+   }          /* Loop over dimensions */
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : dimension_sort_function
+@INPUT      : v1, v2 - values to compare
+@OUTPUT     : (none)
+@RETURNS    : -1, 0 or 1 if v1 < v2, v1 == v2 or v1 > v2
+@DESCRIPTION: Function to compare to array elements for sorting. Elements are
+              compared first on value, then on their original array index
+              (this tries to preserve the original sequence).
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : February 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public int dimension_sort_function(const void *v1, const void *v2)
+{
+   Sort_Element *value1, *value2;
+
+   value1 = (Sort_Element *) v1;
+   value2 = (Sort_Element *) v2;
+
+   if (value1->value < value2->value)
+      return -1;
+   else if (value1->value > value2->value)
+      return 1;
+   else if (value1->original_index < value2->original_index)
+      return -1;
+   else if (value1->original_index > value2->original_index)
+      return 1;
+   else
+      return 0;
+}
+
+public char *prot_find_string(Acr_Element Protocol, char *Field) {
+
+  char FieldName[512];
+  char Separator[512];
+  char FieldValue[512];
+  char *Output = calloc(512,sizeof(char)); // return value
+
+  char ProtHead[] = "### ASCCONV BEGIN ###";
+  long prot_offset;
+  char *field_ptr;
+  char DefaultValue = '0';
+  int  ix1,ix2;
+
+  // scan throught the group containing the protocol, to find the 
+  // ascii dump of the MrProt structure
+  for (prot_offset = 0; 
+       prot_offset < Protocol->data_length - sizeof(ProtHead); 
+       prot_offset++) {
+    if (!memcmp(Protocol->data_pointer+prot_offset,
+		ProtHead,sizeof(ProtHead)-1)) {
+      break;
+    }
+  }
+
+  //  bail if we didn't find the protocol
+  if (prot_offset == Protocol->data_length-sizeof(ProtHead)) {
+    (void) fprintf(stderr,
+		   "ERROR:  could not find protocol dump in group\n");
+    exit(EXIT_FAILURE);
+  }
+
+  // try to find the Field name 
+  // (should bracket with newline and white space)
+  field_ptr = strstr(Protocol->data_pointer+prot_offset,Field);
+
+  if (field_ptr != NULL) {
+    sscanf(field_ptr,"%s %s %s",FieldName,Separator,FieldValue);
+  } else {
+    sprintf(FieldValue,"0");
+  }
+
+  // copy FieldValue to output, skipping quotation marks in strings
+
+  ix1 = 0;
+  for (ix2 = 0; ix2 < strlen(FieldValue); ix2++) {
+    if (FieldValue[ix2] != '"')
+      Output[ix1++] = FieldValue[ix2];
+  }
+
+  // terminate string
+  Output[ix1] = '\0';
+  
+  return (char*) Output;
+
+}
+
+public char *dump_protocol_text(Acr_Element Protocol) {
+
+  char ProtHead[] = "### ASCCONV BEGIN ###";
+  char ProtTail[] = "### ASCCONV END ###";
+  char *Output = calloc(Protocol->data_length,sizeof(char)); // return value
+  int  prot_found = FALSE;
+  long prot_offset;
+  int  ix1;
+
+  // scan throught the group containing the protocol, to find the 
+  // ascii dump of the MrProt structure
+  ix1 = 0;
+  for (prot_offset = 0; 
+       prot_offset < Protocol->data_length - sizeof(ProtHead); 
+       prot_offset++) {
+    if (!memcmp(Protocol->data_pointer+prot_offset,
+		ProtHead,sizeof(ProtHead)-1)) {
+      prot_found = TRUE;
+    }
+    if (!memcmp(Protocol->data_pointer+prot_offset,
+		ProtTail,sizeof(ProtTail)-1)) {
+      break;      
+    }
+    if (prot_found) {
+      if (*(Protocol->data_pointer+prot_offset) != '"')
+	Output[ix1++] = *(Protocol->data_pointer+prot_offset);
+    }
+  }
+
+  // terminate string
+  Output[ix1] = '\0';
+
+  //  bail if we didn't find the protocol
+  if (prot_offset == Protocol->data_length-sizeof(ProtHead)) {
+    (void) fprintf(stderr,
+		   "ERROR:  could not find protocol dump in group\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (char*) Output;
+
+}
+
+public int multi_image_init(Acr_Group group_list, 
+                            Multi_Image *multi_image)
+{
+   int group_id, element_id;
+   int last_image, grid_size;
+   long new_image_size;
+   void *data;
+   Acr_Element element;
+   char string[256];
+   int idim;
+   double pixel_spacing[2], separation;
+   char *protocol;
+   double normal[3];
+   double RowColVec[6];
+   double dircos[VOL_NDIMS][WORLD_NDIMS];
+
+   // Get some basic image information
+   // (big[0/1] is number of columns/rows in whole mosaic)
+   multi_image->big[0] = acr_find_int(group_list, ACR_Columns, 1);
+   multi_image->big[1] = acr_find_int(group_list, ACR_Rows, 1);
+   multi_image->pixel_size = 
+      (acr_find_int(group_list, ACR_Bits_allocated, 16)-1) / 8 + 1;
+
+   // Get the image size
+   // (size[0/1] is number of columns/rows in a single slice)
+   multi_image->size[0] = acr_find_short(group_list,EXT_Sub_image_columns,1);
+   multi_image->size[1] = acr_find_short(group_list,EXT_Sub_image_rows,1);
+
+   // Get the grid shape, checking that it is not too big if specified
+   multi_image->grid[0] = multi_image->big[0] / multi_image->size[0];
+   multi_image->grid[1] = multi_image->big[1] / multi_image->size[1];
+   if ((multi_image->grid[0] < 1) || (multi_image->grid[0] < 1)) {
+      (void) fprintf(stderr, "Grid too small: %d x %d\n",
+                     multi_image->grid[0], multi_image->grid[1]);
+      exit(EXIT_FAILURE);
+   }
+
+   // Check whether we need to do anything (1x1 grid may be the whole image)
+   grid_size = multi_image->grid[0] * multi_image->grid[1];
+   if ((grid_size == 1) &&
+       (multi_image->size[0] == multi_image->big[0]) &&
+       (multi_image->size[1] == multi_image->big[1])) {
+     /* had to remove this as now ANY images acquired with 
+	the mosaic sequence need special treatment */
+     multi_image->packed = FALSE;
+      return 1;
+   }
+
+   // Steal the image element from the group list
+   multi_image->big_image = acr_find_group_element(group_list, ACR_Pixel_data);
+
+   if (multi_image->big_image == NULL) {
+      (void) fprintf(stderr, "Couldn't find an image\n");
+      exit(EXIT_FAILURE);
+   }
+   group_id = acr_get_element_group(multi_image->big_image);
+   element_id = acr_get_element_element(multi_image->big_image);
+   acr_group_steal_element(acr_find_group(group_list, group_id),
+                           multi_image->big_image);
+
+   // Add a small image
+   new_image_size = 
+      multi_image->size[0] * multi_image->size[1] * multi_image->pixel_size;
+   data = malloc((size_t) new_image_size);
+   multi_image->small_image = 
+      acr_create_element(group_id, element_id,
+                         acr_get_element_vr(multi_image->big_image),
+                         new_image_size, data);
+   acr_set_element_vr(multi_image->small_image,
+      acr_get_element_vr(multi_image->big_image));
+   acr_set_element_byte_order(multi_image->small_image,
+      acr_get_element_byte_order(multi_image->big_image));
+   acr_set_element_vr_encoding(multi_image->small_image,
+      acr_get_element_vr_encoding(multi_image->big_image));
+   acr_insert_element_into_group_list(&group_list, multi_image->small_image);
+
+   // Update the number of image rows and columns
+   acr_insert_short(&group_list, ACR_Rows, multi_image->size[1]);
+   acr_insert_short(&group_list, ACR_Columns, multi_image->size[0]);
+
+   // Get image image index info (number of slices in file)
+   last_image = acr_find_int(group_list, EXT_Slices_in_file,1);
+
+   // sub_images is now just the number of mosaic elements, even if
+   // they don't all contain slices 
+   multi_image->sub_images = multi_image->grid[0] * multi_image->grid[1];
+
+   // unlike Numaris 3.5, last_image should always be correct
+   multi_image->first_image = last_image -
+     multi_image->sub_images + 1;
+
+   // get the pixel size
+   element = acr_find_group_element(group_list, ACR_Pixel_size);
+   if ((element != NULL) &&
+       (acr_get_element_numeric_array(element, 2, pixel_spacing) == 2)) {
+     
+     // adjust pixel size for old Numaris 3.5 data
+     if (file_type == IMA ||
+	 file_type == N3DCM) {
+       
+       pixel_spacing[0] *= 
+         (double) multi_image->big[0] / (double) multi_image->size[0];
+       pixel_spacing[1] *= 
+         (double) multi_image->big[1] / (double) multi_image->size[1];
+       (void) sprintf(string, "%.15g\\%.15g", 
+		      pixel_spacing[0], pixel_spacing[1]);
+       acr_insert_string(&group_list, ACR_Pixel_size, string);
+     }
+   }
+
+   // Get step between slices
+   separation = acr_find_double(group_list, ACR_Spacing_between_slices, 1.0);
+
+   // get image normal vector
+   // (need to compute based on dicom field, which gives
+   //  unit vectors for row and column direction)
+   element = acr_find_group_element(group_list,
+				    ACR_Image_orientation_patient);
+   acr_get_element_numeric_array(element, 6, RowColVec);
+   
+   memcpy(dircos[VCOLUMN],RowColVec,sizeof(RowColVec[0])*3);
+   memcpy(dircos[VROW],&RowColVec[3],sizeof(RowColVec[0])*3);
+   
+   // used to convert x/y flips here...
+   // convert_dicom_coordinate(dircos[VROW]);
+   // convert_dicom_coordinate(dircos[VCOLUMN]);
+
+   // compute slice normal as cross product of row/column unit vectors
+   // (should check for unit length?)
+   multi_image->normal[0] = 
+     dircos[VCOLUMN][1] * dircos[VROW][2] -
+     dircos[VCOLUMN][2] * dircos[VROW][1];
+   
+   multi_image->normal[1] = 
+     dircos[VCOLUMN][2] * dircos[VROW][0] -
+     dircos[VCOLUMN][0] * dircos[VROW][2];
+   
+   multi_image->normal[2] = 
+     dircos[VCOLUMN][0] * dircos[VROW][1] -
+     dircos[VCOLUMN][1] * dircos[VROW][0];
+
+   // compute slice-to-slice step vector
+   for (idim=0; idim < 3; idim++) {
+      multi_image->step[idim] = separation * multi_image->normal[idim];
+   }
+
+   // Get position and correct to first slice
+   element = acr_find_group_element(group_list, ACR_Image_position_patient);
+   acr_get_element_numeric_array(element, WORLD_NDIMS,multi_image->position);
+
+   if (file_type == IMA ||
+       file_type == N3DCM) {
+     // Numaris 3.5 style correction:
+     // (position in file is for last slice, we want first)
+     for (idim=0; idim < 3; idim++) {
+       multi_image->position[idim] -= 
+	 (double) (multi_image->sub_images-1) * multi_image->step[idim];
+     } 
+   } else {
+     // Numaris 4 mosaic correction:
+     // - position given is edge of huge slice constructed as if 
+     //   real slice was at center of mosaic
+     // - multi_image->big[0,1] are number of columns and rows of mosaic
+     // - multi_image->size[0,1] are number of columns and rows of sub-image
+
+     for (idim=0; idim < 3; idim++) {
+
+       // correct offset from mosaic Center
+       multi_image->position[idim] += (double)
+	 ((dircos[VCOLUMN][idim]*multi_image->big[0]*pixel_spacing[0]/2.0) +
+	  (dircos[VROW][idim] * multi_image->big[1] * pixel_spacing[1]/2));
+
+       // move from center to corner of slice
+       multi_image->position[idim] -= 
+	 dircos[VCOLUMN][idim] * multi_image->size[0] * pixel_spacing[0]/2.0 +
+	 dircos[VROW][idim] * multi_image->size[1] * pixel_spacing[1]/2.0;
+	 
+     } 
+
+   }
+
+   /* Return number of sub-images in this image */
+   return multi_image->sub_images;
+}
+
+public int multi_image_modify_group_list(Acr_Group group_list, 
+                                          Multi_Image *multi_image,
+                                          int iimage)
+{
+   int irow, ibyte, idim, nbyte;
+   int isub, jsub;
+   char *new, *old;
+   long old_offset, new_offset;
+   double position[3], distance;
+   char string[256];
+
+   // slice order in mosaic is bottom->top under Numaris 4,
+   // unlike Numaris 3.5 in which slices were top->bottom
+   if (!(file_type == IMA ||
+	 file_type == N3DCM)) {
+     iimage = acr_find_int(group_list, EXT_Slices_in_file,1) - iimage - 1;
+   } 
+
+   // Check the image number 
+   if ((iimage < 0) || (iimage > multi_image->sub_images)) {
+      (void) fprintf(stderr, "Invalid image number to send: %d of %d\n",
+                     iimage, multi_image->sub_images);
+      exit(EXIT_FAILURE);
+   }
+
+   // Figure out the sub-image indices 
+   isub = iimage % multi_image->grid[0];
+   jsub = iimage / multi_image->grid[0];
+
+   // Get pointers
+   old = acr_get_element_data(multi_image->big_image);
+   new = acr_get_element_data(multi_image->small_image);
+
+   // Copy the image
+   nbyte = multi_image->size[0] * multi_image->pixel_size;
+   for (irow=0; irow < multi_image->size[1]; irow++) {
+      old_offset = isub * multi_image->size[0] +
+         (jsub * multi_image->size[1] + irow) * multi_image->big[0];
+      old_offset *= multi_image->pixel_size;
+      new_offset = (irow * multi_image->size[0]) * multi_image->pixel_size;
+      for (ibyte=0; ibyte < nbyte; ibyte++) {
+         new[new_offset + ibyte] = old[old_offset + ibyte];
+      }
+   }
+
+   // Reset the byte order and VR encoding. This will be modified on each
+   // send according to what the connection needs.
+   acr_set_element_byte_order(multi_image->small_image,
+      acr_get_element_byte_order(multi_image->big_image));
+   acr_set_element_vr_encoding(multi_image->small_image,
+      acr_get_element_vr_encoding(multi_image->big_image));
+
+   // Update the index
+   acr_insert_numeric(&group_list, SPI_Current_slice_number, 
+		      (double) iimage);
+
+   // Update the position
+
+   for (idim=0; idim < 3; idim++) {
+     position[idim] = multi_image->position[idim] + 
+       (double) iimage * multi_image->step[idim];
+   }
+
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g",
+                  position[0], position[1], position[2]);
+   acr_insert_string(&group_list, SPI_Image_position, string);
+   acr_insert_string(&group_list, ACR_Image_position_patient, string);
+
+   if (file_type == IMA ||
+       file_type == N3DCM) {
+     // this will convert Siemens SPI info into dicom compliant info
+     // not needed for Numaris 4
+     update_coordinate_info(group_list);
+   }
+
+   return 1;
+
+}
+
+public int multi_image_cleanup(Acr_Group group_list, 
+                                Multi_Image *multi_image)
+/* ARGSUSED */
+{
+
+   if (!multi_image->packed) return;
+
+   acr_delete_element(multi_image->big_image);
+
+   return 1;
+}
+
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_dicom_to_minc.h
@@ -0,0 +1,253 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_dicom_to_minc.h
+@DESCRIPTION: Header file for siemens_dicom_to_minc.h
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: siemens_dicom_to_minc.h,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.6  2002/04/26 03:27:03  rhoge
+ * fixed MrProt problem - replaced fixed lenght char array with malloc
+ *
+ * Revision 1.5  2002/04/08 17:26:34  rhoge
+ * added additional sequence info to minc header
+ *
+ * Revision 1.4  2002/03/27 18:57:50  rhoge
+ * added diffusion b value
+ *
+ * Revision 1.3  2002/03/19 13:13:57  rhoge
+ * initial working mosaic support - I think time is scrambled though.
+ *
+ * Revision 1.2  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:51:59  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <minc.h>
+
+/* General constants */
+#define SECONDS_PER_MINUTE 60
+#define MINUTES_PER_HOUR 60
+#define SECONDS_PER_HOUR (MINUTES_PER_HOUR*SECONDS_PER_MINUTE)
+#define HOURS_PER_DAY 24
+#define SECONDS_PER_DAY (HOURS_PER_DAY*SECONDS_PER_HOUR)
+#define MS_PER_SECOND 1000
+#define COORDINATE_EPSILON (100.0*FLT_EPSILON)
+
+/* Default value for ncopts */
+#define NCOPTS_DEFAULT NC_VERBOSE
+
+/* MINC variable for dicom elements */
+#define DICOM_ROOT_VAR "dicom_groups"
+
+/* Possible MRI dimensions */
+typedef enum { SLICE = 0, ECHO, TIME, PHASE, CHEM_SHIFT, MRI_NDIMS } Mri_Index;
+
+/* World dimensions */
+typedef enum { XCOORD = 0, YCOORD, ZCOORD, WORLD_NDIMS } World_Index;
+
+/* Volume dimensions */
+typedef enum { VSLICE = 0, VROW, VCOLUMN, VOL_NDIMS } Volume_Index;
+
+/* Orientations */
+typedef enum {TRANSVERSE = 0, SAGITTAL, CORONAL, NUM_ORIENTATIONS} Orientation;
+
+/* String type */
+typedef char Cstring[256];
+
+/* Structure for general info about files */
+typedef struct {
+   int initialized;
+   double study_id;
+   int acq_id;                   /* Time of scan */
+   int rec_num;
+   int image_type;
+   Cstring image_type_string;
+   int nrows;
+   int ncolumns;
+   int default_index[MRI_NDIMS]; /* Index for dimensions with size == 1 */
+   int size[MRI_NDIMS];        /* Size of dimension across these files */
+   int total_size[MRI_NDIMS];  /* Size of dimension across acquisition */
+   int *indices[MRI_NDIMS];    /* List of indices found for each dimension.
+                                  Only allocated when size > 1 */
+   int search_start[MRI_NDIMS]; /* Indices into lists for starting searches */
+   double *coordinates[MRI_NDIMS]; /* Array indicating coordinate of each
+                                      index in indices array */
+   int image_index[MRI_NDIMS];  /* Mapping from MRI dim to output image dim */
+   World_Index slice_world;
+   World_Index row_world;
+   World_Index column_world;
+   double step[WORLD_NDIMS];
+   double start[WORLD_NDIMS];
+   double dircos[WORLD_NDIMS][WORLD_NDIMS];
+   nc_type datatype;
+   int is_signed;
+   double pixel_min;
+   double pixel_max;
+   Cstring units;
+   double window_min;
+   double window_max;
+   int num_mosaic_rows;
+   int num_mosaic_cols;
+   int num_slices_in_file;
+   int sub_image_rows;
+   int sub_image_columns;
+   struct {
+      Cstring name;
+      Cstring identification;
+      Cstring birth_date;
+      Cstring age;
+      Cstring sex;
+      Cstring reg_date;
+      Cstring reg_time;
+      double weight;
+   } patient;
+   struct {
+      Cstring start_time;
+      Cstring modality;
+      Cstring manufacturer;
+      Cstring model;
+      double  field_value;
+      Cstring software_version;
+      Cstring serial_no;
+      Cstring calibration_date;
+      Cstring institution;
+      Cstring station_id;
+      Cstring referring_physician;
+      Cstring performing_physician;
+      Cstring operator;
+      Cstring procedure;
+      Cstring study_id;
+      Cstring acquisition_id;
+   } study;
+   struct {
+      Cstring scan_seq;
+      Cstring seq_owner;
+      Cstring seq_descr;
+      Cstring protocol_name;
+      Cstring receive_coil;
+      Cstring transmit_coil;
+      double rep_time;
+      double slice_thickness;
+      double num_slices;
+      double echo_time;
+      double echo_number;
+      double inv_time;
+      double b_value;
+      double flip_angle;
+      double num_avg;
+      double num_dyn_scans;
+      double scan_dur;
+      double ky_lines;
+      double kymax_ix;
+      double kymin_ix;
+      double kz_lines;
+      double dummy_scans;
+      double imaging_freq;
+      Cstring imaged_nucl;
+      double  adc_voltage;
+      double  adc_offset;
+      double  transmit_ampl;
+      double  rec_amp_gain;
+      double  rec_preamp_gain;
+      double  win_center;
+      double  win_width;
+      double  gy_ampl;
+      double  gx_ampl;
+      double  gz_ampl;
+     double  num_phase_enc_steps;
+     double  percent_sampling;
+     double  percent_phase_fov;
+     double  pixel_bandwidth;
+     char phase_enc_dir[16];
+     char mr_acq_type[16];
+     char image_type[128];
+     double  sar;
+      Cstring comments;
+     char *MrProt;  // Siemens Numaris 4 specific
+   } acq;
+   Acr_Group group_list;
+} General_Info;
+
+/* Structure for file-specific info */
+typedef struct {
+   int valid;
+   int bits_alloc;
+   int bits_stored;
+   int index[MRI_NDIMS];
+   double pixel_max;
+   double pixel_min;
+   double slice_max;
+   double slice_min;
+   double window_max;
+   double window_min;
+   double coordinate[MRI_NDIMS];
+} File_Info;
+
+/* Structure for image data */
+typedef struct {
+   int free;
+   int nrows;
+   int ncolumns;
+   unsigned short *data;
+} Image_Data;
+
+/* Structure for sorting dimensions */
+typedef struct {
+   int identifier;
+   int original_index;
+   double value;
+} Sort_Element;
+
+// multi-image (mosaic) info
+typedef struct {
+   int packed;
+   int mosaic_seq;
+   int size[2];
+   int big[2];
+   int grid[2];
+   int pixel_size;
+   Acr_Element big_image;
+   Acr_Element small_image;
+   int sub_images;
+   int first_image;
+   double normal[3];
+   double step[3];
+   double position[3];
+} Multi_Image;
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_header_table.h
@@ -0,0 +1,211 @@
+Siemens_header_entry Siemens_header_table[] = {
+{0x0008, 0x0020, &Siemens_header.G08.Ide.StudyDate, create_ds_date_t_element, 1},
+{0x0008, 0x0022, &Siemens_header.G08.Ide.AcquisitionDate, create_ds_date_t_element, 1},
+{0x0008, 0x0023, &Siemens_header.G08.Ide.ImageDate, create_ds_date_t_element, 1},
+{0x0008, 0x0030, &Siemens_header.G08.Ide.StudyTime, create_ds_time_t_element, 1},
+{0x0008, 0x0032, &Siemens_header.G08.Ide.AcquisitionTime, create_ds_time_t_element, 1},
+{0x0008, 0x0033, &Siemens_header.G08.Ide.ImageTime, create_ds_time_t_element, 1},
+{0x0008, 0x0041, &Siemens_header.G08.Ide.DataSetSubtype, create_data_set_subtype_t_element, 1},
+{0x0008, 0x0060, &Siemens_header.G08.Ide.Modality, create_modality_t_element, 1},
+{0x0008, 0x0070, &Siemens_header.G08.Ide.Manufacturer, create_char_element, LENGTH_MANUFACTURER + 1},
+{0x0008, 0x0080, &Siemens_header.G08.Ide.InstitutionID, create_char_element, LENGTH_LABEL + 1},
+{0x0008, 0x0090, &Siemens_header.G08.Ide.ReferringPhysician, create_char_element, LENGTH_LABEL + 1},
+{0x0008, 0x1010, &Siemens_header.G08.Ide.StationID, create_char_element, LENGTH_LABEL + 1},
+{0x0008, 0x1080, &Siemens_header.G08.Ide.AdmittingDiagnosis, create_char_element, LENGTH_DIAGNOSIS + 1},
+{0x0008, 0x1090, &Siemens_header.G08.Ide.ManufacturerModel, create_char_element, LENGTH_LABEL + 1},
+{0x0009, 0x1041, &Siemens_header.G09.Ide.DataObjectSubtype, create_data_object_subtype_t_element, 1},
+{0x0009, 0x1210, &Siemens_header.G09.Ide.StorageMode, create_storage_mode_t_element, 1},
+{0x0009, 0x1226, &Siemens_header.G09.Ide.LastMoveDate, create_ds_date_t_element, 1},
+{0x0009, 0x1227, &Siemens_header.G09.Ide.LastMoveTime, create_ds_time_t_element, 1},
+{0x0009, 0x1316, &Siemens_header.G09.Ide.CPUIdentificationLabel, create_char_element, LENGTH_LABEL + 1},
+{0x0009, 0x1320, &Siemens_header.G09.Ide.HeaderVersion, create_char_element, LENGTH_HEADER_VERSION + 1},
+{0x0010, 0x0010, &Siemens_header.G10.Pat.PatientName, create_char_element, LENGTH_LABEL + 1},
+{0x0010, 0x0020, &Siemens_header.G10.Pat.PatientId, create_char_element, LENGTH_PATIENT_ID + 1},
+{0x0010, 0x0030, &Siemens_header.G10.Pat.PatientBirthdate, create_ds_date_t_element, 1},
+{0x0010, 0x0040, &Siemens_header.G10.Pat.PatientSex, create_sex_t_element, 1},
+{0x0010, 0x1010, &Siemens_header.G10.Pat.PatientAge, create_char_element, LENGTH_AGE + 1},
+{0x0010, 0x1030, &Siemens_header.G10.Pat.PatientWeight, create_long_element, 1},
+{0x0011, 0x1110, &Siemens_header.G11.Pat.RegistrationDate, create_ds_date_t_element, 1},
+{0x0011, 0x1111, &Siemens_header.G11.Pat.RegistrationTime, create_ds_time_t_element, 1},
+{0x0011, 0x1123, &Siemens_header.G11.Pat.UsedPatientWeight, create_long_element, 1},
+{0x0018, 0x0010, &Siemens_header.G18.Acq.Contrast, create_contrast_t_element, 1},
+{0x0018, 0x0050, &Siemens_header.G18.Acq.SliceThickness, create_double_element, 1},
+{0x0018, 0x0080, &Siemens_header.G18.Acq.RepetitionTime, create_double_element, 1},
+{0x0018, 0x0081, &Siemens_header.G18.Acq.EchoTime, create_double_element, 1},
+{0x0018, 0x0083, &Siemens_header.G18.Acq.NumberOfAverages, create_long_element, 1},
+{0x0018, 0x0084, &Siemens_header.G18.Acq.ImagingFrequency, create_double_element, 1},
+{0x0018, 0x0085, &Siemens_header.G18.Acq.ImagedNucleus, create_char_element, LENGTH_NUCLEUS + 1},
+{0x0018, 0x0086, &Siemens_header.G18.Acq.EchoNumber, create_long_element, 1},
+{0x0018, 0x0090, &Siemens_header.G18.Acq.DataCollectionDiameter, create_long_element, 1},
+{0x0018, 0x1000, &Siemens_header.G18.Acq.DeviceSerialNumber, create_char_element, LENGTH_LABEL + 1},
+{0x0018, 0x1020, &Siemens_header.G18.Acq.SoftwareVersion, create_char_element, LENGTH_SOFTWARE_VERSION + 1},
+{0x0018, 0x1200, &Siemens_header.G18.Acq.CalibrationDate, create_ds_date_t_element, 1},
+{0x0018, 0x1201, &Siemens_header.G18.Acq.CalibrationTime, create_ds_time_t_element, 1},
+{0x0018, 0x1250, &Siemens_header.G18.Acq.ReceivingCoil, create_char_element, LENGTH_LABEL + 1},
+{0x0018, 0x5100, &Siemens_header.G18.Acq.PatientPosition, create_patient_position_t_element, 1},
+{0x0019, 0x1010, &Siemens_header.G19.Acq1.CM.NetFrequency, create_long_element, 1},
+{0x0019, 0x1020, &Siemens_header.G19.Acq1.CM.MeasurementMode, create_measurement_mode_t_element, 1},
+{0x0019, 0x1030, &Siemens_header.G19.Acq1.CM.CalculationMode, create_calculation_mode_t_element, 1},
+{0x0019, 0x1050, &Siemens_header.G19.Acq1.CM.NoiseLevel, create_long_element, 1},
+{0x0019, 0x1060, &Siemens_header.G19.Acq1.CM.NumberOfDataBytes, create_long_element, 1},
+{0x0019, 0x1210, &Siemens_header.G19.Acq2.Mr.TotalMeasurementTime, create_double_element, 1},
+{0x0019, 0x1211, &Siemens_header.G19.Acq2.Mr.TotalMeasurementTimeCur, create_double_element, 1},
+{0x0019, 0x1212, &Siemens_header.G19.Acq2.Mr.StartDelayTime, create_double_element, 1},
+{0x0019, 0x1213, &Siemens_header.G19.Acq2.Mr.DwellTime, create_double_element, 1},
+{0x0019, 0x1214, &Siemens_header.G19.Acq2.Mr.NumberOfPhases, create_long_element, 1},
+{0x0019, 0x1220, &Siemens_header.G19.Acq2.Mr.NumberOfFourierLinesNominal, create_long_element, 1},
+{0x0019, 0x1221, &Siemens_header.G19.Acq2.Mr.NumberOfFourierLinesCurrent, create_long_element, 1},
+{0x0019, 0x1226, &Siemens_header.G19.Acq2.Mr.NumberOfFourierLinesAfterZero, create_long_element, 1},
+{0x0019, 0x1228, &Siemens_header.G19.Acq2.Mr.FirstMeasuredFourierLine, create_long_element, 1},
+{0x0019, 0x1230, &Siemens_header.G19.Acq2.Mr.AcquisitionColumns, create_long_element, 1},
+{0x0019, 0x1231, &Siemens_header.G19.Acq2.Mr.ReconstructionColumns, create_long_element, 1},
+{0x0019, 0x1250, &Siemens_header.G19.Acq2.Mr.NumberOfAverages, create_long_element, 1},
+{0x0019, 0x1260, &Siemens_header.G19.Acq2.Mr.FlipAngle, create_double_element, 1},
+{0x0019, 0x1270, &Siemens_header.G19.Acq2.Mr.NumberOfPrescans, create_long_element, 1},
+{0x0019, 0x1281, &Siemens_header.G19.Acq2.Mr.FilterTypeRawData, create_filter_type_t_element, 1},
+{0x0019, 0x1282, &Siemens_header.G19.Acq2.Mr.FilterParameterRawData, create_filter_parameter_t_element, 1},
+{0x0019, 0x1283, &Siemens_header.G19.Acq2.Mr.FilterTypeImageData, create_filter_type_image_t_element, 1},
+{0x0019, 0x1285, &Siemens_header.G19.Acq2.Mr.FilterTypePhaseCorrection, create_filter_type_t_element, 1},
+{0x0019, 0x1290, &Siemens_header.G19.Acq2.Mr.NumberOfSaturationRegions, create_long_element, 1},
+{0x0019, 0x1294, &Siemens_header.G19.Acq2.Mr.ImageRotationAngle, create_double_element, 1},
+{0x0019, 0x1298, &Siemens_header.G19.Acq2.Mr.CoilPosition, create_image_location_t_element, 1},
+{0x0019, 0x1412, &Siemens_header.G19.Acq3.Mr.MagneticFieldStrength, create_double_element, 1},
+{0x0019, 0x1414, &Siemens_header.G19.Acq3.Mr.ADCVoltage, create_double_element, 1},
+{0x0019, 0x1416, &Siemens_header.G19.Acq3.Mr.ADCOffset, create_double_element, 2},
+{0x0019, 0x1420, &Siemens_header.G19.Acq3.Mr.TransmitterAmplitude, create_double_element, 1},
+{0x0019, 0x1421, &Siemens_header.G19.Acq3.Mr.NumberOfTransmitterAmplitudes, create_long_element, 1},
+{0x0019, 0x1422, &Siemens_header.G19.Acq3.Mr.TransmitterAttenuator, create_double_element, 1},
+{0x0019, 0x1424, &Siemens_header.G19.Acq3.Mr.TransmitterCalibration, create_double_element, 1},
+{0x0019, 0x1426, &Siemens_header.G19.Acq3.Mr.TransmitterReference, create_double_element, 1},
+{0x0019, 0x1450, &Siemens_header.G19.Acq3.Mr.ReceiverTotalGain, create_double_element, 1},
+{0x0019, 0x1451, &Siemens_header.G19.Acq3.Mr.ReceiverAmplifierGain, create_double_element, 1},
+{0x0019, 0x1452, &Siemens_header.G19.Acq3.Mr.ReceiverPreamplifierGain, create_double_element, 1},
+{0x0019, 0x1454, &Siemens_header.G19.Acq3.Mr.ReceiverCableAttenuation, create_double_element, 1},
+{0x0019, 0x1455, &Siemens_header.G19.Acq3.Mr.ReceiverReferenceGain, create_double_element, 1},
+{0x0019, 0x1456, &Siemens_header.G19.Acq3.Mr.ReceiverFilterFrequency, create_long_element, 1},
+{0x0019, 0x1460, &Siemens_header.G19.Acq3.Mr.ReconstructionScaleFactor, create_double_element, 1},
+{0x0019, 0x1462, &Siemens_header.G19.Acq3.Mr.ReferenceScaleFactor, create_double_element, 1},
+{0x0019, 0x1470, &Siemens_header.G19.Acq3.Mr.PhaseGradientAmplitude, create_double_element, 1},
+{0x0019, 0x1471, &Siemens_header.G19.Acq3.Mr.ReadoutGradientAmplitude, create_double_element, 1},
+{0x0019, 0x1472, &Siemens_header.G19.Acq3.Mr.SelectionGradientAmplitude, create_double_element, 1},
+{0x0019, 0x1480, &Siemens_header.G19.Acq3.Mr.GradientDelayTime, create_gradient_delay_time_t_element, 1},
+{0x0019, 0x1482, &Siemens_header.G19.Acq3.Mr.TotalGradientDelayTime, create_double_element, 1},
+{0x0019, 0x1490, &Siemens_header.G19.Acq3.Mr.SensitivityCorrectionLabel, create_char_element, LENGTH_LABEL + 1},
+{0x0019, 0x14a0, &Siemens_header.G19.Acq3.Mr.RfWatchdogMask, create_long_element, 1},
+{0x0019, 0x14a2, &Siemens_header.G19.Acq3.Mr.RfPowerErrorIndicator, create_double_element, 1},
+{0x0019, 0x14a5, &Siemens_header.G19.Acq3.Mr.SarWholeBody, create_sar_sed_t_element, 1},
+{0x0019, 0x14a6, &Siemens_header.G19.Acq3.Mr.Sed, create_sar_sed_t_element, 1},
+{0x0019, 0x14b0, &Siemens_header.G19.Acq3.Mr.AdjustmentStatusMask, create_long_element, 1},
+{0x0019, 0x1510, &Siemens_header.G19.Acq4.CM.ParameterFileName, create_char_element, LENGTH_FILE_NAME + 1},
+{0x0019, 0x1511, &Siemens_header.G19.Acq4.CM.SequenceFileName, create_char_element, LENGTH_FILE_NAME + 1},
+{0x0019, 0x1512, &Siemens_header.G19.Acq4.CM.SequenceFileOwner, create_char_element, LENGTH_SEQUENCE_INFO + 1},
+{0x0019, 0x1513, &Siemens_header.G19.Acq4.CM.SequenceDescription, create_char_element, LENGTH_SEQUENCE_INFO + 1},
+{0x0020, 0x0010, &Siemens_header.G20.Rel.Study, create_long_element, 1},
+{0x0020, 0x0012, &Siemens_header.G20.Rel.Acquisition, create_long_element, 1},
+{0x0020, 0x0013, &Siemens_header.G20.Rel.Image, create_long_element, 1},
+{0x0020, 0x0050, &Siemens_header.G20.Rel.Location, create_long_element, 1},
+{0x0020, 0x0070, &Siemens_header.G20.Rel.ImageGeometryType, create_geometry_t_element, 1},
+{0x0020, 0x1001, &Siemens_header.G20.Rel.AcquisitionsInSeries, create_long_element, 1},
+{0x0020, 0x1020, &Siemens_header.G20.Rel.Reference, create_reference_t_element, 1},
+{0x0021, 0x1011, &Siemens_header.G21.Rel1.CM.Target, create_target_point_t_element, 1},
+{0x0021, 0x1020, &Siemens_header.G21.Rel1.CM.RoiMask, create_short_element, 1},
+{0x0021, 0x1120, &Siemens_header.G21.Rel1.CM.FoV, create_field_of_view_t_element, 1},
+{0x0021, 0x1122, &Siemens_header.G21.Rel1.CM.ImageMagnificationFactor, create_double_element, 1},
+{0x0021, 0x1130, &Siemens_header.G21.Rel1.CM.ViewDirection, create_view_direction_t_element, 1},
+{0x0021, 0x1132, &Siemens_header.G21.Rel1.CM.RestDirection, create_rest_direction_t_element, 1},
+{0x0021, 0x1160, &Siemens_header.G21.Rel1.CM.ImagePosition, create_image_location_t_element, 1},
+{0x0021, 0x1161, &Siemens_header.G21.Rel1.CM.ImageNormal, create_image_location_t_element, 1},
+{0x0021, 0x1163, &Siemens_header.G21.Rel1.CM.ImageDistance, create_double_element, 1},
+{0x0021, 0x1165, &Siemens_header.G21.Rel1.CM.ImagePositioningHistoryMask, create_short_element, 1},
+{0x0021, 0x116a, &Siemens_header.G21.Rel1.CM.ImageRow, create_image_location_t_element, 1},
+{0x0021, 0x116b, &Siemens_header.G21.Rel1.CM.ImageColumn, create_image_location_t_element, 1},
+{0x0021, 0x1170, &Siemens_header.G21.Rel1.CM.PatientOrientationSet1, create_patient_orientation_t_element, 1},
+{0x0021, 0x1171, &Siemens_header.G21.Rel1.CM.PatientOrientationSet2, create_patient_orientation_t_element, 1},
+{0x0021, 0x1180, &Siemens_header.G21.Rel1.CM.StudyName, create_char_element, LENGTH_LABEL + 1},
+{0x0021, 0x1182, &Siemens_header.G21.Rel1.CM.StudyType, create_study_type_t_element, 1},
+{0x0021, 0x1322, &Siemens_header.G21.Rel2.Mr.PhaseCorRowRec, create_long_element, 1},
+{0x0021, 0x1324, &Siemens_header.G21.Rel2.Mr.PhaseCorColRec, create_long_element, 1},
+{0x0021, 0x1330, &Siemens_header.G21.Rel2.Mr.NumberOf3DRawPartNom, create_long_element, 1},
+{0x0021, 0x1331, &Siemens_header.G21.Rel2.Mr.NumberOf3DRawPartCur, create_long_element, 1},
+{0x0021, 0x1334, &Siemens_header.G21.Rel2.Mr.NumberOf3DImaPart, create_long_element, 1},
+{0x0021, 0x1336, &Siemens_header.G21.Rel2.Mr.Actual3DImaPartNumber, create_long_element, 1},
+{0x0021, 0x1339, &Siemens_header.G21.Rel2.Mr.SlabThickness, create_double_element, 1},
+{0x0021, 0x1340, &Siemens_header.G21.Rel2.Mr.NumberOfSlicesNom, create_long_element, 1},
+{0x0021, 0x1341, &Siemens_header.G21.Rel2.Mr.NumberOfSlicesCur, create_long_element, 1},
+{0x0021, 0x1342, &Siemens_header.G21.Rel2.Mr.CurrentSliceNumber, create_long_element, 1},
+{0x0021, 0x1343, &Siemens_header.G21.Rel2.Mr.CurrentGroupNumber, create_long_element, 1},
+{0x0021, 0x1344, &Siemens_header.G21.Rel2.Mr.CurrentSliceDistanceFactor, create_double_element, 1},
+{0x0021, 0x134f, &Siemens_header.G21.Rel2.Mr.OrderOfSlices, create_order_of_slices_t_element, 1},
+{0x0021, 0x1356, &Siemens_header.G21.Rel2.Mr.RepetitionTime, create_double_element, 1},
+{0x0021, 0x1370, &Siemens_header.G21.Rel2.Mr.NumberOfEchoes, create_long_element, 1},
+{0x0028, 0x0005, &Siemens_header.G28.Pre.ImageDimension, create_short_element, 1},
+{0x0028, 0x0010, &Siemens_header.G28.Pre.Rows, create_short_element, 1},
+{0x0028, 0x0011, &Siemens_header.G28.Pre.Columns, create_short_element, 1},
+{0x0028, 0x0030, &Siemens_header.G28.Pre.PixelSize, create_pixel_size_t_element, 1},
+{0x0028, 0x0040, &Siemens_header.G28.Pre.ImageFormat, create_image_format_t_element, 1},
+{0x0028, 0x0060, &Siemens_header.G28.Pre.CompressionCode, create_compression_code_t_element, 1},
+{0x0028, 0x0100, &Siemens_header.G28.Pre.BitsAllocated, create_short_element, 1},
+{0x0028, 0x0101, &Siemens_header.G28.Pre.BitsStored, create_short_element, 1},
+{0x0028, 0x0102, &Siemens_header.G28.Pre.HighBit, create_short_element, 1},
+{0x0028, 0x0103, &Siemens_header.G28.Pre.PixelRepresentation, create_short_element, 1},
+{0x0028, 0x1050, &Siemens_header.G28.Pre.WindowCenter, create_windows_t_element, 1},
+{0x0028, 0x1051, &Siemens_header.G28.Pre.WindowWidth, create_windows_t_element, 1},
+{0x0028, 0x1052, &Siemens_header.G28.Pre.RescaleIntercept, create_long_element, 1},
+{0x0028, 0x1053, &Siemens_header.G28.Pre.RescaleSlope, create_long_element, 1},
+{0x0029, 0x1110, &Siemens_header.G29.Pre.WindowStyle, create_window_style_t_element, 1},
+{0x0029, 0x1120, &Siemens_header.G29.Pre.PixelQualityCode, create_pixel_quality_code_t_element, 1},
+{0x0029, 0x1152, &Siemens_header.G29.Pre.SortCode, create_long_element, 1},
+{0, 0, NULL, NULL, 0}
+};
+
+
+/* Functions needed for this table:
+
+      create_calculation_mode_t_element
+      create_char_element
+      create_compression_code_t_element
+      create_contrast_t_element
+      create_data_object_subtype_t_element
+      create_data_set_subtype_t_element
+      create_double_element
+      create_ds_date_t_element
+      create_ds_time_t_element
+      create_field_of_view_t_element
+      create_filter_parameter_t_element
+      create_filter_type_image_t_element
+      create_filter_type_t_element
+      create_gate_phase_t_element
+      create_geometry_t_element
+      create_gradient_delay_time_t_element
+      create_image_format_t_element
+      create_image_location_t_element
+      create_laterality_t_element
+      create_long_element
+      create_measurement_mode_t_element
+      create_modality_t_element
+      create_object_orientation_t_element
+      create_object_threshold_t_element
+      create_order_of_slices_t_element
+      create_patient_orientation_t_element
+      create_patient_phase_t_element
+      create_patient_position_t_element
+      create_patient_region_t_element
+      create_pixel_quality_code_t_element
+      create_pixel_quality_value_t_element
+      create_pixel_size_t_element
+      create_reference_t_element
+      create_rest_direction_t_element
+      create_rotation_direction_t_element
+      create_sar_sed_t_element
+      create_save_code_t_element
+      create_sex_t_element
+      create_short_element
+      create_storage_mode_t_element
+      create_study_type_t_element
+      create_target_point_t_element
+      create_view_direction_t_element
+      create_window_style_t_element
+      create_windows_t_element
+
+ */
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/STC_Common_Status.h
@@ -0,0 +1,720 @@
+/*------------------------------------------------------------------------------*
+ *										*
+ *	File Name :	STC_Common_Status.h					*
+ *										*
+ *	Author :	M. Rohbrecht	CMS / SME 24	Tel. ... 9131 84 4790	*
+ *	Author :	C. Schaefer	CMS / SME 24	Tel. ... 9131 84 4790	*
+ *	Author :	J.H. Siebert	CMS / SME 24	Tel. ... 9131 84 4790	*
+ *										*
+ *	Description :	Based on the definition of the structure of a status	*
+ *			file, the common (CMS) part can be found in the include	*
+ *			module `STC_Status.h`.					*
+ *										*
+ *			The contents of this include file is in consistency 	*
+ *			with the definition of the document 'Contents of	*
+ *			Status-, Configuration,- and Common Files' for the part	*
+ *			of 'Status File'. 					*
+ *										*
+ *			The informations for 'General Installation' and 'Fixed	*
+ *			Device Conditions' are found inhere.			*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	July 9th 1990		Creation			*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	August 6th 1990		Integration of exposure data	*
+ *						for company S.E.P.P.		*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	October 22nd 1990	Integration of device data and 	*
+ *						additional camera data.		*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	December 11th 1990	Integration of modality 	*
+ *						subtype (enum + variable).	*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	January 17th 1991	Integration of		 	*
+ *						- STC_Config_Hostname		*
+ *						- STC_Config_Consoles		*
+ *						- STC_Config_Host_Dbhost	*
+ *						- STC_Config_Host_Dbserver	*
+ *						- STC_Config_Host_Camera	*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	January 18th 1991	Integration of		 	*
+ *						- STC_Camera_1_Code		*
+ *						- STC_Camera_2_Code		*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	February 15th 1991	by J. H. Siebert		*
+ *						Integration of		 	*
+ *						- Country Code for Japan	*
+ *						- __STC_Enum_UNDEFINED		*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	February 22nd 1991	by C. Schaefer			*
+ *						Integration of		 	*
+ *						- STC_Maxicam_Auto_Filmtransport*
+ *										*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	March 12th 1991	by C. Schaefer				*
+ *						Integration of		 	*
+ *						- STC_Maxicam_Density		*
+ *						- STC_Maxicam_LUT		*
+ *						- STC_Num_Of_Cameras		*
+ *										*
+ *------------------------------------------------------------------------------*
+ *	Last Change :					(J.H. Siebert)		*
+ *	May 16th 1991	STC_PACS_NodeList introduced				*
+ *	June 25th 1991	STC_PACS_NodeFlag_t is now an int (before: enum),	*
+ *			__STC_PACS_NodeActiveSUN introduced			*
+ *	July, 9th 1991	Integration of STC_Customer, STC_City, STC_Destrict	*
+ *	Aug, 14th 1991	Integration of STC_dsvWinAutoCorr			*
+ *										*
+ *------------------------------------------------------------------------------*
+ *	STC_Device_Net_Installed seems not to be used				*
+ *------------------------------------------------------------------------------*
+ *										*
+ *	Last Change :	Sep 9th 1991	by C. Schaefer				*
+ *						Integration of STC_VCR_Norm 	*
+ *------------------------------------------------------------------------------*
+ *	Last Change :					(J.H. Siebert)		*
+ *	November 4th 1991	New:						*
+ *				__STC_PACS_Country_Other, __STC_PACS_Country_UK	*
+ *				STC_DefaultHospitalInstall,			*
+ *				   STC_CustomerHospitalInstall			*
+ *				STC_MIN_WINAUT_CORR, STC_MAX_WINAUT_CORR	*
+ *				STC_InstallCountry_t STC_Installation_Country	*
+ *										*
+ *      30Apr92    CHARM 205149 J.H.Siebert                                     *
+ *				Country and PACS code with additional countries *
+ *------------------------------------------------------------------------------*/
+
+#ifndef BASIC_STC_DEFINE
+#define	BASIC_STC_DEFINE	TRUE
+
+#ifndef	__STC_Enum_UNDEFINED
+#define __STC_Enum_UNDEFINED	(-19222)
+#endif
+
+#define	CHAR	char
+#define	UL	unsigned long
+#define	US	unsigned short
+#define	SS	short
+#define	DO	double
+#define	SL	long int
+
+
+/*------------------------------------------------------------------------------*/
+
+#define	__STC_BASIC_DATA_LEN		8192
+
+/*------------------------------------------------------------------------------*
+ *	For those variables of the status file where bitwise definitions are	*
+ *	needed, no enums are defined, but #define statements.			*
+ *------------------------------------------------------------------------------*/
+
+#define	__STC_Type_None				0
+#define	__STC_Type_MINICAM			1
+#define	__STC_Type_MAXICAM			2
+
+#define	__STC_LISA_Present			1
+#define	__STC_LISA_Not_Present			0
+
+#define	__STC_Plotter_Present			1
+#define	__STC_Plotter_Not_Present		0
+
+#define	__STC_Input_Mouse			1
+#define	__STC_Input_Trackball			2
+
+#define	__STC_HostnameLen			8	/*** Ex 16Bytes ?***/
+
+
+/******************\
+* Defines for PACS *
+*                  *
+\******************/
+
+#define	__STC_PACS_Country_None		    "000"
+#define	__STC_PACS_Country_Other	    "999"
+#define	__STC_PACS_Country_USA		    "001"
+/* START CHANGE CHARM 205149 J.H.Siebert 30Apr92 */
+#define	__STC_PACS_Country_France	    "033"
+#define	__STC_PACS_Country_Italy	    "039"
+/* END CHANGE CHARM 205149 J.H.Siebert 30Apr92 */
+#define	__STC_PACS_Country_Germany	    "049"
+#define	__STC_PACS_Country_Japan	    "081"
+#define	__STC_PACS_Country_UK		    __STC_PACS_Country_Other
+
+/*** NEW May, 16th 1991 J.H. Siebert***/
+
+#define __STC_PACS_NUMOF_NODES		16
+
+#define __STC_PACS_NODE_LOG_LEN		__STC_HostnameLen
+#define __STC_PACS_NODE_PHYS_LEN	__STC_PACS_NODE_LOG_LEN
+
+/* defines of flags */
+typedef int	STC_PACS_NodeFlag_t;
+#define    __STC_PACS_NodeNULL		0
+#define    __STC_PACS_NodeActive 	1
+#define    __STC_PACS_NodeSUN		8
+#define    __STC_PACS_NodeFlag_UNDEFINED  __STC_Enum_UNDEFINED
+
+typedef enum
+{
+    __STC_PACS_NodeOwn = 0,
+    __STC_PACS_NodeRmt1, __STC_PACS_NodeRmt2, __STC_PACS_NodeRmt3,
+    __STC_PACS_NodeRmt4, __STC_PACS_NodeRmt5, __STC_PACS_NodeRmt6,
+    __STC_PACS_NodeRmt7,  __STC_PACS_NodeRmt8, __STC_PACS_NodeRmt9,
+    __STC_PACS_NodeRmt10, __STC_PACS_NodeRmt11, __STC_PACS_NodeRmt12,
+    __STC_PACS_NodeRmt13, __STC_PACS_NodeRmt14, __STC_PACS_NodeRmt15,
+    __STC_PACS_Node_UNDEFINED = __STC_Enum_UNDEFINED
+} STC_PACS_NodeNum_t;
+
+
+typedef struct
+{
+    STC_PACS_NodeFlag_t		flag;	/* PACSNET configurationbits */
+    char log[__STC_PACS_NODE_LOG_LEN+1];		/* logical name */
+/***    char log_ext[65-__STC_PACS_NODE_LOG_LEN];***/	/* logical name extension*/
+
+    char phys[__STC_PACS_NODE_PHYS_LEN+1];		/* physical name */
+/***    char phys_ext[65-__STC_PACS_NODE_PHYS_LEN];***/	/* physical name extension*/
+
+} STC_PACS_node_t;
+
+typedef struct
+{
+    STC_PACS_node_t node[__STC_PACS_NUMOF_NODES];
+} STC_PACS_nodelist_t;
+
+
+/*****************************************************************/
+
+
+#define	__STC_Net_Present			1
+#define	__STC_Net_Not_Present			0
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	In case of a defined and limited value range enum definitions are used.	*
+ *										*
+ *------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Modality_CT = 1,
+		__STC_Modality_MR,
+		__STC_Modality_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Modality_t;
+
+
+	typedef	enum
+	{
+		__STC_Modality_Sub_M2 = 0,
+		__STC_Modality_Sub_P8 = 1,
+		__STC_Modality_Sub_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Modality_Sub_t;
+
+
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Weight_Kg = 1,
+		__STC_Weight_lbs,
+		__STC_Weight_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Weight_t;
+
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Main_Console = 1,
+		__STC_Satellite_Console,
+		__STC_Console_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Console_t;
+	
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Language_English = 1,
+		__STC_Language_German,
+		__STC_Language_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Language_t;
+
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Device_Type_Unknown = 1,
+		__STC_Device_Type_Magnetic_Disk,
+		__STC_Device_Type_Magnetic_Tape,
+		__STC_Device_Type_Optical_Disk,
+		__STC_Device_Type_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Device_t;
+
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Net_Installed = 1,
+		__STC_Net_Not_Installed,
+		__STC_Net_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Net_t;
+
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_Minicam_Matrix_512 = 1,
+		__STC_Minicam_Matrix_484,
+		__STC_Minicam_Matrix_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Minicam_Matrix_t;
+	
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_VCR_NORM_PAL = 1,
+		__STC_VCR_NORM_NTSC,
+		__STC_VCR_NORM_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_VCR_Norm_t;
+	
+/*------------------------------------------------------------------------------*/
+
+	typedef	enum
+	{
+		__STC_List_Lokalizer_F = 1,
+		__STC_List_Lokalizer_A,
+		__STC_List_Lokalizer_N,
+		__STC_List_Lokalizer_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_List_Lokalizer_Default_t;
+	
+	typedef	enum
+	{
+		__STC_NULL_VERSION = 0,
+		__STC_91E5_VERSION,
+		__STC_91E7_VERSION,
+		__STC_91E11_VERSION,
+		__STC_Version_UNDEFINED = __STC_Enum_UNDEFINED
+		
+	}	STC_Version_t;
+	
+#define	__STC_INFO_VERSION_LEN	32
+
+	typedef	struct
+	{
+	    int flag;
+	    char version[__STC_INFO_VERSION_LEN+1];
+	} STC_Info_t;
+	
+	
+	typedef struct
+	{
+	    char space[__STC_BASIC_DATA_LEN -
+	    	(sizeof(STC_Version_t) + sizeof(STC_Info_t))];
+	    STC_Info_t	info;
+	    STC_Version_t Version;
+	}  structInfo_t;
+	
+#define	__STC_CustomerLen	26
+#define	__STC_CityLen		26
+#define	__STC_DestrictLen	26
+
+#define	__STC_InstallationLen	26
+#define	__STC_CustomerHospitalNUM	3
+
+/*********************************\
+*                                 *
+* MR requirement (ui_window, ...) *
+*                                 *
+\*********************************/
+
+#define STC_MIN_WINAUT_CORR	0
+#define STC_MAX_WINAUT_CORR	5
+
+	typedef struct
+	{
+	    int	center;
+	    int	width;
+	    int	part;
+	}  STC_dsvWinAutoCorr_t;
+	
+
+/***************************\
+*                           *
+* MR requirement (M. Gress) *
+*                           *
+\***************************/
+
+/* START CHANGE CHARM 205149 J.H.Siebert 30Apr92 */
+
+typedef enum
+{
+    __STC_InstallCountry_USA = 1,
+    __STC_InstallCountry_GERMANY,
+    __STC_InstallCountry_UK,
+    __STC_InstallCountry_JAPAN,
+    __STC_InstallCountry_FRANCE,
+    __STC_InstallCountry_ITALY,
+    __STC_InstallCountry_OTHERS = 99,
+    __STC_InstallCountry_UNDEFINED  = __STC_Enum_UNDEFINED
+} STC_InstallCountry_t;
+
+/* END CHANGE CHARM 205149 J.H.Siebert 30Apr92 */
+
+
+	
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Union and structure definition of the 8 KByte of common status file	*
+ *	data									*
+ *										*
+ *------------------------------------------------------------------------------*/
+
+union	__STC_BASIC_DATA
+{
+    char		space	[__STC_BASIC_DATA_LEN];	/* 8 blocks for map	*/
+    
+    structInfo_t	structInfo;
+    
+    struct blablabla			/* Name needed only for STC tool for 	*/
+					/* naming within the debugger - Dummy	*/
+    {
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Manufacturer and installation						*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+ 
+	CHAR	STC_Manufacturer [8+1];		/* Name of Manufacturer, e.g.	*/
+						/* SIEMENS.			*/
+						
+	CHAR	STC_Manufacturer_Model [26+1];	/* Manufacturer's model, e.g.	*/
+						/* SOMATOM, MAGNETOM		*/
+						
+	CHAR	STC_Installation_Name [__STC_InstallationLen+1];
+						/* Name of hospital, instal.	*/
+
+	CHAR	STC_Software_Version [8+1];	/* Software version for image 	*/
+						/* text				*/
+
+	UL	STC_Int_Software_Version;	/* Internal software version	*/
+
+
+/*------------------------------------------------------------------------------*
+ *	PACS data								*
+ *------------------------------------------------------------------------------*/
+						
+	CHAR	STC_PACS_Country_Code [3+1];	/* Country code for PACS	*/
+						/* installation			*/
+	
+	CHAR	STC_PACS_Identification [3+1];	/* Manufacturer PACS identifi-	*/
+						/* cation			*/
+						
+	CHAR	STC_PACS_Modality [4+1];	/* Modality PACS identification */
+	
+#ifndef VERSION_NO_PACS
+	STC_PACS_nodelist_t	STC_PACS_NodeList; /* List of nodes in net */
+#endif
+
+	UL	STC_Serial_Number;		/* Serial number of installation*/
+	
+	UL	STC_System_Code;		/* System Code - to be defined	*/
+
+	STC_Modality_t	STC_Modality;		/* System Modality		*/
+	
+	STC_Language_t	STC_System_Language;	/* User language		*/
+	
+	STC_Weight_t	STC_Weight_System;	/* Weight system		*/
+
+	UL	STC_Net_Frequency;		/* Net frequency in Hz		*/
+
+	STC_Console_t	STC_Console_Type;	/* Either main or satellite	*/
+	
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Camera data								*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+ 
+ 	UL	STC_Camera_Display_Birthday;	/* Text superimposing of birth-	*/
+ 						/* day				*/
+						/* Yes = 1			*/
+						/* No = 0			*/
+
+	UL	STC_Camera_1_Type;		/* Type of instal. camera no. 1	*/
+						/* <no camera> = 0		*/
+						/* MINICAM = 1			*/
+						/* MAXICAM = 2			*/
+						/* . . . 			*/
+	
+	UL	STC_Camera_2_Type;		/* Type of instal. camera no. 2	*/
+						/* <no camera> = 0		*/
+						/* MINICAM = 1			*/
+						/* MAXICAM = 2			*/
+						/* . . . 			*/
+						
+	UL	STC_Camera_1_Code;		/* Code for type of instal.	*/
+						/* camera no. 1			*/
+						/* <no camera> = 0		*/
+						/* DIGICAM = 1			*/
+						/* . . . 			*/
+	
+	UL	STC_Camera_2_Code;		/* Code for type of instal.	*/
+						/* camera no. 2			*/
+						/* <no camera> = 0		*/
+						/* DIGICAM = 1			*/
+						/* . . . 			*/
+	
+	CHAR	STC_Camera_1_Name [40+1];	/* Name of camera no. 1		*/
+	
+	CHAR	STC_Camera_2_Name [40+1];	/* Name of camera no. 2		*/
+	
+	UL	STC_Camera_1_Copy_Range;	/* Copy range for exposure	*/
+	
+	UL	STC_Camera_1_Low_Level_Timer;	/* Low level timer		*/
+	
+	UL	STC_Camera_1_High_Level_Timer;	/* High level timer		*/
+	
+	UL	STC_Camera_2_Copy_Range;	/* Copy range for exposure	*/
+	
+	UL	STC_Camera_2_Low_Level_Timer;	/* Low level timer		*/
+	
+	UL	STC_Camera_2_High_Level_Timer;	/* High level timer		*/
+	
+	
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Special entries for MINICAM only					*
+ *										*
+ *	A maximum of 100 different film formats is possible. The actual valid	*
+ *	number of formats is inquired within the installation. Only those ele-	*
+ *	ments are supplied during instalation.					*
+ *										*
+ *------------------------------------------------------------------------------*/
+	
+	
+	UL	STC_Minicam_Num_of_Formats;	/* Numver of valid formats	*/
+	
+	
+	UL	STC_Minicam_Filmsize [100];
+	
+	UL	STC_Minicam_Format [100];
+	
+	UL	STC_Minicam_Format_Code [100];
+	
+	US	STC_Minicam_Row [100];
+	
+	US	STC_Minicam_Col [100];
+	
+	STC_Minicam_Matrix_t	STC_Minicam_Matrixsize;
+	
+	
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Lokalizer components							*
+ *										*
+ *------------------------------------------------------------------------------*/
+
+
+	STC_List_Lokalizer_Default_t	STC_List_Lokalizer_Default;
+	
+	
+/*------------------------------------------------------------------------------*
+ *										*
+ *	SMIV hardware components						*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+ 
+	UL	STC_LISA_Present;		/* Is component LISA installed	*/
+						/* Yes = 1			*/
+						/* No = 0			*/
+						/* . . . 			*/
+
+	UL	STC_Plotter_Present;		/* Is a plotter installed	*/
+						/* Yes = 1			*/
+						/* No = 0			*/
+						/* . . . 			*/
+						
+
+	UL	STC_SIAM_Memsize;		/* Number of MBytes for SIAM	*/
+	
+	UL	STC_Num_of_Mem_Board;		/* Number of boards for additi-	*/
+						/* onal imager memory		*/
+
+	UL	STC_Add_Mem_Size;		/* Number of MByte per board	*/
+						/* for additional imager memory	*/
+
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Graphical input medium							*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+ 
+	UL	STC_Graphic_Input_Type;		/* Kind of graphical input :	*/
+						/* Mouse = 1			*/
+						/* Trackball = 2		*/
+						/* . . . 			*/
+
+	UL	STC_Graphic_Input_Character [3]; /* Factors for hysteresis	*/
+						/* curve oF sensitivity of	*/
+						/* graphical input		*/
+
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Patient storage device data						*
+ *										*
+ *------------------------------------------------------------------------------*/
+
+
+	STC_Device_t	STC_Device_Type [10];	/* Kind of device :		*/
+						/* Magnetic Disk		*/
+						/* Magnetic Tape		*/
+						/* Optical Disk			*/
+						/* . . .			*/
+	
+	CHAR	STC_Device_Manufacturer_Name [10] [19+1];
+						/* Name of Device manufacturer	*/
+	
+	UL	STC_Device_Net_Installed;	/* Is a Net installed :		*/
+						/* Yes = 1			*/
+						/* No = 0			*/
+						/* . . . 			*/
+
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Installation status encoding						*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+ 
+	UL	STC_Installation_Status;	/* Encoded status of already	*/
+						/* done	installation steps (e.g.*/
+						/* first installation, partial 	*/
+						/* installation, etc.)		*/
+
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Modality sub-type. This field contains informations about		*
+ *	variants of the modality described in STC_Modality (e.g.		*
+ *	STC_Modality == MR and STC_Modality_Sub == STC_Modality_Sub_P8). 	*
+ *	This field can be used by both, CT and MR modalities.			*
+ *										*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+	STC_Modality_Sub_t	STC_Modality_Sub;	/* System Modality
+							   Sub-type */
+
+
+/*------------------------------------------------------------------------------*
+ *										*
+ *	Host configuration data.						*
+ *										*
+ *										*
+ *------------------------------------------------------------------------------*/
+ 
+	CHAR	STC_Config_Hostname      [__STC_HostnameLen+1];	/* Name of own host	   */
+
+	CHAR	STC_Config_Consoles   [8][__STC_HostnameLen+1];	/* Name of other hosts	   */
+
+	CHAR	STC_Config_Host_Dbhost   [__STC_HostnameLen+1];	/* Name of database host   */
+
+	CHAR	STC_Config_Host_Dbserver [__STC_HostnameLen+1];	/* Name of database server */
+
+	CHAR	STC_Config_Host_Camera   [__STC_HostnameLen+1];	/* Name of camera host	   */
+
+
+/*------------------------------------------------------------------------------*
+ *	Special entries for MAXICAM only					*
+ *------------------------------------------------------------------------------*/
+	
+	UL	STC_Maxicam_Auto_Filmtransport;	/*			   */
+	UL	STC_Maxicam_Density;		/*			   */
+	UL	STC_Maxicam_LUT;		/*			   */
+
+	UL	STC_Num_Of_Cameras;		/*			   */
+
+/*------------------------------------------------------------------------------*
+ *	CT requirement				 				*
+ *------------------------------------------------------------------------------*/
+
+	CHAR	STC_Customer	[__STC_CustomerLen+1];	/* Name of customer	*/
+	CHAR	STC_City	[__STC_CityLen+1];	/* Name of city		*/
+	CHAR	STC_Destrict	[__STC_DestrictLen+1];	/* Name of destrict	*/
+	
+	
+/*------------------------------------------------------------------------------*
+ *	MR requirement				 				*
+ *------------------------------------------------------------------------------*/
+
+	STC_dsvWinAutoCorr_t	STC_dsvWinAutoCorr;
+
+/*------------------------------------------------------------------------------*
+ *	MR requirement				 				*
+ *------------------------------------------------------------------------------*/
+
+	STC_VCR_Norm_t	STC_VCR_Norm;	/* Videonorm of Camera	*/
+	
+/*------------------------------------------------------------------------------*
+ *	New requirement				 				*
+ *------------------------------------------------------------------------------*/
+
+	STC_InstallCountry_t	STC_Installation_Country;
+						
+
+	CHAR	STC_DefaultHospitalInstall[__STC_InstallationLen+1];
+						/* Name of default hospital	*/
+	CHAR	STC_CustomerHospitalInstall [__STC_CustomerHospitalNUM] [__STC_InstallationLen+1];
+						/* Name of customer hospital, 
+						via ui_text installed	*/
+
+
+    }	s;
+};
+
+/*------------------------------------------------------------------------------*/
+
+struct	STC_COMMON
+{
+	union	__STC_BASIC_DATA	Basic;
+};
+
+/*------------------------------------------------------------------------------*/
+
+#endif
+
+/*------------------------------------------------------------------------------*/
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_date.h
@@ -0,0 +1,109 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_date.h
+
+   Description: The header file defines the basic types, constants and macros for the
+                data set library part "ds_date": date and time converting handling.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_DATE
+#define DS_DATE
+
+/* DECLARATION: types */
+
+typedef struct ds_date_tag
+{
+  long Year;						   /* four digits e.g. 1989 */
+  long Month;						   /* 1 - 12 */
+  long Day;						   /* 1 - 31 */
+} ds_date_t;
+
+
+typedef struct ds_time_tag
+{
+  long Hour;						   /* 0 - 23 */
+  long Minute;						   /* 0 - 59 */
+  long Second;						   /* 0 - 59 */
+  long Fraction;					   /* 0 - 999 */
+} ds_time_t;
+
+
+typedef struct date_position_table_tag
+{
+  long PreBegin;					   /* number of first character of
+							      date string part pre-number;
+							      always 0 */
+  long PreDelimiter;					   /* number of pre-delimiter
+							      character */
+  long MonthBegin;					   /* number of first character of
+							      date string part month */
+  long PostDelimiter;					   /* number of post-delimiter
+							      character */
+  long PostBegin;					   /* number of first character of
+							      date string part post-number */
+} date_position_table_t;
+
+
+typedef struct time_position_table_tag
+{
+  long HourBegin;					   /* number of first character of
+							      time string part hour; always 0 */
+  long HourDelimiter;					   /* number of hour delimiter
+							      character */
+  long MinuteBegin;					   /* number of first character of
+							      time string part minute */
+  long MinuteDelimiter;					   /* number of minute delimiter
+							      character */
+  long SecondBegin;					   /* number of first character of
+							      time string part second */
+  long SecondDelimiter;					   /* number of second delimiter
+							      character */
+  long FractionBegin;					   /* number of first character of
+							      time string part fraction */
+
+} time_position_table_t;
+
+
+typedef union ds_pdp_time_tag
+{
+  short ValueAsShort[2];
+  long ValueAsLong;
+} ds_pdp_time_t;
+
+
+
+/* PRECOMPILER: common constants */
+#define CENTURY                                                                         1900L
+#define DEFAULT                                                                            0L
+#define MAX_ALLOWED_DATE_STRING_LENGTH                                                    20L
+#define MAX_ALLOWED_TIME_STRING_LENGTH                                                    15L
+#define WITH_FRACTION                                                                      2L
+#define WITH_SECOND                                                                        1L
+
+
+/* PRECOMPILER: range constants */
+#define DS_A_DAY_IN_MS                                          (24.0 * 60.0 * 60.0 * 1000.0)
+#define DS_A_HOUR_IN_MS                                                      (60 * 60 * 1000)
+#define DS_A_MINUTE_IN_MS                                                         (60 * 1000)
+#define DS_A_SECOND_IN_MS                                                              (1000)
+
+#define DS_A_HOUR_IN_S                                                              (60 * 60)
+#define DS_A_MINUTE_IN_S                                                                 (60)
+
+
+/* PRECOMPILER: delimiter constants */
+#define COMMON_DATE_DELIMITER_SET                                                      ".-/:"
+#define DB_DATE_DELIMITER_SET                                                             "-"
+#define NEMA_DATE_DELIMITER_SET                                                           "."
+#define VMS_DATE_DELIMITER_SET                                                            "-"
+#define COMMON_TIME_DELIMITER_SET                                                      ":.-/"
+#define DB_TIME_DELIMITER_SET                                                             ":"
+#define NEMA_TIME_DELIMITER_SET                                                          ":."
+#define VMS_TIME_DELIMITER_SET                                                           ":."
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_functions.h
@@ -0,0 +1,560 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_functions.h
+
+   Description: The header file defines all functions declared by Data Set Library.
+
+                To generate an actual function list delete the current list and copy the
+                output of following command as statements in paragraph 'Sequence:
+                define functions'.
+
+                % grep "Name:" ds_*.c | grep "()" | awk '{print "   long " $3 ";"}' | sort
+
+
+                To generate an actual modul list use the command:
+
+                % ls -l ds_*.c | awk '{print "   " $8}'
+
+
+                To generate an actual header file list use the command:
+
+                % ls -l ds_*.h | awk '{print "   " $8}'
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+/* NOTE: list of data set library source code moduls */
+/* The first 15 characters must be unique. The unix "ar" utility works only with the first
+   15 characters. */
+/*
+   ds_456789012345----0----5----0
+   ds_adapt.c
+   ds_build_acr.c
+   ds_build_area.c
+   ds_build_s1.c
+   ds_build_s2.c
+   ds_build_up.c
+   ds_collect.c
+   ds_convert.c
+   ds_date.c
+   ds_db.c
+   ds_fill_acr.c
+   ds_fill_area.c
+   ds_fill_s1.c
+   ds_fill_s2.c
+   ds_fill_sha.c
+   ds_format.c
+   ds_get1.c
+   ds_get2.c
+   ds_head.c
+   ds_info.c
+   ds_interface.c
+   ds_mani.c
+   ds_mixed.c
+   ds_num1.c
+   ds_num1_xyz.c
+   ds_num2.c
+   ds_num2_xyz.c
+   ds_parser.c
+   ds_post.c
+   ds_pre.c
+   ds_separate.c
+   ds_set2.c
+   ds_set_s.c
+   ds_som0_b1.c
+   ds_som0_b2.c
+   ds_som0_b3.c
+   ds_som0_b4.c
+   ds_som0_b5.c
+   ds_som0_s.c
+   ds_som1.c
+   ds_split.c
+   ds_string.c
+   ds_text.c
+   ds_top.c
+   ds_transform.c
+   ds_vector.c
+   ds_xyz.c
+   ds_456789012345----0----5----0
+*/
+
+
+/* NOTE: list of data set library header files */
+/*
+   ds_date.h
+   ds_functions.h
+   ds_head_acr_groups_types.h
+   ds_head_basic_types.h
+   ds_head_constants.h
+   ds_head_image_text_type.h
+   ds_head_numaris1.h
+   ds_head_numaris2.h
+   ds_head_shadow_groups_types.h
+   ds_head_somaris0.h
+   ds_head_somaris1.h
+   ds_head_type.h
+   ds_include_files.h
+   ds_mani.h
+   ds_messages.h
+   ds_transformation.h
+   ds_transformation_control.h
+*/
+
+
+#ifndef DS_FUNCTIONS
+#define DS_FUNCTIONS
+
+/* DECLARATION: define data set library functions */
+
+  /* DECLARATION: define integer data set library functions */
+  long ds_adapt_double();
+  long ds_adapt_int();
+  long ds_adapt_string();
+  long ds_build_up_char_buf();
+  long ds_build_up_cms_nema_data_set();
+  long ds_build_up_data_groups();
+  long ds_build_up_graphic_groups();
+  long ds_build_up_group0008();
+  long ds_build_up_group0009();
+  long ds_build_up_group0010();
+  long ds_build_up_group0011();
+  long ds_build_up_group0013();
+  long ds_build_up_group0018();
+  long ds_build_up_group0019();
+  long ds_build_up_group0020();
+  long ds_build_up_group0021();
+  long ds_build_up_group0028();
+  long ds_build_up_group0029();
+  long ds_build_up_group0051();
+  long ds_build_up_group600x();
+  long ds_build_up_group6021();
+  long ds_build_up_group7FE0();
+  long ds_build_up_group7FE1();
+  long ds_build_up_header_groups();
+  long ds_build_up_header_groups();
+  long ds_build_up_image_text_item_value();
+  long ds_build_up_key();
+  long ds_build_up_long_buf();
+  long ds_build_up_short_buf();
+  long ds_build_up_som00008();
+  long ds_build_up_som00009();
+  long ds_build_up_som00010();
+  long ds_build_up_som00011();
+  long ds_build_up_som00018();
+  long ds_build_up_som00020();
+  long ds_build_up_som00021();
+  long ds_build_up_som00028();
+  long ds_build_up_som0600x();
+  long ds_build_up_som07001();
+  long ds_build_up_som07003();
+  long ds_build_up_som07005();
+  long ds_build_up_som0_blocked_data_set();
+  long ds_build_up_som0_framed_data_set();
+  long ds_collect_calculation_mode();
+  long ds_collect_cardiac_code();
+  long ds_collect_compression_code();
+  long ds_collect_contrast();
+  long ds_collect_data_object_subtype();
+  long ds_collect_data_object_type();
+  long ds_collect_data_set_subtype();
+  long ds_collect_data_set_type();
+  long ds_collect_date();
+  long ds_collect_filter_type();
+  long ds_collect_filter_type_image();
+  long ds_collect_gate_phase();
+  long ds_collect_ident();
+  long ds_collect_image_format();
+  long ds_collect_image_geometry_type();
+  long ds_collect_image_location();
+  long ds_collect_imaged_nucleus();
+  long ds_collect_integer_number();
+  long ds_collect_laterality();
+  long ds_collect_measurement_mode();
+  long ds_collect_modality();
+  long ds_collect_order_of_slices();
+  long ds_collect_patient_phase();
+  long ds_collect_patient_position();
+  long ds_collect_patient_region();
+  long ds_collect_pixel_quality_mode();
+  long ds_collect_procedure_description();
+  long ds_collect_real_number();
+  long ds_collect_rest_direction();
+  long ds_collect_rotation_direction();
+  long ds_collect_save_code();
+  long ds_collect_sex();
+  long ds_collect_storage_mode();
+  long ds_collect_study_type();
+  long ds_collect_time();
+  long ds_collect_uid();
+  long ds_collect_view_direction();
+  long ds_collect_window_style();
+  long ds_convert_double();
+  long ds_convert_int();
+  long ds_convert_string();
+  long ds_date_check_cms();
+  long ds_date_cms_to_display();
+  long ds_date_cms_to_ingres();
+  long ds_date_cms_to_nema();
+  long ds_date_cms_to_rt11();
+  long ds_date_cms_to_spi();
+  long ds_date_days_of_month();
+  long ds_date_days_of_year();
+  long ds_date_display_to_cms();
+  long ds_date_get();
+  long ds_date_get_age();
+  long ds_date_get_new();
+  long ds_date_ingres_to_cms();
+  long ds_date_nema_to_cms();
+  long ds_date_pdp_to_cms();
+  long ds_date_string_to_cms();
+  long ds_date_vax_to_cms();
+  long ds_date_vms_to_cms();
+  long ds_db_set_comdiainfo();
+  long ds_db_set_imainfo();
+  long ds_db_set_patinfo();
+  long ds_db_set_stuinfo();
+  long ds_db_use_comdiainfo();
+  long ds_db_use_patinfo();
+  long ds_file_control();
+  long ds_fill_basic_structs();
+  long ds_fill_binary_data();
+  long ds_fill_binary_g7FE0();
+  long ds_fill_binary_g7FE1();
+  long ds_fill_common_black_image_data();
+  long ds_fill_data_structs();
+  long ds_fill_default_data();
+  long ds_fill_fix_data();
+  long ds_fill_graphic_structs();
+  long ds_fill_image_g7FE0();
+  long ds_fill_image_graphic();
+  long ds_fill_image_text();
+  long ds_fill_patient_data();
+  long ds_fill_struct_g08();
+  long ds_fill_struct_g09();
+  long ds_fill_struct_g09Cms();
+  long ds_fill_struct_g09Lab();
+  long ds_fill_struct_g09Spi();
+  long ds_fill_struct_g10();
+  long ds_fill_struct_g11();
+  long ds_fill_struct_g11Cms();
+  long ds_fill_struct_g11Spi();
+  long ds_fill_struct_g13();
+  long ds_fill_struct_g13Cms();
+  long ds_fill_struct_g18();
+  long ds_fill_struct_g19();
+  long ds_fill_struct_g19Acqu();
+  long ds_fill_struct_g19Cms();
+  long ds_fill_struct_g19Ct();
+  long ds_fill_struct_g19CtCoAd();
+  long ds_fill_struct_g19Mr();
+  long ds_fill_struct_g19MrCoAd();
+  long ds_fill_struct_g20();
+  long ds_fill_struct_g21();
+  long ds_fill_struct_g21Cms();
+  long ds_fill_struct_g21Ct();
+  long ds_fill_struct_g21CtRaw();
+  long ds_fill_struct_g21Med();
+  long ds_fill_struct_g21Mr();
+  long ds_fill_struct_g21MrRaw();
+  long ds_fill_struct_g28();
+  long ds_fill_struct_g29();
+  long ds_fill_struct_g29Cms();
+  long ds_fill_struct_g29Spi();
+  long ds_fill_struct_g51();
+  long ds_fill_struct_g6021();
+  long ds_fill_test_data();
+  long ds_finally_interface_status_update();
+  long ds_generate_image_text();
+  long ds_get_data_set_owner();
+  long ds_get_data_set_type();
+  long ds_get_g09_med_parameter();
+  long ds_get_subgroup_owner_code();
+  long ds_get_swap_mode();
+  long ds_get_vax_char_buf();
+  long ds_get_vax_integer2_buf();
+  long ds_get_vax_integer4_buf();
+  long ds_get_vax_real_buf();
+  long ds_get_vax_skip_gap();
+  long ds_hea_slice_1_2_single();
+  long ds_info_get_xxx_version();
+  long ds_info_show_versions();
+  long ds_init_error_handling();
+  long ds_init_header();
+  long ds_initialize_nema_parser();
+  long ds_mani_gen_rot_matrix();
+  long ds_mani_image_magnify();
+  long ds_mani_image_mirror();
+  long ds_mani_image_rotate_90();
+  long ds_mani_mult_matrix_matrix();
+  long ds_mani_mult_matrix_scalar();
+  long ds_mani_patient_modify();
+  long ds_mani_set_id_matrix();
+  long ds_mani_transform_vector();
+  long ds_mes_calc_prs();
+  long ds_modify_patient_data();
+  long ds_nema_check_if_transformation_possible();
+  long ds_num1_blocked_fill_basic_structs();
+  long ds_num1_blocked_fill_data_structs();
+  long ds_num1_framed_fill_basic_structs();
+  long ds_num1_framed_fill_data_structs();
+  long ds_num1_get_cms_sep_basic_data();
+  long ds_num1_get_pixel_quality_code();
+  long ds_num1_get_pixel_quality_mode();
+  long ds_num1_num1_to_cms();
+  long ds_num1_vax_to_sun();
+  long ds_num2_fill_basic_structs();
+  long ds_num2_fill_data_structs();
+  long ds_num2_get_cms_sep_basic_data();
+  long ds_num2_get_pixel_quality_code();
+  long ds_num2_get_pixel_quality_mode();
+  long ds_num2_num2_to_cms();
+  long ds_num2_vax_to_sun();
+  long ds_parser_error_handling();
+  long ds_post_build_up_name();
+  long ds_post_build_up_record();
+  long ds_post_separate();
+  long ds_pre_allocate_data_areas_b1();
+  long ds_pre_allocate_data_areas_b2();
+  long ds_pre_allocate_data_areas_s();
+  long ds_pre_build_up_name();
+  long ds_pre_build_up_record();
+  long ds_pre_determine_control_status_b1();
+  long ds_pre_determine_control_status_b2();
+  long ds_pre_determine_control_status_s();
+  long ds_pre_determine_data_area_lengths_b1();
+  long ds_pre_determine_data_area_lengths_b2();
+  long ds_pre_determine_data_area_lengths_s();
+  long ds_pre_initialize();
+  long ds_pre_separation();
+  long ds_reset_nema_parser();
+  long ds_return_control();
+  long ds_separate_byte_buf();
+  long ds_separate_char_buf();
+  long ds_separate_cms_blocked_data_set();
+  long ds_separate_common_data_set();
+  long ds_separate_given_item();
+  long ds_separate_group_600x();
+  long ds_separate_key();
+  long ds_separate_long_buf();
+  long ds_separate_nema_data_set();
+  long ds_separate_num1_blocked_data_set();
+  long ds_separate_num1_framed_data_set();
+  long ds_separate_num2_data_set();
+  long ds_separate_short_buf();
+  long ds_separate_som0_blocked_data_set();
+  long ds_separate_som0_framed_data_set();
+  long ds_separate_som_blocked_data_set();
+  long ds_separate_som_framed_data_set();
+  long ds_set_pdp_byte_buf();
+  long ds_set_pdp_char_buf();
+  long ds_set_pdp_fill_gap();
+  long ds_set_pdp_integer2_buf();
+  long ds_set_pdp_integer4_buf();
+  long ds_set_struct_g09Cms();
+  long ds_set_struct_g09Lab();
+  long ds_set_struct_g09Spi();
+  long ds_set_struct_g11Cms();
+  long ds_set_struct_g11Spi();
+  long ds_set_struct_g19Acqu();
+  long ds_set_struct_g19Cms();
+  long ds_set_struct_g19Ct();
+  long ds_set_struct_g19CtCoAd();
+  long ds_set_struct_g19Mr();
+  long ds_set_struct_g19MrCoAd();
+  long ds_set_struct_g21Cms();
+  long ds_set_struct_g21Ct();
+  long ds_set_struct_g21CtRaw();
+  long ds_set_struct_g21Med();
+  long ds_set_struct_g21Mr();
+  long ds_set_struct_g21MrRaw();
+  long ds_set_struct_g29Cms();
+  long ds_set_struct_g29Spi();
+  long ds_show_help_text();
+  long ds_simulate_ct_mr_status_file();
+  long ds_som0_blocked_build_up_basic_structs();
+  long ds_som0_blocked_build_up_data_structs();
+  long ds_som0_blocked_fill_basic_structs();
+  long ds_som0_blocked_fill_data_structs();
+  long ds_som0_check_if_transformation_possible();
+  long ds_som0_cms_to_som0();
+  long ds_som0_fill_bild_text();
+  long ds_som0_fill_block_0();
+  long ds_som0_framed_build_up_basic_groups();
+  long ds_som0_framed_build_up_data_groups();
+  long ds_som0_framed_fill_basic_structs();
+  long ds_som0_framed_fill_data_structs();
+  long ds_som0_get_cms_sep_basic_data();
+  long ds_som0_get_patient_orientation_vector();
+  long ds_som0_pdp_to_sun();
+  long ds_som0_print_build_up_protocol();
+  long ds_som0_som0_to_cms();
+  long ds_som0_sun_to_pdp();
+  long ds_som_blocked_fill_basic_structs();
+  long ds_som_blocked_fill_data_structs();
+  long ds_som_framed_fill_basic_structs();
+  long ds_som_framed_fill_data_structs();
+  long ds_som_get_cms_sep_basic_data();
+  long ds_som_get_patient_position();
+  long ds_som_get_rest_direction();
+  long ds_som_som_to_cms();
+  long ds_som_vax_to_sun();
+  long ds_split_calculation_mode();
+  long ds_split_cardiac_code();
+  long ds_split_compression_code();
+  long ds_split_contrast();
+  long ds_split_data_object_subtype();
+  long ds_split_data_set_subtype();
+  long ds_split_filter_type();
+  long ds_split_filter_type_image();
+  long ds_split_gate_phase();
+  long ds_split_ident();
+  long ds_split_image_format();
+  long ds_split_image_geometry_type();
+  long ds_split_imaged_nucleus();
+  long ds_split_integer_number();
+  long ds_split_laterality();
+  long ds_split_measurement_mode();
+  long ds_split_modality();
+  long ds_split_order_of_slices();
+  long ds_split_patient_phase();
+  long ds_split_patient_position();
+  long ds_split_patient_region();
+  long ds_split_pixel_quality_mode();
+  long ds_split_procedure_description();
+  long ds_split_real_number();
+  long ds_split_rest_direction();
+  long ds_split_rotation_direction();
+  long ds_split_save_code();
+  long ds_split_sex();
+  long ds_split_storage_mode();
+  long ds_split_study_type();
+  long ds_split_view_direction();
+  long ds_split_window_style();
+  long ds_stop_dbx();
+  long ds_string_delete_leading_characters();
+  long ds_string_delete_multiple_characters();
+  long ds_string_delete_tailing_characters();
+  long ds_string_find_string_in_string();
+  long ds_string_reformate();
+  long ds_string_replace();
+  long ds_text_comment_no_1();
+  long ds_text_comment_no_2();
+  long ds_text_contrast();
+  long ds_text_data_set_id();
+  long ds_text_date_of_measurement();
+  long ds_text_echo_time();
+  long ds_text_field_of_view();
+  long ds_text_gantry_tilt();
+  long ds_text_gating_and_trigger();
+  long ds_text_get_black_image_text();
+  long ds_text_get_none_image_text();
+  long ds_text_get_normal_image_text();
+  long ds_text_get_recon_3d_image_text();
+  long ds_text_image_number();
+  long ds_text_installation_name();
+  long ds_text_label();
+  long ds_text_magnification_factor();
+  long ds_text_manufacturer_model();
+  long ds_text_matrix();
+  long ds_text_mip_column();
+  long ds_text_mip_head_line();
+  long ds_text_mip_line();
+  long ds_text_mip_slice();
+  long ds_text_number_of_acquisitions();
+  long ds_text_patient_birthdate();
+  long ds_text_patient_name();
+  long ds_text_patient_number();
+  long ds_text_patient_orientation_set_1();
+  long ds_text_patient_orientation_set_2();
+  long ds_text_patient_orientation_sets();
+  long ds_text_patient_orientation_string();
+  long ds_text_patient_position();
+  long ds_text_patient_sex_and_age();
+  long ds_text_repetition_time();
+  long ds_text_saturation_regions();
+  long ds_text_scan_number();
+  long ds_text_sequence_information();
+  long ds_text_slice_orientation_no();
+  long ds_text_slice_position();
+  long ds_text_slice_thickness();
+  long ds_text_software_version();
+  long ds_text_study_number();
+  long ds_text_table_position();
+  long ds_text_time_of_acquisition();
+  long ds_text_time_of_measurement();
+  long ds_text_time_of_scanning();
+  long ds_text_tube_current();
+  long ds_text_tube_voltage();
+  long ds_text_type_of_measurement();
+  long ds_text_zoom_center();
+  long ds_time_check_cms();
+  long ds_time_cms_to_display();
+  long ds_time_cms_to_nema();
+  long ds_time_cms_to_pdp();
+  long ds_time_cms_to_spi();
+  long ds_time_display_to_cms();
+  long ds_time_nema_to_cms();
+  long ds_time_pdp_to_cms();
+  long ds_time_string_to_cms();
+  long ds_top_up_header();
+  long ds_trace_control();
+  long ds_transform_cms_to_blocked_som0();
+  long ds_transform_cms_to_cms_nema();
+  long ds_transform_cms_to_framed_som0();
+  long ds_transform_common_to_cms();
+  long ds_update_nema_parser();
+  long ds_vector_add();
+  long ds_vector_assign();
+  long ds_vector_check_if_equal();
+  long ds_vector_check_if_nil();
+  long ds_vector_check_if_normalized();
+  long ds_vector_check_if_undefined();
+  long ds_vector_cut();
+  long ds_vector_get();
+  long ds_vector_inner_product();
+  long ds_vector_multiply();
+  long ds_vector_orthogonal_to_polar();
+  long ds_vector_polar_to_orthogonal();
+  long ds_vector_print();
+  long ds_vector_put();
+  long ds_vector_set();
+  long ds_vector_subtract();
+  long ds_vector_transform_l();
+  long ds_vector_transform_m();
+  long ds_vector_vector_product();
+  long ds_xyz_get_cms_black_basic_data();
+  long ds_xyz_get_cms_derived_data();
+  long ds_xyz_get_cms_field_of_view();
+  long ds_xyz_get_cms_sep_basic_data();
+  long ds_xyz_get_image_class();
+  long ds_xyz_get_nema_image_place();
+  long ds_xyz_get_slice_orientation_parameters();
+  long ds_xyz_get_transformation_list1();
+  long ds_xyz_get_transformation_list2();
+  long ds_xyz_get_view_direction();
+  long ds_xyz_shift_definition_point();
+
+
+  /* DECLARATION: define special data set library functions */
+  data_area_type_t ds_get_data_area_type();
+  item_quality_t ds_get_item_quality();
+  image_text_type_t ds_get_image_text_type();
+  double ds_get_max_abs_vector_component();
+  char *ds_info_get_header_version();
+  char *ds_info_get_nema_version();
+  char *ds_info_get_software_version();
+  char *ds_info_get_spi_version();
+  char *ds_strstr();
+  long unsigned ds_cal_image_base_vectors();
+  long unsigned ds_cal_vec_mode();
+  long unsigned ds_mpr_mult_matmat3();
+  
+#define ds_string_find_string_in_string ds_strstr
+
+
+  /* DECLARATION: define special system functions */
+  char *malloc();
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_acr_groups_types.h
@@ -0,0 +1,237 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_acr_groups_types.h
+
+   Description: The header file defines the NEMA defined data set basic groups (even group
+                numbers) as structures for internal use (internal header).
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_ACR_GROUPS_TYPES
+#define DS_HEAD_ACR_GROUPS_TYPES
+
+/******************************************/
+/* Identifying Information (Group 0008'H) */
+/******************************************/
+
+typedef struct acr_identifying_tag
+{
+  ds_date_t StudyDate;					   /* (0008,0020)   10  AT DF 2NS-NEM */
+  ds_date_t AcquisitionDate;				   /* (0008,0022)   10  AT DF 2NS-CMS */
+  ds_date_t ImageDate;					   /* (0008,0023)   10  AT DF 2NS-CMS */
+  ds_time_t StudyTime;					   /* (0008,0030)   12  AT DF 2NS-NEM */
+  ds_time_t AcquisitionTime;				   /* (0008,0032)   12  AT DF 2NS-CMS */
+  ds_time_t ImageTime;					   /* (0008,0033)   12  AT DF 2NS-CMS */
+  data_set_subtype_t DataSetSubtype;			   /* (0008,0041)    8  AT EV 2NS-CMS */
+  modality_t Modality;					   /* (0008,0060)    2  AT EV 1NS-CMS */
+  char Manufacturer[LENGTH_MANUFACTURER + 1];		   /* (0008,0070)    8  AT FF 2NS-NEM */
+  char InstitutionID[LENGTH_LABEL + 1];			   /* (0008,0080)   26  AT FF 2NS-NEM */
+  char ReferringPhysician[LENGTH_LABEL + 1];		   /* (0008,0090)   26  AT FF 2NS-NEM */
+  char StationID[LENGTH_LABEL + 1];			   /* (0008,1010)   26  AT FF 2NS-NEM */
+  char ProcedureDescription_1[LENGTH_COMMENT + 1];	   /* (0008,1030)   52  AT FF 2DS-CMS */
+  char ProcedureDescription_2[LENGTH_COMMENT + 1];
+  char AdmittingDiagnosis[LENGTH_DIAGNOSIS + 1];	   /* (0008,1080)   40  AT FF 2DS-CMS */
+  char ManufacturerModel[LENGTH_LABEL + 1];		   /* (0008,1090)   26  AT FF 2DS-CMS */
+} acr_identifying_t;
+
+
+/**************************************/
+/* Patient Information (Group 0010'H) */
+/**************************************/
+
+typedef struct acr_patient_tag
+{
+  char PatientName[LENGTH_LABEL + 1];		           /* (0010,0010)   26  AT FF 2NS-NEM */
+  char PatientId[LENGTH_PATIENT_ID + 1];		   /* (0010,0020)   12  AT FF 2NS-NEM */
+  ds_date_t PatientBirthdate;				   /* (0010,0030)   10  AT DF 2NS-NEM */
+  sex_t PatientSex;					   /* (0010,0040)    2  AT EV 2NS-NEM */
+  char PatientMaidenName[LENGTH_LABEL + 1];		   /* (0010,1005)   26  AT FF 2DS-CMS */
+  char PatientAge[LENGTH_AGE + 1];			   /* (0010,1010)    4  AT DF 2NS-CMS */
+  double PatientSize;					   /* (0010,1020)    6  AN FF 3NS-NEM */
+  long PatientWeight;					   /* (0010,1030)    6  AN FF 2NS-CMS */
+} acr_patient_t;
+
+
+
+/******************************************/
+/* Acquisition Information (Group 0018'H) */
+/******************************************/
+
+typedef struct acr_acquisition_tag
+{
+  contrast_t Contrast;					   /* (0018,0010)    8  AT EV 2DS-NEM */
+  int Pad1;					           /* Dummy for byte alignment */
+  double SliceThickness;				   /* (0018,0050)   14  AN FF 2NS-NEM */
+  long GeneratorVoltage;				   /* (0018,0060)    6  AN FF 2NM-NEM */
+  long GeneratorVoltageDual;				   /* (0018,0060) */
+  double RepetitionTime;				   /* (0018,0080)   14  AN FF 2NS-NEM */
+  double EchoTime;					   /* (0018,0081)   14  AN FF 2NS-NEM */
+  double InversionTime;					   /* (0018,0082)   14  AN FF 2NS-NEM */
+  long NumberOfAverages;				   /* (0018,0083)    6  AN FF 3NS-NEM */
+  int Pad2;					           /* Dummy for byte alignment */
+  double ImagingFrequency;				   /* (0018,0084)   14  AN FF 2NS-NEM */
+  nucleus_t Gap0085;
+  long EchoNumber;					   /* (0018,0086)    6  AN FF 3NS-CMS */
+  long DataCollectionDiameter;				   /* (0018,0090)    6  AN FF 3NS-NEM */
+  char DeviceSerialNumber[LENGTH_LABEL + 1];		   /* (0018,1000)   26  AT FF 2DS-CMS */
+  char SoftwareVersion[LENGTH_SOFTWARE_VERSION + 1];	   /* (0018,1020)    8  AT FF 2DS-CMS */
+  long DistanceSourceToDetector;			   /* (0018,1110)    6  AN FF 3NS-NEM */
+  long DistanceSourceToPatient;				   /* (0018,1111)    6  AN FF 3NS-NEM */
+  long GantryTilt;					   /* (0018,1120)    6  AN FF 2NS-CMS */
+  long TableHeight;					   /* (0018,1130)    6  AN FF 3NS-NEM */
+  rotation_direction_t RotationDirection;		   /* (0018,1140)    2  AT EV 3NS-NEM */
+  long ExposureTime;					   /* (0018,1150)    6  AN FF 2NS-CMS */
+  long Exposure;					   /* (0018,1152)    6  AN FF 2NS-CMS */
+  char FilterIdLabel[LENGTH_FILTER_ID + 1];		   /* (0018,1160)   12  AT FF 3NS-NEM */
+  int Pad3;					           /* Dummy for byte alignment */
+  double GeneratorPower;				   /* (0018,1170)   14  AN FF 2NS-CMS */
+  double FocalSpot;					   /* (0018,1190    14  AN FF 3NS-NEM) */
+  ds_date_t CalibrationDate;				   /* (0018,1200)   10  AT DF 3NS-NEM */
+  ds_time_t CalibrationTime;				   /* (0018,1201)   12  AT DF 3NS-NEM */
+  char ConvolutionKernel[LENGTH_LABEL + 1];		   /* (0018,1210)   12  AT DF 3NS-NEM */
+  char ReceivingCoil[LENGTH_LABEL + 1];			   /* (0018,1250)   26  AT FF 2DS-CMS */
+  char Gap1251[LENGTH_LABEL + 1];
+  patient_position_t PatientPosition;			   /* (0018,5100)    8  AT EV 2NS-CMS */
+  char ImagedNucleus[LENGTH_NUCLEUS + 1];		   /* (0018,0085)    8  AT FF 2NS-NEM */
+} acr_acquisition_t;
+
+
+
+/*******************************************/
+/* Relationship Information (Group 0020'H) */
+/*******************************************/
+
+typedef struct acr_relationship_tag
+{
+  long Study;						   /* (0020,0010)    6  AN FF 2NS-NEM */
+  long Gap0011;
+  long Acquisition;					   /* (0020,0012)    6  AN FF 2DS-NEM */
+  long Image;						   /* (0020,0013)    6  AN FF 2DS-NEM */
+  long Gap0030[3];
+  int Pad1;                                                /* Dummy for byte alignment */
+  double Gap0035[6];
+  long Location;					   /* (0020,0050)    6  AN FF 3NS-NEM */
+  laterality_t Laterality;				   /* (0020,0060)    2  AT EV 2DS-NEM */
+  geometry_t ImageGeometryType;				   /* (0020,0070)    8  AT EV 2DS-NEM */
+  long AcquisitionsInSeries;				   /* (0020,1001)    6  AN FF 3NS-NEM */
+  reference_t Reference;				   /* (0020,1020)    n  AT FF 3NM-NEM */
+} acr_relationship_t;
+
+
+
+/*************************************************/
+/* Image Presentation Information (Group 0028'H) */
+/*************************************************/
+
+typedef struct acr_presentation_tag
+{
+  short ImageDimension;					   /* (0028,0005)    2  BI HX 1DS-NEM */
+  short Rows;						   /* (0028,0010)    2  BI HX 1NS-NEM */
+  short Columns;					   /* (0028,0011)    2  BI HX 1NS-NEM */
+  pixel_size_t PixelSize;				   /* (0028,0030)   30  AN FF 2NM-NEM */
+  image_format_t ImageFormat;				   /* (0028,0040)    4  AT EV 1DS-NEM */
+  compression_code_t CompressionCode;			   /* (0028,0060)    4  AT EV 1DS-NEM */
+  short BitsAllocated;					   /* (0028,0100)    2  BI HX 1DS-NEM */
+  short BitsStored;					   /* (0028,0101)    2  BI HX 1DS-NEM */
+  short HighBit;					   /* (0028,0102)    2  BI HX 1DS-NEM */
+  short PixelRepresentation;				   /* (0028,0103)    2  BI HX 1DS-NEM */
+  windows_t WindowCenter;				   /* (0028,1050)   12  AN DF 2NM-MED */
+  windows_t WindowWidth;				   /* (0028,1051)   12  AN DF 2NM-MED */
+  long RescaleIntercept;				   /* (0028,1052)    6  AN FF 2NS-MED */
+  long RescaleSlope;					   /* (0028,1053)    6  AN FF 2NS-MED */
+} acr_presentation_t;
+
+#endif
+
+
+
+
+/*==  HELP TEXT  ===========================================================================*/
+
+#ifdef DS_STC_TOOL
+
+"G08.Ide.StudyDate.Year", "Study Date (0008,0020)",
+"G08.Ide.AcquisitionDate.Year", "Acquisition Date (0008,0022)",
+"G08.Ide.ImageDate.Year", "Image Date (0008,0023)",
+"G08.Ide.StudyTime.Hour", "Study Time (0008,0030)",
+"G08.Ide.AcquisitionTime.Hour", "Acquisition Time (0008,0032)",
+"G08.Ide.ImageTime.Hour", "Image Time (0008,0033)",
+"G08.Ide.DataSetSubtype.M", "Data Set Subtype (0008,0041)",
+"G08.Ide.Modality", "Modality (0008,0060)",
+"G08.Ide.Manufacturer", "Manufacturer (0008,0070)",
+"G08.Ide.InstitutionID", "Institution ID (0008,0080)",
+"G08.Ide.ReferringPhysician", "Referring Physician (0008,0090)",
+"G08.Ide.StationID", "Station ID (0008,1010)",
+"G08.Ide.ProcedureDescription_1", "Procedure Description (0008,1030) - first part",
+"G08.Ide.ProcedureDescription_2", "Procedure Description (0008,1030) - second part",
+"G08.Ide.AdmittingDiagnosis", "Admitting Diagnosis (0008,1080)",
+"G08.Ide.ManufacturerModel", "Manufacturer Model (0008,1090)",
+
+"G10.Pat.PatientName", "Patient Name (0010,0010)",
+"G10.Pat.PatientId", "Patient Id (0010,0020)",
+"G10.Pat.PatientBirthdate.Year", "Patient Birthdate (0010,0030)",
+"G10.Pat.PatientSex", "Patient Sex (0010,0040): Female | Male | Others",
+"G10.Pat.PatientMaidenName", "Patient Maiden Name (0010,1005)",
+"G10.Pat.PatientAge", "Patient Age (0010,1010) in Years | Months | Days",
+"G10.Pat.PatientSize", "Patient Size (0010,1020) in meters",
+"G10.Pat.PatientWeight", "Patient Weight (0010,1030) in kilograms",
+
+"G18.Acq.Contrast",  "Contrast (0018,0010): APPLIED | NONE",
+"G18.Acq.SliceThickness",  "Slice Thickness (0018,0050) in mm",
+"G18.Acq.GeneratorVoltage",  "nominal Generator Voltage (0018,0060) in kV",
+"G18.Acq.GeneratorVoltageDual",  "second value of Generator Voltage (0018,0060) in kV",
+"G18.Acq.RepetitionTime",  "Repetition Time (0018,0080) in msec",
+"G18.Acq.EchoTime",  "Echo Time (0018,0081) in msec",
+"G18.Acq.InversionTime",  "Inversion Time (0018,0082) in msec",
+"G18.Acq.NumberOfAverages",  "nominal Number of Averages (0018,0083)",
+"G18.Acq.ImagingFrequency",  "Imaging Frequency (0018,0084) in MHz",
+"G18.Acq.ImagedNucleus",  "Imaged Nucleus (0018,0085)",
+"G18.Acq.EchoNumber",  "Echo Number (0018,0086)",
+"G18.Acq.DataCollectionDiameter",  "Data Collection Diameter (0018,0090) in mm",
+"G18.Acq.DeviceSerialNumber",  "Device Serial Number (0018,1000)",
+"G18.Acq.SoftwareVersion",  "Software Version (0018,1020)",
+"G18.Acq.DistanceSourceToDetector",  "Distance Source to Detector (0018,1110)in mm",
+"G18.Acq.DistanceSourceToPatient",  "Distance Source to Patient (0018,1111) in mm",
+"G18.Acq.GantryTilt",  "Gantry Tilt (0018,1120) in degrees",
+"G18.Acq.TableHeight",  "Table Height (0018,1130) in mm",
+"G18.Acq.RotationDirection",  "Rotation Direction (0018,1140): Counter Clock | Clock Wise | NO",
+"G18.Acq.ExposureTime",  "nominal Exposure Time (0018,1150) in msec",
+"G18.Acq.Exposure",  "nominal Exposure (0018,1152) in mAs",
+"G18.Acq.FilterIdLabel",  "Filter Id Label (0018,1160)",
+"G18.Acq.GeneratorPower",  "nominal Generator Power (0018,1170) in kW",
+"G18.Acq.FocalSpot",  "Focal Spot (0018,1190) in mm",
+"G18.Acq.CalibrationDate.Year",  "Calibration Date (0018,1200)",
+"G18.Acq.CalibrationTime.Hour",  "Calibration Time (0018,1201)",
+"G18.Acq.ConvolutionKernel",  "Convolution Kernel (0018,1210)",
+"G18.Acq.ReceivingCoil",  "Receiving Coil (0018,1250)",
+"G18.Acq.PatientPosition",  "Patient Position (0018,5100)",
+  
+"G20.Rel.Study",  "Study (0020,0010)",
+"G20.Rel.Acquisition",  "Acquisition (0020,0012)",
+"G20.Rel.Image",  "Image (0020,0013)",
+"G20.Rel.Location",  "Location (0020,0050) in mm",
+"G20.Rel.Laterality",  "Laterality (0020,0060)",
+"G20.Rel.ImageGeometryType",  
+"Image Geometry Type (0020,0070): PLANAR | UNRAVEL | CURVED",
+"G20.Rel.AcquisitionsInSeries",  "Acquisitions in Series (0020,1001)",
+"G20.Rel.Reference.One.Image",  "Reference (0020,1020)",
+
+"G28.Pre.ImageDimension",  "Image Dimension (0028,0005)",
+"G28.Pre.Rows",  "Rows (0028,0010)",
+"G28.Pre.Columns",  "Columns (0028,0011)",
+"G28.Pre.PixelSize.Row",  "Pixel Size (0028,0030) in mm",
+"G28.Pre.ImageFormat",  "Image Format (0028,0040)",
+"G28.Pre.CompressionCode",  "Compression Code (0028,0060)",
+"G28.Pre.BitsAllocated",  "Bits Allocated (0028,0100)",
+"G28.Pre.BitsStored",  "Bits Stored (0028,0101)",
+"G28.Pre.HighBit",  "High Bit (0028,0102)",
+"G28.Pre.PixelRepresentation",  "Pixel Representation (0028,0103)",
+"G28.Pre.WindowCenter.X",  "Window Center (0028,1050)",
+"G28.Pre.WindowWidth.X",  "Window Width (0028,1051)",
+"G28.Pre.RescaleIntercept",  "Rescale Intercept (0028,1052)",
+"G28.Pre.RescaleSlope",  "Rescale Slope (0028,1053)",
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_basic_types.h
@@ -0,0 +1,532 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_basic_types.h
+
+   Description: The header file defines the basic types for internal header.
+                Each enumerator identifier is build up as a type qualification and the
+                enumerator item value defined in document [DS Item Format] paragraphs "item
+                "item contents".
+
+                As exampel: Rotation_CC
+
+                Rotation --> identifier for item Rotation Direction (0018,1140
+                CC       --> counter clockwise rotation
+
+                No enumerator value is set to zero to avoid problems e.g. if an automatic
+                initialication during allocation was done. Zore is not a unique
+                identification, because several item values equal zero are defined.
+                
+                The used bit masks are not defined with C-language type bit array, because
+                the internal representation is compiler dependent. To handle not CMS
+                created bit masks (e.g. form foreign manufacturer NEMA data set) the
+                data set library macros DS_BIT_xxx() are used.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_BASIC_TYPES
+#define DS_HEAD_BASIC_TYPES
+
+
+typedef enum cardiac_code_tag
+{
+  Cardiac_Code_COMMON = 1,
+  Cardiac_Code_CONFIRM = 2,
+  Cardiac_Code_DIASTOLE = 3,
+  Cardiac_Code_NONE = 4,
+  Cardiac_Code_SYSTOLE = 5,
+  Cardiac_Code_UNDEFINED = Enum_UNDEFINED
+} cardiac_code_t;
+
+typedef enum 
+{
+  Calculation_m_A = 20,
+  Calculation_m_NONE = 1,
+  Calculation_m_PC = 21,
+  Calculation_m_PU = 22,
+  Calculation_m_UNDEFINED = Enum_UNDEFINED
+} calculation_mode_m_t;
+
+
+typedef enum calculation_mode_s_tag
+{
+  Calculation_s_BSP = 1,
+  Calculation_s_IRS = 2,
+  Calculation_s_NONE = 3,
+  Calculation_s_SUN = 4,
+  Calculation_s_VAX = 5,
+  Calculation_s_UNDEFINED = Enum_UNDEFINED
+} calculation_mode_s_t;
+
+
+typedef struct calculation_mode_tag
+{
+  calculation_mode_m_t M;
+  calculation_mode_s_t S;
+} calculation_mode_t;
+
+
+typedef enum compression_code_tag
+{
+  Compression_DONE = 2,
+  Compression_NONE = 1,
+  Compression_UNDEFINED = Enum_UNDEFINED
+} compression_code_t;
+
+
+typedef enum contrast_tag
+{
+  Contrast_NONE = 1,
+  Contrast_APPLIED = 2,
+  Contrast_UNDEFINED = Enum_UNDEFINED
+} contrast_t;
+
+
+typedef enum data_object_subtype_m_tag
+{
+  Object_m_CT = 1,
+  Object_m_MRS = 2,
+  Object_m_MRU = 3,
+  Object_m_UNDEFINED = Enum_UNDEFINED
+} data_object_subtype_m_t;
+
+
+typedef enum data_object_subtype_d_tag
+{
+  Object_d_P = 1,
+  Object_d_U = 2,
+  Object_d_UNDEFINED = Enum_UNDEFINED
+} data_object_subtype_d_t;
+
+
+typedef enum data_object_subtype_s_tag
+{
+  Object_s_NONE = 1,
+  Object_s_UNDEFINED = Enum_UNDEFINED
+} data_object_subtype_s_t;
+
+
+typedef struct data_object_subtype_tag
+{
+  data_object_subtype_m_t M;
+  data_object_subtype_d_t D;
+  data_object_subtype_s_t S;
+} data_object_subtype_t;
+
+
+typedef enum data_set_subtype_m_tag
+{
+  Set_m_IMAGE = 1,
+  Set_m_PLOT = 2,
+  Set_m_RAW = 3,
+  Set_m_SPECT = 4,
+  Set_m_TEXT = 5,
+  Set_m_UNDEFINED = Enum_UNDEFINED
+} data_set_subtype_m_t;
+
+
+typedef enum data_set_subtype_s_tag
+{
+  /* NOTE: data_set_subtype_s_tag */
+  /* If this basic data type "data_set_subtype_s_t" is changed please check also the basic
+     data type "measurement_mode_s_t" and the sequence "determine image type" in data set
+     library function "ds_get_image_text_type()". */
+
+  /* To find a free enum number you can use the following command "sort -t= +1 <Return> <set
+     list> <Control D>" */
+     
+  Set_s_NONE = 1,
+  Set_s_DYNA = 14,
+  Set_s_HIS = 19,
+  Set_s_HISC = 60,
+  Set_s_PLOT = 18,
+  Set_s_QUAL = 17,
+  Set_s_ROT = 16,
+  Set_s_SCAN = 10,
+  Set_s_SINC = 11,
+  Set_s_SIN = 12,
+  Set_s_STAT = 15,
+  Set_s_R2D = 62,
+  Set_s_R3D = 63,
+  Set_s_TOPO = 13,
+  Set_s_CAR = 20,
+  Set_s_MC = 21,
+  Set_s_BLK = 41,
+  Set_s_FPA = 42,
+  Set_s_PROJ = 43,
+  Set_s_READ = 44,
+  Set_s_VFLO = 45,
+  Set_s_VFPA = 46,
+  Set_s_VSUM = 47,
+  Set_s_CFL = 51,
+  Set_s_CSH = 52,
+  Set_s_UNDEFINED = Enum_UNDEFINED
+} data_set_subtype_s_t;
+
+
+typedef struct data_set_subtype_tag
+{
+  data_set_subtype_m_t M;
+  data_set_subtype_s_t S;
+} data_set_subtype_t;
+
+
+typedef struct gradient_delay_time_tag
+{
+  double X;
+  double Y;
+  double Z;
+} gradient_delay_time_t;
+
+
+typedef struct field_of_view_tag
+{
+  double Height;
+  double Width;
+} field_of_view_t;
+
+typedef struct filter_parameter_tag
+{
+  double Value1;
+  double Value2;
+  double Value3;
+  double Value4;
+} filter_parameter_t;
+
+
+typedef enum filter_type_tag
+{
+  Filter_EXTERNAL = 5,
+  Filter_FERMI = 1,
+  Filter_GAUSS = 2,
+  Filter_HANNING = 3,
+  Filter_NONE = 4,
+  Filter_UNDEFINED = Enum_UNDEFINED
+} filter_type_t;
+
+
+typedef enum filter_type_image_tag
+{
+  Filter_Image_NO1 = 1,
+  Filter_Image_NONE = 4,
+  Filter_Image_UNDEFINED = Enum_UNDEFINED
+} filter_type_image_t;
+
+
+typedef enum gate_phase_tag
+{
+  Gate_EXPIRATION = 1,
+  Gate_INSPIRATION = 2,
+  Gate_UNDEFINED = Enum_UNDEFINED
+} gate_phase_t;
+
+typedef enum geometry_tag
+{
+  Geometry_CURVED = 3,
+  Geometry_PLANAR = 1,
+  Geometry_UNRAVEL = 2,
+  Geometry_UNDEFINED = Enum_UNDEFINED
+} geometry_t;
+
+
+typedef enum image_format_tag
+{
+  Format_RECT = 1,
+  Format_UNDEFINED = Enum_UNDEFINED
+} image_format_t;
+
+
+typedef struct image_id_tag
+{
+  char gap[LENGTH_LABEL + 1];
+  char PatientName[LENGTH_LABEL + 1];
+  char PatientId[LENGTH_LABEL + 1];
+  long Image;
+} image_id_t;
+
+
+typedef struct image_location_tag
+{
+  double Sag;
+  double Cor;
+  double Tra;
+} image_location_t;
+
+
+typedef struct int_point_tag
+{
+  long X;
+  long Y;
+  long Z;
+} int_point_t;
+
+
+typedef enum laterality_tag
+{
+  Laterality_L = 1,
+  Laterality_NO = 2,
+  Laterality_R = 3,
+  Laterality_UNDEFINED = Enum_UNDEFINED
+} laterality_t;
+
+
+typedef enum measurement_mode_m_tag
+{
+  Measurement_m_ADJU = 1,
+  Measurement_m_EXAM = 2,
+  Measurement_m_TEST = 3,
+  Measurement_m_UNDEFINED = Enum_UNDEFINED
+} measurement_mode_m_t;
+
+
+typedef enum measurement_mode_s_tag
+{
+  Measurement_s_NONE = 1,
+  Measurement_s_DYNA = 14,
+  Measurement_s_HIST = 19,
+  Measurement_s_PLOT = 18,
+  Measurement_s_QUAL = 17,
+  Measurement_s_ROT = 16,
+  Measurement_s_SCAN = 10,
+  Measurement_s_SINC = 11,
+  Measurement_s_SINZ = 12,
+  Measurement_s_STAT = 15,
+  Measurement_s_R2D = 22,
+  Measurement_s_R3D = 23,
+  Measurement_s_TOPO = 13,
+  Measurement_s_UNDEFINED = Enum_UNDEFINED
+} measurement_mode_s_t;					   /* check also data_set_subtype_s_t */
+
+
+typedef struct measurement_mode_tag
+{
+  measurement_mode_m_t M;
+  measurement_mode_s_t S;
+} measurement_mode_t;
+
+
+typedef enum modality_tag
+{
+  Modality_CT = 1,
+  Modality_MR = 2,
+  Modality_UNDEFINED = Enum_UNDEFINED
+} modality_t;
+
+
+typedef enum nucleus_tag
+{
+  Nucleus_C = 1,
+  Nucleus_F = 2,
+  Nucleus_H = 3,
+  Nucleus_N = 4,
+  Nucleus_NA = 5,
+  Nucleus_P = 6,
+  Nucleus_UNDEFINED = Enum_UNDEFINED
+} nucleus_t;
+
+
+typedef struct object_orientation_tag
+{
+  double Phi;
+  double Theta;
+  double Radius;
+} object_orientation_t;
+
+
+typedef struct object_threshold_tag
+{
+  long LowerBoundary;
+  long UpperBoundary;
+} object_threshold_t;
+
+
+typedef enum order_of_slices_tag
+{
+  Slice_Order_ASCENDING = 1,
+  Slice_Order_DECREASING = 2,
+  Slice_Order_FREE = 3,
+  Slice_Order_INTERLEAVED = 4,
+  Slice_Order_NONE = 5,
+  Slice_Order_UNDEFINED = Enum_UNDEFINED
+} order_of_slices_t;
+
+
+typedef struct patient_orientation_tag
+{
+  char Y[LENGTH_ORIENTATION + 1];			   /* up - down */
+  char X[LENGTH_ORIENTATION + 1];			   /* left - right */
+  char Z[LENGTH_ORIENTATION + 1];			   /* back - front */
+} patient_orientation_t;
+
+
+typedef enum patient_phase_tag
+{
+  Phase_ADULT = 1,
+  Phase_CHILD = 2,
+  Phase_UNDEFINED = Enum_UNDEFINED
+} patient_phase_t;
+
+
+typedef enum patient_position_tag
+{
+  Position_LEFT = 1,
+  Position_PRONE = 2,
+  Position_RIGHT = 3,
+  Position_SUPINE = 4,
+  Position_UNDEFINED = Enum_UNDEFINED
+} patient_position_t;
+
+
+typedef enum patient_region_tag
+{
+  Region_BODY = 1,
+  Region_HEAD = 2,
+  Region_UNDEFINED = Enum_UNDEFINED
+} patient_region_t;
+
+
+typedef struct pixel_size_tag
+{
+  double Row;
+  double Col;
+} pixel_size_t;
+
+
+typedef enum pixel_quality_mode_tag
+{
+  Pixel_Quality_ESTIMATED = 1,
+  Pixel_Quality_EXACT = 2,
+  Pixel_Quality_NONE = 3,
+  Pixel_Quality_UNDEFINED = Enum_UNDEFINED
+} pixel_quality_mode_t;
+
+
+typedef struct pixel_quality_code_tag
+{
+  pixel_quality_mode_t Min;
+  pixel_quality_mode_t Mean;
+  pixel_quality_mode_t Max;
+} pixel_quality_code_t;
+
+
+typedef struct pixel_quality_value_tag
+{
+  long Min;
+  long Mean;
+  long Max;
+} pixel_quality_value_t;
+
+
+typedef struct reference_tag
+{
+  image_id_t One;
+  image_id_t Two;
+  image_id_t Three;
+} reference_t;
+
+
+typedef enum rest_direction_tag
+{
+  Rest_FEET = 1,
+  Rest_HEAD = 2,
+  Rest_UNDEFINED = Enum_UNDEFINED
+} rest_direction_t;
+
+
+typedef enum rotation_direction_tag
+{
+  Rotation_NO = 1,
+  Rotation_CC = 2,
+  Rotation_CW = 3,
+  Rotation_UNDEFINED = Enum_UNDEFINED
+} rotation_direction_t;
+
+
+typedef struct sar_sed_tag
+{
+  double Lim;
+  double Cal;
+  double Det;
+} sar_sed_t;
+
+
+typedef enum save_code_tag
+{
+  Save_DONE = 1,
+  Save_MARKED = 2,
+  Save_NOT = 3,
+  Save_UNDEFINED = Enum_UNDEFINED
+} save_code_t;
+
+
+typedef enum sex_tag
+{
+  Sex_F = 1,
+  Sex_M = 2,
+  Sex_O = 3,
+  Sex_UNDEFINED = Enum_UNDEFINED
+} sex_t;
+
+
+typedef enum storage_mode_tag
+{
+  Storage_COMPRESS = 1,
+  Storage_EXPANDED = 2,
+  Storage_MIP_MPR = 5,
+  Storage_REDUCED = 3,
+  Storage_XDR = 4,
+  Storage_UNDEFINED = Enum_UNDEFINED
+} storage_mode_t;
+
+
+typedef enum study_type_tag
+{
+  Study_Type_CRE = 1,
+  Study_Type_MEA = 2,
+  Study_Type_MIP = 3,
+  Study_Type_MPR = 4,
+  Study_Type_RAW = 5,
+  Study_Type_UNDEFINED = Enum_UNDEFINED
+} study_type_t;
+
+
+typedef struct target_point_tag
+{
+  double X;
+  double Y;
+} target_point_t;
+
+
+typedef enum view_direction_tag
+{
+  View_FEET = 1,
+  View_HEAD = 2,
+  View_AtoP = 3,
+  View_LtoR = 4,
+  View_PtoA = 5,
+  View_RtoL = 6,
+  View_UNDEFINED = Enum_UNDEFINED
+} view_direction_t;
+
+
+typedef struct windows_tag
+{
+  long X;
+  long Y;
+} windows_t;
+
+
+typedef enum window_style_tag
+{
+  Style_DOUBLE = 1,
+  Style_HIGH = 2,
+  Style_NONE = 3,
+  Style_STD_1 = 4,
+  Style_STD_2 = 5,
+  Style_UNDEFINED = Enum_UNDEFINED
+} window_style_t;
+
+#endif
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_constants.h
@@ -0,0 +1,76 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_constants.h
+
+   Description: The header file defines the constants used by the internal header
+                definiton.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_CONSTANTS
+#define DS_HEAD_CONSTANTS
+
+#define DS_DUMMY_LENGTH                                                                    1L
+
+/* PRECOMPILER: define length of group overlaying buffers */
+#define LENGTH_GROUP_0008                                                                 384
+#define LENGTH_GROUP_0009                                                                 384
+#define LENGTH_GROUP_0010                                                                 256
+#define LENGTH_GROUP_0011                                                                 128
+#define LENGTH_GROUP_0013                                                                 384
+#define LENGTH_GROUP_0018                                                                 384
+#define LENGTH_GROUP_0019_PART1                                                           128
+#define LENGTH_GROUP_0019_PART2                                                           512
+#define LENGTH_GROUP_0019_PART3                                                           384
+#define LENGTH_GROUP_0019_PART4                                                           256
+#define LENGTH_GROUP_0020                                                                 512
+#define LENGTH_GROUP_0021_PART1                                                           256
+#define LENGTH_GROUP_0021_PART2                                                           256
+#define LENGTH_GROUP_0021_PART3                                                           768
+#define LENGTH_GROUP_0028                                                                 256
+#define LENGTH_GROUP_0029                                                                 256
+#define LENGTH_GROUP_0051                                                                 640
+#define LENGTH_TO_FILL_K_BORDER                                               DS_DUMMY_LENGTH
+
+
+/* PRECOMPILER: define length of common header strings */
+#define LENGTH_LABEL                                                                      26L
+
+
+/* PRECOMPILER: define length of special header stings */
+#define LENGTH_AGE                                                                         4L
+#define LENGTH_COMMENT                                                                    26L
+#define LENGTH_DIAGNOSIS                                                                  40L
+#define LENGTH_DIRECTION                                                                   4L
+#define LENGTH_FILE_NAME                                                                  64L
+#define LENGTH_FILTER_ID                                                                  12L
+#define LENGTH_HEADER_VERSION                                                              8L
+#define LENGTH_NUCLEUS                                                                     8L
+#define LENGTH_MANUFACTURER                                                                8L
+#define LENGTH_ORIENTATION                                                                 3L
+#define LENGTH_PATIENT_ID                                                                 12L
+#define LENGTH_SEQUENCE_INFO                                                               8L
+#define LENGTH_SOFTWARE_VERSION                                                            8L
+
+
+/* PRECOMPILER: define length of origianl headers */
+#define LENGTH_NUM1_HEADER                                                              4096L
+#define LENGTH_NUM2_HEADER                                                              8192L
+#define LENGTH_SOM0_HEADER                                                              2048L
+#define LENGTH_SOM0_IMAGE_TEXT                                                           960L
+#define LENGTH_SOM1_HEADER                                                              4096L
+
+#define LENGTH_SOM_HEADER                                                  LENGTH_SOM1_HEADER
+
+
+/* PRECOMPILER: define Xxx_UNDEFINED constants */
+#define Enum_UNDEFINED                                                               (-19222)
+#define Integer_UNDEFINED                                                            (-19222)
+#define String_UNDEFINED                                                                  '?'
+#define Real_UNDEFINED                                                             (-19222.0)
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_image_text_type.h
@@ -0,0 +1,195 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_image_text_type.h
+
+   Description: The header file defines the data set image text for internal
+                use (internal image text area).
+
+                The image text parameter names are not NEMA item names. Parameters with
+                equal names can but must not contain equal information.
+
+                The sign "->" means, this parameter is derivated from listed NEMA items.
+
+                For more information please see document "Data Set Format" chapter "Group
+                0051'H Image Text".
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_IMAGE_TEXT_TYPE
+#define DS_HEAD_IMAGE_TEXT_TYPE
+
+/* PRECOMPILER: define length constants */
+#define DS_PATIENT_NUMBER_SIZE                                                             12
+
+#define DS_PATIENT_DATE_SIZE                                                               11
+
+#define DS_PATIENT_POSITION_SIZE                                                           11
+
+#define DS_IMAGE_NUMBER_SIZE                                                               11
+#define DS_IMAGE_NUMBER_TEXT                                                          "IMAGE"
+
+#define DS_LABEL_SIZE                                                                       5
+
+#define DS_DATE_OF_MEASUREMENT_SIZE                                                        11
+
+#define DS_TIME_OF_MEASUREMENT_SIZE                                                         5
+
+#define DS_TIME_OF_ACQUISITION_SIZE                                                        11
+#define DS_TIME_OF_ACQUISITION_TEXT_CT                                                   "TI"
+#define DS_TIME_OF_ACQUISITION_TEXT_MR                                                  "TA "
+
+#define DS_NUMBER_OF_ACQUISITIONS_SIZE                                                     11
+#define DS_NUMBER_OF_ACQUISITIONS_TEXT                                                   "AC"
+
+#define DS_COMMENT_NO1_SIZE                                                                26
+
+#define DS_COMMENT_NO2_SIZE                                                                26
+
+#define DS_INSTALLATION_NAME_SIZE                                                          26
+
+#define DS_SOFTWARE_VERSION_SIZE                                                           11
+
+#define DS_MATRIX_SIZE                                                                     11
+
+#define DS_TYPE_OF_MEASUREMENT_SIZE                                                        11
+
+#define DS_SCAN_NUMBER_SIZE                                                                11
+#define DS_SCAN_NUMBER_TEXT                                                            "SCAN"
+
+#define DS_REPETITION_TIME_SIZE                                                            11
+#define DS_REPETITION_TIME_TEXT                                                          "TR"
+
+#define DS_ECHO_TIME_SIZE                                                                  11
+#define DS_ECHO_TIME_TEXT                                                                "TE"
+
+#define DS_GATING_AND_TRIGGER_SIZE                                                         11
+#define DS_GATING_AND_TRIGGER_TEXT                                                       "TD"
+
+#define DS_TUBE_CURRENT_SIZE                                                               11
+#define DS_TUBE_CURRENT_TEXT                                                             "mA"
+
+#define DS_TUBE_VOLTAGE_SIZE                                                               11
+#define DS_TUBE_VOLTAGE_TEXT                                                             "kV"
+
+#define DS_SLICE_THICKNESS_SIZE                                                            11
+#define DS_SLICE_THICKNESS_TEXT                                                          "SL"
+
+#define DS_SLICE_POSITION_SIZE                                                             11
+#define DS_SLICE_POSITION_TEXT                                                           "SP"
+
+#define DS_SLICE_ORIENTATION_NO1_SIZE                                                      11
+#define DS_SLICE_ORIENTATION_NO2_SIZE                           DS_SLICE_ORIENTATION_NO1_SIZE
+#define DS_COR_TEXT                                                                     "Cor"
+#define DS_SAG_TEXT                                                                     "Sag"
+#define DS_TRA_TEXT                                                                     "Tra"
+
+#define DS_FIELD_OF_VIEW_SIZE                                                              11
+#define DS_FIELD_OF_VIEW_TEXT                                                           "FoV"
+
+#define DS_ZOOM_CENTER_SIZE                                                                11
+#define DS_ZOOM_CENTER_TEXT                                                              "CE"
+#define DS_ZOOM_CENTER_TEXT_MR                                                           "MF"
+
+#define DS_GANTRY_TILT_SIZE                                                                11
+#define DS_GANTRY_TILT_TEXT                                                              "GT"
+
+#define DS_TABLE_POSITION_SIZE                                                             11
+#define DS_TABLE_POSITION_TEXT                                                           "TP"
+
+#define DS_MIP_HEADLINE_SIZE                                                                3
+#define DS_MIP_HEADLINE_TEXT                                                            "VOI"
+
+#define DS_MIP_LINE_SIZE                                                                   15
+#define DS_MIP_LINE_TEXT                                                                "Lin"
+
+#define DS_MIP_COLUMN_SIZE                                                                 15
+#define DS_MIP_COLUMN_TEXT                                                              "Col"
+
+#define DS_MIP_SLICE_SIZE                                                                  15
+#define DS_MIP_SLICE_TEXT                                                               "Sli"
+
+#define DS_STUDY_NUMBER_SIZE                                                               11
+#define DS_STUDY_NUMBER_TEXT                                                          "STUDY"
+
+#define DS_CONTRAST_SIZE                                                                    5
+#define DS_CONTRAST_TEXT_CT                                                           "+C IV"
+#define DS_CONTRAST_TEXT_MR                                                           "+C   "
+#define DS_CONTRAST_TEXT_NONE                                                         "     "
+
+#define DS_PATIENT_BIRTHDATE_SIZE                                                          11
+
+#define DS_SEQUENCE_INFO_SIZE                                                              11
+
+#define DS_SATURATION_REGIONS_SIZE                                                         11
+#define DS_SATURATION_REGIONS_TEXT                                                      "SAT"
+
+#define DS_DATA_SET_ID_SIZE                                                                26
+#define DS_DATA_SET_ID_TEXT_STUDY                                                       "STU"
+#define DS_DATA_SET_ID_TEXT_IMAGE                                                       "IMA"
+#define DS_DATA_SET_ID_TEXT_DELIMITER                                                     "/"
+
+#define DS_MAGNIFICATION_FACTOR_SIZE                                                       11
+#define DS_MAGNIFICATION_FACTOR_TEXT                                                     "MF"
+
+#define DS_MANUFACTURER_MODEL_SIZE                                                         26
+
+#define DS_PATIENT_NAME_SIZE                                                               26
+
+#define DS_TIME_OF_SCANNING_SIZE                                                            8
+
+
+
+/* DECLARATION: image text type */
+
+typedef struct image_text_tag
+{
+  char PatientNumber[DS_PATIENT_NUMBER_SIZE + 1];	   /* -> Patient Id */
+  char PatientSexAndAge[DS_PATIENT_DATE_SIZE + 1];	   /* -> Patient Sex, Patient Age */
+  char PatientPosition[DS_PATIENT_POSITION_SIZE + 1];	   /* -> Patient Rest Direction, ... */
+  char ImageNumber[DS_IMAGE_NUMBER_SIZE + 1];		   /* -> Image */
+  char Label[DS_LABEL_SIZE + 1];			   /* -> Archiving Mark Mask, ... */
+  char DateOfMeasurement[DS_DATE_OF_MEASUREMENT_SIZE + 1]; /* -> Acquisition Date */
+  char TimeOfMeasurement[DS_TIME_OF_MEASUREMENT_SIZE + 1]; /* -> Acquisition Time */
+  char TimeOfAcquisition[DS_TIME_OF_ACQUISITION_SIZE + 1]; /* -> CT: Exposure Time -> MR:
+							      Total Measurement Time */
+  char NumberOfAcquisitions[DS_NUMBER_OF_ACQUISITIONS_SIZE + 1];	/* -> Number of Averages */
+  char CommentNo1[DS_COMMENT_NO1_SIZE + 1];		   /* -> Procedure Description */
+  char CommentNo2[DS_COMMENT_NO2_SIZE + 1];
+  char InstallationName[DS_INSTALLATION_NAME_SIZE + 1];	   /* -> Institution ID */
+  char SoftwareVersion[DS_SOFTWARE_VERSION_SIZE + 1];	   /* -> Software Version */
+  char Matrix[DS_MATRIX_SIZE + 1];			   /* -> Rows, Columns */
+  char TypeOfMeasurement[DS_TYPE_OF_MEASUREMENT_SIZE + 1]; /* -> Calculation Mode */
+  char ScanNumber[DS_SCAN_NUMBER_SIZE + 1];		   /* -> Acquisition */
+  char RepetitionTime[DS_REPETITION_TIME_SIZE + 1];	   /* -> Repetition Time */
+  char EchoTime[DS_ECHO_TIME_SIZE + 1];			   /* -> Echo Time */
+  char GatingAndTrigger[DS_GATING_AND_TRIGGER_SIZE + 1];   /* -> Signal Mask */
+  char TubeCurrent[DS_TUBE_CURRENT_SIZE + 1];		   /* -> Exposure */
+  char TubeVoltage[DS_TUBE_VOLTAGE_SIZE + 1];		   /* -> Generator Power */
+  char SliceThickness[DS_SLICE_THICKNESS_SIZE + 1];	   /* -> Slice Thickness */
+  char SlicePosition[DS_SLICE_POSITION_SIZE + 1];	   /* -> Image Distance */
+  char SliceOrientationNo1[DS_SLICE_ORIENTATION_NO1_SIZE + 1];	/* -> Image Position, ... */
+  char SliceOrientationNo2[DS_SLICE_ORIENTATION_NO2_SIZE + 1];
+  char FieldOfView[DS_FIELD_OF_VIEW_SIZE + 1];		   /* -> Field of View */
+  char ZoomCenter[DS_ZOOM_CENTER_SIZE + 1];		   /* -> Target */
+  char GantryTilt[DS_GANTRY_TILT_SIZE + 1];		   /* -> Gantry Tilt */
+  char TablePosition[DS_TABLE_POSITION_SIZE + 1];	   /* -> Location */
+  char MipHeadLine[DS_MIP_HEADLINE_SIZE + 1];		   /* -> <string> */
+  char MipLine[DS_MIP_LINE_SIZE + 1];			   /* -> MIP x Row */
+  char MipColumn[DS_MIP_COLUMN_SIZE + 1];		   /* -> MIP x Column */
+  char MipSlice[DS_MIP_SLICE_SIZE + 1];			   /* -> MIP x Slice */
+  char StudyNumber[DS_STUDY_NUMBER_SIZE + 1];		   /* -> Study */
+  char Contrast[DS_CONTRAST_SIZE + 1];			   /* -> Contrast Agent */
+  char PatientBirthdate[DS_PATIENT_BIRTHDATE_SIZE + 1];    /* -> Patient Birthday */
+  char SequenceInformation[DS_SEQUENCE_INFO_SIZE + 1];     /* -> Sequence File Owner, ... */
+  char SaturationRegions[DS_SATURATION_REGIONS_SIZE + 1];  /* -> Saturation Regions, ... */
+  char DataSetId[DS_DATA_SET_ID_SIZE + 1];                 /* -> Image, Study */
+  char MagnificationFactor[DS_MAGNIFICATION_FACTOR_SIZE + 1]; /* -> Image Maginification Factor */
+  char ManufacturerModel[DS_MANUFACTURER_MODEL_SIZE + 1];  /* -> Manufacturer Model */
+  char PatientName[DS_PATIENT_NAME_SIZE + 1];              /* -> Patient Name */
+  char TimeOfScanning[DS_TIME_OF_SCANNING_SIZE + 1];	   /* -> Acquisition Time */
+} image_text_t;
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_shadow_groups_types.h
@@ -0,0 +1,671 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_shadow_groups_types.h
+
+   Description: The header file defines the SPI and CMS defined data set basic groups
+                (odd group numbers) as structures for internal use (internal header).
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_SHADOW_GROUPS_TYPES
+#define DS_HEAD_SHADOW_GROUPS_TYPES
+
+/******************************************/
+/* Identifying Information (Group 0009'H) */
+/******************************************/
+
+typedef struct shadow_identifying_tag
+{
+  data_object_subtype_t DataObjectSubtype;		   /* (0009,1041)    8  AT EV 2NS-SPI */
+  long NumberOfMeasurements;				   /* (0009,1200)    6  AN FF 3NS-CMS */
+  storage_mode_t StorageMode;				   /* (0009,1210)    8  AT EV 2DS-CMS */
+  long EvaluationMask;					   /* (0009,1212)    4  BD FF 2DS-CMS */
+  long Gap1212;
+  ds_date_t LastMoveDate;				   /* (0009,1226)   10  AT DF 3NS-CMS */
+  ds_time_t LastMoveTime;				   /* (0009,1227)   12  AT DF 3NS-CMS */
+  char GeneratorIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1310)   26  AT DF 2DS-CMS */
+  char GantryIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1311)   26  AT DF 2DS-CMS */
+  char XRayTubeIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1312)   26  AT DF 2DS-CMS */
+  char DetectorIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1313)   26  AT DF 2DS-CMS */
+  char DASIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1314)   26  AT DF 2DS-CMS */
+  char SMIIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1315)   26  AT DF 2DS-CMS */
+  char CPUIdentificationLabel[LENGTH_LABEL + 1];	   /* (0009,1316)   26  AT DF 2DS-CMS */
+  char HeaderVersion[LENGTH_HEADER_VERSION + 1];	   /* (0009,1320)    8  AT DF 2DS-CMS */
+} shadow_identifying_t;
+
+
+
+/**************************************/
+/* Patient Information (Group 0011'H) */
+/**************************************/
+
+typedef struct shadow_patient_tag
+{
+  char Organ[LENGTH_LABEL + 1];				   /* (0011,1010)   26  AT FF 3NS-SPI */
+  ds_date_t RegistrationDate;				   /* (0011,1110)   10  AT DF 2NS-CMS */
+  ds_time_t RegistrationTime;				   /* (0011,1111)   12  AT DF 2NS-CMS */
+  long UsedPatientWeight;				   /* (0011,1123)    4  AN FF 2NS-CMS */
+  long OrganCode;                                          /* (0011,1012)    6  AN FF 3NS-CMS */
+} shadow_patient_t;
+
+
+
+/*********************************************/
+/* Patient Modify Information (Group 0013'H) */
+/*********************************************/
+
+typedef struct shadow_patient_modify_tag
+{
+  char ModifyingPhysician[LENGTH_LABEL + 1];		   /* (0013,1000)   26  AT FF 2NS-CMS */
+  ds_date_t ModificationDate;				   /* (0013,1010)   10  AT DF 2NS-CMS */
+  ds_time_t ModificationTime;				   /* (0013,1012)   12  AT DF 2NS-CMS */
+  char PatientName[LENGTH_LABEL + 1];			   /* (0013,1020)   26  AT FF 3NS-CMS */
+  char PatientId[LENGTH_PATIENT_ID + 1];		   /* (0013,1022)   12  AT FF 3NS-CMS */
+  ds_date_t PatientBirthdate;				   /* (0013,1030)   10  AT DF 3NS-CMS */
+  long PatientWeight;					   /* (0013,1031)    6  AN FF 3NS-CMS */
+  char PatientMaidenName[LENGTH_LABEL + 1];		   /* (0013,1032)   26  AT FF 3NS-CMS */
+  char ReferringPhysician[LENGTH_LABEL + 1];		   /* (0013,1033)   26  AT FF 3NS-CMS */
+  char AdmittingDiagnosis[LENGTH_DIAGNOSIS + 1];	   /* (0013,1034)   40  AT FF 3DS-CMS */
+  sex_t PatientSex;					   /* (0013,1035)    2  AT EV 3NS-CMS */
+  char ProcedureDescription_1[LENGTH_COMMENT + 1];	   /* (0013,1040)   52  AT FF 3NS-CMS */
+  char ProcedureDescription_2[LENGTH_COMMENT + 1];
+  rest_direction_t RestDirection;			   /* (0013,1042)    4  AT EV 3NS-CMS */
+  patient_position_t PatientPosition;			   /* (0013,1044)    8  AT EV 3NS-CMS */
+  view_direction_t ViewDirection;			   /* (0013,1046)    4  AT EV 2NS-CMS */
+} shadow_patient_modify_t;
+
+
+
+/******************************************/
+/* Acquisition Information (Group 0019'H) */
+/******************************************/
+
+typedef struct shadow_acquisition_cms_tag		   /* CMS shadowsubgroup */
+{
+  long NetFrequency;					   /* (0019,1010)    6  AN FF 3NS-CMS */
+  measurement_mode_t MeasurementMode;			   /* (0019,1020)    8  AT EV 2DS-CMS */
+  calculation_mode_t CalculationMode;			   /* (0019,1030)    8  AT EV 2NS-CMS */
+  long Gap1040;
+  long NoiseLevel;					   /* (0019,1050)    6  AN FF 3NS-CMS */
+  long NumberOfDataBytes;				   /* (0019,1060)    6  AN FF 2NS-CMS */
+} shadow_acquisition_cms_t;
+
+
+typedef struct shadow_acquisition_ct_tag		   /* CT shadowsubgroup */
+{
+  double SourceSideCollimatorAperture;			   /* (0019,1110)   14  AN FF 3NS-CMS */
+  double DetectorSideCollimatorAperture;		   /* (0019,1111)   14  AN FF 3NS-CMS */
+  long ExposureTime;					   /* (0019,1120)    6  AN FF 3NS-CMS */
+  long Exposure;					   /* (0019,1121)    6  AN FF 3NS-CMS */
+  double GeneratorPower;				   /* (0019,1125)   14  AN FF 3NS-CMS */
+  long GeneratorVoltage;				   /* (0019,1126)    6  AN FF 3NM-CMS */
+  long GeneratorVoltageDual;
+  long MasterControlMask;				   /* (0019,1140)    4  BD HX 3NM-CMS */
+  long Gap1140;
+  short ProcessingMask[5];				   /* (0019,1142)    2  BI HX 3NM-CMS */
+  short Gap1142[3];
+  long NumberOfVirtuellChannels;			   /* (0019,1162)    6  AN FF 3NS-CMS */
+  long NumberOfReadings;				   /* (0019,1170)    6  AN FF 3NS-CMS */
+  long NumberOfProjections;				   /* (0019,1174)    6  AN FF 3NS-CMS */
+  long NumberOfBytes;					   /* (0019,1175)    6  AN FF 3NS-CMS */
+  long ReconstructionAlgorithmSet[3];                      /* (0019,1180)    6  AN FF 3NS-CMS */
+  long Gap1180[2];
+  long ReconstructionAlgorithmIndex;                       /* (0019,1181)    6  AN FF 3NS-CMS */
+  char RegenerationSoftwareVersion[LENGTH_SOFTWARE_VERSION + 1]; /* (0019,1182)    8  AT FF 3NS-CMS */
+} shadow_acquisition_ct_t;
+
+
+typedef struct shadow_acquisition_mr_tag		   /* MR shadowsubgroup */
+{
+  double TotalMeasurementTime;				   /* (0019,1210)   14  AN FF 3NS-CMS */
+  double StartDelayTime;				   /* (0019,1212)   14  AN FF 3NS-CMS */
+  long NumberOfPhases;					   /* (0019,1214)    6  AN FF 2DS-CMS */
+  long SequenceControlMask[2];				   /* (0019,1216)    4  BD HX 3NM-CMS */
+  long Gap1216[2];
+  long NumberOfFourierLinesNominal;			   /* (0019,1220)    6  AN FF 3NS-CMS */
+  long NumberOfFourierLinesCurrent;			   /* (0019,1221)    6  AN FF 3NS-CMS */
+  long NumberOfFourierLinesAfterZero;			   /* (0019,1226)    6  AN FF 3NS-CMS */
+  long FirstMeasuredFourierLine;			   /* (0019,1228)    6  AN FF 3NS-CMS */
+  long AcquisitionColumns;				   /* (0019,1230)    6  AN FF 3NS-CMS */
+  long ReconstructionColumns;				   /* (0019,1231)    6  AN FF 3NS-CMS */
+  long NumberOfAverages;				   /* (0019,1250)    6  AN FF 3NS-CMS */
+  double FlipAngle;					   /* (0019,1260)   14  AN FF 3NS-CMS */
+  long NumberOfPrescans;				   /* (0019,1270)    6  AN FF 3NS-CMS */
+  filter_type_t FilterTypeRawData;			   /* (0019,1281)    8  AT EV 2DS-CMS */
+  filter_parameter_t FilterParameterRawData;		   /* (0019,1282)   14  AN FF 3NM-CMS */
+  filter_type_image_t FilterTypeImageData;		   /* (0019,1283)    8  AT EV 2DS-CMS */
+  int Pad1;                                                /* Dummy for byte alignament */
+  filter_parameter_t FilterParameterImageData;		   /* (0019,1284)   14  AN FF 3NM-CMS */
+  filter_type_t FilterTypePhaseCorrection;		   /* (0019,1285)    8  AT EV 2DS-CMS */
+  int Pad2;                                                /* Dummy for byte alignament */
+  filter_parameter_t FilterParameterPhaseCorrection;	   /* (0019,1286)   14  AN FF 3NM-CMS */
+  long NumberOfSaturationRegions;			   /* (0019,1290)    6  AN FF 2DS-CMS */
+  /*  short Pad4[5];                                                /* Dummy for byte alignment */
+  int Pad3;                                                /* Dummy for byte alignament */
+  double ImageRotationAngle;				   /* (0019,1294)   14  AN FF 3NS-CMS */
+  double DwellTime;					   /* (0019,1213)   14  AN FF 3NS-CMS */
+  long CoilIdMask[3];					   /* (0019,1296)    4  BD HX 3NM-CMS */
+  long Gap1296[2];
+  int Pad4;                                                /* Dummy for byte alignament */
+  image_location_t CoilPosition;			   /* (0019,1298)   14  AN FF 2NM-CMS */
+  double TotalMeasurementTimeCur;			   /* (0019,1211)   14  AN FF 3NS-CMS*/
+  long MeasurementStatusMask;				   /* (0019,1218)    4  BD FF 2DS-CMS */
+} shadow_acquisition_mr_t;
+
+
+typedef struct shadow_acquisition_ct_conf_tag		   /* CT configuration and adjust
+							      shadowsubgroup */
+{
+  long DistanceSourceToSourceSideCollimator;		   /* (0019,1310)    6  AN FF 3NS-CMS */
+  long DistanceSourceToDetectorSideCollimator;		   /* (0019,1311)    6  AN FF 3NS-CMS */
+  long NumberOfPossibleChannels;			   /* (0019,1320)    6  AN FF 3NS-CMS */
+  long MeanChannelNumber;				   /* (0019,1321)    6  AN FF 3NS-CMS */
+  double DetectorSpacing;				   /* (0019,1322)   14  AN FF 3NS-CMS */
+  double ReadingIntegrationTime;			   /* (0019,1324)   14  AN FF 3NS-CMS */
+  double DetectorAlignment;				   /* (0019,1350)   14  AN FF 3NS-CMS */
+  double FocusAlignment;				   /* (0019,1360)   14  AN FF 3NS-CMS */
+  long FocalSpotDeflectionAmplitude;			   /* (0019,1365)    4  BD HX 3NS-CMS */
+  long FocalSpotDeflectionPhase;			   /* (0019,1366)    4  BD HX 3NS-CMS */
+  long FocalSpotDeflectionOffset;			   /* (0019,1367)    4  BD HX 3NS-CMS */
+  double WaterScalingFactor;				   /* (0019,1370)   14  AN FF 3NS-CMS */
+  double InterpolationFactor;				   /* (0019,1371)   14  AN FF 3NS-CMS */
+  patient_region_t PatientRegion;			   /* (0019,1380)    4  AT EV 3NS-CMS */
+  patient_phase_t PatientPhaseOfLife;			   /* (0019,1382)    8  AT EV 3NS-CMS */
+  double DetectorCenter;				   /* (0019,1323)   14  AN FF 3NS-CMS */
+} shadow_acquisition_ct_conf_t;
+
+
+typedef struct shadow_acquisition_mr_conf_tag		   /* MR configuration and adjust
+							      shadowsubgroup */
+{
+  double MagneticFieldStrength;				   /* (0019,1412)   14  AN FF 3NS-CMS */
+  double ADCVoltage;					   /* (0019,1414)   14  AN FF 3NS-CMS */
+  double TransmitterAmplitude;				   /* (0019,1420)   14  AN FF 3NS-CMS */
+  long NumberOfTransmitterAmplitudes;			   /* (0019,1421)    6  AN FF 3NS-CMS */
+  int Pad1;                                                /* Dummy for byte alignment */
+  double TransmitterCalibration;			   /* (0019,1424)   14  AN FF 3NS-CMS */
+  double ReceiverTotalGain;				   /* (0019,1450)   14  AN FF 3NS-CMS */
+  double ReceiverAmplifierGain;				   /* (0019,1451)   14  AN FF 3NS-CMS */
+  double ReceiverPreamplifierGain;			   /* (0019,1452)   14  AN FF 3NS-CMS */
+  double ReceiverCableAttenuation;			   /* (0019,1454)   14  AN FF 3NS-CMS */
+  double ReconstructionScaleFactor;			   /* (0019,1460)   14  AN FF 3NS-CMS */
+  double PhaseGradientAmplitude;			   /* (0019,1470)   14  AN FF 3NS-CMS */
+  double ReadoutGradientAmplitude;			   /* (0019,1471)   14  AN FF 3NS-CMS */
+  double SelectionGradientAmplitude;			   /* (0019,1472)   14  AN FF 3NS-CMS */
+  gradient_delay_time_t GradientDelayTime;		   /* (0019,1480)   14  AN FF 3NS-CMS */
+  char SensitivityCorrectionLabel[LENGTH_LABEL + 1];	   /* (0019,1490)   26  AT FF 2DS-CMS */
+  int Pad2;                                                /* Dummy for byte alignment */
+  double ADCOffset[2];					   /* (0019,1416)   14  AN FF 3NM-CMS */
+  double TransmitterAttenuator;                            /* (0019,1422)   14  AN FF 3NS-CMS */
+  double TransmitterReference;                             /* (0019,1426)   14  AN FF 3NS-CMS */
+  double ReceiverReferenceGain;                            /* (0019,1455)   14  AN FF 3NS-CMS */
+  long ReceiverFilterFrequency;                            /* (0019,1456)    6  AN FF 3NS-CMS */
+  int Pad3;                                                /* Dummy for byte alignment */
+  double ReferenceScaleFactor;                             /* (0019,1462)   14  AN FF 3NS-CMS */
+  double TotalGradientDelayTime;                           /* (0019,1482)   14  AN FF 3NS-CMS */
+  long RfWatchdogMask;                                     /* (0019,14A0)    4  BD HX 3NM-CMS */
+  int Pad4;                                                /* Dummy for byte alignment */
+  double RfPowerErrorIndicator;                            /* (0019,14A2)   14  AN FF 3NS-CMS */
+  sar_sed_t SarWholeBody;                                  /* (0019,14A5)   14  AN FF 3NS-CMS */
+  sar_sed_t Sed;                                           /* (0019,14A6)   14  AN FF 3NS-CMS */
+  long AdjustmentStatusMask;				   /* (0019,14B0)    4 BD FF 2DS-CMS */
+} shadow_acquisition_mr_conf_t;
+
+
+typedef struct shadow_acquisition_acq_tag		   /* acquisition shadowsubgroup */
+{
+  char ParameterFileName[LENGTH_FILE_NAME + 1];		   /* (0019,1510)   64  AT FF 3NS-CMS */
+  char SequenceFileName[LENGTH_FILE_NAME + 1];		   /* (0019,1511)   64  AT FF 3NS-CMS */
+  char SequenceFileOwner[LENGTH_SEQUENCE_INFO + 1];        /* (0019,1512)    8  AT FF 2DS-CMS */
+  char SequenceDescription[LENGTH_SEQUENCE_INFO + 1];      /* (0019,1513)    8  AT FF 2DS-CMS */
+} shadow_acquisition_acq_t;
+
+
+/*******************************************/
+/* Relationship Information (Group 0021'H) */
+/*******************************************/
+
+typedef struct shadow_relationship_med_cms_tag		   /* MED and CMS shadowsubgroups */
+{
+  double Gap1010;
+  target_point_t Target;				   /* (0021,1011)   30  AT FF 2NM-MED */
+  short RoiMask;					   /* (0021,1020)    2  BI HX 2NS-MED */
+  int Pad1;                                                /* Dummy for byte alignment */
+  field_of_view_t FoV;					   /* (0021,1120)   30  AN FF 2NM-CMS */
+  view_direction_t ViewDirection;			   /* (0021,1130)    4  AT EV 2NS-CMS */
+  rest_direction_t RestDirection;			   /* (0021,1132)    4  AT EV 2NS-CMS */
+  image_location_t ImagePosition;			   /* (0021,1160)   14  AN FF 2NM-CMS */
+  image_location_t ImageNormal;				   /* (0021,1161)   14  AN FF 2NM-CMS */
+  double ImageDistance;					   /* (0021,1163)   14  AN FF 2NM-CMS */
+  short ImagePositioningHistoryMask;			   /* (0021,1165)    2  BI HX 2DS-CMS */
+  int Pad2;                                                /* Dummy for byte alignment */
+  image_location_t ImageRow;				   /* (0021,116A)   14  AN FF 2NM-CMS */
+  image_location_t ImageColumn;				   /* (0021,116B)   14  AN FF 2NM-CMS */
+  patient_orientation_t PatientOrientationSet1;		   /* (0021,1170)    4  AT EV 2NM-CMS */
+  patient_orientation_t PatientOrientationSet2;		   /* (0021,1171)    4  AT EV 2NM-CMS */
+  char StudyName[LENGTH_LABEL + 1];			   /* (0021,1180)   26  AT FF 3NS-CMS */
+  study_type_t StudyType;				   /* (0021,1182)    4  AT EV 3NS-CMS */
+  double ImageMagnificationFactor;                         /* (0021,1122)   14  AN FF 2DS-CMS */
+} shadow_relationship_med_cms_t;
+
+
+typedef struct shadow_relationship_ct_tag		   /* CT common shadowsubgroups */
+{
+  long RotationAngle;					   /* (0021,1210)    6  AN FF 3NS-CMS */
+  long StartAngle;					   /* (0021,1211)    6  AN FF 3NS-CMS */
+  long TubePosition;					   /* (0021,1230)    6  AN FF 3NS-CMS */
+  long LengthOfTopogram;				   /* (0021,1232)    6  AN FF 3NS-CMS */
+  double CorrectionFactor;				   /* (0021,1234)   14  AN FF 3NS-CMS */
+  long MaximumTablePosition;				   /* (0021,1236)    6  AN FF 3NS-CMS */
+  long TableMoveDirectionCode;				   /* (0021,1240)    6  AN FF 3NS-CMS */
+  long VectorStartRow;					   /* (0021,1250)    6  AN FF 3NS-CMS */
+  long VectorRowStep;					   /* (0021,1251)    6  AN FF 3NS-CMS */
+  long VectorStartColumn;				   /* (0021,1252)    6  AN FF 3NS-CMS */
+  long VectorColumnStep;				   /* (0021,1253)    6  AN FF 3NS-CMS */
+  long VoiStartRow;					   /* (0021,1245)    6  AN FF 3NS-CMS */
+  long VoiStopRow;					   /* (0021,1246)    6  AN FF 3NS-CMS */
+  long VoiStartColumn;					   /* (0021,1247)    6  AN FF 3NS-CMS */
+  long VoiStopColumn;					   /* (0021,1248)    6  AN FF 3NS-CMS */
+  long VoiStartSlice;					   /* (0021,1249)    6  AN FF 3NS-CMS */
+  long VoiStopSlice;					   /* (0021,124A)    6  AN FF 3NS-CMS */
+  long RangeTypeCode;					   /* (0021,1260)    6  AN FF 3NS-CMS */
+  long ReferenceTypeCode;				   /* (0021,1262)    6  AN FF 3NS-CMS */
+  object_orientation_t ObjectOrientation;		   /* (0021,1270)   14  AN FF 3NS-CMS */
+  object_orientation_t LightOrientation;		   /* (0021,1272)   14  AN FF 3NS-CMS */
+  double LightBrightness;				   /* (0021,1275)   14  AN FF 3NS-CMS */
+  double LightContrast;					   /* (0021,1276)   14  AN FF 3NS-CMS */
+  object_threshold_t OverlayThreshold;			   /* (0021,127A)   12  AN FF 3NM-CMS */
+  object_threshold_t SurfaceThreshold;			   /* (0021,127B)   12  AN FF 3NM-CMS */
+  object_threshold_t GreyScaleThreshold;		   /* (0021,127C)   12  AN FF 3NM-CMS */
+} shadow_relationship_ct_t;
+
+
+typedef struct shadow_relationship_mr_tag		   /* MR common shadowsubgroups */
+{
+  long PhaseCorRowSeq;					   /* (0021,1320)    6  AN FF 3NS-CMS */
+  long PhaseCorColSeq;					   /* (0021,1321)    6  AN FF 3NS-CMS */
+  long PhaseCorRowRec;					   /* (0021,1322)    6  AN FF 3NS-CMS */
+  long PhaseCorColRec;					   /* (0021,1324)    6  AN FF 3NS-CMS */
+  long NumberOf3DRawPartNom;				   /* (0021,1330)    6  AN FF 3NS-CMS */
+  long NumberOf3DRawPartCur;				   /* (0021,1331)    6  AN FF 3NS-CMS */
+  long NumberOf3DImaPart;				   /* (0021,1334)    6  AN FF 3NS-CMS */
+  long Actual3DImaPartNumber;				   /* (0021,1336)    6  AN FF 3NS-CMS */
+  long Gap1338;
+  long NumberOfSlicesNom;				   /* (0021,1340)    6  AN FF 3NS-CMS */
+  long NumberOfSlicesCur;				   /* (0021,1341)    6  AN FF 3NS-CMS */
+  long CurrentSliceNumber;				   /* (0021,1342)    6  AN FF 3NS-CMS */
+  long CurrentGroupNumber;				   /* (0021,1343)    6  AN FF 3NS-CMS */
+  long MipStartRow;					   /* (0021,1345)    6  AN FF 3NS-CMS */
+  long MipStopRow;					   /* (0021,1346)    6  AN FF 3NS-CMS */
+  long MipStartColumn;					   /* (0021,1347)    6  AN FF 3NS-CMS */
+  long MipStopColumn;					   /* (0021,1348)    6  AN FF 3NS-CMS */
+  long MipStartSlice;					   /* (0021,1349)    6  AN FF 3NS-CMS */
+  long MipStopSlice;					   /* (0021,134A)    6  AN FF 3NS-CMS */
+  long SignalMask;					   /* (0021,1350)    4  BI HX 2DS-CMS */
+  long Gap1350;
+  long DelayAfterTrigger;				   /* (0021,1352)    6  AN FF 3NS-CMS */
+  long RRInterval;					   /* (0021,1353)    6  AN FF 3NS-CMS */
+  int Pad1;                                                /* Dummy for byte alignment */
+  double NumberOfTriggerPulses;				   /* (0021,1354)   14  AN FF 3NS-CMS */
+  double RepetitionTime;				   /* (0021,1356)   14  AN FF 3NS-CMS */
+  gate_phase_t GatePhase;				   /* (0021,1357)   12  AT EV 3NS-CMS */
+  int Pad2;                                                /* Dummy for byte alignment */
+  double GateThreshold;					   /* (0021,1358)   14  AN FF 3NS-CMS */
+  double GateRatio;					   /* (0021,1359)   14  AN FF 3NS-CMS */
+  long NumberOfInterpolatedImages;			   /* (0021,1360)    6  AN FF 3NS-CMS */
+  long NumberOfEchoes;					   /* (0021,1370)    6  AN FF 3NS-CMS */
+  double SecondEchoTime;				   /* (0021,1372)   14  AN FF 3NS-CMS */
+  double SecondRepetitionTime;				   /* (0021,1373)   14  AN FF 3NS-CMS */
+  long CardiacCode;				           /* (0021,1380)    6  AN FF 3NS-CMS */
+  int Pad3;                                                /* Dummy for byte alignment */
+  double CurrentSliceDistanceFactor;                       /* (0021,1344)   14  AN FF 3NS-CMS */
+  order_of_slices_t OrderOfSlices;                         /* (0021,134F)   12  AT EV 3NS-CMS */
+  int Pad4;                                                /* Dummy for byte alignment */
+  double SlabThickness;					   /* (0021,1339)    6  AN FF 3NS-CMS */
+} shadow_relationship_mr_t;
+
+
+typedef struct shadow_relationship_ct_spe_tag		   /* CT special shadowsubgroups */
+{
+  long EvaluationMask[2];				   /* (0021,2220)    4  BD FF 2DM-CMS */
+  long Gap2220[2];
+  short ExtendedProcessingMask[7];			   /* (0021,2230)    4  BD FF 2DM-CMS */
+  short Gap2230[3];
+  long CreationMask[2];					   /* (0021,2210)    2  BI HX 3NM-CMS
+ */
+  long Gap2210[2];
+} shadow_relationship_ct_spe_t;
+
+
+typedef struct shadow_relationship_mr_spe_tag		   /* MR special shadowsubgroups */
+{
+  double EpiReconstructionPhase;			   /* (0019,12A0)   14  AN FF 3NS-CMS */
+  double EpiReconstructionSlope;			   /* (0019,12A1)   14  AN FF 3NS-CMS */
+  double EpiCapacity[6];				   /* (0019,14C1)   14  AN FF 3NM-CMS */
+  double EpiInductance[3];				   /* (0019,14C2)   14  AN FF 3NM-CMS */
+  long EpiSwitchConfigurationCode[3];			   /* (0019,14C3)    6  AN FF 3NM-CMS */
+  long EpiSwitchHardwareCode[3];			   /* (0019,14C4)    6  AN FF 3NM-CMS */
+  long EpiSwitchDelayTime[6];				   /* (0019,14C5)    6  AN FF 3NM-CMS */
+  char EpiFileName[LENGTH_FILE_NAME + 1];		   /* (0019,1514)   64  AT FF 3NS-CMS */
+  
+} shadow_relationship_mr_spe_t;
+
+
+/*************************************************/
+/* Image Presentation Information (Group 0029'H) */
+/*************************************************/
+
+typedef struct shadow_presentation_tag
+{
+  window_style_t WindowStyle;				   /* (0029,1110)    8  AT EV 2DS-CMS */
+  pixel_quality_code_t PixelQualityCode;		   /* (0029,1120)   12  AT FF 2DM-CMS */
+  pixel_quality_value_t PixelQualityValue;		   /* (0029,1122)    6  AN FF 3NM-CMS */
+  save_code_t ArchiveCode;				   /* (0029,1150)    8  AN EV 3NS-CMS */
+  save_code_t ExposureCode;				   /* (0029,1151)    8  AN EV 3NS-CMS */
+  long SortCode;					   /* (0029,1152)    6  AN FF 3NS-CMS */
+  long Splash;						   /* (0029,1160)    6  AN FF 3NS-CMS */
+} shadow_presentation_t;
+
+#endif
+
+
+
+
+/*==  HELP TEXT  ===========================================================================*/
+
+#ifdef DS_STC_TOOL
+
+"G09.Ide.DataObjectSubtype.M",
+"Data Object Subtype (0009,0041) - main: CT | MR Signed | MR Unsigned",
+"G09.Ide.DataObjectSubtype.D",
+"Data Object Subtype (0009,0041) - defined by: Predefined | defined by User",
+"G09.Ide.DataObjectSubtype.S - sub: NONE",
+"Data Object Subtype (0009,0041)",
+"G09.Ide.NumberOfMeasurements", "Number of Measurements (0009,1200)",
+"G09.Ide.StorageMode", 
+"Storage Mode (0009,1210): COMPRESS | EXPANDED | MIP_MPR | REDUCED | XDR",
+"G09.Ide.EvaluationMask", "Evaluation Mask - Image (0009,1212)",
+"G09.Ide.LastMoveDate.Year", "Last Move Date (0009,1226)",
+"G09.Ide.LastMoveTime.Hour", "Last Move Time (0009,1227)",
+"G09.Ide.GeneratorIdentificationLabel", "Generator Identification Label (0009,1310)",
+"G09.Ide.GantryIdentificationLabel", "Gantry Identification Label (0009,1311)",
+"G09.Ide.XRayTubeIdentificationLabel", "X-Ray Tube Identification Label (0009,1312)",
+"G09.Ide.DetectorIdentificationLabel", "Detector Identification Label (0009,1313)",
+"G09.Ide.DASIdentificationLabel", "DAS Identification Label (0009,1314)",
+"G09.Ide.SMIIdentificationLabel", "SMI Identification Label (0009,1315)",
+"G09.Ide.CPUIdentificationLabel", "CPU Identification Label (0009,1316)",
+"G09.Ide.HeaderVersion", "Header Version (0009,1320)",
+
+"G11.Pat.Organ", "Organ (0011,1010)",
+"G11.Pat.RegistrationDate.Year", "Registration Date (0011,1110)",
+"G11.Pat.RegistrationTime.Hour", "Registration Time (0011,1111)",
+"G11.Pat.UsedPatientWeight", "Used Patient Weight (0011,1123) in kg",
+"G11.Pat.OrganCode", "Organ Code (0011,1140)",
+
+"G13.PatMod.ModifyingPhysician", "Modifying Physician (0013,1000)",
+"G13.PatMod.ModificationDate.Year", "Modification Date (0013,1022)",
+"G13.PatMod.ModificationTime.Hour", "Modification Time (0013,1010)",
+"G13.PatMod.PatientName", "former Patient Name (0013,1020)",
+"G13.PatMod.PatientId", "former Patient Id (0013,1022)",
+"G13.PatMod.PatientBirthdate.Year", "former Patient Birthdate (0013,1030)",
+"G13.PatMod.PatientWeight", "former Patient Weight (0013,1031)",
+"G13.PatMod.PatientMaidenName", "former Patient Maiden Name (0013,1032)",
+"G13.PatMod.ReferringPhysician", "former Referring Physician (0013,1033)",
+"G13.PatMod.AdmittingDiagnosis", "former Admitting Diagnosis (0013,1034)",
+"G13.PatMod.PatientSex", "former Patient Sex (0013,1035)",
+"G13.PatMod.ProcedureDescription_1", "former Procedure Description_1 (0013,1040)",
+"G13.PatMod.ProcedureDescription_2", "former Procedure Description_2",
+"G13.PatMod.RestDirection", "former Rest Direction (0013,1042)",
+"G13.PatMod.PatientPosition", "former Patient Position (0013,1044)",
+"G13.PatMod.ViewDirection", "former View Direction (0013,1046)",
+
+"G19.Acq1.CM.NetFrequency", "Net Frequency (0019,1010) in Hz",
+"G19.Acq1.CM.MeasurementMode.M",
+"Measurement Mode (0019,1020) - main: ADJUstment | EXAMination | TEST",
+"G19.Acq1.CM.MeasurementMode.S",
+"Measurement Mode (0019,1020) - subreason",
+"G19.Acq1.CM.CalculationMode.M",
+"CalculationMode (0019,1030) - main: NONE | A| PC | PU",
+"G19.Acq1.CM.CalculationMode.S",
+"Calculation Mode (0019,1030) - sub: NONE |BSP | IRS | SUN | VAX",
+"G19.Acq1.CM.NoiseLevel", "Noise Level (0019,1050)",
+"G19.Acq1.CM.NumberOfDataBytes", "Number of Data Bytes (0019,1060)",
+
+"G19.Acq2.Ct.SourceSideCollimatorAperture",
+"Source Side Collimator Aperture (0019,1110) in mm",
+"G19.Acq2.Ct.DetectorSideCollimatorAperture",
+"Detector Side Collimator Aperture (0019,1111) in mm",
+"G19.Acq2.Ct.ExposureTime", "current Exposure Time (0019,1120) in msec",
+"G19.Acq2.Ct.Exposure", "current Exposure (0019,1121) in mAs",
+"G19.Acq2.Ct.GeneratorPower", "current Generator Power (0019,1125) in kW",
+"G19.Acq2.Ct.GeneratorVoltage", "current Generator Voltage (0019,1126) in kV",
+"G19.Acq2.Ct.GeneratorVoltageDual", "second value of Generator Voltage (0019,1126) in kV",
+"G19.Acq2.Ct.MasterControlMask", "Master Control Mask (0019,1140)",
+"G19.Acq2.Ct.ProcessingMask", "Processing Mask (0019,1142)",
+"G19.Acq2.Ct.NumberOfVirtuellChannels", "Number of Virtuell Channels (0019,1162)",
+"G19.Acq2.Ct.NumberOfReadings", "Number of Readings (0019,1170)",
+"G19.Acq2.Ct.NumberOfProjections", "Number of Projections (0019,1174)",
+"G19.Acq2.Ct.NumberOfBytes", "Number of Bytes (0019,1175)",
+"G19.Acq2.Ct.ReconstructionAlgorithmSet", 
+"Reconstruction Algorithm Set (0019,1180): smooth, standard, sharp RPF number",
+"G19.Acq2.Ct.ReconstructionAlgorithmIndex", "Reconstruction Algorithm Index (0019,1181)",
+"G19.Acq2.Ct.RegenerationSoftwareVersion", "Regeneration Software Version (0019,1182)",
+
+"G19.Acq2.Mr.TotalMeasurementTime", "Total Measurement Time - nominal (0019,1210) in sec",
+"G19.Acq2.Mr.TotalMeasurementTimeCur", "Total Measurement Time - current (0019,1211) in sec",
+"G19.Acq2.Mr.StartDelayTime", "Start Delay Time (0019,1212) in sec",
+"G19.Acq2.Mr.DwellTime", "Dwell Time (0019,1213) in usec",
+"G19.Acq2.Mr.NumberOfPhases", "Number of Phases (0019,1214)",
+"G19.Acq2.Mr.SequenceControlMask", "Sequence Control Mask (0019,1216)",
+"G19.Acq2.Mr.MeasurementStatusMask", "Measurement Status Mask (0019,1218)",
+"G19.Acq2.Mr.NumberOfFourierLinesNominal", "nominal Number of Fourier Lines (0019,1220)",
+"G19.Acq2.Mr.NumberOfFourierLinesCurrent", "current Number of Fourier Lines (0019,1221)",
+"G19.Acq2.Mr.NumberOfFourierLinesAfterZero", "Number of Fourier Lines after Zero (0019,1226)",
+"G19.Acq2.Mr.FirstMeasuredFourierLine", "First Measured Fourier Line (0019,1228)",
+"G19.Acq2.Mr.AcquisitionColumns", "Acquisition Columns (0019,1230)",
+"G19.Acq2.Mr.ReconstructionColumns", "Reconstruction Columns (0019,1231)",
+"G19.Acq2.Mr.NumberOfAverages", "current Number of Averages (0019,1250)",
+"G19.Acq2.Mr.FlipAngle", "Flip Angle (0019,1260) in degree",
+"G19.Acq2.Mr.NumberOfPrescans", "Number of Prescans (0019,1270) in main loop",
+"G19.Acq2.Mr.FilterTypeRawData", 
+"Filter Type Raw Data (0019,1281): NONE | EXTERNAL | FERMI | GAUSS |HANNING",
+"G19.Acq2.Mr.FilterParameterRawData.Value1", "Filter Parameter Raw Data (0019,1282)",
+"G19.Acq2.Mr.FilterTypeImageData", 
+"Filter Type Image Data (0019,1283): NONE | NO1",
+"G19.Acq2.Mr.FilterParameterImageData.Value1", "Filter Parameter Image Data (0019,1284)",
+"G19.Acq2.Mr.FilterTypePhaseCorrection", 
+"Filter Type Phase Correction (0019,1285): NONE | EXTERNAL | FERMI | GAUSS |HANNING",
+"G19.Acq2.Mr.FilterParameterPhaseCorrection", "Filter Parameter Phase Correction (0019,1286)",
+"G19.Acq2.Mr.NumberOfSaturationRegions", "Number of Saturation Regions (0019,1290)",
+"G19.Acq2.Mr.ImageRotationAngle",
+"Image Rotation Angle (0019,1294) for readout direction in radiant",
+"G19.Acq2.Mr.CoilIdMask", "Coil ID Mask (0019,1296)",
+"G19.Acq2.Mr.CoilPosition.Sag", "Coil Position (0019,1298) vector (sag, cor, tra) in mm",
+"G21.Rel3.Mr.EpiReconstructionPhase", "EPI Reconstruction Phase (0019,12A0)",
+"G21.Rel3.Mr.EpiReconstructionSlope", "EPI Reconstruction Slope (0019,12A1)",
+
+"G19.Acq3.Ct.DistanceSourceToSourceSideCollimator",
+"Distance Source to Source Side Collimator (0019,1310) in mm",
+"G19.Acq3.Ct.DistanceSourceToDetectorSideCollimator",
+"Distance Source to Detector Side Collimator (0019,1311) in mm",
+"G19.Acq3.Ct.NumberOfPossibleChannels", "Number of Possible Channels (0019,1320)",
+"G19.Acq3.Ct.MeanChannelNumber", "Mean Channel Number (0019,1321)",
+"G19.Acq3.Ct.DetectorSpacing", "Detector Spacing (0019,1322) in minutes",
+"G19.Acq3.Ct.DetectorCenter", "Detector Center (0019,1323) in channels as real",
+"G19.Acq3.Ct.ReadingIntegrationTime", "Reading Integration Time (0019,1324) in ms",
+"G19.Acq3.Ct.DetectorAlignment", "Detector Alignment (0019,1350) in mm",
+"G19.Acq3.Ct.FocusAlignment", "Focus Alignment (0019,1360) in channel digits",
+"G19.Acq3.Ct.FocalSpotDeflectionAmplitude", 
+"Focal Spot Deflection Amplitude (0019,1365) in DMS digits",
+"G19.Acq3.Ct.FocalSpotDeflectionPhase", 
+"Focal Spot Deflection Phase (0019,1366) in DMS digits",
+"G19.Acq3.Ct.FocalSpotDeflectionOffset", 
+"Focal Spot Deflection Offset (0019,1367) in DMS digits",
+"G19.Acq3.Ct.WaterScalingFactor", "Water Scaling Factor (0019,1370)",
+"G19.Acq3.Ct.InterpolationFactor", "Interpolation Factor (0019,1371)",
+"G19.Acq3.Ct.PatientRegion", "Patient Region (0019,1380): BODY | HEAD",
+"G19.Acq3.Ct.PatientPhaseOfLife", "Patient Phase of Life (0019,1382): ADULT | CHILD",
+
+"G19.Acq3.Mr.MagneticFieldStrength", "Magnetic Field Strength (0019,1412) in T",
+"G19.Acq3.Mr.ADCVoltage", "ADC Voltage (0019,1414) in V",
+"G19.Acq3.Mr.ADCOffset", "ADC Offset (0019,1416): real value, imaginary value",
+"G19.Acq3.Mr.TransmitterAmplitude", "Transmitter Amplitude (0019,1420) in V",
+"G19.Acq3.Mr.NumberOfTransmitterAmplitudes", "Number of Transmitter Amplitudes (0019,1421)",
+"G19.Acq3.Mr.TransmitterAttenuator", "Transmitter Attenuator (0019,1422) in dB",
+"G19.Acq3.Mr.TransmitterCalibration", "Transmitter Calibration (0019,1424) in V",
+"G19.Acq3.Mr.TransmitterReference", "Transmitter Reference (0019,1426) in V",
+"G19.Acq3.Mr.ReceiverTotalGain", "Receiver Total Gain (0019,1450) in dB",
+"G19.Acq3.Mr.ReceiverAmplifierGain", "Receiver Amplifier Gain (0019,1451) in dB",
+"G19.Acq3.Mr.ReceiverPreamplifierGain", "Receiver Preamplifier Gain (0019,1452) in dB",
+"G19.Acq3.Mr.ReceiverCableAttenuation", "Receiver Cable Attenuation (0019,1454) in dB",
+"G19.Acq3.Mr.ReceiverReferenceGain", "Receiver Reference Gain (0019,1455) in dB",
+"G19.Acq3.Mr.ReceiverFilterFrequency", "Receiver Filter Frequency (0019,1456) in Hz",
+"G19.Acq3.Mr.ReconstructionScaleFactor", "Reconstruction Scale Factor (0019,1460)",
+"G19.Acq3.Mr.ReferenceScaleFactor", "Reference Scale Factor (0019,1462)",
+"G19.Acq3.Mr.PhaseGradientAmplitude", "Phase Gradient Amplitude (0019,1470) in mT/m",
+"G19.Acq3.Mr.ReadoutGradientAmplitude", "Readout Gradient Amplitude (0019,1471) in mT/m",
+"G19.Acq3.Mr.SelectionGradientAmplitude", "Selection Gradient Amplitude (0019,1472) in mT/m",
+"G19.Acq3.Mr.GradientDelayTime.X", "Gradient Delay Time (0019,1480) in usec",
+"G19.Acq3.Mr.TotalGradientDelayTime", "Total Gradient Delay Time (0019,1482) in usec",
+"G19.Acq3.Mr.SensitivityCorrectionLabel", "Sensitivity Correction Label (0019,1490)",
+"G19.Acq3.Mr.RfWatchdogMask", "RF Watchdog Mask (0019,14A0)",
+"G19.Acq3.Mr.RfPowerErrorIndicator", "RF Power Error Indicator (0019,14A2)",
+"G19.Acq3.Mr.SarWholeBody.Lim", 
+"Specific Absorption Rate (SAR) - whole body (0019,14A5) - limit in W/kg",
+"G19.Acq3.Mr.SarWholeBody.Cal", 
+"Specific Absorption Rate (SAR) - whole body (0019,14A5) - calculated value in W/kg",
+"G19.Acq3.Mr.SarWholeBody.Det", 
+"Specific Absorption Rate (SAR) - whole body (0019,14A5) - detected value in W/kg",
+"G19.Acq3.Mr.Sed.Lim", 
+"Specific Energy Dose (SED) (0019,14A6) - limit in Wmin/kg",
+"G19.Acq3.Mr.Sed.Cal", 
+"Specific Energy Dose (SED) (0019,14A6) - calculated value in Wmin/kg",
+"G19.Acq3.Mr.Sed.Det", 
+"Specific Energy Dose (SED) (0019,14A6) - detected value in Wmin/kg",
+"G19.Acq3.Mr.AdjustmentStatusMask", "Adjustment Status Mask (0019,14B0)",
+"G21.Rel3.Mr.EpiCapacity", "EPI Capacity (0019,14C1) in nF",
+"G21.Rel3.Mr.EpiInductance", "EPI Inductance (0019,14C2) in uH",
+"G21.Rel3.Mr.EpiSwitchConfigurationCode", 
+"EPI Switch Configuration Code (0019,14C3): 0 (without) | 1 (two) | 2 (four)",
+"G21.Rel3.Mr.EpiSwitchHardwareCode", 
+"EPI Switch Hardware Code (0019,14C4): 0 (no) | 1 (thyristor) | 2 (transistor)",
+"G21.Rel3.Mr.EpiSwitchDelayTime", "EPI Switch Delay Time (0019,14C5) in ns",
+
+"G19.Acq4.CM.ParameterFileName", "Parameter File Name (0019,1510)",
+"G19.Acq4.CM.SequenceFileName", "Sequence File Name (0019,1511)",
+"G19.Acq4.CM.SequenceFileOwner", "Sequence File Owner (0019,1512)",
+"G19.Acq4.CM.SequenceDescription", "Sequence Description (0019,1513)",
+"G21.Rel3.Mr.EpiFileName", "EPI File Name (0019,1514)",
+
+"G21.Rel1.CM.Target.X", "Target (0021,1011)",
+"G21.Rel1.CM.RoiMask", "ROI Mask (0021,1020)",
+"G21.Rel1.CM.FoV.Height", "Field of View (0021,1120) - height in mm",
+"G21.Rel1.CM.FoV.Width", "Field of View (0021,1120) - width in mm",
+"G21.Rel1.CM.ImageMagnificationFactor", "Image Magnification Factor (0021,1122)",
+"G21.Rel1.CM.ViewDirection",
+"View Direction (0021,1130): HEAD | FEET | AtoP | PtoA | RtoL | LtoR",
+"G21.Rel1.CM.RestDirection", "Rest Direction (0021,1132): HEAD | FEET",
+"G21.Rel1.CM.ImagePosition.Sag", "Image Position (0021,1160) vector (sag, cor, tra) in mm",
+"G21.Rel1.CM.ImageNormal.Sag", "Image Normal (0021,1161) cosinus directions (sag, cor, tra)",
+"G21.Rel1.CM.ImageDistance", "Image Distance (0021,1163) in mm",
+"G21.Rel1.CM.ImagePositioningHistoryMask", "Image Positioning History Mask (0021,1165)",
+"G21.Rel1.CM.ImageRow.Sag", "Image Row (0021,116A) cosinus directions (sag, cor, tra)",
+"G21.Rel1.CM.ImageColumn.Sag", "Image Column (0021,116B) cosinus directions (sag, cor, tra)",
+"G21.Rel1.CM.PatientOrientationSet1.Y",
+"Patient Orientation Set 1 (0021,1170): Y = up, X = left, Z = back",
+"G21.Rel1.CM.PatientOrientationSet2.Y",
+"Patient Orientation Set 2 (0021,1171): Y = down, X = right, Z = front",
+"G21.Rel1.CM.StudyName", "Study Name (0021,1180)",
+"G21.Rel1.CM.StudyType", "Study Type (0021,1182): CRE | MEA | MIP | MPR | RAW",
+
+"G21.Rel2.Ct.RotationAngle", "Rotation Angle (0021,1210) in degree",
+"G21.Rel2.Ct.StartAngle", "Start Angle (0021,1211) in degree (0.0 == 03:00)",
+"G21.Rel2.Ct.TubePosition", "Tube Position (0021,1230) in degree (0.0 == 03:00)",
+"G21.Rel2.Ct.LengthOfTopogram", "Length of Topogram (0021,1232) in mm",
+"G21.Rel2.Ct.CorrectionFactor", "Correction Factor (0021,1234) for topogram in x-direction",
+"G21.Rel2.Ct.MaximumTablePosition", "Maximum Table Position (0021,1236) in mm",
+"G21.Rel2.Ct.TableMoveDirectionCode", "Tabel Move Direction Code (0019,1240): -1 (into) | 1 (out)",
+"G21.Rel2.Ct.VoiStartRow", "VOI Start Row (0021,1245)",
+"G21.Rel2.Ct.VoiStopRow", "VOI Stop Row (0021,1246)",
+"G21.Rel2.Ct.VoiStartColumn", "VOI Start Column (0021,1247)",
+"G21.Rel2.Ct.VoiStopColumn", "VOI Stop Column (0021,1248)",
+"G21.Rel2.Ct.VoiStartSlice", "VOI Start Slice (0021,1249)",
+"G21.Rel2.Ct.VoiStopSlice", "VOI Stop Slice (0021,124A)",
+"G21.Rel2.Ct.VectorStartRow", "Vector Start Row(0021,1250)",
+"G21.Rel2.Ct.VectorRowStep", "Vector Row Step(0021,1251)",
+"G21.Rel2.Ct.VectorStartColumn", "Vector Start Column(0021,1252)",
+"G21.Rel2.Ct.VectorColumnStep", "Vector Column Step(0021,1253)",
+"G21.Rel2.Ct.RangeTypeCode", "Range Type Code (0021,1260): 0 (sector) | 1 (parallel)",
+"G21.Rel2.Ct.ReferenceTypeCode", 
+"Reference Type Code (0021,1262): 0 (topo) | 1 (tra) | 2 (sag) | 3 (cor)",
+"G21.Rel2.Ct.ObjectOrientation.Phi", 
+"Object Orientation (0021,1270) vector (phi, theta, 1.0) in degree",
+"G21.Rel2.Ct.LightOrientation.Phi", 
+"Light Orientation (0021,1272) vector (phi, theta, 1.0) in degree",
+"G21.Rel2.Ct.LightBrightness", "Light Brightness (0021,1275)",
+"G21.Rel2.Ct.LightContrast", "Light Contrast (0021,1276)",
+"G21.Rel2.Ct.OverlayThreshold.LowerBoundary", 
+"Overlay Threshold (0021,127A) boundaries (lower, upper)",
+"G21.Rel2.Ct.SurfaceThreshold.LowerBoundary", 
+"Surface Threshold (0021,127B) boundaries (lower, upper)",
+"G21.Rel2.Ct.GreyScaleThreshold.LowerBoundary", 
+"Grey Scale Threshold (0021,127C) boundaries (lower, upper)",
+
+
+"G21.Rel2.Mr.PhaseCorRowSeq", "Phase Corrections Rows (0021,1320) of actual sequence",
+"G21.Rel2.Mr.PhaseCorColSeq", "Phase Corrections Columns (0021,1321) of actual sequence",
+"G21.Rel2.Mr.PhaseCorRowRec", "Phase Corrrections Rows (0021,1322) of actual reconstruction",
+"G21.Rel2.Mr.PhaseCorColRec", "Phase Corrrections Columns (0021,1324) of actual reconstruction",
+"G21.Rel2.Mr.NumberOf3DRawPartNom", "nominal Number of 3D Raw Partitions (0021,1330)",
+"G21.Rel2.Mr.NumberOf3DRawPartCur", "current Number of 3D Raw Partitions (0021,1331)",
+"G21.Rel2.Mr.NumberOf3DImaPart", "Number of 3D Image Partitions (0021,1334)",
+"G21.Rel2.Mr.Actual3DImaPartNumber", "Actual 3D Image Partitions Number (0021,1336)",
+"G21.Rel2.Mr.SlabThickness", "Slab Thickness (0021,1339) in mm",
+"G21.Rel2.Mr.NumberOfSlicesNom", "nominal Number of Slices (0021,1340)",
+"G21.Rel2.Mr.NumberOfSlicesCur", "current Number of Slices (0021,1341)",
+"G21.Rel2.Mr.CurrentSliceNumber", "Current Slice Number (0021,1342)",
+"G21.Rel2.Mr.CurrentGroupNumber", "Current Group Number (0021,1343)",
+"G21.Rel2.Mr.CurrentSliceDistanceFactor", "Current Slice Distance Factor (0021,1344)",
+"G21.Rel2.Mr.MipStartRow", "MIP Start Row (0021,1345)",
+"G21.Rel2.Mr.MipStopRow", "MIP Stop Row (0021,1346)",
+"G21.Rel2.Mr.MipStartColumn", "MIP Start Column (0021,1347)",
+"G21.Rel2.Mr.MipStopColumn", "MIP Stop Column (0021,1348)",
+"G21.Rel2.Mr.MipStartSlice", "MIP Start Slice (0021,1349)",
+"G21.Rel2.Mr.MipStopSlice", "MIP StopSlice (0021,134A)",
+"G21.Rel2.Mr.OrderOfSlices", 
+"Order of Slices (0021,134F): NONE | ASCENDING | DECREASING | FREE | INTERLEAVED",
+"G21.Rel2.Mr.SignalMask", "Signal Mask (0021,1350)",
+"G21.Rel2.Mr.DelayAfterTrigger", "Delay After Trigger (0021,1352) in msec",
+"G21.Rel2.Mr.RRInterval", "RR Interval (0021,1353) in msec",
+"G21.Rel2.Mr.NumberOfTriggerPulses", "Number of Trigger Pulses (0021,1354)",
+"G21.Rel2.Mr.RepetitionTime", "effective Repetition Time (0021,1356) in msec",
+"G21.Rel2.Mr.GatePhase", "Gate Phase (0021,1357): EXPIRATION | INSPIRATION",
+"G21.Rel2.Mr.GateThreshold", "Gate Threshold (0021,1358) in %",
+"G21.Rel2.Mr.GateRatio", "Gate Ratio (0021,1359) in %",
+"G21.Rel2.Mr.NumberOfInterpolatedImages", "Number of Interpolated Images (0021,1360)",
+"G21.Rel2.Mr.NumberOfEchoes", "total Number of Echoes (0021,1370)",
+"G21.Rel2.Mr.SecondEchoTime", "second Echo Time (0021,1372) in msec",
+"G21.Rel2.Mr.SecondRepetitionTime", "second Repetition Time (0021,1373) in msec",
+"G21.Rel2.Mr.CardiacCode", "Cardiac Code (0021,1380)",
+
+"G21.Rel3.Ct.CreationMask", "Creation Mask - Service (0021,2210)",
+"G21.Rel3.Ct.EvaluationMask", "Evaluation Mask - Service (0021,2220)",
+"G21.Rel3.Ct.ExtendedProcessingMask", "Extended Processing Mask (0021,2230)",
+
+"G29.Pre.WindowStyle",
+"Window Style (0029,1110): NONE | DOUBLE | HIGH | STD 1 | STD 2",
+"G29.Pre.PixelQualityCode.Min",
+"Pixel Quality Code (0029,1120): NONE | ESTIMATED | EXACT",
+"G29.Pre.PixelQualityValue.Min", "Pixel Quality Value (0029,1122)",
+"G29.Pre.ArchiveCode", "Archive Code (0029,1150): NOT | MARKED | DONE",
+"G29.Pre.ExposureCode", "Exposure Code (0029,1151): NOT | MARKED | DONE",
+"G29.Pre.SortCode", 
+"Sort Code (0029,1152): 0 (CH) | 1 (AN) | 2 (TE) | 3 (TR) | 4 (TD) | 5 (CA)",
+"G29.Pre.Splash", "Splash (0029,1160)",
+
+"G51.Txt_buf", "Image Text (0051,1010)",
+"Gap.Fill_buf", "reserved: gap to fill Internal Header to kByte border",
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_head_type.h
@@ -0,0 +1,207 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_head_type.h
+
+   Description: The header file defines the data set basic groups as unions for
+                internal use (internal header).
+                Unions are used to overlay a buffer and the group structure for more flexi-
+                bility and compatibility. To expand a group the new item must only be
+                defined at the structure end in header file "ds_head_acr_groups_types.h" or
+                "ds_head_shadow_groups_types.h".
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_HEAD_TYPE
+#define DS_HEAD_TYPE
+
+typedef union group_0008_tag
+{
+  char Ide_buf[LENGTH_GROUP_0008];			   /* fill-in */
+  acr_identifying_t Ide;				   /* work area */
+} group_0008_t;
+
+
+
+typedef union group_0009_tag
+{
+  char Ide_buf[LENGTH_GROUP_0009];			   /* fill-in */
+  shadow_identifying_t Ide;				   /* work area */
+} group_0009_t;
+
+
+
+typedef union group_0010_tag
+{
+  char Pat_buf[LENGTH_GROUP_0010];			   /* fill-in */
+  acr_patient_t Pat;					   /* work area */
+} group_0010_t;
+
+
+
+typedef union group_0011_tag
+{
+  char Pat_buf[LENGTH_GROUP_0011];			   /* fill-in */
+  shadow_patient_t Pat;					   /* work area */
+} group_0011_t;
+
+
+
+typedef union group_0013_tag
+{
+  char PatMod_buf[LENGTH_GROUP_0013];			   /* fill-in */
+  shadow_patient_modify_t PatMod;			   /* work area */
+} group_0013_t;
+
+
+
+typedef union group_0018_tag
+{
+  char Acq_buf[LENGTH_GROUP_0018];			   /* fill-in */
+  acr_acquisition_t Acq;				   /* work area */
+} group_0018_t;
+
+
+
+typedef union group_0019_part1_tag
+{
+  char Acq1_buf[LENGTH_GROUP_0019_PART1];		   /* fill-in */
+  shadow_acquisition_cms_t CM;				   /* work area */
+} group_0019_part1_t;
+
+typedef union group_0019_part2_tag
+{
+  char Acq2_buf[LENGTH_GROUP_0019_PART2];		   /* fill-in */
+  shadow_acquisition_ct_t Ct;				   /* CT common work area */
+  shadow_acquisition_mr_t Mr;				   /* MR common work area */
+} group_0019_part2_t;
+
+typedef union group_0019_part3_tag
+{
+  char Acq3_buf[LENGTH_GROUP_0019_PART3];		   /* fill-in */
+  shadow_acquisition_ct_conf_t Ct;			   /* CT configuration work area */
+  shadow_acquisition_mr_conf_t Mr;			   /* MR configuration work area */
+} group_0019_part3_t;
+
+typedef union group_0019_part4_tag
+{
+  char Acq4_buf[LENGTH_GROUP_0019_PART4];		   /* fill-in */
+  shadow_acquisition_acq_t CM;				   /* work area */
+} group_0019_part4_t;
+
+typedef struct group_0019_tag
+{
+  group_0019_part1_t Acq1;				   /* CMS subgroup */
+  group_0019_part2_t Acq2;				   /* common subgroup */
+  group_0019_part3_t Acq3;				   /* config. and adjust subgroup */
+  group_0019_part4_t Acq4;				   /* acquisition subgroup */
+} group_0019_t;
+
+
+
+typedef union group_0020_tag
+{
+  char Rel_buf[LENGTH_GROUP_0020];			   /* fill-in */
+  acr_relationship_t Rel;				   /* work area */
+} group_0020_t;
+
+
+
+typedef union group_0021_part1_tag
+{
+  char Rel1_buf[LENGTH_GROUP_0021_PART1];		   /* fill-in */
+  shadow_relationship_med_cms_t CM;			   /* work area */
+} group_0021_part1_t;
+
+typedef union group_0021_part2_tag
+{
+  char Rel2_buf[LENGTH_GROUP_0021_PART2];		   /* fill-in */
+  shadow_relationship_ct_t Ct;				   /* CT common work area */
+  shadow_relationship_mr_t Mr;				   /* MR common work area */
+} group_0021_part2_t;
+
+typedef union group_0021_part3_tag
+{
+  char Rel2_buf[LENGTH_GROUP_0021_PART3];		   /* fill-in */
+  shadow_relationship_ct_spe_t Ct;			   /* CT special work area */
+  shadow_relationship_mr_spe_t Mr;			   /* MR special work area */
+} group_0021_part3_t;
+
+typedef struct group_0021_tag
+{
+  group_0021_part1_t Rel1;				   /* CMS subgroup */
+  group_0021_part2_t Rel2;				   /* common subgroup */
+  group_0021_part3_t Rel3;				   /* special subgroup */
+} group_0021_t;
+
+
+
+typedef union group_0028_tag
+{
+  char Pre_buf[LENGTH_GROUP_0028];			   /* fill-in */
+  acr_presentation_t Pre;				   /* work area */
+} group_0028_t;
+
+
+
+typedef union group_0029_tag
+{
+  char Pre_buf[LENGTH_GROUP_0029];			   /* fill-in */
+  shadow_presentation_t Pre;				   /* work area */
+} group_0029_t;
+
+
+
+typedef union group_0051_tag
+{
+  char Txt_buf[LENGTH_GROUP_0051];			   /* fill-in */
+  image_text_t Txt;					   /* work area */
+} group_0051_t;
+
+
+
+typedef union fill_to_border_tag
+{
+  char Fill_buf[LENGTH_TO_FILL_K_BORDER];		   /* fill-in */
+} fill_to_border_t;
+
+
+
+
+/*******************/
+/* internal header */
+/*******************/
+
+typedef struct header_tag
+{
+  group_0008_t G08;					   /* Identifying Information */
+  group_0009_t G09;
+  group_0010_t G10;					   /* Patient Information */
+  group_0011_t G11;
+  group_0013_t G13;                                        /* Patient Modify Information */
+  group_0018_t G18;					   /* Acquisition Information */
+  group_0019_t G19;
+  group_0020_t G20;					   /* Relationship Information */
+  group_0021_t G21;
+  group_0028_t G28;					   /* Image Presentation Information */
+  group_0029_t G29;
+  group_0051_t G51;					   /* Image Text */
+} header_t;
+
+#endif
+
+
+/*==========================================================================================*/
+
+#ifdef DS_STC_TOOL
+
+char *_STC_HELP[] =
+{
+#include <ds_head_acr_groups_types.h>
+#include <ds_head_shadow_groups_types.h>
+  0
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_include_files.h
@@ -0,0 +1,42 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_include_files.h
+
+   Description: The header file include all necessary header files for data set library
+                functions. The "#ifndef XXX" - "#endif" construct in the different header
+                files avoid a multiple type, parameter, constant or macro definition.
+                Don't change the order because the header files are implemented as a
+                hierachy and so not indepent of calling order.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_INCLUDE_FILES
+#define DS_INCLUDE_FILES
+
+
+/* PRECOMILER: sepecial include files */
+#include <STC_Common_Status.h>
+
+
+/* PRECOMILER: data set library include files */
+#include <ds_head_constants.h>
+#include <ds_transformation.h>
+
+#include <ds_messages.h>
+
+#include <ds_date.h>
+
+#include <ds_head_basic_types.h>
+#include <ds_head_acr_groups_types.h>
+#include <ds_head_shadow_groups_types.h>
+#include <ds_head_image_text_type.h>
+#include <ds_head_type.h>
+
+#include <ds_transformation_control.h>
+
+#include <ds_functions.h>
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_messages.h
@@ -0,0 +1,322 @@
+/*---------------------------------------------------
+ *
+ *	include	ds_messages.h
+ *
+ *---------------------------------------------------
+ */
+#define DS_RET_MORE_PARAMETER_AVAILABLE 6815752		/* (0x00680008) */
+#define DS_RET_MORE_PARAMETER_AVAILABLE_E 6815760		/* (0x00680010) */
+#define DS_RET_MORE_PARAMETER_AVAILABLE_U 6815768		/* (0x00680018) */
+#define DS_RET_MORE_PARAMETER_AVAILABLE_D 6815776		/* (0x00680020) */
+#define DS_RET_MORE_VALUES_AVAILABLE 6815784		/* (0x00680028) */
+#define DS_RET_MORE_VALUES_AVAILABLE_E 6815792		/* (0x00680030) */
+#define DS_RET_MORE_VALUES_AVAILABLE_U 6815800		/* (0x00680038) */
+#define DS_RET_MORE_VALUES_AVAILABLE_D 6815808		/* (0x00680040) */
+#define DS_RET_UNDEFINED 6815816		/* (0x00680048) */
+#define DS_RET_UNDEFINED_E 6815824		/* (0x00680050) */
+#define DS_RET_UNDEFINED_U 6815832		/* (0x00680058) */
+#define DS_RET_UNDEFINED_D 6815840		/* (0x00680060) */
+#define DS_RET_WITH_WARNING 6815848		/* (0x00680068) */
+#define DS_RET_WITH_WARNING_E 6815856		/* (0x00680070) */
+#define DS_RET_WITH_WARNING_U 6815864		/* (0x00680078) */
+#define DS_RET_WITH_WARNING_D 6815872		/* (0x00680080) */
+#define DS_RET_NORMAL 6817345		/* (0x00680641) */
+#define DS_RET_NORMAL_E 6817353		/* (0x00680649) */
+#define DS_RET_NORMAL_U 6817361		/* (0x00680651) */
+#define DS_RET_NORMAL_D 6817369		/* (0x00680659) */
+#define DS_RET_BAD_DATES 6818946		/* (0x00680c82) */
+#define DS_RET_BAD_DATES_E 6818954		/* (0x00680c8a) */
+#define DS_RET_BAD_DATES_U 6818962		/* (0x00680c92) */
+#define DS_RET_BAD_DATES_D 6818970		/* (0x00680c9a) */
+#define DS_RET_BAD_NUMBER 6818978		/* (0x00680ca2) */
+#define DS_RET_BAD_NUMBER_E 6818986		/* (0x00680caa) */
+#define DS_RET_BAD_NUMBER_U 6818994		/* (0x00680cb2) */
+#define DS_RET_BAD_NUMBER_D 6819002		/* (0x00680cba) */
+#define DS_RET_BUILD_UP_FAILED 6819010		/* (0x00680cc2) */
+#define DS_RET_BUILD_UP_FAILED_E 6819018		/* (0x00680cca) */
+#define DS_RET_BUILD_UP_FAILED_U 6819026		/* (0x00680cd2) */
+#define DS_RET_BUILD_UP_FAILED_D 6819034		/* (0x00680cda) */
+#define DS_RET_CMS_TO_NEMA_NOT_POSSIBLE 6819042		/* (0x00680ce2) */
+#define DS_RET_CMS_TO_NEMA_NOT_POSSIBLE_E 6819050		/* (0x00680cea) */
+#define DS_RET_CMS_TO_NEMA_NOT_POSSIBLE_U 6819058		/* (0x00680cf2) */
+#define DS_RET_CMS_TO_NEMA_NOT_POSSIBLE_D 6819066		/* (0x00680cfa) */
+#define DS_RET_CMS_TO_SOM0_NOT_POSSIBLE 6819074		/* (0x00680d02) */
+#define DS_RET_CMS_TO_SOM0_NOT_POSSIBLE_E 6819082		/* (0x00680d0a) */
+#define DS_RET_CMS_TO_SOM0_NOT_POSSIBLE_U 6819090		/* (0x00680d12) */
+#define DS_RET_CMS_TO_SOM0_NOT_POSSIBLE_D 6819098		/* (0x00680d1a) */
+#define DS_RET_DAY_OUT_OF_RANGE 6819106		/* (0x00680d22) */
+#define DS_RET_DAY_OUT_OF_RANGE_E 6819114		/* (0x00680d2a) */
+#define DS_RET_DAY_OUT_OF_RANGE_U 6819122		/* (0x00680d32) */
+#define DS_RET_DAY_OUT_OF_RANGE_D 6819130		/* (0x00680d3a) */
+#define DS_RET_FRACTION_OUT_OF_RANGE 6819138		/* (0x00680d42) */
+#define DS_RET_FRACTION_OUT_OF_RANGE_E 6819146		/* (0x00680d4a) */
+#define DS_RET_FRACTION_OUT_OF_RANGE_U 6819154		/* (0x00680d52) */
+#define DS_RET_FRACTION_OUT_OF_RANGE_D 6819162		/* (0x00680d5a) */
+#define DS_RET_HOUR_OUT_OF_RANGE 6819170		/* (0x00680d62) */
+#define DS_RET_HOUR_OUT_OF_RANGE_E 6819178		/* (0x00680d6a) */
+#define DS_RET_HOUR_OUT_OF_RANGE_U 6819186		/* (0x00680d72) */
+#define DS_RET_HOUR_OUT_OF_RANGE_D 6819194		/* (0x00680d7a) */
+#define DS_RET_INVALID_IMAGE_AXIS 6819202		/* (0x00680d82) */
+#define DS_RET_INVALID_IMAGE_AXIS_E 6819210		/* (0x00680d8a) */
+#define DS_RET_INVALID_IMAGE_AXIS_U 6819218		/* (0x00680d92) */
+#define DS_RET_INVALID_IMAGE_AXIS_D 6819226		/* (0x00680d9a) */
+#define DS_RET_INVALID_IMAGE_GRAPHICS 6819234		/* (0x00680da2) */
+#define DS_RET_INVALID_IMAGE_GRAPHICS_E 6819242		/* (0x00680daa) */
+#define DS_RET_INVALID_IMAGE_GRAPHICS_U 6819250		/* (0x00680db2) */
+#define DS_RET_INVALID_IMAGE_GRAPHICS_D 6819258		/* (0x00680dba) */
+#define DS_RET_INVALID_IMAGE_PLACE 6819266		/* (0x00680dc2) */
+#define DS_RET_INVALID_IMAGE_PLACE_E 6819274		/* (0x00680dca) */
+#define DS_RET_INVALID_IMAGE_PLACE_U 6819282		/* (0x00680dd2) */
+#define DS_RET_INVALID_IMAGE_PLACE_D 6819290		/* (0x00680dda) */
+#define DS_RET_INVALID_IMAGE_TEXT 6819298		/* (0x00680de2) */
+#define DS_RET_INVALID_IMAGE_TEXT_E 6819306		/* (0x00680dea) */
+#define DS_RET_INVALID_IMAGE_TEXT_U 6819314		/* (0x00680df2) */
+#define DS_RET_INVALID_IMAGE_TEXT_D 6819322		/* (0x00680dfa) */
+#define DS_RET_INVALID_INTERFACE 6819330		/* (0x00680e02) */
+#define DS_RET_INVALID_INTERFACE_E 6819338		/* (0x00680e0a) */
+#define DS_RET_INVALID_INTERFACE_U 6819346		/* (0x00680e12) */
+#define DS_RET_INVALID__INTERFACE_D 6819354		/* (0x00680e1a) */
+#define DS_RET_INVALID_MATRIX 6819362		/* (0x00680e22) */
+#define DS_RET_INVALID_MATRIX_E 6819370		/* (0x00680e2a) */
+#define DS_RET_INVALID_MATRIX_U 6819378		/* (0x00680e32) */
+#define DS_RET_INVALID_MATRIX_D 6819386		/* (0x00680e3a) */
+#define DS_RET_INVALID_VIEW_DIRECTION 6819394		/* (0x00680e42) */
+#define DS_RET_INVALID_VIEW_DIRECTION_E 6819402		/* (0x00680e4a) */
+#define DS_RET_INVALID_VIEW_DIRECTION_U 6819410		/* (0x00680e52) */
+#define DS_RET_INVALID_VIEW_DIRECTION_D 6819418		/* (0x00680e5a) */
+#define DS_RET_ITEM_NOT_FOUND 6819426		/* (0x00680e62) */
+#define DS_RET_ITEM_NOT_FOUND_E 6819434		/* (0x00680e6a) */
+#define DS_RET_ITEM_NOT_FOUND_U 6819442		/* (0x00680e72) */
+#define DS_RET_ITEM_NOT_FOUND_D 6819450		/* (0x00680e7a) */
+#define DS_RET_LENGTH_NOT_EVEN 6819458		/* (0x00680e82) */
+#define DS_RET_LENGTH_NOT_EVEN_E 6819466		/* (0x00680e8a) */
+#define DS_RET_LENGTH_NOT_EVEN_U 6819474		/* (0x00680e92) */
+#define DS_RET_LENGTH_NOT_EVEN_D 6819482		/* (0x00680e9a) */
+#define DS_RET_LENGTH_OUT_OF_RANGE 6819490		/* (0x00680ea2) */
+#define DS_RET_LENGTH_OUT_OF_RANGE_E 6819498		/* (0x00680eaa) */
+#define DS_RET_LENGTH_OUT_OF_RANGE_U 6819506		/* (0x00680eb2) */
+#define DS_RET_LENGTH_OUT_OF_RANGE_D 6819514		/* (0x00680eba) */
+#define DS_RET_LENGTH_TO_LESS 6819522		/* (0x00680ec2) */
+#define DS_RET_LENGTH_TO_LESS_E 6819530		/* (0x00680eca) */
+#define DS_RET_LENGTH_TO_LESS_U 6819538		/* (0x00680ed2) */
+#define DS_RET_LENGTH_TO_LESS_D 6819546		/* (0x00680eda) */
+#define DS_RET_MINUTE_OUT_OF_RANGE 6819554		/* (0x00680ee2) */
+#define DS_RET_MINUTE_OUT_OF_RANGE_E 6819562		/* (0x00680eea) */
+#define DS_RET_MINUTE_OUT_OF_RANGE_U 6819570		/* (0x00680ef2) */
+#define DS_RET_MINUTE_OUT_OF_RANGE_D 6819578		/* (0x00680efa) */
+#define DS_RET_MISSING_INFORMATION 6819586		/* (0x00680f02) */
+#define DS_RET_MISSING_INFORMATION_E 6819594		/* (0x00680f0a) */
+#define DS_RET_MISSING_INFORMATION_U 6819602		/* (0x00680f12) */
+#define DS_RET_MISSING_INFORMATION_D 6819610		/* (0x00680f1a) */
+#define DS_RET_MONTH_OUT_OF_RANGE 6819618		/* (0x00680f22) */
+#define DS_RET_MONTH_OUT_OF_RANGE_E 6819626		/* (0x00680f2a) */
+#define DS_RET_MONTH_OUT_OF_RANGE_U 6819634		/* (0x00680f32) */
+#define DS_RET_MONTH_OUT_OF_RANGE_D 6819642		/* (0x00680f3a) */
+#define DS_RET_NIL_VECTOR 6819650		/* (0x00680f42) */
+#define DS_RET_NIL_VECTOR_E 6819658		/* (0x00680f4a) */
+#define DS_RET_NIL_VECTOR_U 6819666		/* (0x00680f52) */
+#define DS_RET_NIL_VECTOR_D 6819674		/* (0x00680f5a) */
+#define DS_RET_NO_VALID_DATE 6819682		/* (0x00680f62) */
+#define DS_RET_NO_VALID_DATE_E 6819690		/* (0x00680f6a) */
+#define DS_RET_NO_VALID_DATE_U 6819698		/* (0x00680f72) */
+#define DS_RET_NO_VALID_DATE_D 6819706		/* (0x00680f7a) */
+#define DS_RET_NO_VALID_ITEM_VALUE 6819714		/* (0x00680f82) */
+#define DS_RET_NO_VALID_ITEM_VALUE_E 6819722		/* (0x00680f8a) */
+#define DS_RET_NO_VALID_ITEM_VALUE_U 6819730		/* (0x00680f92) */
+#define DS_RET_NO_VALID_ITEM_VALUE_D 6819738		/* (0x00680f9a) */
+#define DS_RET_NO_VALID_TIME 6819746		/* (0x00680fa2) */
+#define DS_RET_NO_VALID_TIME_E 6819754		/* (0x00680faa) */
+#define DS_RET_NO_VALID_TIME_U 6819762		/* (0x00680fb2) */
+#define DS_RET_NO_VALID_TIME_D 6819770		/* (0x00680fba) */
+#define DS_RET_NUMBER_NOT_EVEN 6819778		/* (0x00680fc2) */
+#define DS_RET_NUMBER_NOT_EVEN_E 6819786		/* (0x00680fca) */
+#define DS_RET_NUMBER_NOT_EVEN_U 6819794		/* (0x00680fd2) */
+#define DS_RET_NUMBER_NOT_EVEN_D 6819802		/* (0x00680fda) */
+#define DS_RET_NUMBER_OUT_OF_RANGE 6819810		/* (0x00680fe2) */
+#define DS_RET_NUMBER_OUT_OF_RANGE_E 6819818		/* (0x00680fea) */
+#define DS_RET_NUMBER_OUT_OF_RANGE_U 6819826		/* (0x00680ff2) */
+#define DS_RET_NUMBER_OUT_OF_RANGE_D 6819834		/* (0x00680ffa) */
+#define DS_RET_OUT_OF_FORMAT 6819842		/* (0x00681002) */
+#define DS_RET_OUT_OF_FORMAT_E 6819850		/* (0x0068100a) */
+#define DS_RET_OUT_OF_FORMAT_U 6819858		/* (0x00681012) */
+#define DS_RET_OUT_OF_FORMAT_D 6819866		/* (0x0068101a) */
+#define DS_RET_SECOND_OUT_OF_RANGE 6819874		/* (0x00681022) */
+#define DS_RET_SECOND_OUT_OF_RANGE_E 6819882		/* (0x0068102a) */
+#define DS_RET_SECOND_OUT_OF_RANGE_U 6819890		/* (0x00681032) */
+#define DS_RET_SECOND_OUT_OF_RANGE_D 6819898		/* (0x0068103a) */
+#define DS_RET_SEPARATE_FAILED 6819906		/* (0x00681042) */
+#define DS_RET_SEPARATE_FAILED_E 6819914		/* (0x0068104a) */
+#define DS_RET_SEPARATE_FAILED_U 6819922		/* (0x00681052) */
+#define DS_RET_SEPARATE_FAILED_D 6819930		/* (0x0068105a) */
+#define DS_RET_STRING_TO_LONG 6819938		/* (0x00681062) */
+#define DS_RET_STRING_TO_LONG_E 6819946		/* (0x0068106a) */
+#define DS_RET_STRING_TO_LONG_U 6819954		/* (0x00681072) */
+#define DS_RET_STRING_TO_LONG_D 6819962		/* (0x0068107a) */
+#define DS_RET_SYSTEM_ERROR 6819970		/* (0x00681082) */
+#define DS_RET_SYSTEM_ERROR_E 6819978		/* (0x0068108a) */
+#define DS_RET_SYSTEM_ERROR_U 6819986		/* (0x00681092) */
+#define DS_RET_SYSTEM_ERROR_D 6819994		/* (0x0068109a) */
+#define DS_RET_UNKNOWN_OVERLAY 6820002		/* (0x006810a2) */
+#define DS_RET_UNKNOWN_OVERLAY_E 6820010		/* (0x006810aa) */
+#define DS_RET_UNKNOWN_OVERLAY_U 6820018		/* (0x006810b2) */
+#define DS_RET_UNKNOWN_OVERLAY_D 6820026		/* (0x006810ba) */
+#define DS_RET_UNKNOWN_UPDATE_CODE 6820034		/* (0x006810c2) */
+#define DS_RET_UNKNOWN_UPDATE_CODE_E 6820042		/* (0x006810ca) */
+#define DS_RET_UNKNOWN_UPDATE_CODE_U 6820050		/* (0x006810d2) */
+#define DS_RET_UNKNOWN_UPDATE_CODE_D 6820058		/* (0x006810da) */
+#define DS_RET_UNKNOWN_HEADER 6820066		/* (0x006810e2) */
+#define DS_RET_UNKNOWN_HEADER_E 6820074		/* (0x006810ea) */
+#define DS_RET_UNKNOWN_HEADER_U 6820082		/* (0x006810f2) */
+#define DS_RET_UNKNOWN_HEADER_D 6820090		/* (0x006810fa) */
+#define DS_RET_UNKNOWN_UPDATE_MODE 6820098		/* (0x00681102) */
+#define DS_RET_UNKNOWN_UPDATE_MODE_E 6820106		/* (0x0068110a) */
+#define DS_RET_UNKNOWN_UPDATE_MODE_U 6820114		/* (0x00681112) */
+#define DS_RET_UNKNOWN_UPDATE_MODE_D 6820122		/* (0x0068111a) */
+#define DS_RET_UNKNOWN_VALUE_MODE 6820130		/* (0x00681122) */
+#define DS_RET_UNKNOWN_VALUE_MODE_E 6820138		/* (0x0068112a) */
+#define DS_RET_UNKNOWN_VALUE_MODE_U 6820146		/* (0x00681132) */
+#define DS_RET_UNKNOWN_VALUE_MODE_D 6820154		/* (0x0068113a) */
+#define DS_RET_VECTOR_NOT_DEFINED 6820162		/* (0x00681142) */
+#define DS_RET_VECTOR_NOT_DEFINED_E 6820170		/* (0x0068114a) */
+#define DS_RET_VECTOR_NOT_DEFINED_U 6820178		/* (0x00681152) */
+#define DS_RET_VECTOR_NOT_DEFINED_D 6820186		/* (0x0068115a) */
+#define DS_RET_VECTOR_NOT_NORMALIZED 6820194		/* (0x00681162) */
+#define DS_RET_VECTOR_NOT_NORMALIZED_E 6820202		/* (0x0068116a) */
+#define DS_RET_VECTOR_NOT_NORMALIZED_U 6820210		/* (0x00681172) */
+#define DS_RET_VECTOR_NOT_NORMALIZED_D 6820218		/* (0x0068117a) */
+#define DS_RET_YEAR_OUT_OF_RANGE 6820226		/* (0x00681182) */
+#define DS_RET_YEAR_OUT_OF_RANGE_E 6820234		/* (0x0068118a) */
+#define DS_RET_YEAR_OUT_OF_RANGE_U 6820242		/* (0x00681192) */
+#define DS_RET_YEAR_OUT_OF_RANGE_D 6820250		/* (0x0068119a) */
+#define DS_RET_FUNCTION_NOT_IMPLEMENTED 6820547		/* (0x006812c3) */
+#define DS_RET_FUNCTION_NOT_IMPLEMENTED_E 6820555		/* (0x006812cb) */
+#define DS_RET_FUNCTION_NOT_IMPLEMENTED_U 6820563		/* (0x006812d3) */
+#define DS_RET_FUNCTION_NOT_IMPLEMENTED_D 6820571		/* (0x006812db) */
+#define DS_RET_ITEM_FOUND 6820579		/* (0x006812e3) */
+#define DS_RET_ITEM_FOUND_E 6820587		/* (0x006812eb) */
+#define DS_RET_ITEM_FOUND_U 6820595		/* (0x006812f3) */
+#define DS_RET_ITEM_FOUND_D 6820603		/* (0x006812fb) */
+#define DS_RET_NO_GRAPHICS_AVAILABLE 6820611		/* (0x00681303) */
+#define DS_RET_NO_GRAPHICS_AVAILABLE_E 6820619		/* (0x0068130b) */
+#define DS_RET_NO_GRAPHICS_AVAILABLE_U 6820627		/* (0x00681313) */
+#define DS_RET_NO_GRAPHICS_AVAILABLE_D 6820635		/* (0x0068131b) */
+#define DS_RET_STRING_NOT_FOUND 6820643		/* (0x00681323) */
+#define DS_RET_STRING_NOT_FOUND_E 6820651		/* (0x0068132b) */
+#define DS_RET_STRING_NOT_FOUND_U 6820659		/* (0x00681333) */
+#define DS_RET_STRING_NOT_FOUND_D 6820667		/* (0x0068133b) */
+#define DS_RET_STRINGS_ARE_EQUAL 6820675		/* (0x00681343) */
+#define DS_RET_STRINGS_ARE_EQUAL_E 6820683		/* (0x0068134b) */
+#define DS_RET_STRINGS_ARE_EQUAL_U 6820691		/* (0x00681353) */
+#define DS_RET_STRINGS_ARE_EQUAL_D 6820699		/* (0x0068135b) */
+#define DS_RET_DATA_SET_OUT_OF_ORDER 6822148		/* (0x00681904) */
+#define DS_RET_DATA_SET_OUT_OF_ORDER_E 6822156		/* (0x0068190c) */
+#define DS_RET_DATA_SET_OUT_OF_ORDER_U 6822164		/* (0x00681914) */
+#define DS_RET_DATA_SET_OUT_OF_ORDER_D 6822172		/* (0x0068191c) */
+#define DS_RET_END_OF_DATA_SET_FOUND 6822180		/* (0x00681924) */
+#define DS_RET_END_OF_DATA_SET_FOUND_E 6822188		/* (0x0068192c) */
+#define DS_RET_END_OF_DATA_SET_FOUND_U 6822196		/* (0x00681934) */
+#define DS_RET_END_OF_DATA_SET_FOUND_D 6822204		/* (0x0068193c) */
+#define DS_RET_FIRST_ELEMENT_INVALID 6822212		/* (0x00681944) */
+#define DS_RET_FIRST_ELEMENT_INVALID_E 6822220		/* (0x0068194c) */
+#define DS_RET_FIRST_ELEMENT_INVALID_U 6822228		/* (0x00681954) */
+#define DS_RET_FIRST_ELEMENT_INVALID_D 6822236		/* (0x0068195c) */
+#define DS_RET_UNKNOWN_COMPRESSION_CODE 6822244		/* (0x00681964) */
+#define DS_RET_UNKNOWN_COMPRESSION_CODE_E 6822252		/* (0x0068196c) */
+#define DS_RET_UNKNOWN_COMPRESSION_CODE_U 6822260		/* (0x00681974) */
+#define DS_RET_UNKNOWN_COMPRESSION_CODE_D 6822268		/* (0x0068197c) */
+#define DS_RET_UNKNOWN_DATA_SET 6822276		/* (0x00681984) */
+#define DS_RET_UNKNOWN_DATA_SET_E 6822284		/* (0x0068198c) */
+#define DS_RET_UNKNOWN_DATA_SET_U 6822292		/* (0x00681994) */
+#define DS_RET_UNKNOWN_DATA_SET_D 6822300		/* (0x0068199c) */
+#define DS_RET_UNKNOWN_DATA_SET_OWNER 6822308		/* (0x006819a4) */
+#define DS_RET_UNKNOWN_DATA_SET_OWNER_E 6822316		/* (0x006819ac) */
+#define DS_RET_UNKNOWN_DATA_SET_OWNER_U 6822324		/* (0x006819b4) */
+#define DS_RET_UNKNOWN_DATA_SET_OWNER_D 6822332		/* (0x006819bc) */
+#define DS_RET_UNKNOWN_MODALITY 6822340		/* (0x006819c4) */
+#define DS_RET_UNKNOWN_MODALITY_E 6822348		/* (0x006819cc) */
+#define DS_RET_UNKNOWN_MODALITY_U 6822356		/* (0x006819d4) */
+#define DS_RET_UNKNOWN_MODALITY_D 6822364		/* (0x006819dc) */
+#define DS_RET_UNKNOWN_SWAP_MODE 6822372		/* (0x006819e4) */
+#define DS_RET_UNKNOWN_SWAP_MODE_E 6822380		/* (0x006819ec) */
+#define DS_RET_UNKNOWN_SWAP_MODE_U 6822388		/* (0x006819f4) */
+#define DS_RET_UNKNOWN_SWAP_MODE_D 6822396		/* (0x006819fc) */
+#define DS_RET_WITH_ERROR 6822404		/* (0x00681a04) */
+#define DS_RET_WITH_ERROR_E 6822412		/* (0x00681a0c) */
+#define DS_RET_WITH_ERROR_U 6822420		/* (0x00681a14) */
+#define DS_RET_WITH_ERROR_D 6822428		/* (0x00681a1c) */
+#define DS_CODE_SET_OUT_OF_ORDER 6825347		/* (0x00682583) */
+#define DS_CODE_SET_OUT_OF_ORDER_E 6825355		/* (0x0068258b) */
+#define DS_CODE_SET_OUT_OF_ORDER_U 6825363		/* (0x00682593) */
+#define DS_CODE_SET_OUT_OF_ORDER_D 6825371		/* (0x0068259b) */
+#define DS_CODE_END_OF_SET_FOUND 6825379		/* (0x006825a3) */
+#define DS_CODE_END_OF_SET_FOUND_E 6825387		/* (0x006825ab) */
+#define DS_CODE_END_OF_SET_FOUND_U 6825395		/* (0x006825b3) */
+#define DS_CODE_END_OF_SET_FOUND_D 6825403		/* (0x006825bb) */
+#define DS_CODE_FATAL_ERROR 6825411		/* (0x006825c3) */
+#define DS_CODE_FATAL_ERROR_E 6825419		/* (0x006825cb) */
+#define DS_CODE_FATAL_ERROR_U 6825427		/* (0x006825d3) */
+#define DS_CODE_FATAL_ERROR_D 6825435		/* (0x006825db) */
+#define DS_CODE_FIRST_ELEMENT_INVALID 6825443		/* (0x006825e3) */
+#define DS_CODE_FIRST_ELEMENT_INVALID_E 6825451		/* (0x006825eb) */
+#define DS_CODE_FIRST_ELEMENT_INVALID_U 6825459		/* (0x006825f3) */
+#define DS_CODE_FIRST_ELEMENT_INVALID_D 6825467		/* (0x006825fb) */
+#define DS_CODE_INVALID_MODALITY 6825475		/* (0x00682603) */
+#define DS_CODE_INVALID_MODALITY_E 6825483		/* (0x0068260b) */
+#define DS_CODE_INVALID_MODALITY_U 6825491		/* (0x00682613) */
+#define DS_CODE_INVALID_MODALITY_D 6825499		/* (0x0068261b) */
+#define DS_CODE_INVALID_SOM0_PARAMETERS 6825507		/* (0x00682623) */
+#define DS_CODE_INVALID_SOM0_PARAMETERS_E 6825515		/* (0x0068262b) */
+#define DS_CODE_INVALID_SOM0_PARAMETERS_U 6825523		/* (0x00682633) */
+#define DS_CODE_INVALID_PARAMETERS_D 6825531		/* (0x0068263b) */
+#define DS_CODE_INVALID_INTERFACE 6825539		/* (0x00682643) */
+#define DS_INVALID_INTERFACE_E 6825547		/* (0x0068264b) */
+#define DS_INVALID_INTERFACE_U 6825555		/* (0x00682653) */
+#define DS_INVALID_INTERFACE_D 6825563		/* (0x0068265b) */
+#define DS_CODE_MULTIPLE_FATAL_ERROR 6825571		/* (0x00682663) */
+#define DS_CODE_FMULTIPLE_ATAL_ERROR_E 6825579		/* (0x0068266b) */
+#define DS_CODE_MULTIPLE_FATAL_ERROR_U 6825587		/* (0x00682673) */
+#define DS_CODE_MULTIPLE_FATAL_ERROR_D 6825595		/* (0x0068267b) */
+#define DS_CODE_NO_OWNER 6825603		/* (0x00682683) */
+#define DS_CODE_NO_OWNER_E 6825611		/* (0x0068268b) */
+#define DS_CODE_NO_OWNER_U 6825619		/* (0x00682693) */
+#define DS_CODE_NO_OWNER_D 6825627		/* (0x0068269b) */
+#define DS_CODE_TRANSFORM_NOT_POSSIBLE 6825635		/* (0x006826a3) */
+#define DS_CODE_TRANSFORM_NOT_POSSIBLE_E 6825643		/* (0x006826ab) */
+#define DS_CODE_TRANSFORM_NOT_POSSIBLE_U 6825651		/* (0x006826b3) */
+#define DS_CODE_TRANSFORM_NOT_POSSIBLE_D 6825659		/* (0x006826bb) */
+#define DS_CODE_UNKNOWN_COMPRESSION 6825667		/* (0x006826c3) */
+#define DS_CODE_UNKNOWN_COMPRESSION_E 6825675		/* (0x006826cb) */
+#define DS_CODE_UNKNOWN_COMPRESSION_U 6825683		/* (0x006826d3) */
+#define DS_CODE_UNKNOWN_COMPRESSION_D 6825691		/* (0x006826db) */
+#define DS_CODE_UNKNOWN_DATA_SET 6825699		/* (0x006826e3) */
+#define DS_CODE_UNKNOWN_DATA_SET_E 6825707		/* (0x006826eb) */
+#define DS_CODE_UNKNOWN_DATA_SET_U 6825715		/* (0x006826f3) */
+#define DS_CODE_UNKNOWN_DATA_SET_D 6825723		/* (0x006826fb) */
+#define DS_CODE_UNKNOWN_HEADER 6825731		/* (0x00682703) */
+#define DS_CODE_UNKNOWN_HEADER_E 6825739		/* (0x0068270b) */
+#define DS_CODE_UNKNOWN_HEADER_U 6825747		/* (0x00682713) */
+#define DS_CODE_UNKNOWN_HEADER_D 6825755		/* (0x0068271b) */
+#define DS_CODE_UNKNOWN_OVERLAY 6825763		/* (0x00682723) */
+#define DS_CODE_UNKNOWN_OVERLAY_E 6825771		/* (0x0068272b) */
+#define DS_CODE_UNKNOWN_OVERLAY_U 6825779		/* (0x00682733) */
+#define DS_CODE_UNKNOWN_OVERLAY_D 6825787		/* (0x0068273b) */
+#define DS_CODE_MISSING_TYP_1 6825795		/* (0x00682743) */
+#define DS_CODE_MISSING_TYP_1_E 6825803		/* (0x0068274b) */
+#define DS_CODE_MISSING_TYP_1_U 6825811		/* (0x00682753) */
+#define DS_CODE_MISSING_TYP_1_D 6825819		/* (0x0068275b) */
+#define DS_CODE_MULTIPLE_ERROR 6825827		/* (0x00682763) */
+#define DS_CODE_MULTIPLE_ERROR_E 6825835		/* (0x0068276b) */
+#define DS_CODE_MULTIPLE_ERROR_U 6825843		/* (0x00682773) */
+#define DS_CODE_MULTIPLE_ERROR_D 6825851		/* (0x0068277b) */
+#define DS_CODE_NOT_ALL_FILLED 6825859		/* (0x00682783) */
+#define DS_CODE_NOT_ALL_FILLED_E 6825867		/* (0x0068278b) */
+#define DS_CODE_NOT_ALL_FILLED_U 6825875		/* (0x00682793) */
+#define DS_CODE_NOT_ALL_FILLED_D 6825883		/* (0x0068279b) */
+#define DS_CODE_NORMAL 6825891		/* (0x006827a3) */
+#define DS_CODE_NORMAL_E 6825899		/* (0x006827ab) */
+#define DS_CODE_NORMAL_U 6825907		/* (0x006827b3) */
+#define DS_CODE_NORMAL_D 6825915		/* (0x006827bb) */
+#define DS_CODE_UNDEFINED 6825923		/* (0x006827c3) */
+#define DS_CODE_UNDEFINED_E 6825931		/* (0x006827cb) */
+#define DS_CODE_UNDEFINED_U 6825939		/* (0x006827d3) */
+#define DS_CODE_UNDEFINED_D 6825947		/* (0x006827db) */
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_transformation.h
@@ -0,0 +1,683 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_transformation.h
+
+   Description: The header file defines the common types, constants and macros for the
+                data set library.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_TRANSFORMATION
+#define DS_TRANSFORMATION
+
+
+
+/*==  VERSION CONTROL  ====================================================================*/
+/* PRECOMPILER: define version control contants */
+/*   NOTE: versions */
+/* 
+     The following list shows the used version codes in chronological order:
+   
+     Date         | Doc     DS      IH      ACR     SPI    notes
+     -------------+----------------------------------------------------------------
+     1989-JUL-03  | V0.2    -       -       1.0     01.00  
+     1990-MAR-10  | V1.1    -       VA1     2.0     01.00  
+     1990-MAR-12  | V1.1    V1.2    VA1     2.0     01.00  
+     1990-APR-27  | V1.3    V1.3    VA3     2.0     01.00  internal version
+     1990-AUG-01  | V1.4    V1.4    VA4     2.0     01.00
+     1990-OCT-01  | V1.5    V1.5    VA5     2.0     01.00
+     1990-OCT-11  | V1.5    V1.51   VA5     2.0     01.00  M 15
+     1990-OCT-15  | V1.5    V1.52   VA5     2.0     01.00  M 13, M19
+     1990-NOV-16  | V1.5    V1.53   VA53    2.0     01.00  parts of M16
+     1990-NOV-23  | V1.5    V1.54   VA53    2.0     01.00  M 28
+     1990-DEC-07  | V1.5    V1.55   VA55    2.0     01.00  M31, parts of M16, M30
+     1991-JAN-31  | V2.0    V2.0    VB      2.0     01.00  M*, som, num2, ...
+     1991-FEB-19  | V2.0    V2.1    VB      2.0     01.00  M 40
+     1991-FEB-28  | V2.0    V2.2    VB2     2.0     01.00  M 38, M 39, M 40, M 45
+     1991-MAR-14  | V2.0    V2.3    VB2     2.0     01.00  M 41, M 48
+     1991-MAR-28  | V2.0    V2.4    VB2     2.0     01.00  M*, som, num2, ...
+     1991-APR-17  | V2.0    V2.5    VB3     2.0     01.00  M*
+     1991-MAY-23  | V2.0    V2.6    VB4     2.0     01.00  parts of M49
+     1991-JUL-31  | V2.0    V2.7    VB5     2.0     01.00  M*, db_set, num1, ...
+     1991-AUG-08  | V2.0    V2.8    VB5     2.0     01.00  M 65
+     1991-SEP-12  | V2.0    V2.9    VB5     2.0     01.00  Image Text: M80, 73, 66, 64, 60, 59
+     1991-OCT-10  | V2.0    V2.10   VB5     2.0     01.00  M 86
+     1991-NOV     | V3.0    V3.0    VB6     2.0     01.00  M*, som0
+
+
+     labels:
+     -------
+     Doc  Documentation Version ("Phone Book" Version)
+     DS   Data Set Library (Software) Version
+     IH   Internal Header Version
+     ACR  NEMA Standard Version
+     SPI  SPI Standard Version
+*/
+
+/*   version strings */
+/*     NOTE: Software Version String */
+/*   The constant "DS_SOFTWARE_VERSION_STRING" is not longer supported. The software
+     version is set in this and future software releases in data set library function 
+     "ds_info_get_software_version" directly. In this way several modul compilations
+     after changing this common used data set library header file are avoided. */
+
+/*     constant definition */
+#define HEADER_VERSION_STRING                                                      "VB6     "
+#define RECOGNITION_CODE_STRING                                                "ACR-NEMA 2.0"
+#define SPI_VERSION_STRING                                               "SPI VERSION 01.00 "
+
+
+
+/*==  CONSTANTS  ==========================================================================*/
+
+/* PRECOMPILER: define common non-numeric constants */
+
+/*   logical constants */
+#ifndef TRUE
+#define TRUE                                                                                1
+#endif
+
+#ifndef FALSE
+#define FALSE                                                                               0
+#endif
+
+
+/*   common status file constants */
+#define DS_STATUS_FILE_TYPE                                                struct STC_COMMON
+
+
+/*   common nil pointer constants */
+#define DS_CHAR_NIL                                                              ((char *) 0)
+#define DS_DOUBLE_NIL                                                          ((double *) 0)
+#define DS_INT_NIL                                                                ((int *) 0)
+#define DS_LONG_NIL                                                              ((long *) 0)
+#define DS_SHORT_NIL                                                            ((short *) 0)
+#define DS_STATUS_FILE_NIL                                        ((DS_STATUS_FILE_TYPE *) 0)
+#define DS_VOID_NIL                                                              ((void *) 0)
+
+
+/* PRECOMPILER: define status area element codes */
+/*   NOTE: list of status abbreviations */
+/*
+   PRE == PREparation of item value e.g. adapt, collect information
+   KEY == build up item KEY
+   BUF == transfere item value into nema data set BUFfer
+   SEP == SEParation of item from nema data set buffer
+   SET == SET back item value for internal use
+   POS == POSition item value into interanl header e.g. split, convert information
+   CH1 == Check a first parameter
+   CH2 == Check a second  parameter
+*/
+
+/*   error handling constants */
+#define PRE                                                                                 0
+#define KEY                                                                                 1
+#define BUF                                                                                 2
+#define SEP                                                                                 0
+#define SET                                                                                 1
+#define POS                                                                                 2
+#define CH1                                                                                 0
+#define CH2                                                                                 1
+
+
+/*   sign constants */
+#define DELIMITER_DS_SIGN                                                                '\\'
+#define INITALIZE_DS_SIGN                                                                 ' '
+#define NON_PRINT_ABLE_DS_SIGN                                                            '~'
+#define OVERLAY_DS_SIGN                                                                   '/'
+#define PADDING_DS_SIGN                                                                   ' '
+#define UNDEFINED_TEXT_DS_SIGN                                                            ' '
+
+
+/*   string constants */
+#define IMAGE_GRAPHIC_FORMAT_CMS                                                       "CMS "
+
+
+/*   end-of constants */
+#define EOAL                                                                         (-19223)
+#define END_OF_DATA_SET                                                              (-19224)
+
+
+/*   coordinate system constants */
+#define AAA                                                                                 0
+#define BBB                                                                                 1
+#define CCC                                                                                 2
+#define XXX                                                                                 0
+#define YYY                                                                                 1
+#define ZZZ                                                                                 2
+#define SAG                                                                                 0
+#define COR                                                                                 1
+#define TRA                                                                                 2
+#define ROW                                                                                 0
+#define COLUMN                                                                              1
+#define DOWN                                                                                0
+#define RIGHT                                                                               1
+
+
+/*   common numeric contants */
+#define DS_DO_NOT_FILL                                                                  (-1L)
+#define DS_MAX_CHAR                                                                 (256 + 1)
+#define DS_SAVE_FACTOR                                                                 (4096)
+#define DS_UID_SIZE                                                                      (26)
+#define DS_WORK_CHAR                                                                 (32 + 1)
+
+
+
+/*==  RUNTIME CONTROL  ====================================================================*/
+
+/* PRECOMPILER: define debug constants */
+
+/*   NOTE: debug constants */
+/*
+     The constant 'DEBUGGING_BY_THUMSER' is used to compile or not compile C-source code
+     for debugging. If you change the '#undef'-command in a '#define'-command all parts
+     with debug code are compiled. This is usefull to activate calls of function printf()
+     etc.
+
+     The macro 'DS_ERROR_CONDITION' controls the call of function ds_initiate_error_handling().
+     During normal run time this macro is defined in a matter, that only if a error
+     or warning raised the function "ds_initiate_error_handling()" will be actived. If the
+     debug switch 'DEBUGGING_BY_THUMSER' is defined for every item a message is printed to
+     standard output device. Note that in this case the interface status is not updated
+     correctly. Please use the shown messages to anlyse the item transformation
+     results.
+
+*/
+#undef DEBUGGING_BY_THUMSER
+
+#ifndef DEBUGGING_BY_THUMSER
+#define DS_ERROR_CONDITION                                   (!(StatusList[0] & 0x0001) || \
+                                                              !(StatusList[1] & 0x0001) || \
+                                                                  !(StatusList[2] & 0x0001))
+#else
+#define DS_ERROR_CONDITION                                                              TRUE
+#endif
+
+
+#define ds_initiate_error_handling(Group, Element, Error, Status, Return)                   \
+            ds_init_error_handling(__FILE__, __LINE__, Group, Element, Error, Status, Return)
+            
+            
+/*-----------------------------------------------------------------------------------------*/
+
+
+/* PRECOMPILER: define interacive constants */
+
+/*   NOTE: interacive constants */
+/*   The constant 'DS_INTERACTIVE' is used to compile or not compile C-source code for a
+     interactive use of separation functions. If you change the '#undef'-command in a
+     '#define'-command all parts with interactive code are compiled. */
+#undef DS_INTERACTIVE
+/*-----------------------------------------------------------------------------------------*/
+
+
+/* PRECOMPILER: define Exception Handler */
+
+/*   NOTE: Exception Handler */
+/*   Three makros are implemented to raise the exception handler. You can choise one for your
+     current work by precompiler statement #define and #undefine, respectively.
+
+
+     DS_RAISE_NORMAL
+     The raise is done with a goto statement. Only to raise an exception handler the goto
+     statement is used in data set library software. No other actions will be done.
+   
+   
+     DS_RAISE_TRACE
+     The raise is done with a goto statement also, but before flow control goes to the raised
+     exception handler a printf() call is done. The following text is printed:
+   
+     "<file>", line <line number>: raise ==> <status>
+     
+     The print out of this message can be controlled by file '/tmp/ds_trace_on'. If the file
+     exist the print out is done otherwise nothing is done. In this manner the switch can be 
+     done during runtime without new compilation or process restart.
+     
+     If 'DS_RAISE_TRACE' defined an item trace is possible too. For more information about
+     this topic see description of function 'ds_finally_interface_status_update()' in modul
+     'ds_mixed.c'.
+   
+   
+     DS_RAISE_DBX
+     The raise is done with a goto statement also, but before flow control goes to the raised
+     exception handler a ds_stop_dbx() is done. This function has no other function than to
+     stop point for debugger. Use during a dbx session the command 'stop in ds_stop_dbx'.
+     The debugger stops program execution everytime a exception is raised. A check of current
+     active parameters is now possible.
+*/
+#undef   DS_RAISE_NORMAL
+#define  DS_RAISE_TRACE
+#undef   DS_RAISE_DBX
+
+#ifdef DS_RAISE_NORMAL
+#define DS_RAISE_EXCEPTION(x)                                                          goto x
+#endif
+
+
+#ifdef DS_RAISE_TRACE
+#define DS_RAISE_EXCEPTION(x)                                                             { \
+                                              ds_trace_control(__FILE__, __LINE__, Status); \
+                                                                                    goto x; \
+                                                                                            }
+#endif
+
+
+#ifdef DS_RAISE_DBX
+#define DS_RAISE_EXCEPTION(x)                                                             { \
+                                                                             ds_stop_dbx(); \
+                                                                                    goto x; \
+                                                                                            }
+#endif
+
+
+/* PRECOMPILER: define Return Code Handler */
+
+/*   NOTE: Return Code Handler */
+/*   To set a special return code the makro 'DS_SET_RETURN_CODE()' is available. Three forms
+     of this makro are implemented to manage the handling during setting of a special return
+     code. You can choise one for your current work by precompiler statement #define and
+     #undefine, respectively.
+
+
+     DS_RETURN_NORMAL
+     The return code is set with a normal assign statement. No other actions will be done.
+   
+   
+     DS_RETURN_TRACE
+     The return code is set with an assign statement also, but in addition a printf() call 
+     is done. The following text is printed:
+   
+     "<file>", line <line number>: return ==> <status>
+     
+     The print out of this message can be controlled by file '/tmp/ds_return_on'. If the file
+     exist the print out is done otherwise nothing is done. In this manner the switch can be
+     done during runtime without new compilation or process restart.
+   
+   
+     DS_RETURN_DBX
+     The return code is set with an assign statement also, but in additon a call of function
+     ds_stop_dbx() is done. This function has no other function than to stop point for debugger.
+     Use during a dbx session the command 'stop in ds_stop_dbx'. The debugger stops program 
+     execution everytime a special return code is set. A check of current active parameters 
+     is now possible.
+*/
+#undef   DS_RETURN_NORMAL
+#define  DS_RETURN_TRACE
+#undef   DS_RETURN_DBX
+
+#ifdef DS_RETURN_NORMAL
+#define DS_SET_RETURN_CODE(x)                                                ReturnCode = (x);
+#endif
+
+
+#ifdef DS_RETURN_TRACE
+#define DS_SET_RETURN_CODE(x)                                                             { \
+                                                ds_return_control(__FILE__, __LINE__, (x)); \
+                                                                          ReturnCode = (x); \
+                                                                                            }
+#endif
+
+
+#ifdef DS_RETURN_DBX
+#define DS_SET_RETURN_CODE(x)                                                             { \
+                                                                             ds_stop_dbx(); \
+                                                                          ReturnCode = (x); \
+                                                                                            }
+#endif
+/*-----------------------------------------------------------------------------------------*/
+
+
+/* PRECOMPILER: define length of NEMA item values */
+
+/*   NOTE: length of NEAM item values control */
+/*
+     If you want to use other lengths for NEMA item values as the CMS defined standard
+     lengths then change the following precompiler statement '#undef DS_USE_NOT_STAN-
+     DARD_LENGTH' to '#define DS_USE_NOT_STANDARD_LENGTH'.
+
+     A reason to do this is do minimize the NEAM Data Set Length during data set build up.
+     If you want a minimal NEAM Data Set length define the following xxx_LENGTH
+     identifier with a replacement of 2. Then the Data Set Library functions get and
+     use the minimal necessary length of each item.
+
+     If you use a replacement less than two then a fatal error occur.
+*/
+
+#undef DS_USE_NOT_STANDARD_LENGTH
+#ifndef DS_USE_NOT_STANDARD_LENGTH
+
+#define AGE_LENGTH                                                                 LENGTH_AGE
+#define DATE_LENGTH                                                                       10L
+#define DIAGNOSIS_LENGTH                                                     LENGTH_DIAGNOSIS
+#define DIRECTION_LENGTH                                                     LENGTH_DIRECTION
+#define COMMENT_LENGTH                                                         LENGTH_COMMENT
+#define FILE_NAME_LENGTH                                                     LENGTH_FILE_NAME
+#define FILTER_ID_LENGTH                                                     LENGTH_FILTER_ID
+#define HEADER_VERSION_LENGTH                                           LENGTH_HEADER_VERSION
+#define INTEGER_NUMBER_LENGTH                                                              6L
+#define LABEL_LENGTH                                                             LENGTH_LABEL
+#define LITTLE_IDENT_LENGTH                                                                4L
+#define LONG_IDENT_LENGTH                                                                 12L
+#define NUCLEUS_LENGTH                                                         LENGTH_NUCLEUS
+#define MANUFACTURER_LENGTH                                               LENGTH_MANUFACTURER
+#define MIDDLE_IDENT_LENGTH                                                                8L
+#define ORIENTATION_LENGTH                                                 LENGTH_ORIENTATION
+#define PATIENT_ID_LENGTH                                                   LENGTH_PATIENT_ID
+#define REAL_NUMBER_LENGTH                                                                14L
+#define SEQUENCE_INFO_LENGTH                                             LENGTH_SEQUENCE_INFO
+#define SHORT_IDENT_LENGTH                                                                 2L
+#define SOFTWARE_VERSION_LENGTH                                       LENGTH_SOFTWARE_VERSION
+#define SPI_VERSION_LENGTH                                                                18L
+#define TIME_LENGTH                                                                       12L
+
+#else
+
+#define AGE_LENGTH                                                                         2L
+#define DIAGNOSIS_LENGTH                                                                   2L
+#define DIRECTION_LENGTH                                                                   2L
+#define COMMENT_LENGTH                                                                     2L
+#define FILE_NAME_LENGTH                                                                   2L
+#define FILTER_ID_LENGTH                                                                   2L
+#define HEADER_VERSION_LENGTH                                                              2L
+#define INTEGER_NUMBER_LENGTH                                                              2L
+#define LABEL_LENGTH                                                                       2L
+#define LITTLE_IDENT_LENGTH                                                                2L
+#define LONG_IDENT_LENGTH                                                                  2L
+#define NUCLEUS_LENGTH                                                                     2L
+#define MANUFACTURER_LENGTH                                                                2L
+#define MIDDLE_IDENT_LENGTH                                                                2L
+#define ORIENTATION_LENGTH                                                                 2L
+#define PATIENT_ID_LENGTH                                                                  2L
+#define REAL_NUMBER_LENGTH                                                                 2L
+#define SEQUENCE_INFO_LENGTH                                                               2L
+#define SHORT_IDENT_LENGTH                                                                 2L
+#define SOFTWARE_VERSION_LENGTH                                                            2L
+#define SPI_VERSION_LENGTH                                                                 2L
+
+#define DATE_LENGTH                                                                       10L
+#define TIME_LENGTH                                                                       12L
+
+#endif
+/*-----------------------------------------------------------------------------------------*/
+
+
+
+/*==  TYPES  ==============================================================================*/
+
+/* DECLARATION: declare types */
+/*   - undependent types */
+
+typedef enum data_area_type_tag
+{
+  Area_Type_BYTE = 1,
+  Area_Type_LONG = 2,
+  Area_Type_SHORT = 3,
+  Area_Type_UNDEFINED = Enum_UNDEFINED
+} data_area_type_t;
+
+
+typedef enum data_set_format_tag
+{
+  Set_format_BLOCK = 1,
+  Set_format_NEMA = 2,
+  Set_format_UNDEFINED = Enum_UNDEFINED
+} data_set_format_t;
+
+
+typedef struct image_orientation_tag
+{
+  double RowX;
+  double RowY;
+  double RowZ;
+  double ColX;
+  double ColY;
+  double ColZ;
+} image_orientation_t;
+
+
+typedef enum image_class_tag
+{
+  Image_Class_CORONAL = 10,
+  Image_Class_SAGITTAL = 20,
+  Image_Class_TRANSVERSAL = 30,
+  Image_Class_UNDEFINED = Enum_UNDEFINED
+} image_class_t;
+
+
+typedef enum image_text_type_tag
+{
+  Image_Text_Type_BLACK = 1,
+  Image_Text_Type_MR_RAW = 2,
+  Image_Text_Type_NONE = 3,
+  Image_Text_Type_NORMAL = 4,
+  Image_Text_Type_CT_REBUILD = 5,
+  
+  Image_Text_Type_UNDEFINED = Enum_UNDEFINED
+} image_text_type_t;
+
+
+typedef enum item_quality_tag
+{
+  Item_Quality_AFTER_IN_FOLLOWING_GROUP = 10,
+  Item_Quality_AFTER_IN_THIS_GROUP = 11,
+  Item_Quality_BEFORE = 20,
+  Item_Quality_END_OF_DATA_SET = 50,
+  Item_Quality_EQUAL = 30,
+  Item_Quality_OUT_OF_RANGE = 99,
+
+  Item_Quality_UNDEFINED = Enum_UNDEFINED
+} item_quality_t;
+
+
+
+typedef char nema_patient_place_t[2][4];
+
+typedef enum overlay_number_tag
+{
+  Overlay_6000 = 1,
+  Overlay_6002 = 2,
+  Overlay_6004 = 3,
+  Overlay_6006 = 4,
+
+  Overlay_UNDEFINED = Enum_UNDEFINED
+} overlay_number_t;
+
+
+typedef union quart_as_tag				   /* four bytes as different bit
+							      patterns */
+{
+  char AsBytes[4];					   /* as four bytes */
+  float AsFloat;					   /* as float */
+  long AsLong;						   /* as long */
+  short AsShort[2];					   /* as two short */
+} quart_as_t;
+
+
+typedef enum swap_mode_tag
+{
+  Swap_NO = 0,
+  Swap_YES = 1,
+  Swap_UNDEFINED = Enum_UNDEFINED
+} swap_mode_t;
+
+
+typedef struct transformation_list_tag
+{
+  int Index;
+  double Factor;
+} transformation_list_t[3];
+
+
+typedef double matrix_3x3_t[3][3];
+
+
+typedef enum update_mode_tag
+{
+  Update_ELEMENT = 1,
+  Update_FOUND = 2,
+  Update_GROUP = 3,
+  Update_UNDEFINED = Enum_UNDEFINED
+} update_mode_t;
+
+
+typedef enum value_mode_tag
+{
+  Value_IS_NORMAL = 1,
+  Value_IS_LAST = 2,
+  Value_UNDEFINED = Enum_UNDEFINED
+} value_mode_t;
+
+
+typedef enum value_representation_tag
+{
+  Representation_AN = 10,
+  Representation_AT = 11,
+  Representation_BI = 20,
+  Representation_BR = 21,
+  Representation_BY = 22,
+  Representation_BX = 23,
+  Representation_UNDEFINED = Enum_UNDEFINED
+} value_representation_t;
+
+
+typedef double vector_t[3];
+
+
+/*   - dependent types */
+
+typedef struct nema_image_place_tag
+{
+  nema_patient_place_t PatientOrientation;
+  vector_t ImagePosition;
+  vector_t ImageOrientation[2];
+} nema_image_place_t;
+
+
+
+/*==  MACROS  =============================================================================*/
+
+/* PRECOMPILER: define macros */
+
+  /* NOTE: define macros */
+  /*
+  If you want to use a "Mathematics" macro don't forget to insert the precompiler line
+  "#include <math.h>".
+  */
+/*-----------------------------------------------------------------------------------------*/
+
+
+/*   Bit Manipulation */
+#define DS_BIT_CLEAR(Variable, BitNumber)     ((Variable) = ((Variable) & ~(1<<(BitNumber))))
+#define DS_BIT_TEST(Variable, BitNumber)               (((Variable) & (1<<(BitNumber))) != 0)
+#define DS_BIT_SET(Variable, BitNumber)        ((Variable) = ((Variable) | (1<<(BitNumber))))
+#define DS_BIT_TOGGLE(Variable, BitNumber)                                   (for future use)
+/*-----------------------------------------------------------------------------------------*/
+
+
+/*   Mathematics */
+#define DS_MAX(a,b)                                                         ((a)>(b)?(a):(b))
+#define DS_MIN(a,b)                                                         ((a)>(b)?(b):(a))
+
+
+#define DS_I_ABS(x)                                                    ((x) < 0 ? -(x) : (x))
+
+#define DS_R_ABS(x)                                                                 fabs((x))
+#define DS_R_EQUAL(x, y)                 (fabs((double)(x) - (double)(y)) <= (double)0.00001)
+#define DS_R_GREATER(x, y)                                                        ((x) > (y))
+#define DS_R_LESS(x, y)                                                           ((x) < (y))
+
+#define DS_V_EQUAL(x, y)                                   ds_vector_check_if_equal((x), (y))
+
+#define DS_G_SIN(x)                                                 (sin(((M_PI/180.0)*(x))))
+#define DS_G_COS(x)                                                 (cos(((M_PI/180.0)*(x))))
+#define DS_G_TAN(x)                                                 (tan(((M_PI/180.0)*(x))))
+#define DS_G_TAN2(x,y)                                         (tan2((M_PI/180.0)*((x),(y))))
+
+#define DS_G_ASIN(x)                                                 ((180.0/M_PI)*asin((x)))
+#define DS_G_ACOS(x)                                                 ((180.0/M_PI)*acos((x)))
+#define DS_G_ATAN(x)                                                 ((180.0/M_PI)*atan((x)))
+#define DS_G_ATAN2(x,y)                                         ((180.0/M_PI)*atan2((x),(y)))
+
+#define DS_R_SIN(x)                                                               (sin((x))))
+#define DS_R_COS(x)                                                               (cos((x))))
+#define DS_R_TAN(x)                                                               (tan((x))))
+#define DS_R_TAN2(x,y)                                                       (tan2((x),(y))))
+
+#define DS_R_ASIN(x)                                                              (asin((x)))
+#define DS_R_ACOS(x)                                                              (acos((x)))
+#define DS_R_ATAN(x)                                                              (atan((x)))
+#define DS_R_ATAN2(x,y)                                                      (atan2((x),(y)))
+
+/*-----------------------------------------------------------------------------------------*/
+
+
+/*   Transformation Matrix Handling */
+#define DS_SET_TRANSFORMATION_LIST(a_fac, a_ind, b_fac, b_ind, c_fac, c_ind)                \
+                                                                                          { \
+                                                  TransformationList[AAA].Index  = (a_ind); \
+                                                  TransformationList[AAA].Factor = (a_fac); \
+                                                  TransformationList[BBB].Index  = (b_ind); \
+                                                  TransformationList[BBB].Factor = (b_fac); \
+                                                  TransformationList[CCC].Index  = (c_ind); \
+                                                  TransformationList[CCC].Factor = (c_fac); \
+                                                                                            }
+/*-----------------------------------------------------------------------------------------*/
+
+
+/*   Image Class / History Label */
+#define DS_SET_HISTORY_LABEL(ClassLabel, No1Label, No2Label)                                \
+                       strncpy(Header->G51.Txt.SliceOrientationNo1, (ClassLabel), (int) 3); \
+		                                     if (!(DS_R_EQUAL(SliceAngleNo1, 0.0))) \
+		                                                                          { \
+		                              Header->G51.Txt.SliceOrientationNo1[3] = '>'; \
+                   strncpy(&(Header->G51.Txt.SliceOrientationNo1[4]), (No1Label), (int) 3); \
+		                                                                          } \
+		                                     if (!(DS_R_EQUAL(SliceAngleNo2, 0.0))) \
+		                                                                          { \
+		                              Header->G51.Txt.SliceOrientationNo2[3] = '>'; \
+		   strncpy(&(Header->G51.Txt.SliceOrientationNo2[4]), (No2Label), (int) 3); \
+	                                                                                    }
+/*-----------------------------------------------------------------------------------------*/
+
+
+/*   String Initialization */
+#define DS_SET_STRING_DEFAULT(String, DefaultSign, StringLength)                            \
+	                             memset((String), (DefaultSign), (int) (StringLength)); \
+	                                                        String[(StringLength)] = '\0'
+
+#define DS_SET_STRING_UNDEFINED(String, FillSign, StringLength)                             \
+	                                memset((String), (FillSign), (int) (StringLength)); \
+	                                                     String[(StringLength)] = '\0'; \
+	                                                         String[0] = String_UNDEFINED
+
+#define DS_SET_STRING_VALUE(String, FillString, StringLength)                               \
+                                       bcopy((FillString), (String), (int) (StringLength)); \
+                                                                String[(StringLength)] = '\0'
+
+#define DS_SET_STRING_CHANGEABLE(String)                                                    \
+                                  ds_string_delete_leading_characters(String, String, ' '); \
+                                     ds_string_delete_tailing_characters(String, String, ' ')
+/*-----------------------------------------------------------------------------------------*/
+
+
+
+/*==  FUNCTIONS  ==========================================================================*/
+
+/* NOTE: define system library functions */
+/*
+  The following system library functions are defined here to avoid an error message during
+  lint task.
+*/
+
+/* DECLARATION: define special parameter */
+/*char *sprintf();*/
+
+
+
+/*========================================================================================*/
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_include/ds_transformation_control.h
@@ -0,0 +1,599 @@
+/*[-  HEADER FILE  -------------------------------------------------------------------------*/
+/*
+   Name:        ds_transformation_control.h
+
+   Description: The header file defines the types, constants and macros necessary to
+                control a data set transformation.
+
+                                                  NOTE
+                The discussion about graphic representation has not finished in the
+                moment (1989-DEC). A final declaration is possible after publishing the
+                graphic discussion results.
+
+
+   Author:      THUMSER, Andreas (TH); Siemens AG UBMed CMS/SCE64; phone: 09131 844797
+*/
+/*]-----------------------------------------------------------------------------------------*/
+
+#ifndef DS_TRANSFORMATION_CONTROL
+#define DS_TRANSFORMATION_CONTROL
+
+
+/*==  "Interpace Pointer List"  ============================================================*/
+
+/*[
+   Description: Entity "Interpace Pointer List"
+
+   The most important part to control the transformation is the Interface
+   Pointer List. To use the data set library build up function "ds_build_up_
+   cms_nema_data_set() to export an Internal Data Set or the data set library
+   separation function "ds_separate_common_data_set() to import a NEMA Data
+   Set this structure must be filled with data to control the transformation.
+   This structure is the link between the different data areas in the host
+   memory.
+
+   The following C-code fragment shows an example to fill an Interface Pointer
+   List before a NEMA Data Set is build up and separate respectively.
+   The example areas are named 'MyHead', 'MyGraphic', 'MyData' for Internal
+   Data Set and 'NemaSet' for the NEMA Data Set. The Interface Pointer List
+   'MyInterface' is used.
+   Please note such areas must be available and filled with valid data before
+   a data set transformation can be done. It is the user's responsibility to
+   ensure that enough storage is available for the different areas.
+
+   To avoid nested comments in the source file the C++ comment sign "//" is
+   used.
+
+   // SEQUENCE: build up CMS defined NEMA Data Set
+     ...
+     // update interface pointer list
+     MyInterface.In.HeadAddress = &MyHead;                    // pointer to head area
+     MyInterface.In.HeadLength = sizeof(header_t);            // length of head area
+     MyInterface.In.GraphicAddress = MyGraphic_p;             // pointer to graphic area
+                                                              // or DS_VOID_NIL
+     MyInterface.In.GraphicLength = MyGraphicLength;          // length of graphic area
+                                                              // or Integer_UNDEFINED
+                                                              // or 0
+     MyInterface.In.DataAddress = (void *)MyData_p;           // pointer to data area
+     MyInterface.In.DataLength = MyDataLength;                // length of data area 1)
+
+     MyInterface.Ex.HeadAddress = MyNema_p;                   // pointer to NEMA area
+     MyInterface.Ex.HeadLength = Integer_UNDEFINED;           // filled during build up
+     MyInterface.Ex.GraphicAddress = DS_VOID_NIL;             // filled during build up
+     MyInterface.Ex.GraphicLength = Integer_UNDEFINED;        // filled during build up
+     MyInterface.Ex.DataAddress = DS_VOID_NIL;                // filled during build up
+     MyInterface.Ex.DataLength = Integer_UNDEFINED;           // filled during build up
+     MyInterface.Ex.DataGroup = (short) Integer_UNDEFINED;    // filled during build up
+
+     MyInterface.CntStatus.Owner = DS_owner_UNDEFINED;        // initialization
+     MyInterface.CntStatus.Modality = <required modality>;    // p r e s e t t i n g !!
+     MyInterface.CntStatus.Code = DS_code_UNDEFINED;          // initialization
+     MyInterface.CntStatus.StatusFileAddress = MyFileAddress; // pointer to mapped status file
+     MyInterface.CntStatus.StopItem.GroupNumber = 0;          // initialization
+     MyInterface.CntStatus.StopItem.ElementNumber = 0;        // initialization
+     ...
+     
+     1) The pure data length in bytes is also stored into item Number of Data Bytes
+        (0019'H,1060'H).
+        
+
+   // SEQUENCE: separate common Data Set
+     ...
+     // update interface pointer list
+     MyInterface.In.HeadAddress = &MyHead;                    // pointer to head area
+     MyInterface.In.HeadLength = sizeof(header_t);            // length of head area
+     MyInterface.In.GraphicAddress = MyGraphic_p;             // pointer to graphic area
+     MyInterface.In.GraphicLength = Integer_UNDEFINED;        // filled during separation
+     MyInterface.In.DataAddress = (void *)MyData_p;           // pointer to data area
+     MyInterface.In.DataLength = Integer_UNDEFINED;           // filled during separation
+
+     MyInterface.Ex.HeadAddress = MyNema_p;                   // pointer to NEMA area
+     MyInterface.Ex.HeadLength = Integer_UNDEFINED;           // filled during separation
+     MyInterface.Ex.GraphicAddress = DS_VOID_NIL;             // filled during separation
+     MyInterface.Ex.GraphicLength = Integer_UNDEFINED;        // filled during separation
+     MyInterface.Ex.DataAddress = DS_VOID_NIL;                // filled during separation
+     MyInterface.Ex.DataLength = Integer_UNDEFINED;           // filled during separation
+     MyInterface.Ex.DataGroup = (short) Integer_UNDEFINED;    // filled during separation
+
+     MyInterface.CntStatus.Owner = DS_owner_UNDEFINED;        // initialization or presetting
+     MyInterface.CntStatus.Modality = Modality_UNDEFINED;     // initialization or presetting
+     MyInterface.CntStatus.Code = DS_code_UNDEFINED;          // initialization
+     MyInterface.CntStatus.StatusFileAddress = DS_STATUS_FILE_NIL; // not used during separation
+     MyInterface.CntStatus.StopItem.GroupNumber = 0;          // initialization
+     MyInterface.CntStatus.StopItem.ElementNumber = 0;        // initialization
+     ...
+*/
+
+
+/* DECLARATION: declare the interpace pointer list types */
+
+typedef enum transformation_status_tag
+{
+
+/*   NOTE: enum transformation_status_tag */
+/*   The data set library defined transformation control status is supported by native
+     language support (nls). This means it is possible to use this code for a detailed status
+     messages after a transformation task. For example the following lines
+
+      // SEQUENCE: transformate data set
+      MyStatus = ds_separate_common_data_set(&MyInterface);
+
+      // SEQUENCE: show transformation task status
+      printf("\ninfo: separate data set: (%s)", nls_message((int) MyStatus));
+      printf("\n                         (%s)", nls_message((int) MyInterface.CntStatus.Code));
+
+      print after transformatin task with error
+
+      info: separate data set: ret: (DS_RET_WITH_ERROR an error occur during transformation task)
+                                    (DS_CODE_SET_OUT_OF_ORDER data set out of order)
+
+
+*/
+
+  DS_code_DATA_SET_OUT_OF_ORDER =
+  DS_CODE_SET_OUT_OF_ORDER,				   /* Error - groups or elements not
+							      in ascending order. Build up or
+							      separation was aborted. */
+  DS_code_END_OF_DATA_SET_FOUND =
+  DS_CODE_END_OF_SET_FOUND,				   /* Error - End Of Data set was
+							      encountered.  Build up or
+							      separation was aborted. */
+  DS_code_FATAL_ERROR =
+  DS_CODE_FATAL_ERROR,					   /* Error - fatal error occured
+							      during data set transformation
+							      Build up or separation was
+							      aborted. */
+  DS_code_FIRST_ELEMENT_IN_GROUP_INVALID =
+  DS_CODE_FIRST_ELEMENT_INVALID,			   /* Error - first element in group
+							      is not element Group Length
+							      (x'H,0000'H).  Build up or
+							      separation was aborted. */
+  DS_code_INVALID_MODALITY =
+  DS_CODE_INVALID_MODALITY,				   /* Error - desired modality is not
+							      supported.  Build up or
+							      separation was aborted. */
+  DS_code_INVALID_SOM0_PARAMETERS =
+  DS_CODE_INVALID_SOM0_PARAMETERS,			   /* Error - given data set can not
+							      transformed.  Build up or
+							      separation was aborted. */
+  DS_code_INVALID_INTERFACE =
+  DS_CODE_INVALID_INTERFACE,				   /* Error - the interface pointer
+							      list dosen't contain length
+							      information. Separation of
+							      internal data set was aborted. */
+  DS_code_NO_OWNER =
+  DS_CODE_NO_OWNER,					   /* Error - no owner entries found
+							      in shadow groups. Build up or
+							      separation was aborted.  */
+  DS_code_TRANSFORMATION_NOT_POSSIBLE =
+  DS_CODE_TRANSFORM_NOT_POSSIBLE,			   /* Error - The transformation is
+							      not possible, because required
+							      dependencies are not fulfilled.
+							      Please see data set library
+							      function descriptions
+							      "ds_*_check_if_transformation_pos
+							      sible()" for more information.  */
+  DS_code_UNKNOWN_COMPRESSION_CODE =
+  DS_CODE_UNKNOWN_COMPRESSION,				   /* Error - compression code is
+							      unknown or not supported.  Build
+							      up or separation was aborted. */
+  DS_code_UNKNOWN_DATA_SET =
+  DS_CODE_UNKNOWN_DATA_SET,				   /* Error - data set format is
+							      unknown.  Build up or separation
+							      was aborted. */
+  DS_code_UNKNOWN_HEADER =
+  DS_CODE_UNKNOWN_HEADER,				   /* Error - header format is
+							      unknown.  Build up or separation
+							      was aborted. */
+  DS_code_UNKNOWN_OVERLAY =
+  DS_CODE_UNKNOWN_OVERLAY,				   /* Warning - a given overlay number
+							      is invalid. The build up task
+							      omitted the build up of this
+							      overlay group. */
+  DS_code_MISSING_TYP_1_VALUE =
+  DS_CODE_MISSING_TYP_1,				   /* Warning - not all type 1 NEMA
+							      items could be build up, that
+							      means an invalid NEMA Data Set
+							      was build up or separated. */
+  DS_code_MULTIPLE_ERROR =
+  DS_CODE_MULTIPLE_ERROR,				   /* Warning - several errors
+							      detected. This means more than
+							      one type 1 item values are
+							      missing or a type 1 value is
+							      missing and one or more other
+							      item values are not filled. An
+							      invalid NEMA Data Set was build
+							      up or separated. */
+  DS_code_MULTIPLE_FATAL_ERROR =
+  DS_CODE_MULTIPLE_FATAL_ERROR,				   /* Error - several fatal errors
+							      detected. This means more than
+							      one error occures to abort the
+							      transformation. No external data
+							      set is filled. */
+  DS_code_NOT_ALL_FILLED =
+  DS_CODE_NOT_ALL_FILLED,				   /* Warning - not all Internal Data
+							      Set parameters could be filled
+							      or not all required NEMA items
+							      could be built up. This
+							      parameters are set 'undefined'.
+							      That means an valid NEMA Data
+							      Set was build up, but it is
+							      possible that this data set
+							      contains to less information for
+							      special CMS internal use. */
+
+  DS_code_NORMAL = DS_CODE_NORMAL,			   /* successful transformation */
+  DS_code_UNDEFINED = DS_CODE_UNDEFINED			   /* initialization value */
+
+} transformation_status_t;
+
+
+
+typedef enum data_set_owner_tag
+{
+  DS_owner_CMS_NEMA = 1,				   /* The data set is NEMA defined
+							      with CMS expansions. The format
+							      is defined in [DS File Format]
+							      and [DS Item Format] */
+  DS_owner_NEMA = 2,					   /* The data set is NEMA defined.
+							      Possible available expansions
+							      are unknown and not analyzed.
+							      The format is defined in [NEMA
+							      Image], [NEMA Image88] and [NEMA
+							      Image89]. */
+  DS_owner_NUMARIS2_FRAMED = 3,				   /* The data set is Siemens defined
+							      with a NEMA frame. The format is
+							      defined in [MR Header]. */
+  DS_owner_SOMARIS1_FRAMED = 4,				   /* The data set is Siemens defined
+							      with a NEMA frame. The format is
+							      defined in [CT Header] and [CT
+							      Image]. */
+  DS_owner_SOMARIS1_BLOCKED = 5,			   /* The data set is Siemens defined
+							      as a binary data stream. The
+							      format is defined in [CT
+							      Header]. */
+  DS_owner_SOMARIS0_FRAMED = 6,				   /* The data set is Siemens defined
+							      with a NEMA frame. The format is
+							      defined in [CT DRH Header] and
+							      [CT Image]. */
+  DS_owner_SOMARIS0_BLOCKED = 7,			   /* The data set is Siemens defined
+							      as a binary data stream. The
+							      format is defined in [CT DRH
+							      Header]. */
+  DS_owner_CMS_BLOCKED = 8,				   /* The data set is CMS defined
+							      as a binary data stream. The
+							      format is defined in [DS File
+							      Format], [DS Item Format] and
+							      [DS Reference Manual]. */
+  DS_owner_NUMARIS1_FRAMED = 9,				   /* The data set is Siemens defined
+							      with a NEMA frame. The format is
+							      defined in [MR NUM1 Header]. */
+  DS_owner_NUMARIS1_BLOCKED = 10,			   /* The data set is Siemens defined
+							      with a binary data stream. The
+							      format is defined in [MR NUM1
+							      Header]. */
+  DS_owner_UNKNOWN = -99,				   /* The data set format is unknown.
+							      No separation is possible */
+
+  DS_owner_UNDEFINED = Enum_UNDEFINED			   /* initialization */
+} data_set_owner_t;
+
+
+
+typedef struct keyword_tag
+{
+  short GroupNumber;					   /* item group number */
+  short ElementNumber;					   /* item element number */
+} keyword_t;
+
+
+typedef struct control_area_ex_tag			   /* - NEMA Data Set - */
+{
+  char *HeadAddress;					   /* header area address (base
+							      address of NEMA Data Set byte
+							      stream, is also base address of
+							      item key of item Group Length
+							      (0008'H, 0000'H)) */
+  long HeadLength;					   /* header area length in byte */
+  char *GraphicAddress;					   /* graphic area address (base
+							      address of item key of item
+							      Group Length (6021'H, 0000'H)) */
+  long GraphicLength;					   /* graphic area length in byte */
+  char *DataAddress;					   /* data area address (base address
+							      of item key of item Group Length
+							      (<DataGroup>, 0000'H)) */
+  long DataLength;					   /* data length in byte */
+  short DataGroup;					   /* NEMA data group */
+} control_area_ex_t;
+
+
+typedef struct control_area_in_tag			   /* - Internal Data Set - */
+{
+  header_t *HeadAddress;				   /* header area address */
+  long HeadLength;					   /* header area length in byte */
+  char *GraphicAddress;					   /* graphic area address */
+  long GraphicLength;					   /* graphic area length in byte */
+  void *DataAddress;					   /* data area address */
+  long DataLength;					   /* data length in byte */
+} control_area_in_t;
+
+
+typedef struct control_status_tag
+{
+  data_set_owner_t Owner;				   /* Format of source data set. This
+							      parameter must be initialized by
+							      separation with the known owner
+							      or with 'DS_owner_UNDEFINED'. If
+							      'DS_owner_UNDEFINED' is used,
+							      the data set library will
+							      determine the data set owner. If
+							      a preset owner not equal the
+							      real owner of data set the
+							      separation is aborted. During
+							      build up the owner is always set
+							      by data set library functions to
+							      'DS_owner_CMS_NEMA'. */
+  modality_t Modality;					   /* Modality of source data set.
+							      This parameter must be
+							      initialized by separation with
+							      the required modality or with
+							      'Modality_UNDEFINED'. If
+							      'Modality_UNDEFINED' is used,
+							      the data set library will
+							      determine the data set modality
+							      during separation. If a preset
+							      owner not equal the real owner
+							      of data set the separation is
+							      aborted. During build up the
+							      modality must be always preset
+							      with a supported modality value
+							      ('Modality_CT' or
+							      'Modality_MR'). */
+  DS_STATUS_FILE_TYPE *StatusFileAddress;		   /* Common Status File address. This
+							      parameter can be set if a status
+							      file mapped outside of the data
+							      set library. Otherwise this
+							      parameter must be set to nil
+							      (DS_STATUS_FILE_NIL). If acssess
+							      to a status file possible the
+							      Unique Identifier
+							      (0009'H,1015'H) is build up with
+							      common status file information
+							      otherwise the non PACS
+							      presettings are used. */
+  transformation_status_t Code;				   /* Detailed status code. This
+							      parameter is set by data set
+							      library. */
+  keyword_t StopItem;					   /* Last handled item. If an fatal
+							      error occur during
+							      transformation this parameter
+							      contains the error produced item
+							      group and element number. This
+							      two parameters must be
+							      initlaized with 0. */
+} control_status_t;
+
+
+
+typedef struct interface_pointer_list_tag
+{
+  control_area_ex_t Ex;					   /* Internal Data Set information */
+  control_area_in_t In;					   /* NEMA Data Set information */
+  control_status_t CntStatus;				   /* common status information */
+} interface_pointer_list_t;
+/*]*/
+
+
+/*==  "NEMA Parser Pointer List"  ==========================================================*/
+
+/*[
+   Description: Entity "NEMA Parser Pointer List"
+
+   The NEMA data set parser works as an anticipationed scanner. In this manner it is possible
+   to analyse the current work item in his NEMA data set context. Detection of end of
+   data set, group change, subgroup change, generation of subgroup owner list, position
+   control during parsing etc. can be done with the same data set library features.
+
+   The NEMA parser pointer list contains several pointers (addresses) to special locations
+   in a NEMA data set, like begin of data set, end of data set, end of current worked
+   group, end of group containing next item. In addition the item keys of current
+   worked item and the following next item are stored.
+
+   But the most importent information for a application programmer is the pointer to
+   the item value of the current worked item. This pointer is used to split, convert or
+   fill the item for internal use.
+
+   For clearness, the 'current worked item' is the item currently analysed, transfered,
+   tested etc. by the running seperation.
+   The 'next item' is the item directly following the worked item in the Nema data set.
+   Durring item separation it is used to approach to the given (searched) item. But this
+   subject is transperent for a application which works in a level higher as level of
+   function ds_seperate_given_item().
+
+
+   The following table shows a comparision of work and next/this item parameter:
+
+   parameter                parser base              parser current location
+   =========================================================================
+   item group number        WorkKey.GroupNumber      NextKey.GroupNumber
+   item element number      WorkKey.ElementNumber    NextKey.ElementNumber
+   item value length        WorkKey.ValueLength      NextKey.ValueLength
+   begin of item key        -                        BeginOfNextKey
+   begin of item value      BeginOfWorkValue         -
+   end of group
+   containing item          EndOfWorkGroup           EndOfThisGroup
+
+   The work item is the current item used by the separation application but the base of
+   scanning by parser.
+   The next/this item is the item current analyzed by the parser. The parameter 'EndOf-
+   ThisGroup' is not named 'EndOfNextGroup' to avoid confusion during reading source
+   code. The term 'next' discribe not the right situation for this pointer.
+*/
+
+
+/* DECLARATION: declare the NEMA parser pointer list types*/
+
+typedef struct item_key_tag
+{
+  short GroupNumber;					   /* item group number */
+  short ElementNumber;					   /* item element number */
+  long ValueLength;					   /* item value length */
+} item_key_t;
+
+
+typedef struct nema_parser_pointer_list_tag
+{
+  item_key_t WorkKey;					   /* current worked item */
+  item_key_t NextKey;					   /* next item in data set */
+  char *BeginOfWorkValue;				   /* points to first byte of item
+							      value */
+  char *BeginOfNextKey;					   /* points to first byte of next
+							      item key */
+  char *EndOfWorkGroup;					   /* points to first byte of group
+							      following the current worked
+							      group. The last address in this
+							      group is EndOfWorkGroup - 1. */
+  char *EndOfThisGroup;					   /* points to first byte of group
+							      following group containing next
+							      item. The last address in this
+							      group is EndOfThisGroup - 1. */
+  char *BeginOfDataSet;					   /* points to first byte of data
+							      set. */
+  char *EndOfDataSet;					   /* points to first byte behint the
+							      NEMA data set. The last address
+							      in the data set is EndOfDataSet
+							      - 1. The address EndOfDataSet is
+							      not part of the data set. The
+							      pointer is only used as stop
+							      mark during data set parsing.
+							      Don't dereference this pointer
+							      to avoid segmentation fault. */
+} nema_parser_pointer_list_t;
+/*]*/
+
+
+/*==  "Shadow Subgroup Owner List"  ========================================================*/
+
+/*[
+   Description: Entity "Shadow Subgroup Owner List"
+
+   In each odd-numbered group expect the command information shadow group 1, a fixed block
+   of data element numbers is reserved to identify the "ownership" of sets of data elements.
+   The elements 0010'H to 007F'H are reserved to identify the manufacturer sets of elements.
+   Each identifier element (0010'H to 007F'H) is a type 1 free-formatted (FF) single (S)
+   ASCII string (AT) and contains e.g. the OWNER_STRING_SPI (SPI Recognition Code) for blocks
+   of data elements reserved by SPI or the OWNER_STRING_MED for blocks of data elements
+   reserved by Siemens UBMed.
+
+   The shodow subgroup owner list is used to fit subgroup location order in the NEMA data
+   set byte stream to the CMS program separation order without a parser reset at change
+   from one shadow subgroup to the next. This is necessary for higher performance.
+
+   The shadow subgroup owner list is a two-dimensional array. In the first column are stored
+   the subgroup numbers found by function ds_get_subgroup_owner_code() in ascent order as
+   item element base number.
+   In the second column are stored the CMS defined subgroup owner numbers.
+   The last element of the shadow subgroup owner list must be marked with the end of list
+   element END_OF_OWNER_LIST.
+   The length of the list must be equal the number of listed shadow owner strings.
+
+   The following graphic shows the shodow subgroup owner list format and an example for a
+   CMS defined Identifiying Information (0009'H) shodow group:
+
+   OWNER_NUMBERS      SUBGROUP_NUMBERS        'ListCounter'
+   +------------------+------------------+
+   |ItemElementBase   |OwnerNumber       |             0
+   +------------------+------------------+
+   |ItemElementBase   |OwnerNumber       |             1
+   +------------------+------------------+
+   |ItemElementBase   |OwnerNumber       |             2
+   +------------------+------------------+
+   |END_OF_OWNER_LIST |END_OF_OWNER_LIST |             3
+   +------------------+------------------+
+   .....                                              ..
+   +------------------+------------------+
+   |END_OF_OWNER_LIST |END_OF_OWNER_LIST |     MAX_OWNER
+   +------------------+------------------+
+
+   OWNER_NUMBERS      SUBGROUP_NUMBERS       'ListCounter'
+   +------------------+------------------+
+   | 0x1000           |OWNER_NUMBER_SPI_1|             0
+   +------------------+------------------+
+   | 0x1100           |OWNER_NUMBER_MED  |             1
+   +------------------+------------------+
+   | 0x1200           |OWNER_NUMBER_CMS  |             2
+   +------------------+------------------+
+   | 0x1300           |OWNER_NUMBER_LAB  |             3
+   +------------------+------------------+
+   |END_OF_OWNER_LIST |END_OF_OWNER_LIST |             4
+   +------------------+------------------+
+   .....                                              ..
+   +------------------+------------------+
+   |END_OF_OWNER_LIST |END_OF_OWNER_LIST |     MAX_OWNER
+   +------------------+------------------+
+
+
+   With this list it is possible to handle the shadow group flexibility defined in
+   [SPI Image] document 4. This means it is possible to parse a NEMA data set
+   without reset the parser at change from one shadow subgroup to the next.
+*/
+/*]*/
+
+
+/* DECLARATION: declare the supported shodow subgroup owner */
+
+#define OWNER_STRING_ACQU                                              "SIEMENS CM VA0  ACQU"
+#define OWNER_STRING_CMS                                               "SIEMENS CM VA0  CMS "
+#define OWNER_STRING_CT                                                "SIEMENS CT VA0  GEN "
+#define OWNER_STRING_CT_COAD                                           "SIEMENS CT VA0  COAD"
+#define OWNER_STRING_CT_IMA                                            "SIEMENS CT VA0  IMA "
+#define OWNER_STRING_CT_RAW                                            "SIEMENS CT VA0  RAW "
+#define OWNER_STRING_LAB                                               "SIEMENS CM VA0  LAB "
+#define OWNER_STRING_MED                                                       "SIEMENS MED "
+#define OWNER_STRING_MR                                                "SIEMENS MR VA0  GEN "
+#define OWNER_STRING_MR_COAD                                           "SIEMENS MR VA0  COAD"
+#define OWNER_STRING_MR_IMA                                            "SIEMENS MR VA0  IMA "
+#define OWNER_STRING_MR_RAW                                            "SIEMENS MR VA0  RAW "
+#define OWNER_STRING_MR_SPEC                                           "SIEMENS MR VA0  SPEC"
+#define OWNER_STRING_SPI_1                                                   "SPI RELEASE 1 "
+#define OWNER_STRING_SPI_2                                                             "SPI "
+#define OWNER_STRING_SPI_3                                                   "SPI Release 1 "
+#define OWNER_STRING_SPI_4                                               "SPI-VERSION 01.00 "
+#define OWNER_STRING_SPI_5                                                   "SPI_RELEASE_1_"
+
+
+/* NOTE: shodow subgroup owner list */
+/* Don't change the order of the following define-blocks! */
+
+#define PRE                                                                                 0
+#define OWNER_NUMBER_ACQU                                                                   0
+#define OWNER_NUMBER_CMS                                                                    1
+#define OWNER_NUMBER_CT                                                                     2
+#define OWNER_NUMBER_CT_COAD                                                                3
+#define OWNER_NUMBER_CT_IMA                                                                 4
+#define OWNER_NUMBER_CT_RAW                                                                 5
+#define OWNER_NUMBER_LAB                                                                    6
+#define OWNER_NUMBER_MED                                                                    7
+#define OWNER_NUMBER_MR                                                                     8
+#define OWNER_NUMBER_MR_COAD                                                                9
+#define OWNER_NUMBER_MR_IMA                                                                10
+#define OWNER_NUMBER_MR_RAW                                                                11
+#define OWNER_NUMBER_MR_SPEC                                                               12
+#define OWNER_NUMBER_SPI_1                                                                 13
+#define OWNER_NUMBER_SPI_2                                                                 14
+#define OWNER_NUMBER_SPI_3                                                                 15
+#define OWNER_NUMBER_SPI_4                                                                 16
+#define OWNER_NUMBER_SPI_5                                                                 17
+
+
+#define MAX_OWNER                                                                      17 + 2
+#define OWNER_STRING_SPI                                                   OWNER_STRING_SPI_1
+
+#define END_OF_OWNER_LIST                                                                (-1)
+#define OWNER_NUMBERS                                                                       0
+#define SUBGROUP_NUMBERS                                                                    1
+
+typedef long shadow_owner_list_t[MAX_OWNER][2];
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/siemens_to_dicom.c
@@ -0,0 +1,790 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_to_dicom.c
+@DESCRIPTION: File containing routines to read in a Siemens vision internal
+              file and convert it to dicom.
+@METHOD     : 
+@GLOBALS    : 
+@CREATED    : July 8, 1997 (Peter Neelin)
+@MODIFIED   : $Log: siemens_to_dicom.c,v $
+@MODIFIED   : Revision 1.1  2003-08-15 19:52:55  leili
+@MODIFIED   : Initial revision
+@MODIFIED   :
+@MODIFIED   : Revision 1.1  2001/12/31 17:28:34  rhoge
+@MODIFIED   : adding file to repos - now needed for reading .ima files in directly
+@MODIFIED   :
+@MODIFIED   : Revision 1.2  2000/12/17 01:05:24  rhoge
+@MODIFIED   : temporary activation of offset table printing macro
+@MODIFIED   :
+@MODIFIED   : Revision 1.1.1.1  2000/11/30 02:05:54  rhoge
+@MODIFIED   : imported sources to CVS repository on amoeba
+@MODIFIED   :
+ * Revision 1.4  1998/11/16  19:54:15  neelin
+ * Added definitions for SunOS.
+ *
+ * Revision 1.3  1998/11/13  16:02:09  neelin
+ * Modifications to support packed images and asynchronous transfer.
+ *
+ * Revision 1.2  1997/11/04  14:31:30  neelin
+ * *** empty log message ***
+ *
+ * Revision 1.1  1997/08/11  12:50:53  neelin
+ * Initial revision
+ *
+---------------------------------------------------------------------------- */
+
+#ifndef lint
+static char rcsid[]="$Header: /private-cvsroot/minc/conversion/dicomserver_sonata/siemens_to_dicom.c,v 1.1 2003-08-15 19:52:55 leili Exp $";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DS_FUNCTIONS
+#include <ds_include_files.h>
+
+#include <acr_nema.h>
+
+/* Constants */
+#ifndef public
+#  define public
+#endif
+#ifndef private
+#  define private static
+#endif
+#ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define EXIT_FAILURE 1
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET 0
+#endif
+
+#define ACR_IMAGE_GID 0x7fe0
+#define ACR_IMAGE_EID 0x10
+#define SIEMENS_IMAGE_OFFSET (6*1024)
+
+#define WORLD_NDIMS 3
+#define IMAGE_NDIMS 2
+
+/* Macros */
+#define MALLOC(size) ((void *) malloc(size))
+#define FREE(ptr) free(ptr)
+#define REALLOC(ptr, size) ((void *) realloc(ptr, size))
+#define CALLOC(nelem, elsize) ((void *) calloc(nelem, elsize))
+
+/* Conversion functions that are not defined */
+#define create_calculation_mode_t_element NULL
+#define create_compression_code_t_element NULL
+#define create_contrast_t_element NULL
+#define create_data_object_subtype_t_element NULL
+#define create_data_set_subtype_t_element NULL
+#define create_field_of_view_t_element NULL
+#define create_filter_parameter_t_element NULL
+#define create_filter_type_image_t_element NULL
+#define create_filter_type_t_element NULL
+#define create_gate_phase_t_element NULL
+#define create_geometry_t_element NULL
+#define create_gradient_delay_time_t_element NULL
+#define create_image_format_t_element NULL
+#define create_laterality_t_element NULL
+#define create_measurement_mode_t_element NULL
+#define create_object_orientation_t_element NULL
+#define create_object_threshold_t_element NULL
+/* #define create_order_of_slices_t_element NULL */
+#define create_patient_orientation_t_element NULL
+#define create_patient_phase_t_element NULL
+#define create_patient_position_t_element NULL
+#define create_patient_region_t_element NULL
+#define create_pixel_quality_code_t_element NULL
+#define create_pixel_quality_value_t_element NULL
+#define create_reference_t_element NULL
+#define create_rest_direction_t_element NULL
+#define create_rotation_direction_t_element NULL
+#define create_sar_sed_t_element NULL
+#define create_save_code_t_element NULL
+#define create_storage_mode_t_element NULL
+#define create_study_type_t_element NULL
+#define create_target_point_t_element NULL
+#define create_view_direction_t_element NULL
+#define create_window_style_t_element NULL
+
+/* Define element id's */
+DEFINE_ELEMENT(static, ACR_Rows                       , 0x0028, 0x0010, US);
+DEFINE_ELEMENT(static, ACR_Columns                    , 0x0028, 0x0011, US);
+DEFINE_ELEMENT(static, ACR_Flip_angle                 , 0x0018, 0x1314, DS);
+DEFINE_ELEMENT(static, SPI_Flip_angle                 , 0x0019, 0x1260, DS);
+DEFINE_ELEMENT(static, ACR_Series                     , 0x0020, 0x0011, IS);
+DEFINE_ELEMENT(static, ACR_Image_position             , 0x0020, 0x0032, DS);
+DEFINE_ELEMENT(static, ACR_Image_orientation          , 0x0020, 0x0037, DS);
+DEFINE_ELEMENT(static, ACR_Image_location             , 0x0028, 0x0200, IS);
+DEFINE_ELEMENT(static, SPI_Image_position             , 0x0021, 0x1160, DS);
+DEFINE_ELEMENT(static, SPI_Image_row                  , 0x0021, 0x116a, DS);
+DEFINE_ELEMENT(static, SPI_Image_column               , 0x0021, 0x116b, DS);
+DEFINE_ELEMENT(static, ACR_Pixel_spacing              , 0x0028, 0x0030, DS);
+
+
+/* Types */
+typedef Acr_Element (*Create_Element_Function)
+     (int group_id, int element_id, void *data, int length);
+typedef struct {
+   int group_id;
+   int element_id;
+   void *data;
+   Create_Element_Function function;
+   int length;
+} Siemens_header_entry;
+
+/* Functions */
+public Acr_Group siemens_to_dicom(char *filename, int read_image);
+public void update_coordinate_info(Acr_Group group_list);
+private Acr_Element_Id get_elid(int group_id, int element_id, 
+                                Acr_VR_Type vr_code);
+private Acr_Element create_char_element(int group_id, int element_id,
+                                        void *data, int length);
+private Acr_Element create_long_element(int group_id, int element_id,
+                                        void *data, int length);
+private Acr_Element create_short_element(int group_id, int element_id,
+                                         void *data, int length);
+private Acr_Element create_double_element(int group_id, int element_id,
+                                        void *data, int length);
+private Acr_Element create_ds_date_t_element(int group_id, int element_id,
+                                             void *data, int length);
+private Acr_Element create_ds_time_t_element(int group_id, int element_id,
+                                             void *data, int length);
+private Acr_Element create_modality_t_element(int group_id, int element_id,
+                                                 void *data, int length);
+private Acr_Element create_sex_t_element(int group_id, int element_id,
+                                            void *data, int length);
+private Acr_Element create_order_of_slices_t_element(int group_id, 
+						     int element_id,
+						     void *data, int length);
+private Acr_Element create_pixel_size_t_element(int group_id, int element_id,
+                                                void *data, int length);
+private Acr_Element create_windows_t_element(int group_id, int element_id,
+                                             void *data, int length);
+private Acr_Element create_image_location_t_element(int group_id, 
+                                                    int element_id,
+                                                    void *data, int length);
+
+/* Define the table of header values */
+header_t Siemens_header;
+#include <siemens_header_table.h>
+
+/* flag to print offset table, useful in debugging byte pad issues
+   with Linux/sun porting */
+/* #define PRINT_OFFSET_TABLE */
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : siemens_to_dicom
+@INPUT      : filename - name of Siemens internal file
+              read_image - if TRUE, then the image is added to the group list,
+                 otherwise it is not read in.
+@OUTPUT     : (none)
+@RETURNS    : Acr-nema group list containing contents of Siemens file
+@DESCRIPTION: Function to read in a siemens internal format file and
+              store it in an ACR-NEMA group list
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : July 8, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public Acr_Group siemens_to_dicom(char *filename, int read_image)
+{
+   FILE *fp;
+   Siemens_header_entry *entry;
+   Acr_Group group_list;
+   Acr_Element element;
+   long image_size, pixel_size;
+   void *image;
+   double flip_angle;
+
+   short rows_in;
+   short cols_in;
+
+   short rows;
+   short cols;
+
+#ifdef PRINT_OFFSET_TABLE
+   void *header_ptr; /* debug junk */
+   void *data_ptr;   /* debug junk */
+   long offset;       /* debug junk */
+#endif
+
+   /* Open the file */
+   if ((fp = fopen(filename, "r")) == NULL) {
+      (void) fprintf(stderr, "Error opening file %s\n", filename);
+      return NULL;
+   }
+
+   /* Read in the header */
+   if (fread(&Siemens_header, sizeof(Siemens_header), 1, fp) != 1) {
+      (void) fprintf(stderr, "Error reading header in %s\n", filename);
+      (void) fclose(fp);
+      return NULL;
+   }
+
+   /* Get the image if it is needed */
+   if (read_image) {
+
+      /* Figure out how much space we need for the image */
+      pixel_size = 2;
+
+      rows_in = Siemens_header.G28.Pre.Rows;
+      acr_get_short(ACR_BIG_ENDIAN,1, (short *) &rows_in, &rows);
+      cols_in = Siemens_header.G28.Pre.Columns;
+      acr_get_short(ACR_BIG_ENDIAN,1, (short *) &cols_in, &cols);
+
+      /* need to byte swap row/col values if needed */
+
+      image_size = rows*cols;
+
+      image = MALLOC((size_t) pixel_size * image_size);
+
+      /* Read in the image */
+      if (fseek(fp, (long) SIEMENS_IMAGE_OFFSET, SEEK_SET)) {
+         (void) fprintf(stderr, "Error finding image in %s\n", filename);
+         (void) fclose(fp);
+         return NULL;
+      }
+      if (fread(image, pixel_size, image_size, fp) != image_size) {
+         (void) fprintf(stderr, "Error reading image in %s\n", filename);
+         (void) fclose(fp);
+         return NULL;
+      }
+
+   }         /* If read_image */
+
+   /* Close the file */
+   (void) fclose(fp);
+
+   /* Loop through the header table, creating a header */
+   group_list = NULL;
+   for (entry = Siemens_header_table; entry->data != NULL; entry++) {
+
+#ifdef PRINT_OFFSET_TABLE
+     data_ptr = entry->data;
+     header_ptr = &Siemens_header;
+     offset = (long) data_ptr - (long) header_ptr;
+     printf("DEBUG:  group = 0x%x, element = 0x%x, offset = 0x%x, length = 0x%x\n",
+     entry->group_id,entry->element_id,offset,entry->length);
+#endif
+
+     if (entry->function == NULL) {
+       continue;
+     }
+      element = entry->function(entry->group_id, entry->element_id,
+                                entry->data, entry->length);
+      if (element == NULL) {
+	continue;
+      }
+
+      acr_insert_element_into_group_list(&group_list, element);
+   }
+
+   /* Insert flip angle element */
+   element = acr_find_group_element(group_list, SPI_Flip_angle);
+   if (element != NULL) {
+      flip_angle = acr_get_element_numeric(element);
+      if (flip_angle >= 0.0) {
+         acr_insert_numeric(&group_list, ACR_Flip_angle, flip_angle);
+      }
+   }
+
+   /* Insert a series number */
+   acr_insert_numeric(&group_list, ACR_Series, 1.0);
+
+   /* Insert appropriate image position and orientation information */
+   update_coordinate_info(group_list);
+
+
+   /* Add the image if it is needed */
+   if (read_image) {
+
+      /* Insert the image location */
+      acr_insert_short(&group_list, ACR_Image_location, ACR_IMAGE_GID);
+
+      /* Add the image. We don't byte-swap here since it will be done
+         automatically when the data is written out. */
+      element = acr_create_element(ACR_IMAGE_GID, ACR_IMAGE_EID, 
+                                   ACR_VR_OW,
+                                   image_size * pixel_size, image);
+      acr_insert_element_into_group_list(&group_list, element);
+
+      /* explicitly label image data as big-endian */
+      acr_set_element_byte_order(element, ACR_BIG_ENDIAN);
+
+   }        /* If read_image */
+
+   /* Return the group list */
+   return group_list;
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : update_coordinate_info
+@INPUT      : group_list
+@OUTPUT     : group_list
+@RETURNS    : (nothing)
+@DESCRIPTION: Function to modify the DICOM coordinate information to match
+              the Siemens info.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 9, 1998 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void update_coordinate_info(Acr_Group group_list)
+{
+   Acr_Element element;
+   int nrows, ncolumns, idim;
+   double coord[WORLD_NDIMS], row[WORLD_NDIMS], column[WORLD_NDIMS];
+   double pixel_spacing[IMAGE_NDIMS];
+   char string[256];
+
+   /* Look for the row vector */
+   element = acr_find_group_element(group_list, SPI_Image_row);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, WORLD_NDIMS, row) 
+        != WORLD_NDIMS)) {
+      row[0] = 1.0; row[1] = 0.0; row[2] = 0.0;
+   }
+
+   /* Look for the column vector */
+   element = acr_find_group_element(group_list, SPI_Image_column);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, WORLD_NDIMS, column) 
+        != WORLD_NDIMS)) {
+      column[0] = 0.0; column[1] = 1.0; column[2] = 0.0;
+   }
+
+   /* Put in the dicom orientation (patient) field */
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g\\%.15g\\%.15g\\%.15g",
+                  row[0], -row[1], -row[2], 
+                  column[0], -column[1], -column[2]);
+   acr_insert_string(&group_list, ACR_Image_orientation, string);
+
+   /* Look for the position */
+   element = acr_find_group_element(group_list, SPI_Image_position);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, WORLD_NDIMS, coord) 
+        != WORLD_NDIMS)) {
+      coord[0] = 0.0; coord[1] = 0.0; coord[2] = 0.0;
+   }
+
+   /* Get the number of rows and columns */
+   nrows = acr_find_int(group_list, ACR_Rows, 0);
+   ncolumns = acr_find_int(group_list, ACR_Columns, 0);
+   if ((nrows <= 0) || (ncolumns <= 0)) {
+      (void) fprintf(stderr, "Illegal image size in Siemens file\n");
+      exit(EXIT_FAILURE);
+   }
+
+   /* Get the pixel size */
+   element = acr_find_group_element(group_list, ACR_Pixel_spacing);
+   if ((element == NULL) ||
+       (acr_get_element_numeric_array(element, IMAGE_NDIMS, pixel_spacing) 
+        != IMAGE_NDIMS)) {
+      pixel_spacing[0] = pixel_spacing[1] = 1.0;
+   }
+
+   /* Calculate the position of the first pixel. This coordinate is still in 
+      the Siemens space, not dicom space and will need to be flipped. Note 
+      that ncolumns is used with row, since they are the size and unit 
+      vector of the same dimension. */
+   for (idim = 0; idim < WORLD_NDIMS; idim++) {
+      coord[idim] -= 
+         pixel_spacing[0] * ((double) ncolumns - 1.0) / 2.0 * row[idim] +
+         pixel_spacing[1] * ((double) nrows - 1.0) / 2.0 * column[idim];
+   }
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g",
+                  coord[0], -coord[1], -coord[2]);
+   acr_insert_string(&group_list, ACR_Image_position, string);
+
+}
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : create_<type>_element
+@INPUT      : group_id
+              element_id
+              data - pointer to data in Siemens header
+              length - number of values in array (if appropriate)
+@OUTPUT     : (none)
+@RETURNS    : New element containing data
+@DESCRIPTION: Series of functions to convert Siemens vision header types
+              to ACR-NEMA elements
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : July 8, 1997 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+
+private Acr_Element_Id get_elid(int group_id, int element_id, 
+                                Acr_VR_Type vr_code)
+{
+   static struct Acr_Element_Id elid_struct = {0, 0, ACR_VR_UNKNOWN};
+   elid_struct.group_id = group_id;
+   elid_struct.element_id = element_id;
+   elid_struct.vr_code = vr_code;
+   return &elid_struct;
+}
+
+private Acr_Element create_char_element(int group_id, int element_id,
+                                        void *data, int length)
+/* ARGSUSED */
+{
+   char *old, *new;
+   int oldsize, newsize, i;
+
+   /* Get a pointer to the old string */
+   old = (char *) data;
+
+   /* Figure out the length of the new string up to the first NUL. Make 
+      sure that there is a room for an additional NUL if necessary */
+   for (i=0; (i < length-1) && (old[i] != '\0'); i++) {}
+   newsize = ((old[i] == '\0') ? i+1 : length + 1);
+   oldsize = newsize - 1;
+   if ((newsize % 2) != 1) newsize++;
+
+   /* Copy the string, making sure that there is a NUL on the end */
+   new = MALLOC(newsize);
+   for (i=0; i < newsize-1; i++) {
+      if (i < oldsize)
+         new[i] = old[i];
+      else
+         new[i] = ' ';
+   }
+   new[newsize-1] = '\0';
+
+   /* Create the element */
+   return acr_create_element(group_id, element_id, ACR_VR_ST, 
+                             (long) newsize-1, (void *) new);
+}
+
+private Acr_Element create_long_element(int group_id, int element_id,
+                                        void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+  long data_out;
+
+  acr_get_long(ACR_BIG_ENDIAN,1, data, &data_out);
+
+   return acr_create_element_numeric
+      (get_elid(group_id, element_id, ACR_VR_IS), 
+       (long) data_out); 
+}
+
+private Acr_Element create_short_element(int group_id, int element_id,
+                                         void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+  unsigned short data_out;
+
+  acr_get_short(ACR_BIG_ENDIAN,1, data, &data_out);
+
+  return acr_create_element_short
+    (get_elid(group_id, element_id, ACR_VR_US), 
+     (unsigned short) data_out);
+}
+
+private Acr_Element create_double_element(int group_id, int element_id,
+                                        void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+  double data_out;
+  
+  acr_get_double(ACR_BIG_ENDIAN,1, data, &data_out);
+
+   return acr_create_element_numeric
+     (get_elid(group_id, element_id, ACR_VR_DS), (double) data_out);
+}
+
+private Acr_Element create_ds_date_t_element(int group_id, int element_id,
+                                             void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+   char string[20];
+   ds_date_t *ptr;
+
+   long year;
+   long month;
+   long day;
+
+   long year_in;
+   long month_in;
+   long day_in;
+
+   ptr = (ds_date_t *) data;
+
+   year_in = ptr->Year;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &year_in, &year); 
+	
+   month_in = ptr->Month;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &month_in, &month);
+	
+   day_in = ptr->Day;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &day_in, &day);
+
+   if ((year < 0) || (year > 9999)) return NULL;
+   if ((month < 0) || (month > 12)) return NULL;
+   if ((day < 0) || (day > 40)) return NULL;
+   (void) sprintf(string, "%04d%02d%02d", 
+                  (int) year, (int) month, (int) day);
+
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_DA), string);
+}
+
+private Acr_Element create_ds_time_t_element(int group_id, int element_id,
+                                             void *data, int length)
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+   char string[20];
+   ds_time_t *ptr;
+
+   long hour;
+   long minute;
+   long second;
+   long fraction;
+
+   long hour_in;
+   long minute_in;
+   long second_in;
+   long fraction_in;
+
+   ptr = (ds_time_t *) data;
+   hour_in = ptr->Hour;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &hour_in, &hour); 
+   minute_in = ptr->Minute;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &minute_in, &minute); 
+   second_in = ptr->Second;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &second_in, &second); 
+   fraction_in = ptr->Fraction;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &fraction_in, &fraction); 
+   if ((hour < 0) || (hour > 24)) return NULL;
+   if ((minute < 0) || (minute > 60)) return NULL;
+   if ((second < 0) || (second > 60)) return NULL;
+   if ((fraction < 0) || (fraction > 999)) return NULL;
+   (void) sprintf(string, "%02d%02d%02d.%03d", hour, minute, second, fraction);
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_TM), string);
+}
+
+private Acr_Element create_modality_t_element(int group_id, int element_id,
+                                                 void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+   char *string;
+   modality_t *ptr_in;
+   modality_t modality;
+   /*   modality_t *ptr; */
+
+   /* Get the appropriate string */
+
+   ptr_in = (modality_t *) data;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) ptr_in, (long *) &modality); 
+
+   switch (modality) {
+   case Modality_CT:
+      string = "CT";
+      break;
+   case Modality_MR:
+      string = "MR";
+      break;
+   default:
+      return NULL;
+   }
+
+   /* Return a new element */
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_CS), string);
+}
+
+private Acr_Element create_sex_t_element(int group_id, int element_id,
+                                            void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+/* ARGSUSED */
+{
+   char *string;
+   sex_t *ptr_in;
+   sex_t sex;
+
+   /* Get the appropriate string */
+   ptr_in = (sex_t *) data;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) ptr_in, (long *) &sex); 
+   switch (sex) {
+   case Sex_F:
+      string = "F ";
+      break;
+   case Sex_M:
+      string = "M ";
+      break;
+   case Sex_O:
+      string = "O ";
+      break;
+   default:
+      return NULL;
+   }
+
+   /* Return a new element */
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_CS), string);
+}
+
+private Acr_Element create_order_of_slices_t_element(int group_id, 
+						   int element_id,
+						   void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+/* ARGSUSED */
+{
+   char *string;
+   order_of_slices_t *ptr_in;
+   order_of_slices_t order_of_slices;
+
+   /* Get the appropriate string */
+   ptr_in = (order_of_slices_t *) data;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) ptr_in, (long *) &order_of_slices); 
+   switch (order_of_slices) {
+   case Slice_Order_ASCENDING:
+      string = "ASCENDING ";
+      break;
+   case Slice_Order_DECREASING:
+      string = "DESCENDING ";
+      break;
+   case Slice_Order_INTERLEAVED:
+      string = "INTERLEAVED ";
+      break;
+   case Slice_Order_NONE:
+      string = "NONE ";
+      break;
+   case Slice_Order_UNDEFINED:
+      string = "UNDEFINED ";
+      break;
+   default:
+      return NULL;
+   }
+
+   /* Return a new element */
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_CS), string);
+}
+
+private Acr_Element create_pixel_size_t_element(int group_id, int element_id,
+                                                void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+   pixel_size_t *ptr;
+   char string[64];
+
+   double row_in;
+   double col_in;
+
+   double row;
+   double col;
+
+   /* Get the pixel sizes */
+   ptr = (pixel_size_t *) data;
+
+   row_in = ptr->Row;
+   acr_get_double(ACR_BIG_ENDIAN,1, (double *) &row_in, &row); 
+   col_in = ptr->Col;
+   acr_get_double(ACR_BIG_ENDIAN,1, (double *) &col_in, &col); 
+
+   (void) sprintf(string, "%.15g\\%.15g", row, col);
+
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_DS), string);
+}
+
+private Acr_Element create_windows_t_element(int group_id, int element_id,
+                                             void *data, int length)
+
+/* modified by rhoge to byte swap if needed */
+
+/* ARGSUSED */
+{
+   windows_t *ptr;
+   char string[64];
+
+   long x_in;
+   long y_in;
+
+   long x;
+   long y;
+
+   /* Get the window info */
+   ptr = (windows_t *) data;
+
+   x_in = ptr->X;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &x_in, &x); 
+   y_in = ptr->Y;
+   acr_get_long(ACR_BIG_ENDIAN,1, (long *) &y_in, &y); 
+
+   (void) sprintf(string, "%ld\\%ld", x, y);
+
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_IS), string);
+}
+
+private Acr_Element create_image_location_t_element(int group_id, 
+                                                    int element_id,
+                                                    void *data, int length)
+/* modified by rhoge to byte swap if needed */
+/* ARGSUSED */
+{
+   image_location_t *ptr;
+   char string[64];
+
+   double sag;
+   double cor;
+   double tra;
+
+   double sag_in;
+   double cor_in;
+   double tra_in;
+
+   /* Get the coordinate */
+   ptr = (image_location_t *) data;
+   
+   sag_in = ptr->Sag;
+   acr_get_double(ACR_BIG_ENDIAN,1, (double *) &sag_in, &sag); 
+   cor_in = ptr->Cor;
+   acr_get_double(ACR_BIG_ENDIAN,1, (double *) &cor_in, &cor); 
+   tra_in = ptr->Tra;
+   acr_get_double(ACR_BIG_ENDIAN,1, (double *) &tra_in, &tra); 
+
+   (void) sprintf(string, "%.15g\\%.15g\\%.15g", sag, cor, tra);
+
+   return acr_create_element_string
+      (get_elid(group_id, element_id, ACR_VR_DS), string);
+}
+
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/spi_element_defs.h
@@ -0,0 +1,86 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : spi_element_defs.h
+@DESCRIPTION: Element definitions for spi
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 23, 1993 (Peter Neelin)
+@MODIFIED   : 
+@COPYRIGHT  :
+              Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+/* Define siemens-specific stuff for associations and messages */
+#define SPI_VISION_AE_TITLE "MRC16505"  /* changed by Leili from OC1SA1MR010000 to MRC16505 */
+#define SPI_VISION_IMPLEMENTATION_UID "1.3.12.2.1107.5.2" /* Chaged by leili from 2.16.840.1.113669.2.931128 to 1.3.12.2.1107.5.2 */
+
+/* Element number for images */
+#define SPI_IMAGE_ELEMENT 0x0010
+
+/* Define spi constants */
+#define SPI_TRANSVERSE_ORIENTATION 1
+#define SPI_SAGITTAL_ORIENTATION   2
+#define SPI_CORONAL_ORIENTATION    3
+
+/* Element id's for SPI */
+GLOBAL_ELEMENT(SPI_Acquisition_columns                , 0x0019, 0x1230, LO);
+GLOBAL_ELEMENT(SPI_Reconstruction_columns             , 0x0019, 0x1231, LO);
+GLOBAL_ELEMENT(SPI_Sequence_file_name                 , 0x0019, 0x1511, LO);
+GLOBAL_ELEMENT(SPI_Image_position                     , 0x0021, 0x1160, DS);
+GLOBAL_ELEMENT(SPI_Image_normal                       , 0x0021, 0x1161, DS);
+GLOBAL_ELEMENT(SPI_Image_row                          , 0x0021, 0x116a, DS);
+GLOBAL_ELEMENT(SPI_Image_column                       , 0x0021, 0x116b, DS);
+GLOBAL_ELEMENT(SPI_Number_of_3D_raw_partitions_nominal, 0x0021, 0x1330, IS);
+GLOBAL_ELEMENT(SPI_Number_of_3D_image_partitions      , 0x0021, 0x1334, IS);
+GLOBAL_ELEMENT(SPI_Actual_3D_partition_number         , 0x0021, 0x1336, IS);
+GLOBAL_ELEMENT(SPI_Number_of_slices_nominal           , 0x0021, 0x1340, IS);
+GLOBAL_ELEMENT(SPI_Current_slice_number               , 0x0021, 0x1342, IS);
+GLOBAL_ELEMENT(SPI_Number_of_echoes                   , 0x0021, 0x1370, IS);
+
+// added by rhoge:
+GLOBAL_ELEMENT(SPI_Registration_date     , 0x0011, 0x1110, DA);
+GLOBAL_ELEMENT(SPI_Registration_time     , 0x0011, 0x1111, TM);
+GLOBAL_ELEMENT(SPI_Parameter_file_name   , 0x0019, 0x1510, CS);
+GLOBAL_ELEMENT(SPI_Protocol              , 0x0029, 0x1020, CS);
+
+// (these appear to be public groups, and should be moved 
+//  to dicom_element_defs.h ? )
+GLOBAL_ELEMENT(SPI_Manufacturer          , 0x0008, 0x0070, CS);
+GLOBAL_ELEMENT(SPI_Manufacturer_model    , 0x0008, 0x1090, CS);
+GLOBAL_ELEMENT(SPI_Device_serial_number  , 0x0018, 0x1000, CS);
+GLOBAL_ELEMENT(SPI_Software_version      , 0x0018, 0x1020, CS);
+GLOBAL_ELEMENT(SPI_Receiving_coil        , 0x0018, 0x1250, CS);
+
+GLOBAL_ELEMENT(SPI_Calibration_date                   , 0x0018, 0x1200, DA);
+GLOBAL_ELEMENT(SPI_Total_measurement_time_cur         , 0x0019, 0x1211, DS);
+GLOBAL_ELEMENT(SPI_Nominal_number_of_fourier_lines    , 0x0019, 0x1220, IS);
+GLOBAL_ELEMENT(SPI_Number_of_fourier_lines_current    , 0x0019, 0x1221, IS);
+GLOBAL_ELEMENT(SPI_Number_of_fourier_lines_after_zero , 0x0019, 0x1226, IS);
+GLOBAL_ELEMENT(SPI_Number_of_3d_raw_part_cur          , 0x0021, 0x1331, IS);
+GLOBAL_ELEMENT(SPI_Order_of_slices                    , 0x0021, 0x134f, IS);
+GLOBAL_ELEMENT(SPI_First_measured_fourier_line        , 0x0019, 0x1228, IS);
+GLOBAL_ELEMENT(SPI_Number_of_prescans                 , 0x0019, 0x1270, IS);
+GLOBAL_ELEMENT(SPI_Magnetic_field_strength            , 0x0019, 0x1412, DS);
+GLOBAL_ELEMENT(SPI_ADC_voltage                        , 0x0019, 0x1414, DS);
+GLOBAL_ELEMENT(SPI_ADC_offset                         , 0x0019, 0x1416, DS);
+GLOBAL_ELEMENT(SPI_Transmitter_amplitude              , 0x0019, 0x1420, DS);
+GLOBAL_ELEMENT(SPI_Receiver_amplifier_gain            , 0x0019, 0x1451, DS);
+GLOBAL_ELEMENT(SPI_Receiver_preamplifier_gain         , 0x0019, 0x1452, DS);
+GLOBAL_ELEMENT(SPI_Phase_gradient_amplitude           , 0x0019, 0x1470, DS);
+GLOBAL_ELEMENT(SPI_Readout_gradient_amplitude         , 0x0019, 0x1471, DS);
+GLOBAL_ELEMENT(SPI_Selection_gradient_amplitude       , 0x0019, 0x1472, DS);
+GLOBAL_ELEMENT(SPI_Sequence_file_owner                , 0x0019, 0x1512, CS);
+GLOBAL_ELEMENT(SPI_Sequence_description               , 0x0019, 0x1513, CS);
+GLOBAL_ELEMENT(SPI_Number_of_slices_cur               , 0x0021, 0x1341, IS);
+GLOBAL_ELEMENT(SPI_Window_center                      , 0x0028, 0x1050, IS);
+GLOBAL_ELEMENT(SPI_Window_width                       , 0x0028, 0x1051, IS);
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/string_to_filename.c
@@ -0,0 +1,312 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : string_to_filename.c
+@DESCRIPTION: Code to convert a string to something that can be used in a 
+              file name.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 10, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: string_to_filename.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.2  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:52:00  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <dicomserver.h>
+#include <ctype.h>
+
+#define SEPARATOR '_'
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : string_to_filename
+@INPUT      : string - string to convert
+              maxlen - maximum length of output string (including terminating
+                 '\0')
+@OUTPUT     : filename - output string
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to convert a string to something that can be used in
+              a filename
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : December 10, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void string_to_filename(char *string, char *filename, int maxlen)
+{
+   int length, isrc, idst;
+   int ch;
+   int found_first, need_separator;
+
+   /* Get string length */
+   length = strlen(string);
+   if (length > maxlen-1) length = maxlen - 1;
+
+   /* Loop through characters */
+   idst = 0;
+   found_first = FALSE;
+   need_separator = FALSE;
+   for (isrc=0; isrc < length; isrc++) {
+      ch = string[isrc];
+      if (isalnum(ch)) {
+         found_first = TRUE;
+         if (need_separator) {
+            filename[idst++] = SEPARATOR;
+            need_separator = FALSE;
+         }
+         filename[idst++] = tolower(ch);
+      }
+      else if (found_first) {
+         need_separator = TRUE;
+      }
+   }
+
+   /* Add terminating '\0' */
+   filename[idst++] = '\0';
+
+   return;
+}
+
+public void string_to_initials(char *string, char *filename, int maxlen)
+{
+  /* function added by R. Hoge to convert name-like strings to
+     initials in environment where confidentiality policy prohibits
+     use of names in file-names */
+
+   int length, isrc, idst;
+   int ch;
+   int first_found, sep_found, multi_word, comma_found, comma_found2, in_word;
+
+   /* Get string length */
+   length = strlen(string);
+   if (length > maxlen-1) length = maxlen - 1;
+
+   /* do first pass to look for multi-words, commas */
+
+   first_found = FALSE;
+   sep_found = FALSE;
+   multi_word = FALSE;
+   comma_found = FALSE;
+
+   for (isrc=0; isrc < length; isrc++) {
+      ch = string[isrc];
+
+      /* if we hit a separator after finding a first alphanum, treat
+	 as multi words */
+
+      /* alphanumeric expressions (including underscores, hyphens) are treated 
+	 as discrete words - note that we won't print hyphens */
+
+      /* examples of single words:
+
+  	   test5
+	   test-5
+	   test_5
+
+	 examples of multi words:
+
+	   test 5
+	   snr_test 5
+	   test,5
+	   snr-test 5
+
+       */
+
+      if (sep_found && isalnum(ch)) {
+	multi_word = TRUE;
+      }
+      
+      if (first_found && !(isalnum(ch)||ch=='-'||ch=='_')) {
+	sep_found = TRUE;
+      }
+
+      if (isalnum(ch)) {
+	first_found = TRUE;
+      }
+
+      // Numaris 4 used caret (^) to separate names (Last^first)
+      if (ch == ',' || ch == '^') {
+	comma_found = TRUE;
+      }
+   }
+
+   /* if Patient name is only a single word, then just strip out
+      non-alphanumeric characters 
+
+      examples:  
+
+      snrtest1   -> snrtest1
+      snrtest-1  -> snrtest1
+      snr_test-2 -> snr_test2
+
+      note that hyphens are omitted, because these
+      are used as delimiters in filename */
+
+   if (!multi_word) {
+
+     idst = 0;
+     for (isrc=0; isrc < length; isrc++) {
+       ch = string[isrc];
+       
+       if (isalnum(ch) || ch=='_') {
+         filename[idst++] = tolower(ch);
+       }
+     }
+
+     /* Add terminating '\0' */
+     filename[idst++] = '\0';
+     
+   } else { /* multiple words */
+     
+     if (!comma_found) {
+
+       /* examples of multi-word no comma:  
+
+	  john doe        -> jd
+	  john edward doe -> jed
+	  john doe-smith  -> jds
+	  my snr_test     -> mst 
+	  john doe 12     -> jd12
+	  john12 smith    -> j12s
+	  12john smith    -> 12js
+	  john doe test2b -> jst2b
+
+	  note that underscores are treated as separators here,
+          contiguous digits are all printed, and digits
+          are treated as printable separators */
+
+       /* Loop through characters */
+       idst = 0;
+       in_word = FALSE;
+       for (isrc=0; isrc < length; isrc++) {
+	 ch = string[isrc];
+	 if (isalpha(ch) && !in_word) {
+	   in_word = TRUE;
+	   filename[idst++] = tolower(ch);
+	 }
+	 else if (isdigit(ch)) {
+	   in_word = FALSE;
+	   filename[idst++] = ch;
+	 }
+	 else if (!isalnum(ch)) {
+	   in_word = FALSE;
+	 }
+       }
+       
+       /* Add terminating '\0' */
+       filename[idst++] = '\0';
+     
+     } else { /* multiple words with comma separation */
+
+       /* examples of multi-word with comma:  
+
+	  doe, john       -> jd
+	  doe,john        -> jd
+	  doe-smith, john -> jds
+
+	  note that we treat stuff before the comma as the LAST name */
+
+       /* we do two passes:  all the stuff after the comma THEN 
+	  all the stuff before the comma */
+
+       idst = 0;
+
+       /* Loop through characters, writing those after comma*/
+
+       comma_found2 = FALSE;
+       in_word = FALSE;
+       for (isrc=0; isrc < length; isrc++) {
+	 ch = string[isrc];
+
+	 if (isalpha(ch) && !in_word) {
+	   in_word = TRUE;
+	   if (comma_found2) filename[idst++] = tolower(ch);
+	 }
+	 else if (isdigit(ch)) {
+	   in_word = FALSE;
+	   if (comma_found2) filename[idst++] = ch;
+	 }
+	 else if (!isalnum(ch)) {
+	   in_word = FALSE;
+	 }
+
+	 // numaris 4 uses Last^First
+	 if (ch == ',' || ch == '^') {
+	   comma_found2 = TRUE;
+	 }
+       }
+
+       /* now write characters/initials before the comma*/
+       
+       comma_found2 = FALSE;
+       in_word = FALSE;
+       for (isrc=0; isrc < length; isrc++) {
+	 ch = string[isrc];
+
+	 if (isalpha(ch) && !in_word) {
+	   in_word = TRUE;
+	   if (!comma_found2) filename[idst++] = tolower(ch);
+	 }
+	 else if (isdigit(ch)) {
+	   in_word = FALSE;
+	   if (!comma_found2) filename[idst++] = ch;
+	 }
+	 else if (!isalnum(ch)) {
+	   in_word = FALSE;
+	 }
+
+	 // Numaris 4 uses Last^First
+	 if (ch == ',' || ch == '^') {
+	   comma_found2 = TRUE;
+	 }
+       }
+       
+       /* Add terminating '\0' */
+       filename[idst++] = '\0';
+     
+     }
+   }
+
+   return;
+}
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/use_the_files.c
@@ -0,0 +1,297 @@
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : use_the_files.c
+@DESCRIPTION: Code to do something with the files copied through dicom.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : January 28, 1997 (Peter Neelin)
+@MODIFIED   : 
+ * $Log: use_the_files.c,v $
+ * Revision 1.1  2003-08-15 19:52:55  leili
+ * Initial revision
+ *
+ * Revision 1.8  2002/04/26 03:27:03  rhoge
+ * fixed MrProt problem - replaced fixed lenght char array with malloc
+ *
+ * Revision 1.7  2002/03/22 19:19:36  rhoge
+ * Numerous fixes -
+ * - handle Numaris 4 Dicom patient name
+ * - option to cleanup input files
+ * - command option
+ * - list-only option
+ * - debug mode
+ * - user supplied name, idstr
+ * - anonymization
+ *
+ * Revision 1.6  2002/03/19 22:10:16  rhoge
+ * removed time sorting for N4DCM mosaics - time is random for mosaics
+ *
+ * Revision 1.5  2001/12/31 18:27:21  rhoge
+ * modifications for dicomreader processing of Numaris 4 dicom files - at
+ * this point code compiles without warning, but does not deal with
+ * mosaiced files.  Also will probably not work at this time for Numaris
+ * 3 .ima files.  dicomserver may also not be functional...
+ *
+ * Revision 1.4  2001/04/19 19:09:04  rhoge
+ * added macro to turn off echos/frames in one file
+ *
+ * Revision 1.3  2001/02/26 06:16:00  rhoge
+ * modified to allow specification of destination directory on command line
+ *
+ * Revision 1.2  2000/12/11 17:44:49  rhoge
+ * added 1 to indices in debugging statements for consistency with number
+ * of elements
+ *
+ * Revision 1.1.1.1  2000/11/30 02:13:15  rhoge
+ * imported sources to CVS repository on amoeba
+ *
+ * Revision 6.1  1999/10/29 17:52:00  neelin
+ * Fixed Log keyword
+ *
+ * Revision 6.0  1997/09/12 13:24:27  neelin
+ * Release of minc version 0.6
+ *
+ * Revision 5.0  1997/08/21  13:25:26  neelin
+ * Release of minc version 0.5
+ *
+ * Revision 4.0  1997/05/07  20:06:20  neelin
+ * Release of minc version 0.4
+ *
+ * Revision 1.2  1997/03/11  13:10:48  neelin
+ * Working version of dicomserver.
+ *
+ * Revision 1.1  1997/03/04  20:56:47  neelin
+ * Initial revision
+ *
+@COPYRIGHT  :
+              Copyright 1997 Peter Neelin, McConnell Brain Imaging Centre, 
+              Montreal Neurological Institute, McGill University.
+              Permission to use, copy, modify, and distribute this
+              software and its documentation for any purpose and without
+              fee is hereby granted, provided that the above copyright
+              notice appear in all copies.  The author and McGill University
+              make no representations about the suitability of this
+              software for any purpose.  It is provided "as is" without
+              express or implied warranty.
+---------------------------------------------------------------------------- */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <dicomserver.h>
+
+/* Function prototypes */
+/* Commented out by rhoge, put back in by Leili */
+//int gethostname (char *name, size_t namelen); 
+
+File_Type file_type;
+char command_line[512];
+char *pname;
+
+/* ----------------------------- MNI Header -----------------------------------
+@NAME       : use_the_files
+@INPUT      : project_name - name to use for project file
+              num_files - number of image files
+              file_list - list of file names
+	      UseArgDir - flag to use command line OutDir destination
+	      OutDir - destination directory
+@OUTPUT     : (none)
+@RETURNS    : (nothing)
+@DESCRIPTION: Routine to do something with the files.
+@METHOD     : 
+@GLOBALS    : 
+@CALLS      : 
+@CREATED    : November 23, 1993 (Peter Neelin)
+@MODIFIED   : 
+---------------------------------------------------------------------------- */
+public void use_the_files(char *project_name,
+                          int num_files, char *file_list[], 
+                          Data_Object_Info *data_info[],
+			  int UseArgDir,char *OutDir)
+     /* last three args added by rhoge */
+{
+   int ifile;
+   int num_acq_files;
+   extern int Do_logging;
+   char **acq_file_list;
+   int *used_file;
+   int found_first;
+   double cur_study;
+   int cur_acq;
+   int cur_rec;
+   int cur_imgtyp;
+   int cur_echo;
+   int cur_dyn_scan;
+   int echoes_in_one_file;
+   int dyn_scans_in_one_file;
+   int exit_status;
+   char *output_file_name;
+   char file_prefix[256];
+   int output_uid, output_gid;
+   char string[512];
+   FILE *fp;
+   (void) fprintf(stderr, "The pname is: %s\n", pname);
+   /* The if statment commented out by Leili forcing the old-style project_file to be used since it is invoked by the server*/ 
+   //if (!strncmp(pname,"dicomserver",11)) {
+     // use old-style project_file if invoked by server
+     (void) read_project_file(project_name, file_prefix, 
+			      &output_uid, &output_gid,
+			      command_line, (int) sizeof(command_line));
+     //}
+
+   if (UseArgDir) { // if an output directory name has been 
+                    // provided on the command line
+     //(void) fprintf(stderr, "The output directory name has been provided \n");
+     strcpy(file_prefix,OutDir);
+   } else if (!strncmp(project_name,"/",1)) { // AEtitle is destination
+     //(void) fprintf(stderr, "The output directory is the one specified in the AEtitle \n");
+     strcpy(file_prefix,project_name);
+   }
+
+   if (Do_logging > HIGH_LOGGING) { // debugging
+     fprintf(stderr,
+	     "project_name:  [%s]    file_prefix:  [%s]\n",
+	     project_name,file_prefix);
+   }
+
+   // Allocate space for acquisition file list
+   acq_file_list = MALLOC(num_files * sizeof(*acq_file_list));
+   used_file = MALLOC(num_files * sizeof(*used_file));
+   for (ifile=0; ifile < num_files; ifile++)
+      used_file[ifile] = FALSE;
+
+   do {
+
+     // Loop through files, looking for an acquisition
+
+     // file groups should already have been sorted into acquisitions
+     // in calling program 
+
+     // this code is in a `do while' loop because we may 
+
+     found_first = FALSE;
+     num_acq_files = 0;
+     for (ifile=0; ifile < num_files; ifile++) {
+       
+       if (used_file[ifile]) continue;
+       if (!found_first) {
+	 
+	 /* found first file:  set all current attributes like
+	    study id, acq id, rec num(?), image type, echo number,
+	    dyn scan number, flag for multiple echoes, flag for
+	    multiple time points the flag input file as `used' */ 
+	 
+	 found_first = TRUE;
+	 cur_study = data_info[ifile]->study_id;
+	 cur_acq = data_info[ifile]->acq_id;
+	 cur_rec = data_info[ifile]->rec_num;
+	 cur_imgtyp = data_info[ifile]->image_type;
+	 cur_echo = data_info[ifile]->echo_number;
+	 cur_dyn_scan = data_info[ifile]->dyn_scan_number;
+
+	 /* note that if there are only two echos OR only two time
+	    points, we turn off dyn_scans_in_one_file on the
+	    presumption that the user is more likely to treat them
+	    as separate acquisitions than a scan with a time
+	    dimension (turned off!!) */
+	 
+#define MIN_FRAMES_PER_FILE 1
+	 
+	 echoes_in_one_file = 
+	   (data_info[ifile]->num_echoes > MIN_FRAMES_PER_FILE);
+	 dyn_scans_in_one_file = 
+	   (data_info[ifile]->num_dyn_scans > MIN_FRAMES_PER_FILE);
+	 
+	 used_file[ifile] = TRUE;
+       }
+       
+       /* otherwise check if attributes of the new input file match those
+	  of the current output context and flag input file as `used' */
+       
+       else if ((data_info[ifile]->study_id == cur_study) &&
+		(data_info[ifile]->acq_id == cur_acq) &&
+		(data_info[ifile]->rec_num == cur_rec) &&
+		(data_info[ifile]->image_type == cur_imgtyp) &&
+		((data_info[ifile]->echo_number == cur_echo) ||
+		 echoes_in_one_file) &&
+		((data_info[ifile]->dyn_scan_number == cur_dyn_scan) ||
+		 dyn_scans_in_one_file)) {
+
+	 used_file[ifile] = TRUE;
+       }
+       if (used_file[ifile]) {
+	 
+	 /* if input file is flagged as `used', then add its index
+	    to the list of files for this acquisition (and increment
+	    counter) */
+
+	 acq_file_list[num_acq_files] = file_list[ifile];
+	 num_acq_files++;
+       }
+     } // rhoge: end of loop over files
+     
+     // Use the files for this acquisition
+     
+     if (found_first) {
+       
+       // Print out the file names 
+       if (Do_logging >= HIGH_LOGGING) {
+	 (void) fprintf(stderr, "\nFiles copied:\n");
+	 for (ifile=0; ifile < num_acq_files; ifile++) {
+	   (void) fprintf(stderr, "     %s\n", acq_file_list[ifile]);
+	 }
+       }
+
+       // Create minc file
+       exit_status = siemens_dicom_to_minc(num_acq_files, acq_file_list, 
+					   NULL, FALSE, file_prefix, 
+					   &output_file_name);
+
+       if (exit_status != EXIT_SUCCESS) continue;
+       
+       /* Print log message */
+       if (Do_logging >= LOW_LOGGING) {
+	 (void) fprintf(stderr, "Created minc file %s.\n",
+			output_file_name);
+       }
+       
+       /* Invoke a command on the file (if requested) and get the 
+	  returned file name */
+       if (strlen(command_line) > (size_t) 0) {
+	 (void) sprintf(string, "%s %s", command_line, output_file_name);
+	 printf("-Applying command '%s' to output file...  ",command_line);
+	 (void) fflush(stdout);
+	 if ((fp=popen(string, "r")) != NULL) {
+	   (void) fscanf(fp, "%s", output_file_name);
+	   if (pclose(fp) != EXIT_SUCCESS) {
+	     (void) fprintf(stderr, 
+			    "Error executing command\n   \"%s\"\n",
+			    string);
+	   }
+	   else if (Do_logging >= LOW_LOGGING) {
+	     (void) fprintf(stderr, 
+			    "Executed command \"%s\",\nproducing file %s.\n",
+			    string, output_file_name);
+	   }
+	 }
+	 else {
+	   (void) fprintf(stderr, "Error executing command \"%s\"\n",
+			  string);
+	 }
+	 printf("Done.\n");
+       }
+       
+       /* Change the ownership */
+       if ((output_uid != INT_MIN) && (output_gid != INT_MIN)) {
+	 (void) chown(output_file_name, (uid_t) output_uid,
+		      (gid_t) output_gid);
+       }
+     }
+   } while (found_first);
+   
+   /* Free acquisition file list */
+   FREE(acq_file_list);
+   FREE(used_file);
+
+}
+
+
new file mode 100644
--- /dev/null
+++ b/conversion/dicomserver_sonata/valid_element_ids
@@ -0,0 +1,280 @@
+0x0008  0x0000
+0x0008  0x0008
+0x0008  0x0016
+0x0008  0x0018
+0x0008  0x0020
+0x0008  0x0022
+0x0008  0x0023
+0x0008  0x0030
+0x0008  0x0032
+0x0008  0x0033
+0x0008  0x0040
+0x0008  0x0041
+0x0008  0x0050
+0x0008  0x0060
+0x0008  0x0070
+0x0008  0x0080
+0x0008  0x0090
+0x0008  0x1010
+0x0008  0x1080
+0x0008  0x1090
+0x0009  0x0000
+0x0009  0x0010
+0x0009  0x0012
+0x0009  0x0013
+0x0009  0x1010
+0x0009  0x1015
+0x0009  0x1040
+0x0009  0x1041
+0x0009  0x1210
+0x0009  0x1226
+0x0009  0x1227
+0x0009  0x1316
+0x0009  0x1320
+0x0010  0x0000
+0x0010  0x0010
+0x0010  0x0020
+0x0010  0x0030
+0x0010  0x0040
+0x0010  0x1010
+0x0010  0x1030
+0x0011  0x0000
+0x0011  0x0010
+0x0011  0x0011
+0x0011  0x110a
+0x0011  0x1110
+0x0011  0x1111
+0x0011  0x1122
+0x0011  0x1123
+0x0018  0x0000
+0x0018  0x0010
+0x0018  0x0020
+0x0018  0x0021
+0x0018  0x0022
+0x0018  0x0023
+0x0018  0x0024
+0x0018  0x0025
+0x0018  0x0050
+0x0018  0x0080
+0x0018  0x0081
+0x0018  0x0083
+0x0018  0x0084
+0x0018  0x0085
+0x0018  0x0086
+0x0018  0x0087
+0x0018  0x0088
+0x0018  0x0090
+0x0018  0x0091
+0x0018  0x0093
+0x0018  0x0094
+0x0018  0x1000
+0x0018  0x1020
+0x0018  0x1200
+0x0018  0x1201
+0x0018  0x1250
+0x0018  0x1314
+0x0018  0x1316
+0x0018  0x5100
+0x0019  0x0000
+0x0019  0x0010
+0x0019  0x0012
+0x0019  0x0015
+0x0019  0x1010
+0x0019  0x1020
+0x0019  0x1030
+0x0019  0x1050
+0x0019  0x1060
+0x0019  0x1210
+0x0019  0x1211
+0x0019  0x1212
+0x0019  0x1213
+0x0019  0x1214
+0x0019  0x1220
+0x0019  0x1221
+0x0019  0x1226
+0x0019  0x1228
+0x0019  0x1230
+0x0019  0x1231
+0x0019  0x1240
+0x0019  0x1241
+0x0019  0x1242
+0x0019  0x1245
+0x0019  0x1246
+0x0019  0x1250
+0x0019  0x1260
+0x0019  0x1270
+0x0019  0x1281
+0x0019  0x1282
+0x0019  0x1283
+0x0019  0x1285
+0x0019  0x1287
+0x0019  0x1290
+0x0019  0x1293
+0x0019  0x1294
+0x0019  0x1297
+0x0019  0x1298
+0x0019  0x12a0
+0x0019  0x12a1
+0x0019  0x1412
+0x0019  0x1414
+0x0019  0x1416
+0x0019  0x1420
+0x0019  0x1421
+0x0019  0x1422
+0x0019  0x1424
+0x0019  0x1426
+0x0019  0x1450
+0x0019  0x1451
+0x0019  0x1452
+0x0019  0x1454
+0x0019  0x1455
+0x0019  0x1456
+0x0019  0x1460
+0x0019  0x1462
+0x0019  0x1470
+0x0019  0x1471
+0x0019  0x1472
+0x0019  0x1480
+0x0019  0x1482
+0x0019  0x1490
+0x0019  0x14a0
+0x0019  0x14a2
+0x0019  0x14a5
+0x0019  0x14a6
+0x0019  0x14b0
+0x0019  0x14c1
+0x0019  0x14c2
+0x0019  0x14c3
+0x0019  0x14c4
+0x0019  0x14c5
+0x0019  0x14d1
+0x0019  0x14d2
+0x0019  0x14d3
+0x0019  0x14d4
+0x0019  0x14d5
+0x0019  0x14d6
+0x0019  0x14d7
+0x0019  0x14d8
+0x0019  0x14d9
+0x0019  0x14da
+0x0019  0x1510
+0x0019  0x1511
+0x0019  0x1512
+0x0019  0x1513
+0x0019  0x1514
+0x0020  0x0000
+0x0020  0x000d
+0x0020  0x000e
+0x0020  0x0010
+0x0020  0x0011
+0x0020  0x0012
+0x0020  0x0013
+0x0020  0x0030
+0x0020  0x0032
+0x0020  0x0035
+0x0020  0x0037
+0x0020  0x0050
+0x0020  0x0052
+0x0020  0x0070
+0x0020  0x0080
+0x0020  0x1001
+0x0020  0x1020
+0x0020  0x1040
+0x0020  0x1041
+0x0020  0x3100
+0x0020  0x3401
+0x0020  0x3402
+0x0020  0x3403
+0x0020  0x3404
+0x0020  0x3405
+0x0020  0x3406
+0x0020  0x5000
+0x0020  0x5002
+0x0021  0x0000
+0x0021  0x0010
+0x0021  0x0011
+0x0021  0x0013
+0x0021  0x0023
+0x0021  0x1010
+0x0021  0x1011
+0x0021  0x1020
+0x0021  0x1120
+0x0021  0x1122
+0x0021  0x1124
+0x0021  0x1126
+0x0021  0x1130
+0x0021  0x1132
+0x0021  0x1160
+0x0021  0x1161
+0x0021  0x1163
+0x0021  0x1165
+0x0021  0x116a
+0x0021  0x116b
+0x0021  0x1170
+0x0021  0x1171
+0x0021  0x1180
+0x0021  0x1182
+0x0021  0x1322
+0x0021  0x1324
+0x0021  0x1330
+0x0021  0x1331
+0x0021  0x1334
+0x0021  0x1336
+0x0021  0x1339
+0x0021  0x1340
+0x0021  0x1341
+0x0021  0x1342
+0x0021  0x1343
+0x0021  0x1344
+0x0021  0x134f
+0x0021  0x1356
+0x0021  0x1370
+0x0021  0x2300
+0x0021  0x2301
+0x0021  0x2302
+0x0021  0x2303
+0x0021  0x2304
+0x0021  0x2305
+0x0021  0x2306
+0x0021  0x2307
+0x0021  0x2308
+0x0021  0x2309
+0x0021  0x2310
+0x0021  0x2311
+0x0021  0x2312
+0x0021  0x2313
+0x0021  0x2314
+0x0021  0x2315
+0x0021  0x2316
+0x0021  0x2317
+0x0021  0x2318
+0x0021  0x2331
+0x0028  0x0000
+0x0028  0x0002
+0x0028  0x0004
+0x0028  0x0005
+0x0028  0x0010
+0x0028  0x0011
+0x0028  0x0030
+0x0028  0x0040
+0x0028  0x0050
+0x0028  0x0060
+0x0028  0x0100
+0x0028  0x0101
+0x0028  0x0102
+0x0028  0x0103
+0x0028  0x0200
+0x0028  0x1050
+0x0028  0x1051
+0x0028  0x1052
+0x0028  0x1053
+0x0029  0x0000
+0x0029  0x0011
+0x0029  0x1110
+0x0029  0x1120
+0x0029  0x1152
+0x0051  0x0000
+0x0051  0x0010
+0x0051  0x1010
+0x7fe0  0x0000
+0x7fe0  0x0010