# This script submits a motif file and a FASTA file to the FIMO web service at NBCR
# and downloads the resulting output to the directory fimo_out.
# Based on the script pdb2pqrclient.pl included in the 2.0.0 Opal-Python
# toolkit, available at http://www.nbcr.net/software/opal/

# Import the Opal libraries
from AppService_client import \
     AppServiceLocator, getAppMetadataRequest, launchJobRequest, \
     queryStatusRequest, getOutputsRequest, \
     launchJobBlockingRequest, getOutputAsBase64ByNameRequest
from AppService_types import ns0
from os import mkdir
from time import sleep
from ZSI.TC import String


# Set the location of our service
# A list of NBCR services can be found at http://ws.nbcr.net/opal2/dashboard?command=serviceList
serviceURL = "http://ws.nbcr.net/opal2/services/FIMO_4.4.0"

# Instantiate a new service object to interact with.  Pass it the service location
appLocator = AppServiceLocator()
appServicePort = appLocator.getAppServicePort(serviceURL)
    
# Instantiate a new blocking job request
req = launchJobRequest()

# Set the command-line arguments for the job.
# The first two items must be the motif filename
# and the sequence db filename. Note that the 
# sequence db filename must be set to uploaded_db
# The FIMO web service uses this to indicate that
# The sequence db is being uploaded, rather then
# using one of the preloaded databases.
# the '--oc .' option is required for Opal
# to see all the output files created by FIMO
req._argList = "crp0.meme.xml uploaded_db --oc ."
# Alternatively, use the argList setting below to scan the 
# preloaded Saccaromyces cerevisiae genome.
#req._argList = "crp0.meme.xml saccharomyces_cerevisiae.na  --oc ."

# Get contents of local files to be used as input
fastaFile = open("./crp0.fasta", "r")
fastaFileContents = fastaFile.read()
fastaFile.close()
motifFile = open("./crp0.meme.xml", "r")
motifFileContents = motifFile.read()
motifFile.close()

# Set name and content of remote input file.
# Two input files are used, the motif file
#and the FASTA file.
inputFiles = []
motifInputFile = ns0.InputFileType_Def('inputFile')
motifInputFile._name = 'crp0.meme.xml'
motifInputFile._contents = motifFileContents
inputFiles.append(motifInputFile)
fastaInputFile = ns0.InputFileType_Def('inputFile')
fastaInputFile._name = 'uploaded_db'
fastaInputFile._contents = fastaFileContents
inputFiles.append(fastaInputFile)
req._inputFile = inputFiles

# Launch a non-blocking job
print "Launching non-blocking FIMO job"
resp = appServicePort.launchJob(req)
jobID = resp._jobID
print "Received Job ID:", jobID

# Poll for job status
status = resp._status
print "Polling job status"
while 1:
  # print current status
  print "Status:"
  print "\tCode:", status._code
  print "\tMessage:", status._message
  print "\tOutput Base URL:", status._baseURL

  if (status._code == 8) or (status._code == 4): # STATUS_DONE || STATUS_FAILED
    break

  print "Waiting 30 seconds"
  sleep(30)
  
  # Query job status
  status = appServicePort.queryStatus(queryStatusRequest(jobID))

if status._code == 8: # 8 = GramJob.STATUS_DONE

  # Create local directory to hold output files
  output_dir = 'fimo_out'
  mkdir(output_dir);

  # Find out what outputs were generated by the job
  outputs = appServicePort.getOutputs(getOutputsRequest(jobID))

  # Instantiate a request object for reteiving output files
  req = getOutputAsBase64ByNameRequest()

  # Retreive each output file and save to local directory.
  # MEME writes stdout and stderr to files that aren't listed
  # in the response, so we handle those separately.
  print "\tStandard Output:", outputs._stdOut
  output = open(output_dir + '/' + "stdout.txt", "w")
  req._jobID = resp._jobID
  req._fileName = "stdout.txt"
  content = appServicePort.getOutputAsBase64ByName(req)
  print >>output, content
  output.close()
  print "\tStandard Error:", outputs._stdErr
  output = open(output_dir + '/' + "stderr.txt", "w")
  req._jobID = jobID
  req._fileName = "stderr.txt"
  content = appServicePort.getOutputAsBase64ByName(req)
  print >>output, content
  output.close()
  # Loop for all the other output files.
  for outputFile in outputs._outputFile:
    # List of output files include 'bin' directory which we should skip.
    if outputFile._name == "bin" or outputFile._name == "data":
      # Bin is a directory, and not of intereest
      # so skip it
      continue
    print "\t" + outputFile._name, ":", outputFile._url
    output = open(output_dir + '/' + outputFile._name, "w")
    req._jobID = jobID
    req._fileName = outputFile._name
    content = appServicePort.getOutputAsBase64ByName(req)
    print >>output, content
    output.close()
