Ejemplo n.º 1
0
Archivo: tabs.py Proyecto: mcvmcv/Poo
class PooTabs(QtGui.QTabWidget):
	def __init__(self):
		super(PooTabs, self).__init__()
		self.setTabsClosable(True)
		self.clearAll()
		
########################################################################
##	Deleting, opening, and saving
	def clearAll(self):
		'''Deletes all stored data and creates a blank Sample table.'''
		self.clear()
		self.sampleTable		= False
		self.keaTable			= False
		self.ebridaTable		= False
		self.addSampleTable()
		
	def openSaved(self,excelFile):
		'''Adds data from a saved file.'''
		for sheetName in excelFile.sheet_names:
			if sheetName == 'Project':
				pass
			elif sheetName == 'Samples':
				samples				= excelFile.parse('Samples').astype(str)
				self.addSampleTable()
				self.sampleTable.appendSamples(samples)
			elif sheetName == 'Kea':
				samples				= excelFile.parse('Kea').astype(str)
				self.addKeaTable()
				self.keaTable.appendSamples(samples)
			elif sheetName == 'EBrida':
				samples				= excelFile.parse('EBrida').astype(str)
				self.addEbridaTable()
				self.ebridaTable.appendSamples(samples)
			else:
				samples				= excelFile.parse(sheetName).astype(str)
				screenTable			= ScreenTable(sheetName)
				screenTable.appendSamples(samples)
				self.addTab(screenTable,sheetName)
	
	def makeProjectName(self):
		'''Creates a project name string in the format
		year-firstplate-lastplate.'''
		return self.sampleTable.makeProjectName()
		
	def toWriter(self,writer):
		'''Adds all tabs to the passed Excel writer object and returns it.'''
		for i in range(self.count()):
			self.widget(i).table.to_excel(writer,self.tabText(i),index=False)
		return writer
		
