/*
Description: converts input file into a tensor or eigensystem and saves the output to disc

Author:      Raimundo Sierra
             www.rsierra.com

Copyright:   Copyright (c) 2000 Raimundo Sierra. All rights reserved.
LICENSE:     This program is free software; you can redistribute it and/or modify
             it under the terms of the GNU General Public License as published by
             the Free Software Foundation; either version 2 of the License, or
             (at your option) any later version.

             This program is distributed in the hope that it will be useful,
             but WITHOUT ANY WARRANTY; without even the implied warranty of
             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
             GNU General Public License for more details.

             You should have received a copy of the GNU General Public License
             along with this program; if not, write to the Free Software
             Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


Institution: Surgical Planning Laboratory
             Department of Radiology
             Brigham and Women's Hospital
             Harvard Medical School
             MA 02115
             USA

Date:        11.2000 - 3.2001

Modifications:
<Date>   <Init>    <Version>    <Description>

*/
#include <string.h>
#include <iostream.h>
#include "tensorfield.h"
#include "eigenfield.h"
#include "background.h"

void usage(){
  cout << 
    "\nUsage:"
    "\n------"
    "\n./convert -i=infile -o=outfile [options]"
    "\n\nwhere infile and outfile are full path and filename"
    "\nNo file extensions are needed: Tensor-file has extension .ten, Eigen-file .eig"
    "\nIn case infile type is \"raw\":" 
    "\ninfile is the path and the name of the files from which"
    "\nto derive the tensors, but without the ending XXXX.pic"
  "\n\nOptions:               Defaults:      Descriptions:"
    "\n--------               ---------      ------------"
    "\n-all                   -it=raw        convert from raw to tensor AND eigen"
    "\n-it=(raw|tensor|eigen) raw            type of infile"
    "\n-ot=(tensor|eigen)     tensor         type of outfile"
    "\n-ix=                   256            x-dimension of infile"
    "\n-iy=                   256            y-dimension of infile"
    "\n-iz=                   1              z-dimension of infile"
    "\n-ox=                   same as input  x-dimension of outfile"
    "\n-ox=                   same as input  y-dimension of outfile"
    "\n-oz=                   same as input  z-dimension of outfile"
    "\n-dx=                   1              delta x"
    "\n-dy=                   1              delta y"
    "\n-dz=                   1              delta z"
    "\n-offx=                 0              x-offset for outfile"
    "\n-offy=                 0              y-offset for outfile"
    "\n-offz=                 0              z-offset for outfile"
    "\n-id=                   0              Patient ID"
    "\n-ex=                   0              Examen number"
    "\n-ser=                  0              Series number"
    "\n-ag=                   0              Age"
    "\n-or=(s|c|a)            a              Orientation: saggital, coronal or axial"
    "\n-orig=                 notAvailable   location of the original data"
    "\n-date=                                actual date (default is empty)"
    "\n-r=                    -1             remove strips, 0 outside the object"
    "\n                                      1 outside and inside the object"
    "\n";
  cout << endl;
};

