#!/usr/bin/env ccp4-python
#
#     Copyright (C) 2005 Ronan Keegan 
#
#     This code is distributed under the terms and conditions of the
#     CCP4 Program Suite Licence Agreement as a CCP4 Application.
#     A copy of the CCP4 licence can be obtained by writing to the
#     CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
#

import os, sys, string, time
import shutil
import urllib

#import MRBUMP_target_info
import Matches 
import Model
import Model_Queue
import Model_struct
import PQS
import PISA
import Ensemble
import MRBUMP_MR
import MRBUMP_HH
import Cleanup
import MRBUMP_loggraphs
import WriteXML
import WriteLogfile
import Dummy_Run
import subprocess
import MRBUMP_writebest
import MRBUMP_HHpred
try:
   import pyrvapi
except:
   #sys.stdout.write("Import warning: No pyrvapi\n")
   sys.stdout.write("")

class Master:
   """ Master script for running MRBUMP """
 
   def __init__(self):
      self.name = ''
      try:
         self.debug=eval(os.environ['MRBUMP_DEBUG'])
      except:
         self.debug=False
 
   def setDEBUG(self, flag):
      self.debug=flag  

   def fast_search_MR(self, init, target_info, mstat):

      queue = None

      # If we want to run a dummy job only (requires example data pickled in folder pickle_data. 
      # Also requires example log files from Phaser/Molrep/Refmac in the same directory
      if init.keywords.DUMMY:
         
         sys.stdout.write("##################################\n")
         sys.stdout.write("###      Running Dummy Job     ###\n")
         sys.stdout.write("##################################\n")
         sys.stdout.write("\n")
   
         dj=Dummy_Run.DummyJob()
         dj.run(init)      
  
         return

      # Set up the directories for the job
      mstat.setSearchDir(init.search_dir)
      mstat.setResultsDir(init.results_dir)
      mstat.setScratchDir(init.scratch_dir)

      # Start the target data processing
      #target_info=MRBUMP_target_info.TargetInfo()

      # Set the log file for matthews coef job
#      target_info.setMattCoefLogfile(os.path.join(init.search_dir, "logs", "matt_coef.log"))

      # Set the target information
#      mstat.InitError = target_info.setTargetInfo(init, init.search_dir)
#      target_info.printTargetInfo(init)

      # Update the no. of mols in the a.s.u. if the user has specified a value
