/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: m-vifi.c                                                      *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : routines which allow to change the FILEINFO information  *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : MdcMakePatAnonymous()     - Make patient anonymous       *
 *                MdcGivePatInformation()   - Give patient information     *
 *                MdcEditFI()               - Edit FILEINFO structure      *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   Copyright (C) 1997-2026 by Erik Nolf

   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, 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.,
   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */

/****************************************************************************
                              H E A D E R S
****************************************************************************/

#include "m-depend.h"

#include <stdio.h>
#ifdef LIBMDC_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef LIBMDC_HAVE_STRING_H
#include <string.h>
#endif
#ifdef LIBMDC_HAVE_STRINGS_H
#ifndef _WIN32
#include <strings.h>
#endif
#endif

#include "medcon.h"

/****************************************************************************
                              D E F I N E S
****************************************************************************/

/****************************************************************************
                            F U N C T I O N S
****************************************************************************/

void MdcMakePatAnonymous(FILEINFO *fi)
{

  MdcStringCopy(fi->patient_sex,"X",1);
  MdcStringCopy(fi->patient_name,"X",1);
  MdcStringCopy(fi->patient_id,"X",1);
  MdcStringCopy(fi->patient_dob,"0000:00:00",10);
  MdcStringCopy(fi->study_descr,"X",1);
  MdcStringCopy(fi->study_id,"X",1);
  MdcStringCopy(fi->series_descr,"X",1);
  fi->study_date_day    = 0;
  fi->study_date_month  = 0;
  fi->study_date_year   = 0;
  fi->study_time_hour   = 0;
  fi->study_time_minute = 0;
  fi->study_time_second = 0;

}

void MdcGivePatInformation(FILEINFO *fi)
{
   int a;

   if (MDC_FILE_STDIN == MDC_YES) return; /* stdin already in use */

   MdcPrintLine('-',MDC_FULL_LENGTH);
   MdcPrntScrn("\tPATIENT/STUDY  INFORMATION\t\tFILE: %s\n",fi->ifname);
   MdcPrintLine('-',MDC_FULL_LENGTH);
   MdcPrntScrn("\n\tNote: all strings are limited to %d characters\n\n"
                 ,MDC_MAXSTR);
   MdcPrntScrn("\n\tGive patient name [%s]: ",fi->patient_name);
   if (! MdcPutDefault(mdcbufr))
     MdcStringCopy(fi->patient_name,mdcbufr,strlen(mdcbufr));

   MdcPrntScrn("\n\tGive patient id [%s]: ",fi->patient_id);
   if (! MdcPutDefault(mdcbufr))
     MdcStringCopy(fi->patient_id,mdcbufr,strlen(mdcbufr));

   MdcPrntScrn("\n\tSelect patient sex [%s]:\n",fi->patient_sex);
   MdcPrntScrn("\n\t\t   1    ->  male");
   MdcPrntScrn("\n\t\t   2    ->  female");
   MdcPrntScrn("\n\t\t   3    ->  other");
   MdcPrntScrn("\n\t\t<enter> ->  default");
   MdcPrntScrn("\n\n\tYour choice? ");
   if (! MdcPutDefault(mdcbufr)) {
     a = atoi(mdcbufr);
     switch (a) {
       case 1 : MdcStringCopy(fi->patient_sex,"M",1); break;
       case 2 : MdcStringCopy(fi->patient_sex,"F",1); break;
       default: MdcStringCopy(fi->patient_sex,"O",1);
     }
   }


   MdcPrntScrn("\n\tGive study description [%s]: ",fi->study_descr);
   if (! MdcPutDefault(mdcbufr))
     MdcStringCopy(fi->study_descr,mdcbufr,strlen(mdcbufr));

   MdcPrntScrn("\n\tGive study id/name/p-number [%s]: ",fi->study_id);
   if (! MdcPutDefault(mdcbufr))
     MdcStringCopy(fi->study_id,mdcbufr,strlen(mdcbufr));

   MdcPrntScrn("\n\tGive series description [%s]: ", fi->series_descr);
   if (! MdcPutDefault(mdcbufr))
     MdcStringCopy(fi->series_descr,mdcbufr,strlen(mdcbufr));

   MdcPrintLine('-',MDC_FULL_LENGTH);
}


