#!/bin/sh
## \section{som\_classify (shell script)}
## 
## \subsection*{Purpose}
## Classify with the SOM (Self Organizing Map)
##
## \subsection*{Description}
## Applies two passes of the Self Organizing Map clustering algorithm
## For large images, run:"
## \begin{verbatim}
##   setenv TMPDIR <dir>"
## \end{verbatim}
## first, where {\tt <dir>} is a directory with plenty of free space."
## 
## \subsection*{Usage}
## \begin{verbatim}
## som_classify [-dec] 
##    [-sn structure number <int>]
##    [-ff feature file <filename>]
##    [-cf classified file <filename>]
##    [-sf statistics file <filename>]
##    [-rlen runlengths <int> <int>]
##    [-alpha alphas <int> <int>]
##    [-radius radies <int> <int>]
##    [-classes number of classes <int>]
## \end{verbatim}
## \begin{description}
##   \item[-U]
## 	Print usage information
##   \item[-sn]
## 	filter structure number
##   \item[-dec]
## 	decimate the filter output?
##   \item[-ff]
## 	feature file (HIPS image (sequence))
##   \item[-cf]
## 	classified (output) file (HIPS image)
##   \item[-sf]
## 	output statistics file
##   \item[-rlen]
##	run lengths of the two passes
##   \item[-alpha]
##	$\alpha$ parameter to SOM of the two passes
##   \item[-radius]
##	radius of neighborhood of SOM of the two passes
##   \item[-classes]
## 	number of classes (default 2)
## \end{description}
## 
## \subsection*{Date created}
## March 1994

# Default parameters:
DEC=FALSE
RLEN1=1000
RLEN2=10000
ALPHA1=0.05
ALPHA2=0.02
RADIUS1=""
RADIUS2=""
TOPOL=hexa
NEIGH=bubble
XDIM=2
YDIM=1

# Temporary files:
SOM_DATA=`tempnam`
CLASS_SOM_DATA=`tempnam`
CODEBOOK=`tempnam`
OBJ_FILE=`tempnam`
ROW_FILE=`tempnam`
COL_FILE=`tempnam`


print_usage ()
{
  # Print usage
  echo "som_classify"
  echo "\tOptions:"
  echo "\t  -U		-- print usage"
  echo "\t  -sn ##	-- filter structure number"
  echo "\t  -dec @@   	-- decimated feature file (TRUE or FALSE)"
  echo "\t  -ff @@  	-- input feature file"
  echo "\t  -cf @@  	-- output classified file"
  echo "\t  -sf @@  	-- output statistics file"
  echo "\t  -rlen ## ##	-- run length of training (two-pass training)"
  echo "\t  -alpha ## ##	-- training parameter (two-pass training)"
  echo "\t  -radius ## ##	-- training parameter (two-pass training)"
  echo "\t  -classes ##	-- number of classes in the problem"
  exit 1
}


clean ()
{
  rm -f $SOM_DATA $CLASS_SOM_DATA $CODEBOOK  $OBJ_FILE $ROW_FILE $COL_FILE
}



classification ()
{
  echo "+-----------------------------------------------------------------+"
  echo "| Classify with the Self Organizing Map (SOM)                     |"
  echo "+-----------------------------------------------------------------+"
  ROWS=`hsize -rows $FEATURE_FILE`
  COLS=`hsize -cols $FEATURE_FILE`
  calcpix -o $OBJ_FILE -s "opix=r*256/${ROWS}" -c $ROWS $COLS > $ROW_FILE
  calcpix -o $OBJ_FILE -s "opix=c*256/${COLS}" -c $ROWS $COLS > $COL_FILE

  # Convert from HIPS to LVQ data format
  if [ ${DEC} = TRUE ] ; then
    HIPS2LVQ_PARAM="-sn ${STRUCT}"
    DEC_FACT=`mindec -sn ${STRUCT}`
  else
    HIPS2LVQ_PARAM=""
    DEC_FACT=1
  fi
#  hips2lvq ${HIPS2LVQ_PARAM} -out $SOM_DATA $FEATURE_FILE 
  hips2lvq ${HIPS2LVQ_PARAM} -out $SOM_DATA $FEATURE_FILE $ROW_FILE $COL_FILE

  randinit -din $SOM_DATA -cout $CODEBOOK -xdim $XDIM -ydim $YDIM \
	-topol $TOPOL -neigh $NEIGH -rand 1
  vsom -din $SOM_DATA -cin $CODEBOOK -cout $CODEBOOK -rlen $RLEN1 \
	-alpha $ALPHA1 -radius $RADIUS1 -rand 1
  vsom -din $SOM_DATA -cin $CODEBOOK -cout $CODEBOOK -rlen $RLEN2 \
	 -alpha $ALPHA2 -radius $RADIUS2 -rand 1
  qerror -din $SOM_DATA -cin $CODEBOOK
  visual -din $SOM_DATA -cin $CODEBOOK -dout $CLASS_SOM_DATA

  CLASS_ROWS=`hsize -rows $FEATURE_FILE`
  CLASS_ROWS=`calc ${CLASS_ROWS}/${DEC_FACT}`
  CLASS_COLS=`hsize -cols $FEATURE_FILE`
  CLASS_COLS=`calc ${CLASS_COLS}/${DEC_FACT}`
  lvq2hips -vis -s ${CLASS_ROWS} ${CLASS_COLS} $CLASS_SOM_DATA | \
	htob | enlarge -s $DEC_FACT > ${CLASS_FILE}
}



summary ()
{
  echo "	Classifier			SOM"   	      >  ${STAT_FILE}
  echo "	Classified datafile:            ${CLASS_FILE}">> ${STAT_FILE}
}




# M A I N   P R O G R A M

until [ $# -eq 0 ]; do
  case "${1}" in
    -U		) shift; print_usage ;;
    -sn		) shift; STRUCT="${1}";		shift;;
    -dec	) shift; if [ "${1}" = "TRUE" -o "${1}" = "FALSE" ] ; then
			   DEC=${1}; shift ;
			 else
			   DEC=TRUE
			 fi;;
    -rlen	) shift; RLEN1=${1};		shift; RLEN2=${1};	shift;;
    -alpha	) shift; ALPHA1=${1};		shift; ALPHA2=${1};	shift;;
    -radius	) shift; RADIUS1=${1};		shift; RADIUS2=${1};	shift;;
    -classes	) shift; XDIM=${1};		shift;;
    -ff		) shift; FEATURE_FILE=${1};	shift;;
    -cf		) shift; CLASS_FILE=${1};	shift;;
    -sf		) shift; STAT_FILE=${1};	shift;;
    *		) shift; print_usage ;;
  esac
done

if [ "${RADIUS1}" = "" ]; then
  RADIUS1=`calc "round(sqrt(${XDIM}*${XDIM}+${YDIM}*${YDIM}),4)"`
  RADIUS2=`calc "round(${RADIUS1}/3,4)"`
fi


classification
summary
clean