########################################################################
##	Utilities
	def getSamplesCommonData(self):
		'''Returns the Plate ID, Plate Name, Plate Kea, and Well columns
		of the Sample Table.'''
		return self.sampleTable.getSamplesCommonData()
	
	def getColumnEntryList(self,column):
		'''Returns a list of all entries for the given column, for the
		current screening table.'''
		return self.currentWidget().getColumnEntryList(column)
	
	def update(self,key,dataframe):
		'''Uses the data in dataframe to update table by key.'''
		self.currentWidget().update(key,dataframe)
	
	def setColumn(self,column,value):
		'''Sets all rows in a column to value.'''
		self.currentWidget().setColumn(column,value)
	
	def replace(self,column,dictionary):
		'''Uses the passed dictionary to replace selected entries of column
		in the currenctly active table.'''
		self.currentWidget().replace(column,dictionary)
		
	def getColumnsWithSelect(self,columns=[],selected=False):
		'''Returns the passed columns of the table, for the samples with
		True in the selected column. The table is indexed by Plate ID and Well.'''
		return self.currentWidget().getColumnsWithSelect(columns,selected)
	
	def renameScreen(self,screen):
		'''Renames the currently active round of screening.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			self.setTabText(self.currentIndex(),screen)
			return self.currentWidget().renameScreen(screen)
	
	def setCurrentMarker(self,marker):
		'''Returns the marker name for the currently active screening tab.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			return self.currentWidget().setMarker(marker)
	
	def getCurrentMarker(self):
		'''Returns the marker name for the currently active screening tab.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			return ' '
		else:
			return self.currentWidget().getMarker()
	
	def setPopulation(self,by):
		'''Sets the Population column of the Sample table to the passed
		option.'''
		if by == 'All':
			self.sampleTable.table['Population'] = 'All'
		elif by == 'Plate ID':
			self.sampleTable.table['Population'] = self.sampleTable.table['Plate ID']
		elif by == 'Kea':
			keaPops				= keaTable.getColumnsWithSelect('Population')
			self.sampleTable.update(keaPops)
			
	def setByPopulation(self,column,data):
		'''Sets the given column of the currently active widget to the
		value given in the data table.'''
		populations				= self.sampleTable.getColumnsWithSelect(['Population'])
		populations[column]		= np.nan
		populations				= populations.reset_index()
		populations				= populations.set_index('Population')
		populations.update(data)
		populations				= populations.reset_index()[['Plate ID','Well',column]]
		populations				= populations.set_index(['Plate ID','Well'],drop=False)
		self.update(['Plate ID','Well'],populations)
	
	def setIncludeByPopulationAndGroup(self,included):
		'''Sets the Include column of the currently active widget to the
		value given in the included table.'''
		populations				= self.sampleTable.getColumnsWithSelect(['Population'])
		samples					= self.currentWidget().getColumnsWithSelect(['Group'])
		samples					= pd.merge(samples,populations,how='inner',left_index=True,right_index=True)
		samples['Include']		= False
		def makeIncludes(x):
			mySamples			= samples.loc[(samples.Population==x.Population) & (samples.Group.isin(x.Groups))]
			mySamples			= mySamples.head(x.Samples)
			mySamples['Include']=True
			mySamples			= mySamples[['Include']]
			samples.update(mySamples)
		included.apply(makeIncludes,1)
		self.update(['Plate ID','Well'],samples)
		
	def setIncludeByPopulationAndGroup2(self,included):
		'''Sets the Include column of the currently active widget to the
		value given in the included table.'''
		populations				= self.sampleTable.getColumnsWithSelect(['Population'])
		samples					= self.currentWidget().getColumnsWithSelect(['Group'])
		samples					= pd.merge(samples,populations,how='inner',left_index=True,right_index=True)
		samples['Include']		= False
		def makeIncludes(x):
			mySamples			= samples.loc[(samples.Population==x.Population) & (samples.Group==x.Group)]
			mySamples			= mySamples.head(x.Samples)
			mySamples['Include']=True
			mySamples			= mySamples[['Include']]
			samples.update(mySamples)
		included.apply(makeIncludes,1)
		self.update(['Plate ID','Well'],samples)
	
	def getPlateStats(self):
		'''Gets a Plate based Group stats table.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() not in sourceTables:
			data				= self.currentWidget().getColumnsWithSelect(['Group'],'Include')
			data				= data.reset_index()[['Plate ID','Group']]
			data				= data.groupby(['Plate ID','Group']).size().unstack().fillna(0)
			data['Samples']		= data.sum(axis=1)
			return data
		else:
			return False
		
	def getPopulationStats(self):
		'''Gets a Population based Group stats table.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() not in sourceTables:
			data				= self.currentWidget().getColumnsWithSelect(['Group'],'Include')
			popdata				= self.sampleTable.getColumnsWithSelect(['Population'])
			data				= pd.merge(data,popdata,how='left',left_index=True,right_index=True)
			data				= data.reset_index()[['Population','Group']]
			data				= data.groupby(['Population','Group']).size().unstack().fillna(0)
			data['Samples']		= data.sum(axis=1)
			return data
		else:
			return False
			
	def getCurrentStatsTable(self,by,results):
		'''Calls the other two functions. Added to preserve the coloured
		Kea output table format. Results button does nothing - it used to
		select the column. I'm doing backwards compatibility!'''
		if by == 'Plate':
			return self.getPlateStats()
		elif by == 'Population':
			return self.getPopulationStats()
	