#      if init.keywords.NMASU != None:
#         print "The estimated number of molecules in the asu is: %d" % target_info.no_of_mols 
#         print "The user has specified a value of %d" % init.keywords.NMASU 
#         print "The value will be set to the user defined value"
#         mstat.setEstNoofMols(target_info.no_of_mols)
#         target_info.no_of_mols = init.keywords.NMASU

      # Set the DB's for local-based searches
      mstat.setFastaDB(os.path.join(init.mrbump,'data','pdb_ATOMseqs.txt'))

      # Set the output results html page
      if init.keywords.HTMLOUT == True:
         mstat.setResultsHTML(init.results_html)

      # Make a note of the start time for the job
      mstat.setStartTime(time.time())

      # Set the model preparation and MR parameters
      mstat.setMRNUM(init.keywords.MRNUM)
      mstat.setENSMODNUM(init.keywords.ENSMODNUM)

      # initialize the results page
      #w=Write_Search_results.Write_html()
      if init.keywords.HTMLOUT == True:
         mstat.search_results.write_header(init, mstat.results_html)
         mstat.search_results.write_footer(init, mstat, mstat.results_html)

      # write the target details
      if init.keywords.HTMLOUT == True:
         mstat.search_results.write_target_details(init, mstat, target_info, mstat.results_html)
      
      # If there was an error in the initialisation exit the program
      if mstat.job_end == True:
         sys.exit()
      
      # Assign the ignore list, i.e. the PDB codes that are to be ignored
      mstat.ignore_list=init.keywords.ignore_list
   
      # Assign the include list, i.e. the CHAIN codes that are to be included
      mstat.include_list=init.keywords.include_list
   
      # If there is no pyrvapi module make sure JSRVIEW is not used
      if sys.modules.has_key("pyrvapi") == False:
         init.keywords.JSRVIEW=False
 
      ##############################################################################################
      ##############################################################################################
      # Jsrview
      ##############################################################################################

      if init.keywords.JSRVIEW:
         jsrview = os.path.join(os.environ["CCP4"], "libexec", "jsrview")
         dir_test=os.path.join(os.environ["CCP4"], "crap")
         pyrvapi.rvapi_init_document("aaa", dir_test, "MRBUMP", 1, os.path.join(os.environ["CCP4"],"share","jsrview"), None, None)
         subprocess.Popen([jsrview, os.path.join(dir_test, "index.html")])
   
         pyrvapi.rvapi_add_header("MrBUMP job ??")
         pyrvapi.rvapi_add_tab("tab1", "Input", True)
         pyrvapi.rvapi_add_tab("tab2", "Log file", False)
         log = os.path.join(dir_test, "output.log")
         pyrvapi.rvapi_append_content(log, True, "tab2")
         pyrvapi.rvapi_flush()
   
         pyrvapi.rvapi_add_section("sec1", "MrBUMP Input", "tab1", 0, 0, 1, 1, True)
         #pyrvapi.rvapi_add_section1("tab1/sec2", "Output files", 1, 0, 1, 1, True)
         pyrvapi.rvapi_flush()
   
         pyrvapi.rvapi_add_table1( "sec1/table1", "Target details", 1, 0, 1, 1, True),
   
         # Make column headers(optional)
         #pyrvapi.rvapi_put_horz_theader("table1", "Column 1", "Tooltip 1", 0),
         #pyrvapi.rvapi_put_horz_theader("table1", "Column 2", "", 1),
         #pyrvapi.rvapi_put_horz_theader("table1", "Column 3", "Tooltip 2", 2),
         #pyrvapi.rvapi_put_horz_theader("table1", "Column 4", "", 3),
         
         # Make row headers(optional)
         pyrvapi.rvapi_put_vert_theader("table1", "HKLIN:", "Tooltip 1", 0)
         pyrvapi.rvapi_put_vert_theader("table1", "SEQIN:", "", 1)
         pyrvapi.rvapi_put_vert_theader("table1", "Sequence:", "", 2)
         pyrvapi.rvapi_put_vert_theader("table1", "Number of residues:", "", 3)
         pyrvapi.rvapi_put_vert_theader("table1", "Molecular weight (daltons):", "", 4)
         pyrvapi.rvapi_put_vert_theader("table1", "No. of molecules in asu:", "", 5)
         pyrvapi.rvapi_put_vert_theader("table1", "Data resolution (Angstroms):", "", 6)
   
         pyrvapi.rvapi_put_table_string("table1", os.path.split(target_info.hklin)[-1], 0, 0)
         pyrvapi.rvapi_put_table_string("table1", os.path.split(target_info.seqfile)[-1], 1, 0)
         pyrvapi.rvapi_put_table_string("table1", target_info.sequence, 2, 0)
         pyrvapi.rvapi_put_table_string("table1", str(target_info.no_of_res), 3, 0)
         pyrvapi.rvapi_put_table_string("table1", str(target_info.mol_weight), 4, 0)
         pyrvapi.rvapi_put_table_string("table1", str(target_info.no_of_mols), 5, 0)
         pyrvapi.rvapi_put_table_string("table1", str(target_info.resolution), 6, 0)
         pyrvapi.rvapi_flush()
      else: 
         pyrvapi=None

      ##############################################################################################
      ##############################################################################################

      # Set up the FASTA search
      seq_search=Matches.SEQ_match()
   
      # If DOFASTA is true do the fasta search otherwise just add the specified chain IDs
      if init.keywords.DOFASTA == True:

         # Search information
         sys.stdout.write("\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("###         Fasta search        ###\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("\n")
   
         # Get the FASTA file using the target sequence
         seq_search.get_Fasta_file(init, mstat, target_info, os.path.join(mstat.results_dir,'data','matches'), \
            init.environment.SETUP_DIR)
   
         # Add the resulting chains to the chain list
         seq_search.get_Fasta_matches(init, mstat, target_info, "FASTA")

      # If DOPHMMER is true do the phmmer search
      if init.keywords.DOPHMMER == True:

         # Search information
         sys.stdout.write("\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("###        PHMMER search        ###\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("\n")
   
         # Do the search and add the resulting chains to the chain list
         seq_search.get_Fasta_matches(init, mstat, target_info, "PHMMER")

         # Set the alignment for each chain that was found in the PHMMER search
         for chain in mstat.PHresultsDict.keys():
             if chain[0:4] not in init.keywords.ignore_list:
                #mstat.chain_list[chain].PHalignment=mstat.PHresultsDict[chain].alignments[">" + chain]
                #mstat.chain_list[chain].PHtargetSequence=mstat.PHresultsDict[chain].alignments[">Target_alignment"]
                mstat.chain_list[chain].PHmatch=True

      # If DOHHPRED is true do the hhblits search otherwise just add the specified chain IDs
      if init.keywords.DOHHPRED == True:

         # Search information
         sys.stdout.write("\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("###        HHpred search        ###\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("\n")

         # Set the various log files and output files
         mstat.HHblits_logfile=os.path.join(init.search_dir, "logs", "hhblits.log")
         mstat.HHblits_oa3mfile=os.path.join(init.search_dir, "sequences", "hhblits_oa3m.txt")
         mstat.HHsearch_logfile=os.path.join(init.search_dir, "logs", "hhsearch.log")
         mstat.HHsearch_fastafile=os.path.join(init.search_dir, "sequences", "hhsearch_fasta.txt")

         # Run HHPRED
         hh=MRBUMP_HH.HHpred()
         hh.runHHblits(seqin=target_info.seqfile, \
                       uniprotDB=init.keywords.HHUNIDB, \
                       oa3mFile=mstat.HHblits_oa3mfile, \
                       logfile=mstat.HHblits_logfile, \
                       debug=eval(os.environ["MRBUMP_DEBUG"]))
         hh.runHHsearch(seqout=mstat.HHsearch_fastafile, \
                        ina3mFile=mstat.HHblits_oa3mfile, \
                        pdbDB=init.keywords.HHDBPDB, \
                        logfile=mstat.HHsearch_logfile, \
                        debug=eval(os.environ["MRBUMP_DEBUG"]))
  
         mstat.HHresultsList=hh.resultsList
         mstat.HHresultsDict=hh.resultsDict

         # If this is a webserver run echo the list of results
         if init.keywords.WEBSERVER:
            sys.stdout.write("List of homologues found using HHPred:\n")
            sys.stdout.write("\n")
            sys.stdout.write(",".join(mstat.HHresultsList))
            sys.stdout.write("\n\n")

         # Set the name of the output alignment file 
         #mstat.hhpredALNFile=os.path.join(init.search_dir, "sequences", "hhpred_alignment.a3m")

         # Instantiate
         #HHBLITS=MRBUMP_HHpred.HHblits()

         # Run it
         #HHBLITS.runHHblits(target_info.seqfile, init.keywords.HHDBPDB, mstat.hhpredALNFile, 2)
         #mstat.hhpredList=HHBLITS.hitList

         # Add the resulting chains to the chain list
         seq_search.get_Fasta_matches(init, mstat, target_info , "HHPRED")

         # Set the alignment for each chain that was found in the HHpred search
         for chain in mstat.HHresultsDict.keys():
             if chain[0:4] not in init.keywords.ignore_list:
                #mstat.chain_list[chain].HHalignment=HHBLITS.chainDict[chain].alignment
                #mstat.chain_list[chain].HHtargetSequence=HHBLITS.chainDict[chain].targetSequence
                mstat.chain_list[chain].HHalignment=mstat.HHresultsDict[chain].alignments[">" + chain]
                mstat.chain_list[chain].HHtargetSequence=mstat.HHresultsDict[chain].alignments[">Target_alignment"]
                mstat.chain_list[chain].HHmatch=True

      # Add the specified chains to the list
      seq_search.add_included_chains(init, mstat)

      # Add the specified chains from local files 
      seq_search.add_local_chains(init, mstat, target_info)

      # Process the results from the FASTA search
      if mstat.no_of_SEQhits > 0:
         ps=Matches.Process_Score()
      
         sys.stdout.write("\n")
         sys.stdout.write("---------------------------------------------------------\n")
         sys.stdout.write("Fasta: Getting Template Sequences and Multiple Alignment:\n")
         sys.stdout.write("---------------------------------------------------------\n")
         sys.stdout.write("\n")
   
         #ps.PDB_process(mstat, 'SEQ')
   
         # Extract the sequences for the chains from the pdb datafile
         ps.getPDB_sequences(init, mstat, "SEQ")
   
         # Set the names of the input and output files to be used in the multiple alignment 
         mstat.setAllRawFile(os.path.join(init.search_dir,"sequences","All_raw_seqs_SEQ.fasta"))
         mstat.setAllAlignFile(os.path.join(init.search_dir,"sequences","All_align_seqs_SEQ.fasta"))
   
         # Do the multiple alignment
         list=ps.alignment(mstat.chain_list.keys(), target_info, init, mstat)
   
         # Get the top hit and sort the list of aligned sequences
         ps.get_top_hit(mstat.chain_list.keys(), init, mstat)
   
         sys.stdout.write("Top match from FASTA search: %s\n" % mstat.top_match_chainid)
   
         # First check if it is one of the local PDB files
         #if mstat.top_match_chainid[0:3]=="loc":
         #   mstat.FASTA_top_match_PDBfile=init.keywords.local_list[mstat.top_match_chainid].filename
         #else:
         #   mstat.FASTA_top_match_PDBfile=os.path.join(init.search_dir, "scratch", mstat.top_match_pdbid + ".pdb")
         #   pdb_get=Matches.PDB_get()
         #   pdb_get.download_single_PDB(mstat.top_match_pdbid, mstat.FASTA_top_match_PDBfile, init.keywords.PDBDIR)

      # Exit if no hits were found
      if mstat.no_of_SEQhits == 0:
         if init.keywords.HTMLOUT == True:
            mstat.search_results.write_SEQ_search_details(mstat, mstat.results_html)

         sys.exit()
   
      # write the SEQ search details to the html page
      if init.keywords.HTMLOUT == True:
         mstat.search_results.write_SEQ_search_details(init, mstat, mstat.results_html)

      #shutil.copy('/tmp/ssm_result.xml', mrsearchdir + '/results/ssm_result.xml')

      if init.keywords.SSM == True:

         sys.stdout.write("\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("###          SSM search         ###\n")
         sys.stdout.write("###################################\n")
         sys.stdout.write("\n")

         ssm_search=Matches.SSM_match()

         ssm_search.setSSMScript(os.path.join(init.mrbump_incl,'perl','ssm.pl'))
         ssm_search.get_SSM_file(init, mstat, init.keywords.JOBID, os.path.join(mstat.results_dir,'data','ssm_result.xml'))

         # Check to see if the SSM search failed
         if init.keywords.SSM:
            ssm_search.get_SSM_matches(init, mstat)

            sys.stdout.write("\n")
            sys.stdout.write("-------------------------------------------------------\n")
            sys.stdout.write("SSM: Getting Template Sequences and Multiple Alignment:\n")
            sys.stdout.write("-------------------------------------------------------\n")
            sys.stdout.write("\n")

            #ps.PDB_process(mstat, 'SSM')

            # Extract the sequences for the chains from the pdb datafile
            ps.getPDB_sequences(init, mstat, "SSM")
   
            # Set the names of the input and output files to be used in the multiple alignment 
            mstat.setAllRawFile(os.path.join(init.search_dir,"sequences","All_raw_seqs_SSM.fasta"))
            mstat.setAllAlignFile(os.path.join(init.search_dir,"sequences","All_align_seqs_SSM.fasta"))
   
            # Do the multiple alignment
            list=ps.alignment(mstat.chain_list.keys(), target_info, init, mstat)

            # Get the top hit and sort the list of aligned sequences
            ps.get_top_hit(mstat.chain_list.keys(), init, mstat)

            # write the SSM search details to the html page
            if init.keywords.HTMLOUT == True:
               mstat.search_results.write_SSM_search_details(init, mstat, mstat.results_html)
 
            # Write out the target processing logfile
            ssmlog=WriteLogfile.Logfile()
            ssmlog.writeSSMLog(init, mstat)
            mstat.SSM_logfile=ssmlog.logfile

      # Prune the list
      ps.prune_list(mstat)
      ps.print_list(mstat)
 
      #Ouput the loggraph data for the alignment results
      if init.keywords.WEBSERVER == False:
         lg_plot=MRBUMP_loggraphs.Mrbump_logs()
         lg_plot.plot_alignment_graphs(init, mstat)
  
      ps.PDB_process(init, mstat)
 
      # Search the SCOP database to see if any domains exist in the template structures
      if init.keywords.SCOP == True:

         sys.stdout.write("\n")
         sys.stdout.write("#####################################################\n")
         sys.stdout.write("###          Searching for Domains (SCOP)         ###\n")
         sys.stdout.write("#####################################################\n")
         sys.stdout.write("\n")

         scop_search=Matches.SCOP_match()
         scop_search.get_SCOP_matches(init, mstat, init.environment.SETUP_DIR)
   
         if mstat.no_of_SCOPhits > 0:
            sys.stdout.write("\n")
            sys.stdout.write("---------------------------\n")
            sys.stdout.write("SCOP: Processing PDB files:\n")
            sys.stdout.write("---------------------------\n")
            sys.stdout.write("\n")

         # ps.PDB_process(mstat, 'SCOP')

         # Extract the sequences for the chains from the pdb datafile
         #ps.getPDB_sequences(init, mstat, "SSM")
   
         # Set the names of the input and output files to be used in the multiple alignment 
         mstat.setAllRawFile(os.path.join(init.search_dir, "sequences", "All_raw_seqs_SCOP.fasta"))
         mstat.setAllAlignFile(os.path.join(init.search_dir, "sequences", "All_align_seqs_SCOP.fasta"))

         # Add the SCOP results into the MR list before re-alignment and sorting   
         mstat.sorted_MR_list = mstat.sorted_MR_list + mstat.Domains_list

         # Do the multiple alignment
         list=ps.alignment(mstat.sorted_MR_list, target_info, init, mstat)
         mstat.sorted_MR_list=list

         # Get the top hit and sort the list of aligned sequences
         ps.get_top_hit(mstat.sorted_MR_list, init, mstat)

         # write the SSM search details to the html page
         if init.keywords.HTMLOUT == True:
            mstat.search_results.write_domains_search_details(init, mstat, mstat.results_html)
 
         # Re-sort the list to take into account the SCOP results scores
         ps.re_sort_MR_list(mstat)
         ps.print_pruned_list(mstat)

      # write the overall search details to the html page
      if init.keywords.HTMLOUT == True:
         mstat.search_results.write_ALL_search_details(init, mstat, target_info, mstat.results_html)
      
      ##############################################################################################
      ##############################################################################################
      # Jsrview
      ##############################################################################################

      if init.keywords.JSRVIEW:
         pyrvapi.rvapi_add_tab("tab3", "Model Search", False)
         pyrvapi.rvapi_flush()

      ##############################################################################################
      ##############################################################################################

      # Do the modelling of the PDB model structures
      sys.stdout.write("\n")
      sys.stdout.write("###########################################\n")
      sys.stdout.write("###       Search Model Preparation      ###\n")
      sys.stdout.write("###########################################\n")
      sys.stdout.write("\n")
      
      # Output the details of what will be modelled
      sys.stdout.write("The following types of model will be generated:\n")
      sys.stdout.write("\n")
      for i in init.model_types:
         sys.stdout.write("%s -- " % i)
         if i == 'UNMOD':
            sys.stdout.write("Unmodified models.\n") 
         if i == 'PDBCLP':
            sys.stdout.write("PDBclip model, waters, hydrogens removed + most probable side-chain conformations.\n") 
         if i == 'PLYALA':
            sys.stdout.write("Polyalanine model, all side chains removed.\n") 
         if i == 'MOLREP':
            sys.stdout.write("Molrep generated model, side chains pruned according to sequence alignment.\n") 
         if i == 'CHNSAW':
            sys.stdout.write("Chainsaw generated model, side chains pruned according to sequence alignment.\n") 
         if i == 'SCLPTR':
            sys.stdout.write("Sculptor generated model, side chains pruned according to sequence alignment.\n") 
      sys.stdout.write("\n")

      model=Model.Modelling()
      model.convert_to_pir(mstat, target_info)

      # Prepare polyalanine models using 
      if init.keywords.MDLUNMOD:
         model.unmodModel(target_info, init, mstat)

      # Prepare polyalanine models using 
      if init.keywords.MDLPLYALA:
         model.polyala(target_info, init, mstat)

      # Prepare models using Molrep
      if init.keywords.MDLMOLREP:
         model.molrepModel(target_info, init, mstat)
      
      # Multiple alignment input to Chainsaw
      if init.keywords.MDLCHAINSAW:
         model.chainsawModel(target_info, init, mstat)
      
      # Multiple alignment input to Sculptor
      if init.keywords.MDLSCULPTOR:
         model.sculptorModel(target_info, init, mstat)

      # Monitor the queue for the completion of all the jobs
      
      if init.keywords.CLUSTER == True:
         queue=Model_Queue.Queue_info()
         queue.qstat_check(init, mstat, target_info, 'MODEL_PREP')

         # Print out the summary of results so far
         #best=MRBUMP_writebest.BestLog()
         #best.write_results_log(init, mstat)
         #mstat.sorted_soln_list=best.sorted_soln_list
         #sys.stdout.write(best.report)

         mstat.resetJobid_Array()
         mstat.resetJobid_Dict()
         mstat.resetJobName_Dict()
   
      # Write the overall search details to the html page
      mstat.search_results.write_model_prep_details(init, mstat, target_info, mstat.results_html)
      
      # Output the loggraph data for the model preparation results
      if init.keywords.MDLMOLREP or init.keywords.MDLCHAINSAW:
         lg_plot=MRBUMP_loggraphs.Mrbump_logs()
         lg_plot.plot_model_prep_graphs(init, mstat)

         ##################################################################

      # Note on PISA positioning
      # Needs to be after PDB coord download, and before ONLYMODELS exit. 
      # Have it after model editing so that we form multimers of models rather than templates.
      # Having it after SCOP means we could have multimers of domains.

      # If the number of molecules in our target is greater than 1 consult PISA for multimers
      if target_info.no_of_mols >= 2 and init.keywords.PISA == True:

         sys.stdout.write("\n")
         sys.stdout.write("#####################################################\n")
         sys.stdout.write("###          Searching for Multimers (PISA)       ###\n")
         sys.stdout.write("#####################################################\n")
         sys.stdout.write("\n")
      
         pisa=PISA.PISA()
         pisa.get_pisa_files(target_info, init, mstat)
   
      # Ensemble preparation moved here from MR_start
      # If we are using an Ensemble model then set it up. We now do this
      # whatever MR program chosen - Molrep should ignore an ensemble_model model.
      if init.keywords.USEENSEM:

         sys.stdout.write("###############################################################################\n")
         sys.stdout.write("### Model Preparation log: Setting up ensemble model from top search models ###\n")
         sys.stdout.write("###############################################################################\n")
         sys.stdout.write("\n")

         # Make sure we are not asking for more models than are in the MR list
         if mstat.num_MR_models < init.keywords.ENSMODNUM:
            init.keywords.ENSMODNUM=mstat.num_MR_models
            sys.stdout.write("Resetting the number in the ensemble to " + `init.keywords.ENSMODNUM`
                             + " as there are not enough models for the specified value\n")
            sys.stdout.write("\n")

         ens=Ensemble.Ensemble()
         ens.setup_ensemble(mstat, init)

         # write the ensemble details to the html page
         if init.keywords.HTMLOUT == True:
            mstat.search_results.write_ensemble_details(init, mstat, target_info, mstat.results_html)
   
      else:
         sys.stdout.write("Model Preparation log: Use Ensemble set to 'False' - no ensemble will be created.\n")
         sys.stdout.write("\n")
 
      #If user only wants to generate the models then we will exit at this point.
      if init.ONLYMODELS == True:

         # Output the list of models that has been created
         mr_setup=Model_struct.MR_setup()
         mr_setup.setTypes(init, mstat, init.search_dir)

         # Print the references and exit
         if init.keywords.HTMLOUT == True:
            mstat.mr_results.print_references(init, mstat)
         mstat.mr_results.print_references_stdout(init)

         # Pickle the objects for running as input for a dummy run later
         if init.keywords.PICKLE:
         
            sys.stdout.write("#############################################################\n")
            sys.stdout.write("###      Pickling the objects for running a dummy job     ###\n")
            sys.stdout.write("#############################################################\n")
            sys.stdout.write("\n")
   
            dj=Dummy_Run.DummyJob()
            dj.pickle(init, mstat, target_info)      
    
         finish_time = time.ctime()
         finish_file = open(os.path.join(mstat.results_dir,'finished.txt'), 'w')
         finish_file.write('Job finished: ' + finish_time)
         finish_file.write('')
         finish_file.write('Information only, please do not reply to this email.')
         finish_file.close()
      
         sys.exit(0)      

      ##############################################################################################
      ##############################################################################################
      # Jsrview
      ##############################################################################################

      if init.keywords.JSRVIEW:
         pyrvapi.rvapi_add_tab("tab4", "Model Preparation", False)
         pyrvapi.rvapi_flush()

      ##############################################################################################
      ##############################################################################################

      # Setup the models for MR
      mr_setup=Model_struct.MR_setup()
      mr_setup.setTypes(init, mstat, init.search_dir)
      
      # Write the header for the MR secion
      if init.keywords.HTMLOUT==True:
         mstat.mr_results.write_MR_header(init, mstat)

      return queue
      
   def runMR(self, init, target_info, mstat, queue=None):
      """ Function for running molecular replacement. """   

      ##############################################################################################
      ##############################################################################################
      # Jsrview
      ##############################################################################################

      if init.keywords.JSRVIEW:
         pyrvapi.rvapi_add_tab("tab5", "MR & Refinement", True)
         pyrvapi.rvapi_flush()

      #pyrvapi.rvapi_add_tab ( "tree_tab","Tree Widget",True ),

      ##############################################################################################
      ##############################################################################################

      #  Announce the Molecular Replacement stage
      sys.stdout.write("##############################################################\n")
      sys.stdout.write("###           Molecular Replacement and Refinement         ###\n")
      sys.stdout.write("##############################################################\n")
      sys.stdout.write("\n")
      
      # If the number of molecules in our target is greater than 1 consult PQS for multimers
      if target_info.no_of_mols >= 2 and init.keywords.PQS == True:
      
         sys.stdout.write("\n")
         sys.stdout.write("------------------------------\n")
         sys.stdout.write("Searching for Multimers (PQS):\n")
         sys.stdout.write("------------------------------\n")
         sys.stdout.write("\n")
      
         pqs=PQS.PQS()
      
         pqs.set_pqs_list(init.environment.SETUP_DIR)
         pqs.get_pqs_files(init, target_info, mstat, init.keywords.MAPROGRAM)
      
         # write the PQS search details to the html page
         if init.keywords.HTMLOUT == True:
            mstat.search_results.write_PQS_search_details(init, mstat, target_info, mstat.results_html)
      
      # Do the molecular replacement using the model list
      MR=MRBUMP_MR.MR_submit()
      
      # Loop over the list of MR programs set at the start
      #for MRPROGRAM in init.keywords.MR_PROGRAM_LIST: 

      sys.stdout.write("*********************************************************************************\n")
      sys.stdout.write("*********************************************************************************\n")
      sys.stdout.write("*********************************************************************************\n")

      # Echo the name of the MR program being used to the stdout
      #sys.stdout.write("MR log: Using " + MRPROGRAM + " for molecular replacement:\n")
      #sys.stdout.write("\n")
           
      #mstat.setMRPROGRAM(MRPROGRAM.upper())
      #if sys.modules.has_key("pyrvapi") == False:
      #   pyrvapi = None
      if init.keywords.JSRVIEW:
         MR.MR_start(target_info, init, mstat, init.keywords.QSIZE, pyrvapi)
      else:
         MR.MR_start(target_info, init, mstat, init.keywords.QSIZE, None)
      
      # Poll the queue to see if the jobs have finished
      if init.keywords.CLUSTER == True:
   
         sys.stdout.write("\n")
         sys.stdout.write("---------------------------\n")
         sys.stdout.write("Results (post-refinement):\n")
         sys.stdout.write("---------------------------\n")
         sys.stdout.write("\n")
        
         if queue==None:
            queue=Model_Queue.Queue_info()
         queue.qstat_check(init, mstat, target_info, 'MOL_REPLACE', MR)
         mstat.resetJobid_Array()
         mstat.resetJobid_Dict()
         #mstat.resetJobName_Dict()
   
         # Print out the summary of results so far
         best=MRBUMP_writebest.BestLog()
         best.write_results_log(init, mstat)
         mstat.sorted_soln_list=best.sorted_soln_list
         sys.stdout.write(best.report)

      # If running in TRYALL mode capture a summary of the results
      if init.keywords.TRYALL:
         mstat.mr_results.setTRYALL_summary(init, mstat)
        
      if mstat.solution_found == False: 
         sys.stdout.write("\n")
         sys.stdout.write("No solution was found using the following MR programs:\n")
         count=1
         for MRPROGRAM in init.keywords.MR_PROGRAM_LIST:
            sys.stdout.write(`count` + ". " + MRPROGRAM + "\n")
            count=count + 1
         sys.stdout.write("\n")

      # If running in TRYALL mode output a summary of the results for each MR program
      #for MRPROGRAM in init.keywords.MR_PROGRAM_LIST: 
      #   if init.keywords.TRYALL:
      #      sys.stdout.write(mstat.TRYALL_summary[MRPROGRAM])

      # write the final solution details to the html page
      mstat.setJob_End(True)
      if init.keywords.HTMLOUT==True:
         mstat.mr_results.write_final_soln(init, mstat, target_info)

      # Display the references in the results html file and the output logfile.
      if init.keywords.HTMLOUT==True:
         mstat.mr_results.print_references(init, mstat)
      mstat.mr_results.print_references_stdout(init)

      if mstat.solution_found == True and init.keywords.TRYALL == False:
         if mstat.soln_MRprogram == "MOLREP":
            shutil.copy(mstat.model_list[mstat.soln_model].refmac_molrep_MTZOUTfile , init.hklout)
            shutil.copy(mstat.model_list[mstat.soln_model].refmac_molrep_PDBfile , init.xyzout)
         if mstat.soln_MRprogram == "PHASER":
            shutil.copy(mstat.model_list[mstat.soln_model].refmac_phaser_MTZOUTfile , init.hklout)
            shutil.copy(mstat.model_list[mstat.soln_model].refmac_phaser_PDBfile , init.xyzout)
           
      # Ouput the job details to an XML file
      if init.keywords.XMLOUT:
         xml=WriteXML.writeXML()
         xml.write_details(init, mstat, target_info, init.keywords.SUMMARYFILE) 

      # Pickle the objects for running as input for a dummy run later
      if init.keywords.PICKLE:
        
         sys.stdout.write("#############################################################\n")
         sys.stdout.write("###      Pickling the objects for running a dummy job     ###\n")
         sys.stdout.write("#############################################################\n")
         sys.stdout.write("\n")
   
         dj=Dummy_Run.DummyJob()
         dj.pickle(init, mstat, target_info)      

      finish_time = time.ctime()
      finish_file = open(os.path.join(mstat.results_dir,'finished.txt'), 'w')
      finish_file.write('Job finished: ' + finish_time)
      finish_file.write('')
      finish_file.write('Information only, please do not reply to this email.')
      finish_file.close()
      
      # If running in LITE mode remove the input and PDB_files directories contents
      if init.keywords.LITE:
         purge=Cleanup.Clean()
         purge.purgeDirectory(os.path.join(init.search_dir, "logs"))
         purge.purgeDirectory(os.path.join(init.search_dir, "PDB_files"))
         purge.purgeDirectory(os.path.join(init.search_dir, "scratch"))
         purge.purgeDirectory(os.path.join(init.search_dir, "results", "data"))
         

      # Some space saving
      if init.keywords.DEBUG == False:
          if os.path.isfile(target_info.refinement_hklin):
              os.remove(target_info.refinement_hklin)

      # Remove the data directory to save memory space
      if init.keywords.CLEAN:
         sys.stdout.write("Cleanup: Removing surplus search data and scratch directory\n")
         cleanup=Cleanup.Clean()
         cleanup.clean_data_dir(mstat, init.keywords.OVERWRITE)
         cleanup.rm_dir(os.path.join(init.search_dir,'scratch'))
      
      # If this is a webserver run tar-up the entire directory for downloading
      if init.keywords.WEBSERVER:
          import tarfile     
          currDIR=os.getcwd()
          tar=tarfile.open(os.path.join(init.search_dir, "mrbump_results.tar.gz"), "w:gz")
          os.chdir(os.path.split(init.search_dir)[0])
          for name in [os.path.split(init.search_dir)[-1]]:
             tar.add(name)
          tar.close()
          os.chdir(currDIR)

      sys.exit(0)