char *MdcEditFI(FILEINFO *fi)
{
   IMG_DATA *id=NULL;
   DYNAMIC_DATA *dd=NULL;
   Uint32 i, number, dflt, dim[MDC_MAX_DIMS];
   Int8 a, LAST_FOUND=MDC_NO;
   float pixel_size, slice_width, slice_spacing, frame_duration;
   char *msg, *badvalue="Bad dim[]-value supplied";
   int modality = fi->modality;

   if (MDC_FILE_STDIN == MDC_YES) return(NULL); /* stdin already in use */

   MdcPrintLine('#',MDC_FULL_LENGTH);
   MdcPrntScrn("\tEDIT  FILEINFO  STRUCTURE\t\tFILE: %s\n",fi->ifname);
   MdcPrintLine('#',MDC_FULL_LENGTH);

   /* patient/slice orientation */
   MdcPrintLine('-',MDC_HALF_LENGTH);
   MdcPrntScrn("\tPATIENT/SLICE  ORIENTATION\n");
   MdcPrintLine('-',MDC_HALF_LENGTH);

   MdcPrntScrn("\n\tSelect Patient/Slice orientation:\n");

   for (a=0; a < MDC_MAX_ORIENT; a++)
      MdcPrntScrn("\n\t\t %2hd  ->  %s",a,MdcGetStrPatSlOrient(a));

   MdcPrntScrn("\n\n\tYour choice [%d]? ",fi->pat_slice_orient);

   if (MdcPutDefault(mdcbufr)) a = fi->pat_slice_orient;
   else a = (Int8)atoi(mdcbufr);

   fi->pat_slice_orient = a;
   strcpy(fi->pat_pos,MdcGetStrPatPos(fi->pat_slice_orient));
   strcpy(fi->pat_orient,MdcGetStrPatOrient(fi->pat_slice_orient));


   MdcPrintLine('-',MDC_HALF_LENGTH);

   /* pixel/slice dimensions */
   MdcPrintLine('-',MDC_HALF_LENGTH);
   MdcPrntScrn("\tPIXEL/SLICE DIMENSIONS\n");
   MdcPrintLine('-',MDC_HALF_LENGTH);


   /* fill in default values */
   id = &fi->image[0];
   pixel_size    = id->pixel_xsize;
   slice_width   = id->slice_width;
   slice_spacing = id->slice_spacing;

   if ((fi->dynnr > 0) && (fi->dyndata != NULL)) {
     frame_duration = fi->dyndata[0].time_frame_duration;
   }else{
     frame_duration = 0.;
   }

   MdcPrntScrn("\n\tNote: The following entries require float values");
   MdcPrntScrn("\n\t      Examples: 10.0 or 1.0e+1\n");

   MdcPrntScrn("\n\tGive pixel size in mm [%e]: ",pixel_size);
   if (! MdcPutDefault(mdcbufr)) pixel_size = (float)atof(mdcbufr);

   MdcPrntScrn("\n\tGive slice width in mm [%e]: ",slice_width);
   if (! MdcPutDefault(mdcbufr)) slice_width = (float)atof(mdcbufr);

   MdcPrntScrn("\n\tGive centre-centre slice separation in mm [%e]: "
                 ,slice_spacing);
   if (! MdcPutDefault(mdcbufr)) slice_spacing = (float)atof(mdcbufr);

   MdcPrntScrn("\n\tGive duration of time frame in ms [%e]: ",frame_duration);
   if (! MdcPutDefault(mdcbufr)) frame_duration= (float)atof(mdcbufr);

   MdcPrintLine('-',MDC_HALF_LENGTH);

   /* array dimensions */
   MdcPrintLine('-',MDC_HALF_LENGTH);
   MdcPrntScrn("\tARRAY  DIMENSIONS\n");
   MdcPrintLine('-',MDC_HALF_LENGTH);

   MdcPrntScrn("\n\t");
   MdcPrntScrn("Note: Each array entry must be a 1-based integer and the");
   MdcPrntScrn("\n\t");
   MdcPrntScrn("      product of dim[]-values = total numer of images\n");


   /* fill in some defaults */
   dflt = fi->number;
   for (i=0; i<MDC_MAX_DIMS; i++) dim[i] = 1;

   MdcPrntScrn("\n\t            ( PET   |    NucMed    )    default");
   MdcPrntScrn("\n\t             ----------------------     -------");
   MdcPrntScrn("\n\tGive dim[3] (planes | (time) slices)     [%u]: ",dflt);
   if (MdcPutDefault(mdcbufr)) dim[3] = dflt;
   else dim[3] = (Uint32)atoi(mdcbufr);
   if (dim[3] == 0) return(badvalue);

   dflt /= dim[3]; if(dflt == 0) return(badvalue);
   MdcPrntScrn("\n\tGive dim[4] (frames | time slots|phases) [%u]: ",dflt);
   if (MdcPutDefault(mdcbufr)) dim[4] = dflt;
   else dim[4] = (Uint32)atoi(mdcbufr);
   if (dim[4] == 0) return(badvalue);

   dflt /= dim[4]; if (dflt == 0) return(badvalue);
   MdcPrntScrn("\n\tGive dim[5] (gates  | R-R intervals)     [%u]: ",dflt);
   if (MdcPutDefault(mdcbufr)) dim[5] = dflt;
   else dim[5] = (Uint32)atoi(mdcbufr);
   if (dim[5] == 0) return(badvalue);

   dflt /= dim[5]; if (dflt == 0) return(badvalue);
   MdcPrntScrn("\n\tGive dim[6] (beds   | detector heads)    [%u]: ",dflt);
   if (MdcPutDefault(mdcbufr)) dim[6] = dflt;
   else dim[6] = (Uint32)atoi(mdcbufr);
   if (dim[6] == 0) return(badvalue);

   dflt /= dim[6]; if (dflt == 0) return(badvalue);
   MdcPrntScrn("\n\tGive dim[7] (????   | energy windows)    [%u]: ",dflt);
   if (MdcPutDefault(mdcbufr)) dim[7] = dflt;
   else dim[7] = (Uint32)atoi(mdcbufr);
   if (dim[7] == 0) return(badvalue);

   number = 1;
   for (i=3; i<MDC_MAX_DIMS; i++) number*=dim[i];

   if (number != fi->number) return(badvalue);

   /* ok, use the values */
   for (i=7; i>=3; i--) {
      fi->dim[i] = dim[i];
      if ((LAST_FOUND == MDC_NO) && (dim[i] > 1)) {
        fi->dim[0] = i; LAST_FOUND = MDC_YES;
      }
   }

   MdcPrintLine('-',MDC_HALF_LENGTH);


   /* study information */
   MdcPrintLine('-',MDC_HALF_LENGTH);
   MdcPrntScrn("\tSTUDY  PARAMETERS\n");
   MdcPrintLine('-',MDC_HALF_LENGTH);

   MdcPrntScrn("\n\tReconstructed ");
   if (fi->reconstructed == MDC_YES) {
     MdcPrntScrn("([y]/n)");
   }else{
     MdcPrntScrn("(y/[n])");
   }
   MdcPrntScrn(" ? ");

   if (!MdcPutDefault(mdcbufr)) {
     if ( mdcbufr[0] == 'y' || mdcbufr[0] == 'Y' ) {
       fi->reconstructed = MDC_YES;
     }else if ( mdcbufr[0] == 'n' || mdcbufr[0] == 'N' ) {
       fi->reconstructed = MDC_NO;
     }
   }

   MdcPrntScrn("\n\tPlanar study  ");
   if (fi->planar == MDC_YES) {
     MdcPrntScrn("([y]/n)");
   }else{
     MdcPrntScrn("(y/[n])");
   }
   MdcPrntScrn(" ? ");

   if (!MdcPutDefault(mdcbufr)) {
     if ( mdcbufr[0] == 'y' || mdcbufr[0] == 'Y' ) {
       fi->planar = MDC_YES;
     }else if ( mdcbufr[0] == 'n' || mdcbufr[0] == 'N' ) {
       fi->planar = MDC_NO;
     }
   }

   MdcPrntScrn("\n\tSelect Modality:\n");
   MdcPrntScrn("\n\t\t   1    ->  NM");
   MdcPrntScrn("\n\t\t   2    ->  PT");
   MdcPrntScrn("\n\t\t   3    ->  CT");
   MdcPrntScrn("\n\t\t   4    ->  MR");
   MdcPrntScrn("\n\t\t<enter> ->  current");
   MdcPrntScrn("\n\n\tYour choice [%s] ? ",MdcGetStrModality(modality));

   if (! MdcPutDefault(mdcbufr)) {
     a = atoi(mdcbufr);
     switch (a) {
       case 1: modality = M_NM; break;
       case 2: modality = M_PT; break;
       case 3: modality = M_CT; break;
       case 4: modality = M_MR; break;
     }
   }

   MdcPrntScrn("\n\tSelect Acquisition type:\n");
   for (a=0; a < MDC_MAX_ACQUISITIONS; a++)
      MdcPrntScrn("\n\t\t %2hd  ->  %s",a,MdcGetStrAcquisition(a));

   MdcPrntScrn("\n\n\tYour choice [%d]? ",fi->acquisition_type);

   if (!MdcPutDefault(mdcbufr)) {
     fi->acquisition_type = (Int16)atoi(mdcbufr);
   }

   MdcPrintLine('-',MDC_HALF_LENGTH);

   /* reset other data structs */
   msg = MdcResetODs(fi);
   if (msg != NULL) return(msg);

   /* fill in FI struct */
   if (fi->pixdim[0] < 4) fi->pixdim[0] = 4; /* at least */
   fi->pixdim[1] = pixel_size;
   fi->pixdim[2] = pixel_size;
   fi->pixdim[3] = slice_width;
   fi->pixdim[4] = frame_duration;

   fi->modality  = modality;

   /* fill in IMG_DATA structs */
   for (i=0; i < fi->number; i++) {
      id = &fi->image[i];

      id->pixel_xsize  = pixel_size;
      id->pixel_ysize  = pixel_size;
      id->slice_width  = slice_width;
      id->slice_spacing= slice_spacing;

      MdcFillImgPos(fi,i,fi->dim[3]==0 ? 0 : i%fi->dim[3],(float)0.0);
      MdcFillImgOrient(fi,i);
   }

   /* fill DYNAMIC_DATA structs */
   for (i=0; i<fi->dynnr; i++) {
      dd = &fi->dyndata[i];

      dd->nr_of_slices = fi->dim[3];
      dd->time_frame_duration = frame_duration;
   }

   /* some final completions */
   msg = MdcImagesPixelFiddle(fi);
   if (msg != NULL) return(msg);

   MdcPrintLine('#',MDC_FULL_LENGTH);

   return(NULL);
}

