From 696200d161b10c21efdaac01612fc15df181f7ed Mon Sep 17 00:00:00 2001 From: Thiago Franco de Moraes Date: Thu, 26 Apr 2018 15:44:31 -0300 Subject: [PATCH] Python3 and wxPython4 support (also run in Python2 and wxPython3) (#135) --- app.py | 58 ++++++++++++++++++++++++++++++++++++++-------------------- docs/devel/example_singleton_pubsub.py | 2 +- invesalius/constants.py | 8 +++++--- invesalius/control.py | 12 ++++++------ invesalius/data/coordinates.py | 10 +++++----- invesalius/data/cursor_actors.py | 4 ++-- invesalius/data/geometry.py | 14 +++++++------- invesalius/data/imagedata_utils.py | 18 +++++++++--------- invesalius/data/mask.py | 17 ++++++++--------- invesalius/data/measures.py | 9 +++++---- invesalius/data/polydata_utils.py | 8 ++++---- invesalius/data/slice_.py | 18 +++++++++--------- invesalius/data/styles.py | 44 ++++++++++++++++++++------------------------ invesalius/data/surface.py | 20 ++++++++++---------- invesalius/data/surface_process.py | 2 +- invesalius/data/trackers.py | 36 ++++++++++++++++++------------------ invesalius/data/viewer_slice.py | 34 +++++++++++++++++++++++----------- invesalius/data/viewer_volume.py | 10 +++++----- invesalius/data/volume.py | 14 +++++++------- invesalius/data/vtk_utils.py | 5 ++--- invesalius/gui/bitmap_preview_panel.py | 24 +++++++++++++++--------- invesalius/gui/data_notebook.py | 46 ++++++++++++++++++++++++++++++++-------------- invesalius/gui/default_tasks.py | 21 ++++++++++++--------- invesalius/gui/default_viewers.py | 2 +- invesalius/gui/dialogs.py | 460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------ invesalius/gui/dicom_preview_panel.py | 44 +++++++++++++++++++++++++------------------- invesalius/gui/frame.py | 11 +++++++++-- invesalius/gui/import_bitmap_panel.py | 7 ++++--- invesalius/gui/import_network_panel.py | 17 +++++++++-------- invesalius/gui/import_panel.py | 7 ++++--- invesalius/gui/language_dialog.py | 11 +++++++---- invesalius/gui/preferences.py | 14 +++++++++----- invesalius/gui/task_exporter.py | 7 ++++++- invesalius/gui/task_importer.py | 10 +++++++--- invesalius/gui/task_navigator.py | 71 +++++++++++++++++++++++++++++++++++++++++++++-------------------------- invesalius/gui/task_slice.py | 38 ++++++++++++++++++++++++++++---------- invesalius/gui/task_surface.py | 40 +++++++++++++++++++++++++++++----------- invesalius/gui/task_tools.py | 9 +++++++-- invesalius/gui/widgets/clut_imagedata.py | 18 +++++++++++++----- invesalius/gui/widgets/clut_raycasting.py | 34 +++++++++++++++++----------------- invesalius/gui/widgets/gradient.py | 11 +++++++---- invesalius/gui/widgets/listctrl.py | 2 +- invesalius/gui/widgets/slice_menu.py | 10 +++++----- invesalius/i18n.py | 10 +++++++--- invesalius/net/dicom.py | 6 +++--- invesalius/presets.py | 7 ++++--- invesalius/project.py | 24 ++++++++++++------------ invesalius/reader/bitmap_reader.py | 12 ++++++++---- invesalius/reader/dicom.py | 38 ++++++++++++++++++-------------------- invesalius/reader/dicom_grouper.py | 17 ++++++++++------- invesalius/reader/dicom_reader.py | 41 +++++++++++++++++++++-------------------- invesalius/session.py | 17 +++++++++-------- invesalius/style.py | 2 +- invesalius/utils.py | 48 ++++++++++++++++++++++++++++++++++-------------- 54 files changed, 908 insertions(+), 571 deletions(-) diff --git a/app.py b/app.py index 8eaa0f3..ca35bab 100644 --- a/app.py +++ b/app.py @@ -18,6 +18,7 @@ # detalhes. #------------------------------------------------------------------------- +from __future__ import print_function import multiprocessing import optparse as op @@ -30,14 +31,18 @@ import re if sys.platform == 'win32': import _winreg -else: - if sys.platform != 'darwin': - import wxversion - #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True) - #wxversion.select('2.8-unicode', optionsRequired=True) - wxversion.ensureMinimal('3.0') +# else: + # if sys.platform != 'darwin': + # import wxversion + # #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True) + # #wxversion.select('2.8-unicode', optionsRequired=True) + # # wxversion.ensureMinimal('4.0') import wx +try: + from wx.adv import SplashScreen +except ImportError: + from wx import SplashScreen #from wx.lib.pubsub import setupv1 #new wx from wx.lib.pubsub import setuparg1# as psv1 #from wx.lib.pubsub import Publisher @@ -64,9 +69,9 @@ if sys.platform == 'win32': try: USER_DIR = expand_user() except: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = utils.decode(os.path.expanduser('~'), FS_ENCODE) else: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = utils.decode(os.path.expanduser('~'),FS_ENCODE) USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius') USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets') @@ -75,6 +80,15 @@ USER_LOG_DIR = os.path.join(USER_INV_DIR, u'logs') # ------------------------------------------------------------------ +if sys.platform == 'linux2': + try: + tmp_var = wx.GetXDisplay + except AttributeError: + # A workaround to make InVesalius run with wxPython4 from Ubuntu 18.04 + wx.GetXDisplay = lambda: None + else: + del tmp_var + class InVesalius(wx.App): """ @@ -89,7 +103,7 @@ class InVesalius(wx.App): freeze_support() self.SetAppName("InVesalius 3") - self.splash = SplashScreen() + self.splash = Inv3SplashScreen() self.splash.Show() wx.CallLater(1000,self.Startup2) @@ -111,7 +125,7 @@ class InVesalius(wx.App): # ------------------------------------------------------------------ -class SplashScreen(wx.SplashScreen): +class Inv3SplashScreen(SplashScreen): """ Splash screen to be shown in InVesalius initialization. """ @@ -202,16 +216,20 @@ class SplashScreen(wx.SplashScreen): bmp = wx.Image(path).ConvertToBitmap() - style = wx.SPLASH_TIMEOUT | wx.SPLASH_CENTRE_ON_SCREEN - wx.SplashScreen.__init__(self, - bitmap=bmp, - splashStyle=style, - milliseconds=1500, - id=-1, - parent=None) + try: + style = wx.adv.SPLASH_TIMEOUT | wx.adv.SPLASH_CENTRE_ON_SCREEN + except AttributeError: + style = wx.SPLASH_TIMEOUT | wx.SPLASH_CENTRE_ON_SCREEN + + SplashScreen.__init__(self, + bitmap=bmp, + splashStyle=style, + milliseconds=1500, + id=-1, + parent=None) self.Bind(wx.EVT_CLOSE, self.OnClose) wx.Yield() - wx.CallLater(200,self.Startup) + wx.CallLater(200, self.Startup) def Startup(self): # Importing takes sometime, therefore it will be done @@ -349,14 +367,14 @@ def use_cmd_optargs(options, args): else: for arg in reversed(args): - file = arg.decode(FS_ENCODE) + file = utils.decode(arg, FS_ENCODE) if os.path.isfile(file): path = os.path.abspath(file) Publisher.sendMessage('Open project', path) check_for_export(options) return True - file = arg.decode(sys.stdin.encoding) + file = utils.decode(arg, sys.stdin.encoding) if os.path.isfile(file): path = os.path.abspath(file) Publisher.sendMessage('Open project', path) diff --git a/docs/devel/example_singleton_pubsub.py b/docs/devel/example_singleton_pubsub.py index 0dd82f5..c85da55 100644 --- a/docs/devel/example_singleton_pubsub.py +++ b/docs/devel/example_singleton_pubsub.py @@ -52,7 +52,7 @@ p3 = Person("Andre ") people = [p1, p2, p3] print "Everyone eats 2 pieces:" -for i in xrange(2): +for i in range(2): for person in people: person.EatPieceOfPizza() diff --git a/invesalius/constants.py b/invesalius/constants.py index d2d5e69..fe7455f 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -23,6 +23,8 @@ import sys import wx import itertools +from invesalius import utils + #from invesalius.project import Project INVESALIUS_VERSION = "3.1.1" @@ -332,15 +334,15 @@ if sys.platform == 'win32': try: USER_DIR = expand_user() except: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = utils.decode(os.path.expanduser('~'), FS_ENCODE) else: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = utils.decode(os.path.expanduser('~'), FS_ENCODE) USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius') USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets') USER_LOG_DIR = os.path.join(USER_INV_DIR, u'logs') -FILE_PATH = os.path.split(__file__)[0].decode(FS_ENCODE) +FILE_PATH = utils.decode(os.path.split(__file__)[0], FS_ENCODE) if hasattr(sys,"frozen") and (sys.frozen == "windows_exe"\ or sys.frozen == "console_exe"): diff --git a/invesalius/control.py b/invesalius/control.py index a28d22a..1f24b88 100644 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -347,7 +347,7 @@ class Controller(): dirpath, filename = session.project_path if isinstance(filename, str): - filename = filename.decode(const.FS_ENCODE) + filename = utils.decode(filename, const.FS_ENCODE) proj = prj.Project() prj.Project().SavePlistProject(dirpath, filename, compress) @@ -458,7 +458,7 @@ class Controller(): def ImportMedicalImages(self, directory, gui=True): patients_groups = dcm.GetDicomGroups(directory) name = directory.rpartition('\\')[-1].split('.') - print "patients: ", patients_groups + print("patients: ", patients_groups) if len(patients_groups): # OPTION 1: DICOM @@ -760,7 +760,7 @@ class Controller(): Publisher.sendMessage("Enable state project", True) def OnOpenOtherFiles(self, pubsub_evt): - filepath = pubsub_evt.data + filepath = utils.decode(pubsub_evt.data, const.FS_ENCODE) if not(filepath) == None: name = filepath.rpartition('\\')[-1].split('.') @@ -785,7 +785,7 @@ class Controller(): 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]: + if file_range is not None and file_range[0] is not None and file_range[1] > file_range[0]: filelist = filelist[file_range[0]:file_range[1] + 1] zspacing = dicom_group.zspacing * interval @@ -828,7 +828,7 @@ class Controller(): self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, orientation, resolution_percentage) - print xyspacing, zspacing + print(xyspacing, zspacing) if orientation == 'AXIAL': spacing = xyspacing[0], xyspacing[1], zspacing elif orientation == 'CORONAL': @@ -893,7 +893,7 @@ class Controller(): proj = prj.Project() thresh_modes = proj.threshold_modes.keys() - thresh_modes.sort() + thresh_modes = sorted(thresh_modes) default_threshold = const.THRESHOLD_PRESETS_INDEX if proj.mask_dict: keys = proj.mask_dict.keys() diff --git a/invesalius/data/coordinates.py b/invesalius/data/coordinates.py index 13aaa83..6a218f7 100644 --- a/invesalius/data/coordinates.py +++ b/invesalius/data/coordinates.py @@ -47,7 +47,7 @@ def GetCoordinates(trck_init, trck_id, ref_mode): 5: DebugCoord} coord = getcoord[trck_id](trck_init, trck_id, ref_mode) else: - print "Select Tracker" + print("Select Tracker") return coord @@ -70,7 +70,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode): k = 30 except AttributeError: k += 1 - print "wait, collecting coordinates ..." + print("wait, collecting coordinates ...") if k == 30: coord = dynamic_reference(probe, reference) coord = (coord[0] * scale[0], coord[1] * scale[1], coord[2] * scale[2], coord[3], coord[4], coord[5]) @@ -84,7 +84,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode): k = 30 except AttributeError: k += 1 - print "wait, collecting coordinates ..." + print("wait, collecting coordinates ...") Publisher.sendMessage('Sensors ID', [trck.probeID, trck.refID]) @@ -180,7 +180,7 @@ def PolhemusSerialCoord(trck_init, trck_id, ref_mode): coord = None if lines[0][0] != '0': - print "The Polhemus is not connected!" + print("The Polhemus is not connected!") else: for s in lines: if s[1] == '1': @@ -198,7 +198,7 @@ def PolhemusSerialCoord(trck_init, trck_id, ref_mode): plh1 = [float(s) for s in data[1:len(data)]] j = 1 except: - print "error!!" + print("error!!") coord = data[0:6] return coord diff --git a/invesalius/data/cursor_actors.py b/invesalius/data/cursor_actors.py index a83635a..8e48dda 100644 --- a/invesalius/data/cursor_actors.py +++ b/invesalius/data/cursor_actors.py @@ -205,7 +205,7 @@ class CursorBase(object): def _set_colour(self, imagedata, colour): scalar_range = int(imagedata.GetScalarRange()[1]) - r, g, b = colour + r, g, b = colour[:3] # map scalar values into colors lut_mask = vtk.vtkLookupTable() @@ -319,7 +319,7 @@ class CursorRectangle(CursorBase): """ Function to plot the Retangle """ - print "Building rectangle cursor", self.orientation + print("Building rectangle cursor", self.orientation) r = self.radius sx, sy, sz = self.spacing if self.orientation == 'AXIAL': diff --git a/invesalius/data/geometry.py b/invesalius/data/geometry.py index ca5006a..b8e757a 100644 --- a/invesalius/data/geometry.py +++ b/invesalius/data/geometry.py @@ -18,6 +18,8 @@ # detalhes. #-------------------------------------------------------------------------- +from six import with_metaclass + import numpy as np import math import vtk @@ -27,14 +29,12 @@ import invesalius.utils as utils import invesalius.constants as const -class Box(object): +class Box(with_metaclass(utils.Singleton, object)): """ - This class is a data structure for storing the + This class is a data structure for storing the coordinates (min and max) of box used in crop-mask. """ - __metaclass__= utils.Singleton - def __init__(self): self.xi = None self.xf = None @@ -356,7 +356,7 @@ class DrawCrop2DRetangle(): x_pos_sl = x_pos_sl_ * xs y_pos_sl = y_pos_sl_ * ys - for k, p in self.box.axial.iteritems(): + for k, p in self.box.axial.items(): p0 = p[0] p1 = p[1] @@ -386,7 +386,7 @@ class DrawCrop2DRetangle(): x_pos_sl = x_pos_sl_ * xs y_pos_sl = y_pos_sl_ * zs - for k, p in self.box.coronal.iteritems(): + for k, p in self.box.coronal.items(): p0 = p[0] p1 = p[1] @@ -415,7 +415,7 @@ class DrawCrop2DRetangle(): x_pos_sl = x_pos_sl_ * ys y_pos_sl = y_pos_sl_ * zs - for k, p in self.box.sagital.iteritems(): + for k, p in self.box.sagital.items(): p0 = p[0] p1 = p[1] diff --git a/invesalius/data/imagedata_utils.py b/invesalius/data/imagedata_utils.py index 645badb..2a65379 100644 --- a/invesalius/data/imagedata_utils.py +++ b/invesalius/data/imagedata_utils.py @@ -265,7 +265,7 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): def create_dicom_thumbnails(filename, window=None, level=None): rvtk = vtkgdcm.vtkGDCMImageReader() - rvtk.SetFileName(filename) + rvtk.SetFileName(utils.encode(filename, const.FS_ENCODE)) rvtk.Update() img = rvtk.GetOutput() @@ -278,7 +278,7 @@ def create_dicom_thumbnails(filename, window=None, level=None): if dz > 1: thumbnail_paths = [] - for i in xrange(dz): + for i in range(dz): img_slice = ExtractVOI(img, 0, dx-1, 0, dy-1, i, i+1) colorer = vtk.vtkImageMapToWindowLevelColors() @@ -355,7 +355,7 @@ def CreateImageData(filelist, zspacing, xyspacing,size, update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog") array = vtk.vtkStringArray() - for x in xrange(len(filelist)): + for x in range(len(filelist)): array.InsertValue(x,filelist[x]) reader = vtkgdcm.vtkGDCMImageReader() @@ -385,7 +385,7 @@ def CreateImageData(filelist, zspacing, xyspacing,size, # Reformat each slice - for x in xrange(len(filelist)): + for x in range(len(filelist)): # TODO: We need to check this automatically according # to each computer's architecture # If the resolution of the matrix is too large @@ -459,7 +459,7 @@ class ImageCreator: update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog") array = vtk.vtkStringArray() - for x in xrange(len(filelist)): + for x in range(len(filelist)): if not self.running: return False array.InsertValue(x,filelist[x]) @@ -491,7 +491,7 @@ class ImageCreator: # Reformat each slice - for x in xrange(len(filelist)): + for x in range(len(filelist)): # TODO: We need to check this automatically according # to each computer's architecture # If the resolution of the matrix is too large @@ -683,11 +683,11 @@ def dcmmf2memmap(dcm_file, orientation): d.shape = z, y, x if orientation == 'CORONAL': matrix.shape = y, z, x - for n in xrange(z): + for n in range(z): matrix[:, n, :] = d[n] elif orientation == 'SAGITTAL': matrix.shape = x, z, y - for n in xrange(z): + for n in range(z): matrix[:, :, n] = d[n] else: matrix[:] = d @@ -695,7 +695,7 @@ def dcmmf2memmap(dcm_file, orientation): matrix.flush() scalar_range = matrix.min(), matrix.max() - print "ORIENTATION", orientation + print("ORIENTATION", orientation) return matrix, spacing, scalar_range, temp_file diff --git a/invesalius/data/mask.py b/invesalius/data/mask.py index b636061..ab39610 100644 --- a/invesalius/data/mask.py +++ b/invesalius/data/mask.py @@ -46,7 +46,7 @@ class EditionHistoryNode(object): def _save_array(self, array): np.save(self.filename, array) - print "Saving history", self.index, self.orientation, self.filename, self.clean + print("Saving history", self.index, self.orientation, self.filename, self.clean) def commit_history(self, mvolume): array = np.load(self.filename) @@ -65,10 +65,10 @@ class EditionHistoryNode(object): elif self.orientation == 'VOLUME': mvolume[:] = array - print "applying to", self.orientation, "at slice", self.index + print("applying to", self.orientation, "at slice", self.index) def __del__(self): - print "Removing", self.filename + print("Removing", self.filename) os.remove(self.filename) @@ -99,7 +99,7 @@ class EditionHistory(object): self.history.append(node) self.index += 1 - print "INDEX", self.index, len(self.history), self.history + print("INDEX", self.index, len(self.history), self.history) Publisher.sendMessage("Enable undo", True) Publisher.sendMessage("Enable redo", False) @@ -128,7 +128,7 @@ class EditionHistory(object): if self.index == 0: Publisher.sendMessage("Enable undo", False) - print "AT", self.index, len(self.history), self.history[self.index].filename + print("AT", self.index, len(self.history), self.history[self.index].filename) def redo(self, mvolume, actual_slices=None): h = self.history @@ -156,7 +156,7 @@ class EditionHistory(object): if self.index == len(h) - 1: Publisher.sendMessage("Enable redo", False) - print "AT", self.index, len(h), h[self.index].filename + print("AT", self.index, len(h), h[self.index].filename) def _reload_slice(self, index): Publisher.sendMessage(('Set scroll position', self.history[index].orientation), @@ -236,7 +236,7 @@ class Mask(): mask['index'] = self.index mask['name'] = self.name - mask['colour'] = self.colour + mask['colour'] = self.colour[:3] mask['opacity'] = self.opacity mask['threshold_range'] = self.threshold_range mask['edition_threshold_range'] = self.edition_threshold_range @@ -289,13 +289,12 @@ class Mask(): def OnSwapVolumeAxes(self, pubsub_evt): axis0, axis1 = pubsub_evt.data self.matrix = self.matrix.swapaxes(axis0, axis1) - print type(self.matrix) def _save_mask(self, filename): shutil.copyfile(self.temp_file, filename) def _open_mask(self, filename, shape, dtype='uint8'): - print ">>", filename, shape + print(">>", filename, shape) self.temp_file = filename self.matrix = np.memmap(filename, shape=shape, dtype=dtype, mode="r+") diff --git a/invesalius/data/measures.py b/invesalius/data/measures.py index b36a52b..5cb6fd4 100644 --- a/invesalius/data/measures.py +++ b/invesalius/data/measures.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- +from six import with_metaclass + import math import random import sys @@ -46,11 +48,10 @@ else: MEASURE_TEXT_COLOUR = (0, 0, 0) MEASURE_TEXTBOX_COLOUR = (255, 255, 165, 255) -class MeasureData: +class MeasureData(with_metaclass(utils.Singleton)): """ Responsible to keep measures data. """ - __metaclass__= utils.Singleton def __init__(self): self.measures = {const.SURFACE: {}, const.AXIAL: {}, @@ -358,7 +359,7 @@ class Measurement(): Measurement.general_index += 1 self.index = Measurement.general_index self.name = const.MEASURE_NAME_PATTERN %(self.index+1) - self.colour = const.MEASURE_COLOUR.next() + self.colour = next(const.MEASURE_COLOUR) self.value = 0 self.location = const.SURFACE # AXIAL, CORONAL, SAGITTAL self.type = const.LINEAR # ANGULAR @@ -832,7 +833,7 @@ class AngularMeasure(object): for p in self.points: coord.SetValue(p) cx, cy = coord.GetComputedDoubleDisplayValue(canvas.evt_renderer) - print cx, cy + print(cx, cy) # canvas.draw_circle((cx, cy), 2.5) points.append((cx, cy)) diff --git a/invesalius/data/polydata_utils.py b/invesalius/data/polydata_utils.py index 45ce644..36830b9 100644 --- a/invesalius/data/polydata_utils.py +++ b/invesalius/data/polydata_utils.py @@ -78,7 +78,7 @@ def FillSurfaceHole(polydata): Fill holes in the given polydata. """ # Filter used to detect and fill holes. Only fill - print "Filling polydata" + print("Filling polydata") filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(500) @@ -133,9 +133,9 @@ def Export(polydata, filename, bin=False): def Import(filename): reader = vtk.vtkXMLPolyDataReader() - if isinstance(filename, unicode): + try: reader.SetFileName(filename.encode(wx.GetDefaultPyEncoding())) - else: + except AttributeError: reader.SetFileName(filename) reader.Update() return reader.GetOutput() @@ -198,7 +198,7 @@ def SplitDisconectedParts(polydata): if progress: UpdateProgress = vu.ShowProgress(progress) - for region in xrange(nregions): + for region in range(nregions): conn.InitializeSpecifiedRegionList() conn.AddSpecifiedRegion(region) conn.Update() diff --git a/invesalius/data/slice_.py b/invesalius/data/slice_.py index 970b11f..ecad5fe 100644 --- a/invesalius/data/slice_.py +++ b/invesalius/data/slice_.py @@ -16,6 +16,8 @@ # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais # detalhes. #-------------------------------------------------------------------------- +from six import with_metaclass + import os import tempfile @@ -72,12 +74,10 @@ class SliceBuffer(object): self.vtk_mask = None -class Slice(object): - __metaclass__= utils.Singleton - # Only one slice will be initialized per time (despite several viewers - # show it from distinct perspectives). - # Therefore, we use Singleton design pattern for implementing it. - +# Only one slice will be initialized per time (despite several viewers +# show it from distinct perspectives). +# Therefore, we use Singleton design pattern for implementing it. +class Slice(with_metaclass(utils.Singleton, object)): def __init__(self): self.current_mask = None self.blend_filter = None @@ -841,7 +841,7 @@ class Slice(object): proj = Project() proj.mask_dict[index].colour = colour - (r,g,b) = colour + (r,g,b) = colour[:3] colour_wx = [r*255, g*255, b*255] Publisher.sendMessage('Change mask colour in notebook', (index, (r,g,b))) @@ -1230,7 +1230,7 @@ class Slice(object): """ if mask is None: mask = self.current_mask - for n in xrange(1, mask.matrix.shape[0]): + for n in range(1, mask.matrix.shape[0]): if mask.matrix[n, 0, 0] == 0: m = mask.matrix[n, 1:, 1:] mask.matrix[n, 1:, 1:] = self.do_threshold_to_a_slice(self.matrix[n-1], m, mask.threshold_range) @@ -1260,7 +1260,7 @@ class Slice(object): def do_colour_mask(self, imagedata, opacity): scalar_range = int(imagedata.GetScalarRange()[1]) - r, g, b = self.current_mask.colour + r, g, b = self.current_mask.colour[:3] # map scalar values into colors lut_mask = vtk.vtkLookupTable() diff --git a/invesalius/data/styles.py b/invesalius/data/styles.py index 1680a9a..bb69e4d 100644 --- a/invesalius/data/styles.py +++ b/invesalius/data/styles.py @@ -17,6 +17,8 @@ # detalhes. #-------------------------------------------------------------------------- +from six import with_metaclass + import os import multiprocessing import tempfile @@ -226,7 +228,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): def OnCrossMove(self, obj, evt): # The user moved the mouse with left button pressed if self.left_pressed: - print "OnCrossMove interactor style" + print("OnCrossMove interactor style") iren = obj.GetInteractor() self.ChangeCrossPosition(iren) @@ -716,8 +718,7 @@ class ChangeSliceInteractorStyle(DefaultInteractorStyle): self.last_position = position[1] -class EditorConfig(object): - __metaclass__= utils.Singleton +class EditorConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.operation = const.BRUSH_THRESH self.cursor_type = const.BRUSH_CIRCLE @@ -759,7 +760,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): def SetUp(self): x, y = self.viewer.interactor.ScreenToClient(wx.GetMousePosition()) - if self.viewer.interactor.HitTestXY(x, y) == wx.HT_WINDOW_INSIDE: + if self.viewer.interactor.HitTest((x, y)) == wx.HT_WINDOW_INSIDE: self.viewer.slice_data.cursor.Show() y = self.viewer.interactor.GetSize()[1] - y @@ -985,8 +986,7 @@ class WatershedProgressWindow(object): self.dlg.Destroy() -class WatershedConfig(object): - __metaclass__= utils.Singleton +class WatershedConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.algorithm = "Watershed" self.con_2d = 4 @@ -1069,7 +1069,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): self.viewer.OnScrollBar() x, y = self.viewer.interactor.ScreenToClient(wx.GetMousePosition()) - if self.viewer.interactor.HitTestXY(x, y) == wx.HT_WINDOW_INSIDE: + if self.viewer.interactor.HitTest((x, y)) == wx.HT_WINDOW_INSIDE: self.viewer.slice_data.cursor.Show() y = self.viewer.interactor.GetSize()[1] - y @@ -1104,7 +1104,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): if self.matrix is not None: self.matrix = None os.remove(self.temp_file) - print "deleting", self.temp_file + print("deleting", self.temp_file) def _set_cursor(self): if self.config.cursor_type == const.BRUSH_SQUARE: @@ -1249,7 +1249,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): position = self.viewer.get_slice_pixel_coord_by_world_pos(*coord) radius = cursor.radius - if position < 0: + if isinstance(position, int) and position < 0: position = viewer.calculate_matrix_position(coord) operation = self.config.operation @@ -1455,7 +1455,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): del wp w_x, w_y = wx.GetMousePosition() - x, y = self.viewer.ScreenToClientXY(w_x, w_y) + x, y = self.viewer.ScreenToClient((w_x, w_y)) flag = self.viewer.interactor.HitTest((x, y)) if flag == wx.HT_WINDOW_INSIDE: @@ -1767,8 +1767,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): buffer_.discard_image() -class FFillConfig(object): - __metaclass__= utils.Singleton +class FFillConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.dlg_visible = False self.target = "2D" @@ -1904,8 +1903,7 @@ class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle): self._progr_title = _(u"Remove part") self._progr_msg = _(u"Removing part ...") -class CropMaskConfig(object): - __metaclass__= utils.Singleton +class CropMaskConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.dlg_visible = False @@ -2007,8 +2005,7 @@ class CropMaskInteractorStyle(DefaultInteractorStyle): Publisher.sendMessage('Reload actual slice') -class SelectPartConfig(object): - __metaclass__= utils.Singleton +class SelectPartConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.mask = None self.con_3d = 6 @@ -2114,8 +2111,7 @@ class SelectMaskPartsInteractorStyle(DefaultInteractorStyle): self.config.mask = mask -class FFillSegmentationConfig(object): - __metaclass__= utils.Singleton +class FFillSegmentationConfig(with_metaclass(utils.Singleton, object)): def __init__(self): self.dlg_visible = False self.target = "2D" @@ -2225,7 +2221,7 @@ class FloodFillSegmentInteractorStyle(DefaultInteractorStyle): elif self.config.method == 'dynamic': if self.config.use_ww_wl: - print "Using WW&WL" + print("Using WW&WL") ww = self.viewer.slice_.window_width wl = self.viewer.slice_.window_level image = get_LUT_value_255(image, ww, wl) @@ -2282,7 +2278,7 @@ class FloodFillSegmentInteractorStyle(DefaultInteractorStyle): elif self.config.method == 'dynamic': if self.config.use_ww_wl: - print "Using WW&WL" + print("Using WW&WL") ww = self.viewer.slice_.window_width wl = self.viewer.slice_.window_level image = get_LUT_value_255(image, ww, wl) @@ -2335,18 +2331,18 @@ class FloodFillSegmentInteractorStyle(DefaultInteractorStyle): bool_mask = np.zeros_like(mask, dtype='bool') out_mask = np.zeros_like(mask) - for k in xrange(int(z-1), int(z+2)): + for k in range(int(z-1), int(z+2)): if k < 0 or k >= bool_mask.shape[0]: continue - for j in xrange(int(y-1), int(y+2)): + for j in range(int(y-1), int(y+2)): if j < 0 or j >= bool_mask.shape[1]: continue - for i in xrange(int(x-1), int(x+2)): + for i in range(int(x-1), int(x+2)): if i < 0 or i >= bool_mask.shape[2]: continue bool_mask[k, j, i] = True - for i in xrange(self.config.confid_iters): + for i in range(self.config.confid_iters): var = np.std(image[bool_mask]) mean = np.mean(image[bool_mask]) diff --git a/invesalius/data/surface.py b/invesalius/data/surface.py index 615bf2c..0ab79af 100644 --- a/invesalius/data/surface.py +++ b/invesalius/data/surface.py @@ -90,7 +90,7 @@ class Surface(): filelist[vtp_filepath] = vtp_filename - surface = {'colour': self.colour, + surface = {'colour': self.colour[:3], 'index': self.index, 'name': self.name, 'polydata': vtp_filename, @@ -361,7 +361,7 @@ class SurfaceManager(): area = measured_polydata.GetSurfaceArea() surface.volume = volume surface.area = area - print ">>>>", surface.volume + print(">>>>", surface.volume) else: surface.volume = volume surface.area = area @@ -430,7 +430,7 @@ class SurfaceManager(): actor.SetMapper(mapper) # Set actor colour and transparency - actor.GetProperty().SetColor(surface.colour) + actor.GetProperty().SetColor(surface.colour[:3]) actor.GetProperty().SetOpacity(1-surface.transparency) self.actors_dict[surface.index] = actor @@ -471,7 +471,7 @@ class SurfaceManager(): mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range - colour = mask.colour + colour = mask.colour[:3] try: overwrite = surface_parameters['options']['overwrite'] @@ -521,7 +521,7 @@ class SurfaceManager(): q_out = multiprocessing.Queue() p = [] - for i in xrange(n_processors): + for i in range(n_processors): sp = surface_process.SurfaceProcess(pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, @@ -539,12 +539,12 @@ class SurfaceManager(): p.append(sp) sp.start() - for i in xrange(n_pieces): + for i in range(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) - print "new_piece", roi + print("new_piece", roi) for i in p: q_in.put(None) @@ -664,7 +664,7 @@ class SurfaceManager(): if decimate_reduction: - print "Decimating", decimate_reduction + print("Decimating", decimate_reduction) decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) @@ -902,7 +902,7 @@ class SurfaceManager(): """ """ index, colour = pubsub_evt.data - self.actors_dict[index].GetProperty().SetColor(colour) + self.actors_dict[index].GetProperty().SetColor(colour[:3]) # Update value in project's surface_dict proj = prj.Project() proj.surface_dict[index].colour = colour @@ -925,7 +925,7 @@ class SurfaceManager(): temp_file = win32api.GetShortPathName(temp_file) os.remove(_temp_file) - temp_file = temp_file.decode(const.FS_ENCODE) + temp_file = utl.decode(temp_file, const.FS_ENCODE) self._export_surface(temp_file, filetype) shutil.move(temp_file, filename) diff --git a/invesalius/data/surface_process.py b/invesalius/data/surface_process.py index aa4e5cb..1f325ea 100644 --- a/invesalius/data/surface_process.py +++ b/invesalius/data/surface_process.py @@ -206,7 +206,7 @@ class SurfaceProcess(multiprocessing.Process): writer.SetFileName(filename) writer.Write() - print "Writing piece", roi, "to", filename + print("Writing piece", roi, "to", filename) del polydata del writer diff --git a/invesalius/data/trackers.py b/invesalius/data/trackers.py index fdd1d43..5d355e5 100644 --- a/invesalius/data/trackers.py +++ b/invesalius/data/trackers.py @@ -50,10 +50,10 @@ def DefaultTracker(tracker_id): trck_init = None try: # import spatial tracker library - print 'Connect to default tracking device.' + print('Connect to default tracking device.') except: - print 'Could not connect to default tracker.' + print('Could not connect to default tracker.') # return tracker initialization variable and type of connection return trck_init, 'wrapper' @@ -78,13 +78,13 @@ def ClaronTracker(tracker_id): if trck_init.GetIdentifyingCamera(): trck_init.Run() - print "MicronTracker camera identified." + print("MicronTracker camera identified.") else: trck_init = None except ImportError: lib_mode = 'error' - print 'The ClaronTracker library is not installed.' + print('The ClaronTracker library is not installed.') return trck_init, lib_mode @@ -94,24 +94,24 @@ def PolhemusTracker(tracker_id): trck_init = PlhWrapperConnection(tracker_id) lib_mode = 'wrapper' if not trck_init: - print 'Could not connect with Polhemus wrapper, trying USB connection...' + print('Could not connect with Polhemus wrapper, trying USB connection...') trck_init = PlhUSBConnection(tracker_id) lib_mode = 'usb' if not trck_init: - print 'Could not connect with Polhemus USB, trying serial connection...' + print('Could not connect with Polhemus USB, trying serial connection...') trck_init = PlhSerialConnection(tracker_id) lib_mode = 'serial' except: trck_init = None lib_mode = 'error' - print 'Could not connect to Polhemus.' + print('Could not connect to Polhemus.') return trck_init, lib_mode def DebugTracker(tracker_id): trck_init = True - print 'Debug device started.' + print('Debug device started.') return trck_init, 'debug' @@ -134,10 +134,10 @@ def PlhWrapperConnection(tracker_id): sleep(0.175) else: trck_init = None - print 'Could not connect to Polhemus via wrapper without error.' + print('Could not connect to Polhemus via wrapper without error.') except: trck_init = None - print 'Could not connect to Polhemus via wrapper with error.' + print('Could not connect to Polhemus via wrapper with error.') return trck_init @@ -163,11 +163,11 @@ def PlhSerialConnection(tracker_id): if not data: trck_init = None - print 'Could not connect to Polhemus serial without error.' + print('Could not connect to Polhemus serial without error.') except: trck_init = None - print 'Could not connect to Polhemus serial with error.' + print('Could not connect to Polhemus serial with error.') return trck_init @@ -198,10 +198,10 @@ def PlhUSBConnection(tracker_id): endpoint.wMaxPacketSize) if not data: trck_init = None - print 'Could not connect to Polhemus USB without error.' + print('Could not connect to Polhemus USB without error.') except: - print 'Could not connect to Polhemus USB with error.' + print('Could not connect to Polhemus USB with error.') return trck_init @@ -217,16 +217,16 @@ def DisconnectTracker(tracker_id, trck_init): if tracker_id == 5: trck_init = False lib_mode = 'debug' - print 'Debug tracker disconnected.' + print('Debug tracker disconnected.') else: try: trck_init.Close() trck_init = False lib_mode = 'wrapper' - print 'Tracker disconnected.' + print('Tracker disconnected.') except: trck_init = True lib_mode = 'error' - print 'The tracker could not be disconnected.' + print('The tracker could not be disconnected.') - return trck_init, lib_mode \ No newline at end of file + return trck_init, lib_mode diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index 1b42da3..3dba70c 100755 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -105,10 +105,16 @@ class ContourMIPConfig(wx.Panel): sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(txt_mip_size, 0, wx.EXPAND | wx.ALL, 2) sizer.Add(self.mip_size_spin, 0, wx.EXPAND) - sizer.AddSpacer((10, 0)) + try: + sizer.Add(10, 0) + except TypeError: + sizer.Add((10, 0)) sizer.Add(self.txt_mip_border, 0, wx.EXPAND | wx.ALL, 2) sizer.Add(self.border_spin, 0, wx.EXPAND) - sizer.AddSpacer((10, 0)) + try: + sizer.Add(10, 0) + except TypeError: + sizer.Add((10, 0)) sizer.Add(self.inverted, 0, wx.EXPAND) self.SetSizer(sizer) sizer.Fit(self) @@ -206,7 +212,10 @@ class CanvasRendererCTX: self.alpha = np.zeros((h, w, 1), dtype=np.uint8) self.bitmap = wx.EmptyBitmapRGBA(w, h) - self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) + try: + self.image = wx.Image(w, h, self.rgb, self.alpha) + except TypeError: + self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) def _resize_canvas(self, w, h): self._array = np.zeros((h, w, 4), dtype=np.uint8) @@ -218,7 +227,10 @@ class CanvasRendererCTX: self.alpha = np.zeros((h, w, 1), dtype=np.uint8) self.bitmap = wx.EmptyBitmapRGBA(w, h) - self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) + try: + self.image = wx.Image(w, h, self.rgb, self.alpha) + except TypeError: + self.image = wx.ImageFromBuffer(w, h, self.rgb, self.alpha) self.modified = True @@ -325,7 +337,7 @@ class CanvasRendererCTX: p0y = -p0y p1y = -p1y - pen = wx.Pen(wx.Colour(*colour), width, wx.SOLID) + pen = wx.Pen(wx.Colour(*[int(c) for c in colour]), width, wx.SOLID) pen.SetCap(wx.CAP_BUTT) gc.SetPen(pen) @@ -496,7 +508,7 @@ class CanvasRendererCTX: if self.gc is None: return None gc = self.gc - pen = wx.Pen(wx.Colour(*line_colour), width, wx.SOLID) + pen = wx.Pen(wx.Colour(*[int(c) for c in line_colour]), width, wx.SOLID) gc.SetPen(pen) c = np.array(center) @@ -521,7 +533,7 @@ class CanvasRendererCTX: ea = a0 path = gc.CreatePath() - path.AddArc((c[0], c[1]), min(s0, s1), sa, ea) + path.AddArc(float(c[0]), float(c[1]), float(min(s0, s1)), float(sa), float(ea), True) gc.StrokePath(path) self._drawn = True @@ -600,7 +612,7 @@ class Viewer(wx.Panel): sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) background_sizer = wx.BoxSizer(wx.VERTICAL) - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + background_sizer.Add(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) #background_sizer.Add(self.mip_ctrls, 0, wx.EXPAND|wx.GROW|wx.ALL, 2) self.SetSizer(background_sizer) background_sizer.Fit(self) @@ -1382,7 +1394,7 @@ class Viewer(wx.Panel): number_renderers = self.layout[0] * self.layout[1] diff = number_renderers - len(self.slice_data_list) if diff > 0: - for i in xrange(diff): + for i in range(diff): slice_data = self.create_slice_window(imagedata) self.slice_data_list.append(slice_data) elif diff < 0: @@ -1400,8 +1412,8 @@ class Viewer(wx.Panel): w *= proportion_x h *= proportion_y n = 0 - for j in xrange(self.layout[1]-1, -1, -1): - for i in xrange(self.layout[0]): + for j in range(self.layout[1]-1, -1, -1): + for i in range(self.layout[0]): slice_xi = i*proportion_x slice_xf = (i+1)*proportion_x slice_yi = j*proportion_y diff --git a/invesalius/data/viewer_volume.py b/invesalius/data/viewer_volume.py index 4404225..d238341 100755 --- a/invesalius/data/viewer_volume.py +++ b/invesalius/data/viewer_volume.py @@ -507,7 +507,7 @@ class Viewer(wx.Panel): """ self.ball_id = pubsub_evt.data[0] ballsize = pubsub_evt.data[1] - ballcolour = pubsub_evt.data[2] + ballcolour = pubsub_evt.data[2][:3] coord = pubsub_evt.data[3] x, y, z = bases.flip_x(coord) @@ -1124,7 +1124,7 @@ class Viewer(wx.Panel): """ Coil for navigation rendered in volume viewer. """ - + filename = utils.decode(filename, const.FS_ENCODE) if filename: if filename.lower().endswith('.stl'): reader = vtk.vtkSTLReader() @@ -1451,9 +1451,9 @@ class Viewer(wx.Panel): if _has_win32api: utils.touch(filename) win_filename = win32api.GetShortPathName(filename) - self._export_surface(win_filename.encode(const.FS_ENCODE), filetype) + self._export_surface(win_filename, filetype) else: - self._export_surface(filename.encode(const.FS_ENCODE), filetype) + self._export_surface(filename, filetype) def _export_surface(self, filename, filetype): fileprefix = filename.split(".")[-2] @@ -1526,7 +1526,7 @@ class Viewer(wx.Panel): def ChangeBackgroundColour(self, pubsub_evt): colour = pubsub_evt.data - self.ren.SetBackground(colour) + self.ren.SetBackground(colour[:3]) self.UpdateRender() def LoadActor(self, pubsub_evt): diff --git a/invesalius/data/volume.py b/invesalius/data/volume.py index b2bf98e..31d2955 100644 --- a/invesalius/data/volume.py +++ b/invesalius/data/volume.py @@ -161,22 +161,22 @@ class Volume(): self.LoadVolume() def OnHideVolume(self, pubsub_evt): - print 'Hide Volume' + print('Hide Volume') self.volume.SetVisibility(0) if (self.plane and self.plane_on): self.plane.Disable() Publisher.sendMessage('Render volume viewer') def OnShowVolume(self, pubsub_evt = None): - print 'Show volume' + print('Show volume') if self.exist: - print 'Volume exists' + print('Volume exists') self.volume.SetVisibility(1) if (self.plane and self.plane_on): self.plane.Enable() Publisher.sendMessage('Render volume viewer') else: - print 'Volume doesnt exit' + print('Volume doesnt exit') Publisher.sendMessage('Load raycasting preset', const.RAYCASTING_LABEL) self.LoadConfig() self.LoadVolume() @@ -222,7 +222,7 @@ class Volume(): Publisher.sendMessage('Render volume viewer') def OnFlipVolume(self, pubsub_evt): - print "Flipping Volume" + print("Flipping Volume") self.loaded_image = False del self.image self.image = None @@ -360,10 +360,10 @@ class Volume(): r = p['Red'] g = p['Green'] b = p['Blue'] - colors = zip(r,g,b) + colors = list(zip(r,g,b)) else: # Grayscale from black to white - colors = [(i, i, i) for i in xrange(256)] + colors = [(i, i, i) for i in range(256)] ww = self.config['ww'] wl = self.TranslateScale(scale, self.config['wl']) diff --git a/invesalius/data/vtk_utils.py b/invesalius/data/vtk_utils.py index a6c2e53..736f131 100644 --- a/invesalius/data/vtk_utils.py +++ b/invesalius/data/vtk_utils.py @@ -140,11 +140,10 @@ class Text(object): # With some encoding in some dicom fields (like name) raises a # UnicodeEncodeError because they have non-ascii characters. To avoid # that we encode in utf-8. - - if sys.platform == 'win32': + if sys.platform == 'win32': self.mapper.SetInput(value.encode("utf-8")) else: - try: + try: self.mapper.SetInput(value.encode("latin-1")) except(UnicodeEncodeError): self.mapper.SetInput(value.encode("utf-8")) diff --git a/invesalius/gui/bitmap_preview_panel.py b/invesalius/gui/bitmap_preview_panel.py index 18f0c9a..13306a7 100644 --- a/invesalius/gui/bitmap_preview_panel.py +++ b/invesalius/gui/bitmap_preview_panel.py @@ -218,7 +218,10 @@ class Preview(wx.Panel): def OnEnter(self, evt): if not self.select_on: - c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) + try: + c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE) + except AttributeError: + c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) self.SetBackgroundColour(c) def OnLeave(self, evt): @@ -257,7 +260,10 @@ class Preview(wx.Panel): def Select(self, on=True): if self.select_on: - c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) + try: + c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) + except AttributeError: + c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) else: c = (PREVIEW_BACKGROUND) self.SetBackgroundColour(c) @@ -291,10 +297,10 @@ class BitmapPreviewSeries(wx.Panel): self.grid = wx.GridSizer(rows=NROWS, cols=NCOLS, vgap=3, hgap=3) sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.AddSizer(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + sizer.Add(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer = wx.BoxSizer(wx.HORIZONTAL) - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + background_sizer.Add(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) self.SetSizer(background_sizer) background_sizer.Fit(self) @@ -311,8 +317,8 @@ class BitmapPreviewSeries(wx.Panel): def _Add_Panels_Preview(self): self.previews = [] - for i in xrange(NROWS): - for j in xrange(NCOLS): + for i in range(NROWS): + for j in range(NCOLS): p = Preview(self) p.Bind(EVT_PREVIEW_CLICK, self.OnSelect) @@ -387,7 +393,7 @@ class BitmapPreviewSeries(wx.Panel): initial = self.displayed_position * NCOLS final = initial + NUM_PREVIEWS if len(self.files) < final: - for i in xrange(final-len(self.files)): + for i in range(final-len(self.files)): try: self.previews[-i-1].Hide() except IndexError: @@ -396,7 +402,7 @@ class BitmapPreviewSeries(wx.Panel): self.nhidden_last_display = final-len(self.files) else: if self.nhidden_last_display: - for i in xrange(self.nhidden_last_display): + for i in range(self.nhidden_last_display): try: self.previews[-i-1].Show() except IndexError: @@ -504,7 +510,7 @@ class SingleImagePreview(wx.Panel): maxValue=99, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS) slider.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) - slider.SetTickFreq(1, 1) + slider.SetTickFreq(1) self.slider = slider checkbox = wx.CheckBox(self, -1, _("Auto-play")) diff --git a/invesalius/gui/data_notebook.py b/invesalius/gui/data_notebook.py index ed5dcc3..90f98fb 100644 --- a/invesalius/gui/data_notebook.py +++ b/invesalius/gui/data_notebook.py @@ -29,7 +29,11 @@ except ImportError: import wx import wx.grid -import wx.lib.flatnotebook as fnb +try: + import wx.lib.agw.flatnotebook as fnb +except ImportError: + import wx.lib.flatnotebook as fnb + import wx.lib.platebtn as pbtn from wx.lib.pubsub import pub as Publisher @@ -40,7 +44,7 @@ import invesalius.gui.widgets.listctrl as listmix import invesalius.utils as ul -BTN_NEW, BTN_REMOVE, BTN_DUPLICATE, BTN_OPEN = [wx.NewId() for i in xrange(4)] +BTN_NEW, BTN_REMOVE, BTN_DUPLICATE, BTN_OPEN = [wx.NewId() for i in range(4)] TYPE = {const.LINEAR: _(u"Linear"), const.ANGULAR: _(u"Angular"), @@ -505,8 +509,8 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): """ image = self.image_gray new_image = Image.new("RGB", image.size) - for x in xrange(image.size[0]): - for y in xrange(image.size[1]): + for x in range(image.size[0]): + for y in range(image.size[1]): pixel_colour = [int(i*image.getpixel((x,y))) for i in colour] new_image.putpixel((x,y), tuple(pixel_colour)) @@ -881,11 +885,17 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): self.surface_list_index[index] = image_index if (index in index_list) and index_list: - self.UpdateItemInfo(index, name, volume, area, transparency, colour) + try: + self.UpdateItemInfo(index, name, volume, area, transparency, colour) + except wx._core.wxAssertionError: + self.InsertNewItem(index, name, volume, area, transparency, colour) else: self.InsertNewItem(index, name, volume, area, transparency, colour) else: - self.UpdateItemInfo(index, name, volume, area, transparency, colour) + try: + self.UpdateItemInfo(index, name, volume, area, transparency, colour) + except wx._core.wxAssertionError: + self.InsertNewItem(index, name, volume, area, transparency, colour) def InsertNewItem(self, index=0, label="Surface 1", volume="0 mm3", area="0 mm2", transparency="0%%", colour=None): @@ -899,6 +909,8 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): def UpdateItemInfo(self, index=0, label="Surface 1", volume="0 mm3", area="0 mm2", transparency="0%%", colour=None): + print("UpdateItemInfo", index) + # TODO: Retornar esse codigo self.SetStringItem(index, 1, label, imageId = self.surface_list_index[index]) self.SetStringItem(index, 2, volume) @@ -913,8 +925,8 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): """ image = self.image_gray new_image = Image.new("RGB", image.size) - for x in xrange(image.size[0]): - for y in xrange(image.size[1]): + for x in range(image.size[0]): + for y in range(image.size[1]): pixel_colour = [int(i*image.getpixel((x,y))) for i in colour] new_image.putpixel((x,y), tuple(pixel_colour)) @@ -1172,11 +1184,17 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): self._list_index[index] = image_index if (index in index_list) and index_list: - self.UpdateItemInfo(index, name, colour, location, type_, value) + try: + self.UpdateItemInfo(index, name, colour, location, type_, value) + except wx._core.wxAssertionError: + self.InsertNewItem(index, name, colour, location, type_, value) else: self.InsertNewItem(index, name, colour, location, type_, value) else: - self.UpdateItemInfo(index, name, colour, location, type_, value) + try: + self.UpdateItemInfo(index, name, colour, location, type_, value) + except wx._core.wxAssertionError: + self.InsertNewItem(index, name, colour, location, type_, value) @@ -1208,8 +1226,8 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): """ image = self.image_gray new_image = Image.new("RGB", image.size) - for x in xrange(image.size[0]): - for y in xrange(image.size[1]): + for x in range(image.size[0]): + for y in range(image.size[1]): pixel_colour = [int(i*image.getpixel((x,y))) for i in colour] new_image.putpixel((x,y), tuple(pixel_colour)) @@ -1301,9 +1319,9 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): def OnCheckItem(self, index, flag): # TODO: use pubsub to communicate to models if flag: - print "checked, ", index + print("checked, ", index) else: - print "unchecked, ", index + print("unchecked, ", index) def InsertNewItem(self, index=0, name="Axial 1", type_="2d", value="bla", colour=None): diff --git a/invesalius/gui/default_tasks.py b/invesalius/gui/default_tasks.py index babb733..466aa53 100644 --- a/invesalius/gui/default_tasks.py +++ b/invesalius/gui/default_tasks.py @@ -18,7 +18,10 @@ #-------------------------------------------------------------------------- import wx -import wx.lib.foldpanelbar as fpb +try: + import wx.lib.agw.foldpanelbar as fpb +except ModuleNotFoundError: + import wx.lib.foldpanelbar as fpb from wx.lib.pubsub import pub as Publisher import invesalius.constants as const @@ -35,7 +38,7 @@ FPB_DEFAULT_STYLE = 2621440 def GetCollapsedIconData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\ \xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\ @@ -58,13 +61,13 @@ def GetCollapsedIconBitmap(): return wx.BitmapFromImage(GetCollapsedIconImage()) def GetCollapsedIconImage(): - import cStringIO - stream = cStringIO.StringIO(GetCollapsedIconData()) + from io import BytesIO + stream = BytesIO(GetCollapsedIconData()) return wx.ImageFromStream(stream) def GetExpandedIconData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\ \xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\ @@ -89,8 +92,8 @@ def GetExpandedIconBitmap(): return wx.BitmapFromImage(GetExpandedIconImage()) def GetExpandedIconImage(): - import cStringIO - stream = cStringIO.StringIO(GetExpandedIconData()) + from io import BytesIO + stream = BytesIO(GetExpandedIconData()) return wx.ImageFromStream(stream) @@ -239,7 +242,7 @@ class UpperTaskPanel(wx.Panel): self.overwrite = False session = ses.Session() - print "session mode: ", session.mode + print("session mode: ", session.mode) if int(session.mode) == const.MODE_RP: tasks = [(_("Load data"), importer.TaskPanel), (_("Select region of interest"), slice_.TaskPanel), @@ -253,7 +256,7 @@ class UpperTaskPanel(wx.Panel): (_("Export data"), exporter.TaskPanel), (_("Navigation system"), navigator.TaskPanel)] - for i in xrange(len(tasks)): + for i in range(len(tasks)): (name, panel) = tasks[i] # Create panel item = fold_panel.AddFoldPanel("%d. %s"%(i+1, name), diff --git a/invesalius/gui/default_viewers.py b/invesalius/gui/default_viewers.py index 90c16b3..a40a8b1 100644 --- a/invesalius/gui/default_viewers.py +++ b/invesalius/gui/default_viewers.py @@ -306,7 +306,7 @@ import wx.lib.colourselect as csel import invesalius.constants as const -[BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE, BUTTON_3D_STEREO, BUTTON_TARGET] = [wx.NewId() for num in xrange(5)] +[BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE, BUTTON_3D_STEREO, BUTTON_TARGET] = [wx.NewId() for num in range(5)] RAYCASTING_TOOLS = wx.NewId() ID_TO_NAME = {} diff --git a/invesalius/gui/dialogs.py b/invesalius/gui/dialogs.py index f859132..aad1a30 100644 --- a/invesalius/gui/dialogs.py +++ b/invesalius/gui/dialogs.py @@ -34,7 +34,10 @@ else: import vtk import wx -import wx.combo +try: + from wx.adv import BitmapComboBox +except ImportError: + from wx.combo import BitmapComboBox from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor from wx.lib import masked @@ -67,11 +70,16 @@ EVT_MASK_SET = wx.PyEventBinder(myEVT_MASK_SET, 1) class NumberDialog(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) + try: + pre = wx.PreDialog() + pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize, + pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, None, -1, "InVesalius 3", size=wx.DefaultSize, + pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE) # Static text which contains message to user label = wx.StaticText(self, -1, message) @@ -117,11 +125,16 @@ class NumberDialog(wx.Dialog): class ResizeImageDialog(wx.Dialog): def __init__(self):#, message, value=0): - pre = self.pre = wx.PreDialog() - pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize, - pos=wx.DefaultPosition, - style=wx.DEFAULT_DIALOG_STYLE) - self.PostCreate(pre) + try: + pre = self.pre = wx.PreDialog() + pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize, + pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, None, -1, "InVesalius 3", size=wx.DefaultSize, + pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE) lbl_message = wx.StaticText(self, -1, _("InVesalius is running on a 32-bit operating system or has insufficient memory. \nIf you want to work with 3D surfaces or volume rendering, \nit is recommended to reduce the medical images resolution.")) icon = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32,32)) @@ -149,12 +162,12 @@ class ResizeImageDialog(wx.Dialog): sizer_itens = wx.BoxSizer(wx.VERTICAL) sizer_itens.Add(lbl_message, 0, wx.EXPAND|wx.ALL, 5) - sizer_itens.AddSizer(sizer_percent, 0, wx.EXPAND|wx.ALL, 5) + sizer_itens.Add(sizer_percent, 0, wx.EXPAND|wx.ALL, 5) sizer_itens.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 5) sizer_general = wx.BoxSizer(wx.HORIZONTAL) sizer_general.Add(bmp, 0, wx.ALIGN_CENTRE|wx.ALL, 10) - sizer_general.AddSizer(sizer_itens, 0, wx.ALL , 5) + sizer_general.Add(sizer_itens, 0, wx.ALL , 5) #self.SetAutoLayout(True) self.SetSizer(sizer_general) @@ -169,7 +182,7 @@ class ResizeImageDialog(wx.Dialog): return self.num_ctrl_porcent.GetValue() def Close(self): - self.pre.Destroy() + self.Destroy() def ShowNumberDialog(message, value=0): dlg = NumberDialog(message, value) @@ -465,7 +478,7 @@ def ShowSaveMarkersDialog(default_filename=None): "", # last used directory default_filename, _("Markers files (*.mks)|*.mks"), - wx.SAVE | wx.OVERWRITE_PROMPT) + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) # dlg.SetFilterIndex(0) # default is VTI filename = None @@ -495,7 +508,7 @@ def ShowSaveCoordsDialog(default_filename=None): "", # last used directory default_filename, _("Coordinates files (*.csv)|*.csv"), - wx.SAVE | wx.OVERWRITE_PROMPT) + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) # dlg.SetFilterIndex(0) # default is VTI filename = None @@ -526,7 +539,7 @@ def ShowLoadMarkersDialog(): defaultDir="", defaultFile="", wildcard=_("Markers files (*.mks)|*.mks"), - style=wx.OPEN|wx.CHANGE_DIR) + style=wx.FD_OPEN|wx.FD_CHANGE_DIR) # inv3 filter is default dlg.SetFilterIndex(0) @@ -555,7 +568,7 @@ def ShowSaveRegistrationDialog(default_filename=None): "", # last used directory default_filename, _("Registration files (*.obr)|*.obr"), - wx.SAVE | wx.OVERWRITE_PROMPT) + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) # dlg.SetFilterIndex(0) # default is VTI filename = None @@ -586,7 +599,7 @@ def ShowLoadRegistrationDialog(): defaultDir="", defaultFile="", wildcard=_("Registration files (*.obr)|*.obr"), - style=wx.OPEN|wx.CHANGE_DIR) + style=wx.FD_OPEN|wx.FD_CHANGE_DIR) # inv3 filter is default dlg.SetFilterIndex(0) @@ -610,10 +623,14 @@ def ShowLoadRegistrationDialog(): class MessageDialog(wx.Dialog): def __init__(self, message): - pre = wx.PreDialog() - pre.Create(None, -1, "InVesalius 3", size=(360, 370), pos=wx.DefaultPosition, - style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(None, -1, "InVesalius 3", size=(360, 370), pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, None, -1, "InVesalius 3", size=(360, 370), pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) # Static text which contains message to user label = wx.StaticText(self, -1, message) @@ -652,10 +669,14 @@ class UpdateMessageDialog(wx.Dialog): title=_("Invesalius Update") self.url = url - pre = wx.PreDialog() - pre.Create(None, -1, title, size=(360, 370), pos=wx.DefaultPosition, - style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(None, -1, title, size=(360, 370), pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, None, -1, title, size=(360, 370), pos=wx.DefaultPosition, + style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION) # Static text which contains message to user label = wx.StaticText(self, -1, msg) @@ -993,18 +1014,22 @@ class NewMask(wx.Dialog): import invesalius.data.mask as mask import invesalius.project as prj - # Instead of calling wx.Dialog.__init__ we precreate the dialog - # so we can set an extra style that must be set before - # creation, and then we create the GUI object using the Create - # method. - pre = wx.PreDialog() - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) - pre.Create(parent, ID, title, pos, (500,300), style) + try: + # Instead of calling wx.Dialog.__init__ we precreate the dialog + # so we can set an extra style that must be set before + # creation, and then we create the GUI object using the Create + # method. + pre = wx.PreDialog() + pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) + pre.Create(parent, ID, title, pos, (500,300), style) + # This next step is the most important, it turns this Python + # object into the real wrapper of the dialog (instead of pre) + # as far as the wxPython extension is concerned. + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, parent, ID, title, pos, (500,300), style) + self.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) - # This next step is the most important, it turns this Python - # object into the real wrapper of the dialog (instead of pre) - # as far as the wxPython extension is concerned. - self.PostCreate(pre) self.CenterOnScreen() @@ -1031,8 +1056,7 @@ class NewMask(wx.Dialog): # Retrieve existing masks project = prj.Project() - thresh_list = project.threshold_modes.keys() - thresh_list.sort() + thresh_list = sorted(project.threshold_modes.keys()) default_index = thresh_list.index(_("Bone")) self.thresh_list = thresh_list @@ -1285,18 +1309,22 @@ class NewSurfaceDialog(wx.Dialog): import invesalius.data.surface as surface import invesalius.project as prj - # Instead of calling wx.Dialog.__init__ we precreate the dialog - # so we can set an extra style that must be set before - # creation, and then we create the GUI object using the Create - # method. - pre = wx.PreDialog() - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) - pre.Create(parent, ID, title, pos, (500,300), style) - - # This next step is the most important, it turns this Python - # object into the real wrapper of the dialog (instead of pre) - # as far as the wxPython extension is concerned. - self.PostCreate(pre) + try: + # Instead of calling wx.Dialog.__init__ we precreate the dialog + # so we can set an extra style that must be set before + # creation, and then we create the GUI object using the Create + # method. + pre = wx.PreDialog() + pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) + pre.Create(parent, ID, title, pos, (500,300), style) + + # This next step is the most important, it turns this Python + # object into the real wrapper of the dialog (instead of pre) + # as far as the wxPython extension is concerned. + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, parent, ID, title, pos, (500,300), style) + self.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) self.CenterOnScreen() @@ -1323,8 +1351,7 @@ class NewSurfaceDialog(wx.Dialog): # Retrieve existing masks project = prj.Project() - index_list = project.mask_dict.keys() - index_list.sort() + index_list = sorted(project.mask_dict.keys()) self.mask_list = [project.mask_dict[index].name for index in index_list] @@ -1498,18 +1525,24 @@ class SurfaceCreationDialog(wx.Dialog): # so we can set an extra style that must be set before # creation, and then we create the GUI object using the Create # method. - pre = wx.PreDialog() - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) - pre.Create(parent, ID, title, pos, (500,300), style) - - # This extra style can be set after the UI object has been created. - if 'wxMac' in wx.PlatformInfo and useMetal: - self.SetExtraStyle(wx.DIALOG_EX_METAL) - - # This next step is the most important, it turns this Python - # object into the real wrapper of the dialog (instead of pre) - # as far as the wxPython extension is concerned. - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) + pre.Create(parent, ID, title, pos, (500,300), style) + + # This extra style can be set after the UI object has been created. + if 'wxMac' in wx.PlatformInfo and useMetal: + self.SetExtraStyle(wx.DIALOG_EX_METAL) + + # This next step is the most important, it turns this Python + # object into the real wrapper of the dialog (instead of pre) + # as far as the wxPython extension is concerned. + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, parent, ID, title, pos, size, style) + self.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) + if 'wxMac' in wx.PlatformInfo and useMetal: + self.SetExtraStyle(wx.DIALOG_EX_METAL) self.CenterOnScreen() @@ -1583,8 +1616,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): #Retrieve existing masks project = prj.Project() index_list = project.mask_dict.keys() - index_list.sort() - self.mask_list = [project.mask_dict[index].name for index in index_list] + self.mask_list = [project.mask_dict[index].name for index in sorted(index_list)] active_mask = slc.Slice().current_mask.index #active_mask = len(self.mask_list)-1 @@ -1810,9 +1842,12 @@ class SurfaceMethodPanel(wx.Panel): class ClutImagedataDialog(wx.Dialog): def __init__(self, histogram, init, end, nodes=None): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) self.histogram = histogram self.init = init @@ -1910,10 +1945,13 @@ class WatershedOptionsPanel(wx.Panel): class WatershedOptionsDialog(wx.Dialog): - def __init__(self, config): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u'Watershed'), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + def __init__(self, config, ID=-1, title=_(u'Watershed'), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT): + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), ID, title=title, style=style) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), ID, title=title, style=style) self.config = config @@ -1951,10 +1989,13 @@ class WatershedOptionsDialog(wx.Dialog): evt.Skip() class MaskBooleanDialog(wx.Dialog): - def __init__(self, masks): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Boolean operations"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) - self.PostCreate(pre) + def __init__(self, masks, ID=-1, title=_(u"Boolean operations"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP): + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), ID, title=title, style=style) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), ID, title=title, style=style) self._init_gui(masks) self.CenterOnScreen() @@ -1980,7 +2021,7 @@ class MaskBooleanDialog(wx.Dialog): (_(u"Difference"), const.BOOLEAN_DIFF, 'bool_difference.png'), (_(u"Intersection"), const.BOOLEAN_AND, 'bool_intersection.png'), (_(u"Exclusive disjunction"), const.BOOLEAN_XOR, 'bool_disjunction.png')) - self.op_boolean = wx.combo.BitmapComboBox(self, -1, op_choices[0][0], choices=[]) + self.op_boolean = BitmapComboBox(self, -1, op_choices[0][0], choices=[]) for n, i, f in op_choices: bmp = wx.Bitmap(os.path.join(icon_folder, f), wx.BITMAP_TYPE_PNG) @@ -2031,10 +2072,13 @@ class MaskBooleanDialog(wx.Dialog): class ReorientImageDialog(wx.Dialog): - def __init__(self): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u'Image reorientation'), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + def __init__(self, ID=-1, title=_(u'Image reorientation'), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT): + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), ID, title=title, style=style) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), ID, title=title, style=style) self._closed = False @@ -2149,22 +2193,25 @@ class ImportBitmapParameters(wx.Dialog): from os import sys def __init__(self): - pre = wx.PreDialog() - if sys.platform == 'win32': size=wx.Size(380,180) else: size=wx.Size(380,210) - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Create project from bitmap"),size=size,\ - style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Create project from bitmap"),size=size, + style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, + _(u"Create project from bitmap"), + size=size, + style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) self.interval = 0 - - self.PostCreate(pre) self._init_gui() - self.bind_evts() self.CenterOnScreen() @@ -2195,13 +2242,19 @@ class ImportBitmapParameters(wx.Dialog): gbs.Add(stx_name, (0,0), flag=flag_labels) gbs.Add(tx_name, (0,1)) - gbs.AddStretchSpacer((1,0)) + try: + gbs.Add(0, 0, (1,0)) + except TypeError: + gbs.AddStretchSpacer((1,0)) gbs.Add(stx_orientation, (2,0), flag=flag_labels) gbs.Add(cb_orientation, (2,1)) gbs.Add(stx_spacing, (3,0)) - gbs.AddStretchSpacer((4,0)) + try: + gbs.Add(0, 0, (4,0)) + except TypeError: + gbs.AddStretchSpacer((4,0)) #--- spacing -------------- gbs_spacing = wx.GridBagSizer(2, 6) @@ -2251,17 +2304,23 @@ class ImportBitmapParameters(wx.Dialog): btn_cancel = wx.Button(p, wx.ID_CANCEL) - gbs_button.AddStretchSpacer((0,2)) + try: + gbs_button.Add(0, 0, (0,2)) + except TypeError: + gbs_button.AddStretchSpacer((0,2)) gbs_button.Add(btn_cancel, (1,2)) gbs_button.Add(btn_ok, (1,3)) - gbs_principal.AddSizer(gbs, (0,0), flag = wx.ALL|wx.EXPAND) - gbs_principal.AddSizer(gbs_spacing, (1,0), flag=wx.ALL|wx.EXPAND) - gbs_principal.AddStretchSpacer((2,0)) - gbs_principal.AddSizer(gbs_button, (3,0), flag = wx.ALIGN_RIGHT) + gbs_principal.Add(gbs, (0,0), flag = wx.ALL|wx.EXPAND) + gbs_principal.Add(gbs_spacing, (1,0), flag=wx.ALL|wx.EXPAND) + try: + gbs_principal.Add(0, 0, (2,0)) + except TypeError: + gbs_principal.AddStretchSpacer((2,0)) + gbs_principal.Add(gbs_button, (3,0), flag = wx.ALIGN_RIGHT) box = wx.BoxSizer() - box.AddSizer(gbs_principal, 1, wx.ALL|wx.EXPAND, 10) + box.Add(gbs_principal, 1, wx.ALL|wx.EXPAND, 10) p.SetSizer(box) box.Fit(self) @@ -2312,10 +2371,16 @@ class PanelTargeFFill(wx.Panel): sizer = wx.GridBagSizer(5, 5) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(self.target_2d, (1, 0), (1, 6), flag=wx.LEFT, border=5) sizer.Add(self.target_3d, (2, 0), (1, 6), flag=wx.LEFT, border=5) - sizer.AddStretchSpacer((3, 0)) + try: + sizer.Add(0, 0, (3, 0)) + except TypeError: + sizer.AddStretchSpacer((3, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2332,11 +2397,17 @@ class Panel2DConnectivity(wx.Panel): sizer = wx.GridBagSizer(5, 5) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(wx.StaticText(self, -1, _(u"2D Connectivity")), (1, 0), (1, 6), flag=wx.LEFT, border=5) sizer.Add(self.conect2D_4, (2, 0), flag=wx.LEFT, border=7) sizer.Add(self.conect2D_8, (2, 1), flag=wx.LEFT, border=7) - sizer.AddStretchSpacer((3, 0)) + try: + sizer.Add(0, 0, (3, 0)) + except TypeError: + sizer.AddStretchSpacer((3, 0)) if show_orientation: self.cmb_orientation = wx.ComboBox(self, -1, choices=(_(u"Axial"), _(u"Coronal"), _(u"Sagital")), style=wx.CB_READONLY) @@ -2344,7 +2415,10 @@ class Panel2DConnectivity(wx.Panel): sizer.Add(wx.StaticText(self, -1, _(u"Orientation")), (4, 0), (1, 6), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5) sizer.Add(self.cmb_orientation, (5, 0), (1, 10), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) - sizer.AddStretchSpacer((6, 0)) + try: + sizer.Add(0, 0, (6, 0)) + except TypeError: + sizer.AddStretchSpacer((6, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2378,12 +2452,18 @@ class Panel3DConnectivity(wx.Panel): sizer = wx.GridBagSizer(5, 5) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(wx.StaticText(self, -1, _(u"3D Connectivity")), (1, 0), (1, 6), flag=wx.LEFT, border=5) sizer.Add(self.conect3D_6, (2, 0), flag=wx.LEFT, border=9) sizer.Add(self.conect3D_18, (2, 1), flag=wx.LEFT, border=9) sizer.Add(self.conect3D_26, (2, 2), flag=wx.LEFT, border=9) - sizer.AddStretchSpacer((3, 0)) + try: + sizer.Add(0, 0, (3, 0)) + except TypeError: + sizer.AddStretchSpacer((3, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2434,7 +2514,7 @@ class PanelFFillThreshold(wx.Panel): def OnSlideChanged(self, evt): self.config.t0 = int(self.threshold.GetMinValue()) self.config.t1 = int(self.threshold.GetMaxValue()) - print self.config.t0, self.config.t1 + print(self.config.t0, self.config.t1) class PanelFFillDynamic(wx.Panel): @@ -2458,11 +2538,17 @@ class PanelFFillDynamic(wx.Panel): sizer = wx.GridBagSizer(5, 5) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(self.use_ww_wl, (1, 0), (1, 6), flag=wx.LEFT, border=5) - sizer.AddStretchSpacer((2, 0)) + try: + sizer.Add(0, 0, (2, 0)) + except TypeError: + sizer.AddStretchSpacer((2, 0)) sizer.Add(wx.StaticText(self, -1, _(u"Deviation")), (3, 0), (1, 6), flag=wx.LEFT, border=5) @@ -2472,7 +2558,10 @@ class PanelFFillDynamic(wx.Panel): sizer.Add(wx.StaticText(self, -1, _(u"Max:")), (4, 2), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border=9) sizer.Add(self.deviation_max, (4, 3)) - sizer.AddStretchSpacer((5, 0)) + try: + sizer.Add(0, 0, (5, 0)) + except TypeError: + sizer.AddStretchSpacer((5, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2516,19 +2605,28 @@ class PanelFFillConfidence(wx.Panel): sizer = wx.GridBagSizer(5, 5) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(self.use_ww_wl, (1, 0), (1, 6), flag=wx.LEFT, border=5) - sizer.AddStretchSpacer((2, 0)) + try: + sizer.Add(0, 0, (2, 0)) + except TypeError: + sizer.AddStretchSpacer((2, 0)) sizer.Add(wx.StaticText(self, -1, _(u"Multiplier")), (3, 0), (1, 3), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border=5) - sizer.Add(self.spin_mult, (3, 3), (1, 2)) + sizer.Add(self.spin_mult, (3, 3), (1, 3)) sizer.Add(wx.StaticText(self, -1, _(u"Iterations")), (4, 0), (1, 3), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border=5) sizer.Add(self.spin_iters, (4, 3), (1, 2)) - sizer.AddStretchSpacer((5, 0)) + try: + sizer.Add(0, 0, (5, 0)) + except TypeError: + sizer.AddStretchSpacer((5, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2550,9 +2648,12 @@ class PanelFFillConfidence(wx.Panel): class FFillOptionsDialog(wx.Dialog): def __init__(self, title, config): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) self.config = config @@ -2651,7 +2752,7 @@ class FFillOptionsDialog(wx.Dialog): self.config.con_3d = 26 def OnClose(self, evt): - print "ONCLOSE" + print("ONCLOSE") if self.config.dlg_visible: Publisher.sendMessage('Disable style', const.SLICE_STATE_MASK_FFILL) evt.Skip() @@ -2660,9 +2761,12 @@ class FFillOptionsDialog(wx.Dialog): class SelectPartsOptionsDialog(wx.Dialog): def __init__(self, config): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Select mask parts"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Select mask parts"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, _(u"Select mask parts"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) self.config = config @@ -2700,7 +2804,7 @@ class SelectPartsOptionsDialog(wx.Dialog): btn_sizer.Add(self.btn_ok, 0, flag=wx.ALIGN_RIGHT, border=5) btn_sizer.Add(self.btn_cancel, 0, flag=wx.LEFT|wx.ALIGN_RIGHT, border=5) - sizer.AddSizer(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) + sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) sizer.AddSpacer(5) self.SetSizer(sizer) @@ -2741,10 +2845,13 @@ class SelectPartsOptionsDialog(wx.Dialog): self.Destroy() class FFillSegmentationOptionsDialog(wx.Dialog): - def __init__(self, config): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Region growing"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + def __init__(self, config, ID=-1, title=_(u"Region growing"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT): + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), ID, title=title, style=style) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), ID, title=title, style=style) self.config = config @@ -2816,20 +2923,38 @@ class FFillSegmentationOptionsDialog(wx.Dialog): # Sizer sizer = wx.GridBagSizer(2, 2) - sizer.AddStretchSpacer((0, 0)) + try: + sizer.Add(0, 0, (0, 0)) + except TypeError: + sizer.AddStretchSpacer((0, 0)) sizer.Add(wx.StaticText(self, -1, _(u"Parameters")), (1, 0), (1, 6), flag=wx.LEFT, border=5) - sizer.AddStretchSpacer((2, 0)) + try: + sizer.Add(0, 0, (2, 0)) + except TypeError: + sizer.AddStretchSpacer((2, 0)) sizer.Add(self.panel_target, (3, 0), (1, 6), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) - sizer.AddStretchSpacer((4, 0)) + try: + sizer.Add(0, 0, (4, 0)) + except TypeError: + sizer.AddStretchSpacer((4, 0)) sizer.Add(self.panel2dcon, (5, 0), (1, 6), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) - sizer.AddStretchSpacer((6, 0)) + try: + sizer.Add(0, 0, (6, 0)) + except TypeError: + sizer.AddStretchSpacer((6, 0)) sizer.Add(self.panel3dcon, (7, 0), (1, 6), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) - sizer.AddStretchSpacer((8, 0)) + try: + sizer.Add(0, 0, (8, 0)) + except TypeError: + sizer.AddStretchSpacer((8, 0)) sizer.Add(wx.StaticText(self, -1, _(u"Method")), (9, 0), (1, 1), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=7) sizer.Add(self.cmb_method, (9, 1), (1, 5), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) - sizer.AddStretchSpacer((10, 0)) + try: + sizer.Add(0, 0, (10, 0)) + except TypeError: + sizer.AddStretchSpacer((10, 0)) if self.config.method == 'dynamic': self.cmb_method.SetSelection(0) @@ -2845,9 +2970,15 @@ class FFillSegmentationOptionsDialog(wx.Dialog): sizer.Add(self.panel_ffill_threshold, (11, 0), (1, 6), flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=7) self.config.method = 'threshold' - sizer.AddStretchSpacer((12, 0)) + try: + sizer.Add(0, 0, (12, 0)) + except TypeError: + sizer.AddStretchSpacer((12, 0)) sizer.Add(self.close_btn, (13, 0), (1, 6), flag=wx.ALIGN_RIGHT|wx.RIGHT, border=5) - sizer.AddStretchSpacer((14, 0)) + try: + sizer.Add(0, 0, (14, 0)) + except TypeError: + sizer.AddStretchSpacer((14, 0)) self.SetSizer(sizer) sizer.Fit(self) @@ -2919,13 +3050,16 @@ class FFillSegmentationOptionsDialog(wx.Dialog): class CropOptionsDialog(wx.Dialog): - def __init__(self, config): + def __init__(self, config, ID=-1, title=_(u"Crop mask"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT): self.config = config - pre = wx.PreDialog() + try: + pre = wx.PreDialog() + + pre.Create(wx.GetApp().GetTopWindow(), ID, title=title, style=style) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), ID, title=title, style=style) - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Crop mask"),\ - style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) self._init_gui() @@ -3000,13 +3134,17 @@ class CropOptionsDialog(wx.Dialog): gbs_button.Add(btn_cancel, (0,0)) gbs_button.Add(btn_ok, (0,1)) - gbs_principal.AddSizer(gbs, (0,0), flag = wx.ALL|wx.EXPAND) - gbs_principal.AddStretchSpacer((1,0)) - gbs_principal.AddStretchSpacer((2,0)) - gbs_principal.AddSizer(gbs_button, (3,0), flag = wx.ALIGN_RIGHT) + gbs_principal.Add(gbs, (0,0), flag = wx.ALL|wx.EXPAND) + try: + gbs_principal.Add(0, 0, (1, 0)) + gbs_principal.Add(0, 0, (2, 0)) + except TypeError: + gbs_principal.AddStretchSpacer((1, 0)) + gbs_principal.AddStretchSpacer((2, 0)) + gbs_principal.Add(gbs_button, (3,0), flag = wx.ALIGN_RIGHT) box = wx.BoxSizer() - box.AddSizer(gbs_principal, 1, wx.ALL|wx.EXPAND, 10) + box.Add(gbs_principal, 1, wx.ALL|wx.EXPAND, 10) p.SetSizer(box) box.Fit(p) @@ -3039,9 +3177,12 @@ class CropOptionsDialog(wx.Dialog): class FillHolesAutoDialog(wx.Dialog): def __init__(self, title): - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT) self._init_gui() @@ -3056,10 +3197,13 @@ class FillHolesAutoDialog(wx.Dialog): self.panel2dcon = Panel2DConnectivity(self, show_orientation=True, style=border_style|wx.TAB_TRAVERSAL) self.panel3dcon = Panel3DConnectivity(self, style=border_style|wx.TAB_TRAVERSAL) - self.panel_target.target_2d.SetValue(1) self.panel2dcon.Enable(1) self.panel3dcon.Enable(0) + self.panel_target.target_2d.SetValue(1) + self.panel2dcon.conect2D_4.SetValue(1) + self.panel3dcon.conect3D_6.SetValue(1) + self.apply_btn = wx.Button(self, wx.ID_APPLY) self.close_btn = wx.Button(self, wx.ID_CLOSE) @@ -3089,7 +3233,7 @@ class FillHolesAutoDialog(wx.Dialog): btn_sizer.Add(self.apply_btn, 0, flag=wx.ALIGN_RIGHT, border=5) btn_sizer.Add(self.close_btn, 0, flag=wx.LEFT|wx.ALIGN_RIGHT, border=5) - sizer.AddSizer(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) + sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) sizer.AddSpacer(5) @@ -3147,10 +3291,14 @@ class ObjectCalibrationDialog(wx.Dialog): self.obj_fiducials = np.full([5, 3], np.nan) self.obj_orients = np.full([5, 3], np.nan) - pre = wx.PreDialog() - pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Object calibration"), size=(450, 440), - style=wx.DEFAULT_DIALOG_STYLE | wx.FRAME_FLOAT_ON_PARENT) - self.PostCreate(pre) + try: + pre = wx.PreDialog() + pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Object calibration"), size=(450, 440), + style=wx.DEFAULT_DIALOG_STYLE | wx.FRAME_FLOAT_ON_PARENT) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, _(u"Object calibration"), size=(450, 440), + style=wx.DEFAULT_DIALOG_STYLE | wx.FRAME_FLOAT_ON_PARENT) self._init_gui() self.LoadObject() @@ -3191,8 +3339,8 @@ class ObjectCalibrationDialog(wx.Dialog): tips_obj = const.TIPS_OBJ for k in btns_obj: - n = btns_obj[k].keys()[0] - lab = btns_obj[k].values()[0] + n = list(btns_obj[k].keys())[0] + lab = list(btns_obj[k].values())[0] self.btns_coord[n] = wx.Button(self, k, label=lab, size=wx.Size(60, 23)) self.btns_coord[n].SetToolTip(wx.ToolTip(tips_obj[n])) self.btns_coord[n].Bind(wx.EVT_BUTTON, self.OnGetObjectFiducials) @@ -3332,7 +3480,7 @@ class ObjectCalibrationDialog(wx.Dialog): return ball_actor, tactor def OnGetObjectFiducials(self, evt): - btn_id = const.BTNS_OBJ[evt.GetId()].keys()[0] + btn_id = list(const.BTNS_OBJ[evt.GetId()].keys())[0] if self.trk_init and self.tracker_id: coord_raw = dco.GetCoordinates(self.trk_init, self.tracker_id, self.obj_ref_id) diff --git a/invesalius/gui/dicom_preview_panel.py b/invesalius/gui/dicom_preview_panel.py index 79cf21c..b6a90f7 100644 --- a/invesalius/gui/dicom_preview_panel.py +++ b/invesalius/gui/dicom_preview_panel.py @@ -272,7 +272,10 @@ class Preview(wx.Panel): def OnEnter(self, evt): if not self.select_on: #c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DHILIGHT) - c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) + try: + c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE) + except AttributeError: + c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) self.SetBackgroundColour(c) def OnLeave(self, evt): @@ -320,7 +323,10 @@ class Preview(wx.Panel): def Select(self, on=True): if self.select_on: - c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) + try: + c = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) + except AttributeError: + c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) else: c = (PREVIEW_BACKGROUND) self.SetBackgroundColour(c) @@ -355,10 +361,10 @@ class DicomPreviewSeries(wx.Panel): self.grid = wx.GridSizer(rows=NROWS, cols=NCOLS, vgap=3, hgap=3) sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.AddSizer(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + sizer.Add(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer = wx.BoxSizer(wx.HORIZONTAL) - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + background_sizer.Add(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) self.SetSizer(background_sizer) background_sizer.Fit(self) @@ -374,8 +380,8 @@ class DicomPreviewSeries(wx.Panel): def _Add_Panels_Preview(self): self.previews = [] - for i in xrange(NROWS): - for j in xrange(NCOLS): + for i in range(NROWS): + for j in range(NCOLS): p = Preview(self) p.Bind(EVT_PREVIEW_CLICK, self.OnSelect) #if (i == j == 0): @@ -432,7 +438,7 @@ class DicomPreviewSeries(wx.Panel): initial = self.displayed_position * NCOLS final = initial + NUM_PREVIEWS if len(self.files) < final: - for i in xrange(final-len(self.files)): + for i in range(final-len(self.files)): try: self.previews[-i-1].Hide() except IndexError: @@ -441,7 +447,7 @@ class DicomPreviewSeries(wx.Panel): self.nhidden_last_display = final-len(self.files) else: if self.nhidden_last_display: - for i in xrange(self.nhidden_last_display): + for i in range(self.nhidden_last_display): try: self.previews[-i-1].Show() except IndexError: @@ -492,10 +498,10 @@ class DicomPreviewSlice(wx.Panel): self.grid = wx.GridSizer(rows=NROWS, cols=NCOLS, vgap=3, hgap=3) sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.AddSizer(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + sizer.Add(self.grid, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer = wx.BoxSizer(wx.HORIZONTAL) - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) + background_sizer.Add(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2) background_sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) self.SetSizer(background_sizer) background_sizer.Fit(self) @@ -511,8 +517,8 @@ class DicomPreviewSlice(wx.Panel): def _Add_Panels_Preview(self): self.previews = [] - for i in xrange(NROWS): - for j in xrange(NCOLS): + for i in range(NROWS): + for j in range(NCOLS): p = Preview(self) p.Bind(EVT_PREVIEW_CLICK, self.OnPreviewClick) #p.Hide() @@ -545,7 +551,7 @@ class DicomPreviewSlice(wx.Panel): if isinstance(dicom.image.thumbnail_path, list): _slice = 0 for thumbnail in dicom.image.thumbnail_path: - print thumbnail + print(thumbnail) info = DicomInfo(n, dicom, _("Image %d") % (n), "%.2f" % (dicom.image.position[2]), _slice) @@ -577,7 +583,7 @@ class DicomPreviewSlice(wx.Panel): if isinstance(dicom.image.thumbnail_path, list): _slice = 0 for thumbnail in dicom.image.thumbnail_path: - print thumbnail + print(thumbnail) info = DicomInfo(n, dicom, _("Image %d") % int(n), "%.2f" % (dicom.image.position[2]), _slice) @@ -603,7 +609,7 @@ class DicomPreviewSlice(wx.Panel): initial = self.displayed_position * NCOLS final = initial + NUM_PREVIEWS if len(self.files) < final: - for i in xrange(final-len(self.files)): + for i in range(final-len(self.files)): try: self.previews[-i-1].Hide() except IndexError: @@ -611,7 +617,7 @@ class DicomPreviewSlice(wx.Panel): self.nhidden_last_display = final-len(self.files) else: if self.nhidden_last_display: - for i in xrange(self.nhidden_last_display): + for i in range(self.nhidden_last_display): try: self.previews[-i-1].Show() except IndexError: @@ -648,7 +654,7 @@ class DicomPreviewSlice(wx.Panel): self.first_selection = dicom_id self.last_selection = dicom_id - for i in xrange(len(self.files)): + for i in range(len(self.files)): if i == dicom_id: self.files[i].selected = True @@ -666,7 +672,7 @@ class DicomPreviewSlice(wx.Panel): self.selected_panel.select_on = self.selected_panel is evt.GetEventObject() if self.first_selection != self.last_selection: - for i in xrange(len(self.files)): + for i in range(len(self.files)): if i >= self.first_selection and i <= self.last_selection: self.files[i].selected = True else: @@ -772,7 +778,7 @@ class SingleImagePreview(wx.Panel): maxValue=99, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS) slider.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) - slider.SetTickFreq(1, 1) + slider.SetTickFreq(1) self.slider = slider checkbox = wx.CheckBox(self, -1, _("Auto-play")) diff --git a/invesalius/gui/frame.py b/invesalius/gui/frame.py index 8e7faf3..27242af 100644 --- a/invesalius/gui/frame.py +++ b/invesalius/gui/frame.py @@ -24,6 +24,12 @@ import sys import webbrowser import wx + +try: + from wx.adv import TaskBarIcon as wx_TaskBarIcon +except ImportError: + from wx import TaskBarIcon as wx_TaskBarIcon + import wx.aui from wx.lib.pubsub import pub as Publisher import wx.lib.agw.toasterbox as TB @@ -386,6 +392,7 @@ class Frame(wx.Frame): s = ses.Session() if not s.IsOpen() or not s.project_path: Publisher.sendMessage('Exit') + self.aui_manager.UnInit() def OnMenuClick(self, evt): """ @@ -1127,7 +1134,7 @@ class StatusBar(wx.StatusBar): # ------------------------------------------------------------------ # ------------------------------------------------------------------ -class TaskBarIcon(wx.TaskBarIcon): +class TaskBarIcon(wx_TaskBarIcon): """ TaskBarIcon has different behaviours according to the platform: - win32: Show icon on "Notification Area" (near clock) @@ -1135,7 +1142,7 @@ class TaskBarIcon(wx.TaskBarIcon): - linux2: Show icon on "Notification Area" (near clock) """ def __init__(self, parent=None): - wx.TaskBarIcon.__init__(self) + wx_TaskBarIcon.__init__(self) self.frame = parent icon = wx.Icon(os.path.join(const.ICON_DIR, "invesalius.ico"), diff --git a/invesalius/gui/import_bitmap_panel.py b/invesalius/gui/import_bitmap_panel.py index 2a7cd3b..25c2ce6 100644 --- a/invesalius/gui/import_bitmap_panel.py +++ b/invesalius/gui/import_bitmap_panel.py @@ -101,7 +101,7 @@ class InnerPanel(wx.Panel): self.combo_interval.SetSelection(0) inner_sizer = wx.BoxSizer(wx.HORIZONTAL) - inner_sizer.AddSizer(btnsizer, 0, wx.LEFT|wx.TOP, 5) + inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5) inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5) panel.SetSizer(inner_sizer) inner_sizer.Fit(panel) @@ -192,7 +192,7 @@ class TextPanel(wx.Panel): wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_ROW_LINES - | wx.TR_COLUMN_LINES + # | wx.TR_COLUMN_LINES | wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE | wx.TR_HIDE_ROOT @@ -308,7 +308,8 @@ class ImagePanel(wx.Panel): splitter.SetOrientation(wx.HORIZONTAL) self.splitter = splitter - splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) + # TODO: Rever isso + # splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(splitter, 1, wx.EXPAND) diff --git a/invesalius/gui/import_network_panel.py b/invesalius/gui/import_network_panel.py index 38086ff..c4b9dab 100644 --- a/invesalius/gui/import_network_panel.py +++ b/invesalius/gui/import_network_panel.py @@ -110,7 +110,7 @@ class InnerPanel(wx.Panel): self.combo_interval.SetSelection(0) inner_sizer = wx.BoxSizer(wx.HORIZONTAL) - inner_sizer.AddSizer(btnsizer, 0, wx.LEFT|wx.TOP, 5) + inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5) inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5) panel.SetSizer(inner_sizer) inner_sizer.Fit(panel) @@ -230,7 +230,7 @@ class TextPanel(wx.Panel): wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_ROW_LINES - | wx.TR_COLUMN_LINES + # | wx.TR_COLUMN_LINES | wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_SINGLE ) @@ -507,8 +507,8 @@ class FindPanel(wx.Panel): sizer_txt_find.Add(self.btn_find) self.sizer.Add((0, 5), 0, wx.EXPAND|wx.HORIZONTAL) - self.sizer.AddSizer(sizer_word_label) - self.sizer.AddSizer(sizer_txt_find) + self.sizer.Add(sizer_word_label) + self.sizer.Add(sizer_txt_find) #self.sizer.Add(self.serie_preview, 1, wx.EXPAND | wx.ALL, 5) #self.sizer.Add(self.dicom_preview, 1, wx.EXPAND | wx.ALL, 5) @@ -568,7 +568,8 @@ class HostFindPanel(wx.Panel): splitter.SetOrientation(wx.HORIZONTAL) self.splitter = splitter - splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) + # TODO: Rever isso + # splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(splitter, 1, wx.EXPAND) @@ -673,7 +674,7 @@ class NodesPanel(wx.Panel): self.tree_node.SetColumnWidth(4, 80) self.hosts[0] = [True, "localhost", "", "invesalius"] - index = self.tree_node.InsertStringItem(sys.maxint, "") + index = self.tree_node.InsertStringItem(sys.maxsize, "") self.tree_node.SetStringItem(index, 1, "localhost") self.tree_node.SetStringItem(index, 2, "") self.tree_node.SetStringItem(index, 3, "invesalius") @@ -704,7 +705,7 @@ class NodesPanel(wx.Panel): sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.tree_node, 85, wx.GROW|wx.EXPAND) - sizer.AddSizer(sizer_btn, 15) + sizer.Add(sizer_btn, 15) sizer.Fit(self) self.SetSizer(sizer) self.Layout() @@ -728,7 +729,7 @@ class NodesPanel(wx.Panel): def OnButtonAdd(self, evt): #adiciona vazio a coluna de check - index = self.tree_node.InsertStringItem(sys.maxint, "") + index = self.tree_node.InsertStringItem(sys.maxsize, "") self.hosts[index] = [True, "localhost", "80", ""] self.tree_node.SetStringItem(index, 1, "localhost") diff --git a/invesalius/gui/import_panel.py b/invesalius/gui/import_panel.py index 2125f1a..4c80466 100644 --- a/invesalius/gui/import_panel.py +++ b/invesalius/gui/import_panel.py @@ -103,7 +103,7 @@ class InnerPanel(wx.Panel): self.combo_interval.SetSelection(0) inner_sizer = wx.BoxSizer(wx.HORIZONTAL) - inner_sizer.AddSizer(btnsizer, 0, wx.LEFT|wx.TOP, 5) + inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5) inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5) panel.SetSizer(inner_sizer) inner_sizer.Fit(panel) @@ -215,7 +215,7 @@ class TextPanel(wx.Panel): wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_ROW_LINES - | wx.TR_COLUMN_LINES + # | wx.TR_COLUMN_LINES | wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_SINGLE ) @@ -362,7 +362,8 @@ class ImagePanel(wx.Panel): splitter.SetOrientation(wx.HORIZONTAL) self.splitter = splitter - splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) + # TODO Rever isso + # splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(splitter, 1, wx.EXPAND) diff --git a/invesalius/gui/language_dialog.py b/invesalius/gui/language_dialog.py index 55538ab..4356644 100644 --- a/invesalius/gui/language_dialog.py +++ b/invesalius/gui/language_dialog.py @@ -20,7 +20,10 @@ import os import sys import wx -import wx.combo +try: + from wx.adv import BitmapComboBox +except ImportError: + from wx.combo import BitmapComboBox import invesalius.i18n as i18n @@ -48,7 +51,7 @@ class ComboBoxLanguage: # Retrieve locales names and sort them self.locales = dict_locales.values() - self.locales.sort() + self.locales = sorted(self.locales) # Retrieve locales keys (eg: pt_BR for Portuguese(Brazilian)) self.locales_key = [dict_locales.get_key(value)[0] for value in self.locales] @@ -65,7 +68,7 @@ class ComboBoxLanguage: selection = self.locales_key.index('en') # Create bitmap combo - self.bitmapCmb = bitmapCmb = wx.combo.BitmapComboBox(parent, style=wx.CB_READONLY) + self.bitmapCmb = bitmapCmb = BitmapComboBox(parent, style=wx.CB_READONLY) for key in self.locales_key: # Based on composed flag filename, get bitmap filepath = os.path.join(ICON_DIR, "%s.bmp"%(key)) @@ -117,7 +120,7 @@ class LanguageDialog(wx.Dialog): # selection = self.locales_key.index('en') # # Create bitmap combo - # self.bitmapCmb = bitmapCmb = wx.combo.BitmapComboBox(self, style=wx.CB_READONLY) + # self.bitmapCmb = bitmapCmb = BitmapComboBox(self, style=wx.CB_READONLY) # for key in self.locales_key: # # Based on composed flag filename, get bitmap # filepath = os.path.join(ICON_DIR, "%s.bmp"%(key)) diff --git a/invesalius/gui/preferences.py b/invesalius/gui/preferences.py index 4ea1696..88f5313 100644 --- a/invesalius/gui/preferences.py +++ b/invesalius/gui/preferences.py @@ -17,11 +17,15 @@ class Preferences(wx.Dialog): def __init__( self, parent, id = ID, title = _("Preferences"), size=wx.DefaultSize,\ pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE): - pre = wx.PreDialog() - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) - pre.Create(parent, ID, title, pos, size, style) + try: + pre = wx.PreDialog() + pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) + pre.Create(parent, ID, title, pos, size, style) - self.PostCreate(pre) + self.PostCreate(pre) + except AttributeError: + wx.Dialog.__init__(self, parent, ID, title, pos, size, style) + self.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) sizer = wx.BoxSizer(wx.VERTICAL) @@ -55,7 +59,7 @@ class Preferences(wx.Dialog): btnsizer.Realize() - sizer.AddSizer(btnsizer, 10, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5) + sizer.Add(btnsizer, 10, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5) self.SetSizer(sizer) sizer.Fit(self) diff --git a/invesalius/gui/task_exporter.py b/invesalius/gui/task_exporter.py index 3b62522..da5b49d 100644 --- a/invesalius/gui/task_exporter.py +++ b/invesalius/gui/task_exporter.py @@ -21,7 +21,12 @@ import os import sys import wx -import wx.lib.hyperlink as hl + +try: + import wx.lib.agw.hyperlink as hl +except ImportError: + import wx.lib.hyperlink as hl + import wx.lib.platebtn as pbtn from wx.lib.pubsub import pub as Publisher diff --git a/invesalius/gui/task_importer.py b/invesalius/gui/task_importer.py index ecd1903..263b2dd 100644 --- a/invesalius/gui/task_importer.py +++ b/invesalius/gui/task_importer.py @@ -20,8 +20,12 @@ import os import sys import wx -import wx.lib.hyperlink as hl +try: + import wx.lib.agw.hyperlink as hl +except ImportError: + import wx.lib.hyperlink as hl import wx.lib.platebtn as pbtn + from wx.lib.pubsub import pub as Publisher import invesalius.constants as const @@ -222,7 +226,7 @@ class InnerTaskPanel(wx.Panel): def ImportPACS(self): - print "TODO: Send Signal - Import DICOM files from PACS" + print("TODO: Send Signal - Import DICOM files from PACS") ####### @@ -264,7 +268,7 @@ class InnerTaskPanel(wx.Panel): """ # Remove each project from sizer - for i in xrange(0, self.proj_count): + for i in range(0, self.proj_count): self.sizer.Remove(self.float_hyper_list[i]) # Delete hyperlinks diff --git a/invesalius/gui/task_navigator.py b/invesalius/gui/task_navigator.py index 80a876f..f7b297c 100644 --- a/invesalius/gui/task_navigator.py +++ b/invesalius/gui/task_navigator.py @@ -23,9 +23,15 @@ import os import numpy as np import wx -import wx.lib.hyperlink as hl + +try: + import wx.lib.agw.hyperlink as hl + import wx.lib.agw.foldpanelbar as fpb +except ImportError: + import wx.lib.hyperlink as hl + import wx.lib.foldpanelbar as fpb + import wx.lib.masked.numctrl -import wx.lib.foldpanelbar as fpb from wx.lib.pubsub import pub as Publisher import wx.lib.colourselect as csel import wx.lib.platebtn as pbtn @@ -42,6 +48,7 @@ import invesalius.data.trackers as dt import invesalius.data.trigger as trig import invesalius.data.record_coords as rec import invesalius.gui.dialogs as dlg +from invesalius import utils BTN_NEW = wx.NewId() BTN_IMPORT_LOCAL = wx.NewId() @@ -114,7 +121,10 @@ class FoldPanel(wx.Panel): class InnerFoldPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) self.__bind_events() @@ -253,7 +263,10 @@ class InnerFoldPanel(wx.Panel): class NeuronavigationPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) self.SetAutoLayout(1) @@ -300,8 +313,8 @@ class NeuronavigationPanel(wx.Panel): tips_img = const.TIPS_IMG for k in btns_img: - n = btns_img[k].keys()[0] - lab = btns_img[k].values()[0] + n = list(btns_img[k].keys())[0] + lab = list(btns_img[k].values())[0] self.btns_coord[n] = wx.ToggleButton(self, k, label=lab, size=wx.Size(45, 23)) self.btns_coord[n].SetToolTip(wx.ToolTip(tips_img[n])) self.btns_coord[n].Bind(wx.EVT_TOGGLEBUTTON, self.OnImageFiducials) @@ -311,8 +324,8 @@ class NeuronavigationPanel(wx.Panel): tips_trk = const.TIPS_TRK for k in btns_trk: - n = btns_trk[k].keys()[0] - lab = btns_trk[k].values()[0] + n = list(btns_trk[k].keys())[0] + lab = list(btns_trk[k].values())[0] self.btns_coord[n] = wx.Button(self, k, label=lab, size=wx.Size(45, 23)) self.btns_coord[n].SetToolTip(wx.ToolTip(tips_trk[n-3])) # Exception for event of button that set image coordinates @@ -393,8 +406,8 @@ class NeuronavigationPanel(wx.Panel): marker_id = pubsub_evt.data[0] coord = pubsub_evt.data[1] for n in const.BTNS_IMG_MKS: - btn_id = const.BTNS_IMG_MKS[n].keys()[0] - fid_id = const.BTNS_IMG_MKS[n].values()[0] + btn_id = list(const.BTNS_IMG_MKS[n].keys())[0] + fid_id = list(const.BTNS_IMG_MKS[n].values())[0] if marker_id == fid_id and not self.btns_coord[btn_id].GetValue(): self.btns_coord[btn_id].SetValue(True) self.fiducials[btn_id, :] = coord[0:3] @@ -461,11 +474,11 @@ class NeuronavigationPanel(wx.Panel): if not self.trk_init[0]: dlg.NavigationTrackerWarning(self.tracker_id, self.trk_init[1]) ctrl.SetSelection(0) - print "Tracker not connected!" + print("Tracker not connected!") else: Publisher.sendMessage('Update status text in GUI', _("Ready")) ctrl.SetSelection(self.tracker_id) - print "Tracker connected!" + print("Tracker connected!") elif choice == 6: if trck: Publisher.sendMessage('Update status text in GUI', _("Disconnecting tracker ...")) @@ -477,10 +490,10 @@ class NeuronavigationPanel(wx.Panel): self.tracker_id = 0 ctrl.SetSelection(self.tracker_id) Publisher.sendMessage('Update status text in GUI', _("Tracker disconnected")) - print "Tracker disconnected!" + print("Tracker disconnected!") else: Publisher.sendMessage('Update status text in GUI', _("Tracker still connected")) - print "Tracker still connected!" + print("Tracker still connected!") else: ctrl.SetSelection(self.tracker_id) @@ -506,11 +519,11 @@ class NeuronavigationPanel(wx.Panel): # TODO: Improve the restarting of trackers after changing reference mode # self.OnChoiceTracker(None, ctrl) Publisher.sendMessage('Update tracker initializer', (self.tracker_id, self.trk_init, self.ref_mode_id)) - print "Reference mode changed!" + print("Reference mode changed!") def OnSetImageCoordinates(self, evt): # FIXME: Cross does not update in last clicked slice, only on the other two - btn_id = const.BTNS_TRK[evt.GetId()].keys()[0] + btn_id = list(const.BTNS_TRK[evt.GetId()].keys())[0] ux, uy, uz = self.numctrls_coord[btn_id][0].GetValue(),\ self.numctrls_coord[btn_id][1].GetValue(),\ @@ -518,12 +531,12 @@ class NeuronavigationPanel(wx.Panel): Publisher.sendMessage('Set ball reference position', (ux, uy, uz)) # Publisher.sendMessage('Set camera in volume', (ux, uy, uz)) - Publisher.sendMessage('Co-registered points', (ux, uy, uz, 0., 0., 0.)) + Publisher.sendMessage('Co-registered points', ((ux, uy, uz), (0., 0., 0.))) Publisher.sendMessage('Update cross position', (ux, uy, uz)) def OnImageFiducials(self, evt): - btn_id = const.BTNS_IMG_MKS[evt.GetId()].keys()[0] - marker_id = const.BTNS_IMG_MKS[evt.GetId()].values()[0] + btn_id = list(const.BTNS_IMG_MKS[evt.GetId()].keys())[0] + marker_id = list(const.BTNS_IMG_MKS[evt.GetId()].values())[0] if self.btns_coord[btn_id].GetValue(): coord = self.numctrls_coord[btn_id][0].GetValue(),\ @@ -540,7 +553,7 @@ class NeuronavigationPanel(wx.Panel): Publisher.sendMessage('Delete fiducial marker', marker_id) def OnTrackerFiducials(self, evt): - btn_id = const.BTNS_TRK[evt.GetId()].keys()[0] + btn_id = list(const.BTNS_TRK[evt.GetId()].keys())[0] coord = None if self.trk_init and self.tracker_id: @@ -704,7 +717,10 @@ class NeuronavigationPanel(wx.Panel): class ObjectRegistrationPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) self.coil_list = const.COIL @@ -917,7 +933,7 @@ class ObjectRegistrationPanel(wx.Panel): else: filename = dlg.ShowSaveRegistrationDialog("object_registration.obr") if filename: - hdr = 'Object' + "\t" + self.obj_name + "\t" + 'Reference' + "\t" + str('%d' % self.obj_ref_mode) + hdr = 'Object' + "\t" + utils.decode(self.obj_name, const.FS_ENCODE) + "\t" + 'Reference' + "\t" + str('%d' % self.obj_ref_mode) data = np.hstack([self.obj_fiducials, self.obj_orients]) np.savetxt(filename, data, fmt='%.4f', delimiter='\t', newline='\n', header=hdr) wx.MessageBox(_("Object file successfully saved"), _("Save")) @@ -939,7 +955,10 @@ class ObjectRegistrationPanel(wx.Panel): class MarkersPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) self.SetAutoLayout(1) @@ -1137,7 +1156,7 @@ class MarkersPanel(wx.Panel): item = self.lc.GetItem(id_n, 4) if item.GetText() == marker_id: for i in const.BTNS_IMG_MKS: - if marker_id in const.BTNS_IMG_MKS[i].values()[0]: + if marker_id in list(const.BTNS_IMG_MKS[i].values())[0]: self.lc.Focus(item.GetId()) index = [self.lc.GetFocusedItem()] else: @@ -1192,7 +1211,7 @@ class MarkersPanel(wx.Panel): if len(line) == 11: for i in const.BTNS_IMG_MKS: - if line[10] in const.BTNS_IMG_MKS[i].values()[0]: + if line[10] in list(const.BTNS_IMG_MKS[i].values())[0]: Publisher.sendMessage('Load image fiducials', (line[10], coord)) elif line[10] == 'TARGET': target = count_line @@ -1210,7 +1229,7 @@ class MarkersPanel(wx.Panel): if len(line) == 8: for i in const.BTNS_IMG_MKS: - if line[7] in const.BTNS_IMG_MKS[i].values()[0]: + if line[7] in list(const.BTNS_IMG_MKS[i].values())[0]: Publisher.sendMessage('Load image fiducials', (line[7], coord)) else: line.append("") diff --git a/invesalius/gui/task_slice.py b/invesalius/gui/task_slice.py index 823ee91..d4e8545 100644 --- a/invesalius/gui/task_slice.py +++ b/invesalius/gui/task_slice.py @@ -21,9 +21,15 @@ import sys import os import wx -import wx.lib.hyperlink as hl + +try: + import wx.lib.agw.hyperlink as hl + import wx.lib.agw.foldpanelbar as fpb +except ImportError: + import wx.lib.hyperlink as hl + import wx.lib.foldpanelbar as fpb + import wx.lib.platebtn as pbtn -import wx.lib.foldpanelbar as fpb import wx.lib.colourselect as csel from wx.lib.pubsub import pub as Publisher @@ -110,7 +116,10 @@ class InnerTaskPanel(wx.Panel): #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_SCROLLBAR) #print wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUHILIGHT) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) fold_panel = FoldPanel(self) fold_panel.SetBackgroundColour(default_colour) self.fold_panel = fold_panel @@ -136,7 +145,7 @@ class InnerTaskPanel(wx.Panel): main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(line_new, 0,wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) main_sizer.Add(fold_panel, 1, wx.GROW|wx.EXPAND|wx.ALL, 5) - main_sizer.AddSizer(line_sizer, 0, wx.GROW|wx.EXPAND) + main_sizer.Add(line_sizer, 0, wx.GROW|wx.EXPAND) main_sizer.AddSpacer(5) main_sizer.Fit(self) @@ -238,7 +247,10 @@ class FoldPanel(wx.Panel): class InnerFoldPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) # Fold panel and its style settings @@ -508,10 +520,10 @@ class MaskProperties(wx.Panel): def CloseProject(self): n = self.combo_mask_name.GetCount() - for i in xrange(n-1, -1, -1): + for i in range(n-1, -1, -1): self.combo_mask_name.Delete(i) n = self.combo_thresh.GetCount() - for i in xrange(n-1, -1, -1): + for i in range(n-1, -1, -1): self.combo_thresh.Delete(i) def OnRemoveMasks(self, pubsub_evt): @@ -659,14 +671,17 @@ class MaskProperties(wx.Panel): session.ChangeProject() def OnSelectColour(self, evt): - colour = evt.GetValue() + colour = evt.GetValue()[:3] self.gradient.SetColour(colour) Publisher.sendMessage('Change mask colour', colour) class EditionTools(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) ## LINE 1 @@ -830,7 +845,10 @@ class EditionTools(wx.Panel): class WatershedTool(EditionTools): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) ## LINE 1 diff --git a/invesalius/gui/task_surface.py b/invesalius/gui/task_surface.py index d2001e8..357ffb1 100644 --- a/invesalius/gui/task_surface.py +++ b/invesalius/gui/task_surface.py @@ -20,9 +20,15 @@ import sys import os import wx -import wx.lib.hyperlink as hl + +try: + import wx.lib.agw.hyperlink as hl + import wx.lib.agw.foldpanelbar as fpb +except ImportError: + import wx.lib.hyperlink as hl + import wx.lib.foldpanelbar as fpb + from wx.lib.pubsub import pub as Publisher -import wx.lib.foldpanelbar as fpb import wx.lib.colourselect as csel import invesalius.constants as const @@ -211,7 +217,10 @@ class FoldPanel(wx.Panel): class InnerFoldPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) # Fold panel and its style settings @@ -280,7 +289,10 @@ BTN_SEEDS = wx.NewId() class SurfaceTools(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) #self.SetBackgroundColour(wx.Colour(255,255,255)) @@ -411,12 +423,12 @@ class SurfaceTools(wx.Panel): self.EndSeeding() def StartSeeding(self): - print "Start Seeding" + print("Start Seeding") Publisher.sendMessage('Enable style', const.VOLUME_STATE_SEED) Publisher.sendMessage('Create surface by seeding - start') def EndSeeding(self): - print "End Seeding" + print("End Seeding") Publisher.sendMessage('Disable style', const.VOLUME_STATE_SEED) Publisher.sendMessage('Create surface by seeding - end') @@ -425,7 +437,10 @@ class SurfaceTools(wx.Panel): class SurfaceProperties(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) self.surface_list = [] @@ -526,7 +541,7 @@ class SurfaceProperties(wx.Panel): def CloseProject(self): n = self.combo_surface_name.GetCount() - for i in xrange(n-1, -1, -1): + for i in range(n-1, -1, -1): self.combo_surface_name.Delete(i) self.surface_list = [] @@ -587,7 +602,10 @@ class QualityAdjustment(wx.Panel): def __init__(self, parent): import invesalius.constants as const wx.Panel.__init__(self, parent) - default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) self.SetBackgroundColour(default_colour) # LINE 1 @@ -643,7 +661,7 @@ class QualityAdjustment(wx.Panel): self.SetAutoLayout(1) def OnComboQuality(self, evt): - print "TODO: Send Signal - Change surface quality: %s" % (evt.GetString()) + print("TODO: Send Signal - Change surface quality: %s" % (evt.GetString())) def OnDecimate(self, evt): - print "TODO: Send Signal - Decimate: %s" % float(self.spin.GetValue())/100 + print("TODO: Send Signal - Decimate: %s" % float(self.spin.GetValue())/100) diff --git a/invesalius/gui/task_tools.py b/invesalius/gui/task_tools.py index d3d4bb4..56cfb41 100644 --- a/invesalius/gui/task_tools.py +++ b/invesalius/gui/task_tools.py @@ -20,7 +20,12 @@ import wx import os import wx.lib.embeddedimage as emb -import wx.lib.hyperlink as hl + +try: + import wx.lib.agw.hyperlink as hl +except ImportError: + import wx.lib.hyperlink as hl + import wx.lib.platebtn as pbtn from wx.lib.pubsub import pub as Publisher @@ -120,7 +125,7 @@ class InnerTaskPanel(wx.Panel): self.sizer = main_sizer def OnTextAnnotation(self, evt=None): - print "TODO: Send Signal - Add text annotation (both 2d and 3d)" + print("TODO: Send Signal - Add text annotation (both 2d and 3d)") def OnLinkLinearMeasure(self): Publisher.sendMessage('Enable style', diff --git a/invesalius/gui/widgets/clut_imagedata.py b/invesalius/gui/widgets/clut_imagedata.py index 13cc17a..bfb290f 100644 --- a/invesalius/gui/widgets/clut_imagedata.py +++ b/invesalius/gui/widgets/clut_imagedata.py @@ -1,3 +1,4 @@ +import functools import math import wx @@ -33,6 +34,7 @@ myEVT_CLUT_NODE_CHANGED = wx.NewEventType() EVT_CLUT_NODE_CHANGED = wx.PyEventBinder(myEVT_CLUT_NODE_CHANGED, 1) +@functools.total_ordering class Node(object): def __init__(self, value, colour): self.value = value @@ -41,6 +43,12 @@ class Node(object): def __cmp__(self, o): return cmp(self.value, o.value) + def __lt__(self, other): + return self.value < other.value + + def __eq__(self, other): + return self.value == other.value + def __repr__(self): return "(%d %s)" % (self.value, self.colour) @@ -147,7 +155,7 @@ class CLUTImageDataWidget(wx.Panel): prop_y = (h) * 1.0 / (y_end - y_init) self._d_hist = [] - for i in xrange(w): + for i in range(w): x = i / prop_x + x_init - 1 if self.i_init <= x < self.i_end: try: @@ -218,7 +226,7 @@ class CLUTImageDataWidget(wx.Panel): self.middle_pressed = False def OnClick(self, evt): - px, py = evt.GetPositionTuple() + px, py = evt.GetPosition() self.left_pressed = True self.selected_node = self.get_node_clicked(px, py) self.last_selected = self.selected_node @@ -231,7 +239,7 @@ class CLUTImageDataWidget(wx.Panel): def OnDoubleClick(self, evt): w, h = self.GetVirtualSize() - px, py = evt.GetPositionTuple() + px, py = evt.GetPosition() # Verifying if the user double-click in a node-colour. selected_node = self.get_node_clicked(px, py) @@ -240,7 +248,7 @@ class CLUTImageDataWidget(wx.Panel): # option to change the color from this node. colour_dialog = wx.GetColourFromUser(self, (0, 0, 0)) if colour_dialog.IsOk(): - r, g, b = colour_dialog.Get() + r, g, b = colour_dialog.Get()[:3] selected_node.colour = r, g, b self._generate_event() else: @@ -255,7 +263,7 @@ class CLUTImageDataWidget(wx.Panel): def OnRightClick(self, evt): w, h = self.GetVirtualSize() - px, py = evt.GetPositionTuple() + px, py = evt.GetPosition() selected_node = self.get_node_clicked(px, py) if selected_node: diff --git a/invesalius/gui/widgets/clut_raycasting.py b/invesalius/gui/widgets/clut_raycasting.py index 158cbdc..99e5b7c 100644 --- a/invesalius/gui/widgets/clut_raycasting.py +++ b/invesalius/gui/widgets/clut_raycasting.py @@ -97,8 +97,8 @@ class Button(object): """ Test if the button was clicked. """ - print self.position - print self.size + print(self.position) + print(self.size) m_x, m_y = position i_x, i_y = self.position w, h = self.size @@ -146,7 +146,7 @@ class CLUTRaycastingWidget(wx.Panel): Se the range from hounsfield """ self.init, self.end = range - print "Range", range + print("Range", range) self.CalculatePixelPoints() def SetPadding(self, padding): @@ -169,9 +169,9 @@ class CLUTRaycastingWidget(wx.Panel): pass def OnClick(self, evt): - x, y = evt.GetPositionTuple() - if self.save_button.HasClicked(evt.GetPositionTuple()): - print "Salvando" + x, y = evt.GetPosition() + if self.save_button.HasClicked((x, y)): + print("Salvando") filename = dialog.ShowSavePresetDialog() if filename: Publisher.sendMessage('Save raycasting preset', filename) @@ -218,7 +218,7 @@ class CLUTRaycastingWidget(wx.Panel): """ Used to change the colour of a point """ - point = self._has_clicked_in_a_point(evt.GetPositionTuple()) + point = self._has_clicked_in_a_point(evt.GetPosition()) if point: i, j = point actual_colour = self.curves[i].nodes[j].colour @@ -240,18 +240,18 @@ class CLUTRaycastingWidget(wx.Panel): """ Used to remove a point """ - point = self._has_clicked_in_a_point(evt.GetPositionTuple()) + point = self._has_clicked_in_a_point(evt.GetPosition()) if point: i, j = point - print "RightClick", i, j + print("RightClick", i, j) self.RemovePoint(i, j) self.Refresh() nevt = CLUTEvent(myEVT_CLUT_POINT_RELEASE, self.GetId(), i) self.GetEventHandler().ProcessEvent(nevt) return - n_curve = self._has_clicked_in_selection_curve(evt.GetPositionTuple()) + n_curve = self._has_clicked_in_selection_curve(evt.GetPosition()) if n_curve is not None: - print "Removing a curve" + print("Removing a curve") self.RemoveCurve(n_curve) self.Refresh() nevt = CLUTEvent(myEVT_CLUT_POINT_RELEASE, self.GetId(), n_curve) @@ -280,7 +280,7 @@ class CLUTRaycastingWidget(wx.Panel): direction = evt.GetWheelRotation() / evt.GetWheelDelta() init = self.init - RANGE * direction end = self.end + RANGE * direction - print direction, init, end + print(direction, init, end) self.SetRange((init, end)) self.Refresh() @@ -369,7 +369,7 @@ class CLUTRaycastingWidget(wx.Panel): def _has_clicked_in_save(self, clicked_point): x, y = clicked_point - print x, y + print(x, y) if self.padding < x < self.padding + 24 and \ self.padding < y < self.padding + 24: return True @@ -559,7 +559,7 @@ class CLUTRaycastingWidget(wx.Panel): def _draw_histogram(self, ctx, height): # The histogram x,y = self.Histogram.points[0] - print "=>", x,y + print("=>", x,y) ctx.SetPen(wx.Pen(HISTOGRAM_LINE_COLOUR, HISTOGRAM_LINE_WIDTH)) ctx.SetBrush(wx.Brush(HISTOGRAM_FILL_COLOUR)) @@ -567,7 +567,7 @@ class CLUTRaycastingWidget(wx.Panel): path = ctx.CreatePath() path.MoveToPoint(x,y) for x,y in self.Histogram.points: - print x,y + print(x,y) path.AddLineToPoint(x, y) ctx.PushState() @@ -624,7 +624,7 @@ class CLUTRaycastingWidget(wx.Panel): proportion_x = width * 1.0 / (x_end - x_init) proportion_y = height * 1.0 / (y_end - y_init) self.Histogram.points = [] - for i in xrange(0, len(self.histogram_array), 5): + for i in range(0, len(self.histogram_array), 5): if self.histogram_array[i]: y = math.log(self.histogram_array[i]) else: @@ -649,7 +649,7 @@ class CLUTRaycastingWidget(wx.Panel): """ for n, (point, colour) in enumerate(zip(self.points, self.colours)): point_colour = zip(point, colour) - point_colour.sort(key=lambda x: x[0]['x']) + point_colour = sorted(point_colour, key=lambda x: x[0]['x']) self.points[n] = [i[0] for i in point_colour] self.colours[n] = [i[1] for i in point_colour] diff --git a/invesalius/gui/widgets/gradient.py b/invesalius/gui/widgets/gradient.py index e93dd95..fe246ae 100755 --- a/invesalius/gui/widgets/gradient.py +++ b/invesalius/gui/widgets/gradient.py @@ -121,8 +121,11 @@ class GradientSlider(wx.Panel): dc.GradientFillLinear((x_init_gradient, y_init_gradient, width_gradient, height_gradient), (0, 0, 0), (255,255, 255)) - - n = wx.RendererNative_Get() + + try: + n = wx.RendererNative.Get() + except AttributeError: + n = wx.RendererNative_Get() # Drawing the push buttons n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h)) @@ -327,7 +330,7 @@ class GradientCtrl(wx.Panel): self.max_range = maxRange self.minimun = minValue self.maximun = maxValue - self.colour = colour + self.colour = colour[:3] self.changed = False self._draw_controls() self._bind_events_wx() @@ -433,7 +436,7 @@ class GradientCtrl(wx.Panel): self._GenerateEvent(myEVT_THRESHOLD_CHANGING) def SetColour(self, colour): - colour = list(colour) + [90,] + colour = list(colour[:3]) + [90,] self.colour = colour self.gradient_slider.SetColour(colour) self.gradient_slider.Refresh() diff --git a/invesalius/gui/widgets/listctrl.py b/invesalius/gui/widgets/listctrl.py index 4d88c05..76017c3 100644 --- a/invesalius/gui/widgets/listctrl.py +++ b/invesalius/gui/widgets/listctrl.py @@ -63,7 +63,7 @@ class ColumnSorterMixin: self.SetColumnCount(numColumns) list = self.GetListCtrl() if not list: - raise ValueError, "No wx.ListCtrl available" + raise ValueError("No wx.ListCtrl available") list.Bind(wx.EVT_LIST_COL_CLICK, self.__OnColClick, list) diff --git a/invesalius/gui/widgets/slice_menu.py b/invesalius/gui/widgets/slice_menu.py index aaab3f7..b46ba6e 100644 --- a/invesalius/gui/widgets/slice_menu.py +++ b/invesalius/gui/widgets/slice_menu.py @@ -183,17 +183,17 @@ class SliceMenu(wx.Menu): def FirstItemSelect(self, pusub_evt): item = self.ID_TO_TOOL_ITEM[self.id_wl_first] - item.Check(1) + item.Check(True) for i in self.pseudo_color_items: it = self.pseudo_color_items[i] if it.IsChecked(): - it.Toggle() + it.Check(False) item = self.ID_TO_TOOL_ITEM[self.id_pseudo_first] - item.Check(1) + item.Check(True) - item = self.ID_TO_TOOL_ITEM[self.id_tiling_first] - item.Check(1) + # item = self.ID_TO_TOOL_ITEM[self.id_tiling_first] + # item.Check(True) def CheckWindowLevelOther(self, pubsub_evt): item = self.ID_TO_TOOL_ITEM[self.other_wl_id] diff --git a/invesalius/i18n.py b/invesalius/i18n.py index d64b954..c47340a 100644 --- a/invesalius/i18n.py +++ b/invesalius/i18n.py @@ -83,6 +83,10 @@ def InstallLanguage(language): lang = gettext.translation('invesalius', language_dir,\ languages=[language], codeset='utf8') - # Using unicode - lang.install(unicode=1) - return lang.ugettext + # Using unicode + try: + lang.install(unicode=1) + return lang.ugettext + except TypeError: + lang.install() + return lang.gettext diff --git a/invesalius/net/dicom.py b/invesalius/net/dicom.py index d69b9f2..9ef858f 100644 --- a/invesalius/net/dicom.py +++ b/invesalius/net/dicom.py @@ -165,14 +165,14 @@ class DicomNet: const char *call=NULL, const char *outputdir=NULL)""" - print ">>>>>", self.address, int(self.port), theQuery, 11112, self.aetitle,\ - self.aetitle_call, "/home/phamorim/Desktop/output/" + print(">>>>>", self.address, int(self.port), theQuery, 11112, self.aetitle, + self.aetitle_call, "/home/phamorim/Desktop/output/") cnf.CMove(self.address, int(self.port), theQuery, 11112, self.aetitle,\ self.aetitle_call, "/home/phamorim/Desktop/") - print "BAIXOUUUUUUUU" + print("BAIXOUUUUUUUU") #ret = gdcm.DataSetArrayType() #cnf.CFind(self.address, int(self.port), theQuery, ret, self.aetitle,\ diff --git a/invesalius/presets.py b/invesalius/presets.py index 401ceee..39ea1f8 100644 --- a/invesalius/presets.py +++ b/invesalius/presets.py @@ -43,7 +43,7 @@ class Presets(): _("Fat Tissue (Child)"):(-212,-72), _("Skin Tissue (Adult)"):(-718,-177), _("Skin Tissue (Child)"):(-766,-202), - _("Custom"):('', '') + _("Custom"):(0, 0) }) self.thresh_mri = TwoWaysDictionary({ @@ -61,7 +61,7 @@ class Presets(): _("Fat Tissue (Child)"):(812,952), _("Skin Tissue (Adult)"):(306,847), _("Skin Tissue (Child)"):(258,822), - _("Custom"):('', '') + _("Custom"):(0, 0) }) self.__bind_events() @@ -78,6 +78,7 @@ class Presets(): for key in presets: (t_min, t_max) = presets[key] + print(key, t_min, t_max) if (t_min is None) or (t_max is None): # setting custom preset t_min = thresh_min @@ -181,7 +182,7 @@ def get_wwwl_preset_colours(pfile): preset = plistlib.readPlist(pfile) ncolours = len(preset['Blue']) colours = [] - for i in xrange(ncolours): + for i in range(ncolours): r = preset['Red'][i] g = preset['Green'][i] b = preset['Blue'][i] diff --git a/invesalius/project.py b/invesalius/project.py index 6edd077..ad9879c 100644 --- a/invesalius/project.py +++ b/invesalius/project.py @@ -17,6 +17,8 @@ # detalhes. #-------------------------------------------------------------------------- +from six import with_metaclass + import datetime import glob import os @@ -33,7 +35,7 @@ import vtk import invesalius.constants as const import invesalius.data.polydata_utils as pu from invesalius.presets import Presets -from invesalius.utils import Singleton, debug, touch +from invesalius.utils import Singleton, debug, touch, decode import invesalius.version as version if sys.platform == 'win32': @@ -45,11 +47,9 @@ if sys.platform == 'win32': else: _has_win32api = False -class Project(object): - # Only one project will be initialized per time. Therefore, we use - # Singleton design pattern for implementing it - __metaclass__= Singleton - +# Only one project will be initialized per time. Therefore, we use +# Singleton design pattern for implementing it +class Project(with_metaclass(Singleton, object)): def __init__(self): # Patient/ acquistion information self.name = '' @@ -205,7 +205,7 @@ class Project(object): return measures def SavePlistProject(self, dir_, filename, compress=False): - dir_temp = tempfile.mkdtemp().decode(const.FS_ENCODE) + dir_temp = decode(tempfile.mkdtemp(), const.FS_ENCODE) self.compress = compress @@ -357,7 +357,7 @@ def Compress(folder, filename, filelist, compress=False): touch(temp_inv3) temp_inv3 = win32api.GetShortPathName(temp_inv3) - temp_inv3 = temp_inv3.decode(const.FS_ENCODE) + temp_inv3 = decode(temp_inv3, const.FS_ENCODE) #os.chdir(tmpdir) #file_list = glob.glob(os.path.join(tmpdir_,"*")) if compress: @@ -374,16 +374,16 @@ def Compress(folder, filename, filelist, compress=False): def Extract(filename, folder): if _has_win32api: folder = win32api.GetShortPathName(folder) - folder = folder.decode(const.FS_ENCODE) + folder = decode(folder, const.FS_ENCODE) tar = tarfile.open(filename, "r") - idir = os.path.split(tar.getnames()[0])[0].decode('utf8') + idir = decode(os.path.split(tar.getnames()[0])[0], 'utf8') os.mkdir(os.path.join(folder, idir)) filelist = [] for t in tar.getmembers(): fsrc = tar.extractfile(t) - fname = os.path.join(folder, t.name.decode('utf-8')) - fdst = file(fname, 'wb') + fname = os.path.join(folder, decode(t.name, 'utf-8')) + fdst = open(fname, 'wb') shutil.copyfileobj(fsrc, fdst) filelist.append(fname) fsrc.close() diff --git a/invesalius/reader/bitmap_reader.py b/invesalius/reader/bitmap_reader.py index 78e049d..2b09df0 100644 --- a/invesalius/reader/bitmap_reader.py +++ b/invesalius/reader/bitmap_reader.py @@ -17,7 +17,6 @@ # detalhes. #-------------------------------------------------------------------------- import os -import Queue import threading import tempfile import sys @@ -136,7 +135,7 @@ class LoadBitmap: def __init__(self, bmp_file, filepath): self.bmp_file = bmp_file - self.filepath = filepath + self.filepath = utils.decode(filepath, const.FS_ENCODE) self.run() @@ -355,8 +354,10 @@ def ReadBitmap(filepath): filepath = win32api.GetShortPathName(filepath) if t == False: - measures_info = GetPixelSpacingFromInfoFile(filepath) - + try: + measures_info = GetPixelSpacingFromInfoFile(filepath) + except UnicodeDecodeError: + measures_info = False if measures_info: Publisher.sendMessage('Set bitmap spacing', measures_info) @@ -377,6 +378,9 @@ def ReadBitmap(filepath): def GetPixelSpacingFromInfoFile(filepath): + filepath = utils.decode(filepath, const.FS_ENCODE) + if filepath.endswith('.DS_Store'): + return False fi = open(filepath, 'r') lines = fi.readlines() measure_scale = 'mm' diff --git a/invesalius/reader/dicom.py b/invesalius/reader/dicom.py index 960b252..41d570f 100644 --- a/invesalius/reader/dicom.py +++ b/invesalius/reader/dicom.py @@ -1240,7 +1240,7 @@ class Parser(): encoding = self.GetEncoding() try: # Returns a unicode decoded in the own dicom encoding - return name.decode(encoding, 'replace') + return utils.decode(name, encoding, 'replace') except(UnicodeEncodeError): return name @@ -1285,7 +1285,7 @@ class Parser(): try: # Returns a unicode decoded in the own dicom encoding - return name.decode(encoding, 'replace') + return utils.decode(name, encoding, 'replace') except(UnicodeEncodeError): return name @@ -1308,7 +1308,7 @@ class Parser(): encoding = self.GetEncoding() # Returns a unicode decoded in the own dicom encoding try: - return data.decode(encoding, 'replace') + return utils.decode(data, encoding, 'replace') except(UnicodeEncodeError): return data return "" @@ -1526,10 +1526,8 @@ class Parser(): try: data = self.data_image[str(0x0008)][str(0x1030)] if (data): - if isinstance(data, unicode): - return data encoding = self.GetEncoding() - return data.decode(encoding, 'replace') + return utils.decode(data, encoding, 'replace') except(KeyError): return "" @@ -1843,31 +1841,31 @@ if __name__ == "__main__": fail_count = 0 total = 48 - for i in xrange(1,total+1): + for i in range(1,total+1): filename = "..//data//"+str(i)+".dcm" parser = Parser() if parser.SetFileName(filename): - print "p:", parser.GetPatientName() - print "l:", parser.GetImageLocation() - print "o:", parser.GetImagePatientOrientation() - print "t:", parser.GetImageThickness() - print "s:", parser.GetPixelSpacing() - print "x:", parser.GetDimensionX() - print "y:", parser.GetDimensionY() - print "z:", parser.GetDimensionZ() + print("p:", parser.GetPatientName()) + print("l:", parser.GetImageLocation()) + print("o:", parser.GetImagePatientOrientation()) + print("t:", parser.GetImageThickness()) + print("s:", parser.GetPixelSpacing()) + print("x:", parser.GetDimensionX()) + print("y:", parser.GetDimensionY()) + print("z:", parser.GetDimensionZ()) else: - print "--------------------------------------------------" + print("--------------------------------------------------") total-=1 fail_count+=1 - print "\nREPORT:" - print "failed: ", fail_count - print "sucess: ", total + print("\nREPORT:") + print("failed: ", fail_count) + print("sucess: ", total) # Example of how to use auxiliary functions total = 38 - for i in xrange(1,total+1): + for i in range(1,total+1): if (i==8) or (i==9) or (i==13): pass else: diff --git a/invesalius/reader/dicom_grouper.py b/invesalius/reader/dicom_grouper.py index 6cb297b..6daa7fd 100644 --- a/invesalius/reader/dicom_grouper.py +++ b/invesalius/reader/dicom_grouper.py @@ -124,7 +124,7 @@ class DicomGroup: # (interpolated) if _has_win32api: - filelist = [win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE) + filelist = [win32api.GetShortPathName(dicom.image.file) for dicom in self.slices_dict.values()] else: @@ -132,16 +132,19 @@ class DicomGroup: self.slices_dict.values()] # Sort slices using GDCM - if (self.dicom.image.orientation_label <> "CORONAL"): + if (self.dicom.image.orientation_label != "CORONAL"): #Organize reversed image sorter = gdcm.IPPSorter() sorter.SetComputeZSpacing(True) sorter.SetZSpacingTolerance(1e-10) - sorter.Sort(filelist) + try: + sorter.Sort([utils.encode(i, const.FS_ENCODE) for i in filelist]) + except TypeError: + sorter.Sort(filelist) filelist = sorter.GetFilenames() # for breast-CT of koning manufacturing (KBCT) - if self.slices_dict.values()[0].parser.GetManufacturerName() == "Koning": + if list(self.slices_dict.values())[0].parser.GetManufacturerName() == "Koning": filelist.sort() return filelist @@ -149,7 +152,7 @@ class DicomGroup: def GetHandSortedList(self): # This will be used to fix problem 1, after merging # single DicomGroups of same study_id and orientation - list_ = self.slices_dict.values() + list_ = list(self.slices_dict.values()) dicom = list_[0] axis = ORIENT_MAP[dicom.image.orientation_label] #list_ = sorted(list_, key = lambda dicom:dicom.image.position[axis]) @@ -173,7 +176,7 @@ class DicomGroup: def GetDicomSample(self): size = len(self.slices_dict) - dicom = self.GetHandSortedList()[size/2] + dicom = self.GetHandSortedList()[size//2] return dicom class PatientGroup: @@ -306,7 +309,7 @@ class PatientGroup: # 3rd STEP: CHECK DIFFERENCES axis = ORIENT_MAP[group_key[0]] # based on orientation - for index in xrange(len(sorted_list)-1): + for index in range(len(sorted_list)-1): current = sorted_list[index] next = sorted_list[index+1] diff --git a/invesalius/reader/dicom_reader.py b/invesalius/reader/dicom_reader.py index 12c3cbc..0fbf53e 100644 --- a/invesalius/reader/dicom_reader.py +++ b/invesalius/reader/dicom_reader.py @@ -17,7 +17,6 @@ # detalhes. #-------------------------------------------------------------------------- import os -import Queue import threading import tempfile import sys @@ -79,7 +78,7 @@ def SelectLargerDicomGroup(patient_group): def SortFiles(filelist, dicom): # Sort slices # FIXME: Coronal Crash. necessary verify - if (dicom.image.orientation_label <> "CORONAL"): + if (dicom.image.orientation_label != "CORONAL"): ##Organize reversed image sorter = gdcm.IPPSorter() sorter.SetComputeZSpacing(True) @@ -96,27 +95,29 @@ main_dict = {} dict_file = {} class LoadDicom: - def __init__(self, grouper, filepath): self.grouper = grouper - self.filepath = filepath - + self.filepath = utils.decode(filepath, const.FS_ENCODE) self.run() - + def run(self): grouper = self.grouper reader = gdcm.ImageReader() if _has_win32api: - reader.SetFileName(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE)) + try: + reader.SetFileName(utils.encode(win32api.GetShortPathName(self.filepath), + const.FS_ENCODE)) + except TypeError: + reader.SetFileName(win32api.GetShortPathName(self.filepath)) else: - reader.SetFileName(self.filepath) - + try: + reader.SetFileName(utils.encode(self.filepath, const.FS_ENCODE)) + except TypeError: + reader.SetFileName(self.filepath) if (reader.Read()): file = reader.GetFile() - # Retrieve data set dataSet = file.GetDataSet() - # Retrieve header header = file.GetHeader() stf = gdcm.StringFilter() @@ -158,7 +159,7 @@ class LoadDicom: data_dict[group] = {} if not(utils.VerifyInvalidPListCharacter(data[1])): - data_dict[group][field] = data[1].decode(encoding) + data_dict[group][field] = utils.decode(data[1], encoding) else: data_dict[group][field] = "Invalid Character" @@ -183,7 +184,7 @@ class LoadDicom: data_dict[group] = {} if not(utils.VerifyInvalidPListCharacter(data[1])): - data_dict[group][field] = data[1].decode(encoding, 'replace') + data_dict[group][field] = utils.decode(data[1], encoding, 'replace') else: data_dict[group][field] = "Invalid Character" @@ -201,7 +202,7 @@ class LoadDicom: window = None if _has_win32api: - thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE), window, level) + thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath), window, level) else: thumbnail_path = imagedata_utils.create_dicom_thumbnails(self.filepath, window, level) @@ -211,10 +212,10 @@ class LoadDicom: direc_cosines = img.GetDirectionCosines() orientation = gdcm.Orientation() try: - type = orientation.GetType(tuple(direc_cosines)) + _type = orientation.GetType(tuple(direc_cosines)) except TypeError: - type = orientation.GetType(direc_cosines) - label = orientation.GetLabel(type) + _type = orientation.GetType(direc_cosines) + label = orientation.GetLabel(_type) # ---------- Refactory -------------------------------------- @@ -305,7 +306,7 @@ def yGetDicomGroups(directory, recursive=True, gui=True): def GetDicomGroups(directory, recursive=True): - return yGetDicomGroups(directory, recursive, gui=False).next() + return next(yGetDicomGroups(directory, recursive, gui=False)) class ProgressDicomReader: @@ -333,7 +334,7 @@ class ProgressDicomReader: def GetDicomGroups(self, path, recursive): if not const.VTK_WARNING: - log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt').encode(const.FS_ENCODE) + log_path = utils.encode(os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt'), const.FS_ENCODE) fow = vtk.vtkFileOutputWindow() fow.SetFileName(log_path) ow = vtk.vtkOutputWindow() @@ -341,7 +342,7 @@ class ProgressDicomReader: y = yGetDicomGroups(path, recursive) for value_progress in y: - print ">>>>", value_progress + print(">>>>", value_progress) if not self.running: break if isinstance(value_progress, tuple): diff --git a/invesalius/session.py b/invesalius/session.py index 6d194aa..0948832 100644 --- a/invesalius/session.py +++ b/invesalius/session.py @@ -17,6 +17,8 @@ # detalhes. #-------------------------------------------------------------------------- +from six import with_metaclass + try: import configparser as ConfigParser except(ImportError): @@ -33,7 +35,7 @@ import codecs from wx.lib.pubsub import pub as Publisher import wx -from invesalius.utils import Singleton, debug +from invesalius.utils import Singleton, debug, decode from random import randint FS_ENCODE = sys.getfilesystemencoding() @@ -43,9 +45,9 @@ if sys.platform == 'win32': try: USER_DIR = expand_user() except: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = decode(os.path.expanduser('~'), FS_ENCODE) else: - USER_DIR = os.path.expanduser('~').decode(FS_ENCODE) + USER_DIR = decode(os.path.expanduser('~'), FS_ENCODE) USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius') USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets') @@ -55,10 +57,9 @@ USER_INV_CFG_PATH = os.path.join(USER_INV_DIR, 'config.cfg') SESSION_ENCODING = 'utf8' -class Session(object): - # Only one session will be initialized per time. Therefore, we use - # Singleton design pattern for implementing it - __metaclass__= Singleton +# Only one session will be initialized per time. Therefore, we use +# Singleton design pattern for implementing it +class Session(with_metaclass(Singleton, object)): def __init__(self): self.temp_item = False @@ -221,7 +222,7 @@ class Session(object): # Remove oldest projects from list if len(l)>const.PROJ_MAX: - for i in xrange(len(l)-const.PROJ_MAX): + for i in range(len(l)-const.PROJ_MAX): l.pop() def GetLanguage(self): diff --git a/invesalius/style.py b/invesalius/style.py index 3c78950..2d24d93 100644 --- a/invesalius/style.py +++ b/invesalius/style.py @@ -64,7 +64,7 @@ from wx.lib.pubsub import pub as Publisher #---------------------- -import constants as const +import invesalius.constants as const class StyleStateManager(object): # don't need to be singleton, only needs to be instantiated inside diff --git a/invesalius/utils.py b/invesalius/utils.py index 6a7a741..a30c99d 100644 --- a/invesalius/utils.py +++ b/invesalius/utils.py @@ -239,13 +239,13 @@ def calculate_resizing_tofitmemory(x_size,y_size,n_slices,byte): ram_total = psutil.phymem_usage().total swap_free = psutil.virtmem_usage().free except: - print "Exception! psutil version < 0.3 (not recommended)" + print("Exception! psutil version < 0.3 (not recommended)") ram_total = psutil.TOTAL_PHYMEM # this is for psutil < 0.3 ram_free = 0.8 * psutil.TOTAL_PHYMEM swap_free = psutil.avail_virtmem() - print "RAM_FREE=", ram_free - print "RAM_TOTAL=", ram_total + print("RAM_FREE=", ram_free) + print( "RAM_TOTAL=", ram_total) if (sys.platform == 'win32'): if (platform.architecture()[0] == '32bit'): @@ -371,8 +371,14 @@ def get_system_encoding(): def UpdateCheck(): - import urllib - import urllib2 + try: + from urllib.parse import urlencode + from urllib.request import urlopen, Request + from urllib.error import HTTPError + except ImportError: + from urllib import urlencode + from urllib2 import urlopen, Request, HTTPError + import wx import invesalius.session as ses def _show_update_info(): @@ -385,7 +391,7 @@ def UpdateCheck(): msgdlg.Show() #msgdlg.Destroy() - print "Checking updates..." + print("Checking updates...") # Check if there is a language set #import invesalius.i18n as i18n import invesalius.session as ses @@ -411,14 +417,14 @@ def UpdateCheck(): 'architecture' : platform.architecture()[0], 'language' : lang, 'random_id' : random_id } - data = urllib.urlencode(data) - req = urllib2.Request(url, data, headers) + data = urlencode(data).encode('utf8') + req = Request(url, data, headers) try: - response = urllib2.urlopen(req, timeout=10) + response = urlopen(req, timeout=10) except: return - last = response.readline().rstrip() - url = response.readline().rstrip() + last = response.readline().rstrip().decode('utf8') + url = response.readline().rstrip().decode('utf8') try: last_ver = LooseVersion(last) @@ -427,14 +433,14 @@ def UpdateCheck(): return if last_ver > actual_ver: - print " ...New update found!!! -> version:", last #, ", url=",url + print(" ...New update found!!! -> version:", last) #, ", url=",url wx.CallAfter(wx.CallLater, 1000, _show_update_info) def vtkarray_to_numpy(m): nm = np.zeros((4, 4)) - for i in xrange(4): - for j in xrange(4): + for i in range(4): + for j in range(4): nm[i, j] = m.GetElement(i, j) return nm @@ -442,3 +448,17 @@ def vtkarray_to_numpy(m): def touch(fname): with open(fname, 'a'): pass + + +def decode(text, encoding, *args): + try: + return text.decode(encoding, *args) + except AttributeError: + return text + + +def encode(text, encoding, *args): + try: + return text.encode(encoding, *args) + except AttributeError: + return text \ No newline at end of file -- libgit2 0.21.2