diff --git a/invesalius/control.py b/invesalius/control.py index 3bf74bc..a6089df 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -19,12 +19,12 @@ import math import os import plistlib - +import wx import numpy from wx.lib.pubsub import pub as Publisher import constants as const -import data.imagedata_utils as utils +import data.imagedata_utils as image_utils import data.mask as msk import data.measures import data.slice_ as sl @@ -37,7 +37,7 @@ import reader.dicom_grouper as dg import reader.dicom_reader as dcm import session as ses -from utils import debug +import utils DEFAULT_THRESH_MODE = 0 @@ -171,14 +171,14 @@ class Controller(): try: filename = session.project_path[1] except(AttributeError): - debug("Project doesn't exist") + utils.debug("Project doesn't exist") filename = None if (filename): if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE): answer = dialog.SaveChangesDialog(filename, self.frame) if not answer: - debug("Close without changes") + utils.debug("Close without changes") self.CloseProject() Publisher.sendMessage("Enable state project", False) Publisher.sendMessage('Set project name') @@ -186,14 +186,14 @@ class Controller(): Publisher.sendMessage("Exit") elif answer == 1: self.ShowDialogSaveProject() - debug("Save changes and close") + utils.debug("Save changes and close") self.CloseProject() Publisher.sendMessage("Enable state project", False) Publisher.sendMessage('Set project name') Publisher.sendMessage("Stop Config Recording") Publisher.sendMessage("Exit") elif answer == -1: - debug("Cancel") + utils.debug("Cancel") else: self.CloseProject() Publisher.sendMessage("Enable state project", False) @@ -347,7 +347,7 @@ class Controller(): self.CreateAnalyzeProject(imagedata) # OPTION 3: Nothing... else: - debug("No medical images found on given directory") + utils.debug("No medical images found on given directory") return self.LoadProject() Publisher.sendMessage("Enable state project", True) @@ -420,7 +420,7 @@ class Controller(): #TODO: Verify if all Analyse are in AXIAL orientation # To get Z, X, Y (used by InVesaliu), not X, Y, Z - matrix, matrix_filename = utils.analyze2mmap(imagedata) + matrix, matrix_filename = image_utils.analyze2mmap(imagedata) if header['orient'] == 0: proj.original_orientation = const.AXIAL elif header['orient'] == 1: @@ -492,7 +492,7 @@ class Controller(): interval += 1 filelist = dicom_group.GetFilenameList()[::interval] if not filelist: - debug("Not used the IPPSorter") + 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]: @@ -500,9 +500,6 @@ class Controller(): zspacing = dicom_group.zspacing * interval - print "\n=======================================" - print ">>>>>>>>>>>>>>>>>> zspacing", zspacing, interval - print "\n=======================================" size = dicom.image.size bits = dicom.image.bits_allocad sop_class_uid = dicom.acquisition.sop_class_uid @@ -514,16 +511,30 @@ class Controller(): else: use_dcmspacing = 0 - #imagedata = utils.CreateImageData(filelist, zspacing, xyspacing,size, - #bits, use_dcmspacing) - 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() + + 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 = utils.dcm2memmap(filelist, size, - orientation) + self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, + orientation, resolution_percentage) self.Slice = sl.Slice() self.Slice.matrix = self.matrix @@ -543,10 +554,10 @@ class Controller(): message = _("Fix gantry tilt applying the degrees below") value = -1*tilt_value tilt_value = dialog.ShowNumberDialog(message, value) - utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) + image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) elif (tilt_value) and not (gui): tilt_value = -1*tilt_value - utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) + image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value) self.Slice.window_level = wl self.Slice.window_width = ww diff --git a/invesalius/data/imagedata_utils.py b/invesalius/data/imagedata_utils.py index 1dcfb39..bb48376 100644 --- a/invesalius/data/imagedata_utils.py +++ b/invesalius/data/imagedata_utils.py @@ -57,21 +57,19 @@ def ResampleImage3D(imagedata, value): return resample.GetOutput() -def ResampleImage2D(imagedata, px, py, +def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None, update_progress = None): """ Resample vtkImageData matrix. """ + extent = imagedata.GetExtent() spacing = imagedata.GetSpacing() + dimensions = imagedata.GetDimensions() - - #if extent[1]==extent[3]: - # f = extent[1] - #elif extent[1]==extent[5]: - # f = extent[1] - #elif extent[3]==extent[5]: - # f = extent[3] + if resolution_percentage: + px = math.ceil(dimensions[0] * resolution_percentage) + py = math.ceil(dimensions[1] * resolution_percentage) if abs(extent[1]-extent[3]) < abs(extent[3]-extent[5]): f = extent[1] @@ -418,7 +416,7 @@ class ImageCreator: return imagedata -def dcm2memmap(files, slice_size, orientation): +def dcm2memmap(files, slice_size, orientation, resolution_percentage): """ From a list of dicom files it creates memmap file in the temp folder and returns it and its related filename. @@ -429,21 +427,43 @@ def dcm2memmap(files, slice_size, orientation): temp_file = tempfile.mktemp() if orientation == 'SAGITTAL': - shape = slice_size[0], slice_size[1], len(files) + if resolution_percentage == 1.0: + shape = slice_size[0], slice_size[1], len(files) + else: + shape = math.ceil(slice_size[0]*resolution_percentage),\ + math.ceil(slice_size[1]*resolution_percentage), len(files) + elif orientation == 'CORONAL': - shape = slice_size[1], len(files), slice_size[0] + if resolution_percentage == 1.0: + shape = slice_size[1], len(files), slice_size[0] + else: + shape = math.ceil(slice_size[1]*resolution_percentage), len(files),\ + math.ceil(slice_size[0]*resolution_percentage) else: - shape = len(files), slice_size[1], slice_size[0] + if resolution_percentage == 1.0: + shape = len(files), slice_size[1], slice_size[0] + else: + 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) dcm_reader = vtkgdcm.vtkGDCMImageReader() cont = 0 max_scalar = None min_scalar = None + for n, f in enumerate(files): dcm_reader.SetFileName(f) dcm_reader.Update() image = dcm_reader.GetOutput() + if resolution_percentage != 1.0: + image_resized = ResampleImage2D(image, px=None, py=None,\ + resolution_percentage = resolution_percentage, update_progress = None) + + image = image_resized + print ">>>>>>>>>", image.GetDimensions() + min_aux, max_aux = image.GetScalarRange() if min_scalar is None or min_aux < min_scalar: min_scalar = min_aux diff --git a/invesalius/gui/dialogs.py b/invesalius/gui/dialogs.py index 9347c21..d2bd063 100644 --- a/invesalius/gui/dialogs.py +++ b/invesalius/gui/dialogs.py @@ -82,6 +82,65 @@ class NumberDialog(wx.Dialog): def GetValue(self): return self.num_ctrl.GetValue() + +class ResizeImageDialog(wx.Dialog): + + def __init__(self):#, message, value=0): + pre = wx.PreDialog() + pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize, + pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE) + self.PostCreate(pre) + + lbl_message = wx.StaticText(self, -1, _("Your operational system is 32bits or have \nlow memory. It's recommended to reduce the image resolution.")) + + icon = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32,32)) + bmp = wx.StaticBitmap(self, -1, icon) + + btn_ok = wx.Button(self, wx.ID_OK) + btn_ok.SetHelpText("Value will be applied.") + btn_ok.SetDefault() + + btn_cancel = wx.Button(self, wx.ID_CANCEL) + btn_cancel.SetHelpText("Value will not be applied.") + + btn_sizer = wx.StdDialogButtonSizer() + btn_sizer.AddButton(btn_ok) + btn_sizer.AddButton(btn_cancel) + btn_sizer.Realize() + + lbl_message_percent = wx.StaticText(self, -1, _("Resolution percentage")) + + num_ctrl_percent = wx.SpinCtrl(self, -1, "", (30, 50)) + num_ctrl_percent.SetRange(20,100) + self.num_ctrl_porcent = num_ctrl_percent + + sizer_percent = wx.BoxSizer(wx.HORIZONTAL) + sizer_percent.Add(lbl_message_percent, 0, wx.ALIGN_CENTRE|wx.ALL, 5) + sizer_percent.Add(num_ctrl_percent, 0, wx.ALIGN_CENTRE|wx.ALL, 5) + + sizer_itens = wx.BoxSizer(wx.VERTICAL) + sizer_itens.Add(lbl_message, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL|wx.EXPAND, 5) + sizer_itens.AddSizer(sizer_percent, 0, wx.ALIGN_CENTRE|wx.ALL, 5) + sizer_itens.Add(btn_sizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 25) + + sizer_general = wx.BoxSizer(wx.HORIZONTAL) + sizer_general.Add(bmp, 0, wx.ALIGN_CENTRE|wx.ALL, 15) + sizer_general.AddSizer(sizer_itens, 90, wx.ALIGN_CENTRE|wx.ALL, 10) + + self.SetSizer(sizer_general) + sizer_itens.Fit(self) + self.Layout() + self.SetAutoLayout(True) + self.Centre() + + def SetValue(self, value): + self.num_ctrl_porcent.SetValue(value) + + def GetValue(self): + return self.num_ctrl_porcent.GetValue() + + def ShowNumberDialog(message, value=0): dlg = NumberDialog(message, value) dlg.SetValue(value) diff --git a/invesalius/utils.py b/invesalius/utils.py index dd9c40b..d833ed1 100755 --- a/invesalius/utils.py +++ b/invesalius/utils.py @@ -213,7 +213,7 @@ def calculate_resizing_tofitmemory(x_size,y_size,n_slices,byte): n_slices: number of slices byte: bytes allocated for each pixel sample """ - imagesize = x_size * y_size * n_slices * byte + imagesize = x_size * y_size * n_slices * byte * 17 sg = sigar.open() ram_free = sg.mem().actual_free() @@ -221,6 +221,9 @@ def calculate_resizing_tofitmemory(x_size,y_size,n_slices,byte): swap_free = sg.swap().free() sg.close() + print "RAM FREE", ram_free + print "RAM_TOTAL", ram_total + if (sys.platform == 'win32'): if (platform.architecture()[0] == '32bit'): if ram_free>1400000000: @@ -237,14 +240,11 @@ def calculate_resizing_tofitmemory(x_size,y_size,n_slices,byte): if (swap_free>ram_total): swap_free=ram_total - resize = (float((ram_free+0.5*swap_free)/imagesize)) + resize = (float((ram_free+0.5*swap_free)/imagesize)) resize=math.sqrt(resize) # this gives the "resize" for each axis x and y if (resize>1): resize=1 - return (100*resize) - - - + return round(resize,2) def predict_memory(nfiles, x, y, p): -- libgit2 0.21.2