diff --git a/invesalius/control.py b/invesalius/control.py index 044de98..b020dbb 100644 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -95,6 +95,11 @@ class Controller(): Publisher.subscribe(self.ApplyReorientation, 'Apply reorientation') + Publisher.subscribe(self.SetBitmapSpacing, 'Set bitmap spacing') + + def SetBitmapSpacing(self, pubsub_evt): + proj = prj.Project() + proj.spacing = pubsub_evt.data def OnCancelImport(self, pubsub_evt): #self.cancel_import = True @@ -381,10 +386,9 @@ class Controller(): #Publisher.sendMessage("Load bitmap preview", first_patient) if data: Publisher.sendMessage("Load import bitmap panel", data) - return True else: - dialog.ImportInvalidFiles() + dialog.ImportInvalidFiles("Bitmap") return False @@ -395,7 +399,7 @@ class Controller(): Publisher.sendMessage("Load dicom preview", first_patient) return True else: - dialog.ImportInvalidFiles() + dialog.ImportInvalidFiles("DICOM") return False @@ -580,10 +584,11 @@ class Controller(): proj.matrix_filename = matrix_filename #proj.imagedata = imagedata #proj.dicom_sample = dicom + proj.original_orientation =\ name_to_const[orientation.upper()] proj.window = float(matrix.max()) - proj.level = float(matrix.max()/2) + proj.level = float(matrix.max()/4) proj.threshold_range = int(matrix.min()), int(matrix.max()) #const.THRESHOLD_RANGE = proj.threshold_range @@ -601,91 +606,79 @@ class Controller(): def OnOpenBitmapFiles(self, pubsub_evt): rec_data = pubsub_evt.data bmp_data = bmp.BitmapData() - matrix, matrix_filename = self.OpenBitmapFiles(bmp_data, rec_data) - - self.CreateBitmapProject(bmp_data, rec_data, matrix, matrix_filename) - self.LoadProject() - Publisher.sendMessage("Enable state project", True) + if bmp_data.IsAllBitmapSameSize(): + matrix, matrix_filename = self.OpenBitmapFiles(bmp_data, rec_data) + + self.CreateBitmapProject(bmp_data, rec_data, matrix, matrix_filename) - def OpenBitmapFiles(self, bmp_data, rec_data): + self.LoadProject() + Publisher.sendMessage("Enable state project", True) + else: + dialogs.BitmapNotSameSize() - if bmp_data.IsAllBitmapSameSize(): + def OpenBitmapFiles(self, bmp_data, rec_data): - name = rec_data[0] - orientation = rec_data[1] - sp_x = float(rec_data[2]) - sp_y = float(rec_data[3]) - sp_z = float(rec_data[4]) - interval = int(rec_data[5]) - - interval += 1 - - filelist = bmp_data.GetOnlyBitmapPath()[::interval] - bits = bmp_data.GetFirstPixelSize() + name = rec_data[0] + orientation = rec_data[1] + sp_x = float(rec_data[2]) + sp_y = float(rec_data[3]) + sp_z = float(rec_data[4]) + interval = int(rec_data[5]) + + interval += 1 + + filelist = bmp_data.GetOnlyBitmapPath()[::interval] + bits = bmp_data.GetFirstPixelSize() - sx, sy = size = bmp_data.GetFirstBitmapSize() - n_slices = len(filelist) - resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8) - - zspacing = sp_z * interval - xyspacing = (sp_y, sp_x) - - 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 + sx, sy = size = bmp_data.GetFirstBitmapSize() + n_slices = len(filelist) + resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8) + + zspacing = sp_z * interval + xyspacing = (sp_y, sp_x) + + 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 - - self.matrix, scalar_range, self.filename = image_utils.bitmap2memmap(filelist, size, - orientation, (sp_z, sp_y, sp_x),resolution_percentage) + + self.matrix, scalar_range, self.filename = image_utils.bitmap2memmap(filelist, size, + orientation, (sp_z, sp_y, sp_x),resolution_percentage) - self.Slice = sl.Slice() - self.Slice.matrix = self.matrix - self.Slice.matrix_filename = self.filename + 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 = float(self.matrix.max()/2) - self.Slice.window_width = float(self.matrix.max()) - - scalar_range = int(self.matrix.min()), int(self.matrix.max()) - Publisher.sendMessage('Update threshold limits list', scalar_range) - - return self.matrix, self.filename#, dicom + 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] + + self.Slice.window_level = float(self.matrix.max()/4) + self.Slice.window_width = float(self.matrix.max()) + + scalar_range = int(self.matrix.min()), int(self.matrix.max()) + Publisher.sendMessage('Update threshold limits list', scalar_range) + + return self.matrix, self.filename#, dicom - else: - print "Error: All slices must be of the same size." def OnOpenDicomGroup(self, pubsub_evt): group, interval, file_range = pubsub_evt.data diff --git a/invesalius/data/converters.py b/invesalius/data/converters.py index c44a6db..1598e27 100644 --- a/invesalius/data/converters.py +++ b/invesalius/data/converters.py @@ -22,6 +22,10 @@ import vtk from vtk.util import numpy_support def to_vtk(n_array, spacing, slice_number, orientation): + + if orientation == "SAGITTAL": + orientation = "SAGITAL" + try: dz, dy, dx = n_array.shape except ValueError: diff --git a/invesalius/data/imagedata_utils.py b/invesalius/data/imagedata_utils.py index 8987413..b5fe80c 100644 --- a/invesalius/data/imagedata_utils.py +++ b/invesalius/data/imagedata_utils.py @@ -430,10 +430,10 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage if orientation == 'SAGITTAL': if resolution_percentage == 1.0: - shape = slice_size[0], slice_size[1], len(files) + shape = slice_size[1], slice_size[0], len(files) else: - shape = math.ceil(slice_size[0]*resolution_percentage),\ - math.ceil(slice_size[1]*resolution_percentage), len(files) + shape = math.ceil(slice_size[1]*resolution_percentage),\ + math.ceil(slice_size[0]*resolution_percentage), len(files) elif orientation == 'CORONAL': if resolution_percentage == 1.0: @@ -448,11 +448,17 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage shape = len(files), math.ceil(slice_size[1]*resolution_percentage),\ math.ceil(slice_size[0]*resolution_percentage) - matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) + + if resolution_percentage == 1.0: + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) + cont = 0 max_scalar = None min_scalar = None - + + xy_shape = None + first_resample_entry = False + for n, f in enumerate(files): image_as_array = bitmap_reader.ReadBitmap(f) @@ -461,10 +467,18 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage if resolution_percentage != 1.0: - + image_resized = ResampleImage2D(image, px=None, py=None,\ resolution_percentage = resolution_percentage, update_progress = None) + yx_shape = image_resized.GetDimensions()[1], image_resized.GetDimensions()[0] + + + if not(first_resample_entry): + shape = shape[0], yx_shape[0], yx_shape[1] + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) + first_resample_entry = True + image = image_resized min_aux, max_aux = image.GetScalarRange() @@ -475,23 +489,25 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage max_scalar = max_aux array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars()) - array = array.astype("int16") - array = image_as_array + if array.dtype == 'uint16': + array = array - 32768/2 + + array = array.astype("int16") if orientation == 'CORONAL': array.shape = matrix.shape[0], matrix.shape[2] - matrix[:, n, :] = array + matrix[:, n, :] = array[:,::-1] elif orientation == 'SAGITTAL': array.shape = matrix.shape[0], matrix.shape[1] # TODO: Verify if it's necessary to add the slices swapped only in # sagittal rmi or only in # Rasiane's case or is necessary in all # sagittal cases. - matrix[:, :, n] = array + matrix[:, :, n] = array[:,::-1] else: - print array.shape, matrix.shape array.shape = matrix.shape[1], matrix.shape[2] matrix[n] = array + update_progress(cont,message) cont += 1 diff --git a/invesalius/data/styles.py b/invesalius/data/styles.py index 51b4242..e59178b 100644 --- a/invesalius/data/styles.py +++ b/invesalius/data/styles.py @@ -337,8 +337,8 @@ class WWWLInteractorStyle(DefaultInteractorStyle): iren = obj.GetInteractor() self.last_x, self.last_y = iren.GetLastEventPosition() - self.acum_achange_window = viewer.slice_.window_width - self.acum_achange_level = viewer.slice_.window_level + self.acum_achange_window = self.viewer.slice_.window_width + self.acum_achange_level = self.viewer.slice_.window_level class LinearMeasureInteractorStyle(DefaultInteractorStyle): diff --git a/invesalius/gui/bitmap_preview_panel.py b/invesalius/gui/bitmap_preview_panel.py index 9b1b621..a0ccdf1 100644 --- a/invesalius/gui/bitmap_preview_panel.py +++ b/invesalius/gui/bitmap_preview_panel.py @@ -2,6 +2,7 @@ import wx import vtk import vtkgdcm import time +import numpy from vtk.util import numpy_support from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor @@ -271,7 +272,6 @@ class Preview(wx.Panel): if evt.m_shiftDown: shift_pressed = True - dicom_id = self.bitmap_info.id self.select_on = True self.bitmap_info.selected = True self.Select() @@ -286,10 +286,11 @@ class Preview(wx.Panel): my_evt.SetEventObject(self) self.GetEventHandler().ProcessEvent(my_evt) + print ">>>",self.bitmap_info.pos, self.bitmap_info.id, self.bitmap_info.data + Publisher.sendMessage('Set bitmap in preview panel', self.bitmap_info.pos) evt.Skip() - def OnSize(self, evt): if self.bitmap_info: @@ -350,6 +351,7 @@ class BitmapPreviewSeries(wx.Panel): self._Add_Panels_Preview() self._bind_events() + self._bind_pub_sub_events() def _Add_Panels_Preview(self): self.previews = [] @@ -371,6 +373,10 @@ class BitmapPreviewSeries(wx.Panel): self.Bind(wx.EVT_SCROLL, self.OnScroll) self.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel) + def _bind_pub_sub_events(self): + Publisher.subscribe(self.RemovePanel, 'Remove preview panel') + #Publisher.subscribe(self.GetBmpInfoIdByOrder, 'Set bitmap in thumbnail') + def OnSelect(self, evt): my_evt = SerieEvent(myEVT_CLICK_SERIE, self.GetId()) my_evt.SetSelectedID(evt.GetSelectID()) @@ -406,7 +412,64 @@ class BitmapPreviewSeries(wx.Panel): self.scroll.SetScrollbar(0, NROWS, scroll_range, NCOLS) self._display_previews() + + def RemovePanel(self, pub_sub): + data = pub_sub.data + for p, f in zip(self.previews, self.files): + if p.bitmap_info != None: + if data.encode('utf-8') in p.bitmap_info.data: + self.files.remove(f) + p.Hide() + self._display_previews() + Publisher.sendMessage('Update max of slidebar in single preview image', len(self.files)) + + self.Update() + self.Layout() + + for n, p in enumerate(self.previews): + if p.bitmap_info != None: + + if p.IsShown(): + p.bitmap_info.pos = n + + #def GetBmpInfoIdByOrder(self, pub_sub): + # order = pub_sub.data + # + # for p in self.previews: + # if p.bitmap_info != None: + # if p.select_on: + # p.select_on = False + # p.selected = False + + # c = (PREVIEW_BACKGROUND) + # p.SetBackgroundColour(c) + + + # for p in self.previews: + # if p.bitmap_info != None: + # if p.bitmap_info.pos == order: + + # p.select_on = True + # p.selected = True + + # p.Select() + + # # Generating a EVT_PREVIEW_CLICK event + # my_evt = SerieEvent(myEVT_PREVIEW_CLICK, p.GetId()) + + # my_evt.SetSelectedID(p.bitmap_info.id) + # my_evt.SetItemData(p.bitmap_info.data) + + # my_evt.SetShiftStatus(False) + # my_evt.SetEventObject(p) + # self.GetEventHandler().ProcessEvent(my_evt) + + # #c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) + # #p.SetBackgroundColour(c) + + #return p.id + #def SetPatientGroups(self, patient): # self.files = [] # self.displayed_position = 0 @@ -576,10 +639,13 @@ class SingleImagePreview(wx.Panel): def __bind_pubsub(self): Publisher.subscribe(self.ShowBitmapByPosition, 'Set bitmap in preview panel') + Publisher.subscribe(self.UpdateMaxValueSliderBar, 'Update max of slidebar in single preview image') + Publisher.subscribe(self.ShowBlackSlice, 'Show black slice in single preview image') def ShowBitmapByPosition(self, evt): - pos = evt.data - self.ShowSlice(pos) + pos = evt.data + if pos != None: + self.ShowSlice(int(pos)) def OnSlider(self, evt): @@ -621,6 +687,36 @@ class SingleImagePreview(wx.Panel): self.slider.SetValue(0) self.ShowSlice() + def UpdateMaxValueSliderBar(self, pub_sub): + self.slider.SetMax(pub_sub.data - 1) + self.slider.Refresh() + self.slider.Update() + + def ShowBlackSlice(self, pub_sub): + n_array = numpy.zeros((100,100)) + + self.text_image_size.SetValue('') + + image = converters.to_vtk(n_array, spacing=(1,1,1),\ + slice_number=1, orientation="AXIAL") + + colorer = vtk.vtkImageMapToWindowLevelColors() + colorer.SetInputData(image) + colorer.Update() + + if self.actor is None: + self.actor = vtk.vtkImageActor() + self.renderer.AddActor(self.actor) + + # PLOT IMAGE INTO VIEWER + self.actor.SetInputData(colorer.GetOutput()) + self.renderer.ResetCamera() + self.interactor.Render() + + # Setting slider position + self.slider.SetValue(0) + + def ShowSlice(self, index = 0): bitmap = self.bitmap_list[index] diff --git a/invesalius/gui/dialogs.py b/invesalius/gui/dialogs.py index 22fbbb2..d902420 100644 --- a/invesalius/gui/dialogs.py +++ b/invesalius/gui/dialogs.py @@ -510,8 +510,12 @@ def ImportEmptyDirectory(dirpath): dlg.ShowModal() dlg.Destroy() -def ImportInvalidFiles(): - msg = _("There are no DICOM files in the selected folder.") +def ImportInvalidFiles(ftype="DICOM"): + if ftype == "Bitmap": + msg = _("There are no Bitmap, JPEG, PNG or TIFF files in the selected folder.") + else: + msg = _("There are no DICOM files in the selected folder.") + if sys.platform == 'darwin': dlg = wx.MessageDialog(None, "", msg, wx.ICON_INFORMATION | wx.OK) @@ -1700,6 +1704,7 @@ class ImportBitmapParameters(wx.Dialog): def _init_gui(self): + import project as prj p = wx.Panel(self, -1, style = wx.TAB_TRAVERSAL | wx.CLIP_CHILDREN @@ -1732,15 +1737,30 @@ class ImportBitmapParameters(wx.Dialog): stx_spacing_x = stx_spacing_x = wx.StaticText(p, -1, _(u"X:")) fsp_spacing_x = self.fsp_spacing_x = FS.FloatSpin(p, -1, min_val=0,\ - increment=0.25, value=1.0, digits=6) + increment=0.25, value=1.0, digits=8) stx_spacing_y = stx_spacing_y = wx.StaticText(p, -1, _(u"Y:")) fsp_spacing_y = self.fsp_spacing_y = FS.FloatSpin(p, -1, min_val=0,\ - increment=0.25, value=1.0, digits=6) + increment=0.25, value=1.0, digits=8) stx_spacing_z = stx_spacing_z = wx.StaticText(p, -1, _(u"Z:")) fsp_spacing_z = self.fsp_spacing_z = FS.FloatSpin(p, -1, min_val=0,\ - increment=0.25, value=1.0, digits=6) + increment=0.25, value=1.0, digits=8) + + + try: + proj = prj.Project() + + sx = proj.spacing[0] + sy = proj.spacing[1] + sz = proj.spacing[2] + + fsp_spacing_x.SetValue(sx) + fsp_spacing_y.SetValue(sy) + fsp_spacing_z.SetValue(sz) + + except(AttributeError): + pass gbs_spacing.Add(stx_spacing_x, (0,0)) gbs_spacing.Add(fsp_spacing_x, (0,1)) @@ -1783,9 +1803,27 @@ class ImportBitmapParameters(wx.Dialog): self.Close() self.Destroy() - values = [self.tx_name.GetValue(), self.cb_orientation.GetValue().upper(),\ + orient_selection = self.cb_orientation.GetSelection() + + if(orient_selection == 1): + orientation = u"CORONAL" + elif(orient_selection == 2): + orientation = u"SAGITTAL" + else: + orientation = u"AXIAL" + + values = [self.tx_name.GetValue(), orientation,\ self.fsp_spacing_x.GetValue(), self.fsp_spacing_y.GetValue(),\ self.fsp_spacing_z.GetValue(), self.interval] Publisher.sendMessage('Open bitmap files', values) +def BitmapNotSameSize(): + + dlg = wx.MessageDialog(None,_("All bitmaps files must be the same width and height size"), 'Error',\ + wx.OK | wx.ICON_ERROR + #wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION + ) + + dlg.ShowModal() + dlg.Destroy() diff --git a/invesalius/gui/frame.py b/invesalius/gui/frame.py index 162f9af..8dcb72d 100644 --- a/invesalius/gui/frame.py +++ b/invesalius/gui/frame.py @@ -612,7 +612,7 @@ class MenuBar(wx.MenuBar): #Import Others Files others_file_menu = wx.Menu() others_file_menu.Append(const.ID_ANALYZE_IMPORT, "Analyze") - others_file_menu.Append(const.ID_TIFF_JPG_PNG, "TIFF,BMP,JPG or PNG") + others_file_menu.Append(const.ID_TIFF_JPG_PNG, u"TIFF,BMP,JPG or PNG (\xb5CT)") # FILE file_menu = wx.Menu() diff --git a/invesalius/gui/import_bitmap_panel.py b/invesalius/gui/import_bitmap_panel.py index 8942658..99dd4e6 100644 --- a/invesalius/gui/import_bitmap_panel.py +++ b/invesalius/gui/import_bitmap_panel.py @@ -24,7 +24,7 @@ import wx.lib.splitter as spl import constants as const import gui.dialogs as dlg import bitmap_preview_panel as bpp -import reader.dicom_grouper as dcm +import reader.bitmap_reader as bpr from dialogs import ImportBitmapParameters myEVT_SELECT_SERIE = wx.NewEventType() @@ -207,10 +207,14 @@ class TextPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) + self.parent = parent + self._selected_by_user = True self.idserie_treeitem = {} self.treeitem_idpatient = {} + self.selected_item = None + self.__init_gui() self.__bind_events_wx() self.__bind_pubsub_evt() @@ -220,6 +224,7 @@ class TextPanel(wx.Panel): def __bind_events_wx(self): self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyPress) def __init_gui(self): tree = gizmos.TreeListCtrl(self, -1, style = @@ -237,7 +242,6 @@ class TextPanel(wx.Panel): tree.AddColumn(_("Type")) tree.AddColumn(_("Width x Height")) - tree.SetMainColumn(0) tree.SetColumnWidth(0, 880) tree.SetColumnWidth(1, 60) @@ -246,6 +250,33 @@ class TextPanel(wx.Panel): self.root = tree.AddRoot(_("InVesalius Database")) self.tree = tree + def OnKeyPress(self, evt): + key_code = evt.GetKeyCode() + if key_code == wx.WXK_DELETE or key_code == wx.WXK_NUMPAD_DELETE: + if self.selected_item != self.tree.GetRootItem(): + text_item = self.tree.GetItemText(self.selected_item) + + index = bpr.BitmapData().GetIndexByPath(text_item) + + bpr.BitmapData().RemoveFileByPath(text_item) + + data_size = len(bpr.BitmapData().GetData()) + + if index >= 0 and index < data_size: + Publisher.sendMessage('Set bitmap in preview panel', index) + elif index == data_size and data_size > 0: + Publisher.sendMessage('Set bitmap in preview panel', index - 1) + elif data_size == 1: + Publisher.sendMessage('Set bitmap in preview panel', 0) + else: + Publisher.sendMessage('Show black slice in single preview image') + + self.tree.Delete(self.selected_item) + self.tree.Update() + self.tree.Refresh() + Publisher.sendMessage('Remove preview panel', text_item) + evt.Skip() + def SelectSeries(self, pubsub_evt): group_index = pubsub_evt.data @@ -263,27 +294,15 @@ class TextPanel(wx.Panel): Publisher.sendMessage('Load bitmap into import panel', data) - def OnSelChanged(self, evt): item = self.tree.GetSelection() if self._selected_by_user: - group = self.tree.GetItemPyData(item) - if isinstance(group, dcm.DicomGroup): - Publisher.sendMessage('Load group into import panel', - group) - - elif isinstance(group, dcm.PatientGroup): - id = group.GetDicomSample().patient.id - my_evt = SelectEvent(myEVT_SELECT_PATIENT, self.GetId()) - my_evt.SetSelectedID(id) - self.GetEventHandler().ProcessEvent(my_evt) - - Publisher.sendMessage('Load bitmap into import panel', - - group) - else: - parent_id = self.tree.GetItemParent(item) - self.tree.Expand(parent_id) + self.selected_item = item + + text_item = self.tree.GetItemText(self.selected_item) + index = bpr.BitmapData().GetIndexByPath(text_item) + Publisher.sendMessage('Set bitmap in preview panel', index) + evt.Skip() def OnActivate(self, evt): @@ -295,6 +314,7 @@ class TextPanel(wx.Panel): def OnSize(self, evt): self.tree.SetSize(self.GetSize()) + evt.Skip() def SelectSerie(self, serie): self._selected_by_user = False @@ -412,7 +432,6 @@ class SeriesPanel(wx.Panel): def OnSelectSerie(self, evt): data = evt.GetItemData() - my_evt = SelectEvent(myEVT_SELECT_SERIE, self.GetId()) my_evt.SetSelectedID(evt.GetSelectID()) my_evt.SetItemData(evt.GetItemData()) diff --git a/invesalius/reader/bitmap_reader.py b/invesalius/reader/bitmap_reader.py index 207c763..af4a198 100644 --- a/invesalius/reader/bitmap_reader.py +++ b/invesalius/reader/bitmap_reader.py @@ -34,6 +34,7 @@ from scipy import misc import numpy import imghdr +import utils from data import converters #flag to control vtk error in read files @@ -89,7 +90,15 @@ class BitmapData: return size + def RemoveFileByPath(self, path): + for d in self.data: + if path.encode('utf-8') in d: + self.data.remove(d) + def GetIndexByPath(self, path): + for i, v in enumerate(self.data): + if path.encode('utf-8') in v: + return i class BitmapFiles: @@ -100,13 +109,11 @@ class BitmapFiles: self.bitmapfiles.append(bmp) def Sort(self, x): - c_re = re.compile('\d+') - - if len(c_re.findall(x[0])) > 0: - return c_re.findall(x[0])[-1] + if len(c_re.findall(x[6])) > 0: + return [int(i) for i in c_re.findall(x[6])] else: - return '0' + return [str(x[6])] def GetValues(self): bmpfile = self.bitmapfiles @@ -133,6 +140,7 @@ class LoadBitmap: #----- verify extension ------------------ #ex = self.filepath.split('.')[-1] + extension = VerifyDataType(self.filepath) file_name = self.filepath.split(os.path.sep)[-1] @@ -297,7 +305,6 @@ def ScipyRead(filepath): try: r = misc.imread(filepath, flatten=True) dt = r.dtype - if dt == "float" or dt == "float16"\ or dt == "float32" or dt == "float64": shift=-r.max()/2 @@ -355,10 +362,14 @@ def VtkRead(filepath, t): def ReadBitmap(filepath): - t = VerifyDataType(filepath) if t == False: + measures_info = GetPixelSpacingFromInfoFile(filepath) + + if measures_info: + Publisher.sendMessage('Set bitmap spacing', measures_info) + return False img_array = VtkRead(filepath, t) @@ -373,7 +384,54 @@ def ReadBitmap(filepath): return False return img_array - + + +def GetPixelSpacingFromInfoFile(filepath): + + fi = open(filepath, 'r') + lines = fi.readlines() + measure_scale = 'mm' + values = [] + + if len(lines) > 0: + #info text from avizo + if '# Avizo Stacked Slices' in lines[0]: + value = lines[2].split(' ') + spx = float(value[1]) + spy = float(value[2]) + value = lines[5].split(' ') + spz = float(value[1]) + + return [spx * 0.001, spy * 0.001, spz * 0.001] + else: + #info text from skyscan + for l in lines: + if 'Pixel Size' in l: + if 'um' in l: + measure_scale = 'um' + + value = l.split("=")[-1] + values.append(value) + + if len(values) > 0: + value = values[-1] + + value = value.replace('\n','') + value = value.replace('\r','') + + #convert um to mm (InVesalius default) + if measure_scale == 'um': + value = float(value) * 0.001 + measure_scale = 'mm' + + elif measure_scale == 'nm': + value = float(value) * 0.000001 + + return [value, value, value] + else: + return False + else: + return False def VtkErrorToPy(obj, evt): global no_error @@ -383,7 +441,10 @@ def VtkErrorToPy(obj, evt): def VerifyDataType(filepath): try: t = imghdr.what(filepath) - return t + if t: + return t + else: + return False except IOError: return False -- libgit2 0.21.2