class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() uic.loadUi('mainwindow.ui', self) self.statusLabel.setText("") self.progressBar.setVisible(False) self.previousButton.clicked.connect(self.previousButton_clicked) self.nextButton.clicked.connect(self.nextButton_clicked) self.siteSelector.lineEdit().returnPressed.connect(self.nextButton_clicked) self.usernameTextbox.returnPressed.connect(self.nextButton_clicked) self.passwordTextbox.returnPressed.connect(self.nextButton_clicked) self.importCsvOption.clicked.connect(self.operationOption_clicked) self.exportCsvOption.clicked.connect(self.operationOption_clicked) self.exportClinVarOption.clicked.connect(self.operationOption_clicked) self.browseButton.clicked.connect(self.browseButton_clicked) def asyncAddGeneSelectorItem(self, item): QMetaObject.invokeMethod(self, 'addGeneSelectorItem', Qt.QueuedConnection, Q_ARG(str, item)) def asyncAddOwnerSelectorItem(self, item): QMetaObject.invokeMethod(self, 'addOwnerSelectorItem', Qt.QueuedConnection, Q_ARG(str, item)) def asyncAddStudySelectorItem(self, item): QMetaObject.invokeMethod(self, 'addStudySelectorItem', Qt.QueuedConnection, Q_ARG(str, item)) def asyncClearOwnerSelector(self): QMetaObject.invokeMethod(self.ownerSelector, 'clear', Qt.QueuedConnection) def asyncClearStudySelector(self): QMetaObject.invokeMethod(self.studySelector, 'clear', Qt.QueuedConnection) def asyncHideGeneSelector(self): QMetaObject.invokeMethod(self.geneLabel, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, False)) QMetaObject.invokeMethod(self.geneSelector, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, False)) def asyncLockUi(self, status, maxProgress = 0): QMetaObject.invokeMethod(self, 'setEnabled', Qt.QueuedConnection, Q_ARG(bool, False)) self.asyncSetStatus(status, maxProgress) QMetaObject.invokeMethod(self.progressBar, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, True)) def asyncResetGeneSelector(self): QMetaObject.invokeMethod(self.geneLabel, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, True)) QMetaObject.invokeMethod(self.geneSelector, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, True)) QMetaObject.invokeMethod(self.geneSelector, 'clear', Qt.QueuedConnection) self.asyncAddGeneSelectorItem('All genes') def asyncSetBrowseLabelText(self, text): QMetaObject.invokeMethod(self.browseLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, text)) def asyncSetConfirmation(self, confirmation): QMetaObject.invokeMethod(self.confirmationLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, confirmation)) def asyncSetOwnerLabelText(self, text): QMetaObject.invokeMethod(self.ownerLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, text)) def asyncSetOwnerSelectorText(self, text): QMetaObject.invokeMethod(self.ownerSelector, 'setCurrentText', Qt.QueuedConnection, Q_ARG(str, text)) def asyncSetPage(self, index): QMetaObject.invokeMethod(self.stackedWidget, 'setCurrentIndex', Qt.QueuedConnection, Q_ARG(int, index)) def asyncSetProgress(self, progress): QMetaObject.invokeMethod(self.progressBar, 'setValue', Qt.QueuedConnection, Q_ARG(int, progress)) def asyncSetStatus(self, status, maxProgress = 0): QMetaObject.invokeMethod(self.statusLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, status)) QMetaObject.invokeMethod(self.progressBar, 'setMaximum', Qt.QueuedConnection, Q_ARG(int, maxProgress)) def asyncSetStudyLabelText(self, text): QMetaObject.invokeMethod(self.studyLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, text)) def asyncSetSummary(self, summary): QMetaObject.invokeMethod(self.summaryLabel, 'setText', Qt.QueuedConnection, Q_ARG(str, summary)) def asyncUnlockUi(self, status = ''): QMetaObject.invokeMethod(self, 'setEnabled', Qt.QueuedConnection, Q_ARG(bool, True)) QMetaObject.invokeMethod(self.progressBar, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, False)) self.asyncSetStatus(status) def turnToPage2(self): self.asyncLockUi('Finding studies, users, and work groups...') self.site = self.siteSelector.currentText().rstrip('/') self.username = self.usernameTextbox.text() self.password = self.passwordTextbox.text() self.bot = PhenoTipsBot(self.site, self.username, self.password) try: self.studies = self.bot.list_studies() self.users = self.bot.list_users() self.groups = self.bot.list_groups() self.gene_table = {} if self.operation == EXPORT_CLINVAR: self.asyncSetStatus('Getting patient list...') patient_ids = self.bot.list() self.asyncSetStatus('Getting gene list...', len(patient_ids)) count = 0 for patient_id in patient_ids: for variant_num in self.bot.list_objects(patient_id, 'Main.ClinVarVariant'): gene = self.bot.get_object(patient_id, 'Main.ClinVarVariant', variant_num).get('gene_symbol').upper() if gene: if gene not in self.gene_table: self.gene_table[gene] = set() self.gene_table[gene].add(patient_id) count += 1 self.asyncSetProgress(count) except Exception as err: self.asyncUnlockUi(str(err)) return if len(self.studies) or len(self.users) > 1 or len(self.groups): self.asyncClearStudySelector() self.asyncClearOwnerSelector() if self.operation == IMPORT_CSV: self.asyncSetStudyLabelText('Which study form should be used for the new patients?') self.asyncSetOwnerLabelText('Who should own (have access to) the new patients?') else: self.asyncSetStudyLabelText('Which study do you want to export from?') self.asyncAddStudySelectorItem('All studies') self.asyncSetOwnerLabelText('Which user or group\'s patients do you want to export?') self.asyncAddOwnerSelectorItem('All users') self.asyncAddStudySelectorItem('Default study') for study in self.studies: self.asyncAddStudySelectorItem(study) for user in self.users: self.asyncAddOwnerSelectorItem(user) for group in self.groups: self.asyncAddOwnerSelectorItem('Groups.' + group) if self.operation == IMPORT_CSV: self.asyncSetOwnerSelectorText(self.username) if self.operation == IMPORT_CSV: self.asyncHideGeneSelector() if len(self.users) > 1 or len(self.studies): self.asyncSetPage(2) else: self.study = None self.turnToPage3() self.asyncUnlockUi() elif self.operation == EXPORT_CSV: self.asyncHideGeneSelector() if len(self.studies) > 1: self.asyncSetPage(2) else: self.study = None self.turnToPage3() self.asyncUnlockUi() else: if len(self.gene_table): self.asyncResetGeneSelector() for gene in self.gene_table: self.asyncAddGeneSelectorItem(gene) if len(self.studies) or len(self.gene_table) > 1: self.asyncSetPage(2) else: self.study = None self.owner = self.username self.gene = None self.asyncTurnToPage3() self.asyncUnlockUi() else: self.asyncUnlockUi('There are no variants for ClinVar on this site.') def turnToPage3(self): if self.operation == IMPORT_CSV: self.asyncSetBrowseLabelText('Please click Browse and open the file to import.') elif self.operation == EXPORT_CSV: self.asyncSetBrowseLabelText('Please click Browse and save the file to export.') else: self.asyncSetBrowseLabelText('Please click Browse and select the folder to save Variant.csv and CaseData.csv to.') self.asyncSetPage(3) def turnToPage4(self): global confirmation self.asyncLockUi('Parsing CSV file...') confirmation = '' try: def unrecognizedColumnHandler(column): global confirmation confirmation += 'WARNING: Ignoring unrecognized column "' + column + '"\n' def unrecognizedValueHandler(value, field): global confirmation confirmation += 'WARNING: Ignoring unrecognized value "' + value + '" for "' + field + '"\n' self.patients = parse_csv_file(self.path, unrecognizedColumnHandler, unrecognizedValueHandler) self.asyncSetStatus('Checking ' + str(len(self.patients)) + ' external IDs...', len(self.patients)) self.patient_ids = get_patient_ids(self.bot, self.patients, self.asyncSetProgress) self.n_to_import = str(len(self.patients) - len(self.patient_ids)) self.n_to_update = str(len(self.patient_ids)) except Exception as err: self.asyncUnlockUi(str(err)) return confirmation += '\nYou are about to import ' + self.n_to_import + ' new patients and update ' + self.n_to_update + ' existing patients.' self.asyncSetConfirmation(confirmation.strip()) self.asyncSetPage(4) self.asyncUnlockUi() def turnToPage5(self): if self.operation == IMPORT_CSV: self.asyncLockUi('Importing/updating...', len(self.patients)) try: elapsedTime = import_patients(self.bot, self.patients, self.patient_ids, self.study, self.owner, self.asyncSetProgress) except Exception as err: self.asyncUnlockUi(str(err)) return self.asyncSetSummary( 'Imported ' + self.n_to_import + ' patients and updated ' + self.n_to_update + ' patients.\n' + 'Elapsed time ' + str(elapsedTime) ) elif self.operation == EXPORT_CSV: self.asyncLockUi('Getting patient list...') try: patient_ids = self.bot.list() self.asyncSetStatus('Exporting...', len(patient_ids)) outFile = open(self.path, 'w') n_exported, elapsedTime = export_patients(self.bot, patient_ids, self.study, self.owner, outFile, self.asyncSetProgress) outFile.close() except Exception as err: self.asyncUnlockUi(str(err)) return self.asyncSetSummary( 'Exported ' + str(n_exported) + ' patients.\n' + 'Elapsed time ' + str(elapsedTime)) else: if self.gene: patient_ids = self.gene_table[self.gene] else: patient_ids = set.intersection(*self.gene_table.values()) self.asyncLockUi('Exporting...', len(patient_ids)) try: clinvar_data, elapsedTime1 = get_clinvar_data(self.bot, patient_ids, self.study, self.owner, self.gene, self.asyncSetProgress) self.asyncSetStatus('Writing files Variant.csv and CaseData.csv...') variantsFile = open(self.path + '/Variant.csv', 'w') caseDataFile = open(self.path + '/CaseData.csv', 'w') n_variants, n_cases, elapsedTime2 = write_clinvar_files(clinvar_data, variantsFile, caseDataFile) variantsFile.close() caseDataFile.close() except Exception as err: self.asyncUnlockUi(str(err)) return self.asyncSetSummary( 'Exported ' + str(n_variants) + ' variants and ' + str(n_cases) + ' cases.\n' + 'Elapsed time ' + str(elapsedTime1 + elapsedTime2) ) self.asyncSetPage(5) self.asyncUnlockUi() # slots # @pyqtSlot(str) def addGeneSelectorItem(self, item): self.geneSelector.addItem(item) @pyqtSlot(str) def addStudySelectorItem(self, item): self.studySelector.addItem(item) @pyqtSlot(str) def addOwnerSelectorItem(self, item): self.ownerSelector.addItem(item) def browseButton_clicked(self): if self.operation == IMPORT_CSV: path = QFileDialog.getOpenFileName(self, 'Import spreadsheet', '', '*.csv')[0] elif self.operation == EXPORT_CSV: path = QFileDialog.getSaveFileName(self, 'Export spreadsheet', '', '*.csv')[0] else: path = QFileDialog.getExistingDirectory(self, 'Export spreadsheets') if path: self.pathLabel.setText(path) def nextButton_clicked(self): if self.stackedWidget.currentIndex() == 0: #operation self.importMode = self.importCsvOption.isChecked() if self.importCsvOption.isChecked(): self.operation = IMPORT_CSV elif self.exportCsvOption.isChecked(): self.operation = EXPORT_CSV else: self.operation = EXPORT_CLINVAR self.previousButton.setEnabled(True) self.stackedWidget.setCurrentIndex(1) #login elif self.stackedWidget.currentIndex() == 1: #login Thread(target=self.turnToPage2).start() #study elif self.stackedWidget.currentIndex() == 2: #study, owner, and gene self.study = self.studySelector.currentText() if self.study == 'All studies': self.study = None elif self.study == 'Default study': if len(self.studies): self.study = '' else: self.study = None self.owner = self.ownerSelector.currentText() if self.owner == 'All users': self.owner = None self.gene = self.geneSelector.currentText() if self.gene == 'All genes': self.gene = None self.pathLabel.setText('') Thread(target=self.turnToPage3).start() #file elif self.stackedWidget.currentIndex() == 3: #file self.path = self.pathLabel.text() if self.path: if self.operation == IMPORT_CSV: Thread(target=self.turnToPage4).start() #confirmation else: Thread(target=self.turnToPage5).start() #summary else: self.browseButton_clicked() elif self.stackedWidget.currentIndex() == 4: #confirmation Thread(target=self.turnToPage5).start() #summary elif self.stackedWidget.currentIndex() == 5: #summary self.previousButton.setEnabled(False) self.stackedWidget.setCurrentIndex(0) #operation def operationOption_clicked(self): self.nextButton.setEnabled(True) def previousButton_clicked(self): self.statusLabel.clear() if self.stackedWidget.currentIndex() in [1, 5]: #login, summary self.stackedWidget.setCurrentIndex(0) #operation self.previousButton.setEnabled(False) self.nextButton.setEnabled(True) elif self.stackedWidget.currentIndex() == 2: #study self.stackedWidget.setCurrentIndex(1) #login self.previousButton.setEnabled(True) self.nextButton.setEnabled(True) elif self.stackedWidget.currentIndex() == 3: #file if len(self.studies): self.stackedWidget.setCurrentIndex(2) #study else: self.stackedWidget.setCurrentIndex(1) #login self.nextButton.setEnabled(True) elif self.stackedWidget.currentIndex() == 4: #confirmation self.stackedWidget.setCurrentIndex(3) #file
if len(studies): print('Available studies:') print('* ' + '\n* '.join(studies)) sys.stderr.write('Are you exporting from a particular study (blank for no)? ') study = input() if study and study[0] == 'y': sys.stderr.write('Input the study to export from (blank for default): ') study = input() else: study = None elif study == 'None': study = None if owner == None: users = bot.list_users() groups = bot.list_groups() if len(users) > 1: print('Available users:') print('* ' + '\n* '.join(users)) if len(groups): print('Available work groups:') print('* ' + '\n* Groups.'.join(groups)) if len(users) > 1 or len(groups): owner = input('Input which user or group\'s patients to export (blank for all users): ') #begin export start_time = time.time() count = 0 patient_ids = bot.list(study, owner)