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()