class ImportDialog(QtWidgets.QDialog): loadData = QtCore.pyqtSignal(str) def __init__(self, *args, **kw): super(ImportDialog, self).__init__(*args, **kw) loadUI(splitext(__file__)[0] + '.ui', self) for name, scn in FileScanner.iterclasses(): self.structType.addItem(scn.icon(), name) self.structType.setIconSize(QtCore.QSize(48, 24)) self.metadata = None self._files = None self.progressBar.hide() self.segdlg = SegmentationDialog(self) self.segdlg.hide() self.thread = AtThread(self) self.viewer.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.cbar = ChannelBar(self, self.viewer) self.cbox.addWidget(self.cbar) self.cbar.newPixmap.connect(self.viewer.showPixmap, Qt.DirectConnection) self.cbar.newContourImage.connect(self.viewer.contourImage) self.dataFileBtn.clicked.connect(self.onOpenOutFile) self.imageDirBtn.clicked.connect(self.onOpenImageDir) self.startBtn.clicked.connect(self.raw2hdf) self.closeBtn.clicked.connect(self.close) self.closeBtn.clicked.connect(self.cbar.clear) self.segmentationBtn.clicked.connect(self.onSegmentationBtn) self.slider.newValue.connect(self.showObjects) self.slider.valueChanged.connect(self.showImage) self.slider.sliderReleased.connect(self.showObjects) self.slider.sliderPressed.connect(self.cbar.clearContours) self.contoursCb.stateChanged.connect(self.onContours) self.showBBoxes.stateChanged.connect(self.onBBoxes) self.showBBoxes.stateChanged.connect(self.showObjects) self.segdlg.paramsChanged.connect(self.showObjects) self.segdlg.refreshBtn.clicked.connect(self.showObjects) self.segdlg.imageUpdate.connect(self.showImage) self.segdlg.activateChannels.connect(self.cbar.activateChannels) self.segdlg.changeColor.connect(self.cbar.setColor) self.nextBtn.clicked.connect(self.onNextBtn) self.prevBtn.clicked.connect(self.onPrevBtn) def keyPressEvent(self, event): if event.key() == Qt.Key_F5: self.showObjects() def closeEvent(self, event): super(ImportDialog, self).closeEvent(event) ofile = self.dataFile.text() if self.loadOnClose.isChecked() and isfile(ofile): self.loadData.emit(ofile) def onNextBtn(self): self.slider.setValue(self.slider.value() + 1) self.showObjects() def onPrevBtn(self): self.slider.setValue(self.slider.value() - 1) self.showObjects() def onContours(self, state): if state == Qt.Checked: self.showObjects() else: self.cbar.clearContours() self.viewer.clearPolygons() def onBBoxes(self, state): if state == Qt.Checked: self.showObjects() else: self.viewer.clearRects() def onSegmentationBtn(self): self.segdlg.show() self.segdlg.raise_() def onOpenOutFile(self): ofile = self.dataFile.text() idir = self.imageDir.text() if isfile(ofile): path = dirname(ofile) elif isdir(idir): path = dirname(idir) else: path = expanduser("~") ofile = QFileDialog.getSaveFileName(self, "save to hdf file", path, "hdf (*.hdf *.h5)")[0] self.dataFile.setText(ofile) def onOpenImageDir(self): self.cbar.clearContours() self.viewer.clearRects() self.viewer.clearPolygons() idir = self.imageDir.text() ofile = self.dataFile.text() if isdir(idir): path = dirname(idir) elif isfile(ofile): path = dirname(ofile) else: path = expanduser("~") # TODO use getOpenFileNames instead idir = QFileDialog.getExistingDirectory(self, "Select an image directory", path) # cancel button if not idir: return self.imageDir.setText(idir) scanner = FileScanner(self.structType.currentText(), idir) self._files = scanner() if not self._files: QMessageBox.warning(self, "Error", "No files found") return self.dirinfo.setText("%d images found" % len(self._files)) proc = LsmProcessor(self._files.keys()[0], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[0]) self.metadata = proc.metadata self.metadata.n_images = len(self._files) images = list(proc.iterQImages()) props = list(proc.iterprops()) self.cbar.addChannels(len(images)) self.cbar.setImages(images, list(proc.iterprops())) state = self.segdlg.blockSignals(True) self.segdlg.setRegions(self.cbar.allChannels(), props) self.segdlg.setMaxZSlice(self.metadata.n_zslices - 1) self.segdlg.blockSignals(state) self.slider.setRange(0, self.metadata.n_images - 1) self.slider.setValue(0) self.showObjects() def showImage(self, index=0): # no image directory yet if self._files is None: return try: proc = LsmProcessor(self._files.keys()[index], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[index]) except IndexError: return self.viewer.clearPolygons() self.viewer.clearRects() images = list(proc.iterQImages()) self.cbar.setImages(images, list(proc.iterprops())) def showObjects(self): if not (self.contoursCb.isChecked() or \ self.showBBoxes.isChecked()) or \ self._files is None: return index = self.slider.value() try: mp = LsmProcessor(self._files.keys()[index], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[index]) # first channel for primary segementation mp.segmentation() except Exception as e: QMessageBox.critical(self, "Error", "%s:%s" % (type(e), str(e))) finally: if not mp.objects: return if self.contoursCb.isChecked(): self.cbar.setContours(mp.objects.contours) if self.showBBoxes.isChecked(): self.cbar.drawRectangles(mp.objects.centers.values(), self.segdlg.galSize.value(), isize=self.metadata.size) def onError(self, exc): self.startBtn.setText("Start") QMessageBox.critical(self, "Error", str(exc)) def onFinished(self): self.raise_() self.startBtn.setText("Start") QMessageBox.information(self, "finished", "training set saved") def showSlider(self): self.progressBar.hide() self.sliderframe.show() def hideSlider(self): self.progressBar.show() self.sliderframe.hide() def raw2hdf(self): if self.thread.isRunning(): self.startBtn.setText("Start") self.thread.worker.abort() else: self.viewer.clearPolygons() self.viewer.clearRects() try: worker = AtImporter(self._files, self.metadata, self.dataFile.text(), self.cbar.checkedChannels(), self.cbar.colors(), self.segdlg.segmentationParams(), self.segdlg.featureGroups()) except Exception as e: QMessageBox.critical(self, str(e), traceback.format_exc()) return worker.connetToProgressBar(self.progressBar, Qt.QueuedConnection) worker.started.connect(self.hideSlider) worker.finished.connect(self.showSlider) worker.finished.connect(self.onFinished, Qt.QueuedConnection) worker.error.connect(self.onError, Qt.QueuedConnection) worker.contourImage.connect(self.cbar.contourImage, Qt.QueuedConnection) self.thread.start(worker) self.startBtn.setText("Abort")
class ImportDialog(QtWidgets.QDialog): loadData = QtCore.pyqtSignal(str) finished = QtCore.pyqtSignal() setProgress = QtCore.pyqtSignal(int) setProgressRange = QtCore.pyqtSignal(int, int) def __init__(self, *args, **kw): super(ImportDialog, self).__init__(*args, **kw) loadUI(splitext(__file__)[0] + ".ui", self) self.zsliceMethod.addItems(ZProject.names()) self.zsliceMethod.currentIndexChanged.connect(self.onZSliceMethodChanged) self.pool = None self._pool_running = False for name, scn in FileScanner.iterclasses(): self.structType.addItem(scn.icon(), name) self.structType.setIconSize(QtCore.QSize(48, 24)) self._files = None self._regex = None self.progressBar.hide() self.segdlg = SegmentationDialog(self) self.segdlg.hide() self.zslice.valueChanged.connect(self.segdlg.setZSlice) self.segdlg.zslice.valueChanged.connect(self.zslice.setValue) self.zsliceMethod.currentIndexChanged.connect(self.segdlg.zsliceMethod.setCurrentIndex) self.segdlg.zsliceMethod.currentIndexChanged.connect(self.zsliceMethod.setCurrentIndex) self.viewer.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.cbar = ChannelBar(self, self.viewer) self.cbox.addWidget(self.cbar) self.cbar.newPixmap.connect(self.viewer.showPixmap, Qt.DirectConnection) self.cbar.newContourImage.connect(self.viewer.contourImage) self.cbar.colorsChanged.connect(self.segdlg.updateRowColors) self.dataFileBtn.clicked.connect(self.onOpenOutFile) self.imageDirBtn.clicked.connect(self.onOpenImageDir) self.startBtn.clicked.connect(self.raw2hdf) self.closeBtn.clicked.connect(self.close) self.closeBtn.clicked.connect(self.cbar.clear) self.segmentationBtn.clicked.connect(self.onSegmentationBtn) self.slider.newValue.connect(self.showObjects) self.slider.valueChanged.connect(self.showImage) self.slider.sliderReleased.connect(self.showObjects) self.slider.sliderPressed.connect(self.cbar.clearContours) self.contoursCb.stateChanged.connect(self.onContours) self.showBBoxes.stateChanged.connect(self.onBBoxes) self.showBBoxes.stateChanged.connect(self.showObjects) self.segdlg.paramsChanged.connect(self.showObjects) self.segdlg.refreshBtn.clicked.connect(self.showObjects) self.segdlg.imageUpdate.connect(self.showImage) self.segdlg.activateChannels.connect(self.cbar.activateChannels) self.segdlg.changeColor.connect(self.cbar.setColor) self.nextBtn.clicked.connect(self.onNextBtn) self.prevBtn.clicked.connect(self.onPrevBtn) self.reloadBtn.clicked.connect(self.onReloadBtn) self.setProgressRange.connect(self.progressBar.setRange) self.setProgress.connect(self.progressBar.setValue, Qt.DirectConnection) def onZSliceMethodChanged(self, index): if index == ZProject.Select: self.zslice.show() else: self.zslice.hide() def setMaxZSlice(self, value, block=True): if value == 0: self.zstack.hide() else: self.zstack.show() state = self.zslice.blockSignals(block) self.zslice.setMaximum(value) self.zslice.setValue(max(0, floor(value / 2.0) - 1)) self.segdlg.setMaxZSlice(value, block) self.zslice.blockSignals(state) def keyPressEvent(self, event): if event.key() == Qt.Key_F5: self.showObjects() def closeEvent(self, event): super(ImportDialog, self).closeEvent(event) ofile = self.dataFile.text() if isfile(ofile): self.loadData.emit(ofile) def onNextBtn(self): self.slider.setValue(self.slider.value() + 1) self.showObjects() def onPrevBtn(self): self.slider.setValue(self.slider.value() - 1) self.showObjects() def onContours(self, state): if state == Qt.Checked: self.showObjects() else: self.viewer.clearPolygons() def onBBoxes(self, state): if state == Qt.Checked: self.showObjects() else: self.viewer.clearRects() def onSegmentationBtn(self): self.segdlg.show() self.segdlg.raise_() def onOpenOutFile(self): ofile = self.dataFile.text() idir = self.imageDir.text() if isfile(ofile): path = dirname(ofile) elif isdir(idir): path = dirname(idir) else: path = expanduser("~") ofile = QFileDialog.getSaveFileName(self, "Save data as", path, "hdf (*.hdf *.h5)")[0] self.dataFile.setText(ofile) def imageDimensionsDlg(self, file_): """Pop up dialog to define stack order and image dimensins.""" dlg = ImageDims(self._files) dlg.exec_() if dlg.result() > 0: dims = dlg.dimensionInfo() self.setMaxZSlice(dims[1]) if dlg.useRegex.isChecked(): self._files = dlg.files return dims else: return None def onOpenImageDir(self): self.cbar.clearContours() self.viewer.clearRects() self.viewer.clearPolygons() idir = self.imageDir.text() ofile = self.dataFile.text() if isdir(idir): path = dirname(idir) elif isfile(ofile): path = dirname(ofile) else: path = expanduser("~") # TODO use getOpenFileNames instead idir = QFileDialog.getExistingDirectory(self, "Select an image directory", path) # cancel button if not idir: return self.imageDir.setText(idir) scanner = FileScanner(self.structType.currentText(), idir) self._files = scanner() if not self._files: QMessageBox.warning(self, "Error", "No files found") return try: self._dimUpdate(self._files[0].file) self._initialImage() except IOError as e: pass def onReloadBtn(self): if self._files is not None: i = self.slider.value() try: self._dimUpdate(self._files[i].file) self._initialImage(i) except (IOError, AttributeError) as e: pass def _dimUpdate(self, file_): # ask user for image dims and stack order, tiff file only mtype = mimetypes.guess_type(file_)[0] if mtype != "image/lsm": regex = self.imageDimensionsDlg(file_) if regex is not None: # in case of cancel button self._regex = regex self.setMaxZSlice(self._regex.nzslices) self.dirinfo.setText("%d images found" % len(self._files)) def _initialImage(self, index=0): """Process the first image.""" # don't know nz yet when segmentationParams is called self.segdlg.setZSlice(0, block=True) proc = TiffProcessor( self._files[index], self._regex, self.segdlg.segmentationParams(), self.cbar.checkedChannels() ) images = proc.iterQImages() props = list(proc.iterprops()) self.cbar.addChannels(len(images)) self.cbar.setImages(images, list(proc.iterprops())) state = self.segdlg.blockSignals(True) self.segdlg.setRegions(self.cbar.allChannels(), props) self.setMaxZSlice(proc.zSlices - 1) self.segdlg.blockSignals(state) self.slider.setRange(0, len(self._files) - 1) self.slider.setValue(index) self.showObjects() def showImage(self, index=0): # no image directory yet if self._files is None: return try: proc = TiffProcessor( self._files[index], self._regex, self.segdlg.segmentationParams(), self.cbar.checkedChannels() ) except IndexError: return self.viewer.clearPolygons() self.viewer.clearRects() images = proc.iterQImages() self.cbar.setImages(images, list(proc.iterprops())) def showObjects(self): if not (self.contoursCb.isChecked() or self.showBBoxes.isChecked()) or self._files is None: return index = self.slider.value() try: mp = TiffProcessor( self._files[index], self._regex, self.segdlg.segmentationParams(), self.cbar.checkedChannels() ) # first channel for primary segementation mp.segmentation() except Exception as e: QMessageBox.critical(self, "Error", "%s:%s" % (type(e), str(e))) finally: objects = mp.objects() if not objects: self.viewer.clearPolygons() self.viewer.clearRects() return if self.contoursCb.isChecked(): self.cbar.setContours(objects.contours) if self.showBBoxes.isChecked(): self.cbar.drawRectangles(objects.centers.values(), self.segdlg.galSize.value(), isize=mp.size) def onError(self, exc): self.pool.terminate() self.showSlider() self.startBtn.setText("Start") self._pool_running = False QMessageBox.critical(self, "Error", str(exc)) def onFinished(self): self.saveData() self.raise_() self.showSlider() self._pool_running = False QMessageBox.information(self, "Informaton", "Image preprocessing successful") def showSlider(self): QApplication.restoreOverrideCursor() self._pool_running = False self.startBtn.setText("Start") self.progressBar.hide() self.sliderframe.show() # self.setEnabled(True) def hideSlider(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.startBtn.setText("Abort") self._pool_running = True self.progressBar.show() self.sliderframe.hide() # self.setEnabled(False) # self.startBtn.setEnabled(True) def raw2hdf(self): if not self.dataFile.text(): self.onOpenOutFile() if not self.dataFile.text(): return if self._pool_running: self.showSlider() self.pool.terminate() return nfiles = len(self._files) self.pool = Pool(processes=cpu_count() - 1) self._pool_running = True self.hideSlider() self.progressBar.setRange(0, 2 * nfiles - 1) self.progressBar.setValue(0) channels = self.cbar.checkedChannels() self.results = list() callback = QCallBack(nfiles) callback.tick.connect(self.incrementProgress) callback.finished.connect(self.onFinished) callback.error.connect(self.onError) for file_ in self._files: self.results.append( self.pool.apply_async( processBild, [file_, self._regex, self.segdlg.segmentationParams(), self.segdlg.featureGroups(), channels], callback=callback, ) ) def incrementProgress(self, value=None): if value is None: value = self.progressBar.value() + 1 self.setProgress.emit(value) def saveData(self): # be carefull save Data is runs in a different thread # (callback of map_async) self.pool.close() self.pool.join() self.parent().onFileClose() writer = HdfWriter(self.dataFile.text()) try: channels = self.cbar.checkedChannels() proc = TiffProcessor( self._files[0], self._regex, self.segdlg.segmentationParams(), self.cbar.checkedChannels() ) colors = [self.cbar.colors[ch] for ch in channels.values()] writer.setupFile(len(self._files), channels, colors) writer.saveSettings( self.segdlg.segmentationParams(), self.segdlg.featureGroups(), channels.values(), self.cbar.colors ) for i, res_ in enumerate(self.results): res = res_.get() file_, image, image_objects, feature_names = res # reconstruct the ObjectDict objects = ObjectDict("multicolor") objects.feature_names = feature_names for obj in image_objects: objects[obj.label] = obj writer.saveData(objects, image, None, file_.file) self.incrementProgress() writer.flush() finally: writer.close() self.finished.emit()
class ImportDialog(QtWidgets.QDialog): loadData = QtCore.pyqtSignal(str) def __init__(self, *args, **kw): super(ImportDialog, self).__init__(*args, **kw) loadUI(splitext(__file__)[0]+'.ui', self) for name, scn in FileScanner.iterclasses(): self.structType.addItem(scn.icon(), name) self.structType.setIconSize(QtCore.QSize(48, 24)) self.metadata = None self._files = None self.progressBar.hide() self.segdlg = SegmentationDialog(self) self.segdlg.hide() self.thread = AtThread(self) self.viewer.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.cbar = ChannelBar(self, self.viewer) self.cbox.addWidget(self.cbar) self.cbar.newPixmap.connect(self.viewer.showPixmap, Qt.DirectConnection) self.cbar.newContourImage.connect(self.viewer.contourImage) self.dataFileBtn.clicked.connect(self.onOpenOutFile) self.imageDirBtn.clicked.connect(self.onOpenImageDir) self.startBtn.clicked.connect(self.raw2hdf) self.closeBtn.clicked.connect(self.close) self.closeBtn.clicked.connect(self.cbar.clear) self.segmentationBtn.clicked.connect(self.onSegmentationBtn) self.slider.newValue.connect(self.showObjects) self.slider.valueChanged.connect(self.showImage) self.slider.sliderReleased.connect(self.showObjects) self.slider.sliderPressed.connect(self.cbar.clearContours) self.contoursCb.stateChanged.connect(self.onContours) self.showBBoxes.stateChanged.connect(self.onBBoxes) self.showBBoxes.stateChanged.connect(self.showObjects) self.segdlg.paramsChanged.connect(self.showObjects) self.segdlg.refreshBtn.clicked.connect(self.showObjects) self.segdlg.imageUpdate.connect(self.showImage) self.segdlg.activateChannels.connect(self.cbar.activateChannels) self.segdlg.changeColor.connect(self.cbar.setColor) self.nextBtn.clicked.connect(self.onNextBtn) self.prevBtn.clicked.connect(self.onPrevBtn) def keyPressEvent(self, event): if event.key() == Qt.Key_F5: self.showObjects() def closeEvent(self, event): super(ImportDialog, self).closeEvent(event) ofile = self.dataFile.text() if self.loadOnClose.isChecked() and isfile(ofile): self.loadData.emit(ofile) def onNextBtn(self): self.slider.setValue(self.slider.value()+1) self.showObjects() def onPrevBtn(self): self.slider.setValue(self.slider.value()-1) self.showObjects() def onContours(self, state): if state == Qt.Checked: self.showObjects() else: self.cbar.clearContours() self.viewer.clearPolygons() def onBBoxes(self, state): if state == Qt.Checked: self.showObjects() else: self.viewer.clearRects() def onSegmentationBtn(self): self.segdlg.show() self.segdlg.raise_() def onOpenOutFile(self): ofile = self.dataFile.text() idir = self.imageDir.text() if isfile(ofile): path = dirname(ofile) elif isdir(idir): path = dirname(idir) else: path = expanduser("~") ofile = QFileDialog.getSaveFileName(self, "save to hdf file", path, "hdf (*.hdf *.h5)")[0] self.dataFile.setText(ofile) def onOpenImageDir(self): self.cbar.clearContours() self.viewer.clearRects() self.viewer.clearPolygons() idir = self.imageDir.text() ofile = self.dataFile.text() if isdir(idir): path = dirname(idir) elif isfile(ofile): path = dirname(ofile) else: path = expanduser("~") # TODO use getOpenFileNames instead idir = QFileDialog.getExistingDirectory(self, "Select an image directory", path) # cancel button if not idir: return self.imageDir.setText(idir) scanner = FileScanner(self.structType.currentText(), idir) self._files = scanner() if not self._files: QMessageBox.warning(self, "Error", "No files found") return self.dirinfo.setText("%d images found" %len(self._files)) proc = LsmProcessor(self._files.keys()[0], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[0]) self.metadata = proc.metadata self.metadata.n_images = len(self._files) images = list(proc.iterQImages()) props = list(proc.iterprops()) self.cbar.addChannels(len(images)) self.cbar.setImages(images, list(proc.iterprops())) state = self.segdlg.blockSignals(True) self.segdlg.setRegions(self.cbar.allChannels(), props) self.segdlg.setMaxZSlice(self.metadata.n_zslices-1) self.segdlg.blockSignals(state) self.slider.setRange(0, self.metadata.n_images-1) self.slider.setValue(0) self.showObjects() def showImage(self, index=0): # no image directory yet if self._files is None: return try: proc = LsmProcessor(self._files.keys()[index], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[index]) except IndexError: return self.viewer.clearPolygons() self.viewer.clearRects() images = list(proc.iterQImages()) self.cbar.setImages(images, list(proc.iterprops())) def showObjects(self): if not (self.contoursCb.isChecked() or \ self.showBBoxes.isChecked()) or \ self._files is None: return index = self.slider.value() try: mp = LsmProcessor(self._files.keys()[index], self.segdlg.segmentationParams(), self.cbar.checkedChannels(), treatment=self._files.values()[index]) # first channel for primary segementation mp.segmentation() except Exception as e: QMessageBox.critical(self, "Error", "%s:%s" %(type(e), str(e))) finally: if not mp.objects: return if self.contoursCb.isChecked(): self.cbar.setContours(mp.objects.contours) if self.showBBoxes.isChecked(): self.cbar.drawRectangles(mp.objects.centers.values(), self.segdlg.galSize.value(), isize=self.metadata.size) def onError(self, exc): self.startBtn.setText("Start") QMessageBox.critical(self, "Error", str(exc)) def onFinished(self): self.raise_() self.startBtn.setText("Start") QMessageBox.information(self, "finished", "training set saved") def showSlider(self): self.progressBar.hide() self.sliderframe.show() def hideSlider(self): self.progressBar.show() self.sliderframe.hide() def raw2hdf(self): if self.thread.isRunning(): self.startBtn.setText("Start") self.thread.worker.abort() else: self.viewer.clearPolygons() self.viewer.clearRects() try: worker = AtImporter(self._files, self.metadata, self.dataFile.text(), self.cbar.checkedChannels(), self.cbar.colors(), self.segdlg.segmentationParams(), self.segdlg.featureGroups()) except Exception as e: QMessageBox.critical(self, str(e), traceback.format_exc()) return worker.connetToProgressBar(self.progressBar, Qt.QueuedConnection) worker.started.connect(self.hideSlider) worker.finished.connect(self.showSlider) worker.finished.connect(self.onFinished, Qt.QueuedConnection) worker.error.connect(self.onError, Qt.QueuedConnection) worker.contourImage.connect(self.cbar.contourImage, Qt.QueuedConnection) self.thread.start(worker) self.startBtn.setText("Abort")