########################################################################
##	Adding and filling
	def addSampleTable(self):
		'''Adds a Sample table, if one does not already exist.'''
		if not self.sampleTable:
			self.sampleTable	= SampleTable()
			self.insertTab(0,self.sampleTable,'Samples')
			self.tabBar().setTabButton(0,QtGui.QTabBar.RightSide,None)
		
	def addKeaTable(self):
		'''Adds a Kea Table, if no Kea Table exists.'''
		if not self.keaTable:
			self.keaTable		= KeaTable()
			self.insertTab(1,self.keaTable,'Kea')
			self.tabBar().setTabButton(1,QtGui.QTabBar.RightSide,None)
		
	def addEbridaTable(self):
		'''Adds an Ebrida table, if no Ebrida table exists.'''
		if not self.ebridaTable:
			self.ebridaTable	= EbridaTable()
			self.insertTab(2,self.ebridaTable,'EBrida')
			self.tabBar().setTabButton(2,QtGui.QTabBar.RightSide,None)
		
	def addAndFillKeaTable(self):
		'''Adds a Kea table and copies data from the Sample table, if a
		Kea table does not already exist.'''
		if not self.keaTable:
			self.addKeaTable()
			samples				= self.getSamplesCommonData()
			self.keaTable.appendSamples(samples)
		
	def addAndFillEbridaTable(self):
		'''Adds an Ebrida table and copies data from the Kea table, if an
		Ebrida table does not already exist.'''
		if not self.ebridaTable:
			self.addEbridaTable()
			samples				= self.keaTable.getEbridaIndexData()
			self.ebridaTable.appendSamples(samples)
		
	def addAndFillEbridaTableNoKea(self):
		'''Adds an Ebrida table if an Ebrida table does not already exist.'''
		if not self.ebridaTable:
			self.addEbridaTable()
			samples				= self.getSamplesCommonData()
			self.ebridaTable.appendSamples(samples)
		
	def appendSamples(self,samples):
		'''Appends the samples in the passed dataframe to all three of
		the Sample, Kea, and Ebrida tables, if they exist.'''
		if self.sampleTable:	self.sampleTable.appendSamples(samples)
		if self.keaTable:		self.keaTable.appendSamples(samples)
		if self.ebridaTable:	self.ebridaTable.appendSamples(samples)
		
	def updateSourceTables(self,index,newData):
		'''Updates the Sample, Kea, and Ebrida tables with data from the
		passed dataframe, if those tables exist.'''
		if self.sampleTable:	self.sampleTable.update(index,newData)
		if self.keaTable:		self.keaTable.update(index,newData)
		if self.ebridaTable:	self.ebridaTable.update(index,newData)
	
	def updateKeaData(self,keaData):
		'''Updates the Kea table with data from the passed dataframe.
		If no Kea table exists, one is created and populated with data
		from the Samples table.'''
		self.addAndFillKeaTable()
		self.ebridaTable.addIndexedInfo(keaData,['Plate Kea','Well'])
		
	def updateEbridaData(self,ebridaData):
		'''Updates the Ebrida table with data from the passed dataframe.
		If no Ebrida table exists, one is created and populated with data
		from the Kea table.'''
		self.addAndFillEbridaTable()
		self.ebridaTable.addIndexedInfo(ebridaData.table,'Barcode')
	
	def updateEbridaDataNoKea(self,ebridaData):
		'''Updates the Ebrida table with data from the passed dataframe.
		If no Ebrida table exists, one is created and populated with data
		from the Kea table.'''
		self.addAndFillEbridaTableNoKea()
		self.ebridaTable.update(['Plate Name','Well'],ebridaData.table.set_index(['Plate Name','Well']))
		
########################################################################
##	Screening and cherrypicking
	def addScreen(self,plateNames,includeAll,oldPlates,newMarker,controls):
		'''Adds a new screen table based on the passed data.'''
		fromSource,samples		= self.getInclude(includeAll)
		screenTable				= ScreenTable(plateNames)
		screenTable.addSamples(fromSource,includeAll,oldPlates,newMarker,samples,controls)
		self.addTab(screenTable,plateNames)
		
	def getInclude(self,includeAll):
		'''Gets the samples to include in the next round of screening.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			return True, self.sampleTable.getInclude(includeAll)
		return False, self.currentWidget().getInclude(includeAll)
		
	def getNegativeUnknowns(self,controls):
		'''Returns a table of Negatives and Unknowns, with new wells and
		plates added.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			return self.currentWidget().getNegativeUnknowns(controls)
		
	def getPotentialContaminants(self):
		'''Returns a table of possible contaminants.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			return self.currentWidget().getPotentialContaminants()
		
	def getNegativeUnknownContaminants(self,controls,contaminants):
		'''Returns a table of Negatives, Unknowns, and Contaminants, with
		new wells and plates added.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			return self.currentWidget().getNegativeUnknownContaminants(controls,contaminants)
		
	def getSamplesForLoading(self):
		'''Gets from/to data for samples to load active Screening tab.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			return self.currentWidget().getSamplesForLoading()
		
	def importLC(self,lc):
		'''Imports data from the give fileDataLists and updates the active
		screening tab.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass # Add "Add screening"?
		else:
			self.currentWidget().importLC(lc)
	
	def addResultGroup(self,markerTable):
		'''Adds Results and Groups to currently active tab using markerTable.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			self.currentWidget().addResultGroup(markerTable)
	
########################################################################
##	Including and outputting
	def getNonExists(self):
		'''Returns a table of Falses for non-existing samples.'''
		return self.sampleTable.getNonExists()
	
	def getNegativeFailGrinds(self):
		'''Returns a table of Falses for Negative, Failgrind samples.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			pass
		else:
			failGrinds			= self.sampleTable.getFailGrinds()
			negatives			= self.currentWidget().getNegatives()
			negativeFailGrinds	= failGrinds.join(negatives,how='inner')
			negativeFailGrinds['Output']	= False
			return negativeFailGrinds[['Output']]
	
