from PyQt4 import QtGui
from os import linesep
from microbegps import taxonomy

class GPSModule:
	""" This GPS Module allows to export MicrobeGPS results as a table """
	helpText = """<b>Export Table</b><br><br>
	This tool allows to export the MicrobeGPS results in tabular format. The
	exported files are plain text and the single fields are separated by a TAB.
	<br><br>"""
	
	def __init__(self, GPS):
		self.name = 'Export Table'
		self.GPS = GPS
		
		self.exportButton = QtGui.QPushButton('Export Results')
		self.exportButton.setToolTip('Exports the MicrobeGPS results as a table.')
		self.exportButton.clicked.connect(self.export_table)
		
		self.exportSupporting = QtGui.QCheckBox('Export supporting genomes')
		self.exportSupporting.setToolTip('Also export the supporting genomes of each candidate.')
		self.exportSupporting.setChecked(False)
		
		columnsLabel = QtGui.QLabel('Columns:')
		
		self.numReads = QtGui.QCheckBox('Number of Reads')
		self.numReads.setToolTip('The total number of reads mapped to the candidate/genome.')
		self.numReads.setChecked(True)
		
		self.numUnique = QtGui.QCheckBox('Number of Unique Reads')
		self.numUnique.setToolTip('The number of reads uniquely mapping to the candidate/genome.')
		self.numUnique.setChecked(False)
		
		self.genomeCoverage = QtGui.QCheckBox('Genome Coverage')
		self.genomeCoverage.setToolTip('The estimated genome coverage.')
		self.genomeCoverage.setChecked(False)
		
		self.genomeValidity = QtGui.QCheckBox('Genome Validity')
		self.genomeValidity.setToolTip('The estimated genome validity, i.e. the fraction of the genome covered by reads.')
		self.genomeValidity.setChecked(True)
		
		self.homogeneity = QtGui.QCheckBox('Coverage Homogeneity')
		self.homogeneity.setToolTip('Homogeneity of the read distribution over the genome.')
		self.homogeneity.setChecked(False)
		
		self.mappingError = QtGui.QCheckBox('Mapping error')
		self.mappingError.setToolTip('The average mapping error of reads mapping to this candidate/genome.')
		self.mappingError.setChecked(False)		
		
		tabGrid = QtGui.QGridLayout()
		tabGrid.addWidget(self.exportButton,0,0,1,2)
		tabGrid.addWidget(self.exportSupporting,1,0)
		tabGrid.addWidget(columnsLabel,2,0)
		tabGrid.addWidget(self.numReads,3,0)
		tabGrid.addWidget(self.numUnique,3,1)
		tabGrid.addWidget(self.genomeCoverage,4,0)
		tabGrid.addWidget(self.genomeValidity,4,1)
		tabGrid.addWidget(self.homogeneity,5,0)
		tabGrid.addWidget(self.mappingError,5,1)
		tabWidget = QtGui.QWidget()
		tabWidget.setLayout(tabGrid)
		tabWidget.helpText = self.helpText
		
		GPS.toolsTab.addTab(tabWidget,"Export Table")
	
	def export_table(self):
		if not hasattr(self.GPS,'sgroups'):
			self.GPS.pr('<b><font color="DarkRed">Error in Export Table:</font></b><br><i>    No data to export.</i>',True)
			return
		# Get the total number of reads for the abundance estimation (Attention: some reads are counted twice here)
		total_reads = 0
		for grp in self.GPS.sgroups:
			total_reads += grp.reads
		
		# Open the output file
		fname = str(QtGui.QFileDialog().getSaveFileName(caption='Save Table as ...',parent=self.GPS))
		ofile = open(fname,'w')
		
		# Write header
		ofile.write('Candidate\tName\tAbundance')
		if self.numReads.isChecked():
			ofile.write('\tNum. Reads')
		if self.numUnique.isChecked():
			ofile.write('\tUnique Reads')
		if self.genomeCoverage.isChecked():
			ofile.write('\tCoverage')
		if self.genomeValidity.isChecked():
			ofile.write('\tValidity')
		if self.homogeneity.isChecked():
			ofile.write('\tHomogeneity')
		if self.mappingError.isChecked():
			ofile.write('\tMapping Error')
		ofile.write(linesep)

		# iterate over all candidates and write data to file
		for i,grp in enumerate(self.GPS.sgroups):
			# Candidate ID
			ofile.write(str(i+1))
			
			# Candidate name: Try to use LCA of all supporting references.
			taxids = [ref.name for ref in grp.members.itervalues()]
			cand_name = taxonomy.find_lowest_common_ancestor_name(taxids, self.GPS.taxonomy_nodes, self.GPS.taxonomy_names)
			if not cand_name:
				#  find member with most unique reads -> use as representative
				most_unique = max([(m,grp.members[m].unique) for m in grp.members],key=lambda x:x[1])
				cand_name = most_unique[0]
			ofile.write('\t'+cand_name)
			
			# Relative Abundance
			abundance = grp.reads / float(total_reads)
			ofile.write('\t%.6f'%abundance)
			
			# Optional columns
			if self.numReads.isChecked():
				ofile.write('\t%i'%(grp.reads))
			if self.numUnique.isChecked():
				ofile.write('\t%i'%(grp.unique))
			if self.genomeCoverage.isChecked():
				ofile.write('\t%.6f'%(grp.cov))
			if self.genomeValidity.isChecked():
				ofile.write('\t%.6f'%(grp.max_val))
			if self.homogeneity.isChecked():
				ofile.write('\t%.6f'%(grp.cov_homog))
			if self.mappingError.isChecked():
				ofile.write('\t%.6f'%(grp.map_qual))
			ofile.write(linesep)
			
			# Now, list all supporting genomes, if desired
			if self.exportSupporting.isChecked():
				# sort supporting genomes by validity
				sorted_genomes = sorted(grp.members, key=lambda x: -grp.members[x].validity )
				for j,gen in enumerate(sorted_genomes):
					genome = grp.members[gen]
					# CandidateID.GenomeID
					ofile.write('%i.%i'%(i+1,j+1))
					# Use the displayed name
					ofile.write('\t'+gen)
					# Relative Abundance is not applicable here
					ofile.write('\t-')
					# Optional columns
					if self.numReads.isChecked():
						ofile.write('\t%i'%(genome.reads))
					if self.numUnique.isChecked():
						ofile.write('\t%i'%(genome.unique))
					if self.genomeCoverage.isChecked():
						ofile.write('\t%.6f'%(genome.coverage))
					if self.genomeValidity.isChecked():
						ofile.write('\t%.6f'%(genome.validity))
					if self.homogeneity.isChecked():
						ofile.write('\t%.6f'%(genome.cov_homog))
					if self.mappingError.isChecked():
						ofile.write('\t%.6f'%(genome.map_qual))
					ofile.write(linesep)
		ofile.close()
