#!/bin/sh
#set -x
#             $HOME/.lcmodel/varian/bin2raw (29 July 2010)

#     Makes an LCModel RAW file from a Varian fid file (also using the 
# corresponding procpar file).  Also makes the files cpStart and extraInfo for 
# LCMgui.

#     Note VOLUME is set to 1.0.  Therefore, Water-scaling will only be valid 
# if the voxel size of your unsuppressed water reference and your 
# water-suppresed data are identical.  Otherwise, only concentration ratios 
# will be relevant.  See the chapter entitled  "Absolute Metabolite 
# Concentrations" in the LCModel manual.

#                  Specific Instructions for this File
#                  ===================================

#     The following requirements must be met:

#     (1) You have selected the Varian file with the name "fid", which must 
# contain your time-domain data.
#-------------------

#     (2) The file "procpar" corresponding to your selected file "fid" is in 
# the same directory as "fid".
#-------------------

#     (3) The program file, bin2asc, must also be in $HOME/.lcmodel/varian/.
#-------------------

#      Normally, the filename should always be "fid".  You can require this by 
# replacing REQUIRE_FILENAME_FID=0 with REQUIRE_FILENAME_FID=1 (one) in the 
# following line:

REQUIRE_FILENAME_FID=0

# (Be sure that there is no space on either side of the "=".)
# In any case, it is your responsibility to make sure that the file that you 
# select is an fid file satisfying Instruction (1) above.
#-------------------

#     Normally, you should not have to read further.  However, more 
# information is given in the General Instructions at the end of this script.

#============================================================================

# Function for checking if a variable is non-integer (adapted from B. Blinn).
#
IsNonNumeric() {
    expr "$1" + 1  >/dev/null  2>&1
    if [ $?  -ge  2 ]; then
	return 0
    fi
    return 1
}
#-----------------------------------------------------------------------------

#      Function produces an integer 1000 times the decimal value in the 
# procpar file.  
#      $1 = line preceding the sought decimal value (which is in field 2) in 
# the procpar file.  Possible violations of this assumption are not checked.
#      This extremely awkward strategy is because, with some language 
# installations, "awk" works with a comma (instead of a period) as the decimal 
# point.  "perl" and "bc" are not guaranteed to be installed.  (This should 
# have been done in C, or avoided by setting LANG.)
#
Int1000() {
   FULL=""
   FULL=`awk "/$1 /"' {getline; print $2}' $PROCPAR`
   if [ "$FULL"  =  "" ]; then
       return 1
   fi
   case "$FULL" in
       *\.* )  FULL=${FULL}0000
               WHOLE=`echo "$FULL" | cut -d. -f1`
               FRACT=`echo "$FULL" | cut -d. -f2 | cut -c1-3 | \
                      awk '{printf ("%d", $1)}'`  
               FRACT_FRACT=`echo "$FULL" | cut -d. -f2 | cut -c4 | \
                      awk '{printf ("%d", $1)}'` ;;
       * )  WHOLE=`echo "$FULL"`
            FRACT="0"
            FRACT_FRACT="0" ;;
   esac
   if [ -z "$WHOLE" ]; then
       X1000=`echo "$FRACT"`
   else
       X1000=`expr 1000 \* $WHOLE + $FRACT`
   fi
   if IsNonNumeric  $FRACT_FRACT; then
       return 1
   fi
   if IsNonNumeric  $X1000; then
       return 1
   fi
   if [ $FRACT_FRACT -ge 5 ]; then
       X1000=`expr $X1000 + 1`
   fi
   if  IsNonNumeric  "$X1000"; then
       return 1
   fi
   return 0
}
#-----------------------------------------------------------------------------

# Initial definitions.
# Note that $LCM_DIR has a "/" at the end and $BIN2RAW_DIR does not.
#
DATA_FILE=$1
LCM_DIR=$2
MET_H2O=$3
BIN2RAW_DIR=$2$3
DATA_DIR=`dirname $1`
PROCPAR=$DATA_DIR/procpar
CP_START=$BIN2RAW_DIR/cpStart
EXTRA_INFO=$BIN2RAW_DIR/extraInfo
ERROR=$BIN2RAW_DIR/error
RAW=$BIN2RAW_DIR/RAW

#      Check for the names & existence of the files fid & procpar, which must 
# be in the same directory.
#
if [ $REQUIRE_FILENAME_FID -eq 1 ]; then
    BASENAME=`basename $1`
    if [ "$BASENAME"  !=  fid ]; then
        echo "  The following file, which you selected, must have the name fid:

$1"  >  $ERROR
        exit 0
    fi
fi

if [ -r  "$PROCPAR" ]; then
    :