########################################################################
##	Output stuff
	def getEbridaHarvestData(self):
		'''Returns the data required for outputting harvest platesheets.'''
		return self.keaTable.getEbridaIndexData()
			
	def getSampleTable(self):
		'''Gets the sample, kea, and ebrida data, and puts it into one
		big table ready to have results added to it.'''
		sampleTableColumns		= ['Plate Name']
		samples					= self.sampleTable.getColumnsWithSelect(sampleTableColumns,'Output')
		if self.keaTable:
			keaTableColumns		= ['Plate Kea','Sample ID','PlantID','Plant Alt Names',
									'Population','Sample Batch']
			keaData				= self.keaTable.getColumnsWithSelect(keaTableColumns)
			samples				= pd.merge(samples,keaData,how='left',left_index=True,right_index=True)
		if self.ebridaTable:
			ebridaTableColumns	= ['Pedigree Item','Plot','Group','Start Date',
									'From Ped. Item','Mother','Father','Barcode',
									'fundingNameCr','BreederName','synonyms']
			ebridaData			= self.ebridaTable.getColumnsWithSelect(ebridaTableColumns)
			samples				= pd.merge(samples,ebridaData,how='left',left_index=True,right_index=True)
		return samples
		
	def getScreenResultsTable(self):
		'''Gets a results table for current round of screening.'''
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		if self.currentWidget() in sourceTables:
			return False
		samples					= self.getSampleTable()
		columns					= ['Experiment','Experiment Date','Marker','Result','Group']
		results					= self.currentWidget().getColumnsWithSelect(columns,'Output')
		samples					= pd.merge(samples,results,how='right',left_index=True,right_index=True)
		samples					= samples.reset_index()
		return samples
	
#	def getAllResultsTableOld(self):
#		'''Gets a results table for all rounds of screening.'''
#		samples					= self.getSampleTable()
#		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
#		markers					= []
#		for i in range(self.count()):
#			if self.widget(i) in sourceTables:
#				pass
#			else:
#				markers.append(self.widget(i).getMarker())
#				screen			= self.widget(i).getColumnsWithSelect(['Marker','Result','Group'],'Output')
#				screen			= screen.reset_index().set_index(['Plate ID','Well','Marker'])
#				screen			= screen.unstack().reset_index().set_index(['Plate ID','Well'])
#				samples			= pd.merge(samples,screen,how='inner',left_index=True,right_index=True)
#		samples					= samples.reset_index()
#		return markers,samples
		
	def getAllResultsTable(self):
		'''Gets results table for all rounds of screening.'''
		results					= pd.DataFrame(columns=[])
		samples					= self.getSampleTable()
		sourceTables			= (self.sampleTable, self.keaTable, self.ebridaTable)
		for i in range(self.count()):
			if self.widget(i) in sourceTables:
				pass
			else:
				screen			= self.widget(i).getColumnsWithSelect(['Marker','Result','Group'],'Output')
				screen			= screen.reset_index().set_index(['Plate ID','Well'])
				screen			= pd.merge(samples,screen,how='inner',left_index=True,right_index=True).fillna('Not tested')
				results			= results.append(screen)
		return results.reset_index()