def __openFolder(self, mode): """ Called when user wants to open a sequence of KEST files. NOTE: a thread is started when this function is invoked. """ try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.ShowDirsOnly folder = QFileDialog.getExistingDirectory(self,"Open KEST sequence", "", options=options) if folder: # Disable buttons: self.sidebar.reconstructionTab.button.setEnabled(False) self.sidebar.preprocessingTab.btnApply.setEnabled(False) # Read the file (on a separate thread): self.readThread = ReadThread(self, folder, mode, True) self.readThread.readDone.connect(self.readJobDone) self.readThread.logOutput.connect(self.handleOutputLog) self.readThread.error.connect(self.handleThreadError) self.readThread.start() # Open the related HDF5 (if exists): #self.sidebar.hdfViewerTab.setHDF5File("C:\\Temp\\test.kest") except Exception as e: eprint(str(e)) # Restore the buttons: self.sidebar.reconstructionTab.button.setEnabled(True) self.sidebar.preprocessingTab.btnApply.setEnabled(True)
def __openFile(self, mode): """ Called when user wants to open a new KEST file. NOTE: a thread is started when this function is invoked. """ try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getOpenFileName(self,"Open KEST file", "","KEST Files (*.dat);;All Files (*)", options=options) if filename: # Disable buttons: self.sidebar.reconstructionTab.button.setEnabled(False) self.sidebar.preprocessingTab.btnApply.setEnabled(False) # Read the file (on a separate thread): self.readThread = ReadThread(self, filename, mode, False) self.readThread.readDone.connect(self.readJobDone) self.readThread.logOutput.connect(self.handleOutputLog) self.readThread.error.connect(self.handleThreadError) self.readThread.start() except Exception as e: eprint(str(e)) # Restore the buttons: self.sidebar.reconstructionTab.button.setEnabled(True) self.sidebar.preprocessingTab.btnApply.setEnabled(True)
def _toolBarBtnPressed(self, button): if button.text() == ZOOM_IN_TOOLTIP: self.imagePanel.performZoom(min(400.0,self.imagePanel.zoomFactor*1.15)) elif button.text() == ZOOM_OUT_TOOLTIP: self.imagePanel.performZoom(max(1.0,self.imagePanel.zoomFactor/1.15)) elif button.text() == ZOOM_RESET_TOOLTIP: self.imagePanel.performZoom(1.0) elif button.text() == EXPORT_TOOLTIP: # Open a Save As dialog: try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getSaveFileName(self,"Save as TIFF", "","TIFF Files (*.tif);;All Files (*)", options=options) if filename: # Call the method to save the current displayed image: self.imagePanel.saveAsTIFF(filename) except Exception as e: eprint(str(e)) elif button.text() == EXPORTALL_TOOLTIP: # Open a Save As dialog: try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DirectoryOnly folder = QFileDialog.getExistingDirectory(self, "Select Folder for TIFF sequence") if folder: for i in range(0,self.__data.shape[2]): # Prepare filename: filename = os.path.join(folder, "image_" + "{:04d}".format(i) + ".tif") # Save as TIFF with tiffile library: tifffile.imsave(filename, data=self.__data[:,:,i]) except Exception as e: eprint(str(e))
def onQApplicationStarted(self): """ Things done as the main window is fully loaded. """ try: # Startup message: platf = platform.uname() cpus = psutil.cpu_count() stat = psutil.virtual_memory() ram = (stat.total) / (1024.0 * 1024 * 1024) # GB # system, node, release, version, machine, and processor. val = "KEST started on " + platf.node + " (# of CPUs: " + str(cpus) + \ ", RAM: " + "{:.2f}".format(ram) + " GB)" # Log string: self.mainPanel.log.logOutput(val) # Read settings: #self.read_settings() except Exception as e: eprint(str(e)) pass
def applyReconstruction(self): """ Called when user wants to perform the reconstruction on current flat-fielded image: NOTE: the current image should be a 'pre-processed' image. The UI should avoid to let this method callable when current image is not a 'pre-processed'. NOTE: a thread is started when this function is invoked. """ try: # Disable buttons: self.sidebar.reconstructionTab.button.setEnabled(False) self.sidebar.preprocessingTab.btnApply.setEnabled(False) # Get current left image: curr_tab = self.mainPanel.getCurrentTab() im = curr_tab.getData() sourceFile = curr_tab.getSourceFile() mode = curr_tab.getOriginalMode() # Get parameters from UI: method = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_Method") iterations = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_Iterations") filter = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_FDK-Filter") weights = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_Weights") angles = self.sidebar.reconstructionTab.getValue("Reconstruction_Angles") angles_shift = self.sidebar.reconstructionTab.getValue("Reconstruction_Angles_Shift") angles_decimation = self.sidebar.reconstructionTab.getValue("Reconstruction_Angles_Decimation") nr_proj = self.sidebar.reconstructionTab.getValue("Reconstruction_Projections") upsampling = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_Upsampling") overpadding = self.sidebar.reconstructionTab.getValue("ReconstructionAlgorithm_Overpadding") geometry = self.sidebar.reconstructionTab.getValue("Geometry_Type") ssd = float(self.sidebar.reconstructionTab.getValue("Geometry_Source-Sample")) sdd = float(self.sidebar.reconstructionTab.getValue("Geometry_Source-Detector")) px = float(self.sidebar.reconstructionTab.getValue("Geometry_DetectorPixelSize")) det_u = float(self.sidebar.reconstructionTab.getValue("Offsets_Detector-u")) det_v = float(self.sidebar.reconstructionTab.getValue("Offsets_Detector-v")) roll = float(self.sidebar.reconstructionTab.getValue("Offsets_Detector-Roll")) pitch = float(self.sidebar.reconstructionTab.getValue("Offsets_Detector-Pitch")) yaw = float(self.sidebar.reconstructionTab.getValue("Offsets_Detector-Yaw")) # Remove extra projections: im = im[:,:,:nr_proj] im = im[:,:,::angles_decimation] # Convert from degrees to radians: angles = angles * numpy.pi / 180.0 angles_shift = angles_shift * numpy.pi / 180.0 # Convert to boolean for short_scan: short_scan = False if (weights == 0) else True # Call reconstruction (on a separate thread): self.reconThread = ReconThread(self, im, sourceFile, angles, geometry, \ ssd, sdd, px, det_u, det_v, short_scan, method, iterations, mode, \ overpadding, angles_shift ) self.reconThread.reconDone.connect(self.reconstructJobDone) self.reconThread.logOutput.connect(self.handleOutputLog) self.reconThread.error.connect(self.handleThreadError) self.reconThread.start() # Only for debug: #rec = recon_tigre_fdk(im, ssd, sdd - ssd, px, angles, \ # angles_shift, det_u, det_v, roll, pitch, # yaw, short_scan, overpadding, filter) #self.reconstructJobDone(rec, sourceFile, RECON_TABLABEL, mode) except Exception as e: # Print the exception: eprint("Error while performing reconstruction: " + str(e)) # Restore the buttons: self.sidebar.reconstructionTab.button.setEnabled(True) self.sidebar.preprocessingTab.btnApply.setEnabled(True)
def applyPreprocessing(self): """ Called when user wants to apply the preprocessing on current image. NOTE: the current image should be a 'raw' image. The UI should avoid to let this method callable when current image is not a 'raw'. NOTE: a thread is started when this function is invoked. """ try: # Disable buttons: self.sidebar.reconstructionTab.button.setEnabled(False) self.sidebar.preprocessingTab.btnApply.setEnabled(False) # Get current left image: curr_tab = self.mainPanel.getCurrentTab() sourceFile = curr_tab.getSourceFile() mode = curr_tab.getOriginalMode() # Get params from UI: crop_top = self.sidebar.preprocessingTab.getValue("Crop_Top") crop_bottom = self.sidebar.preprocessingTab.getValue("Crop_Bottom") crop_left = self.sidebar.preprocessingTab.getValue("Crop_Left") crop_right = self.sidebar.preprocessingTab.getValue("Crop_Right") proj_avg_mode = self.sidebar.preprocessingTab.getValue("ProjectionAveraging_Mode") proj_avg_alpha = self.sidebar.preprocessingTab.getValue("ProjectionAveraging_AlphaTrimmed") rebinning = self.sidebar.preprocessingTab.getValue("MatrixManipulation_Rebinning2x2") flatfielding_window = self.sidebar.preprocessingTab.getValue("FlatFielding_Window") despeckle_thresh = self.sidebar.preprocessingTab.getValue("Despeckle_Threshold") ringremoval_thresh = self.sidebar.preprocessingTab.getValue("RingRemoval_Threshold") output_low = self.sidebar.preprocessingTab.getValue("Output_LowEnergy") output_high = self.sidebar.preprocessingTab.getValue("Output_HighEnergy") output_diff = self.sidebar.preprocessingTab.getValue("Output_LogSubtraction") output_sum = self.sidebar.preprocessingTab.getValue("Output_EnergyIntegration") ## Call pre-processing (on a separate thread): #self.preprocessThread = PreprocessThread(self, self.dset, rebinning, \ # flatfielding_window, despeckle_thresh, output_low, output_high, \ # output_diff, output_sum, mode, crop_top, crop_bottom, crop_left, \ # crop_right, proj_avg_mode, proj_avg_alpha ) #self.preprocessThread.processDone.connect(self.preprocessJobDone) #self.preprocessThread.logOutput.connect(self.handleOutputLog) #self.preprocessThread.error.connect(self.handleThreadError) #self.preprocessThread.start() # For debug: low, high, diff, sum = pre_processing(self.dset, rebinning, \ flatfielding_window, despeckle_thresh, output_low, \ output_high, output_diff, output_sum, mode, \ [crop_top, crop_bottom, crop_left, crop_right], \ proj_avg_mode, proj_avg_alpha, ringremoval_thresh ) self.preprocessJobDone( low, high, diff, sum, output_low, output_high, \ output_diff, output_sum, sourceFile, PREPROC_TABLABEL, mode ) except Exception as e: eprint("Error while pre-processing: " + str(e)) # Restore the buttons: self.sidebar.reconstructionTab.button.setEnabled(True) self.sidebar.preprocessingTab.btnApply.setEnabled(True)