def handle_scan(self, param): ox_len = int(abs(Settings.settings['lrServoMax'] - Settings.settings['lrServoMin']) / Settings.settings['lrStep'])+1 oy_len = int(abs(Settings.settings['udServoMax'] - Settings.settings['udServoMin']) / Settings.settings['udStep'])+1 arduinoCtrl.set_lr_servo(Settings.settings['lrServoMin']) arduinoCtrl.set_ud_servo(Settings.settings['udServoMin']) total_points = ox_len * oy_len progress = QProgressDialog('Scanning thermal image', 'Stop', 0, total_points) self.mMatrix = np.zeros((oy_len, ox_len))+23 self.mQPixmap = QPixmap(ox_len, oy_len) self.mQPixmap.fill() rectangleScanJob = RectangleScanJob() rectangleScanJob.new_value.connect(self.handle_temperature) rectangleScanJob.progress.connect(progress.setValue) rectangleScanJob.start() #rectangleScanJob.run() progress.exec_() if progress.wasCanceled(): rectangleScanJob.terminate() return self.update_picture_from_matrix()
def create_progressdialog(self): dialog = QProgressDialog(self) thread = MyThread(self, 100) dialog.setMinimum(0) thread.total.connect(dialog.setMaximum) def update(i): print('update() thread id: ', threading.get_ident()) dialog.setValue(i) thread.update.connect(update) thread.end.connect(update) thread.start() dialog.exec_()
class GuiView(QObject): """ Graphical User Interface """ def __init__(self): super().__init__() self.mainwindow = MainWindow() self.mainwindow.show() self.presenter = None self.connect_to_actions() def connect_to_actions(self): self.mainwindow.connect_to_yadisk_signal.connect( self.connect_to_yadisk) self.mainwindow.get_local_listdir.connect(self.get_local_listdir) self.mainwindow.get_yadisk_listdir.connect(self.get_yadisk_listdir) self.mainwindow.get_bublic_listdir.connect(self.get_bublic_listdir) # download/upload files self.mainwindow.download_from_auth_yadisk.connect( self.download_from_auth_yadisk) self.mainwindow.download_from_bublic_yadisk.connect( self.download_from_bublic_yadisk) self.mainwindow.upload_to_auth_yadisk.connect( self.upload_to_auth_yadisk) # add new tab self.mainwindow.open_link_signal.connect(self.open_link) # browse clicked self.mainwindow.local_browse_clicked.connect(self.local_browse_request) self.mainwindow.yadisk_browse_clicked.connect( self.yadisk_browse_request) # self.mainwindow.yadisk_browse_clicked.connect(self.browse) self.mainwindow.local_algorithm_changed.connect( self.on_local_algorithm_changed) self.mainwindow.yadisk_algorithm_changed.connect( self.on_yadisk_algorithm_changed) self.mainwindow.set_media_folder.connect(self.on_set_media_folder) def set_presenter(self, presenter): self.presenter = presenter def connect_to_yadisk(self): self.presenter.connect_to_yadisk() def set_verification_url(self, url): self.dialog = ConnectionDialog(url) self.dialog.accepted.connect(self.send_verification_code) self.dialog.show() def send_verification_code(self): code = self.dialog.get_verification_code() self.presenter.verificate_auth(code) def show_error(self, message): self.msg_box = QMessageBox(QMessageBox.Warning, "Warning", message) self.msg_box.show() def show_progress_dialog(self, message, value=0, minmax=None): if minmax == None: minmax = (0, 0) self.progress = QProgressDialog() self.progress.setWindowTitle("Please, wait") self.progress.setLabelText(message) self.progress.setRange(*minmax) self.progress.setValue(value) self.progress.setCancelButton(None) self.progress.setWindowModality(Qt.WindowModal) self.progress.exec_() def close_progress_dialog(self): self.progress.close() def set_is_verified(self, is_verified): if is_verified: self.dialog.close() self.mainwindow.show_status("Connected to Yandex Disk") self.mainwindow.add_authorized_yadisk_tab() else: self.dialog.show_warning() def get_yadisk_listdir(self, path): self.presenter.get_yadisk_listdir(path) def get_local_listdir(self, path): self.presenter.get_local_listdir(path) def show_local_listdir(self, listdir, path): self.mainwindow.show_local_listdir(listdir, path) def show_yadisk_listdir(self, listdir, path): self.mainwindow.show_yadisk_listdir(listdir, path) def download_from_auth_yadisk(self, from_file, to_file, encryption_data): self.presenter.download_from_auth_yadisk( from_file, to_file, encryption_data) self.update_local() def download_from_bublic_yadisk(self, from_file, to_file, encryption_data): self.presenter.download_from_bublic_yadisk( from_file, to_file, encryption_data) self.update_local() def upload_to_auth_yadisk(self, from_file, to_file, encryption_data): self.presenter.upload_to_auth_yadisk( from_file, to_file, encryption_data) self.update_auth_yadisk() self.update_local() def update_local(self): local_folder = self.mainwindow.get_local_folder_name() self.get_local_listdir(local_folder) def update_auth_yadisk(self): yadisk_folder = self.mainwindow.get_yadisk_folder_name() self.get_yadisk_listdir(yadisk_folder) def open_link(self): self.dialog = OpenLinkDialog() self.dialog.accepted.connect(self.send_bublic_url) self.dialog.show() def send_bublic_url(self): url = self.dialog.get_bublic_url() self.presenter.open_bublic_url(url) def set_is_bublic_url_correct(self, is_correct): if is_correct: self.dialog.close() name = self.dialog.get_tab_name() self.mainwindow.add_bublic_yadisk_tab(name) else: self.dialog.show_warning() def get_bublic_listdir(self, url): self.presenter.get_bublic_listdir(url) def local_browse_request(self, key_type, algorithm): self.presenter.local_browse(key_type, algorithm) def yadisk_browse_request(self, key_type, algorithm): self.presenter.yadisk_browse(key_type, algorithm) def local_browse(self, result): self.mainwindow.local_browse(result) def yadisk_browse(self, result): self.mainwindow.yadisk_browse(result) def on_local_algorithm_changed(self, algorithm, key_type): self.presenter.get_local_key(algorithm, key_type) def on_yadisk_algorithm_changed(self, algorithm, key_type): self.presenter.get_yadisk_key(algorithm, key_type) def put_local_key(self, key): self.mainwindow.put_local_key(key) def put_yadisk_key(self, key): self.mainwindow.put_yadisk_key(key) def on_set_media_folder(self, path): self.presenter.set_media_folder(path)
class Window(QWidget): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.resize(600, 400) layout = QHBoxLayout(self) # 左侧 widgetLeft = QWidget(self) layoutLeft = QVBoxLayout(widgetLeft) # 右侧 self.widgetRight = QListWidget(self, minimumWidth=200, iconSize=QSize(150, 150)) self.widgetRight.setViewMode(QListWidget.IconMode) layout.addWidget(widgetLeft) layout.addWidget(self.widgetRight) self.webView = QWebEngineView() layoutLeft.addWidget(self.webView) # 截图方式一 groupBox1 = QGroupBox('截图方式一', self) layout1 = QVBoxLayout(groupBox1) layout1.addWidget(QPushButton('截图1', self, clicked=self.onScreenShot1)) layoutLeft.addWidget(groupBox1) # 截图方式二(采用js) groupBox2 = QGroupBox('截图方式二', self) layout2 = QVBoxLayout(groupBox2) self.codeEdit = QLineEdit( 'body', groupBox2, placeholderText='请输入需要截图的元素、ID或者class:如body、#id .class') layout2.addWidget(self.codeEdit) self.btnMethod2 = QPushButton('', self, clicked=self.onScreenShot2, enabled=False) layout2.addWidget(self.btnMethod2) layoutLeft.addWidget(groupBox2) # 提供访问接口 self.channel = QWebChannel(self) # 把自身对象传递进去 self.channel.registerObject('_self', self) # 设置交互接口 self.webView.page().setWebChannel(self.channel) # 支持截图 settings = QWebEngineSettings.globalSettings() settings.setAttribute(QWebEngineSettings.ScreenCaptureEnabled, True) self.webView.loadStarted.connect(self.onLoadStarted) self.webView.loadFinished.connect(self.onLoadFinished) self.webView.load(QUrl("https://pyqt.site")) def onLoadStarted(self): print('load started') self.btnMethod2.setEnabled(False) self.btnMethod2.setText('暂时无法使用(等待页面加载完成)') @pyqtSlot(bool) def onLoadFinished(self, finished): if not finished: return print('load finished') # 注入脚本 page = self.webView.page() # 执行qwebchannel,jquery,promise,html2canvas page.runJavaScript(open('Data/qwebchannel.js', 'rb').read().decode()) page.runJavaScript(open('Data/jquery.js', 'rb').read().decode()) # page.runJavaScript( # open('Data/promise-7.0.4.min.js', 'rb').read().decode()) page.runJavaScript( open('Data/html2canvas.min.js', 'rb').read().decode()) page.runJavaScript(CreateBridge) print('inject js ok') self.btnMethod2.setText('截图2') self.btnMethod2.setEnabled(True) def onScreenShot1(self): # 截图方式1 page = self.webView.page() oldSize = self.webView.size() self.webView.resize(page.contentsSize().toSize()) def doScreenShot(): rect = self.webView.contentsRect() size = rect.size() image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter() painter.begin(image) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) self.webView.render(painter) painter.end() self.webView.resize(oldSize) # 添加到左侧list中 item = QListWidgetItem(self.widgetRight) image = QPixmap.fromImage(image) item.setIcon(QIcon(image)) item.setData(Qt.UserRole + 1, image) # 先等一下再截图吧 QTimer.singleShot(2000, doScreenShot) def onScreenShot2(self): # 截图方式2 code = self.codeEdit.text().strip() if not code: return self.progressdialog = QProgressDialog(self, windowTitle='正在截图中') self.progressdialog.setRange(0, 0) self.webView.page().runJavaScript(CODE % code) self.progressdialog.exec_() @pyqtSlot(str) def saveImage(self, image): self.progressdialog.close() # data:image/png;base64,iVBORw0KG.... if not image.startswith('data:image'): return data = base64.b64decode(image.split(';base64,')[1]) image = QPixmap() image.loadFromData(data) # 添加到左侧list中 item = QListWidgetItem(self.widgetRight) item.setIcon(QIcon(image)) item.setData(Qt.UserRole + 1, image)
class Window(QWidget): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.resize(600, 400) layout = QHBoxLayout(self) # 左侧 widgetLeft = QWidget(self) layoutLeft = QVBoxLayout(widgetLeft) # 右侧 self.widgetRight = QListWidget(self, minimumWidth=200, iconSize=QSize(150, 150)) self.widgetRight.setViewMode(QListWidget.IconMode) layout.addWidget(widgetLeft) layout.addWidget(self.widgetRight) self.webView = QWebView() layoutLeft.addWidget(self.webView) # 截图方式一 groupBox1 = QGroupBox('截图方式一', self) layout1 = QVBoxLayout(groupBox1) layout1.addWidget(QPushButton('截图1', self, clicked=self.onScreenShot1)) layoutLeft.addWidget(groupBox1) # 截图方式二(采用js) groupBox2 = QGroupBox('截图方式二', self) layout2 = QVBoxLayout(groupBox2) self.codeEdit = QLineEdit( 'body', groupBox2, placeholderText='请输入需要截图的元素、ID或者class:如body、#id .class') layout2.addWidget(self.codeEdit) self.btnMethod2 = QPushButton('', self, clicked=self.onScreenShot2, enabled=False) layout2.addWidget(self.btnMethod2) layoutLeft.addWidget(groupBox2) # 开启开发人员工具 QWebSettings.globalSettings().setAttribute( QWebSettings.DeveloperExtrasEnabled, True) self.webView.loadStarted.connect(self.onLoadStarted) self.webView.loadFinished.connect(self.onLoadFinished) self.webView.load(QUrl("https://pyqt5.com")) # 暴露接口和加载完成后执行jquery等一些库文件 self.webView.page().mainFrame().javaScriptWindowObjectCleared.connect( self.populateJavaScriptWindowObject) def populateJavaScriptWindowObject(self): self.webView.page().mainFrame().addToJavaScriptWindowObject( '_self', self) def onLoadStarted(self): print('load started') self.btnMethod2.setEnabled(False) self.btnMethod2.setText('暂时无法使用(等待页面加载完成)') def onLoadFinished(self): # 注入脚本 mainFrame = self.webView.page().mainFrame() # 执行jquery,promise,html2canvas mainFrame.evaluateJavaScript( open('Data/jquery.js', 'rb').read().decode()) mainFrame.evaluateJavaScript( open('Data/promise-7.0.4.min.js', 'rb').read().decode()) mainFrame.evaluateJavaScript( open('Data/html2canvas.min.js', 'rb').read().decode()) print('inject js ok') self.btnMethod2.setText('截图2') self.btnMethod2.setEnabled(True) def onScreenShot1(self): # 截图方式1 page = self.webView.page() frame = page.mainFrame() size = frame.contentsSize() image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter() painter.begin(image) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) # 记录旧大小 oldSize = page.viewportSize() # *****重点就是这里****** page.setViewportSize(size) frame.render(painter) painter.end() # 截图完成后需要还原,否则界面不响应鼠标等 page.setViewportSize(oldSize) # 添加到左侧list中 item = QListWidgetItem(self.widgetRight) image = QPixmap.fromImage(image) item.setIcon(QIcon(image)) item.setData(Qt.UserRole + 1, image) def onScreenShot2(self): # 截图方式2 code = self.codeEdit.text().strip() if not code: return self.progressdialog = QProgressDialog(self, windowTitle='正在截图中') self.progressdialog.setRange(0, 0) self.webView.page().mainFrame().evaluateJavaScript(CODE % code) self.progressdialog.exec_() @pyqtSlot(str) def saveImage(self, image): self.progressdialog.close() # data:image/png;base64,iVBORw0KG.... if not image.startswith('data:image'): return data = base64.b64decode(image.split(';base64,')[1]) image = QPixmap() image.loadFromData(data) # 添加到左侧list中 item = QListWidgetItem(self.widgetRight) item.setIcon(QIcon(image)) item.setData(Qt.UserRole + 1, image)
class MyWindow(Ui_MainWindow): VersionDict = { "Android 7": 7.0, "Android 8": 8.0 } def __init__(self): super(MyWindow, self).__init__() self.MainWindow = QMainWindow() self.setupUi(self.MainWindow) # self.Button_start.clicked.connect(self.Button_stop.click) self.Button_start.clicked.connect(self.runtest) self.Button_start.clicked.connect(self.Step_Log.clear) #self.Step_Log.textChanged.connect(self.StepScroll) self.Button_stop.clicked.connect(self.end) self.config_file = 'Testcase/config.ini' self.cp = configparser.ConfigParser() self.cp.read(self.config_file) self.logthread = LogcatThread() self.logthread.sinOut.connect(self.Logcat.append) self.logthread.sinOutClear.connect(self.Logcat.clear) self.ThreadStress = TestTableThread() self.checkDevice = CheckDevice() self.checkDevice.FindDevice.connect(self.logthread.start) self.checkDevice.FindDevice.connect(self.ThreadStress.start) self.font = QtGui.QFont() self.font.setFamily("Microsoft YaHei") self.get_value() def end(self): self.logthread.terminate() self.ThreadStress.terminate() def get_value(self): self.treeWidget.setSortingEnabled(False) for session in self.cp.sections(): topitem = QtWidgets.QTreeWidgetItem(self.treeWidget) if str(session) != "Initialize settings": topitem.setCheckState(0, QtCore.Qt.Unchecked) # topitem.setCheckState(0, QtCore.Qt.Checked) topitem.setText(0, str(session)) for item in self.cp.options(session): seconditem = QtWidgets.QTreeWidgetItem(topitem) # seconditem.setCheckState(0, QtCore.Qt.Checked) seconditem.setText(0, str(item)) seconditem.setFlags(QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable) seconditem.setText(1, str(self.cp.get(session, item))) def set_value(self): for treeitem in range(0, self.treeWidget.topLevelItemCount()): for childitem in range(0, self.treeWidget.topLevelItem(treeitem).childCount()): self.cp.set(self.treeWidget.topLevelItem(treeitem).text(0), self.treeWidget.topLevelItem(treeitem).child(childitem).text(0), self.treeWidget.topLevelItem(treeitem).child(childitem).text(1)) self.cp.write(open(self.config_file, 'w')) def runtest(self): try: self.set_value() logger.info(str(ctime())) newDir = "testresult/log-" + datetime.now().strftime("%Y-%m-%d-%H-%M-%S") os.mkdir(newDir) QThread.sleep(1) self.ThreadStress.reportfile = newDir + '/Report.html' self.logthread.reportdir = newDir # Testcase.LOG_Switch = True self.ThreadStress.treeWidget = self.treeWidget self.checkProcess = QProgressDialog() self.checkProcess.setFont(self.font) self.checkProcess.setCancelButtonText("Close") self.checkProcess.setWindowTitle("Device checking...") self.checkDevice.Process.connect(self.checkProcess.setValue) self.checkDevice.FindDevice.connect(self.checkProcess.close) self.checkProcess.resize(400, 150) self.checkDevice.start() self.checkProcess.exec_() # self.TestTable.sinOutLog.connect(self.exportlog) # self.TestTable.sinOutProcess.connect(self.set_BarProcess) except Exception as err: # logger.error(str(err)) traceback.print_exc() def set_BarProcess(self, process): self.progressBar.setProperty("value", process) def StepScroll(self): self.Step_Log.scroll(self.Step_Log.maximumWidth(),self.Step_Log.maximumHeight())
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None): """ Prompt the user for layer import settings, and perform the layer import. :param labelLayer: The top label layer source :param labelingSlots: An instance of LabelingGui.LabelingSlots :param parent_widget: The Qt GUI parent object """ writeSeeds = labelingSlots.labelInput assert isinstance(writeSeeds, lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds)) opLabels = writeSeeds.getRealOperator() assert isinstance(opLabels, lazyflow.graph.Operator), "slot's operator is of type %r" % (type(opLabels)) recentlyImported = PreferencesManager().get('labeling', 'recently imported') mostRecentProjectPath = PreferencesManager().get('shell', 'recently opened') mostRecentImageFile = PreferencesManager().get( 'DataSelection', 'recent image' ) if recentlyImported: defaultDirectory = os.path.split(recentlyImported)[0] elif mostRecentProjectPath: defaultDirectory = os.path.split(mostRecentProjectPath)[0] elif mostRecentImageFile: defaultDirectory = os.path.split(mostRecentImageFile)[0] else: defaultDirectory = os.path.expanduser('~') fileNames = DataSelectionGui.getImageFileNamesToOpen(parent_widget, defaultDirectory) fileNames = list(map(str, fileNames)) if not fileNames: return PreferencesManager().set('labeling', 'recently imported', fileNames[0]) try: # Initialize operators opImport = OpInputDataReader( parent=opLabels.parent ) opCache = OpBlockedArrayCache( parent=opLabels.parent ) opMetadataInjector = OpMetadataInjector( parent=opLabels.parent ) opReorderAxes = OpReorderAxes( parent=opLabels.parent ) # Set up the pipeline as follows: # # opImport --> (opCache) --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput # / / # User-specified axisorder labelInput.meta.axistags opImport.WorkingDirectory.setValue(defaultDirectory) opImport.FilePath.setValue(fileNames[0] if len(fileNames) == 1 else os.path.pathsep.join(fileNames)) assert opImport.Output.ready() maxLabels = len(labelingSlots.labelNames.value) # We don't bother with counting the label pixels # (and caching the data) if it's big (1 GB) if numpy.prod(opImport.Output.meta.shape) > 1e9: reading_slot = opImport.Output # For huge data, we don't go through and search for the pixel values, # because that takes an annoyingly long amount of time. # Instead, we make the reasonable assumption that the input labels are already 1,2,3..N # and we don't tell the user what the label pixel counts are. unique_read_labels = numpy.array(list(range(maxLabels+1))) readLabelCounts = numpy.array([-1]*(maxLabels+1)) labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) else: opCache.Input.connect( opImport.Output ) opCache.CompressionEnabled.setValue(True) assert opCache.Output.ready() reading_slot = opCache.Output # We'll show a little window with a busy indicator while the data is loading busy_dlg = QProgressDialog(parent=parent_widget) busy_dlg.setLabelText("Scanning Label Data...") busy_dlg.setCancelButton(None) busy_dlg.setMinimum(100) busy_dlg.setMaximum(100) def close_busy_dlg(*args): QApplication.postEvent(busy_dlg, QCloseEvent()) # Load the data from file into our cache # When it's done loading, close the progress dialog. req = reading_slot[:] req.notify_finished( close_busy_dlg ) req.notify_failed( close_busy_dlg ) req.submit() busy_dlg.exec_() readData = req.result # Can't use return_counts feature because that requires numpy >= 1.9 #unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True) # This does the same as the above, albeit slower, and probably with more ram. bincounts = chunked_bincount(readData) unique_read_labels = bincounts.nonzero()[0].astype(readData.dtype, copy=False) readLabelCounts = bincounts[unique_read_labels] labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) del readData opMetadataInjector.Input.connect( reading_slot ) metadata = reading_slot.meta.copy() opMetadataInjector.Metadata.setValue( metadata ) opReorderAxes.Input.connect( opMetadataInjector.Output ) # Transpose the axes for assignment to the labeling operator. opReorderAxes.AxisOrder.setValue( writeSeeds.meta.getAxisKeys() ) # Ask the user how to interpret the data. settingsDlg = LabelImportOptionsDlg( parent_widget, fileNames, opMetadataInjector.Output, labelingSlots.labelInput, labelInfo ) def handle_updated_axes(): # The user is specifying a new interpretation of the file's axes updated_axisorder = str(settingsDlg.axesEdit.text()) metadata = opMetadataInjector.Metadata.value.copy() metadata.axistags = vigra.defaultAxistags(updated_axisorder) opMetadataInjector.Metadata.setValue( metadata ) if opReorderAxes._invalid_axes: settingsDlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) # Red background settingsDlg.axesEdit.setStyleSheet("QLineEdit { background: rgb(255, 128, 128);" "selection-background-color: rgb(128, 128, 255); }") settingsDlg.axesEdit.editingFinished.connect( handle_updated_axes ) # Initialize handle_updated_axes() dlg_result = settingsDlg.exec_() if dlg_result != LabelImportOptionsDlg.Accepted: return # Get user's chosen label mapping from dlg labelMapping = settingsDlg.labelMapping # Get user's chosen offsets, ordered by the 'write seeds' slot axes_5d = opReorderAxes.Output.meta.getAxisKeys() tagged_offsets = collections.OrderedDict( list(zip( axes_5d, [0]*len(axes_5d) )) ) tagged_offsets.update( dict( list(zip( opReorderAxes.Output.meta.getAxisKeys(), settingsDlg.imageOffsets )) ) ) imageOffsets = list(tagged_offsets.values()) # Optimization if mapping is identity if list(labelMapping.keys()) == list(labelMapping.values()): labelMapping = None # If the data was already cached, this will be fast. label_data = opReorderAxes.Output[:].wait() # Map input labels to output labels if labelMapping: # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential) # But this supports potentially huge values of unique_read_labels (in the billions), # without needing GB of RAM. mapping_indexes = numpy.searchsorted(unique_read_labels, label_data) new_labels = numpy.array([labelMapping[x] for x in unique_read_labels]) label_data[:] = new_labels[mapping_indexes] label_roi = numpy.array( roiFromShape(opReorderAxes.Output.meta.shape) ) label_roi += imageOffsets label_slice = roiToSlice(*label_roi) writeSeeds[label_slice] = label_data finally: opReorderAxes.cleanUp() opMetadataInjector.cleanUp() opCache.cleanUp() opImport.cleanUp()
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None): """ Prompt the user for layer import settings, and perform the layer import. :param labelLayer: The top label layer source :param labelingSlots: An instance of LabelingGui.LabelingSlots :param parent_widget: The Qt GUI parent object """ writeSeeds = labelingSlots.labelInput assert isinstance(writeSeeds, lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds)) opLabels = writeSeeds.getRealOperator() assert isinstance(opLabels, lazyflow.graph.Operator), "slot's operator is of type %r" % (type(opLabels)) fileNames = ImageFileDialog( parent_widget, preferences_group="labeling", preferences_setting="recently imported" ).getSelectedPaths() fileNames = list(map(str, fileNames)) if not fileNames: return try: # Initialize operators opImport = OpInputDataReader(parent=opLabels.parent) opCache = OpBlockedArrayCache(parent=opLabels.parent) opMetadataInjector = OpMetadataInjector(parent=opLabels.parent) opReorderAxes = OpReorderAxes(parent=opLabels.parent) # Set up the pipeline as follows: # # opImport --> (opCache) --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput # / / # User-specified axisorder labelInput.meta.axistags opImport.FilePath.setValue(fileNames[0] if len(fileNames) == 1 else os.path.pathsep.join(fileNames)) assert opImport.Output.ready() maxLabels = len(labelingSlots.labelNames.value) # We don't bother with counting the label pixels # (and caching the data) if it's big (1 GB) if numpy.prod(opImport.Output.meta.shape) > 1e9: reading_slot = opImport.Output # For huge data, we don't go through and search for the pixel values, # because that takes an annoyingly long amount of time. # Instead, we make the reasonable assumption that the input labels are already 1,2,3..N # and we don't tell the user what the label pixel counts are. unique_read_labels = numpy.array(list(range(maxLabels + 1))) readLabelCounts = numpy.array([-1] * (maxLabels + 1)) labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) else: opCache.Input.connect(opImport.Output) opCache.CompressionEnabled.setValue(True) assert opCache.Output.ready() reading_slot = opCache.Output # We'll show a little window with a busy indicator while the data is loading busy_dlg = QProgressDialog(parent=parent_widget) busy_dlg.setLabelText("Scanning Label Data...") busy_dlg.setCancelButton(None) busy_dlg.setMinimum(100) busy_dlg.setMaximum(100) def close_busy_dlg(*args): QApplication.postEvent(busy_dlg, QCloseEvent()) # Load the data from file into our cache # When it's done loading, close the progress dialog. req = reading_slot[:] req.notify_finished(close_busy_dlg) req.notify_failed(close_busy_dlg) req.submit() busy_dlg.exec_() readData = req.result # Can't use return_counts feature because that requires numpy >= 1.9 # unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True) # This does the same as the above, albeit slower, and probably with more ram. bincounts = chunked_bincount(readData) unique_read_labels = bincounts.nonzero()[0].astype(readData.dtype, copy=False) readLabelCounts = bincounts[unique_read_labels] labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) del readData opMetadataInjector.Input.connect(reading_slot) metadata = reading_slot.meta.copy() opMetadataInjector.Metadata.setValue(metadata) opReorderAxes.Input.connect(opMetadataInjector.Output) # Transpose the axes for assignment to the labeling operator. opReorderAxes.AxisOrder.setValue(writeSeeds.meta.getAxisKeys()) # Ask the user how to interpret the data. settingsDlg = LabelImportOptionsDlg( parent_widget, fileNames, opMetadataInjector.Output, labelingSlots.labelInput, labelInfo ) def handle_updated_axes(): # The user is specifying a new interpretation of the file's axes updated_axisorder = str(settingsDlg.axesEdit.text()) metadata = opMetadataInjector.Metadata.value.copy() metadata.axistags = vigra.defaultAxistags(updated_axisorder) opMetadataInjector.Metadata.setValue(metadata) if opReorderAxes._invalid_axes: settingsDlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) # Red background settingsDlg.axesEdit.setStyleSheet( "QLineEdit { background: rgb(255, 128, 128);" "selection-background-color: rgb(128, 128, 255); }" ) settingsDlg.axesEdit.editingFinished.connect(handle_updated_axes) # Initialize handle_updated_axes() dlg_result = settingsDlg.exec_() if dlg_result != LabelImportOptionsDlg.Accepted: return # Get user's chosen label mapping from dlg labelMapping = settingsDlg.labelMapping # Get user's chosen offsets, ordered by the 'write seeds' slot axes_5d = opReorderAxes.Output.meta.getAxisKeys() tagged_offsets = collections.OrderedDict(list(zip(axes_5d, [0] * len(axes_5d)))) tagged_offsets.update(dict(list(zip(opReorderAxes.Output.meta.getAxisKeys(), settingsDlg.imageOffsets)))) imageOffsets = list(tagged_offsets.values()) # Optimization if mapping is identity if list(labelMapping.keys()) == list(labelMapping.values()): labelMapping = None # If the data was already cached, this will be fast. label_data = opReorderAxes.Output[:].wait() # Map input labels to output labels if labelMapping: # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential) # But this supports potentially huge values of unique_read_labels (in the billions), # without needing GB of RAM. mapping_indexes = numpy.searchsorted(unique_read_labels, label_data) new_labels = numpy.array([labelMapping[x] for x in unique_read_labels]) label_data[:] = new_labels[mapping_indexes] label_roi = numpy.array(roiFromShape(opReorderAxes.Output.meta.shape)) label_roi += imageOffsets label_slice = roiToSlice(*label_roi) writeSeeds[label_slice] = label_data finally: opReorderAxes.cleanUp() opMetadataInjector.cleanUp() opCache.cleanUp() opImport.cleanUp()
class Window(QWidget, Ui_FormFrameworkTools): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.setupUi(self) self.groupBoxPs.setEnabled(False) self._initSocket() self._initCodeEdit() # 配置 self._setting = QSettings('PsConnectFrameworkTools', 'Settings') # 本地端口 self.spinBoxPort.setValue( self._setting.value('spinBoxPort', 59595, int)) # ip地址 self.lineEditAddress.setText(self._setting.value( 'lineEditAddress', '127.0.0.1', str)) # ps端口 self.spinBoxPsPort.setValue( self._setting.value('spinBoxPsPort', 49494, int)) # ps密码 self.lineEditPassword.setText(self._setting.value( 'lineEditPassword', '', str)) # 设置参数 self.argsEdit.setPlainText(self._setting.value( 'argsEdit', 'test1();\ntest2();', str)) # 设置编辑器里的代码 self.codeEdit.setText(self._setting.value('codeEdit', Template, str)) def _initSocket(self): # 初始化server(用于接收ps返回消息) self._server = TcpServer(self) self._server.messageReceived.connect(self.onMessageReceived) # 初始化client(用于连接ps) self._client = TcpSocket(self) self._client.connected.connect(self.onConnectSuccessed) # 连接成功 self._client.connectClosed.connect(self.onConnectClosed) def _initCodeEdit(self): # 初始化编辑器的工作 self.codeEdit.setUtf8(True) self.codeEdit.linesChanged.connect(self.onLinesChanged) # 行改变 # 代码高亮 self.codeEdit.setLexer(QsciLexerJavaScript(self)) # 自动折叠 self.codeEdit.setMarginType(3, QsciScintilla.SymbolMargin) self.codeEdit.setMarginLineNumbers(3, False) self.codeEdit.setMarginWidth(3, 15) self.codeEdit.setMarginSensitivity(3, True) # 显示行号 #self.codeEdit.setMarginType(0, QsciScintilla.NumberMargin) self.codeEdit.setMarginLineNumbers(0, True) self.onLinesChanged() # 代码提示 sciApi = QsciAPIs(self.codeEdit.lexer()) sciApi.prepare() self.codeEdit.setAutoCompletionSource(QsciScintilla.AcsAll) # 设置源 self.codeEdit.setAutoCompletionCaseSensitivity(True) # 设置自动补全大小写敏感 self.codeEdit.setAutoCompletionThreshold(1) # 设置每输入一个字符就会出现自动补全的提示 # 设置字体 self.codeEdit.setFont(QFont('Consolas', 16)) self.codeEdit.setMarginsFont(self.codeEdit.font()) # 设置编码 self.codeEdit.SendScintilla( QsciScintilla.SCI_SETCODEPAGE, QsciScintilla.SC_CP_UTF8) self.codeEdit.setBraceMatching(QsciScintilla.StrictBraceMatch) # 设置当前行高亮 self.codeEdit.setCaretLineVisible(True) self.codeEdit.setCaretLineBackgroundColor(Qt.lightGray) self.codeEdit.setCaretForegroundColor(Qt.white) # tab # table relative self.codeEdit.setIndentationsUseTabs(True) self.codeEdit.setIndentationWidth(4) self.codeEdit.setTabIndents(True) self.codeEdit.setAutoIndent(True) self.codeEdit.setBackspaceUnindents(True) self.codeEdit.setTabWidth(4) # indentation guides self.codeEdit.setIndentationGuides(True) # folding margin self.codeEdit.setFolding(QsciScintilla.PlainFoldStyle) self.codeEdit.setMarginWidth(2, 12) # 自动换行 self.codeEdit.setWrapMode(QsciScintilla.WrapWord) def onLinesChanged(self): # 动态设置左边的边距 self.codeEdit.setMarginWidth( 0, self.codeEdit.fontMetrics().width(str(self.codeEdit.lines())) + 5) def onMessageReceived(self, data): # 接收到ps中js发送的结果 self.closeWait() # 解码数据 try: data = data.decode() except Exception as e: self.resultEdit.append('解码数据错误: ' + str(e)) return self.resultEdit.append(data) # 尝试解析消息 try: data = json.loads(data) # 获取版本 version = data.get('version', '0.') if not version or int(version.split('.')[0]) < 18: QMessageBox.information( self, '提示', '未能获取到版本或者版本号小于18(PS 2017)') return # 获取可能需要调用的函数和参数 method = data.get('method', 'nomethod') params = data.get('params', []) if hasattr(self, method): # 调用函数 getattr(self, method)(*params) except Exception as e: print('解析数据错误:', e) traceback.print_exc() def onConnectSuccessed(self): self.closeWait() QMessageBox.information(self, '恭喜', '连接成功') def onConnectClosed(self, message=None): # 连接被断开 self.closeWait() if QMessageBox.question( self, '错误', message + '\n是否重连?', QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: # 重连 self.on_buttonConnect_clicked() def showMessage(self, message): # 显示消息 if message: # unquote 尝试对消息反编码 QMessageBox.information(self, '提示', unquote(message)) @pyqtSlot() def on_buttonResetCode_clicked(self): # 重置代码区域为默认 self.codeEdit.setText(Template) @pyqtSlot() def on_buttonStartServer_clicked(self): # 开启本地服务的按钮 if not self._server.listen(QHostAddress.LocalHost, self.spinBoxPort.value()): QMessageBox.critical( self, '错误', '监听本地端口{}失败,请尝试更换端口试试'.format(self.spinBoxPort.value())) return # 保存本地端口到配置 self._setting.setValue('spinBoxPort', self.spinBoxPort.value()) self._setting.sync() # 本地服务器开启成功则禁用 self.buttonStartServer.setEnabled(False) self.spinBoxPort.setEnabled(False) self.groupBoxPs.setEnabled(True) @pyqtSlot() def on_buttonConnect_clicked(self): # 连接ps的按钮 if self._client.state() == self._client.ConnectedState: # 如果已经连接上了则跳过 return # 保存ps的地址端口和密码 self._setting.setValue( 'lineEditAddress', self.lineEditAddress.text().strip()) self._setting.setValue('spinBoxPsPort', self.spinBoxPsPort.value()) self._setting.setValue( 'lineEditPassword', self.lineEditPassword.text().strip()) self._setting.sync() # 构建协议类(用于传递数据的加密) Protocol.init(self.lineEditPassword.text().strip()) # 开始连接ps self._client.connectToHost( self.lineEditAddress.text().strip(), self.spinBoxPsPort.value()) # 显示进度条 self.showWait('正在连接中') @pyqtSlot() def on_runButton_clicked(self): # 运行按钮 code = self.codeEdit.text().strip() if not code: return if self._client.state() == self._client.ConnectedState and self._client.isWritable(): # 保存参数和代码 self._setting.setValue( 'argsEdit', self.argsEdit.toPlainText().strip()) self._setting.setValue( 'codeEdit', self.codeEdit.text().strip()) self._setting.sync() self._client.write(Protocol.pack(self.formatCode(code), 2)) # 发送数据 Protocol.increase() # 自增1 self.showWait('正在处理中...') # 显示进度条 else: QMessageBox.critical(self, '错误', '未连接或者不能发送数据') def formatCode(self, code): # 格式化code code = code.replace( '#HOST#', '127.0.0.1').replace( '#PORT#', str(self.spinBoxPort.value())).replace( '//#Function#', self.argsEdit.toPlainText().strip()) print('格式化code, 长度: ', len(code)) return code def showWait(self, text): # 显示等待进度条 self._wdialog = QProgressDialog(text, '', 0, 0, self) self._wdialog.setWindowFlags( self._wdialog.windowFlags() | Qt.FramelessWindowHint) self._wdialog.setWindowTitle('请稍候') self._wdialog.setCancelButton(None) self._wdialog.exec_() def closeWait(self): # 隐藏或者关闭等待进度条 self._wdialog.accept() def closeEvent(self, event): if self._server.isListening(): # 关闭本地服务器 self._server.close() self._server.deleteLater() # 断开和ps的连接 self._client.blockSignals(True) self._client.abort() self._client.deleteLater() super(Window, self).closeEvent(event)