else
    echo "     There is no readable file procpar in the following directory:

$DATA_DIR

The file, procpar, corresponding to your selected fid file must be in this
same directory."  >  $ERROR
    exit 0
fi
#-----------------------------------------------------------------------------

# Delete possible old files, e.g., after "Reload" Button. 
#
rm  -f  $CP_START
rm  -f  $EXTRA_INFO
rm  -f  $ERROR
rm  -f  $RAW
#-----------------------------------------------------------------------------

# Extract info for cpStart from ACQP file.

# First make TITLE
#
STUDY=`awk -F\" '/^studyid/ {getline
                            print $2}' $PROCPAR`

WORK=`awk -F\" '/^time_run / {getline
                                   print $2}' $PROCPAR`
YEAR=`echo $WORK | cut -c1-4`
MONTH=`echo $WORK | cut -c5-6`
DAY=`echo $WORK | cut -c7-8`
HOUR=`echo $WORK | cut -c10-11`
MINUTE=`echo $WORK | cut -c12-13`
SECOND=`echo $WORK | cut -c14-15`
DATE_TIME="$YEAR/$MONTH/$DAY $HOUR:$MINUTE:$SECOND"
TITLE="$STUDY  ($DATE_TIME)"

SEQ_IN=`awk -F\" '/^seqfil / {getline
                           print $2}' $PROCPAR`
SEQ_LC=`echo "$SEQ_IN" | tr '[A-Z]' '[a-z]' `
case  "$SEQ_LC"  in
    *steam* )  SEQ=STEAM    ;;
    *press* )  SEQ=PRESS    ;;
          * )  SEQ=UNKNOWN  ;;
esac
if [ $SEQ = UNKNOWN ]; then
    TITLE="$TITLE  $SEQ_IN"
else
    TITLE="$TITLE  $SEQ"
fi
# Get TE.
# Assumptions (from files received so far): PRESS:
#    In older versions: TE1 is in te and TE2 is in te2; there is no te1.
#    In newer versions: TE, TE1 & TE2 are where they should be.
# STEAM: TE is in te; there is no te1 or te2.
# Failures in Int1000 are due to missing variable, no other error.
#
Int1000  "^te"
if [ $? -ne 0 ]; then
    TE="NaN"
else
    TE="$X1000"
    if [ $TE -le 0 ]; then
        TE="NaN"
    else  # te > 0
        Int1000  "^te1"
        if [ $? -ne 0 ]; then # No te1 ===> STEAM or old PRESS.
            Int1000  "^te2"
            if [ $? -ne 0 ]; then # Both te1 & te2 missing ===> STEAM
                :
            else  # te1 missing, te2 present ===> old PRESS
                TE2="$X1000"
                if [ $TE2 -gt 0 ]; then
                    TE=`expr $TE + $TE2`
                else
                    TE="NaN"
                fi
            fi
        fi
    fi
fi

# TR

Int1000 "^tr"
if [ $? -ne 0 ]; then
    TR="NaN"
else
    TR="$X1000"
    if [ $TR -le 0 ]; then
        TR="NaN"
    fi
fi

# nt is the maximum possible number of scans.
# ct is the actual number of scans
#
NS=`awk '/^ct / {getline
                 printf("%d", $2)}' $PROCPAR`
if IsNonNumeric "$NS"; then
    NS="NaN"
elif [ $NS -le 0 ]; then
    NS="NaN"
fi

TITLE="$TITLE  TE/TR/NS=$TE/$TR/$NS"

# Make cpStart & extraInfo
#
echo "title= '$TITLE'
filraw= '$RAW'
filps= '${LCM_DIR}ps'" >  $CP_START

Int1000  "^sfrq"
if [ $? -eq 0 ]; then
    HZPPPM=`echo "$X1000" | awk '{printf("%.3f", $1/1000)}' | tr ',' '.'`
    echo "hzpppm= $HZPPPM" >> $CP_START
    echo "hzpppm  $HZPPPM" > $EXTRA_INFO
else
    HZPPPM="NaN"
fi

Int1000  "^sw"
if [ $? -eq 0 ]; then
    DELTAT=`echo "$X1000" | awk '{printf("%.4e", 1000/$1)}' | tr ',' '.'`
    echo "deltat= $DELTAT" >> $CP_START
else
    DELTAT="NaN"
fi

if [ "$TE"  !=  NaN ]; then
    echo "echot  $TE.0" >> $EXTRA_INFO
fi

if [ "$SEQ" != UNKNOWN ]; then
    echo "seq $SEQ" >> $EXTRA_INFO
fi
#-----------------------------------------------------------------------------

# Produce $RAW file

#-------------------------------------------------
# First write Namelists to BUFFER and then to $RAW.

