#!/usr/bin/python

# See below for name and description
# Copyright (C) 2011 Norman E. Davey
#  
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program; if not, write to 
# the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
# To incorporate this module into your own programs, please see GNU Lesser General Public License disclaimer in rje.py

"""
Program:      SLiMPrints
Description:  Short Linear Motif fingerPrints
Version:      3.0
Last Edit:    29/11/11
Copyright (C) 2011  Norman E. Davey - See source code for GNU License Notice
"""

import sys,copy,random,math,os,time,getopt,re,traceback,urllib,difflib,types

sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)),"../libraries/"))

import ned_SLiMPrints as slimprints
import ned_SLiMPrints_Tester as slimprints_Tester

import ned_commandLine as commandLine

import ned_proteinInfoHelper as proteinInfoHelper
import ned_conservationScorer as conservationHelper
import ned_basic as basic

#slimprints.py -a ../Datasets/Alignments/Human/ -c0.35 -qT -W30 -PF -fT -m0.1 -FF
version = 3

optionsVariables = {
		'alignment':"-a",
		'accession':"-A",
		'destination_file':"-d",
		"scoreWeight":"-s",
		"start":"-x",
		"stop":"-y",
		"help":"-h",
		"minScore":"-m",
		"MinSpec":"-B",
		"iucut":"-c",
		"maxLength":"-l",
		"gap":"-g",
		"rlcScorer":"-r",
		"weighted":"-b",
		"offsets":"-o",
		"offsets_file":"-O",
		"scoreWeight":"-w",
		"maxCount":"-M",
		"dis_weight":"-Q",
		"window":"-W",
		"printSub":"-p",
		"probScores":"-P",
		"server":"-S",
		"startFrom":"-R",
		"iupath":"-u",
		"idFile":"-i",
		"quiet":"-q",
		"clustalw":"-C",
		"findMotifs":"-N",
		"FastTree":"-F",
		"force":"-f",
		"dat_file":"-D",
		"jobList":"-J",
		"filter_uniprot":"-U",
		"prune_long":"-L",
		"analyse_scores":"-Z"
		}

optionsDesc = {
		'accession':"Uniprot accessions [list comma seperated]",
		'alignment':"Alignment in fasta format [path]",
		"start":"Start of window",
		"stop":"End of window",
		"help":"This",
		"minScore":"Minimum score of residue considered in motif discovery",
		"iucut":"Disorder cut-off",
		"maxLength":"Maximum motif length",
		"gap":"Maximum gap length",
		"rlcScorer":"Score motifs",
		"offsets":"List of motifs offsets to score Motif:offset,....",
		"maxCount":"Number of results returned",
		"dis_weight":"Scaling to be used in disorder weighting",
		"window":"Window size for calcualtions",
		"printSub":"Whether to output sub-motifs",
		"probScores":"Weight to calculate probability based scores",
		"server":"If runnning a server",
		"iupath":"Path to Iupred",
		"startFrom":"Restart from",
		"quiet":"Whether to output anything to screen",
		"findMotifs":"Whether run SLiMPrints",
		
		"filter_uniprot":"Whether to filter based on UNIPROT features Domain, TRANSMEM and Extracellular",
		"dat_file":"Uniprot dat file for masking of features",
		
		"clustalw":"Path to clustal",
		"FastTree":"Path to FastTree",
		"prune_long":"Prune branches greater 1 from root",
		
		"analyse_scores":"Get stats for an analysis"
		}
		
options = {
		'accession':"",
		'alignment':"",
		'destination_file':"",
		"start":0,
		"stop":0,
		"minScore":0.2,
		"maxCount":1000,
		"window":25,
		"MinSpec":4,
		"iucut":0.3,
		"maxLength":5,
		"dis_weight":1,
		"gap":2,
		"rlcScorer":'F',
		"weighted":"T",
		"offsets":"",
		"offsets_file":"",
		"scoreWeight":"wcs_d",
		"printSub":"F",
		"server":"F",
		"probScores":"F",
		"start":"0",
		"stop":"0",
		"startFrom":"",
		"iupath":"",
		"idFile":"",
		"clustalw":"",
		"FastTree":"",
		"quiet":"T",
		"findMotifs":"T",
		"force":"T",
		"jobList":"",
		"dat_file":"",
		"filter_uniprot":"T",
		"prune_long":"F",
		"analyse_scores":"F"
		}


