class OWDtoxsAlignment(widget.OWWidget): name = "Dtoxs Alignment" description = "Step 1 of the Dtoxs SOP. Uses a Burrows-Wheeler Aligner (BWA)." category = "RNASeq" icon = "icons/dtoxs-alignment2.svg" priority = 10 image_name = "biodepot/dtoxs_alignment" image_version = "latest" inputs = [("References", str, "set_refs"), ("Seqs", str, "set_seqs"), ("Configs", str, "set_configs"), ("Barcodes", str, "set_barcodes_file")] outputs = [("Counts", str)] auto_run = Setting(True) want_main_area = False def __init__(self): super().__init__() # Docker Client # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') self.hostDirectories = {'refs': None, 'seqs': None, 'conf': None, 'counts': None, 'aligns': None, 'barcodes': None} self.labelText = {'refs': 'References: {0}', 'seqs': 'Sequences: {0}', 'conf': 'Configs: {0}', 'barcodes': 'Barcode file: {0}'} # folders that will created automatically self.result_folder_name = "Counts" self.aligns_folder_name = "Aligns" # GUI box = gui.widgetBox(self.controlArea, "Info") self.lblRefs = gui.widgetLabel(box, 'References: Not Set') self.lblSeqs = gui.widgetLabel(box, 'Sequences: Not Set') self.lblConfigs = gui.widgetLabel(box, 'Configs: Not Set') self.lblBarcodes = gui.widgetLabel(box, "Barcode file: Not Set") self.infoLabel = gui.widgetLabel(box, 'Waiting...') self.infoLabel.setWordWrap(True) gui.checkBox(self.controlArea, self, 'auto_run', 'Run automatically when input set') self.btn_run = gui.button(self.controlArea, self, "Run", callback=self.btn_run_pushed) self.is_running = False self.setMinimumSize(500, 200) """ Called when the user pushes 'Run' """ def btn_run_pushed(self): self.start_container(run_btn_pushed=True) """ Set references """ def set_refs(self, path): self.__set_directory__('refs', self.lblRefs, path) """ Set seqs """ def set_seqs(self, path): self.__set_directory__('seqs', self.lblSeqs, path, startContainer=False) if self.hostDirectories['seqs'] is not None: # Jimmy March-28-2017, once the seq input was set, automatically create a result and aligns folder as a sibling of "Seqs" parent_path = os.path.abspath(os.path.join(self.hostDirectories['seqs'], '..')) self.hostDirectories['counts'] = os.path.join(parent_path, self.result_folder_name) self.hostDirectories['aligns'] = os.path.join(parent_path, self.aligns_folder_name) if not os.path.exists(self.hostDirectories['counts']): os.makedirs(self.hostDirectories['counts']) if not os.path.exists(self.hostDirectories['aligns']): os.makedirs(self.hostDirectories['aligns']) self.start_container(run_btn_pushed=False) def set_configs(self, path): self.__set_directory__('conf', self.lblConfigs, path) def __set_directory__(self, key, ctrlLabel, path, startContainer = True): # When a user removes a connected Directory widget, # it sends a signal with path=None if path is None: self.hostDirectories[key] = None ctrlLabel.setText(self.labelText[key].format('Not Set')) elif not os.path.exists(path): self.hostDirectories[key] = None ctrlLabel.setText(self.labelText[key].format('None existent directory: {}'.format(str(path)))) else: self.hostDirectories[key] = path.strip() if key == 'barcodes': path = os.path.basename(path) self.hostDirectories['barcodes_basename'] = path ctrlLabel.setText(self.labelText[key].format((str(path)))) if startContainer: self.start_container(run_btn_pushed=False) def set_barcodes_file(self, filename): self.__set_directory__('barcodes', self.lblBarcodes, filename) """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.is_running = True self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_worker = PullImageThread(self.docker, self.image_name, self.image_version) self.pull_image_worker.pull_progress.connect(self.pull_image_progress) self.pull_image_worker.finished.connect(self.pull_image_finished) self.pull_image_worker.start() def pull_image_progress(self, val): self.progressBarSet(val) def pull_image_finished(self): self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.run_container() """ Alignment """ def start_container(self, run_btn_pushed=True): # Make sure both inputs are set all_set = all(value is not None for value in self.hostDirectories.values()) if all_set: if not self.is_running and (self.auto_run or run_btn_pushed): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() else: self.run_container() def run_container(self): self.is_running = True self.btn_run.setEnabled(False) self.infoLabel.setText('Running alignment...') self.setStatusMessage('Running...') #self.progressBarInit() # Run the container in a new thread self.run_container_thread = RunAlignmentThread(self.docker, self.image_name, self.hostDirectories) self.run_container_thread.progress.connect(self.run_container_progress) self.run_container_thread.finished.connect(self.run_container_finished) self.run_container_thread.start() def run_container_progress(self, val): self.progressBarSet(val) def run_container_finished(self): self.infoLabel.setText("Finished running alignment!") self.btn_run.setEnabled(True) self.is_running = False self.btn_run.setText('Run again') self.setStatusMessage('Finished!') #self.progressBarFinished() self.send("Counts", self.hostDirectories['counts'])
class OWRSEMCalc(widget.OWWidget): name = "RSEM Calculation" description = "Step2: handles both the alignment of reads against reference transcript sequences and the calculation of relative abundances. It executes rsem-calculate-expression command" category = "RNASeq" icon = "icons/rsemcalc.svg" priority = 10 image_name = "genomicpariscentre/rsem" image_version = "latest" inputs = [(".fastq files + ref files from step1", str, "set_aligns")] outputs = [("Results", str)] want_main_area = False # The directory of the alignment data needed to run # the container will be set by the user before the # container can be run host_counts_dir = "" # The default write location of all widgets should be # ~/BioDepot/WidgetName/ # TODO is this an issue if multiple containers write to the same place? # host_results_dir = os.path.expanduser('~') + '/BioDepot/Kallisto' host_results_dir = os.path.expanduser('~') + '/BioDepot/RSEM_Calc/Results' def __init__(self): super().__init__() # Docker Client # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') # GUI box = gui.widgetBox(self.controlArea, "Info") self.infoLabel = gui.widgetLabel( box, 'Connect to data or use a Directory widget' ' to specify location of UMI read data files') self.infoLabel.setWordWrap(True) # TODO let user specify results directory # self.btn_res = gui.button(None, self, "Open", callback=self.set_results_dir) # self.resultsEdit = QtGui.QLineEdit(self.host_results_dir) # self.buttonsArea.layout().addWidget(self.btn_res) # self.buttonsArea.layout().addWidget(self.resultsEdit) self.autoRun = True gui.checkBox(self.controlArea, self, 'autoRun', 'Run automatically when input set') self.btn_run = gui.button(self.controlArea, self, "Run", callback=self.start_analysis) """ Set input """ def set_aligns(self, path): if not type(path) is str: # TODO create warning print('Tried to set input directory to None') elif not os.path.exists(path): # TODO create warning print('Tried to set input directory to none existent directory: ' + str(path)) else: self.host_counts_dir = path.strip() if self.autoRun: self.start_analysis() else: self.infoLabel.setText( 'Input directory set.\nWaiting to run...') """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_thread = PullImageThread(self.docker, self.image_name, self.image_version) self.pull_image_thread.pull_progress.connect(self.pull_image_progress) self.pull_image_thread.finished.connect(self.pull_image_done) self.pull_image_thread.start() def pull_image_progress(self, val): self.progressBarSet(val) def pull_image_done(self): self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.run_analysis() """ Analysis """ def start_analysis(self): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() # Make sure there is an alignment directory set elif self.host_counts_dir: self.run_analysis() else: self.infoLabel.setText('Set directory before running.') def run_analysis(self): self.btn_run.setEnabled(False) self.infoLabel.setText('Running analysis...') self.setStatusMessage('Running...') self.progressBarInit() # Run the container in a new thread self.run_analysis_thread = RunAnalysisThread(self.docker, self.image_name, self.host_counts_dir, self.host_results_dir) self.run_analysis_thread.analysis_progress.connect( self.run_analysis_progress) self.run_analysis_thread.finished.connect(self.run_analysis_done) self.run_analysis_thread.start() def run_analysis_progress(self, val): self.progressBarSet(val) def run_analysis_done(self): self.infoLabel.setText("Finished running analysis!") self.btn_run.setEnabled(True) self.btn_run.setText('Run again') self.setStatusMessage('Finished!') self.progressBarFinished() self.send("Results", self.host_results_dir) self.btn_run.setEnabled(True)
class OWDtoxsAlignment(widget.OWWidget): name = "Dtoxs Alignment" description = "Step 1 of the Dtoxs SOP. Uses a Burrows-Wheeler Aligner (BWA)." category = "RNASeq" icon = "icons/dtoxs-alignment2.svg" priority = 10 image_name = "biodepot/dtoxs_alignment" image_version = "latest" inputs = [("References", str, "set_refs"), ("Seqs", str, "set_seqs")] outputs = [("Counts", str)] auto_run = Setting(True) want_main_area = False def __init__(self): super().__init__() # Docker Client # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') self.host_ref_dir = None self.host_seq_dir = None self.ref_dir_set = False self.seq_dir_set = False self.result_folder_name = "/Count" self.aligns_folder_name = "/Aligns" # TODO is this an issue if multiple containers write to the same place? # TODO add timestamp to directory name to differentiate runs # Jimmy, Mar/7/2017, I don't know what does "toHostDir" do. Since our DockerClient missed that code, I comment it temporary #self.host_counts_dir = counts_dir #self.docker.toHostDir(counts_dir) # GUI box = gui.widgetBox(self.controlArea, "Info") self.infoLabel = gui.widgetLabel( box, 'Connect to a Directory widget ' 'to specify location of reference ' 'and seq fastq files') self.infoLabel.setWordWrap(True) gui.checkBox(self.controlArea, self, 'auto_run', 'Run automatically when input set') self.btn_run = gui.button(self.controlArea, self, "Run", callback=self.btn_run_pushed) self.is_running = False """ Called when the user pushes 'Run' """ def btn_run_pushed(self): self.start_container(run_btn_pushed=True) """ Set references """ def set_refs(self, path): # When a user removes a connected Directory widget, # it sends a signal with path=None if path is None: self.ref_dir_set = False else: self.host_ref_dir = path if self.host_ref_dir is None: # TODO emit error self.ref_dir_set = False print('References set to invalid directory') else: self.ref_dir_set = True self.start_container(run_btn_pushed=False) """ Set seqs """ def set_seqs(self, path): # When a user removes a connected Directory widget, # it sends a signal with path=None if path is None: self.seq_dir_set = False else: self.host_seq_dir = path # Jimmy March-28-2017, once the seq input was set, automatically create a result and aligns folder as a sibling of "Seqs" parent_path = os.path.abspath(os.path.join(self.host_seq_dir, '..')) self.host_counts_dir = os.path.join(parent_path + self.result_folder_name) self.host_aligns_dir = os.path.join(parent_path + self.aligns_folder_name) if not os.path.exists(self.host_counts_dir): os.makedirs(self.host_counts_dir) if not os.path.exists(self.host_aligns_dir): os.makedirs(self.host_aligns_dir) if self.host_seq_dir is None: # TODO emit error self.seq_dir_set = False print('Seq set to invalid directory') else: self.seq_dir_set = True self.start_container(run_btn_pushed=False) """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.is_running = True self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_worker = PullImageThread(self.docker, self.image_name, self.image_version) self.pull_image_worker.pull_progress.connect(self.pull_image_progress) self.pull_image_worker.finished.connect(self.pull_image_finished) self.pull_image_worker.start() def pull_image_progress(self, val): self.progressBarSet(val) def pull_image_finished(self): self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.run_container() """ Alignment """ def start_container(self, run_btn_pushed=True): # Make sure both inputs are set if self.ref_dir_set and self.seq_dir_set: if not self.is_running and (self.auto_run or run_btn_pushed): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() else: self.run_container() else: self.infoLabel.setText( 'References and Seqs directories set.\nWaiting to run...') elif self.ref_dir_set: self.infoLabel.setText("Waiting for user to set Seqs directory.") elif self.seq_dir_set: self.infoLabel.setText( "Waiting for user to set References directory.") def run_container(self): self.is_running = True self.infoLabel.setText('Running alignment...') self.setStatusMessage('Running...') #self.progressBarInit() # Run the container in a new thread self.run_container_thread = RunAlignmentThread( self.docker, self.image_name, self.host_ref_dir, self.host_seq_dir, self.host_counts_dir, self.host_aligns_dir) self.run_container_thread.progress.connect(self.run_container_progress) self.run_container_thread.finished.connect(self.run_container_finished) self.run_container_thread.start() def run_container_progress(self, val): self.progressBarSet(val) def run_container_finished(self): self.infoLabel.setText("Finished running alignment!") self.btn_run.setEnabled(True) self.is_running = False self.btn_run.setText('Run again') self.setStatusMessage('Finished!') #self.progressBarFinished() self.send("Counts", self.host_counts_dir)
class OWDtoxsAnalysis(widget.OWWidget): name = "Dtoxs Analysis" description = "Step 2 of Dtoxs SOP. Uses edgeR for differential expression analysis." category = "RNASeq" icon = "icons/dtoxs-analysis2.svg" priority = 10 image_name = "biodepot/dtoxs_analysis" image_version = "latest" inputs = [("Counts", str, "set_aligns", widget.Default), ("Configs", str, "set_configs"), ("Params", str, "set_params")] outputs = [("Results", str), ("Top 40", Orange.data.Table)] want_main_area = True want_control_area = False Exp_Design_file = settings.Setting('', schema_only=True) def __init__(self): super().__init__() self.result_folder_name = "Results" self.host_counts_dir = None self.host_config_dir = None self.host_param_dir = None # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') # GUI self.setStyleSheet("QPushButton{\n" " background-color: #1588c5;\n" " color: white;\n" " height: 25px;\n" " border: 1px solid #1a8ac6;\n" "}") # creat controls self.vlayoutBase = QtWidgets.QVBoxLayout() self.vlayoutBase.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.vlayoutBase.setContentsMargins(0, 0, 0, 0) self.vlayoutBase.setSpacing(0) self.vlayoutBase.setObjectName("vlayoutBase") self.vlayoutBase = QtWidgets.QVBoxLayout() self.vlayoutBase.setContentsMargins(0, 0, 0, 0) self.vlayoutBase.setSpacing(0) self.vlayoutBase.setObjectName("vlayoutBase") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") self.frameTitle = QtWidgets.QFrame(self.mainArea) self.frameTitle.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.frameTitle.sizePolicy().hasHeightForWidth()) self.frameTitle.setSizePolicy(sizePolicy) self.frameTitle.setMinimumSize(QtCore.QSize(0, 45)) self.frameTitle.setMaximumSize(QtCore.QSize(16777215, 65)) self.frameTitle.setStyleSheet("QFrame#frameTitle{\n" " background: #1588c5;\n" " color: #1588c5\n" "}") self.frameTitle.setFrameShape(QtWidgets.QFrame.Box) self.frameTitle.setFrameShadow(QtWidgets.QFrame.Plain) self.frameTitle.setObjectName("frameTitle") self.lblFormTitle = QtWidgets.QLabel(self.frameTitle) self.lblFormTitle.setGeometry(QtCore.QRect(10, 13, 221, 21)) font = QtGui.QFont() font.setPointSize(18) font.setBold(False) font.setWeight(50) self.lblFormTitle.setFont(font) self.lblFormTitle.setStyleSheet("\n" " color: white;\n" "") self.lblFormTitle.setObjectName("lblFormTitle") self.verticalLayout.addWidget(self.frameTitle) self.mainContent = QtWidgets.QWidget(self.mainArea) self.mainContent.setObjectName("mainContent") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.mainContent) self.verticalLayout_4.setContentsMargins(15, 15, 15, 15) self.verticalLayout_4.setObjectName("verticalLayout_4") self.vlayout_content = QtWidgets.QVBoxLayout() self.vlayout_content.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.vlayout_content.setSpacing(2) self.vlayout_content.setObjectName("vlayout_content") self.lblExpFile = QtWidgets.QLabel(self.mainContent) self.lblExpFile.setMinimumSize(QtCore.QSize(0, 25)) self.lblExpFile.setMaximumSize(QtCore.QSize(16777215, 25)) self.lblExpFile.setObjectName("lblExpFile") self.vlayout_content.addWidget(self.lblExpFile) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.horizontalLayout.setContentsMargins(0, -1, -1, -1) self.horizontalLayout.setSpacing(1) self.horizontalLayout.setObjectName("horizontalLayout") self.edtExpDesignFile = QtWidgets.QLineEdit(self.mainContent) self.edtExpDesignFile.setObjectName("edtExpDesignFile") self.horizontalLayout.addWidget(self.edtExpDesignFile) self.btnSelectExpFile = QtWidgets.QPushButton(self.mainContent) self.btnSelectExpFile.setMinimumSize(QtCore.QSize(24, 24)) self.btnSelectExpFile.setMaximumSize(QtCore.QSize(24, 24)) self.btnSelectExpFile.setObjectName("btnSelectExpFile") self.horizontalLayout.addWidget(self.btnSelectExpFile) self.vlayout_content.addLayout(self.horizontalLayout) self.line_2 = QtWidgets.QFrame(self.mainContent) self.line_2.setFrameShape(QtWidgets.QFrame.HLine) self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) self.line_2.setObjectName("line_2") self.vlayout_content.addWidget(self.line_2) self.lblInfoTitle = QtWidgets.QLabel(self.mainContent) self.lblInfoTitle.setMinimumSize(QtCore.QSize(0, 25)) self.lblInfoTitle.setMaximumSize(QtCore.QSize(16777215, 25)) self.lblInfoTitle.setStyleSheet( "background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(235, 235, 235, 255), stop:1 rgba(217, 217, 217, 255));\n" "padding-left: 3px;") self.lblInfoTitle.setObjectName("lblInfoTitle") self.vlayout_content.addWidget(self.lblInfoTitle) self.line = QtWidgets.QFrame(self.mainContent) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.vlayout_content.addWidget(self.line) self.infoLabel = QtWidgets.QLabel(self.mainContent) self.infoLabel.setMinimumSize(QtCore.QSize(0, 45)) self.infoLabel.setStyleSheet("padding-left: 3px") self.infoLabel.setFrameShape(QtWidgets.QFrame.NoFrame) self.infoLabel.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.infoLabel.setWordWrap(True) self.infoLabel.setObjectName("infoLabel") self.vlayout_content.addWidget(self.infoLabel) self.btn_run = QtWidgets.QPushButton(self.mainContent) self.btn_run.setMinimumSize(QtCore.QSize(90, 0)) self.btn_run.setMaximumSize(QtCore.QSize(90, 16777215)) self.btn_run.setObjectName("btn_run") self.vlayout_content.addWidget(self.btn_run, 0, QtCore.Qt.AlignRight) self.verticalLayout_4.addLayout(self.vlayout_content) self.verticalLayout.addWidget(self.mainContent) self.vlayoutBase.addLayout(self.verticalLayout) self.mainArea.layout().addLayout(self.vlayoutBase) self.mainArea.layout().setContentsMargins(0, 0, 0, 0) self.mainArea.setMinimumSize(568, 246) # events self.btnSelectExpFile.clicked.connect(self.OnChooseExpFile) self.btn_run.clicked.connect(self.start_analysis) self.retranslateUi(self.mainArea) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Widget", "Form")) self.lblFormTitle.setText(_translate("Widget", "DTOXS Analysis")) self.lblExpFile.setText( _translate("Widget", "Select experiment design file:")) self.btnSelectExpFile.setText(_translate("Widget", " ☰ ")) self.lblInfoTitle.setText(_translate("Widget", "Information")) self.infoLabel.setText( _translate( "Widget", "Connect to Dtoxs Alignment or use a Directory widget to specify location of UMI read counts data files" )) self.btn_run.setText(_translate("Widget", "Run")) self.edtExpDesignFile.setText(self.Exp_Design_file) """ Set input """ def set_aligns(self, path): if not type(path) is str: # TODO create warning print('Tried to set alignment directory to None') elif not os.path.exists(path): # TODO create warning print( 'Tried to set alignment directory to none existent directory: ' + str(path)) else: self.host_counts_dir = path.strip() # Jimmy March-29-2017, once the counts input was set, automatically create an output fold as a sibling of "Seqs" parent_path = os.path.abspath( os.path.join(self.host_counts_dir, '..')) self.host_results_dir = os.path.join(parent_path, self.result_folder_name) if not os.path.exists(self.host_results_dir): os.makedirs(self.host_results_dir) if os.path.exists(self.Exp_Design_file): import shutil shutil.copy2(self.Exp_Design_file, self.host_counts_dir) if self.host_param_dir and self.host_config_dir and self.Exp_Design_file: self.infoLabel.setText('All set.\nWaiting to run...') def set_configs(self, path): if not type(path) is str: print('Tried to set configs directory to None') elif not os.path.exists(path): print( 'Tried to set configs directory to none existent directory: ' + str(path)) else: self.host_config_dir = path.strip() if self.host_counts_dir and self.host_param_dir and self.Exp_Design_file: self.infoLabel.setText('All set.\nWaiting to run...') def set_params(self, path): if not type(path) is str: print('Tried to set params directory to None') elif not os.path.exists(path): print( 'Tried to set params directory to none existent directory: ' + str(path)) else: self.host_param_dir = path.strip() if self.host_counts_dir and self.host_config_dir and self.Exp_Design_file: self.infoLabel.setText('All set.\nWaiting to run...') def OnChooseExpFile(self): start_file = os.path.expanduser("~/") filename, _ = QtWidgets.QFileDialog.getOpenFileName( self, 'Open Experiment Design File', start_file) if not filename: return self.edtExpDesignFile.setText(filename) self.Exp_Design_file = filename if self.host_counts_dir and self.host_config_dir and self.host_param_dir: import shutil shutil.copy2(self.Exp_Design_file, self.host_counts_dir) self.infoLabel.setText('All set.\nWaiting to run...') """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_thread = PullImageThread(self.docker, self.image_name, self.image_version) self.pull_image_thread.pull_progress.connect(self.pull_image_progress) self.pull_image_thread.finished.connect(self.pull_image_done) self.pull_image_thread.start() def pull_image_progress(self, val): self.progressBarSet(val) def pull_image_done(self): self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.run_analysis() """ Analysis """ def start_analysis(self): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() # Make sure there is an alignment directory set elif self.host_counts_dir and self.host_config_dir and self.host_param_dir: self.run_analysis() else: self.infoLabel.setText( 'Set counts, params and configs directories before running.') def run_analysis(self): self.infoLabel.setText('Running analysis...') self.setStatusMessage('Running...') #self.progressBarInit() # Run the container in a new thread self.run_analysis_thread = RunAnalysisThread( self.docker, self.image_name, self.host_counts_dir, self.host_results_dir, self.host_config_dir, self.host_param_dir) self.run_analysis_thread.analysis_progress.connect( self.run_analysis_progress) self.run_analysis_thread.finished.connect(self.run_analysis_done) self.run_analysis_thread.start() def run_analysis_progress(self, val): self.progressBarSet(val) def run_analysis_done(self): self.infoLabel.setText("Finished running analysis!") self.btn_run.setEnabled(True) self.btn_run.setText('Run again') self.setStatusMessage('Finished!') #self.progressBarFinished() self.send("Results", self.host_results_dir) # Jimmy March 29 2017 added, create a dataset for DataTable widget to show TOP-40.tsv tsvFile = os.path.join(self.host_results_dir, 'FDR-0.1/TOP-40.tsv') tsvReader = FileFormat.get_reader(tsvFile) data = None try: data = tsvReader.read() # TODO Jimmy March 29 2017, tried to define domain for DataTable, didn't work ''' domain = Orange.data.Domain(["Cell", "Plate", "Gene", "logFC", "logCPM", "PValue"], data.domain) domain = Orange.data.Domain(data.domain.attributes, data.domain.class_vars, [Orange.data.DiscreteVariable("Cell"), Orange.data.DiscreteVariable("Plate"), Orange.data.DiscreteVariable("Condition1"), Orange.data.DiscreteVariable("Condition2"), Orange.data.StringVariable("Gene"), Orange.data.ContinuousVariable("logFC"), Orange.data.ContinuousVariable("logCPM"), Orange.data.StringVariable("PValue")]) data = data.from_table(domain, data)''' except Exception as ex: print(ex) self.send("Top 40", data)
class FastQCAnalysis(widget.OWWidget): name = "FastQC Analysis" description = "Step 2 of Dtoxs SOP. Uses edgeR for differential expression analysis." category = "RNASeq" icon = "icons/dtoxs-analysis2.svg" priority = 10 image_name = "conradstoerker/fastqc" image_version = "latest" inputs = [("Counts", str, "set_aligns")] outputs = [("Results", str)] want_main_area = False # The directory of the alignment data needed to run # the container will be set by the user before the # container can be run host_counts_dir = "" def __init__(self): super().__init__() # Docker Client # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') # GUI box = gui.widgetBox(self.controlArea, "Info") self.infoLabel = gui.widgetLabel(box, 'Connect to Dtoxs Alignment or use a Directory widget' ' to specify location of UMI read counts data files') self.infoLabel.setWordWrap(True) # TODO let user specify results directory # self.btn_res = gui.button(None, self, "Open", callback=self.set_results_dir) # self.resultsEdit = QtGui.QLineEdit(self.host_results_dir) # self.buttonsArea.layout().addWidget(self.btn_res) # self.buttonsArea.layout().addWidget(self.resultsEdit) self.autoRun = True gui.checkBox(self.controlArea, self, 'autoRun', 'Run automatically when input set') self.btn_run = gui.button(self.controlArea, self, "Run", callback=self.start_analysis) """ Set input """ def set_aligns(self, path): if not type(path) is str: # TODO create warning print('Tried to set alignment directory to None') elif not os.path.exists(path): # TODO create warning print('Tried to set alignment directory to none existent directory: ' + str(path)) else: self.host_counts_dir = path.strip() if self.autoRun: self.start_analysis() else: self.infoLabel.setText('Alignment directory set.\nWaiting to run...') """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_thread = PullImageThread(self.docker, self.image_name, self.image_version) self.pull_image_thread.pull_progress.connect(self.pull_image_progress) self.pull_image_thread.finished.connect(self.pull_image_done) self.pull_image_thread.start() def pull_image_progress(self, val=0): self.progressBarSet(val) def pull_image_done(self): self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.run_analysis() """ Analysis """ def start_analysis(self): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() # Make sure there is an alignment directory set elif self.host_counts_dir: self.run_analysis() else: self.infoLabel.setText('Set alignment directory before running.') def run_analysis(self): self.infoLabel.setText('Running analysis...') self.setStatusMessage('Running...') self.progressBarInit() # Run the container in a new thread self.run_analysis_thread = RunAnalysisThread(self.docker, self.image_name, self.host_counts_dir, self.host_counts_dir) self.run_analysis_thread.analysis_progress.connect(self.run_analysis_progress) self.run_analysis_thread.finished.connect(self.run_analysis_done) self.run_analysis_thread.start() def run_analysis_progress(self, val): self.progressBarSet(val) def run_analysis_done(self): self.infoLabel.setText("Finished running analysis!") self.btn_run.setEnabled(True) self.btn_run.setText('Run again') self.setStatusMessage('Finished!') self.progressBarFinished() self.send("Results", self.host_counts_dir)
class OWDtoxsAlignment(widget.OWWidget): name = "Dtoxs Alignment" description = "Step 1 of the Dtoxs SOP. Uses a Burrows-Wheeler Aligner (BWA)." category = "RNASeq" icon = "icons/dtoxs-alignment2.svg" priority = 10 image_name = "biodepot/dtoxs_alignment" image_version = "latest" inputs = [("References", str, "set_refs"), ("Seqs", str, "set_seqs")] outputs = [("Counts", str)] auto_run = Setting(True) want_main_area = False def __init__(self): super().__init__() # Docker Client # This client talks to your local docker self.docker = DockerClient('unix:///var/run/docker.sock', 'local') # The directory of the seq data needed to run # the container will be set by the user before the # container can be run self.host_ref_dir = None self.host_seq_dir = None self.ref_dir_set = False self.seq_dir_set = False # The default write location of all widgets should be # ~/BioDepot/WidgetName/ # TODO is this an issue if multiple containers write to the same place? # TODO add timestamp to directory name to differentiate runs counts_dir = '~/BioDepot/Dtoxs_Alignment/Counts' if not os.path.exists(counts_dir): os.makedirs(counts_dir) self.host_counts_dir = self.docker.toHostDir(counts_dir) # GUI box = gui.widgetBox(self.controlArea, "Info") self.infoLabel = gui.widgetLabel( box, 'Connect to a Directory widget ' 'to specify location of reference ' 'and seq fastq files') self.infoLabel.setWordWrap(True) gui.checkBox(self.controlArea, self, 'auto_run', 'Run automatically when input set') self.btn_run = gui.button(self.controlArea, self, "Run", callback=self.btn_run_pushed) self.is_running = False """ Called when the user pushes 'Run' """ def btn_run_pushed(self): self.start_container(run_btn_pushed=True) """ Set references """ def set_refs(self, path): # When a user removes a connected Directory widget, # it sends a signal with path=None if path is None: self.ref_dir_set = False else: self.host_ref_dir = self.docker.toHostDir(path) if self.host_ref_dir is None: # TODO emit error self.ref_dir_set = False print('References set to invalid directory') else: self.ref_dir_set = True self.start_container(run_btn_pushed=False) """ Set seqs """ def set_seqs(self, path): # When a user removes a connected Directory widget, # it sends a signal with path=None if path is None: self.seq_dir_set = False else: self.host_seq_dir = self.docker.toHostDir(path) if self.host_seq_dir is None: # TODO emit error self.seq_dir_set = False print('Seq set to invalid directory') else: self.seq_dir_set = True self.start_container(run_btn_pushed=False) """ Pull image """ def pull_image(self): self.infoLabel.setText('Pulling \'' + self.image_name + ":" + self.image_version + '\' from Dockerhub...') self.setStatusMessage("Downloading...") self.progressBarInit() self.is_running = True self.btn_run.setEnabled(False) # Pull the image in a new thread self.pull_image_thread = QThread() self.pull_image_worker = PullImageWorker(self.docker, self.image_name, self.image_version) self.pull_image_worker.progress[int].connect(self.pull_image_progress) self.pull_image_worker.finished.connect(self.pull_image_finished) self.pull_image_worker.moveToThread(self.pull_image_thread) self.pull_image_thread.started.connect(self.pull_image_worker.work) self.pull_image_thread.start() @pyqtSlot(int, name="pullImageProgress") def pull_image_progress(self, val): self.progressBarSet(val) @pyqtSlot(name="pullImageFinished") def pull_image_finished(self): self.pull_image_thread.terminate() self.pull_image_thread.wait() self.infoLabel.setText('Finished pulling \'' + self.image_name + ":" + self.image_version + '\'') self.progressBarFinished() self.start_container() """ Alignment """ def start_container(self, run_btn_pushed=True): # Make sure both inputs are set if self.ref_dir_set and self.seq_dir_set: if not self.is_running and (self.auto_run or run_btn_pushed): # Make sure the docker image is downloaded if not self.docker.has_image(self.image_name, self.image_version): self.pull_image() else: self.run_container() else: self.infoLabel.setText( 'References and Seqs directories set.\nWaiting to run...') elif self.ref_dir_set: self.infoLabel.setText("Waiting for user to set Seqs directory.") elif self.seq_dir_set: self.infoLabel.setText( "Waiting for user to set References directory.") def run_container(self): self.is_running = True self.infoLabel.setText('Running alignment...') self.setStatusMessage('Running...') self.progressBarInit() # Run the container in a new thread self.run_container_thread = QThread() self.run_container_worker = RunAlignmentWorker(self.docker, self.image_name, self.host_ref_dir, self.host_seq_dir, self.host_counts_dir) self.run_container_worker.progress[int].connect( self.run_container_progress) self.run_container_worker.finished.connect(self.run_container_finished) self.run_container_worker.moveToThread(self.run_container_thread) self.run_container_thread.started.connect( self.run_container_worker.work) self.run_container_thread.start() @pyqtSlot(int, name="runContainerProgress") def run_container_progress(self, val): self.progressBarSet(val) @pyqtSlot(name="runContainerFinished") def run_container_finished(self): self.run_container_thread.terminate() self.run_container_thread.wait() self.infoLabel.setText("Finished running alignment!") self.btn_run.setEnabled(True) self.is_running = False self.btn_run.setText('Run again') self.setStatusMessage('Finished!') self.progressBarFinished() self.send("Counts", self.docker.toContainerDir(self.host_counts_dir))