BUFFER=" \$SEQPAR"

if [ "$HZPPPM" != NaN ]; then
    BUFFER="$BUFFER
 hzpppm=$HZPPPM"
fi

if [ "$TE"  !=  NaN ]; then
    BUFFER="$BUFFER
 echot=$TE.0"
fi

if [ "$SEQ"  !=  UNKNOWN ]; then
    BUFFER="$BUFFER
 seq='$SEQ'"
fi

# gain is in dB
# TRAMP is divided by gain and by the number of scans.

Int1000  "^gain"
if [ $? -ne 0   -o   $NS = "NaN" ]; then
    TRAMP=1.
else
    GAIN="$X1000"
    TRAMP=`echo "$NS $GAIN" | awk '{print exp(-0.00011512925 * $2) / $1}' \
                            | tr ',' '.'`
fi

echo "$BUFFER
 \$END
 \$NMID
 fmtdat='(2e14.5)'
 tramp=$TRAMP
 volume=1. 
 \$END"  >  $RAW
#---------------------------------------------------------
# Append binary fid data converted into ASCII with bin2asc.
#
    $HOME/.lcmodel/varian/bin2asc  $DATA_FILE  $BIN2RAW_DIR

#----------------------------------------------------------------------------
#
# You must always exit this script with "exit 0"
#
exit 0

#=============================================================================
#=============================================================================
#=============================================================================

#            General Instructions for writing your own my-bin2raw
#            ====================================================

#     If you want to modify this file, use this file as a template only; copy 
# it to my-bin2raw (in the same directory as bin2raw), and then edit 
# my-bin2raw.
#     LCMgui always first attempts to execute my-bin2raw.  If LCMgui cannot 
# find my-bin2raw, then it executes bin2raw.
#     bin2raw will be overwritten by LCMgui updates, but your my-bin2raw will 
# not be overwritten.

#      LCMgui executes this script and supplies 3 arguments to it, i.e., it 
# executes
#   $HOME/.lcmodel/other/bin2raw  $1  $2  $3
#----------------------------------------------------------------------------

#      The 3 arguments supplied by LCMgui are:
#
# $1 = the absolute pathname of the data file that you selected to be 
#      analyzed.
#
# $2 = the absolute pathname (with a "/" at the end) of the temporary 
#      directory where you must put the output from this script.
#
# $3 = met if the data file contains your water-suppressed data (or if the 
#          data file contains both your water-suppressed data and your 
#          unsuppressed water reference data for eddy-current correction).
#    = h2o if the data file contains only the unsuppressed water reference 
#          data.

# (C programs can access $3 as argv[3], etc.)
#----------------------------------------------------------------------------

#     This script must output the following files:

# $2$3/RAW = LCModel RAW file.

# $2h2o/RAW = LCModel RAW file of the unsuppressed water reference data for
#             eddy-current correction. 
#                  This is only possible if your data file contains both the
#             unsuppressed and suppressed data.  In this case, $3 = "met", and 
#             you output both $2$3/RAW and $2h2o/RAW.
#                  If the unsuppressed and suppressed are in different files,
#             then you only output $2$3/RAW, first when $3 = "met", and later 
#             LCMgui calls other/bin2raw again with another $1 and with 
#             $3 = "h2o"

# $2$3/cpStart : sets any default Control Parameters (which you can later 
#                  modify in LCMgui) that can be obtained from (the headers 
#                  of) your data file.
#                The format illustrated below must be strictly followed; i.e.:
#                  control_parameter= value
#                e.g.,
#                  hzpppm= $HZPPPM
#                with NO space between the control parameter and the "=" and 
#                with space between the "=" and the value.

# $2$3/extraInfo : As illustrated below, this file can contain "echot" and 
#                    "seq", with which LCMgui will attempt to automatically 
#                    select the correct default BASIS file of model spectra 
#                    with these sequence parameters.
#                  With the three "voiPosition*", LCMgui will produce an error 
#                    window if these three in the unsuppressed reference and 
#                    water-suppressed files do not agree (indicating spectra 
#                    from different voxels).
#                  With the "headerInfo*, the default path of the directory 
#                    that archives the LCModel results is determined.
#                  The format is illustrated below.  It is the same as for 
#                    cpStart, except that there is no "=".  There still must 
#                    be space between the parameter and the value.

# $2$3/error : Error messages on aborts should go here.  They will then be 
#                displayed by LCMgui, PROVIDED that you then exit with 
#                "exit 0"; i.e., a "successful" exit.  It is essential that 
#                ALL exits (successful and error exits) be with "exit 0".
#              From a C program, you must also always exit with "exit(0)".

#============================================================================