if __name__ == "__main__":
	try:
		commandline = commandLine.CommandLine(optionsVariables,options,optionsDesc)
	
		options.update(commandline.loadIniFile(os.path.join(os.path.dirname(os.path.realpath(__file__)),"../settings/utilities.ini")))
		options.update(commandline.loadIniFile(os.path.join(os.path.dirname(os.path.realpath(__file__)),"../settings/slimprints.ini")))
		
		for arg in sys.argv:
			if arg[0:3] == "ini":
				options.update(commandline.loadIniFile(os.path.abspath(arg.split("=")[1])))
		
				
		options.update(commandline.parseCommandLine())
		
		
		
		slimprintsHelper = slimprints.SLiMPrints(options)
		
		fileList = []
		jobList = []
		
		
		if options["analyse_scores"] == "T":
			slimprintsTester = slimprints_Tester.SLiMPrints_Tester(options)
			slimprintsTester.run_analysis()
			sys.exit()
				
		if len(options['alignment']) == 0 and len(options['accession']) == 0 and len(options['jobList']) == 0 and len(options['idFile']) == 0:
			print "No alignments (-a) or accessions (-A) were chosen for SLiMPrints analysis"
			sys.exit()
			
		
		if len(options['accession']) > 0:
			idList =  options['accession'].split(",")
			idList.sort()
			
			for accession in options['accession'].split(","):
				if options["startFrom"] == accession:
					fileList = []
					print "\nStarting from " + options["startFrom"] + "\n"
								
				
				proteinInfo = proteinInfoHelper.proteinInfoHelper()
				proteinInfo.options["quiet"] = "F"
				proteinInfo.getInfo(accession,tasks=["fasta","alignment"])
				del proteinInfo
				
				alignmentPath = os.path.join(options['alignment_dir'],"ALN",accession + ".orthaln.fas")
				
				fileList.append(alignmentPath)
				
		elif len(options['idFile']) > 0:
			idList = open(options['idFile']).read().strip().split("\n")[1:]
			idList.sort()
			for accession in idList:
				if options["startFrom"] == accession:
					fileList = []
					print "\nStarting from " + options["startFrom"] + "\n"
								
				
				proteinInfo = proteinInfoHelper.proteinInfoHelper()
				proteinInfo.options["quiet"] = "F"
				proteinInfo.getInfo(accession,tasks=["fasta","alignment"])
				del proteinInfo
				
				alignmentPath = os.path.join(options['alignment_dir'],"ALN",accession + ".orthaln.fas")
				
				fileList.append(alignmentPath)
				
		elif len(options['alignment']) > 0:
			
			if os.path.isfile(options['alignment']):
				fileList = [options['alignment']]
			elif os.path.isdir(options['alignment']):
				try:
					for file in os.listdir(options['alignment'])[0:]:
						if file.split(".")[-1] in ["fas","aln","fasta"]:
							if options["startFrom"] == file.split(".")[0]:
								fileList = []
								print "\nStarting from " + options["startFrom"] + "\n"
								
							fileList.append(os.path.join(options['alignment'],file))
				except:
					pass
			else:
				print "Problem with path " ,options['alignment']
		
		counter = 0
		fileList.sort()
		
		
		###########################################################
		#Score alignment for RLC/ find SLiMPrints
		###########################################################
		
		if options["rlcScorer"] == "F":
			if len(options["jobList"]) > 0:
				try:
					jobList = open(options["jobList"]).read().split("\n")
				except Exception,e:
					raise
						
			for file in fileList:
				try:
					jobname= os.path.basename(file).split(".")[0]
					
					if jobname in jobList or len(jobList) == 0:
						counter += 1
						
						if options["quiet"] == "F":
							if len(jobList) > 0:
								print jobname + " " + str(counter) + "/" + str(len(jobList)) + "\t",
							else:
								print jobname + " " + str(counter) + "/" + str(len(fileList)) + "\t",
						
						exists = False
							
						test = "F"
						
						if test == "T":	
							tester = Tester()
							tester.runTest()
							sys.exit()
								
						else:
							if os.path.isfile( os.path.join(os.path.dirname(options["alignment"]),os.path.basename(options["alignment"]).split(".")[0] + ".scores")):
								exists = True
							
							if not exists or options["force"] == "T":
								slimprintsHelper.data = {}
								
								conHelper = conservationHelper.conservationScorer()
								conHelper.scoreAlignment(file,makeFile=True,readFile=True)
								
								slimprintsHelper.data.update(conHelper.data)
											
								proteinInfo = proteinInfoHelper.proteinInfoHelper()
								proteinInfo.getInfo(jobname,tasks=["uniprot","disorder","pfam","mutation",'dssp','anchor','elm']) #"mutation" slow for some reason / Deletes the searchDB each time
								slimprintsHelper.data.update(proteinInfo.data)
								
								try:
									slimprintsHelper.initialiseData()
								except Exception,e:
									print "Error initialising data",e
									basic.writeError(e)
								
								slimprintsHelper.createMotifs()
								slimprintsHelper.findChildren()
								slimprintsHelper.compressMotifs()
								slimprintsHelper.createCompressedOutput()
								#slimprintsHelper.createFlatOutput()
								#slimprintsHelper.printScores()
								#del slimprintsHelper
								del proteinInfo
								
							else:
								print "Skipping " + file
					#else:
					#	print " not in joblist"
				except Exception,e:
					error_type = sys.exc_info()[0]
					error_value = sys.exc_info()[1]
					error_traceback = traceback.extract_tb(sys.exc_info()[2])
					#print error_traceback
					
					print "Problem (" + str(e) + ") with " ,os.path.basename(file)
					basic.writeError(e)
					
					
	except SystemExit:
		pass
	except Exception,e:
		print e
		error_type = sys.exc_info()[0]
		error_value = sys.exc_info()[1]
		error_traceback = traceback.extract_tb(sys.exc_info()[2])
		print error_traceback	
		
		print "\n<br>"
		print 'Error in routine\n<br>'
		print 'Error Type       : ' + str(error_type) + '\n<br>'
		print 'Error Value      : ' + str(error_value) + '\n<br>'
		print 'File             : ' + str(error_traceback[-1][0]) + '\n<br>'
		print 'Method           : ' + str(error_traceback[-1][2]) + '\n<br>'
		print 'Line             : ' + str(error_traceback[-1][1]) + '\n<br>'
		print 'Error            : ' + str(error_traceback[-1][3]) + '\n<br>'

 
