예제 #1
0
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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))