<commit_before>#!/usr/bin/python3

from phenotipsbot import PhenoTipsBot
from PyQt5 import uic
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import Q_ARG
from PyQt5.QtCore import QMetaObject
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QMainWindow
from sys import argv
from sys import exit
from threading import Thread
parse_csv_file = __import__('import-csv').parse_csv_file
get_patient_ids = __import__('import-csv').get_patient_ids
import_patients = __import__('import-csv').import_patients
export_patients = __import__('export-csv').export_patients
get_clinvar_data = __import__('export-clinvar').get_clinvar_data
write_clinvar_files = __import__('export-clinvar').write_clinvar_files

IMPORT_CSV = 1
EXPORT_CSV = 2
EXPORT_CLINVAR = 3

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        uic.loadUi('mainwindow.ui', self)
        self.statusLabel.setVisible(False)
        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.statusLabel, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, bool(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(having_object='PhenoTips.ClinVarVariantClass')
                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, 'PhenoTips.ClinVarVariantClass'):
                        gene = self.bot.get_object(patient_id, 'PhenoTips.ClinVarVariantClass', 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:<commit_msg>Show friendlier errors in GUI on bad site, username, or password<commit_after>#!/usr/bin/python3

from phenotipsbot import PhenoTipsBot
from PyQt5 import uic
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import Q_ARG
from PyQt5.QtCore import QMetaObject
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QMainWindow
from requests import ConnectionError
from requests import HTTPError
from sys import argv
from sys import exit
from threading import Thread
parse_csv_file = __import__('import-csv').parse_csv_file
get_patient_ids = __import__('import-csv').get_patient_ids
import_patients = __import__('import-csv').import_patients
export_patients = __import__('export-csv').export_patients
get_clinvar_data = __import__('export-clinvar').get_clinvar_data
write_clinvar_files = __import__('export-clinvar').write_clinvar_files

IMPORT_CSV = 1
EXPORT_CSV = 2
EXPORT_CLINVAR = 3

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        uic.loadUi('mainwindow.ui', self)
        self.statusLabel.setVisible(False)
        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.statusLabel, 'setVisible', Qt.QueuedConnection, Q_ARG(bool, bool(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(having_object='PhenoTips.ClinVarVariantClass')
                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, 'PhenoTips.ClinVarVariantClass'):
                        gene = self.bot.get_object(patient_id, 'PhenoTips.ClinVarVariantClass', 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 ConnectionError:
            self.asyncUnlockUi('The site appears to be mistyped')
            return
        except HTTPError as err:
            if err.response.status_code == 401:
                self.asyncUnlockUi('Wrong username or password')
            else:
                self.asyncUnlockUi(str(err))
            return
        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:
{'fraction_non_alphanumeric': 0.09826336831584208, 'fraction_numerical': 0.0024362818590704647, 'mean_word_length': 3.4370842572062084, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1123531', 'n_tokens_mistral': 4737, 'n_tokens_neox': 4541, 'n_words': 852}