BuildFeatures/GenDistFeatures4Proteins.sh
#!/bin/sh

if [[ -z "${DistFeatureHome}" ]]; then
        echo "ERROR: Please set environmental variable DistFeatureHome to the installation folder of BuildFeatures "
        exit 1
fi

GPUMachineFile=$DistFeatureHome/params/GPUMachines.txt
GPUmode=4

gpu=-1
numAllowedJobs=3
numAllowedMSAs=2

function Usage
{
	echo $0 "[ -g gpu | -n numJobs | -m numMSAs | -r machineMode | -h MachineFile ] proteinListFile MetaFolder"
	echo "	This script generates distance features for a set of proteins, each having multiple MSAs generated by different methods and settings"
	echo "	proteinListFile: a file for a list of protein names, each in one row"
	echo "	MetaFolder: a folder for all input. This folder shall contain XXX_OUT for each protein where XXX is the protein name."
	echo "	     XXX_OUT shall contain one subfolder XXX_contact, which shall be writable and have subfolders XXX_uce3, XXX_uce3_meta ..."
	echo "	     Each subfolder (e.g., XXX_uce3) shall contain an MSA in a3m format"
	echo "	The results will be saved to new subfolders XXX_contact/feat_XXX_uce3/, XXX_contact/feat_XXX_ure3/... "
	echo " "
	echo "	gpu: -1 (default), 0-3. If -1, select one GPU automatically"
	echo "	numJobs: the number of proteins to be run simultaneously, default $numAllowedJobs"
	echo "	numMSAs: the number of MSAs of the same proteins to be run simultaneously, default $numAllowedMSAs"
	echo "	     Note that all the (numJobs * numMSAs) jobs may compete for the same GPU, so using a small value for both. Set gpu=-1 may use multiple GPUs if availble"
	echo "	-r: specifiy what kind of CPUs and GPUs to use, default $GPUmode"
        echo "	     1: use local GPUs if available"
        echo "	     2: use local GPUs and CPUs"
        echo "	     3: use local GPUs and GPUs of machines defined by the -h option"
        echo "	     4: use local GPUs/CPUs and GPUs of machines defined by the -h option"
        echo "	-h: a file specifying remote machines with GPUs, default $GPUMachineFile"
}

while getopts ":g:n:m:r:h:" opt; do
        case $opt in
        g )
                gpu=$OPTARG
                ;;
        n )
        	numAllowedJobs=$OPTARG
        	;;
	m )
		numAllowedMSAs=$OPTARG
		;;
	h )
                GPUMachineFile=$OPTARG
                ;;
        r )
                GPUmode=$OPTARG
                ;;
        #-> help
        \?)
                echo "Invalid option: -$OPTARG" >&2
                exit 1
                ;;
        :)
                echo "Option -$OPTARG requires an argument." >&2
                exit 1
                ;;
        esac
done
shift $((OPTIND -1))

if [ $# -ne 2 ]; then
	Usage
	exit 1
fi

proteinListFile=$1
if [ ! -f $proteinListFile ]; then
	echo "ERROR: invalid protein list file $proteinListFile"
	exit 1
fi

proteins=`cat $proteinListFile `

MetaDir=$2
if [ ! -d $MetaDir ]; then
	echo "ERROR: invalid folder for inputs: $MetaDir "
	exit 1
fi

cmd=`readlink -f $0 `
cmdDir=`dirname $cmd`
program=$cmdDir/GenDistFeatures4OneProtein.sh
if [ ! -x $program ]; then
	echo "ERROR: $program not executable"
	exit 1
fi

keywords=`basename $program`
myself=`basename $0 `

for protein in $proteins
do
	ContactDir=$MetaDir/${protein}_OUT/${protein}_contact
	if [ ! -d $ContactDir ]; then
		echo "ERROR: $protein has an invalid folder for MSAs: $ContactDir"
		exit 1
	fi

	if [ ! -w $ContactDir ]; then
		echo "ERROR: the folder for $protein not writable: $ContactDir"
		exit 1
	fi

	while true
	do
                numRunningJobs=`ps -x | grep ${keywords} | grep -v ${myself} | wc -l`
                if [ $numRunningJobs -lt $numAllowedJobs ]; then
                	$program -g $gpu -n $numAllowedMSAs -r $GPUmode -h $GPUMachineFile $protein $ContactDir &
			sleep 1
                        break
                else
                        a=`expr $RANDOM % 4 `
                        sleep $a
                fi
	done
done

wait