int main(int argc, const char *argv[]){

const int MAXSTRINGLENGTH = 1024;
char  infile[MAXSTRINGLENGTH];
char  outfile[MAXSTRINGLENGTH];

// the initializations include the defaults
int dimx_in  = 256;
int dimy_in  = 256;
int dimz_in  =   1;
int dimx_out =  -1;
int dimy_out =  -1;
int dimz_out =  -1;
int offx_out =   0;
int offy_out =   0;
int offz_out =   0;
int reader   =   0;
int remove   =  -1; 
int all      =  -1;
float dx     =   1;
float dy     =   1;
float dz     =   1;
int id       =   0;
int ex       =   0;
int ser      =   0;
int ag       =   0;
char or      = 'a';
char * orig  = new char[MAXSTRINGLENGTH]; strcpy(orig, "notAvailable");
char * date  = new char[15];
 
 // not enough arguments
 if(argc<3){
   if(argc==2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-help"))){ // help requested
     usage();
     exit(0);
   } else {
     cout << "\nConvert needs at least 2 arguments;\n";
     usage(); 
     exit(0);
   }
 }

 // read the arguments
 else {
   int parameter=1;
   while (argc>1) {
     if(   !strncmp(argv[parameter], "-i=", 3)
	|| !strncmp(argv[parameter], "-I=", 3)){ 
       strcpy(infile, &argv[parameter][3]);
     }
     else if(!strncmp(argv[parameter], "-o=", 3)
	  || !strncmp(argv[parameter], "-O=", 3)){
       strcpy(outfile, &argv[parameter][3]);
     }

     else if(!strncmp(argv[parameter], "-date=", 6)
	  || !strncmp(argv[parameter], "-DATE=", 6)){ 
       strcpy(date, &argv[parameter][6]);
     }
     else if(!strncmp(argv[parameter], "-orig=", 6)
	  || !strncmp(argv[parameter], "-ORIG=", 6)){
       strcpy(orig, &argv[parameter][6]);
     }

     else if(!strncmp(argv[parameter], "-it=", 4)
	  || !strncmp(argv[parameter], "-IT=", 4)){
       if(!strcmp(&argv[parameter][4], "tensor")){
	 reader = reader + 2;
       } else if(!strcmp(&argv[parameter][4], "eigen")){
	 reader = reader + 3;
       } else if(!strcmp(&argv[parameter][4], "raw")){
	 reader = reader + 1;
       }
     }
     else if(!strncmp(argv[parameter], "-ot=", 4)
	  || !strncmp(argv[parameter], "-OT=", 4)){
       if(!strcmp(&argv[parameter][4], "eigen")){
	 reader = reader+30;
       } else if(!strcmp(&argv[parameter][4], "tensor")){
	 reader = reader+20;
       }
     }
     else if(!strncmp(argv[parameter], "-all", 4)){
       all = 1;
     }

     else if(!strncmp(argv[parameter], "-ix=", 4)
	  || !strncmp(argv[parameter], "-IX=", 4)){
       dimx_in = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-iy=", 4)
	  || !strncmp(argv[parameter], "-IY=", 4)){
       dimy_in = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-iz=", 4)
	  || !strncmp(argv[parameter], "-IZ=", 4)){
       dimz_in = atoi(&argv[parameter][4]);
     }

     else if(!strncmp(argv[parameter], "-ox=", 4)
	  || !strncmp(argv[parameter], "-OX=", 4)){
       dimx_out = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-oy=", 4)
	  || !strncmp(argv[parameter], "-OY=", 4)){
       dimy_out = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-oz=", 4)
	  || !strncmp(argv[parameter], "-OZ=", 4)){
       dimz_out = atoi(&argv[parameter][4]);
     }

     else if(!strncmp(argv[parameter], "-dx=", 4)
	  || !strncmp(argv[parameter], "-DX=", 4)){
       dx = atof(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-dy=", 4)
	  || !strncmp(argv[parameter], "-DY=", 4)){
       dy = atof(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-dz=", 4)
	  || !strncmp(argv[parameter], "-DZ=", 4)){
       dz = atof(&argv[parameter][4]);
     }

     else if(!strncmp(argv[parameter], "-id=", 4)
	  || !strncmp(argv[parameter], "-ID=", 4)){
       id = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-ex=", 4)
	  || !strncmp(argv[parameter], "-EX=", 4)){
       ex = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-ag=", 4)
	  || !strncmp(argv[parameter], "-AG=", 4)){
       ag = atoi(&argv[parameter][4]);
     }
     else if(!strncmp(argv[parameter], "-ser=", 5)
	  || !strncmp(argv[parameter], "-SER=", 5)){
       ser = atoi(&argv[parameter][5]);
     }

     else if(!strncmp(argv[parameter], "-offx=", 6)
	  || !strncmp(argv[parameter], "-OFFX=", 6)){
       offx_out = atoi(&argv[parameter][6]);
     }
     else if(!strncmp(argv[parameter], "-offy=", 6)
	  || !strncmp(argv[parameter], "-OFFY=", 6)){
       offy_out = atoi(&argv[parameter][6]);
     }
     else if(!strncmp(argv[parameter], "-offz=", 6)
	  || !strncmp(argv[parameter], "-OFFZ=", 6)){
       offz_out = atoi(&argv[parameter][6]);
     }
     else if(!strncmp(argv[parameter], "-date=", 6)
	  || !strncmp(argv[parameter], "-DATE=", 6)){
       strcpy(date, &argv[parameter][6]);
     }

     else if(!strncmp(argv[parameter], "-or=a", 5)){  or = 'a'; }
     else if(!strncmp(argv[parameter], "-or=A", 5)){  or = 'a'; }
     else if(!strncmp(argv[parameter], "-or=s", 5)){  or = 's'; }
     else if(!strncmp(argv[parameter], "-or=S", 5)){  or = 's'; }
     else if(!strncmp(argv[parameter], "-or=c", 5)){  or = 'c'; }
     else if(!strncmp(argv[parameter], "-or=C", 5)){  or = 'c'; }

     else if(!strncmp(argv[parameter], "-r=", 3)
	  || !strncmp(argv[parameter], "-r=", 3)){
       remove   = atoi(&argv[parameter][3]);
     }


     else {
       cout <<"Unknown option "<<argv[parameter]<<endl;
       usage();
       exit(0);
     }
     argc--;
     parameter++;
   }
 }
#ifdef debug
 cout << "Reader is: "<< reader<< endl;
#endif
 // output dimensions have not been specified, set defaults
 if(dimx_out == -1) dimx_out=dimx_in;
 if(dimy_out == -1) dimy_out=dimy_in;
 if(dimz_out == -1) dimz_out=dimz_in;
   
 int offset[3] = {offx_out, offy_out, offz_out};
 int window[3] = {dimx_out, dimy_out, dimz_out};

 // now process the data as requested
 if (all==1){                                    // convert from raw to eigen and tensor
   cout << "\nDeriving tensorfile and eigenfile from raw data:\n";
   /*
   tensorfield t_field(infile, dimx_in, dimy_in, dimz_in);
   if (remove != -1) t_field.remove_strips(remove);
   t_field.setDelta(dx, dy, dz);
   t_field.setNumbers(ag, id, ex, ser);
   t_field.setDate(date);
   t_field.setOrig(orig);
   t_field.setOrientation(or);
   t_field.save(outfile, offset, window);
   eigenfield e_field(t_field, offset, window);
   e_field.save(outfile);
   */
   eigenfield e_field(infile, dimx_in, dimy_in, dimz_in);
   if (remove != -1) e_field.remove_strips(remove);
   e_field.correctVectors();
   e_field.setDelta(dx, dy, dz);
   e_field.setNumbers(ag, id, ex, ser);
   e_field.setDate(date);
   e_field.setOrig(orig);
   e_field.setOrientation(or);
   e_field.save(outfile);
   tensorfield t_field(dimx_in, dimy_in, dimz_in);
   e_field.eigen2tensor(t_field);
   t_field.save(outfile, offset, window);
   background bac(infile, dimx_in, dimy_in, dimz_in);
   bac.save(outfile);
 }
 else if (reader==0 || reader==1  || reader==20 || reader==21){    // convert from raw to tensor
   cout << "\nDeriving tensorfile from raw data:\n";
   tensorfield t_field(infile, dimx_in, dimy_in, dimz_in);
   if (remove != -1) t_field.remove_strips(remove);
   t_field.setDelta(dx, dy, dz);
   t_field.setNumbers(ag, id, ex, ser);
   t_field.setDate(date);
   t_field.setOrig(orig);
   t_field.setOrientation(or);
   t_field.save(outfile, offset, window);
 } 
 else if(reader==2  || reader==22) {             // convert from tensor to tensor
   cout << "\nCreating tensorfile from tensorfile:\n";
   tensorfield t_field(dimx_in, dimy_in, dimz_in);
   t_field.load(infile);
   if (remove != -1) t_field.remove_strips(remove);
   t_field.save(outfile, offset, window); 
 }
 else if(reader==3  || reader==23) {             // convert from eigensystem to tensor
   cout << "\nConverting from eigensystem to tensorfield\n";
   eigenfield e_field(dimx_in, dimy_in, dimz_in);
   e_field.load(infile);
   tensorfield t_field(dimx_in, dimy_in, dimz_in);
   e_field.eigen2tensor(t_field);
   if (remove != -1) t_field.remove_strips(remove);
   t_field.save(outfile, offset, window); 
 }
 else if(reader==30 || reader==31) {             // convert from raw to eigensystem
   cout << "\nDeriving eigensystem from raw data\n";
   tensorfield t_field(infile, dimx_in, dimy_in, dimz_in);
   if (remove != -1) t_field.remove_strips(remove);
   eigenfield e_field(t_field, offset, window);
   e_field.save(outfile);
   e_field.write_XMLHeader(outfile);
 }
 else if(reader==32)               {             // convert from tensor to eigensystem
   cout << "\nConverting from tensorfield to eigensystem\n";
   tensorfield t_field(dimx_in, dimy_in, dimz_in);
   t_field.load(infile);
   if (remove != -1) t_field.remove_strips(remove);
   eigenfield e_field(t_field, offset, window);
   e_field.save(outfile);
   e_field.write_XMLHeader(outfile);
 }
 else if(reader==33)               {             // convert from eigensystem to eigensystem
   cout << "\nCreating eigenfile from eigenfile\n";
   eigenfield e_field(dimx_in, dimy_in, dimz_in);
   e_field.load(infile);
   e_field.save(outfile, offset, window);
   e_field.write_XMLHeader(outfile);
 }
 else {
   cout <<"Unknown conversion\nType ./convert -h for help\n";
 }

};                                 
