#! /bin/sh
####################################################
#
#  NAME:
#    ObtainSimilarityBlast.sh (sh)
#  AUTHOR:
#    Moises Burset
#  HISTORY:
#    Version 1.0 -> 09-06-98
#    Version 1.1 -> 18-08-99
#     -Change completely how parameters are passed and add align option
#      Program can parse blast 1.4 and 2.0 formats
#     -Format change in text files from web requests in blast 2.0.11 added
#    Last modification -> 13-04-00
#  DESCRIPTION:
#    This program parse the blast results and obtain similarity
#    regions
#  INPUT:
#    variables:
#    parameters:
#      -help -> print help message
#      -minscr float -> minscore
#      -maxprb float -> maxprob
#      -minsim float -> minsim
#      -minlen int -> minlength
#      -align -> report alignments
#    files:
#      <STDIN> -> blast results
#  OUTPUT:
#    variables:
#    files:
#      <STDOUT> -> query subjc query1pos query2pos subj1pos subj2pos sim score prob [align]
#      <STDERR> -> Errors in execution
#  RETURN:
#    2 -> printing help
#    0 -> correct execution
#    1 -> error in execution
#  DEPENDENCES:
#  BUGS:
#  COMMENTS:
#
####################################################

InitializeVariables () {
  #Constants:
  PROGRAM=ObtainSimilarityBlast.sh
  #Variables:
  MINSCORE=0
  MAXPROB=1
  MINSIM=0
  MINLENGTH=0
  ALIGN=0
}

Error () {
  echo "There are this error in program execution" 1>&2
  echo "    "$1 1>&2
  echo "" 1>&2
  echo "If you don't know how to run $PROGRAM type \"$PROGRAM -help\"" 1>&2
  exit 1
}

Help () {
  echo ""
  echo ""
  echo "NAME"
  echo "       $PROGRAM - parse blast results and obtain similarities"
  echo ""
  echo "SYNOPSIS"
  echo "       $PROGRAM [-help] [-minscr minscore] [-maxprb maxprobability]"
  echo "                 [-minsim minsimilarity] [-minlen minlength] [-align]"
  echo ""
  echo "DESCRIPTION"
  echo "       This program parse the blast results and obtain similarity"
  echo "   regions"
  echo ""
  echo "   OPTIONS"
  echo "      -help"
  echo "            Print this message and exit (return 2)"
  echo ""
  echo "      -minscr float"
  echo "            Minimum blast score (default 0)"
  echo ""
  echo "      -maxprb float"
  echo "            Maximum blast match probability (default 1)"
  echo ""
  echo "      -minsim float"
  echo "            Minimum similarity (in percent, default 0)"
  echo ""
  echo "      -minlen int"
  echo "            Minimum match length (default 0)"
  echo ""
  echo "      -align"
  echo "            Report alignment (default is NOT printed)"
  echo "            Upper case letters means insertion in subject"
  echo "            Lower case letters means substitution in subject"
  echo ""
  echo "AUTHOR"
  echo "       Moises Burset"
  echo ""
  echo ""
  echo ""
  exit 2
}

Exist () {
  if [ -z "$2" ]
  then
    Error "You must write a valid argument to $1 specified option"
  fi
}

IsNumber () {
  if [ "`gawk 'BEGIN{if (length(ARGV[1]+0)==length(ARGV[1])) print 1}' $2`" != "1" ]
  then
    Error "You must write a number with max 4 decimals as argument to $1 option"
  fi
}

ReadArgv () {
  while [ $1 ]
  do
    case $1 in
    -[Hh][Ee][Ll][Pp])
      Help;;
    -[Mm][Ii][Nn][Ss][Cc][Rr])
      opt=$1
      shift 2>/dev/null
      Exist $opt $1
      IsNumber $opt $1
      MINSCORE=$1
      shift 2>/dev/null;;
    -[Mm][Aa][Xx][Pp][Rr][Bb])
      opt=$1
      shift 2>/dev/null
      Exist $opt $1
      IsNumber $opt $1
      MAXPROB=$1
      shift 2>/dev/null;;
    -[Mm][Ii][Nn][Ss][Ii][Mm])
      opt=$1
      shift 2>/dev/null
      Exist $opt $1
      IsNumber $opt $1
      MINSIM=$1
      shift 2>/dev/null;;
    -[Mm][Ii][Nn][Ll][Ee][Nn])
      opt=$1
      shift 2>/dev/null
      Exist $opt $1
      IsNumber $opt $1
      MINLENGTH=$1
      shift 2>/dev/null;;
    -[Aa][Ll][Ii][Gg][Nn])
      ALIGN=1
      shift 2>/dev/null;;
    *)Error "I don't know the $1 parameter";;
    esac
  done
}

##########     MAIN PROGRAM     ##########
# Initialize
InitializeVariables
ReadArgv "$@"

gawk 'BEGIN{
  minscore=ARGV[1]
  maxprob=ARGV[2]
  minsim=ARGV[3]
  minlength=ARGV[4]
  BitAlign=ARGV[5]
  ARGV[1]=ARGV[2]=ARGV[3]=ARGV[4]=ARGV[5]=""
}
{
  if ($1=="Query=") {
    PrintMatch()
    query=$2
  }
  if (substr($1,1,1) == ">" || (substr($0,1,1)==" " && substr($0,2,1)!=" " && $2!="=")) {
    PrintMatch()
    gsub(/>/,"",$0)
    subj=$1
  }
  if ($1=="Score") {
    PrintMatch()
    score=$3
    prob=$NF
  }
  if ($1=="Identities") {
    gsub(/\,/,"",$4)
    sim=substr($4,2,length($4)-3)
  }
  if (substr($0,1,6)=="Query:") {
    if (score+0>=minscore && prob+0<=maxprob && sim+0>=minsim) {
      if (!p1) {
        p1=$2
        p2=$4
      }
      else
        p2=$4
      if (BitAlign) {
        tmpquery=$3
        getline
        while (substr($0,1,1)==" ")
          $0=substr($0,2,length($0))
        tmpalign=$0
      }
    }
  }
  if (substr($0,1,6)=="Sbjct:") {
    if (!q1) {
      align=""
      q1=$2
      q2=$4
    }
    else
      q2=$4
    if (BitAlign)
      for (i=1;i<=length($3);i++) {
        if (substr(tmpalign,i,1)=="|")
          align=align"."
        else {
          if (substr(tmpquery,i,1)=="-")
            align=align""toupper(substr($3,i,1))
          else
            align=align""tolower(substr($3,i,1))
        }
      }
  }
}
END {
  PrintMatch()
}
function PrintMatch () {
  if (p1 && (p1-p2>minlength || p2-p1>minlength)) {
    if (p1<p2)
      print query,subj,p1,p2,q1,q2,sim,score,prob,align
    else
      print query,subj,p2,p1,q2,q1,sim,score,prob,align
  }
  p1=q1=""
}' $MINSCORE $MAXPROB $MINSIM $MINLENGTH $ALIGN
