def initUI(self): self.setWindowTitle("Data Formatter") self.menubar = fydMenuBar() self.setMenuBar(self.menubar) self.statusBar() self.resultsTable = ResultsTable() self.infoTable = InfoTable() self.tabWidget = QtGui.QTabWidget() self.tabWidget.addTab(self.resultsTable, "Results") self.tabWidget.addTab(self.infoTable, "Information") self.setCentralWidget(self.tabWidget) self.showMaximized()
def new(self): """Nukes the resultsTable and starts again.""" del self.resultsTable del self.infoTable del self.tabWidget self.resultsTable = ResultsTable() self.infoTable = InfoTable() self.tabWidget = QtGui.QTabWidget() self.tabWidget.addTab(self.resultsTable, "Results") self.tabWidget.addTab(self.infoTable, "Information") self.setCentralWidget(self.tabWidget) self.__updateView()
class DataFormatter(QtGui.QMainWindow): def __init__(self): super(DataFormatter, self).__init__() self.initVars() self.initUI() self.initConnections() def initVars(self): self.path = "/home/mcv/Genotyping Project Records/Genotyping Projects/" self.ignoreList = ["", "Population"] def initUI(self): self.setWindowTitle("Data Formatter") self.menubar = fydMenuBar() self.setMenuBar(self.menubar) self.statusBar() self.resultsTable = ResultsTable() self.infoTable = InfoTable() self.tabWidget = QtGui.QTabWidget() self.tabWidget.addTab(self.resultsTable, "Results") self.tabWidget.addTab(self.infoTable, "Information") self.setCentralWidget(self.tabWidget) self.showMaximized() def initConnections(self): self.menubar.clearTableAction.triggered.connect(self.new) self.menubar.openAction.triggered.connect(self.openDialog) self.menubar.saveAction.triggered.connect(self.saveDialog) # self.menubar.readMarkerConfigAction.triggered.connect(self.readMarkerConfig) self.menubar.createSamplesAction.triggered.connect(self.createSamples) self.menubar.createPlatesAction.triggered.connect(self.createPlates) # self.menubar.createSamplesFromExcelAction.triggered.connect(self.createSamplesFromExcel) self.menubar.createSamplesFromExcelKeaAction.triggered.connect(self.createSamplesFromExcelKea) self.menubar.kiwifruitWizardAction.triggered.connect(self.kiwifruitWizard) self.menubar.brassicaRyegrassWizardAction.triggered.connect(self.brassicaRyegrassWizard) self.menubar.keaWizardAction.triggered.connect(self.keaWizard) self.menubar.exitAction.triggered.connect(self.close) # self.menubar.importSamplesSpreadsheetAction.triggered.connect(self.importSamplesSpreadsheet) self.menubar.importEBridaSamplesSpreadsheetAction.triggered.connect(self.importEBridaSamplesSpreadsheet) self.menubar.importPlatesSpreadsheetAction.triggered.connect(self.importPlatesSpreadsheet) self.menubar.importLightcyclerFileAction.triggered.connect(self.importLightcyclerFile) self.menubar.importTaqmanFileAction.triggered.connect(self.importTaqmanFile) # self.menubar.importSpecFileAction.triggered.connect(self.importSpecFile) self.menubar.cherryPickHelpAction.triggered.connect(self.cherryPickHelp) self.menubar.cherryPickNegativeUnknownAction.triggered.connect(self.cherryPickNegativeUnknown) self.menubar.cherryPickFromPopulationAction.triggered.connect(self.cherryPickFromPopulation) self.menubar.importCherryPickingAction.triggered.connect(self.importCherryPicking) self.menubar.setCropAction.triggered.connect(self.setCrop) self.menubar.explainCropAction.triggered.connect(self.explainCrop) self.menubar.editPlatesAction.triggered.connect(self.editPlates) self.menubar.viewPlateStatsAction.triggered.connect(self.viewPlateStats) # self.menubar.viewPopulationStatsAction.triggered.connect(self.viewPopulationStats) self.menubar.standardiseResultsAction.triggered.connect(self.standardiseResults) self.menubar.negativiseUnknownsAction.triggered.connect(self.negativiseUnknowns) self.menubar.addAutoResultsAction.triggered.connect(self.addAutoResults) self.menubar.addManualResultsAction.triggered.connect(self.addManualResults) self.menubar.setNonExistsToNoSampleAction.triggered.connect(self.setNonExistsToNoSample) self.menubar.setNonExistsToNegativeAction.triggered.connect(self.setNonExistsToNegative) self.menubar.includeAllAction.triggered.connect(self.includeAll) self.menubar.excludeFailGrindsAction.triggered.connect(self.excludeFailGrinds) self.menubar.excludeNegativeFailGrindsAction.triggered.connect(self.excludeNegativeFailGrinds) self.menubar.excludeNonExistsAction.triggered.connect(self.excludeNonExists) self.menubar.kiwifruitResultsAction.triggered.connect(self.kiwifruitResults) self.menubar.brassicaRyegrassResultsAction.triggered.connect(self.brassicaRyegrassResults) self.menubar.appleResultsAction.triggered.connect(self.appleResults) self.menubar.outputHarvestSheetsAction.triggered.connect(self.outputHarvestSheets) # self.menubar.outputSampleTableAction.triggered.connect(self.outputSampleTable) self.menubar.outputForKeaAction.triggered.connect(self.outputForKea) self.menubar.outputForEBridaAction.triggered.connect(self.outputForEBrida) self.menubar.colouredResultsAction.triggered.connect(self.colouredResults) self.menubar.niceKeaSpreadsheetAction.triggered.connect(self.niceKeaSpreadsheet) ######################################################################## ## Private Methods def __updateView(self): """Reorders the columns of self.resultsTable, and updates the self.tableWidget dataframe to the current version of self.resultsTable""" self.resultsTable.update() self.infoTable.update() def __getPlatesRecords(self): title = "Locate plate spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) plateData = pd.read_excel(fileName, sheetname="Plates", header=1) plateData = plateData[["Slipstream Identifier", "Plate Name", "Kea Name", "Non-harvested plants", "Bad Grinds"]] plateData.columns = ["Plate ID", "Plate Name", "Plate Kea", "Non-harvested plants", "Bad Grinds"] plateData = plateData.dropna(subset=["Plate ID"]) return plateData def __getStatsTable(self, included, groups, by): stats = included[[by, "Group"]].groupby([by, "Group"]).size().unstack() plateLookup = included.drop_duplicates(by)[[by]] columns = [by] + groups statsTable = pd.DataFrame(columns=columns).append(plateLookup).set_index([by]) statsTable = statsTable.combine_first(stats).fillna(0).reset_index() statsTable["Samples"] = statsTable.sum(axis=1) statsTable = statsTable[[by, "Samples"] + groups] return statsTable ## To make platesheets work: def __getStatsTable(self, included, groups, by): included = included[included.Group != "No sample"] stats = included[["Plate ID", "Group"]] stats = stats.groupby(["Plate ID", "Group"]).size().unstack() plateLookup = included.drop_duplicates("Plate ID")[["Plate ID", "Plate Name"]] columns = ["Plate ID", "Plate Name"] + groups statsTable = pd.DataFrame(columns=columns).append(plateLookup).set_index(["Plate ID"]) statsTable = statsTable.combine_first(stats).fillna(0).reset_index() statsTable["Samples"] = statsTable.sum(axis=1) statsTable = statsTable[["Plate ID", "Plate Name", "Samples"] + groups] return statsTable def __readMarkerConfig(self, fileName): with open(fileName, "r") as config: for line in config.readlines(): lineList = line.split("\t") Crop = lineList[0] Marker = lineList[1] Result = lineList[2] Group = lineList[3] Colour = lineList[4] ######################################################################## ## File Menu Actions def new(self): """Nukes the resultsTable and starts again.""" del self.resultsTable del self.infoTable del self.tabWidget self.resultsTable = ResultsTable() self.infoTable = InfoTable() self.tabWidget = QtGui.QTabWidget() self.tabWidget.addTab(self.resultsTable, "Results") self.tabWidget.addTab(self.infoTable, "Information") self.setCentralWidget(self.tabWidget) self.__updateView() def openDialog(self): """Opens a saved .xls file.""" title = "Open project .xls file..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) results = pd.io.excel.read_excel(fileName, sheetname="Results") if set(results.columns) == set(self.resultsTable.table.columns): self.resultsTable.table = results self.infoTable.table = pd.io.excel.read_excel(fileName, sheetname="Information") self.__updateView() else: dialog = QtGui.QMessageBox.information( self, "Open file fail...", "The columns in this file's results\n" + "table are not what is expected. Please\n" + "make sure you have the right file, and\n" + "make sure the columns of the saved file\n" + "match those in the Results tab.", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) def saveDialog(self): """Saves the project as an .xls file.""" title = "Save project as..." fileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) fileName = fileName.split(".")[0] writer = pd.ExcelWriter(fileName + ".xls") self.resultsTable.table.to_excel(writer, "Results") self.infoTable.table.to_excel(writer, "Information") writer.save() def readMarkerConfig(self): """Opens a specified marker config file and creates marker data.""" title = "Select marker config file..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) self.markers = self.__readMarkerConfig(fileName) def createSamples(self): """Creates a given number of samples with no names or plant names.""" samples, ok = CreateSamplesDialog.create(self) if ok: newSamplesDF = pd.DataFrame( samples, columns=["Plate ID", "Plate Name", "Plate Kea", "Well", "Grind", "Include"] ) self.resultsTable.append(newSamplesDF) self.infoTable.append(newSamplesDF[["Plate ID", "Plate Name", "Plate Kea", "Well"]]) self.__updateView() def createPlates(self): """Creates a set of consecutively numbered full plates.""" samples, ok = CreatePlatesDialog.create(self) if ok: newSamplesDF = pd.DataFrame( samples, columns=["Plate ID", "Plate Name", "Plate Kea", "Well", "Crop", "Grind", "Include"] ) self.resultsTable.append(newSamplesDF) self.infoTable.append(newSamplesDF[["Plate ID", "Plate Name", "Plate Kea", "Well"]]) self.__updateView() def createSamplesFromExcel(self): """Opens an Excel spreadsheet and creates samples.""" title = "Locate sample spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) excelFile = pd.ExcelFile(fileName) sheets = excelFile.sheet_names sheet, ok = MyDialog.chooseExcelSheet(sheets) imported = excelFile.parse(sheet) columns = list(imported.columns) name, well, ok = MyDialog.getIndexMatches(columns) columnsToImport, ok = MyDialog.chooseColumns(columns) columnsToImport = self.columns2 + columnsToImport imported["Plate ID"] = "" imported["Plate Name"] = imported.get(name, "") imported["Well"] = imported.get(well, "") imported = imported.dropna(how="all", subset=["Plate Name", "Well"]) imported = imported.set_index("Plate Name") title = "Locate plate spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) plateData = pd.read_excel(fileName, sheetname="Plates", header=1) plateData = plateData[["Slipstream Identifier", "Kea Name", "Plate Name", "Bad Grinds"]] plateData.columns = ["Plate ID", "Kea Name", "Plate Name", "Bad Grinds"] plateData = plateData.dropna(how="all", subset=["Kea Name"]) plateData = plateData.set_index("Kea Name") imported.update(plateData) imported = imported.reset_index() badGrinds = plateData.dropna(how="all", subset=["Bad Grinds"]) badGrinds = pd.DataFrame(badGrinds["Bad Grinds"].str.split(" ").tolist(), index=badGrinds["Plate ID"]).stack() badGrinds = badGrinds.reset_index().drop("level_1", 1) badGrinds.columns = ["Plate ID", "Well"] badGrinds["Grind"] = False badGrinds = badGrinds.set_index(["Plate ID", "Well"]) self.resultsTable = self.resultsTable.append(imported[self.columns2]) self.resultsTable = self.resultsTable.set_index(["Plate ID", "Well"]) self.resultsTable.update(badGrinds) self.resultsTable = self.resultsTable.reset_index() self.infoTable = self.infoTable.append(imported[columnsToImport]) self.__updateView() def createSamplesFromExcelKea(self): """Opens a Kea Sample Batch spreadsheet and imports the samples.""" title = "Locate Kea sample batch spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) excelFile = pd.ExcelFile(fileName) imported = excelFile.parse("Data") imported["Plate ID"] = "" sheetColumns = ["Plate ID", "Plate No", "Position on Plate(s)", "PlantID", "Sample ID", "Plant Alt Names"] tableColumns = ["Plate ID", "Plate Kea", "Well", "PlantID", "Sample ID", "Plant Alt Names"] resColumns = ["Plate ID", "Plate Kea", "Well", "Population"] imported = imported[sheetColumns] imported.columns = tableColumns imported = imported.dropna(how="all", subset=["Sample ID"]) self.population = "" def addPopulations(row): if pd.isnull(row["Plate Kea"]): self.population = row["Sample ID"].split(" ")[0] return self.population imported["Population"] = imported.apply(addPopulations, 1) imported = imported.dropna(how="all", subset=["Plate Kea", "Well"]) self.resultsTable.append(imported[resColumns]) self.infoTable.append(imported) plateData = self.__getPlatesRecords() self.resultsTable.importPlateData(plateData, "Plate Kea") self.infoTable.importPlateData(plateData, "Plate Kea") self.__updateView() def kiwifruitWizard(self): """Runs a wizard to input data for a kiwifruit project.""" dialog = QtGui.QMessageBox.information( self, "Kiwifruit Wizard", "You will be prompted to select files for\n" + "import. The files you will need are:\n" + " - Kea sample batch harvest sheet\n" + " - Plates records spreadsheet\n" + " - E-brida information sheet\n" + " - Lightcycler .txt files\n\n" + "After running this wizard you will have\n" + "all required information imported and\n" + "all logic on results set up.\n\n" + "Afterwards you will want to save the\n" + "project, and export the data in the\n" + "appropriate format.", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) self.createSamplesFromExcelKea() self.importEBridaSamplesSpreadsheet() self.resultsTable.setCrop("Kiwifruit") self.importLightcyclerFile() self.kiwifruitResults() self.__updateView() def brassicaRyegrassWizard(self): """Runs a wizard to input data for a brassica or ryegrass project.""" dialog = QtGui.QMessageBox.information( self, "Brassica/Ryegrass Wizard", "You will be prompted to set up samples\n" + "and to select files for import. Sample\n" + "setup requires you to select the crop.\n" + "This determines which results will be\n" + "included in the output files.\n\n" + "For Brassica, select:\n" + "-Brassica for a normal project\n" + "-Brassica R-S to include Rape-Swede\n" + "-Brassica J/P-C to include Juncea/Pak Choy\n" + "-Brassica SPF for Spitfire/Other Rape\n\n" + "For Ryegrass, select:\n" + "-Ryegrass for a normal project\n" + "-Ryegrass501 for AR501/Other Endo\n\n" + "The files you will need are the plates\n" + "records spreadsheet and the appropriate\n" + "Lightcycler .txt files.\n\n" + "After running this wizard you will have\n" + "all required information imported and\n" + "all logic on results set up.\n\n" + "Afterwards you will want to save the\n" + "project, and export the data in the\n" + "appropriate format.", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) self.createPlates() self.importPlatesSpreadsheet() self.importLightcyclerFile() self.resultsTable.negativiseUnknowns() self.brassicaRyegrassResults() self.__updateView() def keaWizard(self): """Runs a wizard to input data for a kea (no ebrida) project.""" dialog = QtGui.QMessageBox.information( self, "Kea Wizard", "You will be prompted to select files for\n" + "import. The files you will need are:\n" + " - Kea sample batch harvest sheet\n" + " - Plates records spreadsheet\n" + " - Lightcycler .txt files\n\n" + "After running this wizard you will have\n" + "all required information imported and\n" + "all logic on results set up.\n\n" + "Afterwards you will want to save the\n" + "project, and export the data in the\n" + "appropriate format.", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) self.createSamplesFromExcelKea() self.setCrop() self.importLightcyclerFile() self.appleResults() self.__updateView() ######################################################################## ## Import Menu Actions def importSamplesSpreadsheet(self): """Opens an Excel spreadsheet and adds the information to samples.""" title = "Locate samples spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) excelFile = pd.ExcelFile(fileName) sheet, ok = MyDialog.chooseExcelSheet(excelFile.sheet_names) imported = excelFile.parse(sheet) indexBy, ok = MyDialog.chooseIndexMethod() if indexBy == "Plate ID and Well": plateC, wellC, ok = MyDialog.choosePlateAndWellColumns(imported.columns) imported["Plate ID"] = imported[plateC] imported["Well"] = imported[wellC] imported = imported.set_index(["Plate ID", "Well"]) self.infoTable = self.infoTable.set_index(["Plate ID", "Well"]) elif indexBy == "Plate Name and Well": plateC, wellC, ok = MyDialog.choosePlateAndWellColumns(imported.columns) imported["Plate Name"] = imported[plateC] imported["Well"] = imported[wellC] imported = imported.set_index(["Plate ID", "Well"]) self.infoTable = self.infoTable.set_index(["Plate ID", "Well"]) elif indexBy == "Other column": tabC, impC, ok = MyDialog.chooseCol(self.infoTable.columns, imported.columns) imported = imported.set_index(impC) self.infoTable = self.infoTable.set_index(tabC) columnsToImport, ok = MyDialog.chooseColumns(imported.columns) self.infoTable = self.infoTable.join(imported[columnsToImport], rsuffix="_new") self.infoTable = self.infoTable.reset_index() self.__updateView() def importEBridaSamplesSpreadsheet(self): """Imports an EBrida Excel spreadsheet and adds the information. Join is done on 'Plant Alt Names' table column with 'Barcode' spreadsheet column.""" title = "Locate E-Brida spreadsheet..." fileName, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) excelFile = pd.ExcelFile(fileName) imported = excelFile.parse("Sheet1") columns = { "From Ped. Item (origin)": "From Ped. Item", "synonym": "synonyms", "Synonym": "synonyms", "Synonyms": "synonyms", "breederCrCode": "synonyms", "BreederCrCode": "synonyms", "breederName": "BreederName", } imported = imported.rename(columns=columns) tableKey, importKey = "Plant Alt Names", "Barcode" self.infoTable.importSampleData(imported, tableKey, importKey) self.__updateView() def importPlatesSpreadsheet(self): """Opens the Plates Records spreadsheet and adds data.""" plateData = self.__getPlatesRecords() self.resultsTable.importPlateData(plateData, "Plate ID") self.infoTable.importPlateData(plateData, "Plate ID") self.__updateView() def importLightcyclerFile(self): """Imports Lightcycler .txt files and adds the results, locating samples by plate name (taken from filename) and well.""" title = "Import LC file(s)..." filter_mask = "Lightcycler text files (*.txt)" lightFileNames, f = QtGui.QFileDialog.getOpenFileNames(self, title, self.path, filter_mask) fileDataLists, ok = LCDialog.importLC(lightFileNames) if ok: self.resultsTable.addLCFiles(fileDataLists) self.__updateView() def importTaqmanFile(self): """Imports Taqman .txt files and adds the results, locating samples by plate name (taken from filename) and well.""" title = "Import Taqman file(s)..." filter_mask = "Taqman text files (*.txt)" lightFileNames, f = QtGui.QFileDialog.getOpenFileNames(self, title, self.path, filter_mask) fileDataLists, ok = LCDialog.importLC(lightFileNames) if ok: self.resultsTable.addTaqFiles(fileDataLists) self.__updateView() def importSpecFile(self): """Imports csv files from the plate spec machine, creates a standard curve for each file, converts to concentration, and adds the data as a column""" pass ######################################################################## ## Cherry Menu Actions def cherryPickHelp(self): """Displays information about how to run a round of cherrypicking.""" dialog = QtGui.QMessageBox.information( self, "About cherrypicking", "Only cherrypicking for Negatives/Unknowns is fully\n" + "implemented currently. Multiple marker cherrypicking\n" + "will be available in Poo.py.\n\n" + "Choosing Cherry pick N/U will open a dialog where\n" + "can choose the location for the cherrypicking files\n" + "to be saved. There will be one Excel file, which gives\n" + "an overview, and a bunch of .csv's to run on the robot.\n\n" + "The Excel file is required when the results are to be\n" + "imported, in order for the LC results to be mapped to\n" + "the correct sample.\n", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) def cherryPickNegativeUnknown(self): """Outputs files for cherrypicking Negatives/Unknowns.""" cherryTable = self.resultsTable.getCherriesNU() self.outputCherries(cherryTable) def cherryPickFromPopulation(self): """Outputs files for cherrypicking by Population and Result.""" title = "Choose populations, results, and numbers to cherrypick..." populations = self.resultsTable.getPopulations() groups = self.resultsTable.getGroups() cherryData, ok = CherryDialog.run(populations, groups) cherryTable = self.resultsTable.getCherriesByPop(cherryData) self.outputCherries(cherryTable) def outputCherries(self, cherryTable): """Outputs cherrypicking files for the passed cherryTable.""" title = "Choose folder for output..." directory = QtGui.QFileDialog.getExistingDirectory(self, title, self.path) writer = pd.ExcelWriter(os.path.join(directory, "cherrypicking.xls")) cherryTable.to_excel(writer, "All", index=False) summarySource = cherryTable[["Run", "Source Position", "Source plate"]].drop_duplicates().reset_index(drop=True) summaryDest = ( cherryTable[["Run", "Destination Position", "Dest plate"]].drop_duplicates().reset_index(drop=True) ) summarySource = summarySource.pivot(index="Run", columns="Source Position", values="Source plate") summaryDest = summaryDest.pivot(index="Run", columns="Destination Position", values="Dest plate") summary = summarySource.join(summaryDest) summary.to_excel(writer, "Summary") runs = pd.unique(cherryTable.Run.ravel()) for run in runs: runTable = cherryTable[cherryTable.Run == run] runTable.to_excel(writer, run, index=False) runTable.to_csv(os.path.join(directory, run + ".csv"), index=False) writer.save() def importCherryPicking(self): """Imports files for a round of Cherrypicking.""" title = "Choose cherrypicking file..." cherryFile, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) title = "Choose lightcycler files..." filter_mask = "Lightcycler text files (*.txt)" lightFileNames, f = QtGui.QFileDialog.getOpenFileNames(self, title, self.path, filter_mask) fileDataLists, ok = LCDialog.importLC(lightFileNames) lc = pd.read_excel(cherryFile, sheetname="All") lc = lc[["Source plate", "Dest plate", "Source Well", "Destination Well"]] lc.columns = ["Plate ID", "CP Plate", "Well", "CP Well"] lc["LC Well"] = "" lc["Result"] = "" lc["Experiment"] = "" lc = lc.set_index(["CP Plate", "CP Well"]) for fDL in fileDataLists: name, plate, exp, robot, pos = fDL lcFrame = pd.read_table(name, sep="\t", header=1) lcFrame = lcFrame.drop(["Include", "Color", "Name", "Status"], 1) lcFrame["Experiment"] = exp lcFrame["CP Plate"] = plate lcFrame["CP Well"] = lcFrame["Pos"].map(lambda x: convert[robot][pos][x]) lcFrame["Group"] = lcFrame["Group"].astype(str) lcFrame.columns = ["LC Well", "Result", "Experiment", "CP Plate", "CP Well"] lcFrame = lcFrame.set_index(["CP Plate", "CP Well"]) lc.update(lcFrame) lc = lc.set_index(["Plate ID", "Well"]) self.resultsTable.table = self.resultsTable.table.set_index(["Plate ID", "Well"]) self.resultsTable.table.update(lc) self.resultsTable.table = self.resultsTable.table.reset_index() self.__updateView() def importCherryPickingTaq(self): """Taq""" title = "Choose cherrypicking file..." cherryFile, f = QtGui.QFileDialog.getOpenFileName(self, title, self.path) title = "Choose lightcycler files..." filter_mask = "Lightcycler text files (*.txt)" lightFileNames, f = QtGui.QFileDialog.getOpenFileNames(self, title, self.path, filter_mask) fileDataLists, ok = LCDialog.importLC(lightFileNames) lc = pd.read_excel(cherryFile, sheetname="All") lc = lc[["Source plate", "Dest plate", "Source Well", "Destination Well"]] lc.columns = ["Plate ID", "CP Plate", "Well", "CP Well"] lc["LC Well"] = "" lc["Result"] = "" lc["Experiment"] = "" lc = lc.set_index(["CP Plate", "CP Well"]) for fDL in fileDataLists: name, plate, exp, robot, pos = fDL lcFrame = pd.read_table(name, sep="\t", header=1) lcFrame = lcFrame.drop(["Include", "Color", "Name", "Status", "465-510", "533-580", "Score"], 1) lcFrame["Experiment"] = exp lcFrame["CP Plate"] = plate lcFrame["CP Well"] = lcFrame["Pos"].map(lambda x: convert[robot][pos].get(x, "")) lcFrame["Call"] = lcFrame["Call"].astype(str) lcFrame.columns = ["LC Well", "Result", "Experiment", "CP Plate", "CP Well"] lcFrame = lcFrame[lcFrame["CP Well"] != ""] lcFrame = lcFrame.set_index(["CP Plate", "CP Well"]) lc.update(lcFrame) lc = lc.set_index(["Plate ID", "Well"]) lc = lc[lc["Result"] != ""] self.resultsTable.table = self.resultsTable.table.set_index(["Plate ID", "Well"]) self.resultsTable.table.update(lc) self.resultsTable.table = self.resultsTable.table.reset_index() self.__updateView() ######################################################################## ## Data Menu Actions def editPlates(self): """Opens a popup table where the data in the sample table can be edited by plate, rather than by sample.""" plates = self.resultsTable.table[ ["Plate ID", "Plate Name", "Plate Kea", "Crop", "Experiment", "Grind", "Include"] ] plates = plates.drop_duplicates(subset=["Plate ID"]) platesData, ok = EditPlatesDialog.run(plates) self.resultsTable.editPlates(platesData) self.infoTable.editPlates(platesData) self.__updateView() def viewPlateStats(self): """Opens a popup with result stats organised by plate.""" included = self.resultsTable.table[self.resultsTable.table["Include"] == True] included = included[included.Group != "No sample"] groups = list(np.unique(included["Group"])) statsTable = self.__getStatsTable(included, groups, "Plate ID") ok = StatsDialog.run(statsTable) def viewPopulationStats(self): """Opens a popup with result stats organised by population.""" included = self.resultsTable.table[self.resultsTable.table["Include"] == True] groups = list(np.unique(included["Group"])) statsTable = self.__getStatsTable(included, groups, "Population") ok = StatsDialog.run(statsTable) def setCrop(self): """Opens a popup to set crop for all samples.""" crop, ok = MyDialog.chooseCrop() if ok: self.resultsTable.setCrop(crop) self.__updateView() def explainCrop(self): """Opens a popup to explain which marker results are valid.""" dialog = QtGui.QMessageBox.information( self, "Crop explanation", "Calls expected:\n" + "Brassica: Kale, Rape, Swede, Turnip\n" + "Brassica R-S: Kale, Rape, Swede, Turnip, Rape-Swede\n" + "Brassica J-P/C: Kale, Rape, Swede, Turnip, Juncea, Pak Choy\n" + "Brassica SPF: Spitfire, Other Rape\n" + "Ryegrass: AR1, AR37, Ct/wt, AR542/584, AR542, AR581\n" + "Ryegrass501: AR501, Other Endo\n" + "Kiwifruit: Male, Female, Super Male,\n" + " (Super) (Fem/M)ale Type (1/2/I/II)\n" + "Apple: 1, 2, 3, 4\n\n" + "Statistics provided:\n" + "Brassica: Kale, Rape, Swede, Turnip\n" + "Brassica R-S: Kale, Rape, Swede, Turnip, Rape-Swede\n" + "Brassica J-P/C: Kale, Rape, Swede, Turnip, Juncea, Pak Choy\n" + "Brassica SPF: Spitfire, Other Rape\n" + "Ryegrass: Group 1, Group 2, Group 3, Group 4, Group 5\n" + "Ryegrass501: AR501, Other Endo\n" + "Kiwifruit: Male, Female\n" + "Apple: 1, 2, 3, 4\n", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) ######################################################################## ## Results Menu Actions def standardiseResults(self): """Corrects HRM results so you can change both 'male' and 'Male' to 'M'.""" results = np.unique(self.resultsTable.table["Result"]) standardisations, ok = MyDialog.standardiseResults(results) if ok: self.resultsTable.table["Result"] = self.resultsTable.table["Result"].map(lambda res: standardisations[res]) self.__updateView() def negativiseUnknowns(self): """Sets all Unknown results in Results column to Negative.""" self.resultsTable.negativiseUnknowns() self.__updateView() def addAutoResults(self): self.resultsTable.table["Group"] = self.resultsTable.table.apply( lambda row: standards[row["Crop"]].get(row["Result"], np.nan), 1 ) self.__updateView() def addManualResults(self): """Adds data to the Group column based on the Result column""" results = np.unique(self.resultsTable.table["Result"]) standardisations, ok = MyDialog.standardiseResults(results) if ok: self.resultsTable.table["Group"] = self.resultsTable.table["Result"].map(lambda res: standardisations[res]) self.__updateView() def setNonExistsToNoSample(self): self.resultsTable.setNonExistsToNoSample() def setNonExistsToNegative(self): self.resultsTable.setNonExistsToNegative() def includeAll(self): self.resultsTable.includeAll() self.__updateView() def excludeFailGrinds(self): self.resultsTable.excludeFailGrinds() self.__updateView() def excludeNegativeFailGrinds(self): self.resultsTable.excludeNegativeFailGrinds() self.__updateView() def excludeNonExists(self): self.resultsTable.excludeNonExists() self.__updateView() def kiwifruitResults(self): self.addAutoResults() self.setNonExistsToNoSample() def brassicaRyegrassResults(self): self.addAutoResults() self.excludeNegativeFailGrinds() self.excludeNonExists() def appleResults(self): self.addAutoResults() self.setNonExistsToNoSample() ######################################################################## ## Export Menu Actions def __checkResults(self): """Makes sure there are good results in the Results and Groups columns in preparation for export.""" if self.resultsTable.missingResults()[0]: dialog = QtGui.QMessageBox.information( self, "Invalid Results", "One or more entries in the Result column is invalid.\n" + "Please check all LC files imported properly.\n" + "There should be no nan in the Result column.", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) return False elif self.resultsTable.missingResults()[1]: dialog = QtGui.QMessageBox.information( self, "Invalid Groups", "One or more entries in the Group column is invalid.\n" + "Please check for typos in the Results column,\n" + "and make sure the correct marker is selected.\n" + "Typos can be mixed with Results > Standardise\n" + "results. The marker can be set with Data > set\n" + "crop. After completing either of these steps,\n" + "select Results > Add groups by crop...", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok, ) return False else: return True def outputHarvestSheets(self): """Outputs harvest spreadsheets.""" title = "Excel filename..." exportFileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) exportFileName = exportFileName.split(".")[0] workBook = ExportWorkbook() sampleTable = self.resultsTable.table.merge(self.infoTable.table, on=["Plate ID", "Well"], suffixes=("", "_y")) workBook.addHarvestSheets(sampleTable) workBook.save(exportFileName + ".xls") def outputForKea(self): """Outputs an Excel file suitable for upload to Kea via the sex testing process run.""" if self.__checkResults(): title = "Excel filename..." exportFileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) exportFileName = exportFileName.split(".")[0] experiments = self.resultsTable.getExperiments() experimentData, ok = ExperimentDialog.run(experiments) if ok: columns = ["Sample ID", "Plant Alt Names", "Plate Name", "Experiment", "Group"] resultTable = self.resultsTable.getKeaSexTestingData() infoTable = self.infoTable.getKeaSexTestingData() table = resultTable.join(infoTable, rsuffix="i").reset_index() table["Screening Date"] = table["Slipstream Expt No"].apply(lambda x: experimentData[x][0]) table["Marker Name"] = table["Slipstream Expt No"].apply(lambda x: experimentData[x][1]) table["Notes"] = "" table["Operator"] = "" columns = [ "Sample ID", "Plant AltName", "Plate", "Screening Date", "Slipstream Expt No", "Marker Name", "Sex Marker Results", "Notes", "Operator", ] table = table[columns] writer = pd.ExcelWriter(exportFileName + ".xls") table.to_excel(writer, "Data", index=False) writer.save() def outputForEBrida(self): """Outputs results as a spreadsheet based on the recieved EBrida spreadsheet...""" if self.__checkResults(): title = "Excel filename..." exportFileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) exportFileName = exportFileName.split(".")[0] keys = ["Plate ID", "Well"] resColumns = ["Group", "Plate ID", "Plate Kea", "Well"] infoColumns = [ "Pedigree Item", "Plot", "Group", "Start Date", "From Ped. Item", "Mother", "Father", "Barcode", "synonyms", "fundingNameCr", "BreederName", "Sample ID", ] outputColumns = [ "Pedigree Item", "Plot", "Group", "Start Date", "From Ped. Item", "Mother", "Father", "Barcode", "synonyms", "fundingNameCr", "BreederName", "keaID", "Result", "Plate ID", "Plate Name", "Well", ] info = self.infoTable.table[infoColumns + keys] results = self.resultsTable.table[resColumns] results.columns = ["Result", "Plate ID", "Plate Kea", "Well"] outputTable = pd.merge(info, results, on=keys, sort=False) outputTable.rename(columns={"Sample ID": "keaID", "Plate Kea": "Plate Name"}, inplace=True) outputTable = outputTable[outputColumns] writer = pd.ExcelWriter(exportFileName + ".xls") outputTable.to_excel(writer, "Sheet1", index=False) writer.save() def colouredResults(self): """Outputs an Excel file with a summary table, a sample table, and a plate sheet for each plate.""" if self.__checkResults(): title = "Excel filename..." exportFileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) exportFileName = exportFileName.split(".")[0] crops = list(np.unique(self.resultsTable.table["Crop"])) groupsLists = [groups[crop] for crop in crops] incGroups = [item for sublist in groupsLists for item in sublist] incGroups = incGroups + ["Unknown", "Negative"] included = self.resultsTable.table[self.resultsTable.table["Include"] == True] exportTable = included[["Plate ID", "Plate Name", "Well", "Result", "Group"]].reset_index(drop=True) statsTable = self.__getStatsTable(exportTable, incGroups, "Plate ID") statsTable["Ind"] = statsTable.index.values plates = statsTable[["Plate ID", "Plate Name"]] ok = True while (plates["Plate Name"].str.len() > 23).any() and ok: plates, ok = ShortenPlateNamesDialog.run(plates) statsTable = statsTable.set_index("Plate ID") exportTable = exportTable.set_index("Plate ID") plates = plates.set_index("Plate ID") statsTable.update(plates) exportTable.update(plates) statsTable = statsTable.reset_index() exportTable = exportTable.reset_index() if ok: workBook = ExportWorkbook() workBook.addStatsPage(incGroups, statsTable) workBook.addSamplePage(exportTable) workBook.addPlateSheets(statsTable, exportTable, incGroups) workBook.save(exportFileName + ".xls") def niceKeaSpreadsheet(self): """Outputs Results and Kea data to a spreadsheet.""" if self.__checkResults(): title = "Excel filename..." exportFileName, f = QtGui.QFileDialog.getSaveFileName(self, title, self.path) exportFileName = exportFileName.split(".")[0] columns = ["Plate ID", "Plate Kea", "Well", "Sample ID", "PlantID", "Group"] table = ( self.resultsTable.table.set_index(["Plate ID", "Well"]) .join(self.infoTable.table.set_index(["Plate ID", "Well"]), rsuffix="i") .reset_index() ) table = table[columns] table["Ind"] = table.index.values workBook = ExportWorkbook() workBook.addKeaTable(table) workBook.save(exportFileName + ".xls")