def OnButtonNextTask(self, evt): overwrite = self.check_box.IsChecked() algorithm = 'Default' options = {} to_generate = True if self.GetMaskSelected() != -1: sl = slice_.Slice() if sl.current_mask.was_edited: dlgs = dlg.SurfaceDialog() if dlgs.ShowModal() == wx.ID_OK: algorithm = dlgs.GetAlgorithmSelected() options = dlgs.GetOptions() else: to_generate = False dlgs.Destroy() if to_generate: mask_index = sl.current_mask.index method = {'algorithm': algorithm, 'options': options} srf_options = {"index": mask_index, "name": '', "quality": _('Optimal *'), "fill": False, "keep_largest": False, "overwrite": overwrite} Publisher.sendMessage('Create surface from index', {'method': method, 'options': srf_options}) Publisher.sendMessage('Fold surface task') else: dlg.InexistentMask()
def OnClutChange(self, evt): Publisher.sendMessage( 'Change colour table from background image from widget', evt.GetNodes()) slc = sl.Slice() Publisher.sendMessage('Update window level value', (slc.window_width, slc.window_level))
def OnButtonInfo(self, evt): sl = slice_.Slice() overlay_data = sl.overlay if overlay_data is not None: ovdlg = dlg.OverlayDialog(overlay_data) ovdlg.Show()
def OnOpenOverlay(self, pubsub_evt): dirpath = dialog.ShowOpenNiftiDialog() nifti_image = nifti.ReadNifti(dirpath) if nifti_image: # Rearranges the axes of the image to be closest to RAS+ orientation, # so the slices of the image (axial, coronal, sagittal) are shown correctly. # See http://nipy.org/nibabel/image_orientation.html nifti_image = as_closest_canonical(nifti_image) imagedata = nifti_image.get_data() # Conversion of type of numpy array (to unsigned char) imagedata = imagedata.astype('f') slc = sl.Slice() y, x = slc.buffer_slices["AXIAL"].image.shape z = slc.buffer_slices["SAGITAL"].image.shape[0] # Add borders (with zero values) to overlay array to fit the dimensions of the 3D image pad_x = numpy.abs((x / 2.0) - (imagedata.shape[0] / 2.0)) pad_y = numpy.abs((y / 2.0) - (imagedata.shape[1] / 2.0)) pad_z = numpy.abs((z / 2.0) - (imagedata.shape[2] / 2.0)) final_overlay = numpy.pad(imagedata, ((pad_x, pad_x), (pad_y, pad_y), (pad_z, pad_z)), mode='constant', constant_values=0) # Modifications to work with Invesalius (Z,Y,X) final_overlay = numpy.swapaxes(final_overlay, 0, 2) final_overlay = numpy.fliplr(final_overlay) Publisher.sendMessage('Set slice overlay', final_overlay)
def LoadProject(self): proj = prj.Project() const.THRESHOLD_OUTVALUE = proj.threshold_range[0] const.THRESHOLD_INVALUE = proj.threshold_range[1] const.WINDOW_LEVEL[_('Default')] = (proj.window, proj.level) const.WINDOW_LEVEL[_('Manual')] = (proj.window, proj.level) self.Slice = sl.Slice() self.Slice.spacing = proj.spacing Publisher.sendMessage('Load slice to viewer', (proj.mask_dict)) Publisher.sendMessage('Load slice plane') Publisher.sendMessage('Bright and contrast adjustment image',\ (proj.window, proj.level)) Publisher.sendMessage('Update window level value',\ (proj.window, proj.level)) Publisher.sendMessage('Set project name', proj.name) Publisher.sendMessage('Load surface dict', proj.surface_dict) Publisher.sendMessage('Hide surface items', proj.surface_dict) self.LoadImagedataInfo() # TODO: where do we insert this <<<? Publisher.sendMessage('Show content panel') Publisher.sendMessage('Update AUI') if len(proj.mask_dict): mask_index = len(proj.mask_dict) -1 for m in proj.mask_dict.values(): Publisher.sendMessage('Add mask', (m.index, m.name, m.threshold_range, m.colour)) self.Slice.current_mask = proj.mask_dict[mask_index] Publisher.sendMessage('Show mask', (mask_index, True)) else: mask_name = const.MASK_NAME_PATTERN % (1,) thresh = const.THRESHOLD_RANGE colour = const.MASK_COLOUR[0] Publisher.sendMessage('Create new mask', (mask_name, thresh, colour)) Publisher.sendMessage('Load measurement dict', (proj.measurement_dict, self.Slice.spacing)) Publisher.sendMessage(('Set scroll position', 'AXIAL'),proj.matrix_shape[0]/2) Publisher.sendMessage(('Set scroll position', 'SAGITAL'),proj.matrix_shape[1]/2) Publisher.sendMessage(('Set scroll position', 'CORONAL'),proj.matrix_shape[2]/2) Publisher.sendMessage('End busy cursor')
def UpdateWindowLevelValue(self, pubsub_evt): window, level = pubsub_evt.data self.acum_achange_window, self.acum_achange_level = (window, level) self.SetWLText(window, level) slc = sl.Slice() slc._update_wwwl_widget_nodes(window, level) Publisher.sendMessage('Update all slice') Publisher.sendMessage('Update clut imagedata widget')
def SetLayout(self, layout): self.layout = layout if (layout == (1, 1)) and self.on_text: self.ShowTextActors() else: self.HideTextActors(change_status=False) slice_ = sl.Slice() self.LoadRenderers(slice_.GetOutput()) self.__configure_renderers() self.__configure_scroll()
def SetInput(self, mask_dict): self.slice_ = sl.Slice() max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation) self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, max_slice_number) self.slice_data = self.create_slice_window() self.slice_data.SetCursor(self.__create_cursor()) self.cam = self.slice_data.renderer.GetActiveCamera() self.__build_cross_lines() # Set the slice number to the last slice to ensure the camera is far # enough to show all slices. self.set_slice_number(max_slice_number - 1) self.__update_camera() self.slice_data.renderer.ResetCamera() self.interactor.GetRenderWindow().AddRenderer(self.slice_data.renderer) self.interactor.Render() self.EnableText() self.wl_text.Hide() ## Insert cursor self.SetInteractorStyle(const.STATE_DEFAULT)
def OnNew(self): sl = slice_.Slice() dialog = dlg.SurfaceCreationDialog( None, -1, _('New surface'), mask_edited=sl.current_mask.was_edited) try: if dialog.ShowModal() == wx.ID_OK: ok = 1 else: ok = 0 except (wx._core.PyAssertionError): #TODO FIX: win64 ok = 1 if ok: surface_options = dialog.GetValue() Publisher.sendMessage('Create surface from index', surface_options) dialog.Destroy()
def OnLinkNewSurface(self, evt=None): #import gui.dialogs as dlg sl = slice_.Slice() dialog = dlg.SurfaceCreationDialog(None, -1, _('New surface'), mask_edited=sl.current_mask.was_edited) try: if dialog.ShowModal() == wx.ID_OK: ok = 1 else: ok = 0 except(wx._core.PyAssertionError): #TODO FIX: win64 ok = 1 if (ok): ## Retrieve information from dialog #(mask_index, surface_name, surface_quality, fill_holes,\ #keep_largest) = dialog.GetValue() ## Retrieve information from mask #proj = prj.Project() #mask = proj.mask_dict[mask_index] ## Send all information so surface can be created #surface_data = [proj.imagedata, #mask.colour, #mask.threshold_range, #mask.edited_points, #False, # overwrite #surface_name, #surface_quality, #fill_holes, #keep_largest] surface_options = dialog.GetValue() Publisher.sendMessage('Create surface from index', surface_options) dialog.Destroy() if evt: evt.Skip()
def CreateNiftiProject(self, imagedata): header = imagedata.get_header() proj = prj.Project() proj.imagedata = None proj.name = _("Untitled") proj.SetAcquisitionModality("MRI") #TODO: Verify if all Nifti are in AXIAL orientation # To get Z, X, Y (used by InVesalius), not X, Y, Z matrix, matrix_filename = image_utils.nifti2mmap(imagedata) # if header['orient'] == 0: # proj.original_orientation = const.AXIAL # elif header['orient'] == 1: # proj.original_orientation = const.CORONAL # elif header['orient'] == 2: # proj.original_orientation = const.SAGITAL # else: # proj.original_orientation = const.SAGITAL # Project orientation set CORONAL as default proj.original_orientation = const.CORONAL proj.threshold_range = (numpy.amin(matrix), numpy.amax(matrix)) proj.window = proj.threshold_range[1] - proj.threshold_range[0] proj.level = (0.5 * (proj.threshold_range[1] + proj.threshold_range[0])) proj.spacing = header['pixdim'][1:4] proj.matrix_shape = matrix.shape self.Slice = sl.Slice() self.Slice.matrix = matrix self.Slice.matrix_filename = matrix_filename self.Slice.window_level = proj.level self.Slice.window_width = proj.window self.Slice.spacing = header.get_zooms()[:3] Publisher.sendMessage('Update threshold limits list', proj.threshold_range)
def OpenProject(self, filepath): Publisher.sendMessage('Begin busy cursor') path = os.path.abspath(filepath) proj = prj.Project() proj.OpenPlistProject(path) proj.SetAcquisitionModality(proj.modality) self.Slice = sl.Slice() self.Slice._open_image_matrix(proj.matrix_filename, tuple(proj.matrix_shape), proj.matrix_dtype) self.Slice.window_level = proj.level self.Slice.window_width = proj.window Publisher.sendMessage('Update threshold limits list', proj.threshold_range) self.LoadProject() session = ses.Session() session.OpenProject(filepath) Publisher.sendMessage("Enable state project", True)
def CreateAnalyzeProject(self, imagedata): header = imagedata.get_header() proj = prj.Project() proj.imagedata = None proj.name = _("Untitled") proj.SetAcquisitionModality("MRI") #TODO: Verify if all Analyze are in AXIAL orientation # To get Z, X, Y (used by InVesalius), not X, Y, Z matrix, matrix_filename = image_utils.analyze2mmap(imagedata) if header['orient'] == 0: proj.original_orientation = const.AXIAL elif header['orient'] == 1: proj.original_orientation = const.CORONAL elif header['orient'] == 2: proj.original_orientation = const.SAGITAL else: proj.original_orientation = const.SAGITAL proj.threshold_range = (header['glmin'], header['glmax']) # Window level and wide are normalized to best visualization experience in NIFTI proj.window = proj.threshold_range[1] - proj.threshold_range[0] proj.level = (0.5 * (proj.threshold_range[1] + proj.threshold_range[0])) proj.spacing = header['pixdim'][1:4] proj.matrix_shape = matrix.shape self.Slice = sl.Slice() self.Slice.matrix = matrix self.Slice.matrix_filename = matrix_filename self.Slice.window_level = proj.level self.Slice.window_width = proj.window self.Slice.spacing = header.get_zooms()[:3] Publisher.sendMessage('Update threshold limits list', proj.threshold_range)
def OnUpdateScroll(self, pubsub_evt): max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation) self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, max_slice_number)
def OpenDicomGroup(self, dicom_group, interval, file_range, gui=True): # Retrieve general DICOM headers dicom = dicom_group.GetDicomSample() # Create imagedata interval += 1 filelist = dicom_group.GetFilenameList()[::interval] if not filelist: utils.debug("Not used the IPPSorter") filelist = [i.image.file for i in dicom_group.GetHandSortedList()[::interval]] if file_range != None and file_range[1] > file_range[0]: filelist = filelist[file_range[0]:file_range[1] + 1] zspacing = dicom_group.zspacing * interval size = dicom.image.size bits = dicom.image.bits_allocad sop_class_uid = dicom.acquisition.sop_class_uid xyspacing = dicom.image.spacing orientation = dicom.image.orientation_label if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage use_dcmspacing = 1 else: use_dcmspacing = 0 imagedata = None sx, sy = size n_slices = len(filelist) resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8) if resolution_percentage < 1.0: re_dialog = dialog.ResizeImageDialog() re_dialog.SetValue(int(resolution_percentage*100)) re_dialog_value = re_dialog.ShowModal() re_dialog.Close() if re_dialog_value == wx.ID_OK: percentage = re_dialog.GetValue() resolution_percentage = percentage / 100.0 else: return xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage wl = float(dicom.image.level) ww = float(dicom.image.window) self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, orientation, resolution_percentage) self.Slice = sl.Slice() self.Slice.matrix = self.matrix self.Slice.matrix_filename = self.filename if orientation == 'AXIAL': self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing elif orientation == 'CORONAL': self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1] elif orientation == 'SAGITTAL': self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0] # 1(a): Fix gantry tilt, if any tilt_value = dicom.acquisition.tilt if (tilt_value) and (gui): # Tell user gantry tilt and fix, according to answer message = _("Fix gantry tilt applying the degrees below") value = -1*tilt_value tilt_value = dialog.ShowNumberDialog(message, value) image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) elif (tilt_value) and not (gui): tilt_value = -1*tilt_value image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) self.Slice.window_level = wl self.Slice.window_width = ww scalar_range = int(self.matrix.min()), int(self.matrix.max()) Publisher.sendMessage('Update threshold limits list', scalar_range) return self.matrix, self.filename, dicom
def OnPopup(self, evt): id = evt.GetId() item = self.ID_TO_TOOL_ITEM[evt.GetId()] key = item.GetLabel() if(key in const.WINDOW_LEVEL.keys()): window, level = const.WINDOW_LEVEL[key] Publisher.sendMessage('Bright and contrast adjustment image', (window, level)) Publisher.sendMessage('Update window level value',\ (window, level)) Publisher.sendMessage('Update window and level text',\ "WL: %d WW: %d"%(level, window)) Publisher.sendMessage('Update slice viewer') #Necessary update the slice plane in the volume case exists Publisher.sendMessage('Render volume viewer') elif(key in const.SLICE_COLOR_TABLE.keys()): values = const.SLICE_COLOR_TABLE[key] Publisher.sendMessage('Change colour table from background image', values) Publisher.sendMessage('Update slice viewer') if sys.platform == 'linux2': for i in self.pseudo_color_items: it = self.pseudo_color_items[i] if it.IsChecked(): it.Toggle() item.Toggle() self.HideClutDialog() self._gen_event = True elif key in self.plist_presets: values = presets.get_wwwl_preset_colours(self.plist_presets[key]) Publisher.sendMessage('Change colour table from background image from plist', values) Publisher.sendMessage('Update slice viewer') if sys.platform == 'linux2': for i in self.pseudo_color_items: it = self.pseudo_color_items[i] if it.IsChecked(): it.Toggle() item.Toggle() self.HideClutDialog() self._gen_event = True elif(key in const.IMAGE_TILING.keys()): values = const.IMAGE_TILING[key] Publisher.sendMessage('Set slice viewer layout', values) Publisher.sendMessage('Update slice viewer') elif key in PROJECTIONS_ID: pid = PROJECTIONS_ID[key] Publisher.sendMessage('Set projection type', pid) Publisher.sendMessage('Reload actual slice') elif key == _('Custom'): if self.cdialog is None: slc = sl.Slice() histogram = slc.histogram init = slc.matrix.min() end = slc.matrix.max() nodes = slc.nodes self.cdialog = ClutImagedataDialog(histogram, init, end, nodes) self.cdialog.Show() else: self.cdialog.Show(self._gen_event) if sys.platform == 'linux2': for i in self.pseudo_color_items: it = self.pseudo_color_items[i] if it.IsChecked(): it.Toggle() item.Toggle() item = self.ID_TO_TOOL_ITEM[evt.GetId()] item.Check(True) self._gen_event = False evt.Skip()