Commit 1b7ed2587b3a1688f9be4a0153784683e5042cb4

Authored by vhosouza
1 parent ba1f3dd5
Exists in usp-navegador

FIX: Fixing errors of git usage.

invesalius/bkps/bases.py.bak
... ... @@ -1,85 +0,0 @@
1   -from numpy import *
2   -from math import sqrt
3   -
4   -class Bases:
5   -
6   - def __init__(self, p1, p2, p3):
7   -
8   - self.p1 = array([p1[0], p1[1], p1[2]])
9   - self.p2 = array([p2[0], p2[1], p2[2]])
10   - self.p3 = array([p3[0], p3[1], p3[2]])
11   -
12   - print "p1: ", self.p1
13   - print "p2: ", self.p2
14   - print "p3: ", self.p3
15   -
16   - self.sub1 = self.p2 - self.p1
17   - self.sub2 = self.p3 - self.p1
18   -
19   - def Basecreation(self):
20   - #g1
21   - g1 = self.sub1
22   -
23   - #g2
24   - lamb1 = g1[0]*self.sub2[0] + g1[1]*self.sub2[1] + g1[2]*self.sub2[2]
25   - lamb2 = dot(g1, g1)
26   - lamb = lamb1/lamb2
27   -
28   - #Ponto q
29   - q = self.p1 + lamb*self.sub1
30   -
31   - #g1 e g2 com origem em q
32   - g1 = self.p1 - q
33   - g2 = self.p3 - q
34   -
35   - #testa se o g1 nao eh um vetor nulo
36   - if g1.any() == False:
37   - g1 = self.p2 - q
38   -
39   - #g3 - Produto vetorial NumPy
40   - g3 = cross(g2, g1)
41   -
42   - #normalizacao dos vetores
43   - g1 = g1/sqrt(lamb2)
44   - g2 = g2/sqrt(dot(g2, g2))
45   - g3 = g3/sqrt(dot(g3, g3))
46   -
47   - M = matrix([[g1[0],g1[1],g1[2]], [g2[0],g2[1],g2[2]], [g3[0],g3[1],g3[2]]])
48   - q.shape = (3, 1)
49   - q = matrix(q.copy())
50   - print"M: ", M
51   - print
52   - print"q: ", q
53   - print
54   - Minv = M.I
55   -
56   - return M, q, Minv
57   -
58   -def FlipX(point):
59   -
60   - point = matrix(point + (0,))
61   -
62   - #inverter o eixo z
63   - ## possivel explicacaoo -- origem do eixo do imagedata esta no canto
64   - ## superior esquerdo e origem da superfice eh no canto inferior esquerdo
65   - ## ou a ordem de empilhamento das fatias
66   -
67   - point[0, 2] = -point[0, 2]
68   -
69   - #Flip em y
70   - Mrot = matrix([[1.0, 0.0, 0.0, 0.0],
71   - [0.0, -1.0, 0.0, 0.0],
72   - [0.0, 0.0, -1.0, 0.0],
73   - [0.0, 0.0, 0.0, 1.0]])
74   - Mtrans = matrix([[1.0, 0, 0, -point[0, 0]],
75   - [0.0, 1.0, 0, -point[0, 1]],
76   - [0.0, 0.0, 1.0, -point[0, 2]],
77   - [0.0, 0.0, 0.0, 1.0]])
78   - Mtrans_return = matrix([[1.0, 0, 0, point[0, 0]],
79   - [0.0, 1.0, 0, point[0, 1]],
80   - [0.0, 0.0, 1.0, point[0, 2]],
81   - [0.0, 0.0, 0.0, 1.0]])
82   -
83   - point_rot = point*Mtrans*Mrot*Mtrans_return
84   - x, y, z = point_rot.tolist()[0][:3]
85   - return x, y, z
invesalius/bkps/co_registration.py.bak
... ... @@ -1,65 +0,0 @@
1   -import threading
2   -
3   -import serial
4   -import wx
5   -from wx.lib.pubsub import pub as Publisher
6   -
7   -from numpy import *
8   -from math import sqrt
9   -from time import sleep
10   -
11   -class Corregister(threading.Thread):
12   -
13   - def __init__(self, bases, flag):
14   - threading.Thread.__init__(self)
15   - self.Minv = bases[0]
16   - self.N = bases[1]
17   - self.q1 = bases[2]
18   - self.q2 = bases[3]
19   - self.flag = flag
20   - self._pause_ = 0
21   - self.start()
22   -
23   - def stop(self):
24   - # Stop neuronavigation
25   - self._pause_ = 1
26   -
27   - def Coordinates(self):
28   - #Get Polhemus points for neuronavigation
29   - ser = serial.Serial(0)
30   - ser.write("Y")
31   - ser.write("P")
32   - str = ser.readline()
33   - ser.write("Y")
34   - str = str.replace("\r\n","")
35   - str = str.replace("-"," -")
36   - aostr = [s for s in str.split()]
37   - #aoflt -> 0:letter 1:x 2:y 3:z
38   - aoflt = [float(aostr[1]), float(aostr[2]), float(aostr[3]),
39   - float(aostr[4]), float(aostr[5]), float(aostr[6])]
40   - ser.close()
41   -
42   - #Unit change: inches to millimeters
43   - x = 25.4
44   - y = 25.4
45   - z = -25.4
46   -
47   - coord = (aoflt[0]*x, aoflt[1]*y, aoflt[2]*z)
48   - return coord
49   -
50   - def run(self):
51   - while self.flag == True:
52   - #Neuronavigation with Polhemus
53   - trck = self.Coordinates()
54   - tracker = matrix([[trck[0]], [trck[1]], [trck[2]]])
55   - img = self.q1 + (self.Minv*self.N)*(tracker - self.q2)
56   - coord = [float(img[0]), float(img[1]), float(img[2])]
57   - coord_cam = float(img[0]), float(img[1]), float(img[2])
58   - Publisher.sendMessage('Set ball reference position based on bound', coord_cam)
59   - Publisher.sendMessage('Set camera in volume', coord_cam)
60   - wx.CallAfter(Publisher.sendMessage, 'Render volume viewer')
61   - wx.CallAfter(Publisher.sendMessage, 'Co-registered Points', coord)
62   - sleep(0.005)
63   -
64   - if self._pause_:
65   - return
invesalius/bkps/constants.py.bak
... ... @@ -1,563 +0,0 @@
1   -#--------------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------------
19   -
20   -import os.path
21   -import platform
22   -import sys
23   -import wx
24   -
25   -from project import Project
26   -
27   -INVESALIUS_VERSION = "3.0 beta 5"
28   -
29   -#---------------
30   -
31   -# Measurements
32   -MEASURE_NAME_PATTERN = _("M %d")
33   -MEASURE_LINEAR = 101
34   -MEASURE_ANGULAR = 102
35   -
36   -DEFAULT_MEASURE_COLOUR = (1,0,0)
37   -DEFAULT_MEASURE_BG_COLOUR = (250/255.0, 247/255.0, 218/255.0)
38   -DEFAULT_MEASURE_RADIUS = 1
39   -DEFAULT_MEASURE_TYPE = MEASURE_LINEAR
40   -
41   -PROP_MEASURE = 0.8
42   -
43   -
44   -STEREO_OFF = _(" Off")
45   -STEREO_RED_BLUE = _("Red-blue")
46   -STEREO_CRISTAL = _("CristalEyes")
47   -STEREO_INTERLACED = _("Interlaced")
48   -STEREO_LEFT = _("Left")
49   -STEREO_RIGHT = _("Right")
50   -STEREO_DRESDEN = _("Dresden")
51   -STEREO_CHECKBOARD = _("Checkboard")
52   -STEREO_ANAGLYPH = _("Anaglyph")
53   -
54   -
55   -# VTK text
56   -TEXT_SIZE_SMALL = 11
57   -TEXT_SIZE = 12
58   -TEXT_SIZE_LARGE = 16
59   -TEXT_COLOUR = (1,1,1)
60   -
61   -(X,Y) = (0.03, 0.97)
62   -(XZ, YZ) = (0.05, 0.93)
63   -TEXT_POS_LEFT_UP = (X, Y)
64   -#------------------------------------------------------------------
65   -TEXT_POS_LEFT_DOWN = (X, 1-Y) # SetVerticalJustificationToBottom
66   -
67   -TEXT_POS_LEFT_DOWN_ZERO = (X, 1-YZ)
68   -#------------------------------------------------------------------
69   -TEXT_POS_RIGHT_UP = (1-X, Y) # SetJustificationToRight
70   -#------------------------------------------------------------------
71   -TEXT_POS_RIGHT_DOWN = (1-X, 1-Y) # SetVerticalJustificationToBottom &
72   - # SetJustificationToRight
73   -#------------------------------------------------------------------
74   -TEXT_POS_HCENTRE_DOWN = (0.5, 1-Y) # SetJustificationToCentered
75   - # ChildrticalJustificationToBottom
76   -
77   -TEXT_POS_HCENTRE_DOWN_ZERO = (0.5, 1-YZ)
78   -#------------------------------------------------------------------
79   -TEXT_POS_HCENTRE_UP = (0.5, Y) # SetJustificationToCentered
80   -#------------------------------------------------------------------
81   -TEXT_POS_VCENTRE_RIGHT = (1-X, 0.5) # SetVerticalJustificationToCentered
82   - # SetJustificationToRight
83   -TEXT_POS_VCENTRE_RIGHT_ZERO = (1-XZ, 0.5)
84   -#------------------------------------------------------------------
85   -TEXT_POS_VCENTRE_LEFT = (X, 0.5) # SetVerticalJustificationToCentered
86   -#------------------------------------------------------------------
87   -
88   -
89   -# Slice orientation
90   -AXIAL = 1
91   -CORONAL = 2
92   -SAGITAL = 3
93   -VOLUME = 4
94   -SURFACE = 5
95   -
96   -# Measure type
97   -LINEAR = 6
98   -ANGULAR = 7
99   -
100   -# Colour representing each orientation
101   -ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red
102   - 'CORONAL': (0,1,0), # Green
103   - 'SAGITAL': (0,0,1)} # Blue
104   -
105   -IMPORT_INTERVAL = [_("Keep all slices"), _("Skip 1 for each 2 slices"),
106   - _("Skip 2 for each 3 slices"), _("Skip 3 for each 4 slices"),
107   - _("Skip 4 for each 5 slices"),_("Skip 5 for each 6 slices")]
108   -
109   -# Camera according to slice's orientation
110   -#CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)}
111   -#CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)}
112   -AXIAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)}
113   -AXIAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)}
114   -
115   -SAGITAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, 1, 0), "SAGITAL":(-1, 0, 0)}
116   -SAGITAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, -1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)}
117   -
118   -CORONAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, 1, 0), "SAGITAL":(-1, 0, 0)}
119   -CORONAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, -1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)}
120   -
121   -SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION],
122   - SAGITAL:[SAGITAL_SLICE_CAM_VIEW_UP, SAGITAL_SLICE_CAM_POSITION],
123   - CORONAL:[CORONAL_SLICE_CAM_VIEW_UP, CORONAL_SLICE_CAM_POSITION]}
124   -#Project Status
125   -#NEW_PROJECT = 0
126   -#OPEN_PROJECT = 1
127   -#CHANGE_PROJECT = 2
128   -#SAVE_PROJECT = 3
129   -PROJ_NEW = 0
130   -PROJ_OPEN = 1
131   -PROJ_CHANGE = 2
132   -PROJ_CLOSE = 3
133   -
134   -PROJ_MAX = 4
135   -
136   -
137   -####
138   -MODE_RP = 0
139   -MODE_NAVIGATOR = 1
140   -MODE_RADIOLOGY = 2
141   -MODE_ODONTOLOGY = 3
142   -
143   -
144   -
145   -#Color Table from Slice
146   -#NumberOfColors, SaturationRange, HueRange, ValueRange
147   -SLICE_COLOR_TABLE = {_("Default "):(None,(0,0),(0,0),(0,1)),
148   - _("Hue"):(None,(1,1),(0,1),(1,1)),
149   - _("Saturation"):(None,(0,1),(0.6,0.6),(1,1)),
150   - _("Desert"):(256, (1,1), (0, 0.1), (1,1)),
151   - _("Rainbow"):(256,(1,1),(0,0.8),(1,1)),
152   - _("Ocean"):(256,(1,1),(0.667, 0.5),(1,1)),
153   - _("Inverse Gray"):(256, (0, 0), (0, 0), (1,0)),
154   - }
155   -
156   -# Volume view angle
157   -VOL_FRONT = wx.NewId()
158   -VOL_BACK = wx.NewId()
159   -VOL_RIGHT = wx.NewId()
160   -VOL_LEFT = wx.NewId()
161   -VOL_TOP = wx.NewId()
162   -VOL_BOTTOM = wx.NewId()
163   -VOL_ISO = wx.NewId()
164   -
165   -# Camera according to volume's orientation
166   -AXIAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,0,1), VOL_BACK:(0,0,1), VOL_RIGHT:(0,0,1),\
167   - VOL_LEFT:(0,0,1), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\
168   - VOL_ISO:(0,0,1)}
169   -AXIAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,1,0), VOL_RIGHT:(-1,0,0),\
170   - VOL_LEFT:(1,0,0), VOL_TOP:(0,0,1), VOL_BOTTOM:(0,0,-1),\
171   - VOL_ISO:(0.5,-1,0.5)}
172   -
173   -SAGITAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,1),\
174   - VOL_LEFT:(0,-1,1), VOL_TOP:(1,-1,0), VOL_BOTTOM:(-1,1,0),\
175   - VOL_ISO:(0,-1,0)}
176   -SAGITAL_VOLUME_CAM_POSITION = {VOL_FRONT:(-1,0,0), VOL_BACK:(1,0,0), VOL_RIGHT:(0,0,1),\
177   - VOL_LEFT:(0,0,-1), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\
178   - VOL_ISO:(-1,-0.5,-0.5)}
179   -
180   -CORONAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,0),\
181   - VOL_LEFT:(0,-1,0), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\
182   - VOL_ISO:(0,-1,0)}
183   -CORONAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,0,-1), VOL_BACK:(0,0,1), VOL_RIGHT:(-1,0,0),\
184   - VOL_LEFT:(1,0,0), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\
185   - VOL_ISO:(0.5,-0.5,-1)}
186   -
187   -VOLUME_POSITION = {AXIAL: [AXIAL_VOLUME_CAM_VIEW_UP, AXIAL_VOLUME_CAM_POSITION],
188   - SAGITAL: [SAGITAL_VOLUME_CAM_VIEW_UP, SAGITAL_VOLUME_CAM_POSITION],
189   - CORONAL: [CORONAL_VOLUME_CAM_VIEW_UP, CORONAL_VOLUME_CAM_POSITION]}
190   -
191   -
192   -# Mask threshold options
193   -proj = Project()
194   -THRESHOLD_RANGE = proj.threshold_modes[_("Bone")]
195   -THRESHOLD_PRESETS_INDEX = _("Bone")
196   -THRESHOLD_HUE_RANGE = (0, 0.6667)
197   -THRESHOLD_INVALUE = 5000
198   -THRESHOLD_OUTVALUE = 0
199   -
200   -# Mask properties
201   -MASK_NAME_PATTERN = _("Mask %d")
202   -MASK_OPACITY = 0.40
203   -#MASK_OPACITY = 0.35
204   -MASK_COLOUR = [[0.33, 1, 0.33],
205   - [1, 1, 0.33],
206   - [0.33, 0.91, 1],
207   - [1, 0.33, 1],
208   - [1, 0.68, 0.33],
209   - [1, 0.33, 0.33],
210   - [0.33333333333333331, 0.33333333333333331, 1.0],
211   - #(1.0, 0.33333333333333331, 0.66666666666666663),
212   - [0.74901960784313726, 1.0, 0.0],
213   - [0.83529411764705885, 0.33333333333333331, 1.0]]#,
214   - #(0.792156862745098, 0.66666666666666663, 1.0),
215   - #(1.0, 0.66666666666666663, 0.792156862745098), # too "light"
216   - #(0.33333333333333331, 1.0, 0.83529411764705885),#],
217   - #(1.0, 0.792156862745098, 0.66666666666666663),
218   - #(0.792156862745098, 1.0, 0.66666666666666663), # too "light"
219   - #(0.66666666666666663, 0.792156862745098, 1.0)]
220   -
221   -
222   -MEASURE_COLOUR = [[1, 0, 0],
223   - [1, 0.4, 0],
224   - [0, 0, 1],
225   - [1, 0, 1],
226   - [0, 0.6, 0]]
227   -
228   -SURFACE_COLOUR = [(0.33, 1, 0.33),
229   - (1, 1, 0.33),
230   - (0.33, 0.91, 1),
231   - (1, 0.33, 1),
232   - (1, 0.68, 0.33),
233   - (1, 0.33, 0.33),
234   - (0.33333333333333331, 0.33333333333333331, 1.0),
235   - (1.0, 0.33333333333333331, 0.66666666666666663),
236   - (0.74901960784313726, 1.0, 0.0),
237   - (0.83529411764705885, 0.33333333333333331, 1.0),
238   - (0.792156862745098, 0.66666666666666663, 1.0),
239   - (1.0, 0.66666666666666663, 0.792156862745098),
240   - (0.33333333333333331, 1.0, 0.83529411764705885),
241   - (1.0, 0.792156862745098, 0.66666666666666663),
242   - (0.792156862745098, 1.0, 0.66666666666666663),
243   - (0.66666666666666663, 0.792156862745098, 1.0)]
244   -
245   -# Related to slice editor brush
246   -BRUSH_CIRCLE = 0 #
247   -BRUSH_SQUARE = 1
248   -DEFAULT_BRUSH_FORMAT = BRUSH_CIRCLE
249   -
250   -BRUSH_DRAW = 0
251   -BRUSH_ERASE = 1
252   -BRUSH_THRESH = 2
253   -DEFAULT_BRUSH_OP = BRUSH_THRESH
254   -BRUSH_OP_NAME = [_("Draw"), _("Erase"), _("Threshold")]
255   -
256   -BRUSH_COLOUR = (0,0,1.0)
257   -BRUSH_SIZE = 30
258   -
259   -# Surface creation values. Each element's list contains:
260   -# 0: imagedata reformat ratio
261   -# 1: smooth_iterations
262   -# 2: smooth_relaxation_factor
263   -# 3: decimate_reduction
264   -SURFACE_QUALITY = {
265   - _("Low"): (3, 2, 0.3000, 0.4),
266   - _("Medium"): (2, 2, 0.3000, 0.4),
267   - _("High"): (0, 1, 0.3000, 0.1),
268   - _("Optimal *"): (0, 2, 0.3000, 0.4)}
269   -DEFAULT_SURFACE_QUALITY = _("Optimal *")
270   -SURFACE_QUALITY_LIST = [_("Low"),_("Medium"),_("High"),_("Optimal *")]
271   -
272   -
273   -# Surface properties
274   -SURFACE_TRANSPARENCY = 0.0
275   -SURFACE_NAME_PATTERN = _("Surface %d")
276   -
277   -# Imagedata - window and level presets
278   -WINDOW_LEVEL = {_("Abdomen"):(350,50),
279   - _("Bone"):(2000, 300),
280   - _("Brain posterior fossa"):(120,40),
281   - _("Brain"):(80,40),
282   - _("Default"):(None, None), #Control class set window and level from DICOM
283   - _("Emphysema"):(500,-850),
284   - _("Ischemia - Hard, non contrast"):(15,32),
285   - _("Ischemia - Soft, non contrast"):(80,20),
286   - _("Larynx"):(180, 80),
287   - _("Liver"):(2000, -500),
288   - _("Lung - Soft"):(1600,-600),
289   - _("Lung - Hard"):(1000,-600),
290   - _("Mediastinum"):(350,25),
291   - _("Manual"):(None, None), #Case the user change window and level
292   - _("Pelvis"): (450,50),
293   - _("Sinus"):(4000, 400),
294   - _("Vasculature - Hard"):(240,80),
295   - _("Vasculature - Soft"):(650,160),
296   - _("Contour"): (255, 127)}
297   -
298   -REDUCE_IMAGEDATA_QUALITY = 0
299   -
300   -ICON_DIR = os.path.abspath(os.path.join('..', 'icons'))
301   -SAMPLE_DIR = os.path.abspath(os.path.join('..', 'samples'))
302   -DOC_DIR = os.path.abspath(os.path.join('..', 'docs'))
303   -
304   -
305   -ID_TO_BMP = {VOL_FRONT: [_("Front"), os.path.join(ICON_DIR, "view_front.png")],
306   - VOL_BACK: [_("Back"), os.path.join(ICON_DIR, "view_back.png")],
307   - VOL_TOP: [_("Top"), os.path.join(ICON_DIR, "view_top.png")],
308   - VOL_BOTTOM: [_("Bottom"), os.path.join(ICON_DIR, "view_bottom.png")],
309   - VOL_RIGHT: [_("Right"), os.path.join(ICON_DIR, "view_right.png")],
310   - VOL_LEFT: [_("Left"), os.path.join(ICON_DIR, "view_left.png")],
311   - VOL_ISO:[_("Isometric"), os.path.join(ICON_DIR,"view_isometric.png")]
312   - }
313   -
314   -# if 1, use vtkVolumeRaycastMapper, if 0, use vtkFixedPointVolumeRayCastMapper
315   -TYPE_RAYCASTING_MAPPER = 0
316   -
317   -folder=RAYCASTING_PRESETS_DIRECTORY= os.path.abspath(os.path.join("..",
318   - "presets",
319   - "raycasting"))
320   -
321   -
322   -RAYCASTING_FILES = {_("Airways"): "Airways.plist",
323   - _("Airways II"): "Airways II.plist",
324   - _("Black & White"): "Black & White.plist",
325   - _("Bone + Skin"): "Bone + Skin.plist",
326   - _("Bone + Skin II"): "Bone + Skin II.plist",
327   - _("Dark bone"): "Dark Bone.plist",
328   - _("Glossy"): "Glossy.plist",
329   - _("Glossy II"): "Glossy II.plist",
330   - _("Gold bone"): "Gold Bone.plist",
331   - _("High contrast"): "High Contrast.plist",
332   - _("Low contrast"): "Low Contrast.plist",
333   - _("Soft on white"): "Soft on White.plist",
334   - _("Mid contrast"): "Mid Contrast.plist",
335   - _("MIP"): "MIP.plist",
336   - _("No shading"): "No Shading.plist",
337   - _("Pencil"): "Pencil.plist",
338   - _("Red on white"): "Red on White.plist",
339   - _("Skin on blue"): "Skin On Blue.plist",
340   - _("Skin on blue II"): "Skin On Blue II.plist",
341   - _("Soft on white"): "Soft on White.plist",
342   - _("Soft + Skin"): "Soft + Skin.plist",
343   - _("Soft + Skin II"): "Soft + Skin II.plist",
344   - _("Soft + Skin III"): "Soft + Skin III.plist",
345   - _("Soft on blue"): "Soft On Blue.plist",
346   - _("Soft"): "Soft.plist",
347   - _("Standard"): "Standard.plist",
348   - _("Vascular"): "Vascular.plist",
349   - _("Vascular II"): "Vascular II.plist",
350   - _("Vascular III"): "Vascular III.plist",
351   - _("Vascular IV"): "Vascular IV.plist",
352   - _("Yellow bone"): "Yellow Bone.plist"}
353   -
354   -
355   -
356   -#RAYCASTING_TYPES = [_(filename.split(".")[0]) for filename in
357   -# os.listdir(folder) if
358   -# os.path.isfile(os.path.join(folder,filename))]
359   -
360   -
361   -LOG_FOLDER = os.path.join(os.path.expanduser('~'), '.invesalius', 'logs')
362   -if not os.path.isdir(LOG_FOLDER):
363   - os.makedirs(LOG_FOLDER)
364   -
365   -folder = os.path.join(os.path.expanduser('~'), '.invesalius', 'presets')
366   -if not os.path.isdir(folder):
367   - os.makedirs(folder)
368   -
369   -
370   -USER_RAYCASTING_PRESETS_DIRECTORY = folder
371   -RAYCASTING_TYPES = [_(filename.split(".")[0]) for filename in
372   - os.listdir(folder) if
373   - os.path.isfile(os.path.join(folder,filename))]
374   -RAYCASTING_TYPES += RAYCASTING_FILES.keys()
375   -RAYCASTING_TYPES.append(_(' Off'))
376   -RAYCASTING_TYPES.sort()
377   -RAYCASTING_OFF_LABEL = _(' Off')
378   -RAYCASTING_TOOLS = [_("Cut plane")]
379   -
380   -# If 0 dont't blur, 1 blur
381   -RAYCASTING_WWWL_BLUR = 0
382   -
383   -RAYCASTING_PRESETS_FOLDERS = (RAYCASTING_PRESETS_DIRECTORY,
384   - USER_RAYCASTING_PRESETS_DIRECTORY)
385   -
386   -
387   -####
388   -#MODE_ZOOM = 0 #"Set Zoom Mode",
389   -#MODE_ZOOM_SELECTION = 1 #:"Set Zoom Select Mode",
390   -#MODE_ROTATE = 2#:"Set Spin Mode",
391   -#MODE_MOVE = 3#:"Set Pan Mode",
392   -#MODE_WW_WL = 4#:"Bright and contrast adjustment"}
393   -#MODE_LINEAR_MEASURE = 5
394   -
395   -
396   -# self.states = {0:"Set Zoom Mode", 1:"Set Zoom Select Mode",
397   -# 2:"Set Spin Mode", 3:"Set Pan Mode",
398   -# 4:"Bright and contrast adjustment"}
399   -
400   -
401   -#ps.Publisher().sendMessage('Set interaction mode %d'%
402   -# (MODE_BY_ID[id]))
403   -
404   -#('Set Editor Mode')
405   -#{0:"Set Change Slice Mode"}
406   -
407   -####
408   -MODE_SLICE_SCROLL = -1
409   -MODE_SLICE_EDITOR = -2
410   -MODE_SLICE_CROSS = -3
411   -
412   -############
413   -
414   -
415   -FILETYPE_IV = wx.NewId()
416   -FILETYPE_RIB = wx.NewId()
417   -FILETYPE_STL = wx.NewId()
418   -FILETYPE_STL_ASCII = wx.NewId()
419   -FILETYPE_VRML = wx.NewId()
420   -FILETYPE_OBJ = wx.NewId()
421   -FILETYPE_VTP = wx.NewId()
422   -FILETYPE_PLY = wx.NewId()
423   -FILETYPE_X3D = wx.NewId()
424   -
425   -FILETYPE_IMAGEDATA = wx.NewId()
426   -
427   -FILETYPE_BMP = wx.NewId()
428   -FILETYPE_JPG = wx.NewId()
429   -FILETYPE_PNG = wx.NewId()
430   -FILETYPE_PS = wx.NewId()
431   -FILETYPE_POV = wx.NewId()
432   -FILETYPE_TIF = wx.NewId()
433   -
434   -IMAGE_TILING = {"1 x 1":(1,1), "1 x 2":(1,2),
435   - "1 x 3":(1,3), "1 x 4":(1,4),
436   - "2 x 1":(2,1), "2 x 2":(2,2),
437   - "2 x 3":(2,3), "2 x 4":(2,4),
438   - "3 x 1":(3,1), "3 x 2":(3,2),
439   - "3 x 3":(3,3), "3 x 4":(3,4),
440   - "4 x 1":(4,1), "4 x 2":(4,2),
441   - "4 x 3":(4,3), "4 x 4":(4,4),
442   - "4 x 5":(4,5), "5 x 4":(5,4)}
443   -
444   -VTK_WARNING = 0
445   -
446   -#----------------------------------------------------------
447   -
448   -[ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE,
449   -ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET,
450   -ID_PRINT_SCREENSHOT, ID_EXIT, ID_IMPORT_OTHERS_FILES, ID_ANALYZE_IMPORT, ID_NIFTI_IMPORT,
451   -ID_PREFERENCES, ID_DICOM_NETWORK] = [wx.NewId() for number in range(15)]
452   -
453   -
454   -[ID_EDIT_UNDO, ID_EDIT_REDO, ID_EDIT_LIST] =\
455   - [wx.NewId() for number in range(3)]
456   -[ID_TOOL_PROJECT, ID_TOOL_LAYOUT, ID_TOOL_OBJECT, ID_TOOL_SLICE] =\
457   - [wx.NewId() for number in range(4)]
458   -[ID_TASK_BAR, ID_VIEW_FOUR] =\
459   - [wx.NewId() for number in range(2)]
460   -[ID_VIEW_FULL, ID_VIEW_TEXT, ID_VIEW_3D_BACKGROUND] =\
461   - [wx.NewId() for number in range(3)]
462   -
463   -ID_ABOUT = wx.NewId()
464   -ID_START = wx.NewId()
465   -
466   -ID_FLIP_X = wx.NewId()
467   -ID_FLIP_Y = wx.NewId()
468   -ID_FLIP_Z = wx.NewId()
469   -
470   -ID_SWAP_XY = wx.NewId()
471   -ID_SWAP_XZ = wx.NewId()
472   -ID_SWAP_YZ = wx.NewId()
473   -
474   -#---------------------------------------------------------
475   -STATE_DEFAULT = 1000
476   -STATE_WL = 1001
477   -STATE_SPIN = 1002
478   -STATE_ZOOM = 1003
479   -STATE_ZOOM_SL = 1004
480   -STATE_PAN = 1005
481   -STATE_ANNOTATE = 1006
482   -STATE_MEASURE_DISTANCE = 1007
483   -STATE_MEASURE_ANGLE = 1008
484   -
485   -SLICE_STATE_CROSS = 3006
486   -SLICE_STATE_SCROLL = 3007
487   -SLICE_STATE_EDITOR = 3008
488   -SLICE_STATE_WATERSHED = 3009
489   -
490   -VOLUME_STATE_SEED = 2001
491   -#STATE_LINEAR_MEASURE = 3001
492   -#STATE_ANGULAR_MEASURE = 3002
493   -
494   -TOOL_STATES = [STATE_WL, STATE_SPIN, STATE_ZOOM,
495   - STATE_ZOOM_SL, STATE_PAN, STATE_MEASURE_DISTANCE,
496   - STATE_MEASURE_ANGLE]#, STATE_ANNOTATE]
497   -
498   -TOOL_SLICE_STATES = [SLICE_STATE_CROSS, SLICE_STATE_SCROLL]
499   -
500   -
501   -SLICE_STYLES = TOOL_STATES + TOOL_SLICE_STATES
502   -SLICE_STYLES.append(STATE_DEFAULT)
503   -SLICE_STYLES.append(SLICE_STATE_EDITOR)
504   -SLICE_STYLES.append(SLICE_STATE_WATERSHED)
505   -
506   -VOLUME_STYLES = TOOL_STATES + [VOLUME_STATE_SEED, STATE_MEASURE_DISTANCE,
507   - STATE_MEASURE_ANGLE]
508   -VOLUME_STYLES.append(STATE_DEFAULT)
509   -
510   -
511   -STYLE_LEVEL = {SLICE_STATE_EDITOR: 1,
512   - SLICE_STATE_WATERSHED: 1,
513   - SLICE_STATE_CROSS: 2,
514   - SLICE_STATE_SCROLL: 2,
515   - STATE_ANNOTATE: 2,
516   - STATE_DEFAULT: 0,
517   - STATE_MEASURE_ANGLE: 2,
518   - STATE_MEASURE_DISTANCE: 2,
519   - STATE_WL: 2,
520   - STATE_SPIN: 2,
521   - STATE_ZOOM: 2,
522   - STATE_ZOOM_SL: 2,
523   - STATE_PAN:2,
524   - VOLUME_STATE_SEED:1}
525   -
526   -#------------ Prefereces options key ------------
527   -RENDERING = 0
528   -SURFACE_INTERPOLATION = 1
529   -LANGUAGE = 2
530   -
531   -
532   -#Correlaction extracted from pyDicom
533   -DICOM_ENCODING_TO_PYTHON = {
534   - 'None':'iso8859',
535   - None:'iso8859',
536   - '': 'iso8859',
537   - 'ISO_IR 6': 'iso8859',
538   - 'ISO_IR 100': 'latin_1',
539   - 'ISO 2022 IR 87': 'iso2022_jp',
540   - 'ISO 2022 IR 13': 'iso2022_jp',
541   - 'ISO 2022 IR 149': 'euc_kr',
542   - 'ISO_IR 192': 'UTF8',
543   - 'GB18030': 'GB18030',
544   - 'ISO_IR 126': 'iso_ir_126',
545   - 'ISO_IR 127': 'iso_ir_127',
546   - 'ISO_IR 138': 'iso_ir_138',
547   - 'ISO_IR 144': 'iso_ir_144',
548   - }
549   -
550   -#-------------------- Projections type ----------------
551   -PROJECTION_NORMAL=0
552   -PROJECTION_MaxIP=1
553   -PROJECTION_MinIP=2
554   -PROJECTION_MeanIP=3
555   -PROJECTION_LMIP=4
556   -PROJECTION_MIDA=5
557   -PROJECTION_CONTOUR_MIP=6
558   -PROJECTION_CONTOUR_LMIP=7
559   -PROJECTION_CONTOUR_MIDA=8
560   -
561   -#------------ Projections defaults ------------------
562   -PROJECTION_BORDER_SIZE=1.0
563   -PROJECTION_MIP_SIZE=2
invesalius/bkps/control.py.bak
... ... @@ -1,658 +0,0 @@
1   -#--------------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------------
19   -import math
20   -import os
21   -import plistlib
22   -import wx
23   -import numpy
24   -from wx.lib.pubsub import pub as Publisher
25   -
26   -import constants as const
27   -import data.imagedata_utils as image_utils
28   -import data.mask as msk
29   -import data.measures
30   -import data.slice_ as sl
31   -import data.surface as srf
32   -import data.volume as volume
33   -import gui.dialogs as dialog
34   -import project as prj
35   -import reader.analyze_reader as analyze
36   -import reader.nifti_reader as nifti
37   -import reader.dicom_grouper as dg
38   -import reader.dicom_reader as dcm
39   -import session as ses
40   -
41   -import utils
42   -import gui.dialogs as dialogs
43   -import subprocess
44   -import sys
45   -
46   -DEFAULT_THRESH_MODE = 0
47   -
48   -class Controller():
49   -
50   - def __init__(self, frame):
51   - self.surface_manager = srf.SurfaceManager()
52   - self.volume = volume.Volume()
53   - self.__bind_events()
54   - self.frame = frame
55   - self.progress_dialog = None
56   - self.cancel_import = False
57   - #Init session
58   - session = ses.Session()
59   - self.measure_manager = data.measures.MeasurementManager()
60   -
61   - Publisher.sendMessage('Load Preferences')
62   -
63   - def __bind_events(self):
64   - Publisher.subscribe(self.OnImportMedicalImages, 'Import directory')
65   - Publisher.subscribe(self.OnShowDialogImportDirectory,
66   - 'Show import directory dialog')
67   - Publisher.subscribe(self.OnShowDialogOpenProject,
68   - 'Show open project dialog')
69   -
70   - Publisher.subscribe(self.OnShowDialogSaveProject, 'Show save dialog')
71   -
72   - Publisher.subscribe(self.LoadRaycastingPreset,
73   - 'Load raycasting preset')
74   - Publisher.subscribe(self.SaveRaycastingPreset,
75   - 'Save raycasting preset')
76   - Publisher.subscribe(self.OnOpenDicomGroup,
77   - 'Open DICOM group')
78   - Publisher.subscribe(self.Progress, "Update dicom load")
79   - Publisher.subscribe(self.OnLoadImportPanel, "End dicom load")
80   - Publisher.subscribe(self.OnCancelImport, 'Cancel DICOM load')
81   - Publisher.subscribe(self.OnShowDialogCloseProject, 'Close Project')
82   - Publisher.subscribe(self.OnOpenProject, 'Open project')
83   - Publisher.subscribe(self.OnOpenRecentProject, 'Open recent project')
84   - Publisher.subscribe(self.OnShowAnalyzeFile, 'Show analyze dialog')
85   - Publisher.subscribe(self.OnShowNiftiFile, 'Show nifti dialog')
86   -
87   -
88   - def OnCancelImport(self, pubsub_evt):
89   - #self.cancel_import = True
90   - Publisher.sendMessage('Hide import panel')
91   -
92   -
93   -
94   -
95   -###########################
96   -###########################
97   -
98   - def OnShowDialogImportDirectory(self, pubsub_evt):
99   - self.ShowDialogImportDirectory()
100   -
101   - def OnShowDialogOpenProject(self, pubsub_evt):
102   - self.ShowDialogOpenProject()
103   -
104   - def OnShowDialogSaveProject(self, pubsub_evt):
105   - saveas = pubsub_evt.data
106   - self.ShowDialogSaveProject(saveas)
107   -
108   - def OnShowDialogCloseProject(self, pubsub_evt):
109   - self.ShowDialogCloseProject()
110   -
111   - def OnShowAnalyzeFile(self, pubsub_evt):
112   - dirpath = dialog.ShowOpenAnalyzeDialog()
113   - imagedata = analyze.ReadAnalyze(dirpath)
114   - if imagedata:
115   - self.CreateAnalyzeProject(imagedata)
116   -
117   - self.LoadProject()
118   - Publisher.sendMessage("Enable state project", True)
119   -
120   - def OnShowNiftiFile(self, pubsub_evt):
121   - dirpath = dialog.ShowOpenNiftiDialog()
122   - imagedata = nifti.ReadNifti(dirpath)
123   - if imagedata:
124   - self.CreateNiftiProject(imagedata)
125   -
126   - self.LoadProject()
127   - Publisher.sendMessage("Enable state project", True)
128   -
129   -
130   -###########################
131   -
132   - def ShowDialogImportDirectory(self):
133   - # Offer to save current project if necessary
134   - session = ses.Session()
135   - st = session.project_status
136   - if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):
137   - filename = session.project_path[1]
138   - answer = dialog.SaveChangesDialog2(filename)
139   - if answer:
140   - self.ShowDialogSaveProject()
141   - self.CloseProject()
142   - #Publisher.sendMessage("Enable state project", False)
143   - Publisher.sendMessage('Set project name')
144   - Publisher.sendMessage("Stop Config Recording")
145   - Publisher.sendMessage("Set slice interaction style", const.STATE_DEFAULT)
146   - # Import project
147   - dirpath = dialog.ShowImportDirDialog()
148   - if dirpath and not os.listdir(dirpath):
149   - dialog.ImportEmptyDirectory(dirpath)
150   - elif dirpath:
151   - self.StartImportPanel(dirpath)
152   - Publisher.sendMessage("Load data to import panel", dirpath)
153   -
154   - def ShowDialogOpenProject(self):
155   - # Offer to save current project if necessary
156   - session = ses.Session()
157   - st = session.project_status
158   - if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):
159   - filename = session.project_path[1]
160   - answer = dialog.SaveChangesDialog2(filename)
161   - if answer:
162   - self.ShowDialogSaveProject()
163   -
164   - # Open project
165   - filepath = dialog.ShowOpenProjectDialog()
166   - if filepath:
167   - self.CloseProject()
168   - self.OpenProject(filepath)
169   -
170   - def ShowDialogSaveProject(self, saveas=False):
171   - session = ses.Session()
172   - if saveas or session.temp_item:
173   - proj = prj.Project()
174   - filepath = dialog.ShowSaveAsProjectDialog(proj.name)
175   - if filepath:
176   - #session.RemoveTemp()
177   - session.OpenProject(filepath)
178   - else:
179   - return
180   - else:
181   - dirpath, filename = session.project_path
182   - filepath = os.path.join(dirpath, filename)
183   -
184   - self.SaveProject(filepath)
185   -
186   -
187   - def ShowDialogCloseProject(self):
188   - session = ses.Session()
189   - st = session.project_status
190   - if st == const.PROJ_CLOSE:
191   - return -1
192   - try:
193   - filename = session.project_path[1]
194   - except(AttributeError):
195   - utils.debug("Project doesn't exist")
196   - filename = None
197   -
198   - if (filename):
199   - if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):
200   - answer = dialog.SaveChangesDialog(filename, self.frame)
201   - if not answer:
202   - utils.debug("Close without changes")
203   - self.CloseProject()
204   - Publisher.sendMessage("Enable state project", False)
205   - Publisher.sendMessage('Set project name')
206   - Publisher.sendMessage("Stop Config Recording")
207   - #Publisher.sendMessage("Exit")
208   - elif answer == 1:
209   - self.ShowDialogSaveProject()
210   - utils.debug("Save changes and close")
211   - self.CloseProject()
212   - Publisher.sendMessage("Enable state project", False)
213   - Publisher.sendMessage('Set project name')
214   - Publisher.sendMessage("Stop Config Recording")
215   - #Publisher.sendMessage("Exit")
216   - elif answer == -1:
217   - utils.debug("Cancel")
218   - else:
219   - self.CloseProject()
220   - Publisher.sendMessage("Enable state project", False)
221   - Publisher.sendMessage('Set project name')
222   - Publisher.sendMessage("Stop Config Recording")
223   - #Publisher.sendMessage("Exit")
224   -
225   - else:
226   - Publisher.sendMessage('Stop Config Recording')
227   - #Publisher.sendMessage('Exit')
228   -
229   -
230   -###########################
231   - def OnOpenProject(self, pubsub_evt):
232   - path = pubsub_evt.data
233   - self.OpenProject(path)
234   -
235   - def OnOpenRecentProject(self, pubsub_evt):
236   - filepath = pubsub_evt.data
237   -
238   - if os.path.exists(filepath):
239   - session = ses.Session()
240   - st = session.project_status
241   - if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):
242   - filename = session.project_path[1]
243   - answer = dialog.SaveChangesDialog2(filename)
244   - if answer:
245   - self.ShowDialogSaveProject()
246   - self.CloseProject()
247   - self.OpenProject(filepath)
248   - else:
249   - dialog.InexistentPath(filepath)
250   -
251   -
252   -
253   - def OpenProject(self, filepath):
254   - Publisher.sendMessage('Begin busy cursor')
255   - path = os.path.abspath(filepath)
256   -
257   - proj = prj.Project()
258   - proj.OpenPlistProject(path)
259   - proj.SetAcquisitionModality(proj.modality)
260   - self.Slice = sl.Slice()
261   - self.Slice._open_image_matrix(proj.matrix_filename,
262   - tuple(proj.matrix_shape),
263   - proj.matrix_dtype)
264   -
265   - self.Slice.window_level = proj.level
266   - self.Slice.window_width = proj.window
267   -
268   - mask = msk.Mask()
269   - mask._set_class_index(proj.last_mask_index)
270   - self.mask_dict_copy = proj.mask_dict.copy()
271   -
272   - Publisher.sendMessage('Update threshold limits list',
273   - proj.threshold_range)
274   -
275   - self.LoadProject()
276   -
277   - session = ses.Session()
278   - session.OpenProject(filepath)
279   - Publisher.sendMessage("Enable state project", True)
280   -
281   - def SaveProject(self, path=None):
282   - Publisher.sendMessage('Begin busy cursor')
283   - session = ses.Session()
284   - if path:
285   - dirpath, filename = os.path.split(path)
286   - session.SaveProject((dirpath, filename))
287   - else:
288   - dirpath, filename = session.project_path
289   -
290   - proj = prj.Project()
291   - prj.Project().SavePlistProject(dirpath, filename)
292   -
293   - session.SaveProject()
294   - Publisher.sendMessage('End busy cursor')
295   -
296   - def CloseProject(self):
297   - proj = prj.Project()
298   - proj.Close()
299   -
300   - Publisher.sendMessage('Hide content panel')
301   - Publisher.sendMessage('Close project data')
302   - session = ses.Session()
303   - session.CloseProject()
304   -
305   -###########################
306   -
307   -
308   - def StartImportPanel(self, path):
309   -
310   - # retrieve DICOM files splited into groups
311   - reader = dcm.ProgressDicomReader()
312   - reader.SetWindowEvent(self.frame)
313   - reader.SetDirectoryPath(path)
314   - Publisher.sendMessage('End busy cursor')
315   -
316   - def Progress(self, evt):
317   - data = evt.data
318   - if (data):
319   - message = _("Loading file %d of %d ...")%(data[0],data[1])
320   - if not(self.progress_dialog):
321   - self.progress_dialog = dialog.ProgressDialog(
322   - maximum = data[1], abort=1)
323   - else:
324   - if not(self.progress_dialog.Update(data[0],message)):
325   - self.progress_dialog.Close()
326   - self.progress_dialog = None
327   - Publisher.sendMessage('Begin busy cursor')
328   - else:
329   - #Is None if user canceled the load
330   - self.progress_dialog.Close()
331   - self.progress_dialog = None
332   -
333   - def OnLoadImportPanel(self, evt):
334   - patient_series = evt.data
335   - ok = self.LoadImportPanel(patient_series)
336   - if ok:
337   - Publisher.sendMessage('Show import panel')
338   - Publisher.sendMessage("Show import panel in frame")
339   -
340   -
341   - def LoadImportPanel(self, patient_series):
342   - if patient_series and isinstance(patient_series, list):
343   - Publisher.sendMessage("Load import panel", patient_series)
344   - first_patient = patient_series[0]
345   - Publisher.sendMessage("Load dicom preview", first_patient)
346   - return True
347   - else:
348   - dialog.ImportInvalidFiles()
349   - return False
350   -
351   - def OnImportMedicalImages(self, pubsub_evt):
352   - directory = pubsub_evt.data
353   - self.ImportMedicalImages(directory)
354   -
355   - def ImportMedicalImages(self, directory):
356   - # OPTION 1: DICOM?
357   - patients_groups = dcm.GetDicomGroups(directory)
358   - if len(patients_groups):
359   - group = dcm.SelectLargerDicomGroup(patients_groups)
360   - matrix, matrix_filename, dicom = self.OpenDicomGroup(group, 0, [0,0],gui=True)
361   - self.CreateDicomProject(dicom, matrix, matrix_filename)
362   -# # OPTION 2: ANALYZE?
363   -# else:
364   -# imagedata = analyze.ReadDirectory(directory)
365   -# if imagedata:
366   -# self.CreateAnalyzeProject(imagedata)
367   -# # OPTION 4: Nothing...
368   -# else:
369   -# utils.debug("No medical images found on given directory")
370   -# return
371   - # OPTION 2: NIfTI
372   - else:
373   - #imagedata = analyze.ReadDirectory(directory)
374   - imagedata = nifti.ReadDirectory(directory)
375   - if imagedata:
376   - #self.CreateAnalyzeProject(imagedata)
377   - self.CreateNiftiProject(imagedata)
378   - # OPTION 3: Nothing...
379   - else:
380   - utils.debug("No medical images found on given directory")
381   - return
382   - self.LoadProject()
383   - Publisher.sendMessage("Enable state project", True)
384   -
385   - def LoadProject(self):
386   - proj = prj.Project()
387   -
388   - const.THRESHOLD_OUTVALUE = proj.threshold_range[0]
389   - const.THRESHOLD_INVALUE = proj.threshold_range[1]
390   -
391   - const.WINDOW_LEVEL[_('Default')] = (proj.window, proj.level)
392   - const.WINDOW_LEVEL[_('Manual')] = (proj.window, proj.level)
393   -
394   - self.Slice = sl.Slice()
395   - self.Slice.spacing = proj.spacing
396   -
397   - Publisher.sendMessage('Load slice to viewer',
398   - (proj.imagedata,
399   - proj.mask_dict))
400   -
401   -
402   - Publisher.sendMessage('Load slice plane')
403   -
404   - Publisher.sendMessage('Bright and contrast adjustment image',\
405   - (proj.window, proj.level))
406   - Publisher.sendMessage('Update window level value',\
407   - (proj.window, proj.level))
408   -
409   - Publisher.sendMessage('Set project name', proj.name)
410   - Publisher.sendMessage('Load surface dict',
411   - proj.surface_dict)
412   - Publisher.sendMessage('Hide surface items',
413   - proj.surface_dict)
414   - self.LoadImagedataInfo() # TODO: where do we insert this <<<?
415   -
416   - Publisher.sendMessage('Show content panel')
417   - Publisher.sendMessage('Update AUI')
418   -
419   - if len(proj.mask_dict):
420   - mask_index = len(proj.mask_dict) -1
421   - for m in proj.mask_dict.values():
422   - Publisher.sendMessage('Add mask',
423   - (m.index, m.name,
424   - m.threshold_range, m.colour))
425   - self.Slice.current_mask = proj.mask_dict[mask_index]
426   - Publisher.sendMessage('Show mask', (mask_index, True))
427   - else:
428   - mask_name = const.MASK_NAME_PATTERN % (1,)
429   - thresh = const.THRESHOLD_RANGE
430   - colour = const.MASK_COLOUR[0]
431   -
432   - Publisher.sendMessage('Create new mask',
433   - (mask_name, thresh, colour))
434   -
435   - Publisher.sendMessage('Load measurement dict',
436   - (proj.measurement_dict, self.Slice.spacing))
437   -
438   - Publisher.sendMessage(('Set scroll position', 'AXIAL'),proj.matrix_shape[0]/2)
439   - Publisher.sendMessage(('Set scroll position', 'SAGITAL'),proj.matrix_shape[1]/2)
440   - Publisher.sendMessage(('Set scroll position', 'CORONAL'),proj.matrix_shape[2]/2)
441   -
442   - Publisher.sendMessage('End busy cursor')
443   -
444   - def CreateAnalyzeProject(self, imagedata):
445   - header = imagedata.get_header()
446   - proj = prj.Project()
447   - proj.imagedata = None
448   - proj.name = _("Untitled")
449   - proj.SetAcquisitionModality("MRI")
450   - #TODO: Verify if all Analyse are in AXIAL orientation
451   -
452   - # To get Z, X, Y (used by InVesaliu), not X, Y, Z
453   - matrix, matrix_filename = image_utils.analyze2mmap(imagedata)
454   - if header['orient'] == 0:
455   - proj.original_orientation = const.AXIAL
456   - elif header['orient'] == 1:
457   - proj.original_orientation = const.CORONAL
458   - elif header['orient'] == 2:
459   - proj.original_orientation = const.SAGITAL
460   - else:
461   - proj.original_orientation = const.SAGITAL
462   -
463   - proj.threshold_range = (header['glmin'],
464   - header['glmax'])
465   - proj.window = proj.threshold_range[1] - proj.threshold_range[0]
466   - proj.level = (0.5 * (proj.threshold_range[1] + proj.threshold_range[0]))
467   - proj.spacing = header['pixdim'][1:4]
468   - proj.matrix_shape = matrix.shape
469   -
470   - self.Slice = sl.Slice()
471   - self.Slice.matrix = matrix
472   - self.Slice.matrix_filename = matrix_filename
473   -
474   - self.Slice.window_level = proj.level
475   - self.Slice.window_width = proj.window
476   - self.Slice.spacing = header.get_zooms()[:3]
477   -
478   - Publisher.sendMessage('Update threshold limits list',
479   - proj.threshold_range)
480   -
481   - def CreateDicomProject(self, dicom, matrix, matrix_filename):
482   - name_to_const = {"AXIAL":const.AXIAL,
483   - "CORONAL":const.CORONAL,
484   - "SAGITTAL":const.SAGITAL}
485   -
486   - proj = prj.Project()
487   - proj.name = dicom.patient.name
488   - proj.modality = dicom.acquisition.modality
489   - proj.SetAcquisitionModality(dicom.acquisition.modality)
490   - proj.matrix_shape = matrix.shape
491   - proj.matrix_dtype = matrix.dtype.name
492   - proj.matrix_filename = matrix_filename
493   - #proj.imagedata = imagedata
494   - proj.dicom_sample = dicom
495   - proj.original_orientation =\
496   - name_to_const[dicom.image.orientation_label]
497   - proj.window = float(dicom.image.window)
498   - proj.level = float(dicom.image.level)
499   - proj.threshold_range = int(matrix.min()), int(matrix.max())
500   - proj.spacing = self.Slice.spacing
501   -
502   - ######
503   - session = ses.Session()
504   - filename = proj.name+".inv3"
505   -
506   - filename = filename.replace("/", "") #Fix problem case other/Skull_DICOM
507   -
508   - dirpath = session.CreateProject(filename)
509   - #proj.SavePlistProject(dirpath, filename)
510   -
511   - def OnOpenDicomGroup(self, pubsub_evt):
512   - group, interval, file_range = pubsub_evt.data
513   - matrix, matrix_filename, dicom = self.OpenDicomGroup(group, interval, file_range, gui=True)
514   - self.CreateDicomProject(dicom, matrix, matrix_filename)
515   - self.LoadProject()
516   - Publisher.sendMessage("Enable state project", True)
517   -
518   - def OpenDicomGroup(self, dicom_group, interval, file_range, gui=True):
519   - # Retrieve general DICOM headers
520   - dicom = dicom_group.GetDicomSample()
521   -
522   - # Create imagedata
523   - interval += 1
524   - filelist = dicom_group.GetFilenameList()[::interval]
525   - if not filelist:
526   - utils.debug("Not used the IPPSorter")
527   - filelist = [i.image.file for i in dicom_group.GetHandSortedList()[::interval]]
528   -
529   - if file_range != None and file_range[1] > file_range[0]:
530   - filelist = filelist[file_range[0]:file_range[1] + 1]
531   -
532   - zspacing = dicom_group.zspacing * interval
533   -
534   - size = dicom.image.size
535   - bits = dicom.image.bits_allocad
536   - sop_class_uid = dicom.acquisition.sop_class_uid
537   - xyspacing = dicom.image.spacing
538   - orientation = dicom.image.orientation_label
539   -
540   - if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage
541   - use_dcmspacing = 1
542   - else:
543   - use_dcmspacing = 0
544   -
545   - imagedata = None
546   -
547   - sx, sy = size
548   - n_slices = len(filelist)
549   - resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8)
550   -
551   - if resolution_percentage < 1.0:
552   - re_dialog = dialog.ResizeImageDialog()
553   - re_dialog.SetValue(int(resolution_percentage*100))
554   - re_dialog_value = re_dialog.ShowModal()
555   - re_dialog.Close()
556   -
557   - if re_dialog_value == wx.ID_OK:
558   - percentage = re_dialog.GetValue()
559   - resolution_percentage = percentage / 100.0
560   - else:
561   - return
562   -
563   - xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage
564   -
565   -
566   - wl = float(dicom.image.level)
567   - ww = float(dicom.image.window)
568   - self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size,
569   - orientation, resolution_percentage)
570   -
571   - self.Slice = sl.Slice()
572   - self.Slice.matrix = self.matrix
573   - self.Slice.matrix_filename = self.filename
574   -
575   - if orientation == 'AXIAL':
576   - self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing
577   - elif orientation == 'CORONAL':
578   - self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1]
579   - elif orientation == 'SAGITTAL':
580   - self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0]
581   -
582   - # 1(a): Fix gantry tilt, if any
583   - tilt_value = dicom.acquisition.tilt
584   - if (tilt_value) and (gui):
585   - # Tell user gantry tilt and fix, according to answer
586   - message = _("Fix gantry tilt applying the degrees below")
587   - value = -1*tilt_value
588   - tilt_value = dialog.ShowNumberDialog(message, value)
589   - image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value)
590   - elif (tilt_value) and not (gui):
591   - tilt_value = -1*tilt_value
592   - image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value)
593   -
594   - self.Slice.window_level = wl
595   - self.Slice.window_width = ww
596   -
597   - Publisher.sendMessage('Update threshold limits list', scalar_range)
598   -
599   - return self.matrix, self.filename, dicom
600   -
601   - def LoadImagedataInfo(self):
602   - proj = prj.Project()
603   -
604   - thresh_modes = proj.threshold_modes.keys()
605   - thresh_modes.sort()
606   - default_threshold = const.THRESHOLD_PRESETS_INDEX
607   - if proj.mask_dict:
608   - keys = proj.mask_dict.keys()
609   - last = max(keys)
610   - (a,b) = proj.mask_dict[last].threshold_range
611   - default_threshold = [a,b]
612   - min_ = proj.threshold_range[0]
613   - max_ = proj.threshold_range[1]
614   - if default_threshold[0] < min_:
615   - default_threshold[0] = min_
616   - if default_threshold[1] > max_:
617   - default_threshold[1] = max_
618   - [a,b] = default_threshold
619   - default_threshold = (a,b)
620   - Publisher.sendMessage('Set threshold modes',
621   - (thresh_modes,default_threshold))
622   -
623   - def LoadRaycastingPreset(self, pubsub_evt=None):
624   - if pubsub_evt:
625   - label = pubsub_evt.data
626   - else:
627   - return
628   -
629   - if label != const.RAYCASTING_OFF_LABEL:
630   - if label in const.RAYCASTING_FILES.keys():
631   - path = os.path.join(const.RAYCASTING_PRESETS_DIRECTORY,
632   - const.RAYCASTING_FILES[label])
633   - else:
634   - path = os.path.join(const.RAYCASTING_PRESETS_DIRECTORY,
635   - label+".plist")
636   - if not os.path.isfile(path):
637   - path = os.path.join(const.USER_RAYCASTING_PRESETS_DIRECTORY,
638   - label+".plist")
639   - preset = plistlib.readPlist(path)
640   - prj.Project().raycasting_preset = preset
641   - # Notify volume
642   - # TODO: Chamar grafico tb!
643   - Publisher.sendMessage('Update raycasting preset')
644   - else:
645   - prj.Project().raycasting_preset = 0
646   - Publisher.sendMessage('Update raycasting preset')
647   -
648   - def SaveRaycastingPreset(self, pubsub_evt):
649   - preset_name = pubsub_evt.data
650   - preset = prj.Project().raycasting_preset
651   - preset['name'] = preset_name
652   - preset_dir = os.path.join(const.USER_RAYCASTING_PRESETS_DIRECTORY,
653   - preset_name + '.plist')
654   - plistlib.writePlist(preset, preset_dir)
655   -
656   -
657   -
658   -
invesalius/bkps/dialogs.py.bak
... ... @@ -1,2383 +0,0 @@
1   -#!/usr/bin/env python
2   -# -*- coding: UTF-8 -*-
3   -#--------------------------------------------------------------------------
4   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
5   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
6   -# Homepage: http://www.softwarepublico.gov.br
7   -# Contact: invesalius@cti.gov.br
8   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
9   -#--------------------------------------------------------------------------
10   -# Este programa e software livre; voce pode redistribui-lo e/ou
11   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
12   -# publicada pela Free Software Foundation; de acordo com a versao 2
13   -# da Licenca.
14   -#
15   -# Este programa eh distribuido na expectativa de ser util, mas SEM
16   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
17   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
18   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
19   -# detalhes.
20   -#--------------------------------------------------------------------------
21   -import os
22   -import random
23   -import sys
24   -
25   -import vtk
26   -import wx
27   -from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
28   -from wx.lib import masked
29   -from wx.lib.agw import floatspin
30   -from wx.lib.wordwrap import wordwrap
31   -from wx.lib.pubsub import pub as Publisher
32   -
33   -import data.bases as bases
34   -import constants as const
35   -import gui.widgets.gradient as grad
36   -import project as proj
37   -import session as ses
38   -import utils
39   -
40   -from gui.widgets.clut_imagedata import CLUTImageDataWidget, EVT_CLUT_NODE_CHANGED
41   -
42   -import numpy as np
43   -
44   -class MaskEvent(wx.PyCommandEvent):
45   - def __init__(self , evtType, id, mask_index):
46   - wx.PyCommandEvent.__init__(self, evtType, id,)
47   - self.mask_index = mask_index
48   -
49   -myEVT_MASK_SET = wx.NewEventType()
50   -EVT_MASK_SET = wx.PyEventBinder(myEVT_MASK_SET, 1)
51   -
52   -class NumberDialog(wx.Dialog):
53   - def __init__(self, message, value=0):
54   - pre = wx.PreDialog()
55   - pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize,
56   - pos=wx.DefaultPosition,
57   - style=wx.DEFAULT_DIALOG_STYLE)
58   - self.PostCreate(pre)
59   -
60   - # Static text which contains message to user
61   - label = wx.StaticText(self, -1, message)
62   -
63   - # Numeric value to be changed by user
64   - num_ctrl = masked.NumCtrl(self, value=value, integerWidth=3,
65   - fractionWidth=2,
66   - allowNegative=True,
67   - signedForegroundColour = "Black")
68   - self.num_ctrl = num_ctrl
69   -
70   - # Buttons
71   - btn_ok = wx.Button(self, wx.ID_OK)
72   - btn_ok.SetHelpText(_("Value will be applied."))
73   - btn_ok.SetDefault()
74   -
75   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
76   - btn_cancel.SetHelpText(_("Value will not be applied."))
77   -
78   - btnsizer = wx.StdDialogButtonSizer()
79   - btnsizer.AddButton(btn_ok)
80   - btnsizer.AddButton(btn_cancel)
81   - btnsizer.Realize()
82   -
83   -
84   - sizer = wx.BoxSizer(wx.VERTICAL)
85   - sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
86   - sizer.Add(num_ctrl, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
87   - sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
88   -
89   - self.SetSizer(sizer)
90   - sizer.Fit(self)
91   -
92   - self.Centre()
93   -
94   - def SetValue(self, value):
95   - self.num_ctrl.SetValue(value)
96   -
97   - def GetValue(self):
98   - return self.num_ctrl.GetValue()
99   -
100   -
101   -class ResizeImageDialog(wx.Dialog):
102   -
103   - def __init__(self):#, message, value=0):
104   - pre = self.pre = wx.PreDialog()
105   - pre.Create(None, -1, "InVesalius 3", size=wx.DefaultSize,
106   - pos=wx.DefaultPosition,
107   - style=wx.DEFAULT_DIALOG_STYLE)
108   - self.PostCreate(pre)
109   -
110   - 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."))
111   - icon = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32,32))
112   - bmp = wx.StaticBitmap(self, -1, icon)
113   -
114   - btn_ok = wx.Button(self, wx.ID_OK)
115   - btn_ok.SetDefault()
116   -
117   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
118   -
119   - btn_sizer = wx.StdDialogButtonSizer()
120   - btn_sizer.AddButton(btn_ok)
121   - btn_sizer.AddButton(btn_cancel)
122   - btn_sizer.Realize()
123   -
124   - lbl_message_percent = wx.StaticText(self, -1,_("Percentage of original resolution"))
125   -
126   - num_ctrl_percent = wx.SpinCtrl(self, -1)
127   - num_ctrl_percent.SetRange(20,100)
128   - self.num_ctrl_porcent = num_ctrl_percent
129   -
130   - sizer_percent = wx.BoxSizer(wx.HORIZONTAL)
131   - sizer_percent.Add(lbl_message_percent, 0, wx.EXPAND|wx.ALL, 5)
132   - sizer_percent.Add(num_ctrl_percent, 0, wx.ALL, 5)
133   -
134   - sizer_itens = wx.BoxSizer(wx.VERTICAL)
135   - sizer_itens.Add(lbl_message, 0, wx.EXPAND|wx.ALL, 5)
136   - sizer_itens.AddSizer(sizer_percent, 0, wx.EXPAND|wx.ALL, 5)
137   - sizer_itens.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 5)
138   -
139   - sizer_general = wx.BoxSizer(wx.HORIZONTAL)
140   - sizer_general.Add(bmp, 0, wx.ALIGN_CENTRE|wx.ALL, 10)
141   - sizer_general.AddSizer(sizer_itens, 0, wx.ALL , 5)
142   -
143   - #self.SetAutoLayout(True)
144   - self.SetSizer(sizer_general)
145   - sizer_general.Fit(self)
146   - self.Layout()
147   - self.Centre()
148   -
149   - def SetValue(self, value):
150   - self.num_ctrl_porcent.SetValue(value)
151   -
152   - def GetValue(self):
153   - return self.num_ctrl_porcent.GetValue()
154   -
155   - def Close(self):
156   - self.pre.Destroy()
157   -
158   -def ShowNumberDialog(message, value=0):
159   - dlg = NumberDialog(message, value)
160   - dlg.SetValue(value)
161   -
162   - if dlg.ShowModal() == wx.ID_OK:
163   - return dlg.GetValue()
164   - dlg.Destroy()
165   -
166   - return 0
167   -
168   -
169   -class ProgressDialog(object):
170   - def __init__(self, maximum, abort=False):
171   - self.title = "InVesalius 3"
172   - self.msg = _("Loading DICOM files")
173   - self.maximum = maximum
174   - self.current = 0
175   - self.style = wx.PD_APP_MODAL
176   - if abort:
177   - self.style = wx.PD_APP_MODAL | wx.PD_CAN_ABORT
178   -
179   - self.dlg = wx.ProgressDialog(self.title,
180   - self.msg,
181   - maximum = self.maximum,
182   - parent = None,
183   - style = self.style)
184   -
185   - self.dlg.Bind(wx.EVT_BUTTON, self.Cancel)
186   - self.dlg.SetSize(wx.Size(250,150))
187   -
188   - def Cancel(self, evt):
189   - Publisher.sendMessage("Cancel DICOM load")
190   -
191   - def Update(self, value, message):
192   - if(int(value) != self.maximum):
193   - try:
194   - return self.dlg.Update(value,message)
195   - #TODO:
196   - #Exception in the Windows XP 64 Bits with wxPython 2.8.10
197   - except(wx._core.PyAssertionError):
198   - return True
199   - else:
200   - return False
201   -
202   - def Close(self):
203   - self.dlg.Destroy()
204   -
205   -
206   -
207   -#---------
208   -WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\
209   - "All files (*.*)|*.*"
210   -
211   -WILDCARD_ANALYZE = "Analyze (*.hdr)|*.hdr|"\
212   - "All files (*.*)|*.*"
213   -
214   -WILDCARD_NIFTI = "NIfTI (*.nii)|*.nii|"\
215   - "All files (*.*)|*.*"
216   -
217   -def ShowOpenProjectDialog():
218   - # Default system path
219   - current_dir = os.path.abspath(".")
220   - dlg = wx.FileDialog(None, message=_("Open InVesalius 3 project..."),
221   - defaultDir="",
222   - defaultFile="", wildcard=WILDCARD_OPEN,
223   - style=wx.OPEN|wx.CHANGE_DIR)
224   -
225   - # inv3 filter is default
226   - dlg.SetFilterIndex(0)
227   -
228   - # Show the dialog and retrieve the user response. If it is the OK response,
229   - # process the data.
230   - filepath = None
231   - try:
232   - if dlg.ShowModal() == wx.ID_OK:
233   - # This returns a Python list of files that were selected.
234   - filepath = dlg.GetPath()
235   - except(wx._core.PyAssertionError): #FIX: win64
236   - filepath = dlg.GetPath()
237   -
238   - # Destroy the dialog. Don't do this until you are done with it!
239   - # BAD things can happen otherwise!
240   - dlg.Destroy()
241   - os.chdir(current_dir)
242   - return filepath
243   -
244   -
245   -def ShowOpenAnalyzeDialog():
246   - # Default system path
247   - current_dir = os.path.abspath(".")
248   - dlg = wx.FileDialog(None, message=_("Open Analyze file"),
249   - defaultDir="",
250   - defaultFile="", wildcard=WILDCARD_ANALYZE,
251   - style=wx.OPEN|wx.CHANGE_DIR)
252   -
253   - # inv3 filter is default
254   - dlg.SetFilterIndex(0)
255   -
256   - # Show the dialog and retrieve the user response. If it is the OK response,
257   - # process the data.
258   - filepath = None
259   - try:
260   - if dlg.ShowModal() == wx.ID_OK:
261   - # This returns a Python list of files that were selected.
262   - filepath = dlg.GetPath()
263   - except(wx._core.PyAssertionError): #FIX: win64
264   - filepath = dlg.GetPath()
265   -
266   - # Destroy the dialog. Don't do this until you are done with it!
267   - # BAD things can happen otherwise!
268   - dlg.Destroy()
269   - os.chdir(current_dir)
270   - return filepath
271   -
272   -def ShowOpenNiftiDialog():
273   - # Default system path
274   - current_dir = os.path.abspath(".")
275   - dlg = wx.FileDialog(None, message=_("Open NIfTI file"),
276   - defaultDir="",
277   - defaultFile="", wildcard=WILDCARD_NIFTI,
278   - style=wx.OPEN|wx.CHANGE_DIR)
279   -
280   - # inv3 filter is default
281   - dlg.SetFilterIndex(0)
282   -
283   - # Show the dialog and retrieve the user response. If it is the OK response,
284   - # process the data.
285   - filepath = None
286   - try:
287   - if dlg.ShowModal() == wx.ID_OK:
288   - # This returns a Python list of files that were selected.
289   - filepath = dlg.GetPath()
290   - except(wx._core.PyAssertionError): #FIX: win64
291   - filepath = dlg.GetPath()
292   -
293   - # Destroy the dialog. Don't do this until you are done with it!
294   - # BAD things can happen otherwise!
295   - dlg.Destroy()
296   - os.chdir(current_dir)
297   - return filepath
298   -
299   -
300   -def ShowImportDirDialog():
301   - current_dir = os.path.abspath(".")
302   -
303   - if (sys.platform == 'win32') or (sys.platform == 'linux2'):
304   - session = ses.Session()
305   -
306   - if (session.GetLastDicomFolder()):
307   - folder = session.GetLastDicomFolder()
308   - else:
309   - folder = ''
310   - else:
311   - folder = ''
312   -
313   - dlg = wx.DirDialog(None, _("Choose a DICOM folder:"), folder,
314   - style=wx.DD_DEFAULT_STYLE
315   - | wx.DD_DIR_MUST_EXIST
316   - | wx.DD_CHANGE_DIR)
317   -
318   - path = None
319   - try:
320   - if dlg.ShowModal() == wx.ID_OK:
321   - # GetPath returns in unicode, if a path has non-ascii characters a
322   - # UnicodeEncodeError is raised. To avoid this, path is encoded in utf-8
323   - if sys.platform == "win32":
324   - path = dlg.GetPath()
325   - else:
326   - path = dlg.GetPath().encode('utf-8')
327   -
328   - except(wx._core.PyAssertionError): #TODO: error win64
329   - if (dlg.GetPath()):
330   - path = dlg.GetPath()
331   -
332   - if (sys.platform != 'darwin'):
333   - if (path):
334   - session.SetLastDicomFolder(path)
335   -
336   - # Only destroy a dialog after you're done with it.
337   - dlg.Destroy()
338   - os.chdir(current_dir)
339   - return path
340   -
341   -def ShowSaveAsProjectDialog(default_filename=None):
342   - current_dir = os.path.abspath(".")
343   - dlg = wx.FileDialog(None,
344   - _("Save project as..."), # title
345   - "", # last used directory
346   - default_filename,
347   - _("InVesalius project (*.inv3)|*.inv3"),
348   - wx.SAVE|wx.OVERWRITE_PROMPT)
349   - #dlg.SetFilterIndex(0) # default is VTI
350   -
351   - filename = None
352   - try:
353   - if dlg.ShowModal() == wx.ID_OK:
354   - filename = dlg.GetPath()
355   - ok = 1
356   - else:
357   - ok = 0
358   - except(wx._core.PyAssertionError): #TODO: fix win64
359   - filename = dlg.GetPath()
360   - ok = 1
361   -
362   - if (ok):
363   - extension = "inv3"
364   - if sys.platform != 'win32':
365   - if filename.split(".")[-1] != extension:
366   - filename = filename + "." + extension
367   -
368   -
369   - os.chdir(current_dir)
370   - return filename
371   -
372   -#Dialog for neuronavigation markers
373   -def ShowSaveMarkersDialog(default_filename=None):
374   - current_dir = os.path.abspath(".")
375   - dlg = wx.FileDialog(None,
376   - _("Save markers as..."), # title
377   - "", # last used directory
378   - default_filename,
379   - _("Markers (*.txt)|*.txt"),
380   - wx.SAVE|wx.OVERWRITE_PROMPT)
381   - #dlg.SetFilterIndex(0) # default is VTI
382   -
383   - filename = None
384   - try:
385   - if dlg.ShowModal() == wx.ID_OK:
386   - filename = dlg.GetPath()
387   - ok = 1
388   - else:
389   - ok = 0
390   - except(wx._core.PyAssertionError): #TODO: fix win64
391   - filename = dlg.GetPath()
392   - ok = 1
393   -
394   - if (ok):
395   - extension = "txt"
396   - if sys.platform != 'win32':
397   - if filename.split(".")[-1] != extension:
398   - filename = filename + "." + extension
399   -
400   -
401   - os.chdir(current_dir)
402   - return filename
403   -
404   -def ShowLoadMarkersDialog():
405   - current_dir = os.path.abspath(".")
406   -
407   - dlg = wx.FileDialog(None, message=_("Load markers"),
408   - defaultDir="",
409   - defaultFile="",
410   - style=wx.OPEN|wx.CHANGE_DIR)
411   -
412   - # inv3 filter is default
413   - dlg.SetFilterIndex(0)
414   -
415   - # Show the dialog and retrieve the user response. If it is the OK response,
416   - # process the data.
417   - filepath = None
418   - try:
419   - if dlg.ShowModal() == wx.ID_OK:
420   - # This returns a Python list of files that were selected.
421   - filepath = dlg.GetPath()
422   - except(wx._core.PyAssertionError): #FIX: win64
423   - filepath = dlg.GetPath()
424   -
425   - # Destroy the dialog. Don't do this until you are done with it!
426   - # BAD things can happen otherwise!
427   - dlg.Destroy()
428   - os.chdir(current_dir)
429   - return filepath
430   -
431   -class MessageDialog(wx.Dialog):
432   - def __init__(self, message):
433   - pre = wx.PreDialog()
434   - pre.Create(None, -1, "InVesalius 3", size=(360, 370), pos=wx.DefaultPosition,
435   - style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION)
436   - self.PostCreate(pre)
437   -
438   - # Static text which contains message to user
439   - label = wx.StaticText(self, -1, message)
440   -
441   - # Buttons
442   - btn_yes = wx.Button(self, wx.ID_YES)
443   - btn_yes.SetHelpText("")
444   - btn_yes.SetDefault()
445   -
446   - btn_no = wx.Button(self, wx.ID_NO)
447   - btn_no.SetHelpText("")
448   -
449   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
450   - btn_cancel.SetHelpText("")
451   -
452   - btnsizer = wx.StdDialogButtonSizer()
453   - btnsizer.AddButton(btn_yes)
454   - btnsizer.AddButton(btn_cancel)
455   - btnsizer.AddButton(btn_no)
456   - btnsizer.Realize()
457   -
458   -
459   - sizer = wx.BoxSizer(wx.VERTICAL)
460   - sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
461   - sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|
462   - wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5)
463   - self.SetSizer(sizer)
464   - sizer.Fit(self)
465   -
466   - self.Centre()
467   -
468   -
469   -class UpdateMessageDialog(wx.Dialog):
470   - def __init__(self, url):
471   - msg=_("A new version of InVesalius is available. Do you want to open the download website now?")
472   - title=_("Invesalius Update")
473   - self.url = url
474   -
475   - pre = wx.PreDialog()
476   - pre.Create(None, -1, title, size=(360, 370), pos=wx.DefaultPosition,
477   - style=wx.DEFAULT_DIALOG_STYLE|wx.ICON_INFORMATION)
478   - self.PostCreate(pre)
479   -
480   - # Static text which contains message to user
481   - label = wx.StaticText(self, -1, msg)
482   -
483   - # Buttons
484   - btn_yes = wx.Button(self, wx.ID_YES)
485   - btn_yes.SetHelpText("")
486   - btn_yes.SetDefault()
487   -
488   - btn_no = wx.Button(self, wx.ID_NO)
489   - btn_no.SetHelpText("")
490   -
491   - btnsizer = wx.StdDialogButtonSizer()
492   - btnsizer.AddButton(btn_yes)
493   - btnsizer.AddButton(btn_no)
494   - btnsizer.Realize()
495   -
496   - sizer = wx.BoxSizer(wx.VERTICAL)
497   - sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
498   - sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|
499   - wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5)
500   - self.SetSizer(sizer)
501   - sizer.Fit(self)
502   - self.Centre()
503   -
504   - btn_yes.Bind(wx.EVT_BUTTON, self._OnYes)
505   - btn_no.Bind(wx.EVT_BUTTON, self._OnNo)
506   -
507   - # Subscribing to the pubsub event which happens when InVesalius is
508   - # closed.
509   - Publisher.subscribe(self._OnCloseInV, 'Exit')
510   -
511   - def _OnYes(self, evt):
512   - # Launches the default browser with the url to download the new
513   - # InVesalius version.
514   - wx.LaunchDefaultBrowser(self.url)
515   - self.Close()
516   - self.Destroy()
517   -
518   - def _OnNo(self, evt):
519   - # Closes and destroy this dialog.
520   - self.Close()
521   - self.Destroy()
522   -
523   - def _OnCloseInV(self, pubsub_evt):
524   - # Closes and destroy this dialog.
525   - self.Close()
526   - self.Destroy()
527   -
528   -
529   -def SaveChangesDialog__Old(filename):
530   - message = _("The project %s has been modified.\nSave changes?")%filename
531   - dlg = MessageDialog(message)
532   -
533   - answer = dlg.ShowModal()
534   - dlg.Destroy()
535   - if answer == wx.ID_YES:
536   - return 1
537   - elif answer == wx.ID_NO:
538   - return 0
539   - else:
540   - return -1
541   -
542   -
543   -def ImportEmptyDirectory(dirpath):
544   - msg = _("%s is an empty folder.") % dirpath.decode("utf-8")
545   - if sys.platform == 'darwin':
546   - dlg = wx.MessageDialog(None, "",
547   - msg,
548   - wx.ICON_INFORMATION | wx.OK)
549   - else:
550   - dlg = wx.MessageDialog(None, msg,
551   - "InVesalius 3",
552   - wx.ICON_INFORMATION | wx.OK)
553   - dlg.ShowModal()
554   - dlg.Destroy()
555   -
556   -def ImportInvalidFiles():
557   - msg = _("There are no DICOM files in the selected folder.")
558   - if sys.platform == 'darwin':
559   - dlg = wx.MessageDialog(None, "", msg,
560   - wx.ICON_INFORMATION | wx.OK)
561   - else:
562   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
563   - wx.ICON_INFORMATION | wx.OK)
564   - dlg.ShowModal()
565   - dlg.Destroy()
566   -
567   -def InexistentMask():
568   - msg = _("A mask is needed to create a surface.")
569   - if sys.platform == 'darwin':
570   - dlg = wx.MessageDialog(None, "", msg,
571   - wx.ICON_INFORMATION | wx.OK)
572   - else:
573   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
574   - wx.ICON_INFORMATION | wx.OK)
575   - dlg.ShowModal()
576   - dlg.Destroy()
577   -
578   -def MaskSelectionRequiredForRemoval():
579   - msg = _("No mask was selected for removal.")
580   - if sys.platform == 'darwin':
581   - dlg = wx.MessageDialog(None, "", msg,
582   - wx.ICON_INFORMATION | wx.OK)
583   - else:
584   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
585   - wx.ICON_INFORMATION | wx.OK)
586   - dlg.ShowModal()
587   - dlg.Destroy()
588   -
589   -def SurfaceSelectionRequiredForRemoval():
590   - msg = _("No surface was selected for removal.")
591   - if sys.platform == 'darwin':
592   - dlg = wx.MessageDialog(None, "", msg,
593   - wx.ICON_INFORMATION | wx.OK)
594   - else:
595   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
596   - wx.ICON_INFORMATION | wx.OK)
597   - dlg.ShowModal()
598   - dlg.Destroy()
599   -
600   -
601   -def MeasureSelectionRequiredForRemoval():
602   - msg = _("No measure was selected for removal.")
603   - if sys.platform == 'darwin':
604   - dlg = wx.MessageDialog(None, "", msg,
605   - wx.ICON_INFORMATION | wx.OK)
606   - else:
607   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
608   - wx.ICON_INFORMATION | wx.OK)
609   - dlg.ShowModal()
610   - dlg.Destroy()
611   -
612   -def MaskSelectionRequiredForDuplication():
613   - msg = _("No mask was selected for duplication.")
614   - if sys.platform == 'darwin':
615   - dlg = wx.MessageDialog(None, "", msg,
616   - wx.ICON_INFORMATION | wx.OK)
617   - else:
618   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
619   - wx.ICON_INFORMATION | wx.OK)
620   - dlg.ShowModal()
621   - dlg.Destroy()
622   -
623   -
624   -
625   -def SurfaceSelectionRequiredForDuplication():
626   - msg = _("No surface was selected for duplication.")
627   - if sys.platform == 'darwin':
628   - dlg = wx.MessageDialog(None, "", msg,
629   - wx.ICON_INFORMATION | wx.OK)
630   - else:
631   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
632   - wx.ICON_INFORMATION | wx.OK)
633   - dlg.ShowModal()
634   - dlg.Destroy()
635   -
636   -#=========aji======================================================================
637   -def InvalidReferences():
638   - msg = _("The references are not set.")
639   - if sys.platform == 'darwin':
640   - dlg = wx.MessageDialog(None, "", msg,
641   - wx.ICON_INFORMATION | wx.OK)
642   - else:
643   - dlg = wx.MessageDialog(None,msg, "InVesalius 3 - Neuronavigator",
644   - wx.ICON_INFORMATION | wx.OK)
645   - dlg.ShowModal()
646   - dlg.Destroy()
647   -
648   -#Dialog for advertising if the tracker is not connetcted
649   -def TrackerNotConnected(tracker):
650   - msg = None
651   - if tracker == 0:
652   - msg = _("The PolhemusISO selected is not connected.")
653   - elif tracker == 1:
654   - msg = _("The Polhemus selected is not connected.")
655   - elif tracker == 2:
656   - msg = _("The Claron MTC is not connected.")
657   - elif tracker == 3:
658   - msg = _("The Zebris is not connected.")
659   -
660   - if sys.platform == 'darwin':
661   - dlg = wx.MessageDialog(None, "", msg,
662   - wx.ICON_INFORMATION | wx.OK)
663   - else:
664   - dlg = wx.MessageDialog(None, msg, "InVesalius 3 - Neuronavigator",
665   - wx.ICON_INFORMATION | wx.OK)
666   - dlg.ShowModal()
667   - dlg.Destroy()
668   -
669   -def InvalidTxt():
670   - msg = _("The TXT file is invalid.")
671   - if sys.platform == 'darwin':
672   - dlg = wx.MessageDialog(None, "", msg,
673   - wx.ICON_INFORMATION | wx.OK)
674   - else:
675   - dlg = wx.MessageDialog(None,msg, "InVesalius 3 - Neuronavigator",
676   - wx.ICON_INFORMATION | wx.OK)
677   - dlg.ShowModal()
678   - dlg.Destroy()
679   -
680   -def error_correg_fine():
681   - msg = _("There aren't any created surface.")
682   - if sys.platform == 'darwin':
683   - dlg = wx.MessageDialog(None, "", msg,
684   - wx.ICON_INFORMATION | wx.OK)
685   - else:
686   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
687   - wx.ICON_INFORMATION | wx.OK)
688   - dlg.ShowModal()
689   - dlg.Destroy()
690   -#===============================================================================
691   -
692   -class NewMask(wx.Dialog):
693   - def __init__(self,
694   - parent=None,
695   - ID=-1,
696   - title="InVesalius 3",
697   - size=wx.DefaultSize,
698   - pos=wx.DefaultPosition,
699   - style=wx.DEFAULT_DIALOG_STYLE,
700   - useMetal=False):
701   - import constants as const
702   - import data.mask as mask
703   - import project as prj
704   -
705   - # Instead of calling wx.Dialog.__init__ we precreate the dialog
706   - # so we can set an extra style that must be set before
707   - # creation, and then we create the GUI object using the Create
708   - # method.
709   - pre = wx.PreDialog()
710   - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
711   - pre.Create(parent, ID, title, pos, (500,300), style)
712   -
713   - # This next step is the most important, it turns this Python
714   - # object into the real wrapper of the dialog (instead of pre)
715   - # as far as the wxPython extension is concerned.
716   - self.PostCreate(pre)
717   -
718   - self.CenterOnScreen()
719   -
720   - # This extra style can be set after the UI object has been created.
721   - if 'wxMac' in wx.PlatformInfo and useMetal:
722   - self.SetExtraStyle(wx.DIALOG_EX_METAL)
723   -
724   - self.CenterOnScreen()
725   -
726   - # LINE 1: Surface name
727   -
728   - label_mask = wx.StaticText(self, -1, _("New mask name:"))
729   -
730   - default_name = const.MASK_NAME_PATTERN %(mask.Mask.general_index+2)
731   - text = wx.TextCtrl(self, -1, "", size=(80,-1))
732   - text.SetHelpText(_("Name the mask to be created"))
733   - text.SetValue(default_name)
734   - self.text = text
735   -
736   - # LINE 2: Threshold of reference
737   -
738   - # Informative label
739   - label_thresh = wx.StaticText(self, -1, _("Threshold preset:"))
740   -
741   - # Retrieve existing masks
742   - project = prj.Project()
743   - thresh_list = project.threshold_modes.keys()
744   - thresh_list.sort()
745   - default_index = thresh_list.index(_("Bone"))
746   - self.thresh_list = thresh_list
747   -
748   - # Mask selection combo
749   - combo_thresh = wx.ComboBox(self, -1, "", choices= self.thresh_list,
750   - style=wx.CB_DROPDOWN|wx.CB_READONLY)
751   - combo_thresh.SetSelection(default_index)
752   - if sys.platform != 'win32':
753   - combo_thresh.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
754   - self.combo_thresh = combo_thresh
755   -
756   - # LINE 3: Gradient
757   - bound_min, bound_max = project.threshold_range
758   - thresh_min, thresh_max = project.threshold_modes[_("Bone")]
759   - original_colour = random.choice(const.MASK_COLOUR)
760   - self.colour = original_colour
761   - colour = [255*i for i in original_colour]
762   - colour.append(100)
763   - gradient = grad.GradientSlider(self, -1, int(bound_min),
764   - int(bound_max),
765   - int(thresh_min), int(thresh_max),
766   - colour)
767   - self.gradient = gradient
768   -
769   - # OVERVIEW
770   - # Sizer that joins content above
771   - flag_link = wx.EXPAND|wx.GROW|wx.ALL
772   - flag_button = wx.ALL | wx.EXPAND| wx.GROW
773   -
774   - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=10, vgap=10)
775   - fixed_sizer.AddGrowableCol(0, 1)
776   - fixed_sizer.AddMany([ (label_mask, 1, flag_link, 5),
777   - (text, 1, flag_button, 2),
778   - (label_thresh, 1, flag_link, 5),
779   - (combo_thresh, 0, flag_button, 1)])#,
780   - #(label_quality, 1, flag_link, 5),
781   - #(combo_quality, 0, flag_button, 1)])
782   -
783   - # LINE 6: Buttons
784   -
785   - btn_ok = wx.Button(self, wx.ID_OK)
786   - btn_ok.SetDefault()
787   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
788   -
789   - btnsizer = wx.StdDialogButtonSizer()
790   - btnsizer.AddButton(btn_ok)
791   - btnsizer.AddButton(btn_cancel)
792   - btnsizer.Realize()
793   -
794   - # OVERVIEW
795   - # Merge all sizers and checkboxes
796   - sizer = wx.BoxSizer(wx.VERTICAL)
797   - sizer.Add(fixed_sizer, 0, wx.ALL|wx.GROW|wx.EXPAND, 15)
798   - sizer.Add(gradient, 1, wx.BOTTOM|wx.RIGHT|wx.LEFT|wx.EXPAND|wx.GROW, 20)
799   - sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 10)
800   -
801   - self.SetSizer(sizer)
802   - sizer.Fit(self)
803   -
804   - self.Bind(grad.EVT_THRESHOLD_CHANGED, self.OnSlideChanged, self.gradient)
805   - self.combo_thresh.Bind(wx.EVT_COMBOBOX, self.OnComboThresh)
806   -
807   -
808   - def OnComboThresh(self, evt):
809   - import project as prj
810   - proj = prj.Project()
811   - (thresh_min, thresh_max) = proj.threshold_modes[evt.GetString()]
812   - self.gradient.SetMinimun(thresh_min)
813   - self.gradient.SetMaximun(thresh_max)
814   -
815   - def OnSlideChanged(self, evt):
816   - import project as prj
817   - thresh_min = self.gradient.GetMinValue()
818   - thresh_max = self.gradient.GetMaxValue()
819   - thresh = (thresh_min, thresh_max)
820   - proj = prj.Project()
821   - if thresh in proj.threshold_modes.values():
822   - preset_name = proj.threshold_modes.get_key(thresh)[0]
823   - index = self.thresh_list.index(preset_name)
824   - self.combo_thresh.SetSelection(index)
825   - else:
826   - index = self.thresh_list.index(_("Custom"))
827   - self.combo_thresh.SetSelection(index)
828   -
829   - def GetValue(self):
830   - #mask_index = self.combo_mask.GetSelection()
831   - mask_name = self.text.GetValue()
832   - thresh_value = [self.gradient.GetMinValue(), self.gradient.GetMaxValue()]
833   - #quality = const.SURFACE_QUALITY_LIST[self.combo_quality.GetSelection()]
834   - #fill_holes = self.check_box_holes.GetValue()
835   - #keep_largest = self.check_box_largest.GetValue()
836   - #return (mask_index, surface_name, quality, fill_holes, keep_largest)
837   - return mask_name, thresh_value, self.colour
838   -
839   -
840   -def InexistentPath(path):
841   - msg = _("%s does not exist.")%(path)
842   - if sys.platform == 'darwin':
843   - dlg = wx.MessageDialog(None, "", msg,
844   - wx.ICON_INFORMATION | wx.OK)
845   - else:
846   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
847   - wx.ICON_INFORMATION | wx.OK)
848   - dlg.ShowModal()
849   - dlg.Destroy()
850   -
851   -def MissingFilesForReconstruction():
852   - msg = _("Please, provide more than one DICOM file for 3D reconstruction")
853   - if sys.platform == 'darwin':
854   - dlg = wx.MessageDialog(None, "", msg,
855   - wx.ICON_INFORMATION | wx.OK)
856   - else:
857   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
858   - wx.ICON_INFORMATION | wx.OK)
859   - dlg.ShowModal()
860   - dlg.Destroy()
861   -
862   -def SaveChangesDialog(filename, parent):
863   - current_dir = os.path.abspath(".")
864   - msg = _("The project %s has been modified.\nSave changes?")%filename
865   - if sys.platform == 'darwin':
866   - dlg = wx.MessageDialog(None, "", msg,
867   - wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL)
868   - else:
869   - dlg = wx.MessageDialog(None, msg, "InVesalius 3",
870   - wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL)
871   -
872   - try:
873   - answer = dlg.ShowModal()
874   - except(wx._core.PyAssertionError): #TODO: FIX win64
875   - answer = wx.ID_YES
876   -
877   - dlg.Destroy()
878   - os.chdir(current_dir)
879   -
880   - if answer == wx.ID_YES:
881   - return 1
882   - elif answer == wx.ID_NO:
883   - return 0
884   - else:
885   - return -1
886   -
887   -def SaveChangesDialog2(filename):
888   - current_dir = os.path.abspath(".")
889   - msg = _("The project %s has been modified.\nSave changes?")%filename
890   - if sys.platform == 'darwin':
891   - dlg = wx.MessageDialog(None, "", msg,
892   - wx.ICON_QUESTION | wx.YES_NO)
893   - else:
894   - dlg = wx.MessageDialog(None, msg,
895   - "InVesalius 3",
896   - wx.ICON_QUESTION | wx.YES_NO)
897   -
898   - answer = dlg.ShowModal()
899   - dlg.Destroy()
900   - os.chdir(current_dir)
901   - if answer == wx.ID_YES:
902   - return 1
903   - else:# answer == wx.ID_NO:
904   - return 0
905   -
906   -
907   -
908   -def ShowAboutDialog(parent):
909   -
910   - info = wx.AboutDialogInfo()
911   - info.Name = "InVesalius"
912   - info.Version = "3.0 - Beta 5"
913   - info.Copyright = _("(c) 2007-2013 Renato Archer Information Technology Center - CTI")
914   - info.Description = wordwrap(_("InVesalius is a medical imaging program for 3D reconstruction. It uses a sequence of 2D DICOM image files acquired with CT or MRI scanners. InVesalius allows exporting 3D volumes or surfaces as STL files for creating physical models of a patient's anatomy using rapid prototyping technologies. The software is supported by CTI, CNPq and the Brazilian Ministry of Health.\n\n Contact: invesalius@cti.gov.br"), 350, wx.ClientDC(parent))
915   -
916   -# _("InVesalius is a software for medical imaging 3D reconstruction. ")+\
917   -# _("Its input is a sequency of DICOM 2D image files acquired with CT or MR.\n\n")+\
918   -# _("The software also allows generating correspondent STL files,")+\
919   -# _("so the user can print 3D physical models of the patient's anatomy ")+\
920   -# _("using Rapid Prototyping."), 350, wx.ClientDC(parent))
921   - info.WebSite = ("http://www.cti.gov.br/invesalius")
922   - info.License = _("GNU GPL (General Public License) version 2")
923   -
924   - info.Developers = ["Paulo Henrique Junqueira Amorim",
925   - "Thiago Franco de Moraes",
926   - "Jorge Vicente Lopes da Silva",
927   - "Tatiana Al-Chueyr (former)",
928   - "Guilherme Cesar Soares Ruppert (former)",
929   - "Fabio de Souza Azevedo (former)",
930   - "Bruno Lara Bottazzini (contributor)"]
931   -
932   - info.Translators = ["Alex P. Natsios",
933   - "Andreas Loupasakis",
934   - "Cheng-Chia Tseng",
935   - "Dimitris Glezos",
936   - "Eugene Liscio",
937   - u"Frédéric Lopez",
938   - "Javier de Lima Moreno"
939   - "Nikos Korkakakis",
940   - "Massimo Crisantemo",
941   - "Raul Bolliger Neto",
942   - "Sebastian Hilbert",
943   - "Semarang Pari"]
944   -
945   - #info.DocWriters = ["Fabio Francisco da Silva (PT)"]
946   -
947   - info.Artists = ["Otavio Henrique Junqueira Amorim"]
948   -
949   - # Then we call wx.AboutBox providing its info object
950   - wx.AboutBox(info)
951   -
952   -
953   -def ShowSavePresetDialog(default_filename="raycasting"):
954   - dlg = wx.TextEntryDialog(None,
955   - _("Save raycasting preset as:"),
956   - "InVesalius 3")
957   - #dlg.SetFilterIndex(0) # default is VTI
958   - filename = None
959   - try:
960   - if dlg.ShowModal() == wx.ID_OK:
961   - filename = dlg.GetValue()
962   - except(wx._core.PyAssertionError):
963   - filename = dlg.GetValue()
964   -
965   - return filename
966   -
967   -class NewSurfaceDialog(wx.Dialog):
968   - def __init__(self, parent=None, ID=-1, title="InVesalius 3", size=wx.DefaultSize,
969   - pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE,
970   - useMetal=False):
971   - import constants as const
972   - import data.surface as surface
973   - import project as prj
974   -
975   - # Instead of calling wx.Dialog.__init__ we precreate the dialog
976   - # so we can set an extra style that must be set before
977   - # creation, and then we create the GUI object using the Create
978   - # method.
979   - pre = wx.PreDialog()
980   - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
981   - pre.Create(parent, ID, title, pos, (500,300), style)
982   -
983   - # This next step is the most important, it turns this Python
984   - # object into the real wrapper of the dialog (instead of pre)
985   - # as far as the wxPython extension is concerned.
986   - self.PostCreate(pre)
987   -
988   - self.CenterOnScreen()
989   -
990   - # This extra style can be set after the UI object has been created.
991   - if 'wxMac' in wx.PlatformInfo and useMetal:
992   - self.SetExtraStyle(wx.DIALOG_EX_METAL)
993   -
994   - self.CenterOnScreen()
995   -
996   - # LINE 1: Surface name
997   -
998   - label_surface = wx.StaticText(self, -1, _("New surface name:"))
999   -
1000   - default_name = const.SURFACE_NAME_PATTERN %(surface.Surface.general_index+2)
1001   - text = wx.TextCtrl(self, -1, "", size=(80,-1))
1002   - text.SetHelpText(_("Name the surface to be created"))
1003   - text.SetValue(default_name)
1004   - self.text = text
1005   -
1006   - # LINE 2: Mask of reference
1007   -
1008   - # Informative label
1009   - label_mask = wx.StaticText(self, -1, _("Mask of reference:"))
1010   -
1011   - # Retrieve existing masks
1012   - project = prj.Project()
1013   - index_list = project.mask_dict.keys()
1014   - index_list.sort()
1015   - self.mask_list = [project.mask_dict[index].name for index in index_list]
1016   -
1017   -
1018   - # Mask selection combo
1019   - combo_mask = wx.ComboBox(self, -1, "", choices= self.mask_list,
1020   - style=wx.CB_DROPDOWN|wx.CB_READONLY)
1021   - combo_mask.SetSelection(len(self.mask_list)-1)
1022   - if sys.platform != 'win32':
1023   - combo_mask.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
1024   - self.combo_mask = combo_mask
1025   -
1026   - # LINE 3: Surface quality
1027   - label_quality = wx.StaticText(self, -1, _("Surface quality:"))
1028   -
1029   - choices = const.SURFACE_QUALITY_LIST
1030   - style = wx.CB_DROPDOWN|wx.CB_READONLY
1031   - combo_quality = wx.ComboBox(self, -1, "",
1032   - choices= choices,
1033   - style=style)
1034   - combo_quality.SetSelection(3)
1035   - if sys.platform != 'win32':
1036   - combo_quality.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
1037   - self.combo_quality = combo_quality
1038   -
1039   -
1040   - # OVERVIEW
1041   - # Sizer that joins content above
1042   - flag_link = wx.EXPAND|wx.GROW|wx.ALL
1043   - flag_button = wx.ALL | wx.EXPAND| wx.GROW
1044   -
1045   - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=10, vgap=0)
1046   - fixed_sizer.AddGrowableCol(0, 1)
1047   - fixed_sizer.AddMany([ (label_surface, 1, flag_link, 5),
1048   - (text, 1, flag_button, 2),
1049   - (label_mask, 1, flag_link, 5),
1050   - (combo_mask, 0, flag_button, 1),
1051   - (label_quality, 1, flag_link, 5),
1052   - (combo_quality, 0, flag_button, 1)])
1053   -
1054   -
1055   - # LINES 4 and 5: Checkboxes
1056   - check_box_holes = wx.CheckBox(self, -1, _("Fill holes"))
1057   - check_box_holes.SetValue(True)
1058   - self.check_box_holes = check_box_holes
1059   - check_box_largest = wx.CheckBox(self, -1, _("Keep largest region"))
1060   - self.check_box_largest = check_box_largest
1061   -
1062   - # LINE 6: Buttons
1063   -
1064   - btn_ok = wx.Button(self, wx.ID_OK)
1065   - btn_ok.SetDefault()
1066   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
1067   -
1068   - btnsizer = wx.StdDialogButtonSizer()
1069   - btnsizer.AddButton(btn_ok)
1070   - btnsizer.AddButton(btn_cancel)
1071   - btnsizer.Realize()
1072   -
1073   - # OVERVIEW
1074   - # Merge all sizers and checkboxes
1075   - sizer = wx.BoxSizer(wx.VERTICAL)
1076   - sizer.Add(fixed_sizer, 0, wx.TOP|wx.RIGHT|wx.LEFT|wx.GROW|wx.EXPAND, 20)
1077   - sizer.Add(check_box_holes, 0, wx.RIGHT|wx.LEFT, 30)
1078   - sizer.Add(check_box_largest, 0, wx.RIGHT|wx.LEFT, 30)
1079   - sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.ALL, 10)
1080   -
1081   - self.SetSizer(sizer)
1082   - sizer.Fit(self)
1083   -
1084   - def GetValue(self):
1085   - mask_index = self.combo_mask.GetSelection()
1086   - surface_name = self.text.GetValue()
1087   - quality = const.SURFACE_QUALITY_LIST[self.combo_quality.GetSelection()]
1088   - fill_holes = self.check_box_holes.GetValue()
1089   - keep_largest = self.check_box_largest.GetValue()
1090   - return (mask_index, surface_name, quality, fill_holes, keep_largest)
1091   -
1092   -
1093   -
1094   -def ExportPicture(type_=""):
1095   - import constants as const
1096   - INDEX_TO_EXTENSION = {0: "bmp", 1: "jpg", 2: "png", 3: "ps", 4:"povray", 5:"tiff"}
1097   - WILDCARD_SAVE_PICTURE = _("BMP image")+" (*.bmp)|*.bmp|"+\
1098   - _("JPG image")+" (*.jpg)|*.jpg|"+\
1099   - _("PNG image")+" (*.png)|*.png|"+\
1100   - _("PostScript document")+" (*.ps)|*.ps|"+\
1101   - _("POV-Ray file")+" (*.pov)|*.pov|"+\
1102   - _("TIFF image")+" (*.tif)|*.tif"
1103   -
1104   - INDEX_TO_TYPE = {0: const.FILETYPE_BMP,
1105   - 1: const.FILETYPE_JPG,
1106   - 2: const.FILETYPE_PNG,
1107   - 3: const.FILETYPE_PS,
1108   - 4: const.FILETYPE_POV,
1109   - 5: const.FILETYPE_TIF}
1110   -
1111   - utils.debug("ExportPicture")
1112   - project = proj.Project()
1113   -
1114   - project_name = "%s_%s" % (project.name, type_)
1115   - if not sys.platform in ('win32', 'linux2'):
1116   - project_name += ".jpg"
1117   -
1118   - dlg = wx.FileDialog(None,
1119   - "Save %s picture as..." %type_,
1120   - "", # last used directory
1121   - project_name, # filename
1122   - WILDCARD_SAVE_PICTURE,
1123   - wx.SAVE|wx.OVERWRITE_PROMPT)
1124   - dlg.SetFilterIndex(1) # default is VTI
1125   -
1126   - if dlg.ShowModal() == wx.ID_OK:
1127   - filetype_index = dlg.GetFilterIndex()
1128   - filetype = INDEX_TO_TYPE[filetype_index]
1129   - extension = INDEX_TO_EXTENSION[filetype_index]
1130   - filename = dlg.GetPath()
1131   - if sys.platform != 'win32':
1132   - if filename.split(".")[-1] != extension:
1133   - filename = filename + "."+ extension
1134   - return filename, filetype
1135   - else:
1136   - return ()
1137   -
1138   -#=======aji========================================================================
1139   -#===============================================================================
1140   -class FineCalibration(wx.Window):
1141   - def __init__(self, parent=None, ID=-1, title="Fine Calibration", size=wx.DefaultSize,
1142   - pos=wx.DefaultPosition,
1143   - useMetal=False):
1144   -
1145   - self.correg = None
1146   - self.staticballs = []
1147   - self.ball_id = 0
1148   - self.ball_centers = []
1149   - self.to_translate = 0
1150   - self.flagpoint1 = 0
1151   - self.init_angle_plh = None
1152   - ####ICP##########
1153   - # initial parameters
1154   - self.actor_head_init = None
1155   - self.actor_cloud = None
1156   -
1157   - # actors parameters
1158   - self.color_head_init = 1.0, 0.0, 0.0
1159   - self.color_cloud = 0.0, 1.0, 0.0
1160   - self.color_head_icp = 224.0/255.0, 201.0/255.0, 190.0/255.0
1161   - self.opacity_head_init = 1.0
1162   - self.opacity_cloud = 0.7
1163   - self.opacity_head_icp = 1.0
1164   - ################
1165   -
1166   - # Instead of calling wx.Dialog.__init__ we precreate the dialog
1167   - # so we can set an extra style that must be set before
1168   - # creation, and then we create the GUI object using the Create
1169   - # method.
1170   - self.pre = wx.Frame(parent, -1, title)
1171   - self.pre.SetPosition(pos)
1172   - self.pre.SetSize(wx.Size(200,200))
1173   - self.pre.SetBackgroundColour('LIGHT GRAY')
1174   - self.pre.CenterOnScreen()
1175   - self.pre.Show()
1176   -
1177   -
1178   - #pre.Create(parent, ID, title, pos, (500,300))
1179   -
1180   - # This next step is the most important, it turns this Python
1181   - # object into the real wrapper of the dialog (instead of pre)
1182   - # as far as the wxPython extension is concerned.
1183   - self.PostCreate(self.pre)
1184   -
1185   -
1186   -
1187   - # This extra style can be set after the UI object has been created.
1188   - if 'wxMac' in wx.PlatformInfo and useMetal:
1189   - self.SetExtraStyle(wx.DIALOG_EX_METAL)
1190   -
1191   - self.Center()
1192   - self.__bind_events()
1193   - self.draw_gui()
1194   -
1195   -
1196   -# try:
1197   - Publisher.sendMessage('Load surface into DLG')
1198   -# except:
1199   -# try:
1200   -# Publisher.sendMessage('Load volume DLG')
1201   -# except:
1202   -# error_correg_fine()
1203   -
1204   - #self.LoadData()
1205   - def ShowLoadSurfaceDialog(self):
1206   - current_dir = os.path.abspath(".")
1207   -
1208   - dlg = wx.FileDialog(None, message=_("Load surface"),
1209   - defaultDir="",
1210   - defaultFile="",
1211   - style=wx.OPEN|wx.CHANGE_DIR)
1212   -
1213   - # inv3 filter is default
1214   - dlg.SetFilterIndex(0)
1215   -
1216   - # Show the dialog and retrieve the user response. If it is the OK response,
1217   - # process the data.
1218   - filepath = None
1219   - try:
1220   - if dlg.ShowModal() == wx.ID_OK:
1221   - # This returns a Python list of files that were selected.
1222   - filepath = dlg.GetPath()
1223   - except(wx._core.PyAssertionError): #FIX: win64
1224   - filepath = dlg.GetPath()
1225   -
1226   - # Destroy the dialog. Don't do this until you are done with it!
1227   - # BAD things can happen otherwise!
1228   - dlg.Destroy()
1229   - os.chdir(current_dir)
1230   - return filepath
1231   -
1232   - def __bind_events(self):
1233   - Publisher.subscribe(self.LoadVolumeDLG,
1234   - 'Load Raycasting into DLG')
1235   - Publisher.subscribe(self.LoadActorDLG,
1236   - 'Load surface actor into DLG')
1237   - # LINE 1: Janela
1238   -
1239   - def draw_gui(self):
1240   - #style = vtk.vtkInteractorStyleTrackballActor()
1241   - self.panel=wx.Panel(self)
1242   - self.interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize())
1243   - #self.interactor.SetInteractorStyle(style)
1244   - self.interactor.Enable(1)
1245   - self.ren = vtk.vtkRenderer()
1246   - self.interactor.GetRenderWindow().AddRenderer(self.ren)
1247   -
1248   - # LINE 2: Botoes
1249   -
1250   - marker = wx.Button(self.panel, -1, "Create Marker",size = wx.Size(85,23))
1251   - marker.Bind(wx.EVT_BUTTON, self.OnCalibrationMarkers)
1252   -
1253   - marker_load = wx.Button(self.panel, -1, "Load Marker",size = wx.Size(85,23))
1254   - marker_load.Bind(wx.EVT_BUTTON, self.OnLoadMarkers)
1255   -
1256   - apply_ICP = wx.Button(self.panel, -1, "Apply ICP",size = wx.Size(85,23))
1257   - apply_ICP.Bind(wx.EVT_BUTTON, self.OnApplyICP)
1258   -
1259   - self.showObjICP = wx.CheckBox(self.panel, -1, 'Show ICP Surface', (100, 10))
1260   - self.showObjICP.SetValue(False)
1261   - wx.EVT_CHECKBOX(self, self.showObjICP.GetId(), self.ShowObjectICP)
1262   -
1263   - self.showObjCloud = wx.CheckBox(self.panel, -1, 'Show Cloud of Points', (100, 10))
1264   - self.showObjCloud.SetValue(True)
1265   - wx.EVT_CHECKBOX(self, self.showObjCloud.GetId(), self.ShowObjectCloud)
1266   -
1267   - self.showObjHead = wx.CheckBox(self.panel, -1, 'Show Head Surface', (100, 10))
1268   - self.showObjHead.SetValue(True)
1269   - wx.EVT_CHECKBOX(self, self.showObjHead.GetId(), self.ShowObjectHead)
1270   -
1271   - text_X = wx.StaticText(self.panel, -1, _("X:"))
1272   - spin_X = wx.SpinCtrl(self.panel, -1, "X", size = wx.Size(67,23))
1273   - spin_X .SetValue(0)
1274   - spin_X.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1275   - spin_X.Bind(wx.EVT_TEXT, self.translate_rotate)
1276   - spin_X .SetRange(-500,500)
1277   -
1278   - self.spin_X = spin_X
1279   -
1280   - text_Y = wx.StaticText(self.panel, -1, _("Y:"))
1281   - spin_Y = wx.SpinCtrl(self.panel, -1, "Y", size = wx.Size(67,23))
1282   - spin_Y .SetValue(0)
1283   - spin_Y.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1284   - spin_Y.Bind(wx.EVT_TEXT, self.translate_rotate)
1285   - spin_Y .SetRange(-500,500)
1286   -
1287   - self.spin_Y = spin_Y
1288   -
1289   - text_Z = wx.StaticText(self.panel, -1, _("Z:"))
1290   - spin_Z = wx.SpinCtrl(self.panel, -1, "Z", size = wx.Size(67,23))
1291   - spin_Z .SetValue(0)
1292   - spin_Z.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1293   - spin_Z.Bind(wx.EVT_TEXT, self.translate_rotate)
1294   - spin_Z .SetRange(-500,500)
1295   -
1296   - self.spin_Z = spin_Z
1297   -
1298   - text_A = wx.StaticText(self.panel,-1, _("Alfa:"))
1299   - spin_A = wx.SpinCtrl(self.panel, -1, "Alfa", size = wx.Size(67,23))
1300   - spin_A .SetValue(0)
1301   - spin_A .SetRange(-500,500)
1302   - spin_A.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1303   - spin_A.Bind(wx.EVT_TEXT, self.translate_rotate)
1304   -
1305   - self.spin_A = spin_A
1306   -
1307   - text_B = wx.StaticText(self.panel, -1, _("Beta:"))
1308   - spin_B = wx.SpinCtrl(self.panel, -1, "Beta", size = wx.Size(67,23))
1309   - spin_B .SetValue(0)
1310   - spin_B .SetRange(-500,500)
1311   - spin_B.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1312   - spin_B.Bind(wx.EVT_TEXT, self.translate_rotate)
1313   -
1314   - self.spin_B = spin_B
1315   -
1316   - text_G = wx.StaticText(self.panel, -1, _("Gama:"))
1317   - spin_G = wx.SpinCtrl(self.panel, -1, "Gama", size = wx.Size(67,23))
1318   - spin_G .SetValue(0)
1319   - spin_G .SetRange(-500,500)
1320   - spin_G.Bind(wx.EVT_SPINCTRL, self.translate_rotate)
1321   - spin_G.Bind(wx.EVT_TEXT, self.translate_rotate)
1322   -
1323   - self.spin_G = spin_G
1324   -
1325   - text_inter = wx.StaticText(self.panel, -1, _("Number of Iterations:"))
1326   - spin_inter = wx.SpinCtrl(self.panel, -1, "Numb Inter", size = wx.Size(95,23))
1327   - spin_inter.SetValue(1000)
1328   - spin_inter.SetRange(0,5000)
1329   -# spin_X .SetValue()
1330   - self.spin_inter = spin_inter
1331   -
1332   - text_land = wx.StaticText(self.panel, -1, _("Number of Landmarks:"))
1333   - spin_land = wx.SpinCtrl(self.panel, -1, "Landmarks", size = wx.Size(95,23))
1334   - spin_land.SetValue(1000)
1335   - spin_land .SetRange(0,5000)
1336   -
1337   -# spin_Y .SetValue()
1338   - self.spin_land = spin_land
1339   -
1340   - text_mean = wx.StaticText(self.panel, -1, _("Max Mean Distance:"))
1341   - #spin_mean= wx.SpinCtrl(self.panel, 1, "mean", size = wx.Size(107,23))
1342   - spin_mean = floatspin.FloatSpin(self.panel,-1,value=0.01, min_val=0.0,max_val=10.0, increment=0.01, digits=2)
1343   -
1344   - #spin_mean.SetValue(0.01)
1345   - #spin_mean .SetRange(0,10)
1346   -# spin_Z .SetValue()
1347   - self.spin_mean = spin_mean
1348   -
1349   - spinicp = wx.FlexGridSizer(rows=3, cols=2, hgap=1, vgap=1)
1350   - spinicp.AddMany([(text_inter,0,wx.ALIGN_TOP|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_inter, 1),
1351   - (text_land,0,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_land, 1),
1352   - (text_mean,0, wx.ALIGN_BOTTOM|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_mean, 1)])
1353   -
1354   - spin = wx.FlexGridSizer(rows=3, cols=4, hgap=1, vgap=1)
1355   - spin.AddMany([(text_X, 0,wx.ALIGN_TOP|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_X, 1),(text_A, 0,wx.ALIGN_TOP|wx.EXPAND|wx.LEFT| wx.TOP|wx.BOTTOM,5),(spin_A, 1),
1356   - (text_Y, 0,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_Y, 1),(text_B, 0,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.LEFT| wx.TOP|wx.BOTTOM,5),(spin_B, 1),
1357   - (text_Z, 0,wx.ALIGN_BOTTOM|wx.EXPAND | wx.TOP|wx.BOTTOM,5),(spin_Z, 1),(text_G, 0,wx.ALIGN_BOTTOM|wx.EXPAND|wx.LEFT| wx.TOP|wx.BOTTOM,5),(spin_G, 1)])
1358   -
1359   - ok = wx.Button(self.panel, wx.ID_OK)
1360   - ok.Bind(wx.EVT_BUTTON, self.OK)
1361   - cancel = wx.Button(self.panel,wx.ID_CANCEL)
1362   - cancel.Bind(wx.EVT_BUTTON, self.CANCEL)
1363   -
1364   - checkb = wx.FlexGridSizer(rows=3, cols=1, hgap=1, vgap=1)
1365   - checkb.AddMany([(self.showObjICP , 0,wx.ALIGN_TOP|wx.EXPAND | wx.TOP|wx.BOTTOM,5),
1366   - (self.showObjHead , 0,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND | wx.TOP|wx.BOTTOM,5),
1367   - (self.showObjCloud , 0,wx.ALIGN_BOTTOM|wx.EXPAND | wx.TOP|wx.BOTTOM,5)])
1368   -
1369   - col1 = wx.FlexGridSizer(rows=3, cols=1, hgap=1, vgap=1)
1370   - col1.AddMany([(marker, 1),
1371   - (marker_load, 1),
1372   - (apply_ICP, 1)])
1373   -
1374   -# col2 = wx.FlexGridSizer(rows=1, cols=1, hgap=1, vgap=1)
1375   -# col2.AddMany([(param_ICP, 1)])
1376   -#
1377   - col4 = wx.FlexGridSizer(rows=2, cols=1, hgap=1, vgap=1)
1378   - col4.AddMany([(ok, 1),
1379   - (cancel, 1)])
1380   -
1381   - button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1382   - button_sizer.Add(col1,0,wx.EXPAND | wx.ALL,10)
1383   - button_sizer.Add(checkb,0,wx.EXPAND | wx.ALL,10)
1384   - button_sizer.Add(spinicp,0,wx.EXPAND | wx.ALL,10)
1385   - button_sizer.Add(spin,0,wx.EXPAND | wx.ALL,10)
1386   - button_sizer.Add(col4,0,wx.EXPAND | wx.ALL,10)
1387   - self.panel.SetSizer(button_sizer)
1388   - # OVERVIEW
1389   - # Merge all sizers and checkboxes
1390   - sizer = wx.BoxSizer(wx.VERTICAL)
1391   - sizer.Add(self.interactor, 5, wx.EXPAND,10)
1392   - sizer.Add(self.panel, 1,wx.ALIGN_CENTER,1)
1393   -
1394   - self.SetSizerAndFit(sizer)
1395   - self.Show()
1396   - sizer.Fit(self)
1397   -
1398   - def GetValue(self):
1399   - return self.actor_icp,self.icp_matrix
1400   - def OK(self,evt):
1401   - self.Close()
1402   - def CANCEL(self,evt):
1403   - self.Destroy()
1404   - def ShowObjectICP(self, evt):
1405   - objectbin = self.showObjICP.GetValue()
1406   - if objectbin == True:
1407   - self.actor_icp.SetVisibility(1)
1408   - self.interactor.Render()
1409   - if objectbin == False:
1410   - self.actor_icp.SetVisibility(0)
1411   - self.interactor.Render()
1412   -
1413   - def ShowObjectCloud(self, evt):
1414   - objectbin = self.showObjCloud.GetValue()
1415   - if objectbin == True:
1416   - self.actor_cloud.SetVisibility(1)
1417   - self.interactor.Render()
1418   - if objectbin == False:
1419   - self.actor_cloud.SetVisibility(0)
1420   - self.interactor.Render()
1421   -
1422   - def ShowObjectHead(self, evt):
1423   - objectbin = self.showObjHead.GetValue()
1424   - if objectbin == True:
1425   - self.actor.SetVisibility(1)
1426   - self.interactor.Render()
1427   - if objectbin == False:
1428   - self.actor.SetVisibility(0)
1429   - self.interactor.Render()
1430   -
1431   - def translate_rotate(self,evt):
1432   - self.transform = vtk.vtkTransform()
1433   - self.transform.Identity()
1434   - self.transform.PostMultiply()
1435   -
1436   -# try2=vtk.vtkImageChangeInformation.SetInput(self.cloud)
1437   -# self.cloud.vtk.vtkImageData.SetOrigin(self.actor_cloud.GetCenter())
1438   -# try1=vtk.vtkImageData(self.reader_cloud)
1439   -# try1.SetOrigin(self.actor_cloud.GetCenter())
1440   -
1441   - self.transform.Translate(self.spin_X.GetValue(), 0, 0)
1442   - self.transform.Translate(0,self.spin_Y.GetValue(), 0)
1443   - self.transform.Translate(0, 0, self.spin_Z.GetValue())
1444   -
1445   - #self.actor_cloud.SetOrientation(self.spin_A.GetValue(),xyz[1],xyz[2])
1446   - #transform.RotateWXYZ(self.spin_A.GetValue(),1,0,0)
1447   -
1448   -# transform.RotateX(self.spin_A.GetValue())
1449   -# transform.RotateY(self.spin_B.GetValue())
1450   -# transform.RotateZ(self.spin_G.GetValue())
1451   -# transform.RotateWXYZ(self.spin_B.GetValue(),xyz[0],1,xyz[2])
1452   -# transform.RotateWXYZ(self.spin_G.GetValue(),xyz[0],xyz[1],1)
1453   - self.actor_cloud.SetOrigin(self.actor_cloud.GetCenter())
1454   - self.actor_cloud.SetOrientation(0,0,0)
1455   - #self.transform.SetInput(self.actor_cloud)
1456   - self.transform.RotateX(self.spin_A.GetValue())
1457   - self.transform.RotateY(self.spin_B.GetValue())
1458   - self.transform.RotateZ(self.spin_G.GetValue())
1459   -
1460   -# self.transform.RotateX(self.spin_A.GetValue())
1461   -# self.transform.RotateY(self.spin_B.GetValue())
1462   -# self.transform.RotateZ(self.spin_G.GetValue())
1463   - self.transform.Update()
1464   -
1465   - self.transf = vtk.vtkTransformPolyDataFilter()
1466   -
1467   - self.transf.SetInput(self.cloud)
1468   - self.transf.SetTransform(self.transform)
1469   - self.transf.Update()
1470   - self.ren.RemoveActor(self.actor_cloud)
1471   - self.mapper_cloud = vtk.vtkPolyDataMapper()
1472   - self.mapper_cloud.SetInput(self.transf.GetOutput())
1473   - self.mapper_cloud.ScalarVisibilityOff()
1474   - self.mapper_cloud.ImmediateModeRenderingOn()
1475   - self.actor_cloud = vtk.vtkActor()
1476   - self.actor_cloud.SetMapper(self.mapper_cloud)
1477   - self.actor_cloud.GetProperty().SetColor(self.color_cloud)
1478   - self.actor_cloud.GetProperty().SetOpacity(self.opacity_cloud)
1479   - self.ren.AddActor(self.actor_cloud)
1480   -
1481   - #self.actor_cloud.SetOrigin(self.actor_cloud.GetCenter())
1482   - #self.actor_cloud.SetOrientation(0,0,0)
1483   - #self.actor_cloud.RotateX(self.spin_A.GetValue())
1484   - #self.actor_cloud.RotateY(self.spin_B.GetValue())
1485   - #self.actor_cloud.RotateZ(self.spin_G.GetValue())
1486   - self.interactor.Render()
1487   -
1488   - def OnLoadMarkers(self, evt):
1489   - print "Reading the points!"
1490   -
1491   - filepath = ShowLoadMarkersDialog()
1492   - text_file = open(filepath, "r")
1493   - #reading all lines and splitting into a float vector
1494   - while 1:
1495   - line = text_file.readline()
1496   - if not line:
1497   - break
1498   - try:
1499   - line1 = [float(s) for s in line.split()]
1500   - coord = float(line1[1] - 1.0), float(line1[0] - 1.0), float(line1[2] - 1.0)
1501   - colour = line1[3], line1[4], line1[5]
1502   - size = line1[6]
1503   -
1504   - CreateSphereMarkers(self,size,colour,coord)
1505   -
1506   - #sum 1 for each coordinate to matlab comprehension
1507   - #coord = coord[0] + 1.0, coord[1] + 1.0, coord[2] + 1.0
1508   - #line with coordinates and properties of a marker
1509   - line = coord[0] , coord[1] , coord[2] , colour[0], colour[1], colour[2], size
1510   - if self.flagpoint1 == 0:
1511   - self.list_coord = [line]
1512   - self.flagpoint1 = 1
1513   - else:
1514   - #adding actual line to a list of all markers already created
1515   - self.list_coord.append(line)
1516   - except:
1517   - InvalidTxt()
1518   - raise ValueError('Invalid Txt')
1519   -
1520   - def OnCalibrationMarkers(self, evt):
1521   - None
1522   -
1523   - def OnParamICP(self, evt):
1524   - None
1525   -
1526   - def OnApplyICP(self, evt):
1527   - self.showObjICP.SetValue(True)
1528   - self.icp_number_iterations= self.spin_inter.GetValue()
1529   - self.icp_number_landmarks= self.spin_land.GetValue()
1530   - self.icp_max_mean_distance = self.spin_mean.GetValue()
1531   - self.Transformation()
1532   - self.interactor.Render()
1533   - self.Show()
1534   -
1535   - def CreateCloudPointsSurface(self, filename_cloud):
1536   - # Reconstruct the surface from the cloud of points
1537   - self.reader_cloud = vtk.vtkPLYReader()
1538   -
1539   - self.reader_cloud.SetFileName(filename_cloud)
1540   - self.reader_cloud.Update()
1541   -
1542   - print "Creating cloud surface..."
1543   -
1544   - self.mapper_cloud = vtk.vtkPolyDataMapper()
1545   - self.mapper_cloud.SetInput(self.reader_cloud.GetOutput())
1546   - self.mapper_cloud.ScalarVisibilityOff()
1547   - self.mapper_cloud.ImmediateModeRenderingOn()
1548   -
1549   - self.actor_cloud = vtk.vtkActor()
1550   - self.actor_cloud.SetMapper(self.mapper_cloud)
1551   - self.actor_cloud.GetProperty().SetColor(self.color_cloud)
1552   - self.actor_cloud.GetProperty().SetOpacity(self.opacity_cloud)
1553   -
1554   - return self.reader_cloud.GetOutput()
1555   -
1556   - def Transformation(self):
1557   - # Apply IterativeClosestPoint Method
1558   -
1559   - #self.filename_cloud=self.ShowLoadSurfaceDialog()
1560   - try:
1561   - self.ren.RemoveActor(self.actor_icp)
1562   - self.interactor.Render()
1563   - except:
1564   - None
1565   - filename_head = self.head
1566   - #filename_cloud = sys.argv[2]
1567   - #head_init = self.CreateHeadSurface(filename_head)
1568   - #cloud = self.CreateCloudPointsSurface(self.filename_cloud)
1569   -
1570   - print "Applying ICP method..."
1571   - icp = vtk.vtkIterativeClosestPointTransform()
1572   - icp.SetSource(filename_head)
1573   - try:
1574   - icp.SetTarget(self.transf.GetOutput())
1575   - except:
1576   - icp.SetTarget(self.cloud)
1577   -
1578   - icp.StartByMatchingCentroidsOn()
1579   - icp.SetMaximumNumberOfIterations(self.icp_number_iterations)
1580   - icp.SetMaximumNumberOfLandmarks(self.icp_number_landmarks)
1581   - icp.SetMaximumMeanDistance(self.icp_max_mean_distance)
1582   - icp.GetLandmarkTransform().SetModeToRigidBody()
1583   - icp.SetMeanDistanceModeToRMS()
1584   - icp.Update()
1585   -
1586   - icp_transf = vtk.vtkTransformPolyDataFilter()
1587   - icp_transf.SetInput(filename_head)
1588   - icp_transf.SetTransform(icp)
1589   - icp_transf.Update()
1590   -
1591   - mapper_head_icp = vtk.vtkPolyDataMapper()
1592   - mapper_head_icp.SetInput(icp_transf.GetOutput())
1593   - mapper_head_icp.ScalarVisibilityOff()
1594   - mapper_head_icp.ImmediateModeRenderingOn()
1595   -
1596   - self.actor_icp = vtk.vtkActor()
1597   - self.actor_icp.SetMapper(mapper_head_icp)
1598   - self.actor_icp.GetProperty().SetColor(self.color_head_icp)
1599   - self.actor_icp.GetProperty().SetOpacity(self.opacity_head_icp)
1600   -
1601   - self.icp_matrix = vtk.vtkMatrix4x4()
1602   - self.icp_matrix = icp.GetMatrix()
1603   - print self.icp_matrix
1604   -
1605   - #Eixos para facilitar visualizacao -----------------
1606   -# axes = vtk.vtkAxesActor()
1607   -# axes.SetShaftTypeToCylinder()
1608   -# axes.SetXAxisLabelText("x")
1609   -# axes.SetYAxisLabelText("y")
1610   -# axes.SetZAxisLabelText("z")
1611   -# axes.SetTotalLength(25, 25, 25)
1612   - #---------------------------------------------------
1613   -
1614   -
1615   - #renderer.AddActor(axes)
1616   -
1617   - self.ren.AddActor(self.actor_icp)
1618   - #self.outlineF(icp_transf.GetOutput())
1619   - #self.ren.AddActor(self.outline)
1620   - self.ren.SetBackground(0, 0, 0)
1621   - self.ren.ResetCamera()
1622   -
1623   - def LoadData(self):
1624   - coil_reference = vtk.vtkOBJReader()
1625   - #coil_reference.SetFileName(os.path.realpath(os.path.join('..',
1626   - # 'models',
1627   - # 'coil_cti_2_scale10.obj')))
1628   -
1629   - coil_reference.SetFileName('C:\Users\Administrator\Dropbox\Biomag\Renan\coil\coil_cti_2_scale10.obj')
1630   - coilMapper = vtk.vtkPolyDataMapper()
1631   - coilMapper.SetInputConnection(coil_reference.GetOutputPort())
1632   - self.coilActor = vtk.vtkActor()
1633   - #self.coilActor.Scale(10.0, 10.0, 10.0)
1634   - self.coilActor.SetMapper(coilMapper)
1635   -
1636   - axes = vtk.vtkAxesActor()
1637   - axes.SetShaftTypeToCylinder()
1638   - axes.SetXAxisLabelText("x")
1639   - axes.SetYAxisLabelText("y")
1640   - axes.SetZAxisLabelText("z")
1641   - axes.SetTotalLength(50.0, 50.0, 50.0)
1642   -
1643   - self.ren.AddActor(self.coilActor)
1644   - self.ren.AddActor(axes)
1645   -
1646   - def LoadActorDLG(self, pubsub_evt):
1647   - self.actor = pubsub_evt.data[0]
1648   - #self.head=actor
1649   - self.head=pubsub_evt.data[1]
1650   -
1651   - self.outlineF(self.head)
1652   - self.ren.AddActor(self.outline)
1653   -
1654   - self.filename_cloud=self.ShowLoadSurfaceDialog()
1655   - self.cloud = self.CreateCloudPointsSurface(self.filename_cloud)
1656   - print self.cloud
1657   -
1658   - self.outlineF(self.cloud)
1659   - self.ren.AddActor(self.outline)
1660   -
1661   - self.ren.AddActor(self.actor)
1662   - self.ren.AddActor(self.actor_cloud)
1663   -
1664   - axes = vtk.vtkAxesActor()
1665   - axes.SetShaftTypeToCylinder()
1666   - axes.SetXAxisLabelText("x")
1667   - axes.SetYAxisLabelText("y")
1668   - axes.SetZAxisLabelText("z")
1669   - axes.SetTotalLength(25, 25, 25)
1670   - self.ren.AddActor(axes)
1671   -
1672   - self.ren.ResetCamera()
1673   - #self.ren.ResetCameraClippingRange()
1674   -
1675   - #self.ShowOrientationCube()
1676   - self.interactor.Render()
1677   -
1678   - def LoadVolumeDLG(self, pubsub_evt):
1679   - self.raycasting_volume = True
1680   - #self._to_show_ball += 1
1681   - #print "to show ball", self._to_show_ball
1682   -
1683   - volume = pubsub_evt.data[0]
1684   - colour = pubsub_evt.data[1]
1685   - self.light = self.ren.GetLights().GetNextItem()
1686   -
1687   - self.ren.AddVolume(volume)
1688   -
1689   - self.ren.SetBackground(colour)
1690   -
1691   - self.interactor.Render()
1692   -
1693   - def outlineF(self,Actor):
1694   - #filtro outline
1695   - self.outline = vtk.vtkActor()
1696   - outlineData = vtk.vtkOutlineFilter()
1697   - outlineData.SetInput(Actor)
1698   - outlineData.Update()
1699   -
1700   - mapoutline = vtk.vtkPolyDataMapper()
1701   - mapoutline.SetInputConnection(outlineData.GetOutputPort())
1702   -
1703   - self.outline.SetMapper(mapoutline)
1704   - self.outline.GetProperty().SetColor(0.0, 0.0, 1.0)
1705   -
1706   -def CreateSphereMarkers(self,ballsize,ballcolour,coord):
1707   -
1708   - x, y, z = bases.FlipX(coord)
1709   -
1710   - ball_ref = vtk.vtkSphereSource()
1711   - ball_ref.SetRadius(ballsize)
1712   - ball_ref.SetCenter(x, y, z)
1713   -
1714   - mapper = vtk.vtkPolyDataMapper()
1715   - mapper.SetInput(ball_ref.GetOutput())
1716   -
1717   - prop = vtk.vtkProperty()
1718   - prop.SetColor(ballcolour)
1719   -
1720   - #adding a new actor for the present ball
1721   - self.staticballs.append(vtk.vtkActor())
1722   -
1723   - self.staticballs[self.ball_id].SetMapper(mapper)
1724   - self.staticballs[self.ball_id].SetProperty(prop)
1725   -
1726   - self.ren.AddActor(self.staticballs[self.ball_id])
1727   - self.ball_id = self.ball_id + 1
1728   - self.interactor.Render()
1729   -
1730   -
1731   -
1732   - self.PostCreate(self.pre)
1733   -# # # class ObjectCalibration(wx.Window):
1734   -# # # def __init__(self, parent=None, ID=-1, title="Object Calibration", size=wx.DefaultSize,
1735   -# # # pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE,
1736   -# # # useMetal=False,nav_prop=None):
1737   -# # # self.correg = None
1738   -# # # self.nav_prop = nav_prop
1739   -# # # self.staticballs = []
1740   -# # # self.ball_id = 0
1741   -# # # self.ball_centers = []
1742   -# # # self.to_translate = 0
1743   -# # # self.flagpoint1 = 0
1744   -# # # self.init_angle_plh = None
1745   -# # #
1746   -# # # # Instead of calling wx.Dialog.__init__ we precreate the dialog
1747   -# # # # so we can set an extra style that must be set before
1748   -# # # # creation, and then we create the GUI object using the Create
1749   -# # # # method.
1750   -# # #
1751   -# # #
1752   -# # # self.pre = wx.Frame(parent, -1, title)
1753   -# # # self.pre.SetPosition(pos)
1754   -# # # self.pre.SetSize(wx.Size(200,200))
1755   -# # # self.pre.SetBackgroundColour('LIGHT GRAY')
1756   -# # # self.pre.CenterOnScreen()
1757   -# # # self.pre.Show()
1758   -# # # # This next step is the most important, it turns this Python
1759   -# # # # object into the real wrapper of the dialog (instead of pre)
1760   -# # # # as far as the wxPython extension is concerned.
1761   -# # # self.PostCreate(self.pre)
1762   -# # #
1763   -# # #
1764   -# # # # This extra style can be set after the UI object has been created.
1765   -# # # if 'wxMac' in wx.PlatformInfo and useMetal:
1766   -# # # self.SetExtraStyle(wx.DIALOG_EX_METAL)
1767   -# # #
1768   -# # # self.draw_gui()
1769   -# # # self.LoadData()
1770   -# # #
1771   -# # # # LINE 1: Janela
1772   -# # #
1773   -# # # def draw_gui(self):
1774   -# # # #style = vtk.vtkInteractorStyleTrackballActor()
1775   -# # # self.panel=wx.Panel(self)
1776   -# # # self.interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize())
1777   -# # # #self.interactor.SetInteractorStyle(style)
1778   -# # # self.interactor.Enable(1)
1779   -# # # self.ren = vtk.vtkRenderer()
1780   -# # # self.interactor.GetRenderWindow().AddRenderer(self.ren)
1781   -# # #
1782   -# # # # LINE 2: Botoes
1783   -# # #
1784   -# # # marker = wx.Button(self.panel, -1, "Create Marker",size = wx.Size(85,23))
1785   -# # # marker.Bind(wx.EVT_BUTTON, self.OnCalibrationMarkers)
1786   -# # #
1787   -# # # marker_load = wx.Button(self.panel, -1, "Load Marker",size = wx.Size(85,23))
1788   -# # # marker_load.Bind(wx.EVT_BUTTON, self.OnLoadMarkers)
1789   -# # #
1790   -# # #
1791   -# # # #Change X,Y,Z and Alfa,Beta,Gama
1792   -# # # text_X = wx.StaticText(self.panel, -1, _("X:"))
1793   -# # # spin_X = wx.SpinCtrl(self.panel, -1, "X", size = wx.Size(47,23))
1794   -# # # spin_X .SetRange(1,100)
1795   -# # # spin_X .SetValue(0)
1796   -# # # self.spin_X = spin_X
1797   -# # #
1798   -# # # text_Y = wx.StaticText(self.panel, -1, _("Y:"))
1799   -# # # spin_Y = wx.SpinCtrl(self.panel, -1, "Y", size = wx.Size(47,23))
1800   -# # # spin_Y .SetRange(1,100)
1801   -# # # spin_Y .SetValue(0)
1802   -# # # self.spin_Y = spin_Y
1803   -# # #
1804   -# # # text_Z = wx.StaticText(self.panel, -1, _("Z:"))
1805   -# # # spin_Z = wx.SpinCtrl(self.panel, -1, "Z", size = wx.Size(47,23))
1806   -# # # spin_Z .SetRange(1,100)
1807   -# # # spin_Z .SetValue(0)
1808   -# # # self.spin_Z = spin_Z
1809   -# # #
1810   -# # # text_A = wx.StaticText(self.panel, -1, _("Alfa:"))
1811   -# # # spin_A = wx.SpinCtrl(self.panel, -1, "Alfa", size = wx.Size(47,23))
1812   -# # # spin_A .SetRange(1,100)
1813   -# # # spin_A .SetValue(0)
1814   -# # # self.spin_A = spin_A
1815   -# # #
1816   -# # # text_B = wx.StaticText(self.panel, -1, _("Beta:"))
1817   -# # # spin_B = wx.SpinCtrl(self.panel, -1, "Beta", size = wx.Size(47,23))
1818   -# # # spin_B .SetRange(1,100)
1819   -# # # spin_B .SetValue(0)
1820   -# # # self.spin_B = spin_B
1821   -# # #
1822   -# # # text_G = wx.StaticText(self.panel, -1, _("Gama:"))
1823   -# # # spin_G = wx.SpinCtrl(self.panel, -1, "Gama", size = wx.Size(47,23))
1824   -# # # spin_G .SetRange(1,100)
1825   -# # # spin_G .SetValue(0)
1826   -# # # self.spin_G = spin_G
1827   -# # #
1828   -# # # spin = wx.FlexGridSizer(rows=3, cols=4, hgap=5, vgap=5)
1829   -# # # spin.AddMany([(text_X, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_X, 1, wx.RIGHT|wx.LEFT),(text_A, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_A, 1, wx.RIGHT),
1830   -# # # (text_Y, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_Y, 1, wx.RIGHT|wx.LEFT),(text_B, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_B, 1, wx.RIGHT),
1831   -# # # (text_Z, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_Z, 1, wx.RIGHT|wx.LEFT),(text_G, 1,wx.LEFT|wx.ALIGN_CENTER_VERTICAL),(spin_G, 1, wx.RIGHT)])
1832   -# # #
1833   -# # # ok = wx.Button(self.panel, wx.ID_OK)
1834   -# # # ok.Bind(wx.EVT_BUTTON, self.OK)
1835   -# # # cancel = wx.Button(self.panel, wx.ID_CANCEL)
1836   -# # #
1837   -# # # col1 = wx.FlexGridSizer(rows=3, cols=1, hgap=5, vgap=5)
1838   -# # # col1.AddMany([(marker, 0, wx.RIGHT|wx.LEFT),
1839   -# # # (marker_load, 0, wx.RIGHT|wx.LEFT)])
1840   -# # #
1841   -# # # col4 = wx.FlexGridSizer(rows=2, cols=1, hgap=5, vgap=5)
1842   -# # # col4.AddMany([(ok, 0, wx.RIGHT|wx.LEFT),
1843   -# # # (cancel, 0, wx.RIGHT|wx.LEFT|wx.BOTTOM)])
1844   -# # #
1845   -# # # button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1846   -# # # button_sizer.Add(col1,0,wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,10)
1847   -# # # button_sizer.Add(spin,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,10)
1848   -# # # button_sizer.Add(col4,0,wx.LEFT|wx.ALIGN_CENTER_VERTICAL,10)
1849   -# # # self.panel.SetSizer(button_sizer)
1850   -# # # # OVERVIEW
1851   -# # # # Merge all sizers and checkboxes
1852   -# # # sizer = wx.BoxSizer(wx.VERTICAL)
1853   -# # # sizer.Add(self.interactor, 3, wx.EXPAND)
1854   -# # # sizer.Add(self.panel, 1,wx.ALIGN_CENTER_HORIZONTAL|wx.TOP|wx.BOTTOM|wx.RIGHT|wx.LEFT, 20)
1855   -# # #
1856   -# # # self.SetSizer(sizer)
1857   -# # # sizer.Fit(self)
1858   -# # #
1859   -# # # def OK(self,evt):
1860   -# # # Publisher.sendMessage('Load Param Obj')
1861   -# # # self.Close()
1862   -# # #
1863   -# # # def OnLoadMarkers(self, evt):
1864   -# # # print "Reading the points!"
1865   -# # #
1866   -# # # filepath = ShowLoadMarkersDialog()
1867   -# # # text_file = open(filepath, "r")
1868   -# # # #reading all lines and splitting into a float vector
1869   -# # # while 1:
1870   -# # # line = text_file.readline()
1871   -# # # if not line:
1872   -# # # break
1873   -# # # try:
1874   -# # # line1 = [float(s) for s in line.split()]
1875   -# # # coord = float(line1[1] - 1.0), float(line1[0] - 1.0), float(line1[2] - 1.0)
1876   -# # # colour = line1[3], line1[4], line1[5]
1877   -# # # size = line1[6]
1878   -# # #
1879   -# # # CreateSphereMarkers(self,size,colour,coord)
1880   -# # #
1881   -# # # #sum 1 for each coordinate to matlab comprehension
1882   -# # # #coord = coord[0] + 1.0, coord[1] + 1.0, coord[2] + 1.0
1883   -# # # #line with coordinates and properties of a marker
1884   -# # # line = coord[0] , coord[1] , coord[2] , colour[0], colour[1], colour[2], size
1885   -# # # if self.flagpoint1 == 0:
1886   -# # # self.list_coord = [line]
1887   -# # # self.flagpoint1 = 1
1888   -# # # else:
1889   -# # # #adding actual line to a list of all markers already created
1890   -# # # self.list_coord.append(line)
1891   -# # # except:
1892   -# # # InvalidTxt()
1893   -# # # raise ValueError('Invalid Txt')
1894   -# # # def OnCalibrationMarkers(self, evt):
1895   -# # # import data.coordinates as co
1896   -# # # from numpy import matrix
1897   -# # # Minv = self.nav_prop[0][0]
1898   -# # # N = self.nav_prop[0][1]
1899   -# # # q1 = self.nav_prop[0][2]
1900   -# # # q2 = self.nav_prop[0][3]
1901   -# # # nav_id = self.nav_prop[1]
1902   -# # # tracker_init = self.nav_prop[1][0]
1903   -# # # tracker = self.nav_prop[1][1]
1904   -# # # tracker_mode = self.nav_prop[1][2]
1905   -# # #
1906   -# # # trck = co.Coordinates(tracker_init, tracker, tracker_mode).Returns()
1907   -# # # tracker = matrix([[trck[0]], [trck[1]], [trck[2]]])
1908   -# # # self.init_angle_plh = trck[3], trck[4], trck[5]
1909   -# # # img = q1 + (Minv*N)*(tracker - q2)
1910   -# # # coord = float(img[0]), float(img[1]), float(img[2])
1911   -# # # x, y, z = bases.FlipX(coord)
1912   -# # #
1913   -# # # if not self.ball_centers:
1914   -# # # self.to_translate = -x, -y, -z
1915   -# # #
1916   -# # # x = x + self.to_translate[0]
1917   -# # # y = y + self.to_translate[1]
1918   -# # # z = z + self.to_translate[2]
1919   -# # #
1920   -# # # ball_ref = vtk.vtkSphereSource()
1921   -# # # ball_ref.SetRadius(4)
1922   -# # # ball_ref.SetCenter(x, y, z)
1923   -# # #
1924   -# # # self.ball_centers.append((x, y, z))
1925   -# # #
1926   -# # # mapper = vtk.vtkPolyDataMapper()
1927   -# # # mapper.SetInput(ball_ref.GetOutput())
1928   -# # #
1929   -# # # prop = vtk.vtkProperty()
1930   -# # # prop.SetColor(0,1, 1)
1931   -# # #
1932   -# # # #adding a new actor for the present ball
1933   -# # # self.staticballs.append(vtk.vtkActor())
1934   -# # #
1935   -# # # self.staticballs[self.ball_id].SetMapper(mapper)
1936   -# # # self.staticballs[self.ball_id].SetProperty(prop)
1937   -# # #
1938   -# # # self.ren.AddActor(self.staticballs[self.ball_id])
1939   -# # # self.ball_id += 1
1940   -# # #
1941   -# # # self.interactor.Render()
1942   -# # #
1943   -# # #
1944   -# # # def LoadData(self):
1945   -# # # coil_reference = vtk.vtkOBJReader()
1946   -# # # #coil_reference.SetFileName(os.path.realpath(os.path.join('..',
1947   -# # # # 'models',
1948   -# # # # 'coil_cti_2_scale10.obj')))
1949   -# # # coil_reference.SetFileName('C:\Users\Administrator\Dropbox\Biomag\Renan\coil\coil_cti_2_scale10.obj')
1950   -# # # # coil_reference.SetFileName('C:\Users\Renan\Dropbox\Biomag\Renan\coil\coil_cti_2_scale10.obj')
1951   -# # # coilMapper = vtk.vtkPolyDataMapper()
1952   -# # # coilMapper.SetInputConnection(coil_reference.GetOutputPort())
1953   -# # # self.coilActor = vtk.vtkActor()
1954   -# # # #self.coilActor.Scale(10.0, 10.0, 10.0)
1955   -# # # self.coilActor.SetMapper(coilMapper)
1956   -# # #
1957   -# # # axes = vtk.vtkAxesActor()
1958   -# # # axes.SetShaftTypeToCylinder()
1959   -# # # axes.SetXAxisLabelText("x")
1960   -# # # axes.SetYAxisLabelText("y")
1961   -# # # axes.SetZAxisLabelText("z")
1962   -# # # axes.SetTotalLength(50.0, 50.0, 50.0)
1963   -# # #
1964   -# # # self.ren.AddActor(self.coilActor)
1965   -# # # self.ren.AddActor(axes)
1966   -class ObjectCalibration(wx.Dialog):
1967   - def __init__(self, parent=None, ID=-1, title="Calibration Dialog", size=wx.DefaultSize,
1968   - pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE,
1969   - useMetal=False, nav_prop=None):
1970   -
1971   - self.nav_prop = nav_prop
1972   - self.correg = None
1973   - self.staticballs = []
1974   - self.ball_id = 0
1975   - self.ball_centers = []
1976   - self.to_translate = 0
1977   - self.init_angle_plh = None
1978   -
1979   - # Instead of calling wx.Dialog.__init__ we precreate the dialog
1980   - # so we can set an extra style that must be set before
1981   - # creation, and then we create the GUI object using the Create
1982   - # method.
1983   - pre = wx.PreDialog()
1984   - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
1985   - pre.Create(parent, ID, title, pos, (700,500), style)
1986   -
1987   -
1988   -class SurfaceDialog(wx.Dialog):
1989   - '''
1990   - This dialog is only shown when the mask whose surface will be generate was
1991   - edited. So far, the only options available are the choice of method to
1992   - generate the surface, Binary or `Context aware smoothing', and options from
1993   - `Context aware smoothing'
1994   - '''
1995   - def __init__(self):
1996   - wx.Dialog.__init__(self, None, -1, _('Surface generation options'))
1997   - self._build_widgets()
1998   - self.CenterOnScreen()
1999   -
2000   - def _build_widgets(self):
2001   - btn_ok = wx.Button(self, wx.ID_OK)
2002   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
2003   - btn_sizer = wx.StdDialogButtonSizer()
2004   - btn_sizer.AddButton(btn_ok)
2005   - btn_sizer.AddButton(btn_cancel)
2006   - btn_sizer.Realize()
2007   -
2008   - self.ca = SurfaceMethodPanel(self, -1, True)
2009   -
2010   - self.main_sizer = wx.BoxSizer(wx.VERTICAL)
2011   - self.main_sizer.Add(self.ca, 0, wx.EXPAND|wx.ALL, 5)
2012   - self.main_sizer.Add(btn_sizer, 0, wx.EXPAND | wx.ALL, 5)
2013   -
2014   - self.SetSizer(self.main_sizer)
2015   - self.Fit()
2016   -
2017   - def GetOptions(self):
2018   - return self.ca.GetOptions()
2019   -
2020   - def GetAlgorithmSelected(self):
2021   - return self.ca.GetAlgorithmSelected()
2022   -
2023   -
2024   -####################### New surface creation dialog ###########################
2025   -class SurfaceCreationDialog(wx.Dialog):
2026   - def __init__(self, parent=None, ID=-1, title=_(u"Surface creation"),
2027   - size=wx.DefaultSize, pos=wx.DefaultPosition,
2028   - style=wx.DEFAULT_DIALOG_STYLE, useMetal=False,
2029   - mask_edited=False):
2030   -
2031   - # Instead of calling wx.Dialog.__init__ we precreate the dialog
2032   - # so we can set an extra style that must be set before
2033   - # creation, and then we create the GUI object using the Create
2034   - # method.
2035   - pre = wx.PreDialog()
2036   - pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
2037   - pre.Create(parent, ID, title, pos, (500,300), style)
2038   -
2039   - # This extra style can be set after the UI object has been created.
2040   - if 'wxMac' in wx.PlatformInfo and useMetal:
2041   - self.SetExtraStyle(wx.DIALOG_EX_METAL)
2042   -
2043   - # This next step is the most important, it turns this Python
2044   - # object into the real wrapper of the dialog (instead of pre)
2045   - # as far as the wxPython extension is concerned.
2046   - self.PostCreate(pre)
2047   -
2048   - self.CenterOnScreen()
2049   -
2050   - # It's necessary to create a staticbox before is children widgets
2051   - # because otherwise in MacOSX it'll not be possible to use the mouse in
2052   - # static's children widgets.
2053   - sb_nsd = wx.StaticBox(self, -1, _('Surface creation options'))
2054   - self.nsd = SurfaceCreationOptionsPanel(self, -1)
2055   - self.nsd.Bind(EVT_MASK_SET, self.OnSetMask)
2056   - surface_options_sizer = wx.StaticBoxSizer(sb_nsd, wx.VERTICAL)
2057   - surface_options_sizer.Add(self.nsd, 1, wx.EXPAND|wx.ALL, 5)
2058   -
2059   - sb_ca = wx.StaticBox(self, -1, _('Surface creation method'))
2060   - self.ca = SurfaceMethodPanel(self, -1, mask_edited)
2061   - surface_method_sizer = wx.StaticBoxSizer(sb_ca, wx.VERTICAL)
2062   - surface_method_sizer.Add(self.ca, 1, wx.EXPAND|wx.ALL, 5)
2063   -
2064   - btn_ok = wx.Button(self, wx.ID_OK)
2065   - btn_ok.SetDefault()
2066   - btn_cancel = wx.Button(self, wx.ID_CANCEL)
2067   -
2068   - btnsizer = wx.StdDialogButtonSizer()
2069   - btnsizer.AddButton(btn_ok)
2070   - btnsizer.AddButton(btn_cancel)
2071   - btnsizer.Realize()
2072   -
2073   - sizer_panels = wx.BoxSizer(wx.HORIZONTAL)
2074   - sizer_panels.Add(surface_options_sizer, 0, wx.EXPAND|wx.ALL, 5)
2075   - sizer_panels.Add(surface_method_sizer, 0, wx.EXPAND|wx.ALL, 5)
2076   -
2077   - sizer = wx.BoxSizer(wx.VERTICAL)
2078   - sizer.Add(sizer_panels, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
2079   - sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
2080   -
2081   - self.SetSizer(sizer)
2082   - sizer.Fit(self)
2083   -
2084   - def OnSetMask(self, evt):
2085   - mask = proj.Project().mask_dict[evt.mask_index]
2086   - self.ca.mask_edited = mask.was_edited
2087   - self.ca.ReloadMethodsOptions()
2088   -
2089   - def GetValue(self):
2090   - return {"method": self.ca.GetValue(),
2091   - "options": self.nsd.GetValue()}
2092   -
2093   -class SurfaceCreationOptionsPanel(wx.Panel):
2094   - def __init__(self, parent, ID=-1):
2095   - import constants as const
2096   - import data.surface as surface
2097   - import project as prj
2098   -
2099   - wx.Panel.__init__(self, parent, ID)
2100   -
2101   - # LINE 1: Surface name
2102   - label_surface = wx.StaticText(self, -1, _("New surface name:"))
2103   -
2104   - default_name = const.SURFACE_NAME_PATTERN %(surface.Surface.general_index+2)
2105   - text = wx.TextCtrl(self, -1, "", size=(80,-1))
2106   - text.SetHelpText(_("Name the surface to be created"))
2107   - text.SetValue(default_name)
2108   - self.text = text
2109   -
2110   - # LINE 2: Mask of reference
2111   -
2112   - # Informative label
2113   - label_mask = wx.StaticText(self, -1, _("Mask of reference:"))
2114   -
2115   - #Retrieve existing masks
2116   - project = prj.Project()
2117   - index_list = project.mask_dict.keys()
2118   - index_list.sort()
2119   - self.mask_list = [project.mask_dict[index].name for index in index_list]
2120   -
2121   - # Mask selection combo
2122   - combo_mask = wx.ComboBox(self, -1, "", choices= self.mask_list,
2123   - style=wx.CB_DROPDOWN|wx.CB_READONLY)
2124   - combo_mask.SetSelection(len(self.mask_list)-1)
2125   - combo_mask.Bind(wx.EVT_COMBOBOX, self.OnSetMask)
2126   - if sys.platform != 'win32':
2127   - combo_mask.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
2128   - self.combo_mask = combo_mask
2129   -
2130   - # LINE 3: Surface quality
2131   - label_quality = wx.StaticText(self, -1, _("Surface quality:"))
2132   -
2133   - choices = const.SURFACE_QUALITY_LIST
2134   - style = wx.CB_DROPDOWN|wx.CB_READONLY
2135   - combo_quality = wx.ComboBox(self, -1, "",
2136   - choices= choices,
2137   - style=style)
2138   - combo_quality.SetSelection(3)
2139   - if sys.platform != 'win32':
2140   - combo_quality.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
2141   - self.combo_quality = combo_quality
2142   -
2143   - # OVERVIEW
2144   - # Sizer that joins content above
2145   - flag_link = wx.EXPAND|wx.GROW|wx.ALL
2146   - flag_button = wx.ALL | wx.EXPAND| wx.GROW
2147   -
2148   - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=10, vgap=5)
2149   - fixed_sizer.AddGrowableCol(0, 1)
2150   - fixed_sizer.AddMany([ (label_surface, 1, flag_link, 0),
2151   - (text, 1, flag_button, 0),
2152   - (label_mask, 1, flag_link, 0),
2153   - (combo_mask, 0, flag_button, 0),
2154   - (label_quality, 1, flag_link, 0),
2155   - (combo_quality, 0, flag_button, 0)])
2156   -
2157   -
2158   - # LINES 4 and 5: Checkboxes
2159   - check_box_holes = wx.CheckBox(self, -1, _("Fill holes"))
2160   - check_box_holes.SetValue(True)
2161   - self.check_box_holes = check_box_holes
2162   - check_box_largest = wx.CheckBox(self, -1, _("Keep largest region"))
2163   - self.check_box_largest = check_box_largest
2164   -
2165   - # OVERVIEW
2166   - # Merge all sizers and checkboxes
2167   - sizer = wx.BoxSizer(wx.VERTICAL)
2168   - sizer.Add(fixed_sizer, 0, wx.TOP|wx.RIGHT|wx.LEFT|wx.GROW|wx.EXPAND, 5)
2169   - sizer.Add(check_box_holes, 0, wx.RIGHT|wx.LEFT, 5)
2170   - sizer.Add(check_box_largest, 0, wx.RIGHT|wx.LEFT, 5)
2171   -
2172   - self.SetSizer(sizer)
2173   - sizer.Fit(self)
2174   -
2175   - def OnSetMask(self, evt):
2176   - new_evt = MaskEvent(myEVT_MASK_SET, -1, self.combo_mask.GetSelection())
2177   - self.GetEventHandler().ProcessEvent(new_evt)
2178   -
2179   - def GetValue(self):
2180   - mask_index = self.combo_mask.GetSelection()
2181   - surface_name = self.text.GetValue()
2182   - quality = const.SURFACE_QUALITY_LIST[self.combo_quality.GetSelection()]
2183   - fill_holes = self.check_box_holes.GetValue()
2184   - keep_largest = self.check_box_largest.GetValue()
2185   - return {"index": mask_index,
2186   - "name": surface_name,
2187   - "quality": quality,
2188   - "fill": fill_holes,
2189   - "keep_largest": keep_largest,
2190   - "overwrite": False}
2191   -
2192   -
2193   -class CAOptions(wx.Panel):
2194   - '''
2195   - Options related to Context aware algorithm:
2196   - Angle: The min angle to a vertex to be considered a staircase vertex;
2197   - Max distance: The max distance a normal vertex must be to calculate its
2198   - weighting;
2199   - Min Weighting: The min weight a vertex must have;
2200   - Steps: The number of iterations the smoothing algorithm have to do.
2201   - '''
2202   - def __init__(self, parent):
2203   - wx.Panel.__init__(self, parent, -1)
2204   - self._build_widgets()
2205   -
2206   - def _build_widgets(self):
2207   - sb = wx.StaticBox(self, -1, _('Options'))
2208   - self.angle = floatspin.FloatSpin(self, -1, value=0.7, min_val=0.0,
2209   - max_val=1.0, increment=0.1,
2210   - digits=1)
2211   -
2212   - self.max_distance = floatspin.FloatSpin(self, -1, value=3.0, min_val=0.0,
2213   - max_val=100.0, increment=0.1,
2214   - digits=2)
2215   -
2216   - self.min_weight = floatspin.FloatSpin(self, -1, value=0.2, min_val=0.0,
2217   - max_val=1.0, increment=0.1,
2218   - digits=1)
2219   -
2220   - self.steps = wx.SpinCtrl(self, -1, value='10', min=1, max=100)
2221   -
2222   - layout_sizer = wx.FlexGridSizer(rows=4, cols=2, hgap=5, vgap=5)
2223   - layout_sizer.Add(wx.StaticText(self, -1, _(u'Angle:')), 0, wx.EXPAND)
2224   - layout_sizer.Add(self.angle, 0, wx.EXPAND)
2225   - layout_sizer.Add(wx.StaticText(self, -1, _(u'Max. distance:')), 0, wx.EXPAND)
2226   - layout_sizer.Add(self.max_distance, 0, wx.EXPAND)
2227   - layout_sizer.Add(wx.StaticText(self, -1, _(u'Min. weight:')), 0, wx.EXPAND)
2228   - layout_sizer.Add(self.min_weight, 0, wx.EXPAND)
2229   - layout_sizer.Add(wx.StaticText(self, -1, _(u'N. steps:')), 0, wx.EXPAND)
2230   - layout_sizer.Add(self.steps, 0, wx.EXPAND)
2231   -
2232   - self.main_sizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
2233   - self.main_sizer.Add(layout_sizer, 0, wx.EXPAND | wx.ALL, 5)
2234   - self.SetSizer(self.main_sizer)
2235   -
2236   -class SurfaceMethodPanel(wx.Panel):
2237   - '''
2238   - This dialog is only shown when the mask whose surface will be generate was
2239   - edited. So far, the only options available are the choice of method to
2240   - generate the surface, Binary or `Context aware smoothing', and options from
2241   - `Context aware smoothing'
2242   - '''
2243   - def __init__(self, parent, id, mask_edited=False):
2244   - wx.Panel.__init__(self, parent, id)
2245   -
2246   - self.mask_edited = mask_edited
2247   - self.alg_types = {_(u'Default'): 'Default',
2248   - _(u'Context aware smoothing'): 'ca_smoothing',
2249   - _(u'Binary'): 'Binary'}
2250   - self.edited_imp = [_(u'Default'), ]
2251   -
2252   - self._build_widgets()
2253   - self._bind_wx()
2254   -
2255   - def _build_widgets(self):
2256   - self.ca_options = CAOptions(self)
2257   -
2258   - self.cb_types = wx.ComboBox(self, -1, _(u'Default'),
2259   - choices=[i for i in sorted(self.alg_types)
2260   - if not (self.mask_edited and i in self.edited_imp)],
2261   - style=wx.CB_READONLY)
2262   - w, h = self.cb_types.GetSizeTuple()
2263   -
2264   - icon = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_MESSAGE_BOX,
2265   - (h * 0.8, h * 0.8))
2266   - self.bmp = wx.StaticBitmap(self, -1, icon)
2267   - self.bmp.SetToolTipString(_("It is not possible to use the Default method because the mask was edited."))
2268   -
2269   - self.method_sizer = wx.BoxSizer(wx.HORIZONTAL)
2270   - self.method_sizer.Add(wx.StaticText(self, -1, _(u'Method:')), 0,
2271   - wx.EXPAND | wx.ALL, 5)
2272   - self.method_sizer.Add(self.cb_types, 1, wx.EXPAND)
2273   - self.method_sizer.Add(self.bmp, 0, wx.EXPAND|wx.ALL, 5)
2274   -
2275   - self.main_sizer = wx.BoxSizer(wx.VERTICAL)
2276   - self.main_sizer.Add(self.method_sizer, 0, wx.EXPAND | wx.ALL, 5)
2277   - self.main_sizer.Add(self.ca_options, 0, wx.EXPAND | wx.ALL, 5)
2278   -
2279   - self.SetSizer(self.main_sizer)
2280   - self.Layout()
2281   - self.Fit()
2282   -
2283   - if self.mask_edited:
2284   - self.cb_types.SetValue(_(u'Context aware smoothing'))
2285   - self.ca_options.Enable()
2286   - self.method_sizer.Show(self.bmp)
2287   - else:
2288   - self.ca_options.Disable()
2289   - self.method_sizer.Hide(self.bmp)
2290   -
2291   - def _bind_wx(self):
2292   - self.cb_types.Bind(wx.EVT_COMBOBOX, self._set_cb_types)
2293   -
2294   - def _set_cb_types(self, evt):
2295   - if self.alg_types[evt.GetString()] == 'ca_smoothing':
2296   - self.ca_options.Enable()
2297   - else:
2298   - self.ca_options.Disable()
2299   - evt.Skip()
2300   -
2301   - def GetAlgorithmSelected(self):
2302   - try:
2303   - return self.alg_types[self.cb_types.GetValue()]
2304   - except KeyError:
2305   - return self.alg_types[0]
2306   -
2307   - def GetOptions(self):
2308   - if self.GetAlgorithmSelected() == 'ca_smoothing':
2309   - options = {'angle': self.ca_options.angle.GetValue(),
2310   - 'max distance': self.ca_options.max_distance.GetValue(),
2311   - 'min weight': self.ca_options.min_weight.GetValue(),
2312   - 'steps': self.ca_options.steps.GetValue()}
2313   - else:
2314   - options = {}
2315   - return options
2316   -
2317   - def GetValue(self):
2318   - algorithm = self.GetAlgorithmSelected()
2319   - options = self.GetOptions()
2320   -
2321   - return {"algorithm": algorithm,
2322   - "options": options}
2323   -
2324   - def ReloadMethodsOptions(self):
2325   - self.cb_types.Clear()
2326   - self.cb_types.AppendItems([i for i in sorted(self.alg_types)
2327   - if not (self.mask_edited and i in self.edited_imp)])
2328   - if self.mask_edited:
2329   - self.cb_types.SetValue(_(u'Context aware smoothing'))
2330   - self.ca_options.Enable()
2331   - self.method_sizer.Show(self.bmp)
2332   - else:
2333   - self.cb_types.SetValue(_(u'Default'))
2334   - self.ca_options.Disable()
2335   - self.method_sizer.Hide(self.bmp)
2336   -
2337   - self.method_sizer.Layout()
2338   -
2339   -
2340   -class ClutImagedataDialog(wx.Dialog):
2341   - def __init__(self, histogram, init, end, nodes=None):
2342   - pre = wx.PreDialog()
2343   - pre.Create(wx.GetApp().GetTopWindow(), -1, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT)
2344   - self.PostCreate(pre)
2345   -
2346   - self.histogram = histogram
2347   - self.init = init
2348   - self.end = end
2349   - self.nodes = nodes
2350   -
2351   - self._init_gui()
2352   - self.bind_events()
2353   - self.bind_events_wx()
2354   -
2355   - def _init_gui(self):
2356   - self.clut_widget = CLUTImageDataWidget(self, -1, self.histogram,
2357   - self.init, self.end, self.nodes)
2358   - sizer = wx.BoxSizer(wx.VERTICAL)
2359   - sizer.Add(self.clut_widget, 1, wx.EXPAND)
2360   -
2361   - self.SetSizer(sizer)
2362   - self.Fit()
2363   -
2364   - def bind_events_wx(self):
2365   - self.clut_widget.Bind(EVT_CLUT_NODE_CHANGED, self.OnClutChange)
2366   -
2367   - def bind_events(self):
2368   - Publisher.subscribe(self._refresh_widget, 'Update clut imagedata widget')
2369   -
2370   - def OnClutChange(self, evt):
2371   - Publisher.sendMessage('Change colour table from background image from widget',
2372   - evt.GetNodes())
2373   - Publisher.sendMessage('Update window level text',
2374   - (self.clut_widget.window_width,
2375   - self.clut_widget.window_level))
2376   -
2377   - def _refresh_widget(self, pubsub_evt):
2378   - self.clut_widget.Refresh()
2379   -
2380   - def Show(self, gen_evt=True, show=True):
2381   - super(wx.Dialog, self).Show(show)
2382   - if gen_evt:
2383   - self.clut_widget._generate_event()
invesalius/bkps/frame.py.bak
... ... @@ -1,1677 +0,0 @@
1   -#--------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------
19   -
20   -import math
21   -import os.path
22   -import platform
23   -import sys
24   -import webbrowser
25   -
26   -import wx
27   -import wx.aui
28   -from wx.lib.pubsub import pub as Publisher
29   -import wx.lib.agw.toasterbox as TB
30   -import wx.lib.popupctl as pc
31   -
32   -import constants as const
33   -import default_tasks as tasks
34   -import default_viewers as viewers
35   -import gui.dialogs as dlg
36   -import import_panel as imp
37   -import import_network_panel as imp_net
38   -import project as prj
39   -import session as ses
40   -import utils
41   -import preferences
42   -
43   -# Layout tools' IDs - this is used only locally, therefore doesn't
44   -# need to be defined in constants.py
45   -VIEW_TOOLS = [ID_LAYOUT, ID_TEXT] =\
46   - [wx.NewId() for number in range(2)]
47   -
48   -
49   -
50   -class MessageWatershed(wx.PopupWindow):
51   - def __init__(self, prnt, msg):
52   - wx.PopupWindow.__init__(self, prnt, -1)
53   - self.txt = wx.StaticText(self, -1, msg)
54   -
55   - self.sizer = wx.BoxSizer(wx.HORIZONTAL)
56   - self.sizer.Add(self.txt, 1, wx.EXPAND)
57   - self.SetSizer(self.sizer)
58   -
59   - self.sizer.Fit(self)
60   - self.Layout()
61   - self.Update()
62   - self.SetAutoLayout(1)
63   -
64   -
65   -
66   -
67   -class Frame(wx.Frame):
68   - """
69   - Main frame of the whole software.
70   - """
71   - def __init__(self, prnt):
72   - """
73   - Initialize frame, given its parent.
74   - """
75   - wx.Frame.__init__(self, id=-1, name='', parent=prnt,
76   - pos=wx.Point(0, 0),
77   - size=wx.Size(1024, 748), #size = wx.DisplaySize(),
78   - style=wx.DEFAULT_FRAME_STYLE, title='InVesalius 3')
79   - self.Center(wx.BOTH)
80   - icon_path = os.path.join(const.ICON_DIR, "invesalius.ico")
81   - self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO))
82   -
83   - self.mw = None
84   -
85   - if sys.platform != 'darwin':
86   - self.Maximize()
87   -
88   - #Necessary update AUI (statusBar in special)
89   - #when maximized in the Win 7 and XP
90   - self.SetSize(self.GetSize())
91   - #self.SetSize(wx.Size(1024, 748))
92   -
93   -
94   - # Set menus, status and task bar
95   - self.SetMenuBar(MenuBar(self))
96   - self.SetStatusBar(StatusBar(self))
97   -
98   - # Set TaskBarIcon
99   - #TaskBarIcon(self)
100   -
101   - # Create aui manager and insert content in it
102   - self.__init_aui()
103   -
104   - self.preferences = preferences.Preferences(self)
105   - # Initialize bind to pubsub events
106   - self.__bind_events()
107   - self.__bind_events_wx()
108   -
109   -
110   - def __bind_events(self):
111   - """
112   - Bind events related to pubsub.
113   - """
114   - sub = Publisher.subscribe
115   - sub(self._BeginBusyCursor, 'Begin busy cursor')
116   - sub(self._ShowContentPanel, 'Cancel DICOM load')
117   - sub(self._EndBusyCursor, 'End busy cursor')
118   - sub(self._HideContentPanel, 'Hide content panel')
119   - sub(self._HideImportPanel, 'Hide import panel')
120   - sub(self._HideTask, 'Hide task panel')
121   - sub(self._SetProjectName, 'Set project name')
122   - sub(self._ShowContentPanel, 'Show content panel')
123   - sub(self._ShowImportPanel, 'Show import panel in frame')
124   - #sub(self._ShowHelpMessage, 'Show help message')
125   - sub(self._ShowImportNetwork, 'Show retrieve dicom panel')
126   - sub(self._ShowTask, 'Show task panel')
127   - sub(self._UpdateAUI, 'Update AUI')
128   - sub(self._Exit, 'Exit')
129   -
130   - def __bind_events_wx(self):
131   - """
132   - Bind normal events from wx (except pubsub related).
133   - """
134   - self.Bind(wx.EVT_SIZE, self.OnSize)
135   - self.Bind(wx.EVT_MENU, self.OnMenuClick)
136   - self.Bind(wx.EVT_CLOSE, self.OnClose)
137   - #self.Bind(wx.EVT_MOVE, self.OnMove)
138   -
139   - def __init_aui(self):
140   - """
141   - Build AUI manager and all panels inside InVesalius frame.
142   - """
143   -
144   - # Tell aui_manager to manage this frame
145   - aui_manager = self.aui_manager = wx.aui.AuiManager()
146   - aui_manager.SetManagedWindow(self)
147   -
148   - # Add panels to manager
149   -
150   - # First, the task panel, to be on the left fo the frame
151   - # This will be specific according to InVesalius application
152   - aui_manager.AddPane(tasks.Panel(self), wx.aui.AuiPaneInfo().
153   - Name("Tasks").CaptionVisible(False))
154   -
155   - # Then, add the viewers panel, which will contain slices and
156   - # volume panels. In future this might also be specific
157   - # according to InVesalius application (e.g. panoramic
158   - # visualization, in odontology)
159   - aui_manager.AddPane(viewers.Panel(self), wx.aui.AuiPaneInfo().
160   - Caption(_("Data panel")).CaptionVisible(False).
161   - Centre().CloseButton(False).Floatable(False).
162   - Hide().Layer(1).MaximizeButton(True).
163   - Name("Data").Position(1))
164   -
165   - # This is the DICOM import panel. When the two panels above
166   - # are shown, this should be hiden
167   - caption = _("Preview medical data to be reconstructed")
168   - aui_manager.AddPane(imp.Panel(self), wx.aui.AuiPaneInfo().
169   - Name("Import").Centre().Hide().
170   - MaximizeButton(True).Floatable(True).
171   - Caption(caption).CaptionVisible(True))
172   -
173   - ncaption = _("Retrieve DICOM from PACS")
174   - aui_manager.AddPane(imp_net.Panel(self), wx.aui.AuiPaneInfo().
175   - Name("Retrieve").Centre().Hide().
176   - MaximizeButton(True).Floatable(True).
177   - Caption(ncaption).CaptionVisible(True))
178   -
179   - # Add toolbars to manager
180   - # This is pretty tricky -- order on win32 is inverted when
181   - # compared to linux2 & darwin
182   - if sys.platform == 'win32':
183   - t1 = ProjectToolBar(self)
184   - t2 = HistoryToolBar(self)
185   - t3 = LayoutToolBar(self)
186   - t4 = ObjectToolBar(self)
187   - t5 = SliceToolBar(self)
188   - else:
189   - t5 = ProjectToolBar(self)
190   - t4 = HistoryToolBar(self)
191   - t3 = LayoutToolBar(self)
192   - t2 = ObjectToolBar(self)
193   - t1 = SliceToolBar(self)
194   -
195   - aui_manager.AddPane(t1, wx.aui.AuiPaneInfo().
196   - Name("General Features Toolbar").
197   - ToolbarPane().Top().Floatable(False).
198   - LeftDockable(False).RightDockable(False))
199   -
200   - aui_manager.AddPane(t2, wx.aui.AuiPaneInfo().
201   - Name("Layout Toolbar").
202   - ToolbarPane().Top().Floatable(False).
203   - LeftDockable(False).RightDockable(False))
204   -
205   - aui_manager.AddPane(t3, wx.aui.AuiPaneInfo().
206   - Name("Project Toolbar").
207   - ToolbarPane().Top().Floatable(False).
208   - LeftDockable(False).RightDockable(False))
209   -
210   - aui_manager.AddPane(t4, wx.aui.AuiPaneInfo().
211   - Name("Slice Toolbar").
212   - ToolbarPane().Top().Floatable(False).
213   - LeftDockable(False).RightDockable(False))
214   -
215   - aui_manager.AddPane(t5, wx.aui.AuiPaneInfo().
216   - Name("History Toolbar").
217   - ToolbarPane().Top().Floatable(False).
218   - LeftDockable(False).RightDockable(False))
219   -
220   - aui_manager.Update()
221   - self.aui_manager = aui_manager
222   -
223   - # TODO: Allow saving and restoring perspectives
224   - self.perspective_all = aui_manager.SavePerspective()
225   -
226   - def _BeginBusyCursor(self, pubsub_evt):
227   - """
228   - Start busy cursor.
229   - Note: _EndBusyCursor should be called after.
230   - """
231   - wx.BeginBusyCursor()
232   -
233   - def _EndBusyCursor(self, pubsub_evt):
234   - """
235   - End busy cursor.
236   - Note: _BeginBusyCursor should have been called previously.
237   - """
238   - try:
239   - wx.EndBusyCursor()
240   - except wx._core.PyAssertionError:
241   - #no matching wxBeginBusyCursor() for wxEndBusyCursor()
242   - pass
243   -
244   - def _Exit(self, pubsub_evt):
245   - """
246   - Exit InVesalius.
247   - """
248   - self.Destroy()
249   - #sys.exit(0)
250   -
251   - def _HideContentPanel(self, pubsub_evt):
252   - """
253   - Hide data and tasks panels.
254   - """
255   - aui_manager = self.aui_manager
256   - aui_manager.GetPane("Data").Show(0)
257   - aui_manager.GetPane("Tasks").Show(1)
258   - aui_manager.Update()
259   -
260   - def _HideImportPanel(self, evt_pubsub):
261   - """
262   - Hide import panel and show tasks.
263   - """
264   - aui_manager = self.aui_manager
265   - aui_manager.GetPane("Import").Show(0)
266   - aui_manager.GetPane("Data").Show(0)
267   - aui_manager.GetPane("Tasks").Show(1)
268   - aui_manager.Update()
269   -
270   - def _HideTask(self, pubsub_evt):
271   - """
272   - Hide task panel.
273   - """
274   - self.aui_manager.GetPane("Tasks").Hide()
275   - self.aui_manager.Update()
276   -
277   - def _SetProjectName(self, pubsub_evt):
278   - """
279   - Set project name into frame's title.
280   - """
281   - proj_name = pubsub_evt.data
282   -
283   - if not(proj_name):
284   - self.SetTitle("InVesalius 3")
285   - else:
286   - self.SetTitle("%s - InVesalius 3"%(proj_name))
287   -
288   - def _ShowContentPanel(self, evt_pubsub):
289   - """
290   - Show viewers and task, hide import panel.
291   - """
292   - Publisher.sendMessage("Set layout button full")
293   - aui_manager = self.aui_manager
294   - aui_manager.GetPane("Import").Show(0)
295   - aui_manager.GetPane("Data").Show(1)
296   - aui_manager.GetPane("Tasks").Show(1)
297   - aui_manager.Update()
298   -
299   - def _ShowImportNetwork(self, evt_pubsub):
300   - """
301   - Show viewers and task, hide import panel.
302   - """
303   - Publisher.sendMessage("Set layout button full")
304   - aui_manager = self.aui_manager
305   - aui_manager.GetPane("Retrieve").Show(1)
306   - aui_manager.GetPane("Data").Show(0)
307   - aui_manager.GetPane("Tasks").Show(0)
308   - aui_manager.GetPane("Import").Show(0)
309   - aui_manager.Update()
310   -
311   - def _ShowHelpMessage(self, evt_pubsub):
312   - aui_manager = self.aui_manager
313   - pos = aui_manager.GetPane("Data").window.GetScreenPosition()
314   - msg = evt_pubsub.data
315   - self.mw = MessageWatershed(self, msg)
316   - self.mw.SetPosition(pos)
317   - self.mw.Show()
318   -
319   - def _ShowImportPanel(self, evt_pubsub):
320   - """
321   - Show only DICOM import panel.
322   - """
323   - Publisher.sendMessage("Set layout button data only")
324   - aui_manager = self.aui_manager
325   - aui_manager.GetPane("Import").Show(1)
326   - aui_manager.GetPane("Data").Show(0)
327   - aui_manager.GetPane("Tasks").Show(0)
328   - aui_manager.Update()
329   -
330   - def _ShowTask(self, pubsub_evt):
331   - """
332   - Show task panel.
333   - """
334   - self.aui_manager.GetPane("Tasks").Show()
335   - self.aui_manager.Update()
336   -
337   - def _UpdateAUI(self, pubsub_evt):
338   - """
339   - Refresh AUI panels/data.
340   - """
341   - self.aui_manager.Update()
342   -
343   - def CloseProject(self):
344   - Publisher.sendMessage('Close Project')
345   -
346   - def OnClose(self, evt):
347   - """
348   - Close all project data.
349   - """
350   - Publisher.sendMessage('Close Project')
351   - Publisher.sendMessage('Exit')
352   -
353   - def OnMenuClick(self, evt):
354   - """
355   - Capture event from mouse click on menu / toolbar (as both use
356   - the same ID's)
357   - """
358   - id = evt.GetId()
359   -
360   - if id == const.ID_DICOM_IMPORT:
361   - self.ShowImportDicomPanel()
362   - elif id == const.ID_PROJECT_OPEN:
363   - self.ShowOpenProject()
364   - elif id == const.ID_ANALYZE_IMPORT:
365   - self.ShowAnalyzeImporter()
366   - elif id == const.ID_NIFTI_IMPORT:
367   - self.ShowNiftiImporter()
368   - elif id == const.ID_PROJECT_SAVE:
369   - session = ses.Session()
370   - if session.temp_item:
371   - self.ShowSaveAsProject()
372   - else:
373   - self.SaveProject()
374   - elif id == const.ID_PROJECT_SAVE_AS:
375   - self.ShowSaveAsProject()
376   - elif id == const.ID_PROJECT_CLOSE:
377   - self.CloseProject()
378   - elif id == const.ID_EXIT:
379   - self.OnClose(None)
380   - elif id == const.ID_ABOUT:
381   - self.ShowAbout()
382   - elif id == const.ID_START:
383   - self.ShowGettingStarted()
384   - elif id == const.ID_PREFERENCES:
385   - self.ShowPreferences()
386   - elif id == const.ID_DICOM_NETWORK:
387   - self.ShowRetrieveDicomPanel()
388   - elif id in (const.ID_FLIP_X, const.ID_FLIP_Y, const.ID_FLIP_Z):
389   - axis = {const.ID_FLIP_X: 2,
390   - const.ID_FLIP_Y: 1,
391   - const.ID_FLIP_Z: 0}[id]
392   - self.FlipVolume(axis)
393   - elif id in (const.ID_SWAP_XY, const.ID_SWAP_XZ, const.ID_SWAP_YZ):
394   - axes = {const.ID_SWAP_XY: (2, 1),
395   - const.ID_SWAP_XZ: (2, 0),
396   - const.ID_SWAP_YZ: (1, 0)}[id]
397   - self.SwapAxes(axes)
398   - elif id == wx.ID_UNDO:
399   - self.OnUndo()
400   - elif id == wx.ID_REDO:
401   - self.OnRedo()
402   -
403   - def OnSize(self, evt):
404   - """
405   - Refresh GUI when frame is resized.
406   - """
407   - Publisher.sendMessage(('ProgressBar Reposition'))
408   - evt.Skip()
409   -
410   -
411   - def OnMove(self, evt):
412   - aui_manager = self.aui_manager
413   - pos = aui_manager.GetPane("Data").window.GetScreenPosition()
414   - self.mw.SetPosition(pos)
415   -
416   - def ShowPreferences(self):
417   -
418   - if self.preferences.ShowModal() == wx.ID_OK:
419   - values = self.preferences.GetPreferences()
420   - self.preferences.Close()
421   -
422   - ses.Session().rendering = values[const.RENDERING]
423   - ses.Session().surface_interpolation = values[const.SURFACE_INTERPOLATION]
424   - ses.Session().language = values[const.LANGUAGE]
425   -
426   - Publisher.sendMessage('Remove Volume')
427   - Publisher.sendMessage('Reset Reaycasting')
428   - Publisher.sendMessage('Update Surface Interpolation')
429   -
430   - def ShowAbout(self):
431   - """
432   - Shows about dialog.
433   - """
434   - dlg.ShowAboutDialog(self)
435   -
436   - def SaveProject(self):
437   - """
438   - Save project.
439   - """
440   - Publisher.sendMessage('Show save dialog', False)
441   -
442   - def ShowGettingStarted(self):
443   - """
444   - Show getting started window.
445   - """
446   - path = os.path.join(const.DOC_DIR,
447   - "user_guide_pt_BR.pdf")
448   - webbrowser.open(path)
449   -
450   - def ShowImportDicomPanel(self):
451   - """
452   - Show import DICOM panel.
453   - """
454   - Publisher.sendMessage('Show import directory dialog')
455   -
456   - def ShowRetrieveDicomPanel(self):
457   - print "teste.............."
458   - Publisher.sendMessage('Show retrieve dicom panel')
459   -
460   - def ShowOpenProject(self):
461   - """
462   - Show open project dialog.
463   - """
464   - Publisher.sendMessage('Show open project dialog')
465   -
466   - def ShowSaveAsProject(self):
467   - """
468   - Show save as dialog.
469   - """
470   - Publisher.sendMessage('Show save dialog', True)
471   -
472   - def ShowAnalyzeImporter(self):
473   - """
474   - Show save as dialog.
475   - """
476   - Publisher.sendMessage('Show analyze dialog', True)
477   -
478   - def FlipVolume(self, axis):
479   - Publisher.sendMessage('Flip volume', axis)
480   - Publisher.sendMessage('Reload actual slice')
481   -
482   - def SwapAxes(self, axes):
483   - Publisher.sendMessage('Swap volume axes', axes)
484   - Publisher.sendMessage('Update scroll')
485   - Publisher.sendMessage('Reload actual slice')
486   -
487   - def OnUndo(self):
488   - print "Undo"
489   - Publisher.sendMessage('Undo edition')
490   -
491   - def OnRedo(self):
492   - print "Redo"
493   - Publisher.sendMessage('Redo edition')
494   -
495   -
496   -
497   -
498   -
499   -
500   -# ------------------------------------------------------------------
501   -# ------------------------------------------------------------------
502   -# ------------------------------------------------------------------
503   -
504   -class MenuBar(wx.MenuBar):
505   - """
506   - MenuBar which contains menus used to control project, tools and
507   - help.
508   - """
509   - def __init__(self, parent):
510   - wx.MenuBar.__init__(self)
511   -
512   - self.parent = parent
513   -
514   - # Used to enable/disable menu items if project is opened or
515   - # not. Eg. save should only be available if a project is open
516   - self.enable_items = [const.ID_PROJECT_SAVE,
517   - const.ID_PROJECT_SAVE_AS,
518   - const.ID_PROJECT_CLOSE]
519   - self.__init_items()
520   - self.__bind_events()
521   -
522   - self.SetStateProjectClose()
523   -
524   - def __bind_events(self):
525   - """
526   - Bind events related to pubsub.
527   - """
528   - # TODO: in future, possibly when wxPython 2.9 is available,
529   - # events should be binded directly from wx.Menu / wx.MenuBar
530   - # message "Binding events of wx.MenuBar" on [wxpython-users]
531   - # mail list in Oct 20 2008
532   - sub = Publisher.subscribe
533   - sub(self.OnEnableState, "Enable state project")
534   - sub(self.OnEnableUndo, "Enable undo")
535   - sub(self.OnEnableRedo, "Enable redo")
536   -
537   - def __init_items(self):
538   - """
539   - Create all menu and submenus, and add them to self.
540   - """
541   - # TODO: This definetely needs improvements... ;)
542   -
543   - #Import Others Files
544   - others_file_menu = wx.Menu()
545   - others_file_menu.Append(const.ID_ANALYZE_IMPORT, "Analyze")
546   -
547   - # FILE
548   - file_menu = wx.Menu()
549   - app = file_menu.Append
550   - app(const.ID_DICOM_IMPORT, _("Import DICOM...\tCtrl+I"))
551   - #app(const.ID_DICOM_NETWORK, _("Retrieve DICOM from PACS"))
552   - file_menu.AppendMenu(const.ID_IMPORT_OTHERS_FILES, _("Import other files..."), others_file_menu)
553   - app(const.ID_PROJECT_OPEN, _("Open project...\tCtrl+O"))
554   - app(const.ID_PROJECT_SAVE, _("Save project\tCtrl+S"))
555   - app(const.ID_PROJECT_SAVE_AS, _("Save project as..."))
556   - app(const.ID_PROJECT_CLOSE, _("Close project"))
557   - file_menu.AppendSeparator()
558   - #app(const.ID_PROJECT_INFO, _("Project Information..."))
559   - #file_menu.AppendSeparator()
560   - #app(const.ID_SAVE_SCREENSHOT, _("Save Screenshot"))
561   - #app(const.ID_PRINT_SCREENSHOT, _("Print Screenshot"))
562   - #file_menu.AppendSeparator()
563   - #app(1, "C:\InvData\sample.inv")
564   - #file_menu.AppendSeparator()
565   - app(const.ID_EXIT, _("Exit\tCtrl+Q"))
566   -
567   -
568   - ############################### EDIT###############################
569   - # Flip
570   - #flip_menu = wx.Menu()
571   - #app = flip_menu.Append
572   - #app(const.ID_FLIP_X, _("R <-> L"))
573   - #app(const.ID_FLIP_Y, _("A <-> P"))
574   - #app(const.ID_FLIP_Z, _("T <-> B"))
575   -
576   - #swap_axes_menu = wx.Menu()
577   - #app = swap_axes_menu.Append
578   - #app(const.ID_SWAP_XY, _("R-L <-> A-P"))
579   - #app(const.ID_SWAP_XZ, _("R-L <-> T-B"))
580   - #app(const.ID_SWAP_YZ, _("A-P <-> T-B"))
581   -
582   - file_edit = wx.Menu()
583   - #file_edit.AppendMenu(wx.NewId(), _('Flip'), flip_menu)
584   - #file_edit.AppendMenu(wx.NewId(), _('Swap axes'), swap_axes_menu)
585   -
586   -
587   - d = const.ICON_DIR
588   - if not(sys.platform == 'darwin'):
589   - # Bitmaps for show/hide task panel item
590   - p = os.path.join(d, "undo_menu.png")
591   - self.BMP_UNDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
592   -
593   - p = os.path.join(d, "redo_menu.png")
594   - self.BMP_REDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
595   -
596   - file_edit_item_undo = wx.MenuItem(file_edit, wx.ID_UNDO, _("Undo\tCtrl+Z"))
597   - file_edit_item_undo.SetBitmap(self.BMP_UNDO)
598   - file_edit_item_undo.Enable(False)
599   - file_edit.AppendItem(file_edit_item_undo)
600   -
601   - file_edit_item_redo = wx.MenuItem(file_edit, wx.ID_REDO, _("Redo\tCtrl+Y"))
602   - file_edit_item_redo.SetBitmap(self.BMP_REDO)
603   - file_edit_item_redo.Enable(False)
604   - file_edit.AppendItem(file_edit_item_redo)
605   - else:
606   - file_edit.Append(wx.ID_UNDO, _("Undo\tCtrl+Z")).Enable(False)
607   - file_edit.Append(wx.ID_REDO, _("Redo\tCtrl+Y")).Enable(False)
608   - #app(const.ID_EDIT_LIST, "Show Undo List...")
609   - #################################################################
610   -
611   -
612   - # VIEW
613   - #view_tool_menu = wx.Menu()
614   - #app = view_tool_menu.Append
615   - #app(const.ID_TOOL_PROJECT, "Project Toolbar")
616   - #app(const.ID_TOOL_LAYOUT, "Layout Toolbar")
617   - #app(const.ID_TOOL_OBJECT, "Object Toolbar")
618   - #app(const.ID_TOOL_SLICE, "Slice Toolbar")
619   -
620   - #view_layout_menu = wx.Menu()
621   - #app = view_layout_menu.Append
622   - #app(const.ID_TASK_BAR, "Task Bar")
623   - #app(const.ID_VIEW_FOUR, "Four View")
624   -
625   - #view_menu = wx.Menu()
626   - #app = view_menu.Append
627   - #appm = view_menu.AppendMenu
628   - #appm(-1, "Toolbars",view_tool_menu)
629   - #appm(-1, "Layout", view_layout_menu)
630   - #view_menu.AppendSeparator()
631   - #app(const.ID_VIEW_FULL, "Fullscreen\tCtrl+F")
632   - #view_menu.AppendSeparator()
633   - #app(const.ID_VIEW_TEXT, "2D & 3D Text")
634   - #view_menu.AppendSeparator()
635   - #app(const.ID_VIEW_3D_BACKGROUND, "3D Background Colour")
636   -
637   - # TOOLS
638   - #tools_menu = wx.Menu()
639   -
640   - # OPTIONS
641   - options_menu = wx.Menu()
642   - options_menu.Append(const.ID_PREFERENCES, _("Preferences..."))
643   -
644   - # HELP
645   - help_menu = wx.Menu()
646   - help_menu.Append(const.ID_START, _("Getting started..."))
647   - #help_menu.Append(108, "User Manual...")
648   - help_menu.AppendSeparator()
649   - help_menu.Append(const.ID_ABOUT, _("About..."))
650   - #help_menu.Append(107, "Check For Updates Now...")
651   -
652   - if platform.system() == 'Darwin':
653   - wx.App.SetMacAboutMenuItemId(const.ID_ABOUT)
654   - wx.App.SetMacExitMenuItemId(const.ID_EXIT)
655   -
656   - # Add all menus to menubar
657   - self.Append(file_menu, _("File"))
658   - self.Append(file_edit, _("Edit"))
659   - #self.Append(view_menu, "View")
660   - #self.Append(tools_menu, "Tools")
661   - self.Append(options_menu, _("Options"))
662   - self.Append(help_menu, _("Help"))
663   -
664   - def OnEnableState(self, pubsub_evt):
665   - """
666   - Based on given state, enables or disables menu items which
667   - depend if project is open or not.
668   - """
669   - state = pubsub_evt.data
670   - if state:
671   - self.SetStateProjectOpen()
672   - else:
673   - self.SetStateProjectClose()
674   -
675   - def SetStateProjectClose(self):
676   - """
677   - Disable menu items (e.g. save) when project is closed.
678   - """
679   - for item in self.enable_items:
680   - self.Enable(item, False)
681   -
682   - def SetStateProjectOpen(self):
683   - """
684   - Enable menu items (e.g. save) when project is opened.
685   - """
686   - for item in self.enable_items:
687   - self.Enable(item, True)
688   -
689   - def OnEnableUndo(self, pubsub_evt):
690   - value = pubsub_evt.data
691   - if value:
692   - self.FindItemById(wx.ID_UNDO).Enable(True)
693   - else:
694   - self.FindItemById(wx.ID_UNDO).Enable(False)
695   -
696   - def OnEnableRedo(self, pubsub_evt):
697   - value = pubsub_evt.data
698   - if value:
699   - self.FindItemById(wx.ID_REDO).Enable(True)
700   - else:
701   - self.FindItemById(wx.ID_REDO).Enable(False)
702   -# ------------------------------------------------------------------
703   -# ------------------------------------------------------------------
704   -# ------------------------------------------------------------------
705   -
706   -class ProgressBar(wx.Gauge):
707   - """
708   - Progress bar / gauge.
709   - """
710   -
711   - def __init__(self, parent):
712   - wx.Gauge.__init__(self, parent, -1, 100)
713   - self.parent = parent
714   - self._Layout()
715   -
716   - self.__bind_events()
717   -
718   - def __bind_events(self):
719   - """
720   - Bind events related to pubsub.
721   - """
722   - sub = Publisher.subscribe
723   - sub(self._Layout, 'ProgressBar Reposition')
724   -
725   - def _Layout(self, evt_pubsub=None):
726   - """
727   - Compute new size and position, according to parent resize
728   - """
729   - rect = self.parent.GetFieldRect(2)
730   - self.SetPosition((rect.x + 2, rect.y + 2))
731   - self.SetSize((rect.width - 4, rect.height - 4))
732   -
733   - def SetPercentage(self, value):
734   - """
735   - Set value [0;100] into gauge, moving "status" percentage.
736   - """
737   - self.SetValue(int(value))
738   - if (value >= 99):
739   - self.SetValue(0)
740   - self.Refresh()
741   - self.Update()
742   -
743   -# ------------------------------------------------------------------
744   -# ------------------------------------------------------------------
745   -# ------------------------------------------------------------------
746   -
747   -class StatusBar(wx.StatusBar):
748   - """
749   - Control general status (both text and gauge)
750   - """
751   - def __init__(self, parent):
752   - wx.StatusBar.__init__(self, parent, -1)
753   -
754   - # General status configurations
755   - self.SetFieldsCount(3)
756   - self.SetStatusWidths([-2,-2,-1])
757   - self.SetStatusText(_("Ready"), 0)
758   - self.SetStatusText("", 1)
759   - self.SetStatusText("", 2)
760   -
761   - # Add gaugee
762   - self.progress_bar = ProgressBar(self)
763   -
764   - self.__bind_events()
765   -
766   - def __bind_events(self):
767   - """
768   - Bind events related to pubsub.
769   - """
770   - sub = Publisher.subscribe
771   - sub(self._SetProgressValue, 'Update status in GUI')
772   - sub(self._SetProgressLabel, 'Update status text in GUI')
773   -
774   - def _SetProgressValue(self, pubsub_evt):
775   - """
776   - Set both percentage value in gauge and text progress label in
777   - status.
778   - """
779   - value, label = pubsub_evt.data
780   - self.progress_bar.SetPercentage(value)
781   - self.SetStatusText(label, 0)
782   - if (int(value) >= 99):
783   - self.SetStatusText("",0)
784   - if sys.platform == 'win32':
785   - #TODO: temporary fix necessary in the Windows XP 64 Bits
786   - #BUG in wxWidgets http://trac.wxwidgets.org/ticket/10896
787   - try:
788   - #wx.SafeYield()
789   - wx.Yield()
790   - except(wx._core.PyAssertionError):
791   - utils.debug("wx._core.PyAssertionError")
792   -
793   - def _SetProgressLabel(self, pubsub_evt):
794   - """
795   - Set text progress label.
796   - """
797   - label = pubsub_evt.data
798   - self.SetStatusText(label, 0)
799   -
800   -# ------------------------------------------------------------------
801   -# ------------------------------------------------------------------
802   -# ------------------------------------------------------------------
803   -
804   -class TaskBarIcon(wx.TaskBarIcon):
805   - """
806   - TaskBarIcon has different behaviours according to the platform:
807   - - win32: Show icon on "Notification Area" (near clock)
808   - - darwin: Show icon on Dock
809   - - linux2: Show icon on "Notification Area" (near clock)
810   - """
811   - def __init__(self, parent=None):
812   - wx.TaskBarIcon.__init__(self)
813   - self.frame = parent
814   -
815   - icon = wx.Icon(os.path.join(const.ICON_DIR, "invesalius.ico"),
816   - wx.BITMAP_TYPE_ICO)
817   - self.SetIcon(icon, "InVesalius")
818   - self.imgidx = 1
819   -
820   - # bind some events
821   - self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
822   -
823   - def OnTaskBarActivate(self, evt):
824   - pass
825   -
826   -# ------------------------------------------------------------------
827   -# ------------------------------------------------------------------
828   -# ------------------------------------------------------------------
829   -
830   -class ProjectToolBar(wx.ToolBar):
831   - """
832   - Toolbar related to general project operations, including: import,
833   - open, save and saveas, among others.
834   - """
835   - def __init__(self, parent):
836   - style = wx.TB_FLAT|wx.TB_NODIVIDER| wx.TB_DOCKABLE
837   - wx.ToolBar.__init__(self, parent, -1, wx.DefaultPosition,
838   - wx.DefaultSize,
839   - style)
840   - self.SetToolBitmapSize(wx.Size(32,32))
841   -
842   - self.parent = parent
843   -
844   - # Used to enable/disable menu items if project is opened or
845   - # not. Eg. save should only be available if a project is open
846   - self.enable_items = [const.ID_PROJECT_SAVE]
847   -
848   - self.__init_items()
849   - self.__bind_events()
850   -
851   - self.Realize()
852   - self.SetStateProjectClose()
853   -
854   - def __bind_events(self):
855   - """
856   - Bind events related to pubsub.
857   - """
858   - sub = Publisher.subscribe
859   - sub(self._EnableState, "Enable state project")
860   -
861   - def __init_items(self):
862   - """
863   - Add tools into toolbar.
864   - """
865   - # Load bitmaps
866   - d = const.ICON_DIR
867   - if sys.platform == 'darwin':
868   - path = os.path.join(d,"file_from_internet_original.png")
869   - BMP_NET = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
870   -
871   - path = os.path.join(d, "file_import_original.png")
872   - BMP_IMPORT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
873   -
874   - path = os.path.join(d, "file_open_original.png")
875   - BMP_OPEN = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
876   -
877   - path = os.path.join(d, "file_save_original.png")
878   - BMP_SAVE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
879   -
880   - path = os.path.join(d, "print_original.png")
881   - BMP_PRINT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
882   -
883   - path = os.path.join(d, "tool_photo_original.png")
884   - BMP_PHOTO = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
885   - else:
886   - path = os.path.join(d, "file_from_internet.png")
887   - BMP_NET = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
888   -
889   - path = os.path.join(d, "file_import.png")
890   - BMP_IMPORT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
891   -
892   - path = os.path.join(d, "file_open.png")
893   - BMP_OPEN = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
894   -
895   - path = os.path.join(d, "file_save.png")
896   - BMP_SAVE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
897   -
898   - path = os.path.join(d, "print.png")
899   - BMP_PRINT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
900   -
901   - path = os.path.join(d, "tool_photo.png")
902   - BMP_PHOTO = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
903   -
904   - # Create tool items based on bitmaps
905   - self.AddLabelTool(const.ID_DICOM_IMPORT,
906   - "",
907   - shortHelp =_("Import DICOM files...\tCtrl+I"),
908   - bitmap=BMP_IMPORT)
909   - #self.AddLabelTool(const.ID_DICOM_LOAD_NET,
910   - # "Load medical image...",
911   - # BMP_NET)
912   - self.AddLabelTool(const.ID_PROJECT_OPEN,
913   - "",
914   - shortHelp =_("Open InVesalius project..."),
915   - bitmap=BMP_OPEN)
916   - self.AddLabelTool(const.ID_PROJECT_SAVE,
917   - "",
918   - shortHelp = _("Save InVesalius project"),
919   - bitmap=BMP_SAVE)
920   - #self.AddLabelTool(const.ID_SAVE_SCREENSHOT,
921   - # "Take photo of screen",
922   - # BMP_PHOTO)
923   - #self.AddLabelTool(const.ID_PRINT_SCREENSHOT,
924   - # "Print medical image...",
925   - # BMP_PRINT)
926   -
927   - def _EnableState(self, pubsub_evt):
928   - """
929   - Based on given state, enable or disable menu items which
930   - depend if project is open or not.
931   - """
932   - state = pubsub_evt.data
933   - if state:
934   - self.SetStateProjectOpen()
935   - else:
936   - self.SetStateProjectClose()
937   -
938   - def SetStateProjectClose(self):
939   - """
940   - Disable menu items (e.g. save) when project is closed.
941   - """
942   - for tool in self.enable_items:
943   - self.EnableTool(tool, False)
944   -
945   - def SetStateProjectOpen(self):
946   - """
947   - Enable menu items (e.g. save) when project is opened.
948   - """
949   - for tool in self.enable_items:
950   - self.EnableTool(tool, True)
951   -
952   -
953   -
954   -# ------------------------------------------------------------------
955   -# ------------------------------------------------------------------
956   -# ------------------------------------------------------------------
957   -
958   -class ObjectToolBar(wx.ToolBar):
959   - """
960   - Toolbar related to general object operations, including: zoom
961   - move, rotate, brightness/contrast, etc.
962   - """
963   - def __init__(self, parent):
964   - style = wx.TB_FLAT|wx.TB_NODIVIDER | wx.TB_DOCKABLE
965   - wx.ToolBar.__init__(self, parent, -1, wx.DefaultPosition,
966   - wx.DefaultSize, style)
967   -
968   - self.SetToolBitmapSize(wx.Size(32,32))
969   -
970   - self.parent = parent
971   - # Used to enable/disable menu items if project is opened or
972   - # not. Eg. save should only be available if a project is open
973   - self.enable_items = [const.STATE_WL, const.STATE_PAN,
974   - const.STATE_SPIN, const.STATE_ZOOM_SL,
975   - const.STATE_ZOOM,
976   - const.STATE_MEASURE_DISTANCE,
977   - const.STATE_MEASURE_ANGLE,]
978   - #const.STATE_ANNOTATE]
979   - self.__init_items()
980   - self.__bind_events()
981   - self.__bind_events_wx()
982   -
983   - self.Realize()
984   - self.SetStateProjectClose()
985   -
986   - def __bind_events(self):
987   - """
988   - Bind events related to pubsub.
989   - """
990   - sub = Publisher.subscribe
991   - sub(self._EnableState, "Enable state project")
992   - sub(self._UntoggleAllItems, 'Untoggle object toolbar items')
993   - sub(self._ToggleLinearMeasure, "Set tool linear measure")
994   - sub(self._ToggleAngularMeasure, "Set tool angular measure")
995   -
996   - def __bind_events_wx(self):
997   - """
998   - Bind normal events from wx (except pubsub related).
999   - """
1000   - self.Bind(wx.EVT_TOOL, self.OnToggle)
1001   -
1002   - def __init_items(self):
1003   - """
1004   - Add tools into toolbar.
1005   - """
1006   - d = const.ICON_DIR
1007   - if sys.platform == 'darwin':
1008   - path = os.path.join(d, "tool_rotate_original.png")
1009   - BMP_ROTATE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1010   -
1011   - path = os.path.join(d, "tool_translate_original.png")
1012   - BMP_MOVE =wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1013   -
1014   - path = os.path.join(d, "tool_zoom_original.png")
1015   - BMP_ZOOM = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1016   -
1017   - path = os.path.join(d, "tool_zoom_select_original.png")
1018   - BMP_ZOOM_SELECT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1019   -
1020   - path = os.path.join(d, "tool_contrast_original.png")
1021   - BMP_CONTRAST = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1022   -
1023   - path = os.path.join(d, "measure_line_original.png")
1024   - BMP_DISTANCE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1025   -
1026   - path = os.path.join(d, "measure_angle_original.png")
1027   - BMP_ANGLE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1028   -
1029   - #path = os.path.join(d, "tool_annotation_original.png")
1030   - #BMP_ANNOTATE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1031   -
1032   - else:
1033   - path = os.path.join(d, "tool_rotate.png")
1034   - BMP_ROTATE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1035   -
1036   - path = os.path.join(d, "tool_translate.png")
1037   - BMP_MOVE =wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1038   -
1039   - path = os.path.join(d, "tool_zoom.png")
1040   - BMP_ZOOM = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1041   -
1042   - path = os.path.join(d, "tool_zoom_select.png")
1043   - BMP_ZOOM_SELECT = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1044   -
1045   - path = os.path.join(d, "tool_contrast.png")
1046   - BMP_CONTRAST = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1047   -
1048   - path = os.path.join(d, "measure_line.png")
1049   - BMP_DISTANCE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1050   -
1051   - path = os.path.join(d, "measure_angle.png")
1052   - BMP_ANGLE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1053   -
1054   - #path = os.path.join(d, "tool_annotation.png")
1055   - #BMP_ANNOTATE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1056   -
1057   - # Create tool items based on bitmaps
1058   - self.AddLabelTool(const.STATE_ZOOM,
1059   - "",
1060   - shortHelp =_("Zoom"),
1061   - bitmap=BMP_ZOOM,
1062   - kind = wx.ITEM_CHECK)
1063   - self.AddLabelTool(const.STATE_ZOOM_SL,
1064   - "",
1065   - shortHelp = _("Zoom based on selection"),
1066   - bitmap = BMP_ZOOM_SELECT,
1067   - kind = wx.ITEM_CHECK)
1068   - self.AddLabelTool(const.STATE_SPIN,
1069   - "",
1070   - shortHelp = _("Rotate"),
1071   - bitmap = BMP_ROTATE,
1072   - kind = wx.ITEM_CHECK)
1073   - self.AddLabelTool(const.STATE_PAN,
1074   - "",
1075   - shortHelp = _("Move"),
1076   - bitmap = BMP_MOVE,
1077   - kind = wx.ITEM_CHECK)
1078   - self.AddLabelTool(const.STATE_WL,
1079   - "",
1080   - shortHelp = _("Constrast"),
1081   - bitmap = BMP_CONTRAST,
1082   - kind = wx.ITEM_CHECK)
1083   - self.AddLabelTool(const.STATE_MEASURE_DISTANCE,
1084   - "",
1085   - shortHelp = _("Measure distance"),
1086   - bitmap = BMP_DISTANCE,
1087   - kind = wx.ITEM_CHECK)
1088   - self.AddLabelTool(const.STATE_MEASURE_ANGLE,
1089   - "",
1090   - shortHelp = _("Measure angle"),
1091   - bitmap = BMP_ANGLE,
1092   - kind = wx.ITEM_CHECK)
1093   - #self.AddLabelTool(const.STATE_ANNOTATE,
1094   - # "",
1095   - # shortHelp = _("Add annotation"),
1096   - # bitmap = BMP_ANNOTATE,
1097   - # kind = wx.ITEM_CHECK)
1098   -
1099   - def _EnableState(self, pubsub_evt):
1100   - """
1101   - Based on given state, enable or disable menu items which
1102   - depend if project is open or not.
1103   - """
1104   - state = pubsub_evt.data
1105   - if state:
1106   - self.SetStateProjectOpen()
1107   - else:
1108   - self.SetStateProjectClose()
1109   -
1110   - def _UntoggleAllItems(self, pubsub_evt=None):
1111   - """
1112   - Untoggle all items on toolbar.
1113   - """
1114   - for id in const.TOOL_STATES:
1115   - state = self.GetToolState(id)
1116   - if state:
1117   - self.ToggleTool(id, False)
1118   -
1119   - def _ToggleLinearMeasure(self, pubsub_evt):
1120   - """
1121   - Force measure distance tool to be toggled and bind pubsub
1122   - events to other classes whici are interested on this.
1123   - """
1124   - id = const.STATE_MEASURE_DISTANCE
1125   - self.ToggleTool(id, True)
1126   - Publisher.sendMessage('Enable style', id)
1127   - Publisher.sendMessage('Untoggle slice toolbar items')
1128   - for item in const.TOOL_STATES:
1129   - state = self.GetToolState(item)
1130   - if state and (item != id):
1131   - self.ToggleTool(item, False)
1132   -
1133   -
1134   - def _ToggleAngularMeasure(self, pubsub_evt):
1135   - """
1136   - Force measure angle tool to be toggled and bind pubsub
1137   - events to other classes which are interested on this.
1138   - """
1139   - id = const.STATE_MEASURE_ANGLE
1140   - self.ToggleTool(id, True)
1141   - Publisher.sendMessage('Enable style', id)
1142   - Publisher.sendMessage('Untoggle slice toolbar items')
1143   - for item in const.TOOL_STATES:
1144   - state = self.GetToolState(item)
1145   - if state and (item != id):
1146   - self.ToggleTool(item, False)
1147   -
1148   - def OnToggle(self, evt):
1149   - """
1150   - Update status of other items on toolbar (only one item
1151   - should be toggle each time).
1152   - """
1153   - id = evt.GetId()
1154   - state = self.GetToolState(id)
1155   - if state and ((id == const.STATE_MEASURE_DISTANCE) or\
1156   - (id == const.STATE_MEASURE_ANGLE)):
1157   - Publisher.sendMessage('Fold measure task')
1158   -
1159   - if state:
1160   - Publisher.sendMessage('Enable style', id)
1161   - Publisher.sendMessage('Untoggle slice toolbar items')
1162   - else:
1163   - Publisher.sendMessage('Disable style', id)
1164   -
1165   - for item in const.TOOL_STATES:
1166   - state = self.GetToolState(item)
1167   - if state and (item != id):
1168   - self.ToggleTool(item, False)
1169   - evt.Skip()
1170   -
1171   - def SetStateProjectClose(self):
1172   - """
1173   - Disable menu items (e.g. zoom) when project is closed.
1174   - """
1175   - for tool in self.enable_items:
1176   - self.EnableTool(tool, False)
1177   - self._UntoggleAllItems()
1178   -
1179   - def SetStateProjectOpen(self):
1180   - """
1181   - Enable menu items (e.g. zoom) when project is opened.
1182   - """
1183   - for tool in self.enable_items:
1184   - self.EnableTool(tool, True)
1185   -
1186   -# ------------------------------------------------------------------
1187   -# ------------------------------------------------------------------
1188   -# ------------------------------------------------------------------
1189   -
1190   -class SliceToolBar(wx.ToolBar):
1191   - """
1192   - Toolbar related to 2D slice specific operations, including: cross
1193   - intersection reference and scroll slices.
1194   - """
1195   - def __init__(self, parent):
1196   - style = wx.TB_FLAT|wx.TB_NODIVIDER | wx.TB_DOCKABLE
1197   - wx.ToolBar.__init__(self, parent, -1, wx.DefaultPosition,
1198   - wx.DefaultSize,
1199   - style)
1200   -
1201   - self.SetToolBitmapSize(wx.Size(32,32))
1202   -
1203   - self.parent = parent
1204   - self.enable_items = [const.SLICE_STATE_SCROLL,
1205   - const.SLICE_STATE_CROSS]
1206   - self.__init_items()
1207   - self.__bind_events()
1208   - self.__bind_events_wx()
1209   -
1210   - self.Realize()
1211   - self.SetStateProjectClose()
1212   -
1213   - def __init_items(self):
1214   - """
1215   - Add tools into toolbar.
1216   - """
1217   - d = const.ICON_DIR
1218   - if sys.platform == 'darwin':
1219   - path = os.path.join(d, "slice_original.png")
1220   - BMP_SLICE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1221   -
1222   - path = os.path.join(d,"cross_original.png")
1223   - BMP_CROSS = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1224   - else:
1225   - path = os.path.join(d, "slice.png")
1226   - BMP_SLICE = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1227   -
1228   - path = os.path.join(d,"cross.png")
1229   - BMP_CROSS = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
1230   -
1231   - self.AddCheckTool(const.SLICE_STATE_SCROLL,
1232   - BMP_SLICE,
1233   - shortHelp = _("Scroll slices"))
1234   -
1235   - self.AddCheckTool(const.SLICE_STATE_CROSS,
1236   - BMP_CROSS,
1237   - shortHelp = _("Slices' cross intersection"))
1238   -
1239   - def __bind_events(self):
1240   - """
1241   - Bind events related to pubsub.
1242   - """
1243   - sub = Publisher.subscribe
1244   - sub(self._EnableState, "Enable state project")
1245   - sub(self._UntoggleAllItems, 'Untoggle slice toolbar items')
1246   -
1247   - def __bind_events_wx(self):
1248   - """
1249   - Bind normal events from wx (except pubsub related).
1250   - """
1251   - self.Bind(wx.EVT_TOOL, self.OnToggle)
1252   -
1253   - def _EnableState(self, pubsub_evt):
1254   - """
1255   - Based on given state, enable or disable menu items which
1256   - depend if project is open or not.
1257   - """
1258   - state = pubsub_evt.data
1259   - if state:
1260   - self.SetStateProjectOpen()
1261   - else:
1262   - self.SetStateProjectClose()
1263   - self._UntoggleAllItems()
1264   -
1265   - def _UntoggleAllItems(self, pubsub_evt=None):
1266   - """
1267   - Untoggle all items on toolbar.
1268   - """
1269   - for id in const.TOOL_SLICE_STATES:
1270   - state = self.GetToolState(id)
1271   - if state:
1272   - self.ToggleTool(id, False)
1273   - if id == const.SLICE_STATE_CROSS:
1274   - msg = 'Set cross visibility'
1275   - Publisher.sendMessage(msg, 0)
1276   -
1277   - def OnToggle(self, evt):
1278   - """
1279   - Update status of other items on toolbar (only one item
1280   - should be toggle each time).
1281   - """
1282   - id = evt.GetId()
1283   - state = self.GetToolState(id)
1284   -
1285   - if state:
1286   - Publisher.sendMessage('Enable style', id)
1287   - Publisher.sendMessage('Untoggle object toolbar items')
1288   - else:
1289   - Publisher.sendMessage('Disable style', id)
1290   -
1291   - for item in const.TOOL_SLICE_STATES:
1292   - state = self.GetToolState(item)
1293   - if state and (item != id):
1294   - self.ToggleTool(item, False)
1295   -
1296   - evt.Skip()
1297   -
1298   - def SetStateProjectClose(self):
1299   - """
1300   - Disable menu items (e.g. cross) when project is closed.
1301   - """
1302   - for tool in self.enable_items:
1303   - self.EnableTool(tool, False)
1304   -
1305   - def SetStateProjectOpen(self):
1306   - """
1307   - Enable menu items (e.g. cross) when project is opened.
1308   - """
1309   - for tool in self.enable_items:
1310   - self.EnableTool(tool, True)
1311   -
1312   -# ------------------------------------------------------------------
1313   -# ------------------------------------------------------------------
1314   -# ------------------------------------------------------------------
1315   -
1316   -class LayoutToolBar(wx.ToolBar):
1317   - """
1318   - Toolbar related to general layout/ visualization configuration
1319   - e.g: show/hide task panel and show/hide text on viewers.
1320   - """
1321   - def __init__(self, parent):
1322   - style = wx.TB_FLAT|wx.TB_NODIVIDER | wx.TB_DOCKABLE
1323   - wx.ToolBar.__init__(self, parent, -1, wx.DefaultPosition,
1324   - wx.DefaultSize,
1325   - style)
1326   -
1327   - self.SetToolBitmapSize(wx.Size(32,32))
1328   -
1329   - self.parent = parent
1330   - self.__init_items()
1331   - self.__bind_events()
1332   - self.__bind_events_wx()
1333   -
1334   - self.ontool_layout = False
1335   - self.ontool_text = True
1336   - self.enable_items = [ID_TEXT]
1337   -
1338   - self.Realize()
1339   - self.SetStateProjectClose()
1340   -
1341   - def __bind_events(self):
1342   - """
1343   - Bind events related to pubsub.
1344   - """
1345   - sub = Publisher.subscribe
1346   - sub(self._EnableState, "Enable state project")
1347   - sub(self._SetLayoutWithTask, "Set layout button data only")
1348   - sub(self._SetLayoutWithoutTask, "Set layout button full")
1349   -
1350   - def __bind_events_wx(self):
1351   - """
1352   - Bind normal events from wx (except pubsub related).
1353   - """
1354   - self.Bind(wx.EVT_TOOL, self.OnToggle)
1355   -
1356   - def __init_items(self):
1357   - """
1358   - Add tools into toolbar.
1359   - """
1360   - d = const.ICON_DIR
1361   - if sys.platform == 'darwin':
1362   - # Bitmaps for show/hide task panel item
1363   - p = os.path.join(d, "layout_data_only_original.gif")
1364   - self.BMP_WITH_MENU = wx.Bitmap(p, wx.BITMAP_TYPE_GIF)
1365   -
1366   - p = os.path.join(d, "layout_full_original.gif")
1367   - self.BMP_WITHOUT_MENU = wx.Bitmap(p, wx.BITMAP_TYPE_GIF)
1368   -
1369   - # Bitmaps for show/hide task item
1370   - p = os.path.join(d, "text_inverted_original.png")
1371   - self.BMP_WITHOUT_TEXT = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1372   -
1373   - p = os.path.join(d, "text_original.png")
1374   - self.BMP_WITH_TEXT = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1375   -
1376   - else:
1377   - # Bitmaps for show/hide task panel item
1378   - p = os.path.join(d, "layout_data_only.gif")
1379   - self.BMP_WITH_MENU = wx.Bitmap(p, wx.BITMAP_TYPE_GIF)
1380   -
1381   - p = os.path.join(d, "layout_full.gif")
1382   - self.BMP_WITHOUT_MENU = wx.Bitmap(p, wx.BITMAP_TYPE_GIF)
1383   -
1384   - # Bitmaps for show/hide task item
1385   - p = os.path.join(d, "text_inverted.png")
1386   - self.BMP_WITHOUT_TEXT = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1387   -
1388   - p = os.path.join(d, "text.png")
1389   - self.BMP_WITH_TEXT = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1390   -
1391   - self.AddLabelTool(ID_LAYOUT,
1392   - "",
1393   - bitmap=self.BMP_WITHOUT_MENU,
1394   - shortHelp= _("Hide task panel"))
1395   - self.AddLabelTool(ID_TEXT,
1396   - "",
1397   - bitmap=self.BMP_WITH_TEXT,
1398   - shortHelp= _("Hide text"))
1399   -
1400   - def _EnableState(self, pubsub_evt):
1401   - """
1402   - Based on given state, enable or disable menu items which
1403   - depend if project is open or not.
1404   - """
1405   - state = pubsub_evt.data
1406   - if state:
1407   - self.SetStateProjectOpen()
1408   - else:
1409   - self.SetStateProjectClose()
1410   -
1411   - def _SetLayoutWithoutTask(self, pubsub_evt):
1412   - """
1413   - Set item bitmap to task panel hiden.
1414   - """
1415   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITHOUT_MENU)
1416   -
1417   - def _SetLayoutWithTask(self, pubsub_evt):
1418   - """
1419   - Set item bitmap to task panel shown.
1420   - """
1421   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITH_MENU)
1422   -
1423   - def OnToggle(self, event):
1424   - """
1425   - Update status of toolbar item (bitmap and help)
1426   - """
1427   - id = event.GetId()
1428   - if id == ID_LAYOUT:
1429   - self.ToggleLayout()
1430   - elif id== ID_TEXT:
1431   - self.ToggleText()
1432   -
1433   - for item in VIEW_TOOLS:
1434   - state = self.GetToolState(item)
1435   - if state and (item != id):
1436   - self.ToggleTool(item, False)
1437   -
1438   - def SetStateProjectClose(self):
1439   - """
1440   - Disable menu items (e.g. text) when project is closed.
1441   - """
1442   - self.ontool_text = True
1443   - self.ToggleText()
1444   - for tool in self.enable_items:
1445   - self.EnableTool(tool, False)
1446   -
1447   - def SetStateProjectOpen(self):
1448   - """
1449   - Disable menu items (e.g. text) when project is closed.
1450   - """
1451   - self.ontool_text = False
1452   - self.ToggleText()
1453   - for tool in self.enable_items:
1454   - self.EnableTool(tool, True)
1455   -
1456   - def ToggleLayout(self):
1457   - """
1458   - Based on previous layout item state, toggle it.
1459   - """
1460   - if self.ontool_layout:
1461   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITHOUT_MENU)
1462   - Publisher.sendMessage('Show task panel')
1463   - self.SetToolShortHelp(ID_LAYOUT,_("Hide task panel"))
1464   - self.ontool_layout = False
1465   - else:
1466   - self.bitmap = self.BMP_WITH_MENU
1467   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITH_MENU)
1468   - Publisher.sendMessage('Hide task panel')
1469   - self.SetToolShortHelp(ID_LAYOUT, _("Show task panel"))
1470   - self.ontool_layout = True
1471   -
1472   - def ToggleText(self):
1473   - """
1474   - Based on previous text item state, toggle it.
1475   - """
1476   - if self.ontool_text:
1477   - self.SetToolNormalBitmap(ID_TEXT,self.BMP_WITH_TEXT)
1478   - Publisher.sendMessage('Hide text actors on viewers')
1479   - self.SetToolShortHelp(ID_TEXT,_("Show text"))
1480   - Publisher.sendMessage('Update AUI')
1481   - self.ontool_text = False
1482   - else:
1483   - self.SetToolNormalBitmap(ID_TEXT, self.BMP_WITHOUT_TEXT)
1484   - Publisher.sendMessage('Show text actors on viewers')
1485   - self.SetToolShortHelp(ID_TEXT,_("Hide text"))
1486   - Publisher.sendMessage('Update AUI')
1487   - self.ontool_text = True
1488   -
1489   -
1490   -class HistoryToolBar(wx.ToolBar):
1491   - """
1492   - Toolbar related to general layout/ visualization configuration
1493   - e.g: show/hide task panel and show/hide text on viewers.
1494   - """
1495   - def __init__(self, parent):
1496   - style = wx.TB_FLAT|wx.TB_NODIVIDER | wx.TB_DOCKABLE
1497   - wx.ToolBar.__init__(self, parent, -1, wx.DefaultPosition,
1498   - wx.DefaultSize,
1499   - style)
1500   -
1501   - self.SetToolBitmapSize(wx.Size(32,32))
1502   -
1503   - self.parent = parent
1504   - self.__init_items()
1505   - self.__bind_events()
1506   - self.__bind_events_wx()
1507   -
1508   - self.ontool_layout = False
1509   - self.ontool_text = True
1510   - #self.enable_items = [ID_TEXT]
1511   -
1512   - self.Realize()
1513   - #self.SetStateProjectClose()
1514   -
1515   - def __bind_events(self):
1516   - """
1517   - Bind events related to pubsub.
1518   - """
1519   - sub = Publisher.subscribe
1520   - #sub(self._EnableState, "Enable state project")
1521   - #sub(self._SetLayoutWithTask, "Set layout button data only")
1522   - #sub(self._SetLayoutWithoutTask, "Set layout button full")
1523   - sub(self.OnEnableUndo, "Enable undo")
1524   - sub(self.OnEnableRedo, "Enable redo")
1525   -
1526   - def __bind_events_wx(self):
1527   - """
1528   - Bind normal events from wx (except pubsub related).
1529   - """
1530   - #self.Bind(wx.EVT_TOOL, self.OnToggle)
1531   - wx.EVT_TOOL( self, wx.ID_UNDO, self.OnUndo )
1532   - wx.EVT_TOOL( self, wx.ID_REDO, self.OnRedo )
1533   -
1534   - def __init_items(self):
1535   - """
1536   - Add tools into toolbar.
1537   - """
1538   - d = const.ICON_DIR
1539   - if sys.platform == 'darwin':
1540   - # Bitmaps for show/hide task panel item
1541   - p = os.path.join(d, "undo_original.png")
1542   - self.BMP_UNDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1543   -
1544   - p = os.path.join(d, "redo_original.png")
1545   - self.BMP_REDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1546   -
1547   - else:
1548   - # Bitmaps for show/hide task panel item
1549   - p = os.path.join(d, "undo_small.png")
1550   - self.BMP_UNDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1551   -
1552   - p = os.path.join(d, "redo_small.png")
1553   - self.BMP_REDO = wx.Bitmap(p, wx.BITMAP_TYPE_PNG)
1554   -
1555   - self.AddLabelTool(wx.ID_UNDO,
1556   - "",
1557   - bitmap=self.BMP_UNDO,
1558   - shortHelp= _("Undo"))
1559   -
1560   - self.AddLabelTool(wx.ID_REDO,
1561   - "",
1562   - bitmap=self.BMP_REDO,
1563   - shortHelp= _("Redo"))
1564   -
1565   - self.EnableTool(wx.ID_UNDO, False)
1566   - self.EnableTool(wx.ID_REDO, False)
1567   -
1568   - def _EnableState(self, pubsub_evt):
1569   - """
1570   - Based on given state, enable or disable menu items which
1571   - depend if project is open or not.
1572   - """
1573   - state = pubsub_evt.data
1574   - if state:
1575   - self.SetStateProjectOpen()
1576   - else:
1577   - self.SetStateProjectClose()
1578   -
1579   - def _SetLayoutWithoutTask(self, pubsub_evt):
1580   - """
1581   - Set item bitmap to task panel hiden.
1582   - """
1583   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITHOUT_MENU)
1584   -
1585   - def _SetLayoutWithTask(self, pubsub_evt):
1586   - """
1587   - Set item bitmap to task panel shown.
1588   - """
1589   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITH_MENU)
1590   -
1591   - def OnUndo(self, event):
1592   - print "Undo"
1593   - Publisher.sendMessage('Undo edition')
1594   -
1595   - def OnRedo(self, event):
1596   - print "Redo"
1597   - Publisher.sendMessage('Redo edition')
1598   -
1599   - def OnToggle(self, event):
1600   - """
1601   - Update status of toolbar item (bitmap and help)
1602   - """
1603   - id = event.GetId()
1604   - if id == ID_LAYOUT:
1605   - self.ToggleLayout()
1606   - elif id== ID_TEXT:
1607   - self.ToggleText()
1608   -
1609   - for item in VIEW_TOOLS:
1610   - state = self.GetToolState(item)
1611   - if state and (item != id):
1612   - self.ToggleTool(item, False)
1613   -
1614   - def SetStateProjectClose(self):
1615   - """
1616   - Disable menu items (e.g. text) when project is closed.
1617   - """
1618   - self.ontool_text = True
1619   - self.ToggleText()
1620   - for tool in self.enable_items:
1621   - self.EnableTool(tool, False)
1622   -
1623   - def SetStateProjectOpen(self):
1624   - """
1625   - Disable menu items (e.g. text) when project is closed.
1626   - """
1627   - self.ontool_text = False
1628   - self.ToggleText()
1629   - for tool in self.enable_items:
1630   - self.EnableTool(tool, True)
1631   -
1632   - def ToggleLayout(self):
1633   - """
1634   - Based on previous layout item state, toggle it.
1635   - """
1636   - if self.ontool_layout:
1637   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITHOUT_MENU)
1638   - Publisher.sendMessage('Show task panel')
1639   - self.SetToolShortHelp(ID_LAYOUT,_("Hide task panel"))
1640   - self.ontool_layout = False
1641   - else:
1642   - self.bitmap = self.BMP_WITH_MENU
1643   - self.SetToolNormalBitmap(ID_LAYOUT,self.BMP_WITH_MENU)
1644   - Publisher.sendMessage('Hide task panel')
1645   - self.SetToolShortHelp(ID_LAYOUT, _("Show task panel"))
1646   - self.ontool_layout = True
1647   -
1648   - def ToggleText(self):
1649   - """
1650   - Based on previous text item state, toggle it.
1651   - """
1652   - if self.ontool_text:
1653   - self.SetToolNormalBitmap(ID_TEXT,self.BMP_WITH_TEXT)
1654   - Publisher.sendMessage('Hide text actors on viewers')
1655   - self.SetToolShortHelp(ID_TEXT,_("Show text"))
1656   - Publisher.sendMessage('Update AUI')
1657   - self.ontool_text = False
1658   - else:
1659   - self.SetToolNormalBitmap(ID_TEXT, self.BMP_WITHOUT_TEXT)
1660   - Publisher.sendMessage('Show text actors on viewers')
1661   - self.SetToolShortHelp(ID_TEXT,_("Hide text"))
1662   - Publisher.sendMessage('Update AUI')
1663   - self.ontool_text = True
1664   -
1665   - def OnEnableUndo(self, pubsub_evt):
1666   - value = pubsub_evt.data
1667   - if value:
1668   - self.EnableTool(wx.ID_UNDO, True)
1669   - else:
1670   - self.EnableTool(wx.ID_UNDO, False)
1671   -
1672   - def OnEnableRedo(self, pubsub_evt):
1673   - value = pubsub_evt.data
1674   - if value:
1675   - self.EnableTool(wx.ID_REDO, True)
1676   - else:
1677   - self.EnableTool(wx.ID_REDO, False)
invesalius/bkps/imagedata_utils.py.bak
... ... @@ -1,533 +0,0 @@
1   -#--------------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------------
19   -
20   -import math
21   -import os
22   -import tempfile
23   -
24   -import gdcm
25   -import numpy
26   -import vtk
27   -import vtkgdcm
28   -from wx.lib.pubsub import pub as Publisher
29   -
30   -from scipy.ndimage import shift
31   -from vtk.util import numpy_support
32   -
33   -import constants as const
34   -from data import vtk_utils
35   -import utils
36   -
37   -# TODO: Test cases which are originally in sagittal/coronal orientation
38   -# and have gantry
39   -
40   -def ResampleImage3D(imagedata, value):
41   - """
42   - Resample vtkImageData matrix.
43   - """
44   - spacing = imagedata.GetSpacing()
45   - extent = imagedata.GetExtent()
46   - size = imagedata.GetDimensions()
47   -
48   - width = float(size[0])
49   - height = float(size[1]/value)
50   -
51   - resolution = (height/(extent[1]-extent[0])+1)*spacing[1]
52   -
53   - resample = vtk.vtkImageResample()
54   - resample.SetInput(imagedata)
55   - resample.SetAxisMagnificationFactor(0, resolution)
56   - resample.SetAxisMagnificationFactor(1, resolution)
57   -
58   - return resample.GetOutput()
59   -
60   -def ResampleImage2D(imagedata, px=None, py=None, resolution_percentage = None,
61   - update_progress = None):
62   - """
63   - Resample vtkImageData matrix.
64   - """
65   -
66   - extent = imagedata.GetExtent()
67   - spacing = imagedata.GetSpacing()
68   - dimensions = imagedata.GetDimensions()
69   -
70   - if resolution_percentage:
71   - px = math.ceil(dimensions[0] * resolution_percentage)
72   - py = math.ceil(dimensions[1] * resolution_percentage)
73   -
74   - if abs(extent[1]-extent[3]) < abs(extent[3]-extent[5]):
75   - f = extent[1]
76   - elif abs(extent[1]-extent[5]) < abs(extent[1] - extent[3]):
77   - f = extent[1]
78   - elif abs(extent[3]-extent[5]) < abs(extent[1] - extent[3]):
79   - f = extent[3]
80   - else:
81   - f = extent[1]
82   -
83   - factor_x = px/float(f+1)
84   - factor_y = py/float(f+1)
85   -
86   - resample = vtk.vtkImageResample()
87   - resample.SetInput(imagedata)
88   - resample.SetAxisMagnificationFactor(0, factor_x)
89   - resample.SetAxisMagnificationFactor(1, factor_y)
90   - resample.SetOutputSpacing(spacing[0] * factor_x, spacing[1] * factor_y, spacing[2])
91   - if (update_progress):
92   - message = _("Generating multiplanar visualization...")
93   - resample.AddObserver("ProgressEvent", lambda obj,
94   - evt:update_progress(resample,message))
95   - resample.Update()
96   -
97   -
98   - return resample.GetOutput()
99   -
100   -def FixGantryTilt(matrix, spacing, tilt):
101   - """
102   - Fix gantry tilt given a vtkImageData and the tilt value. Return new
103   - vtkImageData.
104   - """
105   - angle = numpy.radians(tilt)
106   - spacing = spacing[0], spacing[1], spacing[2]
107   - gntan = math.tan(angle)
108   -
109   - for n, slice_ in enumerate(matrix):
110   - offset = gntan * n * spacing[2]
111   - matrix[n] = shift(slice_, (-offset/spacing[1], 0), cval=matrix.min())
112   -
113   -
114   -def BuildEditedImage(imagedata, points):
115   - """
116   - Editing the original image in accordance with the edit
117   - points in the editor, it is necessary to generate the
118   - vtkPolyData via vtkContourFilter
119   - """
120   - init_values = None
121   - for point in points:
122   - x, y, z = point
123   - colour = points[point]
124   - imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour)
125   - imagedata.Update()
126   -
127   - if not(init_values):
128   - xi = x
129   - xf = x
130   - yi = y
131   - yf = y
132   - zi = z
133   - zf = z
134   - init_values = 1
135   -
136   - if (xi > x):
137   - xi = x
138   - elif(xf < x):
139   - xf = x
140   -
141   - if (yi > y):
142   - yi = y
143   - elif(yf < y):
144   - yf = y
145   -
146   - if (zi > z):
147   - zi = z
148   - elif(zf < z):
149   - zf = z
150   -
151   - clip = vtk.vtkImageClip()
152   - clip.SetInput(imagedata)
153   - clip.SetOutputWholeExtent(xi, xf, yi, yf, zi, zf)
154   - clip.Update()
155   -
156   - gauss = vtk.vtkImageGaussianSmooth()
157   - gauss.SetInput(clip.GetOutput())
158   - gauss.SetRadiusFactor(0.6)
159   - gauss.Update()
160   -
161   - app = vtk.vtkImageAppend()
162   - app.PreserveExtentsOn()
163   - app.SetAppendAxis(2)
164   - app.SetInput(0, imagedata)
165   - app.SetInput(1, gauss.GetOutput())
166   - app.Update()
167   -
168   - return app.GetOutput()
169   -
170   -
171   -def Export(imagedata, filename, bin=False):
172   - writer = vtk.vtkXMLImageDataWriter()
173   - writer.SetFileName(filename)
174   - if bin:
175   - writer.SetDataModeToBinary()
176   - else:
177   - writer.SetDataModeToAscii()
178   - #writer.SetInput(imagedata)
179   - #writer.Write()
180   -
181   -def Import(filename):
182   - reader = vtk.vtkXMLImageDataReader()
183   - reader.SetFileName(filename)
184   - # TODO: Check if the code bellow is necessary
185   - reader.WholeSlicesOn()
186   - reader.Update()
187   -
188   - return reader.GetOutput()
189   -
190   -def View(imagedata):
191   - viewer = vtk.vtkImageViewer()
192   - viewer.SetInput(imagedata)
193   - viewer.SetColorWindow(200)
194   - viewer.SetColorLevel(100)
195   - viewer.Render()
196   -
197   - import time
198   - time.sleep(10)
199   -
200   -def ViewGDCM(imagedata):
201   - viewer = vtkgdcm.vtkImageColorViewer()
202   - viewer.SetInput(reader.GetOutput())
203   - viewer.SetColorWindow(500.)
204   - viewer.SetColorLevel(50.)
205   - viewer.Render()
206   -
207   - import time
208   - time.sleep(5)
209   -
210   -
211   -
212   -def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf):
213   - """
214   - Cropping the vtkImagedata according
215   - with values.
216   - """
217   - voi = vtk.vtkExtractVOI()
218   - voi.SetVOI(xi,xf,yi,yf,zi,zf)
219   - voi.SetInput(imagedata)
220   - voi.SetSampleRate(1, 1, 1)
221   - voi.Update()
222   - return voi.GetOutput()
223   -
224   -def CreateImageData(filelist, zspacing, xyspacing,size,
225   - bits, use_dcmspacing):
226   - message = _("Generating multiplanar visualization...")
227   -
228   - if not const.VTK_WARNING:
229   - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt')
230   - fow = vtk.vtkFileOutputWindow()
231   - fow.SetFileName(log_path)
232   - ow = vtk.vtkOutputWindow()
233   - ow.SetInstance(fow)
234   -
235   - x,y = size
236   - px, py = utils.predict_memory(len(filelist), x, y, bits)
237   -
238   - utils.debug("Image Resized to >>> %f x %f" % (px, py))
239   -
240   - if (x == px) and (y == py):
241   - const.REDUCE_IMAGEDATA_QUALITY = 0
242   - else:
243   - const.REDUCE_IMAGEDATA_QUALITY = 1
244   -
245   - if not(const.REDUCE_IMAGEDATA_QUALITY):
246   - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog")
247   -
248   - array = vtk.vtkStringArray()
249   - for x in xrange(len(filelist)):
250   - array.InsertValue(x,filelist[x])
251   -
252   - reader = vtkgdcm.vtkGDCMImageReader()
253   - reader.SetFileNames(array)
254   - reader.AddObserver("ProgressEvent", lambda obj,evt:
255   - update_progress(reader,message))
256   - reader.Update()
257   -
258   - # The zpacing is a DicomGroup property, so we need to set it
259   - imagedata = vtk.vtkImageData()
260   - imagedata.DeepCopy(reader.GetOutput())
261   - if (use_dcmspacing):
262   - spacing = xyspacing
263   - spacing[2] = zspacing
264   - else:
265   - spacing = imagedata.GetSpacing()
266   -
267   - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
268   - else:
269   -
270   - update_progress= vtk_utils.ShowProgress(2*len(filelist),
271   - dialog_type = "ProgressDialog")
272   -
273   - # Reformat each slice and future append them
274   - appender = vtk.vtkImageAppend()
275   - appender.SetAppendAxis(2) #Define Stack in Z
276   -
277   -
278   - # Reformat each slice
279   - for x in xrange(len(filelist)):
280   - # TODO: We need to check this automatically according
281   - # to each computer's architecture
282   - # If the resolution of the matrix is too large
283   - reader = vtkgdcm.vtkGDCMImageReader()
284   - reader.SetFileName(filelist[x])
285   - reader.AddObserver("ProgressEvent", lambda obj,evt:
286   - update_progress(reader,message))
287   - reader.Update()
288   -
289   - if (use_dcmspacing):
290   - spacing = xyspacing
291   - spacing[2] = zspacing
292   - else:
293   - spacing = reader.GetOutput().GetSpacing()
294   -
295   - tmp_image = vtk.vtkImageData()
296   - tmp_image.DeepCopy(reader.GetOutput())
297   - tmp_image.SetSpacing(spacing[0], spacing[1], zspacing)
298   - tmp_image.Update()
299   -
300   - #Resample image in x,y dimension
301   - slice_imagedata = ResampleImage2D(tmp_image, px, py, update_progress)
302   - #Stack images in Z axes
303   - appender.AddInput(slice_imagedata)
304   - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender))
305   - appender.Update()
306   -
307   - spacing = appender.GetOutput().GetSpacing()
308   -
309   - # The zpacing is a DicomGroup property, so we need to set it
310   - imagedata = vtk.vtkImageData()
311   - imagedata.DeepCopy(appender.GetOutput())
312   - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
313   -
314   - imagedata.AddObserver("ProgressEvent", lambda obj,evt:
315   - update_progress(imagedata,message))
316   - imagedata.Update()
317   -
318   - return imagedata
319   -
320   -
321   -class ImageCreator:
322   - def __init__(self):
323   - self.running = True
324   - Publisher.subscribe(self.CancelImageDataLoad, "Cancel DICOM load")
325   -
326   - def CancelImageDataLoad(self, evt_pusub):
327   - utils.debug("Canceling")
328   - self.running = False
329   -
330   - def CreateImageData(self, filelist, zspacing, size, bits):
331   - message = _("Generating multiplanar visualization...")
332   -
333   - if not const.VTK_WARNING:
334   - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt')
335   - fow = vtk.vtkFileOutputWindow()
336   - fow.SetFileName(log_path)
337   - ow = vtk.vtkOutputWindow()
338   - ow.SetInstance(fow)
339   -
340   - x,y = size
341   - px, py = utils.predict_memory(len(filelist), x, y, bits)
342   - utils.debug("Image Resized to >>> %f x %f" % (px, py))
343   -
344   - if (x == px) and (y == py):
345   - const.REDUCE_IMAGEDATA_QUALITY = 0
346   - else:
347   - const.REDUCE_IMAGEDATA_QUALITY = 1
348   -
349   - if not(const.REDUCE_IMAGEDATA_QUALITY):
350   - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog")
351   -
352   - array = vtk.vtkStringArray()
353   - for x in xrange(len(filelist)):
354   - if not self.running:
355   - return False
356   - array.InsertValue(x,filelist[x])
357   -
358   - if not self.running:
359   - return False
360   - reader = vtkgdcm.vtkGDCMImageReader()
361   - reader.SetFileNames(array)
362   - reader.AddObserver("ProgressEvent", lambda obj,evt:
363   - update_progress(reader,message))
364   - reader.Update()
365   -
366   - if not self.running:
367   - reader.AbortExecuteOn()
368   - return False
369   - # The zpacing is a DicomGroup property, so we need to set it
370   - imagedata = vtk.vtkImageData()
371   - imagedata.DeepCopy(reader.GetOutput())
372   - spacing = imagedata.GetSpacing()
373   - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
374   - else:
375   -
376   - update_progress= vtk_utils.ShowProgress(2*len(filelist),
377   - dialog_type = "ProgressDialog")
378   -
379   - # Reformat each slice and future append them
380   - appender = vtk.vtkImageAppend()
381   - appender.SetAppendAxis(2) #Define Stack in Z
382   -
383   -
384   - # Reformat each slice
385   - for x in xrange(len(filelist)):
386   - # TODO: We need to check this automatically according
387   - # to each computer's architecture
388   - # If the resolution of the matrix is too large
389   - if not self.running:
390   - return False
391   - reader = vtkgdcm.vtkGDCMImageReader()
392   - reader.SetFileName(filelist[x])
393   - reader.AddObserver("ProgressEvent", lambda obj,evt:
394   - update_progress(reader,message))
395   - reader.Update()
396   -
397   - #Resample image in x,y dimension
398   - slice_imagedata = ResampleImage2D(reader.GetOutput(), px, py, update_progress)
399   - #Stack images in Z axes
400   - appender.AddInput(slice_imagedata)
401   - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender))
402   - appender.Update()
403   -
404   - # The zpacing is a DicomGroup property, so we need to set it
405   - if not self.running:
406   - return False
407   - imagedata = vtk.vtkImageData()
408   - imagedata.DeepCopy(appender.GetOutput())
409   - spacing = imagedata.GetSpacing()
410   -
411   - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
412   -
413   - imagedata.AddObserver("ProgressEvent", lambda obj,evt:
414   - update_progress(imagedata,message))
415   - imagedata.Update()
416   -
417   - return imagedata
418   -
419   -def dcm2memmap(files, slice_size, orientation, resolution_percentage):
420   - """
421   - From a list of dicom files it creates memmap file in the temp folder and
422   - returns it and its related filename.
423   - """
424   - message = _("Generating multiplanar visualization...")
425   - update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog")
426   -
427   - temp_file = tempfile.mktemp()
428   -
429   - if orientation == 'SAGITTAL':
430   - if resolution_percentage == 1.0:
431   - shape = slice_size[0], slice_size[1], len(files)
432   - else:
433   - shape = math.ceil(slice_size[0]*resolution_percentage),\
434   - math.ceil(slice_size[1]*resolution_percentage), len(files)
435   -
436   - elif orientation == 'CORONAL':
437   - if resolution_percentage == 1.0:
438   - shape = slice_size[1], len(files), slice_size[0]
439   - else:
440   - shape = math.ceil(slice_size[1]*resolution_percentage), len(files),\
441   - math.ceil(slice_size[0]*resolution_percentage)
442   - else:
443   - if resolution_percentage == 1.0:
444   - shape = len(files), slice_size[1], slice_size[0]
445   - else:
446   - shape = len(files), math.ceil(slice_size[1]*resolution_percentage),\
447   - math.ceil(slice_size[0]*resolution_percentage)
448   -
449   - matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape)
450   - dcm_reader = vtkgdcm.vtkGDCMImageReader()
451   - cont = 0
452   - max_scalar = None
453   - min_scalar = None
454   -
455   - for n, f in enumerate(files):
456   - dcm_reader.SetFileName(f)
457   - dcm_reader.Update()
458   - image = dcm_reader.GetOutput()
459   -
460   - if resolution_percentage != 1.0:
461   - image_resized = ResampleImage2D(image, px=None, py=None,\
462   - resolution_percentage = resolution_percentage, update_progress = None)
463   -
464   - image = image_resized
465   - print ">>>>>>>>>", image.GetDimensions()
466   -
467   - min_aux, max_aux = image.GetScalarRange()
468   - if min_scalar is None or min_aux < min_scalar:
469   - min_scalar = min_aux
470   -
471   - if max_scalar is None or max_aux > max_scalar:
472   - max_scalar = max_aux
473   -
474   - array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())
475   - if orientation == 'CORONAL':
476   - array.shape = matrix.shape[0], matrix.shape[2]
477   - matrix[:, n, :] = array
478   - elif orientation == 'SAGITTAL':
479   - array.shape = matrix.shape[0], matrix.shape[1]
480   - # TODO: Verify if it's necessary to add the slices swapped only in
481   - # sagittal rmi or only in # Rasiane's case or is necessary in all
482   - # sagittal cases.
483   - matrix[:, :, n] = array
484   - else:
485   - print array.shape, matrix.shape
486   - array.shape = matrix.shape[1], matrix.shape[2]
487   - matrix[n] = array
488   - update_progress(cont,message)
489   - cont += 1
490   -
491   - matrix.flush()
492   - scalar_range = min_scalar, max_scalar
493   -
494   - return matrix, scalar_range, temp_file
495   -
496   -def analyze2mmap(analyze):
497   - data = analyze.get_data()
498   - header = analyze.get_header()
499   - temp_file = tempfile.mktemp()
500   -
501   - # Sagital
502   - if header['orient'] == 2:
503   - print "Orientation Sagital"
504   - shape = tuple([data.shape[i] for i in (1, 2, 0)])
505   - matrix = numpy.memmap(temp_file, mode='w+', dtype=data.dtype, shape=shape)
506   - for n, slice in enumerate(data):
507   - matrix[:,:, n] = slice
508   -
509   - # Coronal
510   - elif header['orient'] == 1:
511   - print "Orientation coronal"
512   - shape = tuple([data.shape[i] for i in (1, 0, 2)])
513   - matrix = numpy.memmap(temp_file, mode='w+', dtype=data.dtype, shape=shape)
514   - for n, slice in enumerate(data):
515   - matrix[:,n,:] = slice
516   -
517   - # AXIAL
518   - elif header['orient'] == 0:
519   - print "no orientation"
520   - shape = tuple([data.shape[i] for i in (0, 1, 2)])
521   - matrix = numpy.memmap(temp_file, mode='w+', dtype=data.dtype, shape=shape)
522   - for n, slice in enumerate(data):
523   - matrix[n] = slice
524   -
525   - else:
526   - print "Orientation Sagital"
527   - shape = tuple([data.shape[i] for i in (1, 2, 0)])
528   - matrix = numpy.memmap(temp_file, mode='w+', dtype=data.dtype, shape=shape)
529   - for n, slice in enumerate(data):
530   - matrix[:,:, n] = slice
531   -
532   - matrix.flush()
533   - return matrix, temp_file
invesalius/bkps/task_importer.py.bak
... ... @@ -1,271 +0,0 @@
1   -#--------------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------------
19   -import os
20   -import sys
21   -
22   -import wx
23   -import wx.lib.hyperlink as hl
24   -import wx.lib.platebtn as pbtn
25   -from wx.lib.pubsub import pub as Publisher
26   -
27   -import constants as const
28   -import gui.dialogs as dlg
29   -
30   -BTN_IMPORT_LOCAL = wx.NewId()
31   -BTN_IMPORT_PACS = wx.NewId()
32   -BTN_OPEN_PROJECT = wx.NewId()
33   -
34   -
35   -
36   -class TaskPanel(wx.Panel):
37   - def __init__(self, parent):
38   - wx.Panel.__init__(self, parent)
39   -
40   - inner_panel = InnerTaskPanel(self)
41   -
42   - sizer = wx.BoxSizer(wx.HORIZONTAL)
43   - sizer.Add(inner_panel, 1, wx.EXPAND | wx.GROW | wx.BOTTOM | wx.RIGHT |
44   - wx.LEFT, 7)
45   - sizer.Fit(self)
46   -
47   - self.SetSizer(sizer)
48   - self.Update()
49   - self.SetAutoLayout(1)
50   -
51   -class InnerTaskPanel(wx.Panel):
52   - def __init__(self, parent):
53   - wx.Panel.__init__(self, parent)
54   - self.SetBackgroundColour(wx.Colour(255,255,255))
55   - self.SetAutoLayout(1)
56   -
57   - # Counter for projects loaded in current GUI
58   - self.proj_count = 0
59   -
60   - # Floating items (to be inserted)
61   - self.float_hyper_list = []
62   -
63   - # Fixed hyperlink items
64   - tooltip = wx.ToolTip(_("Select DICOM or Analyze files to be reconstructed"))
65   - link_import_local = hl.HyperLinkCtrl(self, -1, _("Import medical images..."))
66   - link_import_local.SetUnderlines(False, False, False)
67   - link_import_local.SetColours("BLACK", "BLACK", "BLACK")
68   - link_import_local.SetToolTip(tooltip)
69   - link_import_local.AutoBrowse(False)
70   - link_import_local.UpdateLink()
71   - link_import_local.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkImport)
72   -
73   - #tooltip = wx.ToolTip("Import DICOM files from PACS server")
74   - #link_import_pacs = hl.HyperLinkCtrl(self, -1,"Load from PACS server...")
75   - #link_import_pacs.SetUnderlines(False, False, False)
76   - #link_import_pacs.SetColours("BLACK", "BLACK", "BLACK")
77   - #link_import_pacs.SetToolTip(tooltip)
78   - #link_import_pacs.AutoBrowse(False)
79   - #link_import_pacs.UpdateLink()
80   - #link_import_pacs.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkImportPACS)
81   -
82   - tooltip = wx.ToolTip(_("Open an existing InVesalius project..."))
83   - link_open_proj = hl.HyperLinkCtrl(self,-1,_("Open an existing project..."))
84   - link_open_proj.SetUnderlines(False, False, False)
85   - link_open_proj.SetColours("BLACK", "BLACK", "BLACK")
86   - link_open_proj.SetToolTip(tooltip)
87   - link_open_proj.AutoBrowse(False)
88   - link_open_proj.UpdateLink()
89   - link_open_proj.Bind(hl.EVT_HYPERLINK_LEFT, self.OnLinkOpenProject)
90   -
91   - # Image(s) for buttons
92   - BMP_IMPORT = wx.Bitmap("../icons/file_import.png", wx.BITMAP_TYPE_PNG)
93   - BMP_NET = wx.Bitmap("../icons/file_from_internet.png", wx.BITMAP_TYPE_PNG)
94   - BMP_OPEN_PROJECT = wx.Bitmap("../icons/file_open.png", wx.BITMAP_TYPE_PNG)
95   -
96   - bmp_list = [BMP_IMPORT, BMP_NET, BMP_OPEN_PROJECT]
97   - for bmp in bmp_list:
98   - bmp.SetWidth(25)
99   - bmp.SetHeight(25)
100   -
101   - # Buttons related to hyperlinks
102   - button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT
103   -
104   - #button_import_pacs = pbtn.PlateButton(self, BTN_IMPORT_PACS, "", BMP_NET,
105   - # style=button_style)
106   - button_import_local = pbtn.PlateButton(self, BTN_IMPORT_LOCAL, "",
107   - BMP_IMPORT, style=button_style)
108   - button_open_proj = pbtn.PlateButton(self, BTN_OPEN_PROJECT, "",
109   - BMP_OPEN_PROJECT, style=button_style)
110   -
111   - # When using PlaneButton, it is necessary to bind events from parent win
112   - self.Bind(wx.EVT_BUTTON, self.OnButton)
113   -
114   - # Tags and grid sizer for fixed items
115   - flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP
116   - flag_button = wx.EXPAND | wx.GROW
117   -
118   - #fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0)
119   - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=2, vgap=0)
120   - fixed_sizer.AddGrowableCol(0, 1)
121   - fixed_sizer.AddMany([ #(link_import_pacs, 1, flag_link, 3),
122   - #(button_import_pacs, 0, flag_button),
123   - (link_import_local, 1, flag_link, 3),
124   - (button_import_local, 0, flag_button),
125   - (link_open_proj, 1, flag_link, 3),
126   - (button_open_proj, 0, flag_button) ])
127   -
128   - # Add line sizers into main sizer
129   - main_sizer = wx.BoxSizer(wx.VERTICAL)
130   - main_sizer.Add(fixed_sizer, 0, wx.GROW|wx.EXPAND)
131   -
132   - # Update main sizer and panel layout
133   - self.SetSizer(main_sizer)
134   - self.Update()
135   - self.SetAutoLayout(1)
136   - self.sizer = main_sizer
137   -
138   - # Test load and unload specific projects' links
139   - self.TestLoadProjects2()
140   - #self.__bind_events()
141   -
142   - #def __bind_events(self):
143   - # Publisher.subscribe(self.OnLoadRecentProjects, "Load recent projects")
144   -
145   - #def OnLoadRecentProjects(self, pubsub_evt):
146   - # projects = pubsub_evt.data
147   - # for tuple in projects:
148   - # filename = tuple[1]
149   - # path = tuple[0]
150   - # self.LoadProject(filename, path)
151   -
152   - def TestLoadProjects2(self):
153   - import session as ses
154   - session = ses.Session()
155   - projects = session.recent_projects
156   - for tuple in projects:
157   - filename = tuple[1]
158   - path = tuple[0]
159   - self.LoadProject(filename, path)
160   -
161   -
162   - def TestLoadProjects(self):
163   - self.LoadProject("test1.inv3", "/Volumes/file/inv3")
164   - self.LoadProject("test2.inv3", "/Volumes/file/inv3")
165   - self.LoadProject("test3.inv3", "/Volumes/file/inv3")
166   -
167   - def LoadProject(self, proj_name="Unnamed", proj_dir=""):
168   - """
169   - Load into user interface name of project into import task panel.
170   - Can be called 3 times in sequence.
171   - Call UnloadProjects to empty it.
172   - """
173   - # TODO: What todo when it is called more than 3 times?
174   - # TODO: Load from config file last 3 recent projects
175   -
176   - proj_path = os.path.join(proj_dir, proj_name)
177   -
178   - if (self.proj_count < 3):
179   - self.proj_count += 1
180   -
181   - # Create name to be plot on GUI
182   - label = " "+str(self.proj_count)+". "+proj_name
183   -
184   - # Create corresponding hyperlink
185   - proj_link = hl.HyperLinkCtrl(self, -1, label)
186   - proj_link.SetUnderlines(False, False, False)
187   - proj_link.SetColours("BLACK", "BLACK", "BLACK")
188   - proj_link.AutoBrowse(False)
189   - proj_link.UpdateLink()
190   - proj_link.Bind(hl.EVT_HYPERLINK_LEFT,
191   - lambda e: self.OpenProject(proj_path))
192   -
193   - # Add to existing frame
194   - self.sizer.Add(proj_link, 1, wx.GROW | wx.EXPAND | wx.ALL, 2)
195   - self.Update()
196   -
197   - # Add hyperlink to floating hyperlinks list
198   - self.float_hyper_list.append(proj_link)
199   -
200   -
201   - def OnLinkImport(self, event):
202   - self.ImportDicom()
203   - event.Skip()
204   -
205   - def OnLinkImportPACS(self, event):
206   - self.ImportPACS()
207   - event.Skip()
208   -
209   - def OnLinkOpenProject(self, event):
210   - self.OpenProject()
211   - event.Skip()
212   -
213   -
214   - def ImportPACS(self):
215   - print "TODO: Send Signal - Import DICOM files from PACS"
216   -
217   -
218   -#######
219   - def ImportDicom(self):
220   - Publisher.sendMessage('Show import directory dialog')
221   -
222   - def OpenProject(self, path=None):
223   - if path:
224   - Publisher.sendMessage('Open recent project', path)
225   - else:
226   - Publisher.sendMessage('Show open project dialog')
227   -
228   - def SaveAsProject(self):
229   - Publisher.sendMessage('Show save dialog', True)
230   -
231   - def SaveProject(self):
232   - Publisher.sendMessage('Show save dialog', False)
233   -
234   - def CloseProject(self):
235   - Publisher.sendMessage('Close Project')
236   -#######
237   -
238   - def OnButton(self, evt):
239   - id = evt.GetId()
240   -
241   - if id == BTN_IMPORT_LOCAL:
242   - self.ImportDicom()
243   - elif id == BTN_IMPORT_PACS:
244   - self.ImportPACS()
245   - else: #elif id == BTN_OPEN_PROJECT:
246   - self.OpenProject()
247   -
248   -
249   -
250   - def UnloadProjects(self):
251   - """
252   - Unload all projects from interface into import task panel.
253   - This will be called when the current project is closed.
254   - """
255   -
256   - # Remove each project from sizer
257   - for i in xrange(0, self.proj_count):
258   - self.sizer.Remove(self.float_hyper_list[i])
259   -
260   - # Delete hyperlinks
261   - for hyper in self.float_hyper_list:
262   - hyper.Destroy()
263   - del(hyper)
264   -
265   - # Update GUI
266   - self.sizer.Layout()
267   - self.Update()
268   -
269   - # Now we set projects loaded to 0
270   - self.proj_count = 0
271   - self.float_hyper_list = []
invesalius/bkps/task_navigator_bkp.py
... ... @@ -1,450 +0,0 @@
1   -#--------------------------------------------------------------------------
2   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
3   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
4   -# Homepage: http://www.softwarepublico.gov.br
5   -# Contact: invesalius@cti.gov.br
6   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
7   -#--------------------------------------------------------------------------
8   -# Este programa e software livre; voce pode redistribui-lo e/ou
9   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
10   -# publicada pela Free Software Foundation; de acordo com a versao 2
11   -# da Licenca.
12   -#
13   -# Este programa eh distribuido na expectativa de ser util, mas SEM
14   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
15   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
16   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17   -# detalhes.
18   -#--------------------------------------------------------------------------
19   -
20   -import os
21   -import sys
22   -
23   -import serial
24   -import wx
25   -import wx.lib.hyperlink as hl
26   -import wx.lib.masked.numctrl
27   -import wx.lib.platebtn as pbtn
28   -from wx.lib.pubsub import pub as Publisher
29   -
30   -import data.bases as db
31   -import data.corregistration as dcr
32   -import project
33   -
34   -IR1 = wx.NewId()
35   -IR2 = wx.NewId()
36   -IR3 = wx.NewId()
37   -PR1 = wx.NewId()
38   -PR2 = wx.NewId()
39   -PR3 = wx.NewId()
40   -Neuronavigate = wx.NewId()
41   -Corregistration = wx.NewId()
42   -GetPoint = wx.NewId()
43   -
44   -class TaskPanel(wx.Panel):
45   - """
46   - This panel works as a "frame", drawing a white margin arround
47   - the panel that really matters (InnerTaskPanel).
48   - """
49   - def __init__(self, parent):
50   - # note: don't change this class!!!
51   - wx.Panel.__init__(self, parent)
52   -
53   - inner_panel = InnerTaskPanel(self)
54   -
55   - sizer = wx.BoxSizer(wx.HORIZONTAL)
56   - sizer.Add(inner_panel, 1, wx.EXPAND | wx.GROW | wx.BOTTOM | wx.RIGHT |
57   - wx.LEFT, 8)
58   - sizer.Fit(self)
59   -
60   - self.SetSizer(sizer)
61   - self.Update()
62   - self.SetAutoLayout(1)
63   -
64   -class InnerTaskPanel(wx.Panel):
65   -
66   - def __init__(self, parent):
67   - wx.Panel.__init__(self, parent, size=wx.Size(320,300))
68   - self.SetBackgroundColour(wx.Colour(221, 221, 221, 255))
69   - self.SetAutoLayout(1)
70   - self.__bind_events()
71   -
72   - self.aux_img_ref1 = 0
73   - self.aux_img_ref2 = 0
74   - self.aux_img_ref3 = 0
75   - self.flagpoint = 0
76   - self.aux_plh_ref1 = 1
77   - self.aux_plh_ref2 = 1
78   - self.aux_plh_ref3 = 1
79   - self.a = 0, 0, 0
80   - self.coord1a = (0, 0, 0)
81   - self.coord2a = (0, 0, 0)
82   - self.coord3a = (0, 0, 0)
83   - self.coord1b = (0, 0, 0)
84   - self.coord2b = (0, 0, 0)
85   - self.coord3b = (0, 0, 0)
86   - self.correg = None
87   -
88   -
89   - self.button_img_ref1 = wx.ToggleButton(self, IR1, label = 'TEI', size = wx.Size(30,23))
90   - self.button_img_ref1.Bind(wx.EVT_TOGGLEBUTTON, self.Img_Ref_ToggleButton1)
91   -
92   - self.button_img_ref2 = wx.ToggleButton(self, IR2, label = 'TDI', size = wx.Size(30,23))
93   - self.button_img_ref2.Bind(wx.EVT_TOGGLEBUTTON, self.Img_Ref_ToggleButton2)
94   -
95   - self.button_img_ref3 = wx.ToggleButton(self, IR3, label = 'FNI', size = wx.Size(30,23))
96   - self.button_img_ref3.Bind(wx.EVT_TOGGLEBUTTON, self.Img_Ref_ToggleButton3)
97   -
98   - self.button_plh_ref1 = wx.Button(self, PR1, label = 'TEP', size = wx.Size(30,23))
99   - self.button_plh_ref2 = wx.Button(self, PR2, label = 'TDP', size = wx.Size(30,23))
100   - self.button_plh_ref3 = wx.Button(self, PR3, label = 'FNP', size = wx.Size(30,23))
101   - self.button_crg = wx.Button(self, Corregistration, label = 'Corregistrate')
102   - self.button_getpoint = wx.Button(self, GetPoint, label = 'GP', size = wx.Size(23,23))
103   - self.Bind(wx.EVT_BUTTON, self.Buttons)
104   -
105   - self.button_neuronavigate = wx.ToggleButton(self, Neuronavigate, "Neuronavigate")
106   - self.button_neuronavigate.Bind(wx.EVT_TOGGLEBUTTON, self.Neuronavigate_ToggleButton)
107   -
108   - self.numCtrl1a = wx.lib.masked.numctrl.NumCtrl(
109   - name='numCtrl1a', parent=self, integerWidth = 4, fractionWidth = 1)
110   - self.numCtrl2a = wx.lib.masked.numctrl.NumCtrl(
111   - name='numCtrl2a', parent=self, integerWidth = 4, fractionWidth = 1)
112   - self.numCtrl3a = wx.lib.masked.numctrl.NumCtrl(
113   - name='numCtrl3a', parent=self, integerWidth = 4, fractionWidth = 1)
114   - self.numCtrl1b = wx.lib.masked.numctrl.NumCtrl(
115   - name='numCtrl1b', parent=self, integerWidth = 4, fractionWidth = 1)
116   - self.numCtrl2b = wx.lib.masked.numctrl.NumCtrl(
117   - name='numCtrl2b', parent=self, integerWidth = 4, fractionWidth = 1)
118   - self.numCtrl3b = wx.lib.masked.numctrl.NumCtrl(
119   - name='numCtrl3b', parent=self, integerWidth = 4, fractionWidth = 1)
120   - self.numCtrl1c = wx.lib.masked.numctrl.NumCtrl(
121   - name='numCtrl1c', parent=self, integerWidth = 4, fractionWidth = 1)
122   - self.numCtrl2c = wx.lib.masked.numctrl.NumCtrl(
123   - name='numCtrl2c', parent=self, integerWidth = 4, fractionWidth = 1)
124   - self.numCtrl3c = wx.lib.masked.numctrl.NumCtrl(
125   - name='numCtrl3c', parent=self, integerWidth = 4, fractionWidth = 1)
126   - self.numCtrl1d = wx.lib.masked.numctrl.NumCtrl(
127   - name='numCtrl1d', parent=self, integerWidth = 4, fractionWidth = 1)
128   - self.numCtrl2d = wx.lib.masked.numctrl.NumCtrl(
129   - name='numCtrl2d', parent=self, integerWidth = 4, fractionWidth = 1)
130   - self.numCtrl3d = wx.lib.masked.numctrl.NumCtrl(
131   - name='numCtrl3d', parent=self, integerWidth = 4, fractionWidth = 1)
132   - self.numCtrl1e = wx.lib.masked.numctrl.NumCtrl(
133   - name='numCtrl1e', parent=self, integerWidth = 4, fractionWidth = 1)
134   - self.numCtrl2e = wx.lib.masked.numctrl.NumCtrl(
135   - name='numCtrl2e', parent=self, integerWidth = 4, fractionWidth = 1)
136   - self.numCtrl3e = wx.lib.masked.numctrl.NumCtrl(
137   - name='numCtrl3e', parent=self, integerWidth = 4, fractionWidth = 1)
138   - self.numCtrl1f = wx.lib.masked.numctrl.NumCtrl(
139   - name='numCtrl1f', parent=self, integerWidth = 4, fractionWidth = 1)
140   - self.numCtrl2f = wx.lib.masked.numctrl.NumCtrl(
141   - name='numCtrl2f', parent=self, integerWidth = 4, fractionWidth = 1)
142   - self.numCtrl3f = wx.lib.masked.numctrl.NumCtrl(
143   - name='numCtrl3f', parent=self, integerWidth = 4, fractionWidth = 1)
144   - self.numCtrl1g = wx.lib.masked.numctrl.NumCtrl(
145   - name='numCtrl1g', parent=self, integerWidth = 4, fractionWidth = 1)
146   - self.numCtrl2g = wx.lib.masked.numctrl.NumCtrl(
147   - name='numCtrl2g', parent=self, integerWidth = 4, fractionWidth = 1)
148   - self.numCtrl3g = wx.lib.masked.numctrl.NumCtrl(
149   - name='numCtrl3g', parent=self, integerWidth = 4, fractionWidth = 1)
150   -
151   - RefImg_sizer1 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
152   - RefImg_sizer1.AddMany([ (self.button_img_ref1),
153   - (self.numCtrl1a),
154   - (self.numCtrl2a),
155   - (self.numCtrl3a)])
156   -
157   - RefImg_sizer2 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
158   - RefImg_sizer2.AddMany([ (self.button_img_ref2),
159   - (self.numCtrl1b),
160   - (self.numCtrl2b),
161   - (self.numCtrl3b)])
162   -
163   - RefImg_sizer3 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
164   - RefImg_sizer3.AddMany([ (self.button_img_ref3),
165   - (self.numCtrl1c),
166   - (self.numCtrl2c),
167   - (self.numCtrl3c)])
168   -
169   - RefPlh_sizer1 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
170   - RefPlh_sizer1.AddMany([ (self.button_plh_ref1, 0, wx.GROW|wx.EXPAND),
171   - (self.numCtrl1d, wx.RIGHT),
172   - (self.numCtrl2d),
173   - (self.numCtrl3d, wx.LEFT)])
174   -
175   - RefPlh_sizer2 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
176   - RefPlh_sizer2.AddMany([ (self.button_plh_ref2, 0, wx.GROW|wx.EXPAND),
177   - (self.numCtrl1e, 0, wx.RIGHT),
178   - (self.numCtrl2e),
179   - (self.numCtrl3e, 0, wx.LEFT)])
180   -
181   - RefPlh_sizer3 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
182   - RefPlh_sizer3.AddMany([ (self.button_plh_ref3, 0, wx.GROW|wx.EXPAND),
183   - (self.numCtrl1f, wx.RIGHT),
184   - (self.numCtrl2f),
185   - (self.numCtrl3f, wx.LEFT)])
186   -
187   - Buttons_sizer4 = wx.FlexGridSizer(rows=1, cols=3, hgap=5, vgap=5)
188   - Buttons_sizer4.AddMany([ (self.button_crg, wx.RIGHT),
189   - (self.button_neuronavigate, wx.LEFT)])
190   -
191   - GetPoint_sizer5 = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
192   - GetPoint_sizer5.AddMany([ (self.button_getpoint, 0, wx.GROW|wx.EXPAND),
193   - (self.numCtrl1g, wx.RIGHT),
194   - (self.numCtrl2g),
195   - (self.numCtrl3g, wx.LEFT)])
196   -
197   - text = wx.StaticText(self, -1, 'Neuronavigator')
198   -
199   - Ref_sizer = wx.FlexGridSizer(rows=9, cols=1, hgap=5, vgap=5)
200   - Ref_sizer.AddGrowableCol(0, 1)
201   - Ref_sizer.AddGrowableRow(0, 1)
202   - Ref_sizer.AddGrowableRow(1, 1)
203   - Ref_sizer.AddGrowableRow(2, 1)
204   - Ref_sizer.AddGrowableRow(3, 1)
205   - Ref_sizer.AddGrowableRow(4, 1)
206   - Ref_sizer.AddGrowableRow(5, 1)
207   - Ref_sizer.AddGrowableRow(6, 1)
208   - Ref_sizer.AddGrowableRow(7, 1)
209   - Ref_sizer.AddGrowableRow(8, 1)
210   - Ref_sizer.SetFlexibleDirection(wx.BOTH)
211   - Ref_sizer.AddMany([ (text, 0, wx.ALIGN_CENTER_HORIZONTAL),
212   - (RefImg_sizer1, 0, wx.ALIGN_CENTER_HORIZONTAL),
213   - (RefImg_sizer2, 0, wx.ALIGN_CENTER_HORIZONTAL),
214   - (RefImg_sizer3, 0, wx.ALIGN_CENTER_HORIZONTAL),
215   - (RefPlh_sizer1, 0, wx.ALIGN_CENTER_HORIZONTAL),
216   - (RefPlh_sizer2, 0, wx.ALIGN_CENTER_HORIZONTAL),
217   - (RefPlh_sizer3, 0, wx.ALIGN_CENTER_HORIZONTAL),
218   - (Buttons_sizer4, 0, wx.ALIGN_CENTER_HORIZONTAL),
219   - (GetPoint_sizer5, 0, wx.ALIGN_CENTER_HORIZONTAL)])
220   -
221   - main_sizer = wx.BoxSizer(wx.HORIZONTAL)
222   - main_sizer.Add(Ref_sizer, 1, wx.ALIGN_CENTER_HORIZONTAL, 10)
223   - self.sizer = main_sizer
224   - self.SetSizer(main_sizer)
225   - self.Fit()
226   -
227   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the image")
228   - self.button_img_ref1.SetToolTip(tooltip)
229   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the image")
230   - self.button_img_ref2.SetToolTip(tooltip)
231   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the image")
232   - self.button_img_ref3.SetToolTip(tooltip)
233   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the space")
234   - self.button_plh_ref1.SetToolTip(tooltip)
235   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the space")
236   - self.button_plh_ref2.SetToolTip(tooltip)
237   - tooltip = wx.ToolTip("Pick the coordinates x, y, z in the space")
238   - self.button_plh_ref3.SetToolTip(tooltip)
239   - tooltip = wx.ToolTip("X Coordinate")
240   - self.numCtrl1a.SetToolTip(tooltip)
241   - tooltip = wx.ToolTip("X Coordinate")
242   - self.numCtrl1b.SetToolTip(tooltip)
243   - tooltip = wx.ToolTip("X Coordinate")
244   - self.numCtrl1c.SetToolTip(tooltip)
245   - tooltip = wx.ToolTip("X Coordinate")
246   - self.numCtrl1d.SetToolTip(tooltip)
247   - tooltip = wx.ToolTip("X Coordinate")
248   - self.numCtrl1e.SetToolTip(tooltip)
249   - tooltip = wx.ToolTip("X Coordinate")
250   - self.numCtrl1f.SetToolTip(tooltip)
251   - tooltip = wx.ToolTip("X Coordinate")
252   - self.numCtrl1g.SetToolTip(tooltip)
253   - tooltip = wx.ToolTip("Y Coordinate")
254   - self.numCtrl2a.SetToolTip(tooltip)
255   - tooltip = wx.ToolTip("Y Coordinate")
256   - self.numCtrl2b.SetToolTip(tooltip)
257   - tooltip = wx.ToolTip("Y Coordinate")
258   - self.numCtrl2c.SetToolTip(tooltip)
259   - tooltip = wx.ToolTip("Y Coordinate")
260   - self.numCtrl2d.SetToolTip(tooltip)
261   - tooltip = wx.ToolTip("Y Coordinate")
262   - self.numCtrl2e.SetToolTip(tooltip)
263   - tooltip = wx.ToolTip("Y Coordinate")
264   - self.numCtrl2f.SetToolTip(tooltip)
265   - tooltip = wx.ToolTip("Y Coordinate")
266   - self.numCtrl2g.SetToolTip(tooltip)
267   - tooltip = wx.ToolTip("Z Coordinate")
268   - self.numCtrl3a.SetToolTip(tooltip)
269   - tooltip = wx.ToolTip("Z Coordinate")
270   - self.numCtrl3b.SetToolTip(tooltip)
271   - tooltip = wx.ToolTip("Z Coordinate")
272   - self.numCtrl3c.SetToolTip(tooltip)
273   - tooltip = wx.ToolTip("Z Coordinate")
274   - self.numCtrl3d.SetToolTip(tooltip)
275   - tooltip = wx.ToolTip("Z Coordinate")
276   - self.numCtrl3e.SetToolTip(tooltip)
277   - tooltip = wx.ToolTip("Z Coordinate")
278   - self.numCtrl3f.SetToolTip(tooltip)
279   - tooltip = wx.ToolTip("Z Coordinate")
280   - self.numCtrl3g.SetToolTip(tooltip)
281   - tooltip = wx.ToolTip("Corregistration of the real position with the image position")
282   - self.button_crg.SetToolTip(tooltip)
283   - tooltip = wx.ToolTip("Neuronavigation")
284   - self.button_neuronavigate.SetToolTip(tooltip)
285   - tooltip = wx.ToolTip("Get Cross Center Coordinates")
286   - self.button_getpoint.SetToolTip(tooltip)
287   -
288   - def __bind_events(self):
289   - Publisher.subscribe(self.__update_points_img, 'Update cross position')
290   - Publisher.subscribe(self.__update_points_plh, 'Update plh position')
291   -
292   - def __update_points_img(self, pubsub_evt):
293   - x, y, z = pubsub_evt.data[1]
294   - self.a = x, y, z
295   - if self.aux_img_ref1 == 0:
296   - self.numCtrl1a.SetValue(x)
297   - self.numCtrl2a.SetValue(y)
298   - self.numCtrl3a.SetValue(z)
299   - if self.aux_img_ref2 == 0:
300   - self.numCtrl1b.SetValue(x)
301   - self.numCtrl2b.SetValue(y)
302   - self.numCtrl3b.SetValue(z)
303   - if self.aux_img_ref3 == 0:
304   - self.numCtrl1c.SetValue(x)
305   - self.numCtrl2c.SetValue(y)
306   - self.numCtrl3c.SetValue(z)
307   -
308   -
309   - def __update_points_plh(self, pubsub_evt):
310   - coord = pubsub_evt.data
311   - if self.aux_plh_ref1 == 0:
312   - self.numCtrl1d.SetValue(coord[0])
313   - self.numCtrl2d.SetValue(coord[1])
314   - self.numCtrl3d.SetValue(coord[2])
315   - self.aux_plh_ref1 = 1
316   - if self.aux_plh_ref2 == 0:
317   - self.numCtrl1e.SetValue(coord[0])
318   - self.numCtrl2e.SetValue(coord[1])
319   - self.numCtrl3e.SetValue(coord[2])
320   - self.aux_plh_ref2 = 1
321   - if self.aux_plh_ref3 == 0:
322   - self.numCtrl1f.SetValue(coord[0])
323   - self.numCtrl2f.SetValue(coord[1])
324   - self.numCtrl3f.SetValue(coord[2])
325   - self.aux_plh_ref3 = 1
326   -
327   - def Buttons(self, evt):
328   - id = evt.GetId()
329   - x, y, z = self.a
330   - if id == PR1:
331   - self.aux_plh_ref1 = 0
332   - self.coord1b = self.Coordinates()
333   - coord = self.coord1b
334   - elif id == PR2:
335   - self.aux_plh_ref2 = 0
336   - self.coord2b = self.Coordinates()
337   - coord = self.coord2b
338   - elif id == PR3:
339   - self.aux_plh_ref3 = 0
340   - self.coord3b = self.Coordinates()
341   - coord = self.coord3b
342   - elif id == GetPoint:
343   - x, y, z = self.a
344   - self.numCtrl1g.SetValue(x)
345   - self.numCtrl2g.SetValue(y)
346   - self.numCtrl3g.SetValue(z)
347   - info = self.a, self.flagpoint
348   - self.SaveCoordinates(info)
349   - self.flagpoint = 1
350   - elif id == Corregistration and self.aux_img_ref1 == 1 and self.aux_img_ref2 == 1 and self.aux_img_ref3 == 1:
351   - print "Coordenadas Imagem: ", self.coord1a, self.coord2a, self.coord3a
352   - print "Coordenadas Polhemus: ", self.coord1b, self.coord2b, self.coord3b
353   -
354   - self.M, self.q1, self.Minv = db.Bases(self.coord1a, self.coord2a, self.coord3a).Basecreation()
355   - self.N, self.q2, self.Ninv = db.Bases(self.coord1b, self.coord2b, self.coord3b).Basecreation()
356   -
357   - if self.aux_plh_ref1 == 0 or self.aux_plh_ref2 == 0 or self.aux_plh_ref3 == 0:
358   - Publisher.sendMessage('Update plh position', coord)
359   -
360   - def Coordinates(self):
361   - #Get Polhemus points for base creation
362   - ser = serial.Serial(0)
363   - ser.write("Y")
364   - ser.write("P")
365   - str = ser.readline()
366   - ser.write("Y")
367   - str = str.replace("\r\n","")
368   - str = str.replace("-"," -")
369   - aostr = [s for s in str.split()]
370   - #aoflt -> 0:letter 1:x 2:y 3:z
371   - aoflt = [float(aostr[1]), float(aostr[2]), float(aostr[3]),
372   - float(aostr[4]), float(aostr[5]), float(aostr[6])]
373   - ser.close()
374   - #Unit change: inches to millimeters
375   - x = 25.4
376   - y = 25.4
377   - z = -25.4
378   -
379   - coord = (aoflt[0]*x, aoflt[1]*y, aoflt[2]*z)
380   - return coord
381   -
382   - def Img_Ref_ToggleButton1(self, evt):
383   - id = evt.GetId()
384   - flag1 = self.button_img_ref1.GetValue()
385   - x, y, z = self.a
386   - if flag1 == True:
387   - self.coord1a = x, y, z
388   - self.aux_img_ref1 = 1
389   - elif flag1 == False:
390   - self.aux_img_ref1 = 0
391   - self.coord1a = (0, 0, 0)
392   - self.numCtrl1a.SetValue(x)
393   - self.numCtrl2a.SetValue(y)
394   - self.numCtrl3a.SetValue(z)
395   -
396   - def Img_Ref_ToggleButton2(self, evt):
397   - id = evt.GetId()
398   - flag2 = self.button_img_ref2.GetValue()
399   - x, y, z = self.a
400   - if flag2 == True:
401   - self.coord2a = x, y, z
402   - self.aux_img_ref2 = 1
403   - elif flag2 == False:
404   - self.aux_img_ref2 = 0
405   - self.coord2a = (0, 0, 0)
406   - self.numCtrl1b.SetValue(x)
407   - self.numCtrl2b.SetValue(y)
408   - self.numCtrl3b.SetValue(z)
409   -
410   - def Img_Ref_ToggleButton3(self, evt):
411   - id = evt.GetId()
412   - flag3 = self.button_img_ref3.GetValue()
413   - x, y, z = self.a
414   - if flag3 == True:
415   - self.coord3a = x, y, z
416   - self.aux_img_ref3 = 1
417   - elif flag3 == False:
418   - self.aux_img_ref3 = 0
419   - self.coord3a = (0, 0, 0)
420   - self.numCtrl1c.SetValue(x)
421   - self.numCtrl2c.SetValue(y)
422   - self.numCtrl3c.SetValue(z)
423   -
424   - def Neuronavigate_ToggleButton(self, evt):
425   - id = evt.GetId()
426   - flag4 = self.button_neuronavigate.GetValue()
427   - bases = self.Minv, self.N, self.q1, self.q2
428   - if flag4 == True:
429   - self.correg = dcr.Corregistration(bases, flag4)
430   - elif flag4 == False:
431   - self.correg.stop()
432   -
433   - def SaveCoordinates(self, info):
434   - #Create a file and write the points given by getpoint's button
435   - x, y, z = info[0]
436   - flag = info[1]
437   -
438   - if flag == 0:
439   - text_file = open("points.txt", "w")
440   - line = str('%.2f' %x) + "\t" + str('%.2f' %y) + "\t" + str('%.2f' %z) + "\n"
441   - text_file.writelines(line)
442   - text_file.close()
443   - else:
444   - text_file = open("points.txt", "r")
445   - filedata = text_file.read()
446   - line = filedata + str('%.2f' %x) + "\t" + str('%.2f' %y) + "\t" + str('%.2f' %z) + "\n"
447   - text_file = open("points.txt", "w")
448   - text_file.write(line)
449   - text_file.close()
450   -
invesalius/bkps/viewer_slice.py.bak
... ... @@ -1,1395 +0,0 @@
1   -#!/usr/bin/env python
2   -# -*- coding: utf-8 -*-
3   -#--------------------------------------------------------------------------
4   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
5   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
6   -# Homepage: http://www.softwarepublico.gov.br
7   -# Contact: invesalius@cti.gov.br
8   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
9   -#--------------------------------------------------------------------------
10   -# Este programa e software livre; voce pode redistribui-lo e/ou
11   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
12   -# publicada pela Free Software Foundation; de acordo com a versao 2
13   -# da Licenca.
14   -#
15   -# Este programa eh distribuido na expectativa de ser util, mas SEM
16   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
17   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
18   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
19   -# detalhes.
20   -#--------------------------------------------------------------------------
21   -
22   -import itertools
23   -import tempfile
24   -
25   -import numpy
26   -
27   -import vtk
28   -from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
29   -
30   -import styles
31   -
32   -import wx
33   -from wx.lib.pubsub import pub as Publisher
34   -
35   -try:
36   - from agw import floatspin as FS
37   -except ImportError: # if it's not there locally, try the wxPython lib.
38   - import wx.lib.agw.floatspin as FS
39   -
40   -import constants as const
41   -import cursor_actors as ca
42   -import data.slice_ as sl
43   -import data.vtk_utils as vtku
44   -import project
45   -import slice_data as sd
46   -import utils
47   -
48   -from data import measures
49   -
50   -ID_TO_TOOL_ITEM = {}
51   -STR_WL = "WL: %d WW: %d"
52   -
53   -ORIENTATIONS = {
54   - "AXIAL": const.AXIAL,
55   - "CORONAL": const.CORONAL,
56   - "SAGITAL": const.SAGITAL,
57   - }
58   -
59   -
60   -class ContourMIPConfig(wx.Panel):
61   - def __init__(self, prnt, orientation):
62   - wx.Panel.__init__(self, prnt)
63   - self.mip_size_spin = wx.SpinCtrl(self, -1, min=1, max=240,
64   - initial=const.PROJECTION_MIP_SIZE)
65   - self.mip_size_spin.SetToolTip(wx.ToolTip(_("Number of slices used to compound the visualization.")))
66   - w, h = self.mip_size_spin.GetTextExtent('M')
67   - self.mip_size_spin.SetMinSize((5 * w + 10, -1))
68   - self.mip_size_spin.SetMaxSize((5 * w + 10, -1))
69   -
70   - self.border_spin = FS.FloatSpin(self, -1, min_val=0, max_val=10,
71   - increment=0.1,
72   - value=const.PROJECTION_BORDER_SIZE,
73   - digits=1, agwStyle=FS.FS_LEFT)
74   - self.border_spin.SetToolTip(wx.ToolTip(_("Controls the sharpness of the"
75   - " contour. The greater the"
76   - " value, the sharper the"
77   - " contour.")))
78   - w, h = self.border_spin.GetTextExtent('M')
79   - self.border_spin.SetMinSize((5 * w + 10, -1))
80   - self.border_spin.SetMaxSize((5 * w + 10, -1))
81   -
82   - self.inverted = wx.CheckBox(self, -1, _("Inverted order"))
83   - self.inverted.SetToolTip(wx.ToolTip(_("If checked, the slices are"
84   - " traversed in descending"
85   - " order to compound the"
86   - " visualization instead of"
87   - " ascending order.")))
88   -
89   - txt_mip_size = wx.StaticText(self, -1, _("Number of slices"), style=wx.ALIGN_CENTER_HORIZONTAL)
90   - self.txt_mip_border = wx.StaticText(self, -1, _("Sharpness"))
91   -
92   - sizer = wx.BoxSizer(wx.HORIZONTAL)
93   - sizer.Add(txt_mip_size, 0, wx.EXPAND | wx.ALL, 2)
94   - sizer.Add(self.mip_size_spin, 0, wx.EXPAND)
95   - sizer.AddSpacer((10, 0))
96   - sizer.Add(self.txt_mip_border, 0, wx.EXPAND | wx.ALL, 2)
97   - sizer.Add(self.border_spin, 0, wx.EXPAND)
98   - sizer.AddSpacer((10, 0))
99   - sizer.Add(self.inverted, 0, wx.EXPAND)
100   - self.SetSizer(sizer)
101   - sizer.Fit(self)
102   -
103   - self.Layout()
104   - self.Update()
105   - self.SetAutoLayout(1)
106   -
107   - self.orientation = orientation
108   -
109   - self.mip_size_spin.Bind(wx.EVT_SPINCTRL, self.OnSetMIPSize)
110   - self.border_spin.Bind(wx.EVT_SPINCTRL, self.OnSetMIPBorder)
111   - self.inverted.Bind(wx.EVT_CHECKBOX, self.OnCheckInverted)
112   -
113   - Publisher.subscribe(self._set_projection_type, 'Set projection type')
114   -
115   - def OnSetMIPSize(self, evt):
116   - val = self.mip_size_spin.GetValue()
117   - Publisher.sendMessage('Set MIP size %s' % self.orientation, val)
118   -
119   - def OnSetMIPBorder(self, evt):
120   - val = self.border_spin.GetValue()
121   - Publisher.sendMessage('Set MIP border %s' % self.orientation, val)
122   -
123   - def OnCheckInverted(self, evt):
124   - val = self.inverted.GetValue()
125   - Publisher.sendMessage('Set MIP Invert %s' % self.orientation, val)
126   -
127   - def _set_projection_type(self, pubsub_evt):
128   - tprojection = pubsub_evt.data
129   -
130   - if tprojection in (const.PROJECTION_MIDA,
131   - const.PROJECTION_CONTOUR_MIDA):
132   - self.inverted.Enable()
133   - else:
134   - self.inverted.Disable()
135   -
136   - if tprojection in (const.PROJECTION_CONTOUR_MIP,
137   - const.PROJECTION_CONTOUR_MIDA):
138   - self.border_spin.Enable()
139   - self.txt_mip_border.Enable()
140   - else:
141   - self.border_spin.Disable()
142   - self.txt_mip_border.Disable()
143   -
144   -
145   -
146   -class Viewer(wx.Panel):
147   -
148   - def __init__(self, prnt, orientation='AXIAL'):
149   - wx.Panel.__init__(self, prnt, size=wx.Size(320, 300))
150   -
151   - #colour = [255*c for c in const.ORIENTATION_COLOUR[orientation]]
152   - #self.SetBackgroundColour(colour)
153   -
154   - # Interactor additional style
155   - #self.modes = []#['DEFAULT']
156   - self.left_pressed = 0
157   - self.right_pressed = 0
158   -
159   - self._number_slices = const.PROJECTION_MIP_SIZE
160   - self._mip_inverted = False
161   -
162   - self.spined_image = False #Use to control to spin
163   - self.paned_image = False
164   -
165   - self.style = None
166   - self.last_position_mouse_move = ()
167   - self.state = const.STATE_DEFAULT
168   -
169   - self.overwrite_mask = False
170   -
171   - # All renderers and image actors in this viewer
172   - self.slice_data_list = []
173   - self.slice_data = None
174   - # The layout from slice_data, the first is number of cols, the second
175   - # is the number of rows
176   - self.layout = (1, 1)
177   - self.orientation_texts = []
178   -
179   - self.measures = []
180   - self.actors_by_slice_number = {}
181   - self.renderers_by_slice_number = {}
182   -
183   - self.orientation = orientation
184   - self.slice_number = 0
185   -
186   - self.__init_gui()
187   -
188   - self._brush_cursor_op = const.DEFAULT_BRUSH_OP
189   - self._brush_cursor_size = const.BRUSH_SIZE
190   - self._brush_cursor_colour = const.BRUSH_COLOUR
191   - self._brush_cursor_type = const.DEFAULT_BRUSH_OP
192   - self.cursor = None
193   - self.wl_text = None
194   - self.on_wl = False
195   - self.on_text = False
196   - # VTK pipeline and actors
197   - self.__config_interactor()
198   - self.cross_actor = vtk.vtkActor()
199   -
200   - self.__bind_events()
201   - self.__bind_events_wx()
202   -
203   - self._warped = False
204   - self._flush_buffer = False
205   -
206   - def __init_gui(self):
207   - self.interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize())
208   -
209   - scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
210   - self.scroll = scroll
211   -
212   - self.mip_ctrls = ContourMIPConfig(self, self.orientation)
213   - self.mip_ctrls.Hide()
214   -
215   - sizer = wx.BoxSizer(wx.HORIZONTAL)
216   - sizer.Add(self.interactor, 1, wx.EXPAND|wx.GROW)
217   - sizer.Add(scroll, 0, wx.EXPAND|wx.GROW)
218   -
219   - background_sizer = wx.BoxSizer(wx.VERTICAL)
220   - background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2)
221   - #background_sizer.Add(self.mip_ctrls, 0, wx.EXPAND|wx.GROW|wx.ALL, 2)
222   - self.SetSizer(background_sizer)
223   - background_sizer.Fit(self)
224   -
225   - self.Layout()
226   - self.Update()
227   - self.SetAutoLayout(1)
228   -
229   - self.pick = vtk.vtkWorldPointPicker()
230   - self.interactor.SetPicker(self.pick)
231   -
232   - def OnContextMenu(self, evt):
233   - self.right_pressed = 0
234   - if (self.last_position_mouse_move ==\
235   - self.interactor.GetLastEventPosition()):
236   - self.menu.caller = self
237   - self.PopupMenu(self.menu)
238   - evt.Skip()
239   -
240   - def SetPopupMenu(self, menu):
241   - self.menu = menu
242   -
243   - def SetLayout(self, layout):
244   - self.layout = layout
245   - if (layout == (1,1)) and self.on_text:
246   - self.ShowTextActors()
247   - else:
248   - self.HideTextActors(change_status=False)
249   -
250   - slice_ = sl.Slice()
251   - self.LoadRenderers(slice_.GetOutput())
252   - self.__configure_renderers()
253   - self.__configure_scroll()
254   -
255   - def HideTextActors(self, change_status=True):
256   - if self.wl_text:
257   - self.wl_text.Hide()
258   - [t.Hide() for t in self.orientation_texts]
259   - self.interactor.Render()
260   - if change_status:
261   - self.on_text = False
262   -
263   - def ShowTextActors(self):
264   - if self.on_wl and self.wl_text:
265   - self.wl_text.Show()
266   - [t.Show() for t in self.orientation_texts]
267   - self.Update()
268   - self.interactor.Render()
269   - self.on_text = True
270   -
271   - def __set_layout(self, pubsub_evt):
272   - layout = pubsub_evt.data
273   - self.SetLayout(layout)
274   -
275   - def __config_interactor(self):
276   - style = vtk.vtkInteractorStyleImage()
277   -
278   - interactor = self.interactor
279   - interactor.SetInteractorStyle(style)
280   -
281   - def SetInteractorStyle(self, state):
282   - cleanup = getattr(self.style, 'CleanUp', None)
283   - if cleanup:
284   - self.style.CleanUp()
285   -
286   - del self.style
287   -
288   - style = styles.get_style(state)(self)
289   -
290   - setup = getattr(style, 'SetUp', None)
291   - if setup:
292   - style.SetUp()
293   -
294   - self.style = style
295   - self.interactor.SetInteractorStyle(style)
296   - self.interactor.Render()
297   -
298   - self.state = state
299   -
300   - def UpdateWindowLevelValue(self, pubsub_evt):
301   - window, level = pubsub_evt.data
302   - self.acum_achange_window, self.acum_achange_level = (window, level)
303   - self.SetWLText(window, level)
304   -
305   - slc = sl.Slice()
306   - slc._update_wwwl_widget_nodes(window, level)
307   -
308   - Publisher.sendMessage('Update all slice')
309   - Publisher.sendMessage('Update clut imagedata widget')
310   -
311   - def UpdateWindowLevelText(self, pubsub_evt):
312   - window, level = pubsub_evt.data
313   - self.acum_achange_window, self.acum_achange_level = (window, level)
314   - self.SetWLText(window, level)
315   - self.interactor.Render()
316   -
317   - def OnClutChange(self, evt):
318   - Publisher.sendMessage('Change colour table from background image from widget',
319   - evt.GetNodes())
320   - slc = sl.Slice()
321   - Publisher.sendMessage('Update window level value',
322   - (slc.window_width, slc.window_level))
323   -
324   - def SetWLText(self, window_width, window_level):
325   - value = STR_WL%(window_level, window_width)
326   - if (self.wl_text):
327   - self.wl_text.SetValue(value)
328   - #self.interactor.Render()
329   -
330   - def EnableText(self):
331   - if not (self.wl_text):
332   - proj = project.Project()
333   - colour = const.ORIENTATION_COLOUR[self.orientation]
334   -
335   - # Window & Level text
336   - self.wl_text = vtku.Text()
337   - self.SetWLText(proj.level, proj.window)
338   - # Orientation text
339   - if self.orientation == 'AXIAL':
340   - values = [_('R'), _('L'), _('A'), _('P')]
341   - elif self.orientation == 'SAGITAL':
342   - values = [_('P'), _('A'), _('T'), _('B')]
343   - else:
344   - values = [_('R'), _('L'), _('T'), _('B')]
345   -
346   - left_text = self.left_text = vtku.TextZero()
347   - left_text.ShadowOff()
348   - left_text.SetColour(colour)
349   - left_text.SetPosition(const.TEXT_POS_VCENTRE_LEFT)
350   - left_text.SetVerticalJustificationToCentered()
351   - left_text.SetValue(values[0])
352   -
353   - right_text = self.right_text = vtku.TextZero()
354   - right_text.ShadowOff()
355   - right_text.SetColour(colour)
356   - right_text.SetPosition(const.TEXT_POS_VCENTRE_RIGHT_ZERO)
357   - right_text.SetVerticalJustificationToCentered()
358   - right_text.SetJustificationToRight()
359   - right_text.SetValue(values[1])
360   -
361   - up_text = self.up_text = vtku.TextZero()
362   - up_text.ShadowOff()
363   - up_text.SetColour(colour)
364   - up_text.SetPosition(const.TEXT_POS_HCENTRE_UP)
365   - up_text.SetJustificationToCentered()
366   - up_text.SetValue(values[2])
367   -
368   - down_text = self.down_text = vtku.TextZero()
369   - down_text.ShadowOff()
370   - down_text.SetColour(colour)
371   - down_text.SetPosition(const.TEXT_POS_HCENTRE_DOWN_ZERO)
372   - down_text.SetJustificationToCentered()
373   - down_text.SetVerticalJustificationToBottom()
374   - down_text.SetValue(values[3])
375   -
376   - self.orientation_texts = [left_text, right_text, up_text,
377   - down_text]
378   -
379   -
380   - self.slice_data.renderer.AddActor(self.wl_text.actor)
381   - self.slice_data.renderer.AddActor(left_text.actor)
382   - self.slice_data.renderer.AddActor(right_text.actor)
383   - self.slice_data.renderer.AddActor(up_text.actor)
384   - self.slice_data.renderer.AddActor(down_text.actor)
385   -
386   - def RenderTextDirection(self, directions):
387   - # Values are on ccw order, starting from the top:
388   - self.up_text.SetValue(directions[0])
389   - self.left_text.SetValue(directions[1])
390   - self.down_text.SetValue(directions[2])
391   - self.right_text.SetValue(directions[3])
392   - self.interactor.Render()
393   -
394   - def ResetTextDirection(self, cam):
395   - # Values are on ccw order, starting from the top:
396   - if self.orientation == 'AXIAL':
397   - values = [_("A"), _("R"), _("P"), _("L")]
398   - elif self.orientation == 'CORONAL':
399   - values = [_("T"), _("R"), _("B"), _("L")]
400   - else: # 'SAGITAL':
401   - values = [_("T"), _("P"), _("B"), _("A")]
402   -
403   - self.RenderTextDirection(values)
404   - self.interactor.Render()
405   -
406   - def UpdateTextDirection(self, cam):
407   - croll = cam.GetRoll()
408   - if (self.orientation == 'AXIAL'):
409   -
410   - if (croll >= -2 and croll <= 1):
411   - self.RenderTextDirection([_("A"), _("R"), _("P"), _("L")])
412   -
413   - elif(croll > 1 and croll <= 44):
414   - self.RenderTextDirection([_("AL"), _("RA"), _("PR"), _("LP")])
415   -
416   - elif(croll > 44 and croll <= 88):
417   - self.RenderTextDirection([_("LA"), _("AR"), _("RP"), _("PL")])
418   -
419   - elif(croll > 89 and croll <= 91):
420   - self.RenderTextDirection([_("L"), _("A"), _("R"), _("P")])
421   -
422   - elif(croll > 91 and croll <= 135):
423   - self.RenderTextDirection([_("LP"), _("AL"), _("RA"), _("PR")])
424   -
425   - elif(croll > 135 and croll <= 177):
426   - self.RenderTextDirection([_("PL"), _("LA"), _("AR"), _("RP")])
427   -
428   - elif(croll >= -180 and croll <= -178) or (croll < 180 and croll > 177):
429   - self.RenderTextDirection([_("P"), _("L"), _("A"), _("R")])
430   -
431   - elif(croll >= -177 and croll <= -133):
432   - self.RenderTextDirection([_("PR"), _("LP"), _("AL"), _("RA")])
433   -
434   - elif(croll >= -132 and croll <= -101):
435   - self.RenderTextDirection([_("RP"), _("PL"), _("LA"), _("AR")])
436   -
437   - elif(croll >= -101 and croll <= -87):
438   - self.RenderTextDirection([_("R"), _("P"), _("L"), _("A")])
439   -
440   - elif(croll >= -86 and croll <= -42):
441   - self.RenderTextDirection([_("RA"), _("PR"), _("LP"), _("AL")])
442   -
443   - elif(croll >= -41 and croll <= -2):
444   - self.RenderTextDirection([_("AR"), _("RP"), _("PL"), _("LA")])
445   -
446   - elif(self.orientation == "CORONAL"):
447   -
448   - if (croll >= -2 and croll <= 1):
449   - self.RenderTextDirection([_("T"), _("R"), _("B"), _("L")])
450   -
451   - elif(croll > 1 and croll <= 44):
452   - self.RenderTextDirection([_("TL"), _("RT"), _("BR"), _("LB")])
453   -
454   - elif(croll > 44 and croll <= 88):
455   - self.RenderTextDirection([_("LT"), _("TR"), _("RB"), _("BL")])
456   -
457   - elif(croll > 89 and croll <= 91):
458   - self.RenderTextDirection([_("L"), _("T"), _("R"), _("B")])
459   -
460   - elif(croll > 91 and croll <= 135):
461   - self.RenderTextDirection([_("LB"), _("TL"), _("RT"), _("BR")])
462   -
463   - elif(croll > 135 and croll <= 177):
464   - self.RenderTextDirection([_("BL"), _("LT"), _("TR"), _("RB")])
465   -
466   - elif(croll >= -180 and croll <= -178) or (croll < 180 and croll > 177):
467   - self.RenderTextDirection([_("B"), _("L"), _("T"), _("R")])
468   -
469   - elif(croll >= -177 and croll <= -133):
470   - self.RenderTextDirection([_("BR"), _("LB"), _("TL"), _("RT")])
471   -
472   - elif(croll >= -132 and croll <= -101):
473   - self.RenderTextDirection([_("RB"), _("BL"), _("LT"), _("TR")])
474   -
475   - elif(croll >= -101 and croll <= -87):
476   - self.RenderTextDirection([_("R"), _("B"), _("L"), _("T")])
477   -
478   - elif(croll >= -86 and croll <= -42):
479   - self.RenderTextDirection([_("RT"), _("BR"), _("LB"), _("TL")])
480   -
481   - elif(croll >= -41 and croll <= -2):
482   - self.RenderTextDirection([_("TR"), _("RB"), _("BL"), _("LT")])
483   -
484   - elif(self.orientation == "SAGITAL"):
485   -
486   - if(croll >= -101 and croll <= -87):
487   - self.RenderTextDirection([_("T"), _("P"), _("B"), _("A")])
488   -
489   - elif(croll >= -86 and croll <= -42):
490   - self.RenderTextDirection([_("TA"), _("PT"), _("BP"), _("AB")])
491   -
492   - elif(croll >= -41 and croll <= -2):
493   - self.RenderTextDirection([_("AT"), _("TP"), _("PB"), _("BA")])
494   -
495   - elif (croll >= -2 and croll <= 1):
496   - self.RenderTextDirection([_("A"), _("T"), _("P"), _("B")])
497   -
498   - elif(croll > 1 and croll <= 44):
499   - self.RenderTextDirection([_("AB"), _("TA"), _("PT"), _("BP")])
500   -
501   - elif(croll > 44 and croll <= 88):
502   - self.RenderTextDirection([_("BA"), _("AT"), _("TP"), _("PB")])
503   -
504   - elif(croll > 89 and croll <= 91):
505   - self.RenderTextDirection([_("B"), _("A"), _("T"), _("P")])
506   -
507   - elif(croll > 91 and croll <= 135):
508   - self.RenderTextDirection([_("BP"), _("AB"), _("TA"), _("PT")])
509   -
510   - elif(croll > 135 and croll <= 177):
511   - self.RenderTextDirection([_("PB"), _("BA"), _("AT"), _("TP")])
512   -
513   - elif(croll >= -180 and croll <= -178) or (croll < 180 and croll > 177):
514   - self.RenderTextDirection([_("P"), _("B"), _("A"), _("T")])
515   -
516   - elif(croll >= -177 and croll <= -133):
517   - self.RenderTextDirection([_("PT"), _("BP"), _("AB"), _("TA")])
518   -
519   - elif(croll >= -132 and croll <= -101):
520   - self.RenderTextDirection([_("TP"), _("PB"), _("BA"), _("AT")])
521   -
522   -
523   - def Reposition(self, slice_data):
524   - """
525   - Based on code of method Zoom in the
526   - vtkInteractorStyleRubberBandZoom, the of
527   - vtk 5.4.3
528   - """
529   - ren = slice_data.renderer
530   - size = ren.GetSize()
531   -
532   - ren.ResetCamera()
533   - ren.GetActiveCamera().Zoom(1.0)
534   - self.interactor.Render()
535   -
536   - def ChangeBrushSize(self, pubsub_evt):
537   - size = pubsub_evt.data
538   - self._brush_cursor_size = size
539   - #for slice_data in self.slice_data_list:
540   - self.slice_data.cursor.SetSize(size)
541   -
542   - def ChangeBrushColour(self, pubsub_evt):
543   - vtk_colour = pubsub_evt.data[3]
544   - self._brush_cursor_colour = vtk_colour
545   - if (self.cursor):
546   - for slice_data in self.slice_data_list:
547   - slice_data.cursor.SetColour(vtk_colour)
548   -
549   - def SetBrushColour(self, pubsub_evt):
550   - colour_wx = pubsub_evt.data
551   - colour_vtk = [colour/float(255) for colour in colour_wx]
552   - self._brush_cursor_colour = colour_vtk
553   - if self.slice_data.cursor:
554   - self.slice_data.cursor.SetColour(colour_vtk)
555   -
556   - def ChangeBrushActor(self, pubsub_evt):
557   - brush_type = pubsub_evt.data
558   - slice_data = self.slice_data
559   - self._brush_cursor_type = brush_type
560   -
561   - if brush_type == const.BRUSH_SQUARE:
562   - cursor = ca.CursorRectangle()
563   - elif brush_type == const.BRUSH_CIRCLE:
564   - cursor = ca.CursorCircle()
565   -
566   - cursor.SetOrientation(self.orientation)
567   - coordinates = {"SAGITAL": [slice_data.number, 0, 0],
568   - "CORONAL": [0, slice_data.number, 0],
569   - "AXIAL": [0, 0, slice_data.number]}
570   - cursor.SetPosition(coordinates[self.orientation])
571   - cursor.SetSpacing(self.slice_.spacing)
572   - cursor.SetColour(self._brush_cursor_colour)
573   - cursor.SetSize(self._brush_cursor_size)
574   - slice_data.SetCursor(cursor)
575   - self.interactor.Render()
576   -
577   - def Navigation(self, pubsub_evt):
578   - # Get point from base change
579   - x, y, z = pubsub_evt.data
580   - coord_cross = x, y, z
581   - position = self.slice_data.actor.GetInput().FindPoint(x, y, z)
582   - coord_cross = self.slice_data.actor.GetInput().GetPoint(position)
583   - coord = self.calcultate_scroll_position(position)
584   -
585   -# this is the code written in the invesalius_navigator 05/02/2015
586   -# with navigation working
587   -# coord_cross = pubsub_evt.data
588   -# mx, my = self.calculate_matrix_position(coord_cross)
589   -#
590   -# if self.orientation == 'AXIAL':
591   -# x = my
592   -# y = mx
593   -# z = self.slice_data.number
594   -#
595   -# elif self.orientation == 'CORONAL':
596   -# x = my
597   -# y = self.slice_data.number
598   -# z = mx
599   -#
600   -# elif self.orientation == 'SAGITAL':
601   -# x = self.slice_data.number
602   -# y = my
603   -# z = mx
604   -#
605   -# coord = x, y, z
606   -
607   - Publisher.sendMessage('Update cross position', coord_cross)
608   -
609   - self.ScrollSlice(coord)
610   - self.interactor.Render()
611   -
612   - def ScrollSlice(self, coord):
613   - if self.orientation == "AXIAL":
614   - Publisher.sendMessage(('Set scroll position', 'SAGITAL'),
615   - coord[0])
616   - Publisher.sendMessage(('Set scroll position', 'CORONAL'),
617   - coord[1])
618   - elif self.orientation == "SAGITAL":
619   - Publisher.sendMessage(('Set scroll position', 'AXIAL'),
620   - coord[2])
621   - Publisher.sendMessage(('Set scroll position', 'CORONAL'),
622   - coord[1])
623   - elif self.orientation == "CORONAL":
624   - Publisher.sendMessage(('Set scroll position', 'AXIAL'),
625   - coord[2])
626   - Publisher.sendMessage(('Set scroll position', 'SAGITAL'),
627   - coord[0])
628   -
629   - def get_slice_data(self, render):
630   - #for slice_data in self.slice_data_list:
631   - #if slice_data.renderer is render:
632   - #return slice_data
633   - # WARN: Return the only slice_data used in this slice_viewer.
634   - return self.slice_data
635   -
636   - def calcultate_scroll_position(self, position):
637   - # Based in the given coord (x, y, z), returns a list with the scroll positions for each
638   - # orientation, being the first position the sagital, second the coronal
639   - # and the last, axial.
640   - image_width = self.slice_.buffer_slices[self.orientation].image.shape[1]
641   -
642   - if self.orientation == 'AXIAL':
643   - axial = self.slice_data.number
644   - coronal = position / image_width
645   - sagital = position % image_width
646   -
647   - elif self.orientation == 'CORONAL':
648   - axial = position / image_width
649   - coronal = self.slice_data.number
650   - sagital = position % image_width
651   -
652   - elif self.orientation == 'SAGITAL':
653   - axial = position / image_width
654   - coronal = position % image_width
655   - sagital = self.slice_data.number
656   -
657   - return sagital, coronal, axial
658   -
659   - def calculate_matrix_position(self, coord):
660   - x, y, z = coord
661   - xi, xf, yi, yf, zi, zf = self.slice_data.actor.GetBounds()
662   - if self.orientation == 'AXIAL':
663   - mx = round((x - xi)/self.slice_.spacing[0], 0)
664   - my = round((y - yi)/self.slice_.spacing[1], 0)
665   - elif self.orientation == 'CORONAL':
666   - mx = round((x - xi)/self.slice_.spacing[0], 0)
667   - my = round((z - zi)/self.slice_.spacing[2], 0)
668   - elif self.orientation == 'SAGITAL':
669   - mx = round((y - yi)/self.slice_.spacing[1], 0)
670   - my = round((z - zi)/self.slice_.spacing[2], 0)
671   - return my, mx
672   -
673   - def get_coordinate_cursor(self):
674   - # Find position
675   - x, y, z = self.pick.GetPickPosition()
676   - bounds = self.slice_data.actor.GetBounds()
677   - if bounds[0] == bounds[1]:
678   - x = bounds[0]
679   - elif bounds[2] == bounds[3]:
680   - y = bounds[2]
681   - elif bounds[4] == bounds[5]:
682   - z = bounds[4]
683   - return x, y, z
684   -
685   - def get_coordinate_cursor_edition(self, slice_data):
686   - # Find position
687   - actor = slice_data.actor
688   - slice_number = slice_data.number
689   - x, y, z = self.pick.GetPickPosition()
690   -
691   - # First we fix the position origin, based on vtkActor bounds
692   - bounds = actor.GetBounds()
693   - bound_xi, bound_xf, bound_yi, bound_yf, bound_zi, bound_zf = bounds
694   - x = float(x - bound_xi)
695   - y = float(y - bound_yi)
696   - z = float(z - bound_zi)
697   -
698   - dx = bound_xf - bound_xi
699   - dy = bound_yf - bound_yi
700   - dz = bound_zf - bound_zi
701   -
702   - dimensions = self.slice_.matrix.shape
703   -
704   - try:
705   - x = (x * dimensions[2]) / dx
706   - except ZeroDivisionError:
707   - x = slice_number
708   - try:
709   - y = (y * dimensions[1]) / dy
710   - except ZeroDivisionError:
711   - y = slice_number
712   - try:
713   - z = (z * dimensions[0]) / dz
714   - except ZeroDivisionError:
715   - z = slice_number
716   -
717   - return x, y, z
718   -
719   - def __bind_events(self):
720   - Publisher.subscribe(self.LoadImagedata,
721   - 'Load slice to viewer')
722   - Publisher.subscribe(self.SetBrushColour,
723   - 'Change mask colour')
724   - Publisher.subscribe(self.UpdateRender,
725   - 'Update slice viewer')
726   - Publisher.subscribe(self.ChangeSliceNumber,
727   - ('Set scroll position',
728   - self.orientation))
729   - Publisher.subscribe(self.__update_cross_position,
730   - 'Update cross position')
731   - Publisher.subscribe(self.Navigation,
732   - 'Co-registered Points')
733   - ###
734   - Publisher.subscribe(self.ChangeBrushSize,
735   - 'Set edition brush size')
736   - Publisher.subscribe(self.ChangeBrushColour,
737   - 'Add mask')
738   - Publisher.subscribe(self.ChangeBrushActor,
739   - 'Set brush format')
740   - Publisher.subscribe(self.ChangeBrushOperation,
741   - 'Set edition operation')
742   -
743   - Publisher.subscribe(self.UpdateWindowLevelValue,
744   - 'Update window level value')
745   -
746   - Publisher.subscribe(self.UpdateWindowLevelText,
747   - 'Update window level text')
748   -
749   - #Publisher.subscribe(self._set_cross_visibility,\
750   - # 'Set cross visibility')
751   - ###
752   - Publisher.subscribe(self.__set_layout,
753   - 'Set slice viewer layout')
754   -
755   - Publisher.subscribe(self.OnSetInteractorStyle,
756   - 'Set slice interaction style')
757   - Publisher.subscribe(self.OnCloseProject, 'Close project data')
758   -
759   - #####
760   - Publisher.subscribe(self.OnShowText,
761   - 'Show text actors on viewers')
762   - Publisher.subscribe(self.OnHideText,
763   - 'Hide text actors on viewers')
764   - Publisher.subscribe(self.OnExportPicture,'Export picture to file')
765   - Publisher.subscribe(self.SetDefaultCursor, 'Set interactor default cursor')
766   -
767   - Publisher.subscribe(self.AddActors, 'Add actors ' + str(ORIENTATIONS[self.orientation]))
768   - Publisher.subscribe(self.RemoveActors, 'Remove actors ' + str(ORIENTATIONS[self.orientation]))
769   - Publisher.subscribe(self.OnSwapVolumeAxes, 'Swap volume axes')
770   -
771   - Publisher.subscribe(self.ReloadActualSlice, 'Reload actual slice')
772   - Publisher.subscribe(self.OnUpdateScroll, 'Update scroll')
773   -
774   -
775   - # MIP
776   - Publisher.subscribe(self.OnSetMIPSize, 'Set MIP size %s' % self.orientation)
777   - Publisher.subscribe(self.OnSetMIPBorder, 'Set MIP border %s' % self.orientation)
778   - Publisher.subscribe(self.OnSetMIPInvert, 'Set MIP Invert %s' % self.orientation)
779   - Publisher.subscribe(self.OnShowMIPInterface, 'Show MIP interface')
780   -
781   - Publisher.subscribe(self.OnSetOverwriteMask, "Set overwrite mask")
782   -
783   - def SetDefaultCursor(self, pusub_evt):
784   - self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
785   -
786   - def OnExportPicture(self, pubsub_evt):
787   - Publisher.sendMessage('Begin busy cursor')
788   - view_prop_list = []
789   - for slice_data in self.slice_data_list:
790   - view_prop_list.append(slice_data.box_actor)
791   - self.ren.RemoveViewProp(slice_data.box_actor)
792   -
793   - id, filename, filetype = pubsub_evt.data
794   - dict = {"AXIAL": const.AXIAL,
795   - "CORONAL": const.CORONAL,
796   - "SAGITAL": const.SAGITAL}
797   -
798   - if id == dict[self.orientation]:
799   - if filetype == const.FILETYPE_POV:
800   - renwin = self.interactor.GetRenderWindow()
801   - image = vtk.vtkWindowToImageFilter()
802   - image.SetInput(renwin)
803   - writer = vtk.vtkPOVExporter()
804   - writer.SetFilePrefix(filename.split(".")[0])
805   - writer.SetRenderWindow(renwin)
806   - writer.Write()
807   - else:
808   - ren = self.slice_data.renderer
809   - #Use tiling to generate a large rendering.
810   - image = vtk.vtkRenderLargeImage()
811   - image.SetInput(ren)
812   - image.SetMagnification(1)
813   -
814   - image = image.GetOutput()
815   -
816   -
817   - # write image file
818   - if (filetype == const.FILETYPE_BMP):
819   - writer = vtk.vtkBMPWriter()
820   - elif (filetype == const.FILETYPE_JPG):
821   - writer = vtk.vtkJPEGWriter()
822   - elif (filetype == const.FILETYPE_PNG):
823   - writer = vtk.vtkPNGWriter()
824   - elif (filetype == const.FILETYPE_PS):
825   - writer = vtk.vtkPostScriptWriter()
826   - elif (filetype == const.FILETYPE_TIF):
827   - writer = vtk.vtkTIFFWriter()
828   - filename = "%s.tif"%filename.strip(".tif")
829   -
830   - writer.SetInput(image)
831   - writer.SetFileName(filename)
832   - writer.Write()
833   -
834   - for actor in view_prop_list:
835   - self.ren.AddViewProp(actor)
836   -
837   - Publisher.sendMessage('End busy cursor')
838   -
839   - def OnShowText(self, pubsub_evt):
840   - self.ShowTextActors()
841   -
842   - def OnHideText(self, pubsub_evt):
843   - self.HideTextActors()
844   -
845   - def OnCloseProject(self, pubsub_evt):
846   - self.CloseProject()
847   -
848   - def CloseProject(self):
849   - for slice_data in self.slice_data_list:
850   - del slice_data
851   -
852   - self.modes = []#['DEFAULT']
853   - self.slice_data_list = []
854   - self.layout = (1, 1)
855   - self.orientation_texts = []
856   - self.slice_number = 0
857   - self.cursor = None
858   - self.wl_text = None
859   - self.pick = vtk.vtkWorldPointPicker()
860   -
861   - def OnSetInteractorStyle(self, pubsub_evt):
862   - state = pubsub_evt.data
863   - self.SetInteractorStyle(state)
864   -
865   - if (state != const.SLICE_STATE_EDITOR):
866   - Publisher.sendMessage('Set interactor default cursor')
867   -
868   - def ChangeBrushOperation(self, pubsub_evt):
869   - self._brush_cursor_op = pubsub_evt.data
870   -
871   - def __bind_events_wx(self):
872   - self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar)
873   - self.scroll.Bind(wx.EVT_SCROLL_THUMBTRACK, self.OnScrollBarRelease)
874   - #self.scroll.Bind(wx.EVT_SCROLL_ENDSCROLL, self.OnScrollBarRelease)
875   - self.interactor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
876   - self.interactor.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu)
877   - self.interactor.Bind(wx.EVT_SIZE, self.OnSize)
878   -
879   - def LoadImagedata(self, pubsub_evt):
880   - imagedata, mask_dict = pubsub_evt.data
881   - self.SetInput(imagedata, mask_dict)
882   -
883   - def LoadRenderers(self, imagedata):
884   - number_renderers = self.layout[0] * self.layout[1]
885   - diff = number_renderers - len(self.slice_data_list)
886   - if diff > 0:
887   - for i in xrange(diff):
888   - slice_data = self.create_slice_window(imagedata)
889   - self.slice_data_list.append(slice_data)
890   - elif diff < 0:
891   - to_remove = self.slice_data_list[number_renderers::]
892   - for slice_data in to_remove:
893   - self.interactor.GetRenderWindow().RemoveRenderer(slice_data.renderer)
894   - self.slice_data_list = self.slice_data_list[:number_renderers]
895   -
896   - def __configure_renderers(self):
897   - proportion_x = 1.0 / self.layout[0]
898   - proportion_y = 1.0 / self.layout[1]
899   - # The (0,0) in VTK is in bottom left. So the creation from renderers
900   - # must be # in inverted order, from the top left to bottom right
901   - w, h = self.interactor.GetRenderWindow().GetSize()
902   - w *= proportion_x
903   - h *= proportion_y
904   - n = 0
905   - for j in xrange(self.layout[1]-1, -1, -1):
906   - for i in xrange(self.layout[0]):
907   - slice_xi = i*proportion_x
908   - slice_xf = (i+1)*proportion_x
909   - slice_yi = j*proportion_y
910   - slice_yf = (j+1)*proportion_y
911   -
912   - position = (slice_xi, slice_yi, slice_xf, slice_yf)
913   - slice_data = self.slice_data_list[n]
914   - slice_data.renderer.SetViewport(position)
915   - # Text actor position
916   - x, y = const.TEXT_POS_LEFT_DOWN
917   - slice_data.text.SetPosition((x+slice_xi,y+slice_yi))
918   - slice_data.SetCursor(self.__create_cursor())
919   - slice_data.SetSize((w, h))
920   - self.__update_camera(slice_data)
921   -
922   - style = 0
923   - if j == 0:
924   - style = style | sd.BORDER_DOWN
925   - if j == self.layout[1] - 1:
926   - style = style | sd.BORDER_UP
927   -
928   - if i == 0:
929   - style = style | sd.BORDER_LEFT
930   - if i == self.layout[0] - 1:
931   - style = style | sd.BORDER_RIGHT
932   -
933   - slice_data.SetBorderStyle(style)
934   - n += 1
935   -
936   - def __create_cursor(self):
937   - cursor = ca.CursorCircle()
938   - cursor.SetOrientation(self.orientation)
939   - #self.__update_cursor_position([i for i in actor_bound[1::2]])
940   - cursor.SetColour(self._brush_cursor_colour)
941   - cursor.SetSpacing(self.slice_.spacing)
942   - cursor.Show(0)
943   - self.cursor_ = cursor
944   - return cursor
945   -
946   - def SetInput(self, imagedata, mask_dict):
947   - self.slice_ = sl.Slice()
948   -
949   - max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation)
950   - self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
951   - max_slice_number)
952   -
953   - self.slice_data = self.create_slice_window()
954   - #self.slice_data.actor.SetInput(imagedata)
955   - self.slice_data.SetCursor(self.__create_cursor())
956   - self.cam = self.slice_data.renderer.GetActiveCamera()
957   - self.__build_cross_lines(imagedata)
958   - #self.set_slice_number(0)
959   -
960   - # Set the slice number to the last slice to ensure the camera if far
961   - # enough to show all slices.
962   - self.set_slice_number(max_slice_number - 1)
963   - self.__update_camera()
964   - self.slice_data.renderer.ResetCamera()
965   - self.interactor.GetRenderWindow().AddRenderer(self.slice_data.renderer)
966   - #if slice_.imagedata is None:
967   - #slice_.SetInput(imagedata, mask_dict)
968   -
969   - ##actor.SetInput(slice_.GetOutput())
970   - #self.LoadRenderers(slice_.GetOutput())
971   - #self.__configure_renderers()
972   - #ren = self.slice_data_list[0].renderer
973   - #actor = self.slice_data_list[0].actor
974   - #actor_bound = actor.GetBounds()
975   - #self.cam = ren.GetActiveCamera()
976   -
977   - #for slice_data in self.slice_data_list:
978   - #self.__update_camera(slice_data)
979   - #self.Reposition(slice_data)
980   -
981   - #number_of_slices = self.layout[0] * self.layout[1]
982   - #max_slice_number = actor.GetSliceNumberMax() + 1/ \
983   - #number_of_slices
984   -
985   - #if actor.GetSliceNumberMax() % number_of_slices:
986   - #max_slice_number += 1
987   - #self.set_scroll_position(0)
988   -
989   - #actor_bound = actor.GetBounds()
990   - self.interactor.Render()
991   -
992   - self.EnableText()
993   - self.wl_text.Hide()
994   - ## Insert cursor
995   - self.SetInteractorStyle(const.STATE_DEFAULT)
996   -
997   - def __build_cross_lines(self, imagedata):
998   - renderer = self.slice_data.overlay_renderer
999   -
1000   - cross = vtk.vtkCursor3D()
1001   - cross.AllOff()
1002   - cross.AxesOn()
1003   - self.cross = cross
1004   -
1005   - c = vtk.vtkCoordinate()
1006   - c.SetCoordinateSystemToWorld()
1007   -
1008   - cross_mapper = vtk.vtkPolyDataMapper()
1009   - cross_mapper.SetInput(cross.GetOutput())
1010   - #cross_mapper.SetTransformCoordinate(c)
1011   -
1012   - p = vtk.vtkProperty()
1013   - p.SetColor(1, 0, 0)
1014   -
1015   - cross_actor = vtk.vtkActor()
1016   - cross_actor.SetMapper(cross_mapper)
1017   - cross_actor.SetProperty(p)
1018   - cross_actor.VisibilityOff()
1019   - # Only the slices are pickable
1020   - cross_actor.PickableOff()
1021   - self.cross_actor = cross_actor
1022   -
1023   - renderer.AddActor(cross_actor)
1024   -
1025   - def __update_cross_position(self, pubsub_evt):
1026   - pos = pubsub_evt.data
1027   - self.cross.SetFocalPoint(pos)
1028   -
1029   - def _set_cross_visibility(self, visibility):
1030   - self.cross_actor.SetVisibility(visibility)
1031   -
1032   - def _set_editor_cursor_visibility(self, visibility):
1033   - for slice_data in self.slice_data_list:
1034   - slice_data.cursor.actor.SetVisibility(visibility)
1035   -
1036   - def __update_cursor_position(self, slice_data, position):
1037   - x, y, z = position
1038   - if (slice_data.cursor):
1039   - slice_number = slice_data.number
1040   - actor_bound = slice_data.actor.GetBounds()
1041   -
1042   - yz = [x + abs(x * 0.001), y, z]
1043   - xz = [x, y - abs(y * 0.001), z]
1044   - xy = [x, y, z + abs(z * 0.001)]
1045   -
1046   - proj = project.Project()
1047   - orig_orien = proj.original_orientation
1048   -
1049   - if (orig_orien == const.SAGITAL):
1050   - coordinates = {"SAGITAL": xy, "CORONAL": yz, "AXIAL": xz}
1051   - elif(orig_orien == const.CORONAL):
1052   - coordinates = {"SAGITAL": yz, "CORONAL": xy, "AXIAL": xz}
1053   - else:
1054   - coordinates = {"SAGITAL": yz, "CORONAL": xz, "AXIAL": xy}
1055   -
1056   - slice_data.cursor.SetPosition(coordinates[self.orientation])
1057   -
1058   - def SetOrientation(self, orientation):
1059   - self.orientation = orientation
1060   - for slice_data in self.slice_data_list:
1061   - self.__update_camera(slice_data)
1062   -
1063   - def create_slice_window(self):
1064   - renderer = vtk.vtkRenderer()
1065   - renderer.SetLayer(0)
1066   - cam = renderer.GetActiveCamera()
1067   -
1068   - overlay_renderer = vtk.vtkRenderer()
1069   - overlay_renderer.SetLayer(1)
1070   - overlay_renderer.SetActiveCamera(cam)
1071   - overlay_renderer.SetInteractive(0)
1072   -
1073   -
1074   - self.interactor.GetRenderWindow().SetNumberOfLayers(2)
1075   - self.interactor.GetRenderWindow().AddRenderer(overlay_renderer)
1076   - self.interactor.GetRenderWindow().AddRenderer(renderer)
1077   -
1078   - actor = vtk.vtkImageActor()
1079   - # TODO: Create a option to let the user set if he wants to interpolate
1080   - # the slice images.
1081   - #actor.InterpolateOff()
1082   - slice_data = sd.SliceData()
1083   - slice_data.SetOrientation(self.orientation)
1084   - slice_data.renderer = renderer
1085   - slice_data.overlay_renderer = overlay_renderer
1086   - slice_data.actor = actor
1087   - slice_data.SetBorderStyle(sd.BORDER_ALL)
1088   - renderer.AddActor(actor)
1089   - renderer.AddActor(slice_data.text.actor)
1090   - renderer.AddViewProp(slice_data.box_actor)
1091   - return slice_data
1092   -
1093   - def __update_camera(self):
1094   - orientation = self.orientation
1095   - proj = project.Project()
1096   - orig_orien = proj.original_orientation
1097   -
1098   - self.cam.SetFocalPoint(0, 0, 0)
1099   - self.cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation])
1100   - self.cam.SetPosition(const.SLICE_POSITION[orig_orien][1][self.orientation])
1101   - #self.cam.ComputeViewPlaneNormal()
1102   - #self.cam.OrthogonalizeViewUp()
1103   - self.cam.ParallelProjectionOn()
1104   -
1105   - def __update_display_extent(self, image):
1106   - self.slice_data.actor.SetDisplayExtent(image.GetExtent())
1107   - self.slice_data.renderer.ResetCameraClippingRange()
1108   -
1109   - def UpdateRender(self, evt):
1110   - print "Updating viewer", self.orientation
1111   - self.interactor.Render()
1112   -
1113   - def __configure_scroll(self):
1114   - actor = self.slice_data_list[0].actor
1115   - number_of_slices = self.layout[0] * self.layout[1]
1116   - max_slice_number = actor.GetSliceNumberMax()/ \
1117   - number_of_slices
1118   - if actor.GetSliceNumberMax()% number_of_slices:
1119   - max_slice_number += 1
1120   - self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
1121   - max_slice_number)
1122   - self.set_scroll_position(0)
1123   -
1124   - @property
1125   - def number_slices(self):
1126   - return self._number_slices
1127   -
1128   - @number_slices.setter
1129   - def number_slices(self, val):
1130   - if val != self._number_slices:
1131   - self._number_slices = val
1132   - buffer_ = self.slice_.buffer_slices[self.orientation]
1133   - buffer_.discard_buffer()
1134   -
1135   - def set_scroll_position(self, position):
1136   - self.scroll.SetThumbPosition(position)
1137   - self.OnScrollBar()
1138   -
1139   - def UpdateSlice3D(self, pos):
1140   - original_orientation = project.Project().original_orientation
1141   - pos = self.scroll.GetThumbPosition()
1142   - Publisher.sendMessage('Change slice from slice plane',\
1143   - (self.orientation, pos))
1144   -
1145   - def OnScrollBar(self, evt=None, update3D=True):
1146   - pos = self.scroll.GetThumbPosition()
1147   - self.set_slice_number(pos)
1148   - if update3D:
1149   - self.UpdateSlice3D(pos)
1150   - if self.state == const.SLICE_STATE_CROSS:
1151   - # Update other slice's cross according to the new focal point from
1152   - # the actual orientation.
1153   - focal_point = self.cross.GetFocalPoint()
1154   - Publisher.sendMessage('Update cross position', focal_point)
1155   - Publisher.sendMessage('Update slice viewer')
1156   - else:
1157   - self.interactor.Render()
1158   - if evt:
1159   - if self._flush_buffer:
1160   - self.slice_.apply_slice_buffer_to_mask(self.orientation)
1161   - evt.Skip()
1162   -
1163   - def OnScrollBarRelease(self, evt):
1164   - pos = self.scroll.GetThumbPosition()
1165   - evt.Skip()
1166   -
1167   - def OnKeyDown(self, evt=None, obj=None):
1168   - pos = self.scroll.GetThumbPosition()
1169   - skip = True
1170   -
1171   - min = 0
1172   - max = self.slice_.GetMaxSliceNumber(self.orientation)
1173   -
1174   - projections = {wx.WXK_NUMPAD0 : const.PROJECTION_NORMAL,
1175   - wx.WXK_NUMPAD1 : const.PROJECTION_MaxIP,
1176   - wx.WXK_NUMPAD2 : const.PROJECTION_MinIP,
1177   - wx.WXK_NUMPAD3 : const.PROJECTION_MeanIP,
1178   - wx.WXK_NUMPAD4 : const.PROJECTION_MIDA,
1179   - wx.WXK_NUMPAD5 : const.PROJECTION_CONTOUR_MIP,
1180   - wx.WXK_NUMPAD6 : const.PROJECTION_CONTOUR_MIDA,}
1181   -
1182   - if self._flush_buffer:
1183   - self.slice_.apply_slice_buffer_to_mask(self.orientation)
1184   -
1185   - if (evt.GetKeyCode() == wx.WXK_UP and pos > min):
1186   - self.OnScrollForward()
1187   - self.OnScrollBar()
1188   -
1189   - elif (evt.GetKeyCode() == wx.WXK_DOWN and pos < max):
1190   - self.OnScrollBackward()
1191   - self.OnScrollBar()
1192   -
1193   - elif (evt.GetKeyCode() == wx.WXK_NUMPAD_ADD):
1194   - actual_value = self.mip_ctrls.mip_size_spin.GetValue()
1195   - self.mip_ctrls.mip_size_spin.SetValue(actual_value + 1)
1196   - if self.mip_ctrls.mip_size_spin.GetValue() != actual_value:
1197   - self.number_slices = self.mip_ctrls.mip_size_spin.GetValue()
1198   - self.ReloadActualSlice()
1199   -
1200   - elif (evt.GetKeyCode() == wx.WXK_NUMPAD_SUBTRACT):
1201   - actual_value = self.mip_ctrls.mip_size_spin.GetValue()
1202   - self.mip_ctrls.mip_size_spin.SetValue(actual_value - 1)
1203   - if self.mip_ctrls.mip_size_spin.GetValue() != actual_value:
1204   - self.number_slices = self.mip_ctrls.mip_size_spin.GetValue()
1205   - self.ReloadActualSlice()
1206   -
1207   - elif evt.GetKeyCode() in projections:
1208   - self.slice_.SetTypeProjection(projections[evt.GetKeyCode()])
1209   - Publisher.sendMessage('Set projection type', projections[evt.GetKeyCode()])
1210   - Publisher.sendMessage('Reload actual slice')
1211   - skip = False
1212   -
1213   - self.UpdateSlice3D(pos)
1214   - self.interactor.Render()
1215   -
1216   - if evt and skip:
1217   - evt.Skip()
1218   -
1219   - def OnScrollForward(self, evt=None, obj=None):
1220   - pos = self.scroll.GetThumbPosition()
1221   - min = 0
1222   -
1223   - if(pos > min):
1224   - if self._flush_buffer:
1225   - self.slice_.apply_slice_buffer_to_mask(self.orientation)
1226   - pos = pos - 1
1227   - self.scroll.SetThumbPosition(pos)
1228   - self.OnScrollBar()
1229   -
1230   - def OnScrollBackward(self, evt=None, obj=None):
1231   - pos = self.scroll.GetThumbPosition()
1232   - max = self.slice_.GetMaxSliceNumber(self.orientation)
1233   -
1234   - if(pos < max):
1235   - if self._flush_buffer:
1236   - self.slice_.apply_slice_buffer_to_mask(self.orientation)
1237   - pos = pos + 1
1238   - self.scroll.SetThumbPosition(pos)
1239   - self.OnScrollBar()
1240   -
1241   - def OnSize(self, evt):
1242   - w, h = evt.GetSize()
1243   - w = float(w)
1244   - h = float(h)
1245   - if self.slice_data:
1246   - self.slice_data.SetSize((w, h))
1247   - evt.Skip()
1248   -
1249   - def OnSetMIPSize(self, pubsub_evt):
1250   - val = pubsub_evt.data
1251   - self.number_slices = val
1252   - self.ReloadActualSlice()
1253   -
1254   - def OnSetMIPBorder(self, pubsub_evt):
1255   - val = pubsub_evt.data
1256   - self.slice_.n_border = val
1257   - buffer_ = self.slice_.buffer_slices[self.orientation]
1258   - buffer_.discard_buffer()
1259   - self.ReloadActualSlice()
1260   -
1261   - def OnSetMIPInvert(self, pubsub_evt):
1262   - val = pubsub_evt.data
1263   - self._mip_inverted = val
1264   - buffer_ = self.slice_.buffer_slices[self.orientation]
1265   - buffer_.discard_buffer()
1266   - self.ReloadActualSlice()
1267   -
1268   - def OnShowMIPInterface(self, pubsub_evt):
1269   - value = pubsub_evt.data
1270   - if value:
1271   - if not self.mip_ctrls.Shown:
1272   - self.mip_ctrls.Show()
1273   - self.GetSizer().Add(self.mip_ctrls, 0, wx.EXPAND|wx.GROW|wx.ALL, 2)
1274   - self.Layout()
1275   - else:
1276   - self.mip_ctrls.Hide()
1277   - self.GetSizer().Remove(self.mip_ctrls)
1278   - self.Layout()
1279   -
1280   - def OnSetOverwriteMask(self, pubsub_evt):
1281   - value = pubsub_evt.data
1282   - self.overwrite_mask = value
1283   -
1284   - def set_slice_number(self, index):
1285   - inverted = self.mip_ctrls.inverted.GetValue()
1286   - border_size = self.mip_ctrls.border_spin.GetValue()
1287   - image = self.slice_.GetSlices(self.orientation, index,
1288   - self.number_slices, inverted, border_size)
1289   - self.slice_data.actor.SetInput(image)
1290   - for actor in self.actors_by_slice_number.get(self.slice_data.number, []):
1291   - self.slice_data.renderer.RemoveActor(actor)
1292   - for actor in self.actors_by_slice_number.get(index, []):
1293   - self.slice_data.renderer.AddActor(actor)
1294   -
1295   - if self.slice_._type_projection == const.PROJECTION_NORMAL:
1296   - self.slice_data.SetNumber(index)
1297   - else:
1298   - max_slices = self.slice_.GetMaxSliceNumber(self.orientation)
1299   - end = min(max_slices, index + self.number_slices - 1)
1300   - self.slice_data.SetNumber(index, end)
1301   - self.__update_display_extent(image)
1302   - self.cross.SetModelBounds(self.slice_data.actor.GetBounds())
1303   -
1304   - def ChangeSliceNumber(self, pubsub_evt):
1305   - index = pubsub_evt.data
1306   - #self.set_slice_number(index)
1307   - self.scroll.SetThumbPosition(index)
1308   - pos = self.scroll.GetThumbPosition()
1309   - self.set_slice_number(pos)
1310   - self.interactor.Render()
1311   -
1312   - def test_operation_position(self, coord):
1313   - """
1314   - Test if coord is into the imagedata limits.
1315   - """
1316   - x, y, z = coord
1317   - xi, yi, zi = 0, 0, 0
1318   - xf, yf, zf = self.imagedata.GetDimensions()
1319   - if xi <= x <= xf \
1320   - and yi <= y <= yf\
1321   - and zi <= z <= zf:
1322   - return True
1323   - return False
1324   -
1325   - def _assert_coord_into_image(self, coord):
1326   - extent = self.imagedata.GetWholeExtent()
1327   - extent_min = extent[0], extent[2], extent[4]
1328   - extent_max = extent[1], extent[3], extent[5]
1329   - for index in xrange(3):
1330   - if coord[index] > extent_max[index]:
1331   - coord[index] = extent_max[index]
1332   - elif coord[index] < extent_min[index]:
1333   - coord[index] = extent_min[index]
1334   - return coord
1335   -
1336   - def ReloadActualSlice(self, pubsub_evt=None):
1337   - pos = self.scroll.GetThumbPosition()
1338   - self.set_slice_number(pos)
1339   - self.interactor.Render()
1340   -
1341   - def OnUpdateScroll(self, pubsub_evt):
1342   - max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation)
1343   - self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
1344   - max_slice_number)
1345   -
1346   - def OnSwapVolumeAxes(self, pubsub_evt):
1347   - # Adjusting cursor spacing to match the spacing from the actual slice
1348   - # orientation
1349   - axis0, axis1 = pubsub_evt.data
1350   - cursor = self.slice_data.cursor
1351   - spacing = cursor.spacing
1352   - if (axis0, axis1) == (2, 1):
1353   - cursor.SetSpacing((spacing[1], spacing[0], spacing[2]))
1354   - elif (axis0, axis1) == (2, 0):
1355   - cursor.SetSpacing((spacing[2], spacing[1], spacing[0]))
1356   - elif (axis0, axis1) == (1, 0):
1357   - cursor.SetSpacing((spacing[0], spacing[2], spacing[1]))
1358   -
1359   - self.slice_data.renderer.ResetCamera()
1360   -
1361   - def AddActors(self, pubsub_evt):
1362   - "Inserting actors"
1363   - actors, n = pubsub_evt.data
1364   - pos = self.scroll.GetThumbPosition()
1365   - print actors
1366   - #try:
1367   - #renderer = self.renderers_by_slice_number[n]
1368   - #for actor in actors:
1369   - #renderer.AddActor(actor)
1370   - #except KeyError:
1371   - #pass
1372   - if pos == n:
1373   - for actor in actors:
1374   - self.slice_data.renderer.AddActor(actor)
1375   -
1376   - try:
1377   - self.actors_by_slice_number[n].extend(actors)
1378   - except KeyError:
1379   - self.actors_by_slice_number[n] = list(actors)
1380   -
1381   - def RemoveActors(self, pubsub_evt):
1382   - "Remove a list of actors"
1383   - actors, n = pubsub_evt.data
1384   - try:
1385   - renderer = self.renderers_by_slice_number[n]
1386   - except KeyError:
1387   - for actor in actors:
1388   - self.actors_by_slice_number[n].remove(actor)
1389   - self.slice_data.renderer.RemoveActor(actor)
1390   - else:
1391   - for actor in actors:
1392   - # Remove the actor from the renderer
1393   - renderer.RemoveActor(actor)
1394   - # and remove the actor from the actor's list
1395   - self.actors_by_slice_number[n].remove(actor)
invesalius/bkps/viewer_volume.py.bak
... ... @@ -1,1299 +0,0 @@
1   -#!/usr/bin/env python
2   -# -*- coding: utf-8 -*-
3   -
4   -#--------------------------------------------------------------------------
5   -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
6   -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
7   -# Homepage: http://www.softwarepublico.gov.br
8   -# Contact: invesalius@cti.gov.br
9   -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
10   -#--------------------------------------------------------------------------
11   -# Este programa e software livre; voce pode redistribui-lo e/ou
12   -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
13   -# publicada pela Free Software Foundation; de acordo com a versao 2
14   -# da Licenca.
15   -#
16   -# Este programa eh distribuido na expectativa de ser util, mas SEM
17   -# QUALQUER GARANTIA; sem mesmo a garantia implicita de
18   -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
19   -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
20   -# detalhes.
21   -#--------------------------------------------------------------------------
22   -
23   -import sys
24   -
25   -import numpy
26   -import wx
27   -import vtk
28   -from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
29   -from wx.lib.pubsub import pub as Publisher
30   -
31   -import constants as const
32   -import data.bases as bases
33   -import data.vtk_utils as vtku
34   -import project as prj
35   -import style as st
36   -import utils
37   -
38   -from data import measures
39   -
40   -PROP_MEASURE = 0.8
41   -
42   -class Viewer(wx.Panel):
43   - def __init__(self, parent):
44   - wx.Panel.__init__(self, parent, size=wx.Size(320, 320))
45   - self.SetBackgroundColour(wx.Colour(0, 0, 0))
46   -
47   - self.interaction_style = st.StyleStateManager()
48   -
49   - self.ball_reference = None
50   - self.initial_foco = None
51   -
52   - style = vtk.vtkInteractorStyleTrackballCamera()
53   - self.style = style
54   -
55   - interactor = wxVTKRenderWindowInteractor(self, -1, size = self.GetSize())
56   - interactor.SetInteractorStyle(style)
57   - self.interactor = interactor
58   -
59   - sizer = wx.BoxSizer(wx.VERTICAL)
60   - sizer.Add(interactor, 1, wx.EXPAND)
61   - self.sizer = sizer
62   - self.SetSizer(sizer)
63   - self.Layout()
64   -
65   - # It would be more correct (API-wise) to call interactor.Initialize() and
66   - # interactor.Start() here, but Initialize() calls RenderWindow.Render().
67   - # That Render() call will get through before we can setup the
68   - # RenderWindow() to render via the wxWidgets-created context; this
69   - # causes flashing on some platforms and downright breaks things on
70   - # other platforms. Instead, we call widget.Enable(). This means
71   - # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
72   - # that doesn't matter.
73   - interactor.Enable(1)
74   -
75   - ren = vtk.vtkRenderer()
76   - interactor.GetRenderWindow().AddRenderer(ren)
77   - self.ren = ren
78   -
79   - self.raycasting_volume = False
80   -
81   - self.onclick = False
82   -
83   - self.text = vtku.Text()
84   - self.text.SetValue("")
85   - self.ren.AddActor(self.text.actor)
86   -
87   -
88   - self.slice_plane = None
89   -
90   - self.view_angle = None
91   -
92   - self.__bind_events()
93   - self.__bind_events_wx()
94   -
95   - self.mouse_pressed = 0
96   - self.on_wl = False
97   -
98   - self.picker = vtk.vtkPointPicker()
99   - interactor.SetPicker(self.picker)
100   - self.seed_points = []
101   -
102   - self.points_reference = []
103   -
104   - self.measure_picker = vtk.vtkPropPicker()
105   - #self.measure_picker.SetTolerance(0.005)
106   - self.measures = []
107   -
108   - self._last_state = 0
109   -
110   - self.repositioned_axial_plan = 0
111   - self.repositioned_sagital_plan = 0
112   - self.repositioned_coronal_plan = 0
113   - self.added_actor = 0
114   -
115   - self._mode_cross = False
116   - self._to_show_ball = 0
117   - self._ball_ref_visibility = False
118   -
119   - # initialization of navigation variables
120   - #======aji=================================================================
121   - self.ShowAngles()
122   - #=======================================================================
123   -
124   - ##---------------------------------------------
125   - ##AXES TO GUIDE VISUALIZATION - CREATED BY VH
126   -# axes = vtk.vtkAxesActor()
127   -# axes.SetXAxisLabelText('x')
128   -# axes.SetYAxisLabelText('y')
129   -# axes.SetZAxisLabelText('z')
130   -# axes.SetTotalLength(50, 50, 50)
131   -# self.ren.AddActor(axes)
132   - ##---------------------------------------------
133   - # ---
134   - def __bind_events(self):
135   - Publisher.subscribe(self.LoadActor,
136   - 'Load surface actor into viewer')
137   - Publisher.subscribe(self.RemoveActor,
138   - 'Remove surface actor from viewer')
139   - Publisher.subscribe(self.OnShowSurface, 'Show surface')
140   - Publisher.subscribe(self.UpdateRender,
141   - 'Render volume viewer')
142   - Publisher.subscribe(self.ChangeBackgroundColour,
143   - 'Change volume viewer background colour')
144   - # Raycating - related
145   - Publisher.subscribe(self.LoadVolume,
146   - 'Load volume into viewer')
147   - Publisher.subscribe(self.UnloadVolume,
148   - 'Unload volume')
149   - Publisher.subscribe(self.OnSetWindowLevelText,
150   - 'Set volume window and level text')
151   - Publisher.subscribe(self.OnHideRaycasting,
152   - 'Hide raycasting volume')
153   - Publisher.subscribe(self.OnShowRaycasting,
154   - 'Update raycasting preset')
155   - ###
156   - Publisher.subscribe(self.AppendActor,'AppendActor')
157   - Publisher.subscribe(self.SetWidgetInteractor,
158   - 'Set Widget Interactor')
159   - Publisher.subscribe(self.OnSetViewAngle,
160   - 'Set volume view angle')
161   -
162   - Publisher.subscribe(self.OnDisableBrightContrast,
163   - 'Set interaction mode '+
164   - str(const.MODE_SLICE_EDITOR))
165   -
166   - Publisher.subscribe(self.OnExportSurface, 'Export surface to file')
167   -
168   - Publisher.subscribe(self.LoadSlicePlane, 'Load slice plane')
169   -
170   - Publisher.subscribe(self.ResetCamClippingRange, 'Reset cam clipping range')
171   - Publisher.subscribe(self.SetVolumeCamera, 'Set camera in volume')
172   -
173   - Publisher.subscribe(self.OnEnableStyle, 'Enable style')
174   - Publisher.subscribe(self.OnDisableStyle, 'Disable style')
175   -
176   - Publisher.subscribe(self.OnHideText,
177   - 'Hide text actors on viewers')
178   -
179   - Publisher.subscribe(self.AddActors, 'Add actors ' + str(const.SURFACE))
180   - Publisher.subscribe(self.RemoveActors, 'Remove actors ' + str(const.SURFACE))
181   -
182   - Publisher.subscribe(self.OnShowText,
183   - 'Show text actors on viewers')
184   - Publisher.subscribe(self.OnCloseProject, 'Close project data')
185   -
186   - Publisher.subscribe(self.RemoveAllActor, 'Remove all volume actors')
187   -
188   - Publisher.subscribe(self.OnExportPicture,'Export picture to file')
189   -
190   - Publisher.subscribe(self.OnStartSeed,'Create surface by seeding - start')
191   - Publisher.subscribe(self.OnEndSeed,'Create surface by seeding - end')
192   -
193   - Publisher.subscribe(self.ActivateBallReference,
194   - 'Activate ball reference')
195   - Publisher.subscribe(self.DeactivateBallReference,
196   - 'Deactivate ball reference')
197   - # see if these subscribes are here just for navigation and if
198   - # they are being used
199   - Publisher.subscribe(self.SetBallReferencePosition,
200   - 'Set ball reference position')
201   - Publisher.subscribe(self.SetBallReferencePositionBasedOnBound,
202   - 'Set ball reference position based on bound')
203   - Publisher.subscribe(self.SetStereoMode, 'Set stereo mode')
204   -
205   - Publisher.subscribe(self.Reposition3DPlane, 'Reposition 3D Plane')
206   -
207   - Publisher.subscribe(self.RemoveVolume, 'Remove Volume')
208   -
209   - Publisher.subscribe(self._check_ball_reference, 'Enable style')
210   - Publisher.subscribe(self._uncheck_ball_reference, 'Disable style')
211   -
212   - # subscribes for navigation functions
213   -
214   - Publisher.subscribe(self.CreateSphereMarkers, 'Create ball')
215   - Publisher.subscribe(self.HideSphereMarkers, 'Hide balls')
216   - Publisher.subscribe(self.ShowSphereMarkers, 'Show balls')
217   - Publisher.subscribe(self.ChangeInitCoilAngle, 'Change Init Coil Angle')
218   -#=========aji======================================================================
219   - Publisher.subscribe(self.RemoveMarkers, 'Remove Markers')
220   - Publisher.subscribe(self.CoilAngleTracking, 'Track Coil Angle')
221   - Publisher.subscribe(self.CoilAngleTracking, 'Track Coil Angle')
222   - Publisher.subscribe(self.HideShowObject, 'Hide Show Object')
223   - Publisher.subscribe(self.ShowObject, 'Show Object status')
224   - Publisher.subscribe(self.UpAngles, 'Update Angles')
225   - Publisher.subscribe(self.HideAnglesActor, 'Hide Angles')
226   -#===============================================================================
227   - # ---
228   - def SetStereoMode(self, pubsub_evt):
229   - mode = pubsub_evt.data
230   - ren_win = self.interactor.GetRenderWindow()
231   -
232   - if mode == const.STEREO_OFF:
233   - ren_win.StereoRenderOff()
234   - else:
235   -
236   - if mode == const.STEREO_RED_BLUE:
237   - ren_win.SetStereoTypeToRedBlue()
238   - elif mode == const.STEREO_CRISTAL:
239   - ren_win.SetStereoTypeToCrystalEyes()
240   - elif mode == const.STEREO_INTERLACED:
241   - ren_win.SetStereoTypeToInterlaced()
242   - elif mode == const.STEREO_LEFT:
243   - ren_win.SetStereoTypeToLeft()
244   - elif mode == const.STEREO_RIGHT:
245   - ren_win.SetStereoTypeToRight()
246   - elif mode == const.STEREO_DRESDEN:
247   - ren_win.SetStereoTypeToDresden()
248   - elif mode == const.STEREO_CHECKBOARD:
249   - ren_win.SetStereoTypeToCheckerboard()
250   - elif mode == const.STEREO_ANAGLYPH:
251   - ren_win.SetStereoTypeToAnaglyph()
252   -
253   - ren_win.StereoRenderOn()
254   -
255   - self.interactor.Render()
256   -
257   - # --- functions for navigation
258   - def CreateSphereMarkers(self, pubsub_evt):
259   - ball_id = pubsub_evt.data[0]
260   - ballsize = pubsub_evt.data[1]
261   - ballcolour = pubsub_evt.data[2]
262   - coord = pubsub_evt.data[3]
263   - x, y, z = bases.FlipX(coord)
264   -
265   - ball_ref = vtk.vtkSphereSource()
266   - ball_ref.SetRadius(ballsize)
267   - ball_ref.SetCenter(x, y, z)
268   -
269   - mapper = vtk.vtkPolyDataMapper()
270   - mapper.SetInput(ball_ref.GetOutput())
271   -
272   - prop = vtk.vtkProperty()
273   - prop.SetColor(ballcolour)
274   -
275   - #adding a new actor for the present ball
276   - self.staticballs.append(vtk.vtkActor())
277   -
278   - self.staticballs[ball_id].SetMapper(mapper)
279   - self.staticballs[ball_id].SetProperty(prop)
280   -
281   - self.ren.AddActor(self.staticballs[ball_id])
282   - ball_id = ball_id + 1
283   - self.UpdateRender()
284   -
285   - def HideSphereMarkers(self, pubsub_evt):
286   - ballid = pubsub_evt.data
287   - for i in range(0, ballid + 1):
288   - self.staticballs[i].SetVisibility(0)
289   - self.UpdateRender()
290   -
291   - def ShowSphereMarkers(self, pubsub_evt):
292   - ballid = pubsub_evt.data
293   - for i in range(0, ballid + 1):
294   - self.staticballs[i].SetVisibility(1)
295   - self.UpdateRender()
296   -
297   - def CreateCoilReference(self):
298   - #SILVER COIL
299   - self.coil_reference = vtk.vtkOBJReader()
300   -
301   - #self.coil_reference.SetFileName(os.path.realpath(os.path.join('..',
302   - # 'models',
303   - # 'coil_cti_2_scale10.obj')))
304   -
305   - self.coil_reference.SetFileName('C:\Users\Biomag\Desktop\invesalius_navigator\icons\coil_cti_2_scale10.obj')
306   -
307   - ##self.coil_reference.Update()
308   - coilMapper = vtk.vtkPolyDataMapper()
309   - coilMapper.SetInputConnection(self.coil_reference.GetOutputPort())
310   -
311   - self.coilActor = vtk.vtkActor()
312   - self.coilActor.SetMapper(coilMapper)
313   -
314   - ##Creating axes to follow the coil
315   - #axisXArrow = vtk.vtkArrowSource()
316   - #axisYArrow = vtk.vtkArrowSource()
317   - #axisZArrow = vtk.vtkArrowSource()
318   -
319   - #axisXMapper = vtk.vtkPolyDataMapper()
320   - #axisXMapper.SetInput(axisXArrow.GetOutput())
321   - #axisXMapper.ScalarVisibilityOff()
322   - #axisYMapper = vtk.vtkPolyDataMapper()
323   - #axisYMapper.SetInput(axisYArrow.GetOutput())
324   - #axisYMapper.ScalarVisibilityOff()
325   - #axisZMapper = vtk.vtkPolyDataMapper()
326   - #axisZMapper.SetInput(axisZArrow.GetOutput())
327   - #axisZMapper.ScalarVisibilityOff()
328   -
329   - #axisXArrowActor = vtk.vtkActor()
330   - #axisXArrowActor.SetMapper(axisXMapper)
331   - #axisXArrowActor.SetScale(40)
332   - #axisXArrowActor.GetProperty().SetColor(1, 0, 0) # x-axis >> red
333   - #axisYArrowActor = vtk.vtkActor()
334   - #axisYArrowActor.SetScale(40)
335   - #axisYArrowActor.RotateZ(90)
336   - #axisYArrowActor.GetProperty().SetColor(0, 1, 0) # y-axis >> green
337   - #axisYArrowActor.SetMapper(axisYMapper)
338   - #axisZArrowActor = vtk.vtkActor()
339   - #axisZArrowActor.RotateY(-90)
340   - #axisZArrowActor.SetScale(40)
341   - #axisZArrowActor.GetProperty().SetColor(0, 0, 1) # z-axis >> blue
342   - #axisZArrowActor.SetMapper(axisZMapper)
343   -
344   - #self.axisAssembly.AddPart(axisXArrowActor)
345   - #self.axisAssembly.AddPart(axisYArrowActor)
346   - #self.axisAssembly.AddPart(axisZArrowActor)
347   - #self.axisAssembly.PickableOff()
348   -
349   - def ChangeInitCoilAngle(self, pubsub_evt):
350   - self.CreateCoilReference()
351   - self.ren.AddActor(self.coilActor)
352   - self.coilActor.SetOrientation(0, 0, 0)
353   - inits_data = pubsub_evt.data
354   - print "inits data", inits_data
355   - init_orient = inits_data[0]
356   - self.init_plh_angles = inits_data[1]
357   - self.vectors = ((inits_data[2][0, 0], inits_data[2][0, 1], inits_data[2][0, 2]),
358   - (inits_data[2][1, 0], inits_data[2][1, 1], inits_data[2][1, 2]),
359   - (inits_data[2][2, 0], inits_data[2][2, 1], inits_data[2][2, 2]))
360   - self.coilActor.SetOrientation(init_orient)
361   - self.axisAssembly.SetOrientation(init_orient)
362   -
363   - self.UpdateRender()
364   -
365   - def SetBallReferencePosition(self, coord, angles):
366   - coord = coord
367   - angles = angles
368   - #Coronal Images dont require this transformation - 1 tested
369   - #and for this case, at navigation, the z axis is inverted
370   -
371   - #E se ao inves de fazer o flipx, da pra soh multiplicar o y por -1
372   -
373   - x, y, z = bases.FlipX(coord)
374   -
375   - #center = self.coilActor.GetCenter()
376   -
377   - ##azimutal - psi - rotz
378   - ##elevation - teta - rotx
379   - ##roll - phi - roty
380   -
381   -## print "center: ", center
382   - #print "orig: ", orig
383   - #print "bounds: ", bounds
384   -## print "coord: ", coord
385   -
386   - transf = vtk.vtkTransform()
387   -
388   - if angles and self.init_plh_angles:
389   - #plh angles variation
390   - delta_angles = (angles[0] - self.init_plh_angles[0],
391   - angles[1] - self.init_plh_angles[1],
392   - angles[2] - self.init_plh_angles[2])
393   -
394   - transf.Translate(x, y, z) #center
395   - ##transf.Translate(0, 0, 0) #origin
396   -
397   - transf.RotateWXYZ(delta_angles[0], self.vectors[2])
398   - transf.RotateWXYZ(delta_angles[1], self.vectors[0])
399   - transf.RotateWXYZ(delta_angles[2], self.vectors[1])
400   - #transf.Scale(1, 1, 1)
401   - #transf.Translate(-center[0], -center[1], -center[2]) #- origin
402   - #transf.Translate(-orig[0], -orig[1], -orig[2])
403   - else:
404   - #transf.Translate(-center[0], -center[1], -center[2])
405   - transf.Translate(x, y, z) #center
406   - #transf.RotateWXYZ(90, 3.0, 1.0, 0.5)
407   - try:
408   - self.coilActor.SetUserMatrix(transf.GetMatrix())
409   - except:
410   - None
411   - self.ball_reference.SetCenter(x, y, z)
412   - self.axisAssembly.SetPosition(x, y, z)
413   -
414   -## print "center 2: ", self.coilActor.GetCenter()
415   -## print "orig 2: ", self.coilActor.GetOrigin()
416   - #print "bounds 2: ", self.coilActor.GetBounds()
417   -## print "angles 2: ", self.coilActor.GetOrientation()
418   -## print "ball center: ", self.ball_reference.GetCenter()
419   -
420   - #a = self.coilActor.GetOrientation()
421   - #b = self.coilActor.GetOrientationWXYZ()
422   - #print "soh o orientation: ", a
423   -## print "orient com wxyz", b
424   - ##self.coilActor.SetPosition(x, y, z)
425   - ##self.ball_reference.SetCenter(x, y, z)
426   -
427   - def SetVolumeCamera(self, pubsub_evt):
428   -
429   - coord = pubsub_evt.data
430   -
431   - if len(coord) == 6:
432   - coord_camera = coord[0:3]
433   - angles = coord[3:6]
434   - else:
435   - coord_camera = coord[0:3]
436   - angles = None
437   -
438   - self.SetBallReferencePosition(coord_camera, angles)
439   -
440   - #Coronal Images dont require this transformation - 1 tested
441   - #and for this case, at navigation, the z axis is inverted
442   - coord_camera = np.array(bases.FlipX(coord_camera))
443   -
444   - cam = self.ren.GetActiveCamera()
445   -
446   - if self.initial_foco is None:
447   - self.initial_foco = np.array(cam.GetFocalPoint())
448   -
449   - cam_initialposition = np.array(cam.GetPosition())
450   - cam_initialfoco = np.array(cam.GetFocalPoint())
451   -
452   - cam_sub = cam_initialposition - cam_initialfoco
453   - cam_sub_norm = np.linalg.norm(cam_sub)
454   - #vet1 = cam_sub/cam_sub_norm
455   -
456   - cam_sub_novo = coord_camera - self.initial_foco
457   - cam_sub_novo_norm = np.linalg.norm(cam_sub_novo)
458   - vet2 = cam_sub_novo/cam_sub_novo_norm
459   - vet2 = vet2*cam_sub_norm + coord_camera
460   -
461   - cam.SetFocalPoint(coord_camera)
462   - cam.SetPosition(vet2)
463   -
464   - self.UpdateRender()
465   -
466   -
467   - # ----------------------------
468   -
469   - def CreateBallReference(self):
470   - MRAD = 3.0
471   - proj = prj.Project()
472   - s = proj.spacing
473   - # The sphere's radius will be MRAD times bigger than the media of the
474   - # spacing values.
475   - r = (s[0] + s[1] + s[2]) / 3.0 * MRAD
476   - self.ball_reference = vtk.vtkSphereSource()
477   - self.ball_reference.SetRadius(r)
478   -
479   - mapper = vtk.vtkPolyDataMapper()
480   - mapper.SetInput(self.ball_reference.GetOutput())
481   -
482   - p = vtk.vtkProperty()
483   - p.SetColor(1, 0, 0)
484   -
485   - self.ball_actor = vtk.vtkActor()
486   - self.ball_actor.SetMapper(mapper)
487   - self.ball_actor.SetProperty(p)
488   -
489   - def RemoveBallReference(self):
490   - self._ball_ref_visibility = False
491   - if self.ball_reference:
492   - self.ren.RemoveActor(self.ball_actor)
493   -
494   - def ActivateBallReference(self, pubsub_evt):
495   - self._mode_cross = True
496   - self._ball_ref_visibility = True
497   - if self._to_show_ball:
498   - if not self.ball_reference:
499   - self.CreateBallReference()
500   - self.ren.AddActor(self.ball_actor)
501   -
502   - def DeactivateBallReference(self, pubsub_evt):
503   - self._mode_cross = False
504   - self.RemoveBallReference()
505   -
506   - def _check_ball_reference(self, pubsub_evt):
507   - st = pubsub_evt.data
508   - if st == const.SLICE_STATE_CROSS:
509   - self._mode_cross = True
510   - self._check_and_set_ball_visibility()
511   - self.interactor.Render()
512   -
513   - def _uncheck_ball_reference(self, pubsub_evt):
514   - st = pubsub_evt.data
515   - if st == const.SLICE_STATE_CROSS:
516   - self._mode_cross = False
517   - self.RemoveBallReference()
518   - self.interactor.Render()
519   -
520   - def OnShowSurface(self, pubsub_evt):
521   - index, value = pubsub_evt.data
522   - if value:
523   - self._to_show_ball += 1
524   - else:
525   - self._to_show_ball -= 1
526   - self._check_and_set_ball_visibility()
527   - # see if these two next functions are being used
528   - def SetBallReferencePosition(self, pubsub_evt):
529   - x, y, z = pubsub_evt.data
530   - self.ball_reference.SetCenter(x, y, z)
531   -
532   - def SetBallReferencePositionBasedOnBound(self, pubsub_evt):
533   - if self._to_show_ball:
534   - self.ActivateBallReference(None)
535   - coord = pubsub_evt.data
536   - x, y, z = bases.FlipX(coord)
537   - self.ball_reference.SetCenter(x, y, z)
538   - else:
539   - self.DeactivateBallReference(None)
540   -
541   - def OnStartSeed(self, pubsub_evt):
542   - index = pubsub_evt.data
543   - self.seed_points = []
544   -
545   - def OnEndSeed(self, pubsub_evt):
546   - Publisher.sendMessage("Create surface from seeds",
547   - self.seed_points)
548   -
549   - def OnExportPicture(self, pubsub_evt):
550   - Publisher.sendMessage('Begin busy cursor')
551   - id, filename, filetype = pubsub_evt.data
552   - if id == const.VOLUME:
553   - if filetype == const.FILETYPE_POV:
554   - renwin = self.interactor.GetRenderWindow()
555   - image = vtk.vtkWindowToImageFilter()
556   - image.SetInput(renwin)
557   - writer = vtk.vtkPOVExporter()
558   - writer.SetFileName(filename)
559   - writer.SetRenderWindow(renwin)
560   - writer.Write()
561   - else:
562   - #Use tiling to generate a large rendering.
563   - image = vtk.vtkRenderLargeImage()
564   - image.SetInput(self.ren)
565   - image.SetMagnification(1)
566   -
567   - image = image.GetOutput()
568   -
569   - # write image file
570   - if (filetype == const.FILETYPE_BMP):
571   - writer = vtk.vtkBMPWriter()
572   - elif (filetype == const.FILETYPE_JPG):
573   - writer = vtk.vtkJPEGWriter()
574   - elif (filetype == const.FILETYPE_PNG):
575   - writer = vtk.vtkPNGWriter()
576   - elif (filetype == const.FILETYPE_PS):
577   - writer = vtk.vtkPostScriptWriter()
578   - elif (filetype == const.FILETYPE_TIF):
579   - writer = vtk.vtkTIFFWriter()
580   - filename = "%s.tif"%filename.strip(".tif")
581   -
582   - writer.SetInput(image)
583   - writer.SetFileName(filename)
584   - writer.Write()
585   - Publisher.sendMessage('End busy cursor')
586   -
587   - def OnCloseProject(self, pubsub_evt):
588   - if self.raycasting_volume:
589   - self.raycasting_volume = False
590   -
591   - if self.slice_plane:
592   - self.slice_plane.Disable()
593   - self.slice_plane.DeletePlanes()
594   - del self.slice_plane
595   - Publisher.sendMessage('Uncheck image plane menu')
596   - self.mouse_pressed = 0
597   - self.on_wl = False
598   - self.slice_plane = 0
599   -
600   - def OnHideText(self, pubsub_evt):
601   - self.text.Hide()
602   - self.interactor.Render()
603   -
604   - def OnShowText(self, pubsub_evt):
605   - if self.on_wl:
606   - self.text.Show()
607   - self.interactor.Render()
608   -
609   - def AddActors(self, pubsub_evt):
610   - "Inserting actors"
611   - actors = pubsub_evt.data[0]
612   - for actor in actors:
613   - self.ren.AddActor(actor)
614   -
615   - def RemoveVolume(self, pub_evt):
616   - volumes = self.ren.GetVolumes()
617   - if (volumes.GetNumberOfItems()):
618   - self.ren.RemoveVolume(volumes.GetLastProp())
619   - self.interactor.Render()
620   - self._to_show_ball -= 1
621   - self._check_and_set_ball_visibility()
622   -
623   - def RemoveActors(self, pubsub_evt):
624   - "Remove a list of actors"
625   - actors = pubsub_evt.data[0]
626   - for actor in actors:
627   - self.ren.RemoveActor(actor)
628   -
629   - def AddPointReference(self, position, radius=1, colour=(1, 0, 0)):
630   - """
631   - Add a point representation in the given x,y,z position with a optional
632   - radius and colour.
633   - """
634   - point = vtk.vtkSphereSource()
635   - point.SetCenter(position)
636   - point.SetRadius(radius)
637   -
638   - mapper = vtk.vtkPolyDataMapper()
639   - mapper.SetInput(point.GetOutput())
640   -
641   - p = vtk.vtkProperty()
642   - p.SetColor(colour)
643   -
644   - actor = vtk.vtkActor()
645   - actor.SetMapper(mapper)
646   - actor.SetProperty(p)
647   - actor.PickableOff()
648   -
649   - self.ren.AddActor(actor)
650   -
651   - self.points_reference.append(actor)
652   -
653   - def RemoveAllPointsReference(self):
654   - for actor in self.points_reference:
655   - self.ren.RemoveActor(actor)
656   - self.points_reference = []
657   -
658   - def RemovePointReference(self, point):
659   - """
660   - Remove the point reference. The point argument is the position that is
661   - added.
662   - """
663   - actor = self.points_reference.pop(point)
664   - self.ren.RemoveActor(actor)
665   -
666   - def __bind_events_wx(self):
667   - #self.Bind(wx.EVT_SIZE, self.OnSize)
668   - pass
669   -
670   - def SetInteractorStyle(self, state):
671   - action = {
672   - const.STATE_PAN:
673   - {
674   - "MouseMoveEvent": self.OnPanMove,
675   - "LeftButtonPressEvent": self.OnPanClick,
676   - "LeftButtonReleaseEvent": self.OnReleasePanClick
677   - },
678   - const.STATE_ZOOM:
679   - {
680   - "MouseMoveEvent": self.OnZoomMove,
681   - "LeftButtonPressEvent": self.OnZoomClick,
682   - "LeftButtonReleaseEvent": self.OnReleaseZoomClick,
683   - },
684   - const.STATE_SPIN:
685   - {
686   - "MouseMoveEvent": self.OnSpinMove,
687   - "LeftButtonPressEvent": self.OnSpinClick,
688   - "LeftButtonReleaseEvent": self.OnReleaseSpinClick,
689   - },
690   - const.STATE_WL:
691   - {
692   - "MouseMoveEvent": self.OnWindowLevelMove,
693   - "LeftButtonPressEvent": self.OnWindowLevelClick,
694   - "LeftButtonReleaseEvent":self.OnWindowLevelRelease
695   - },
696   - const.STATE_DEFAULT:
697   - {
698   - },
699   - const.VOLUME_STATE_SEED:
700   - {
701   - "LeftButtonPressEvent": self.OnInsertSeed
702   - },
703   - const.STATE_MEASURE_DISTANCE:
704   - {
705   - "LeftButtonPressEvent": self.OnInsertLinearMeasurePoint
706   - },
707   - const.STATE_MEASURE_ANGLE:
708   - {
709   - "LeftButtonPressEvent": self.OnInsertAngularMeasurePoint
710   - }
711   - }
712   -
713   - if self._last_state in (const.STATE_MEASURE_DISTANCE,
714   - const.STATE_MEASURE_ANGLE):
715   - if self.measures and not self.measures[-1].text_actor:
716   - del self.measures[-1]
717   -
718   - if state == const.STATE_WL:
719   - self.on_wl = True
720   - if self.raycasting_volume:
721   - self.text.Show()
722   - self.interactor.Render()
723   - else:
724   - self.on_wl = False
725   - self.text.Hide()
726   - self.interactor.Render()
727   -
728   - if state in (const.STATE_MEASURE_DISTANCE,
729   - const.STATE_MEASURE_ANGLE):
730   - self.interactor.SetPicker(self.measure_picker)
731   -
732   - if (state == const.STATE_ZOOM_SL):
733   - style = vtk.vtkInteractorStyleRubberBandZoom()
734   - self.interactor.SetInteractorStyle(style)
735   - self.style = style
736   - else:
737   - style = vtk.vtkInteractorStyleTrackballCamera()
738   - self.interactor.SetInteractorStyle(style)
739   - self.style = style
740   -
741   - # Check each event available for each mode
742   - for event in action[state]:
743   - # Bind event
744   - style.AddObserver(event,action[state][event])
745   -
746   - self._last_state = state
747   -
748   - def OnSpinMove(self, evt, obj):
749   - if (self.mouse_pressed):
750   - evt.Spin()
751   - evt.OnRightButtonDown()
752   -
753   - def OnSpinClick(self, evt, obj):
754   - self.mouse_pressed = 1
755   - evt.StartSpin()
756   -
757   - def OnReleaseSpinClick(self,evt,obj):
758   - self.mouse_pressed = 0
759   - evt.EndSpin()
760   -
761   - def OnZoomMove(self, evt, obj):
762   - if (self.mouse_pressed):
763   - evt.Dolly()
764   - evt.OnRightButtonDown()
765   -
766   - def OnZoomClick(self, evt, obj):
767   - self.mouse_pressed = 1
768   - evt.StartDolly()
769   -
770   - def OnReleaseZoomClick(self,evt,obj):
771   - self.mouse_pressed = 0
772   - evt.EndDolly()
773   -
774   - def OnPanMove(self, evt, obj):
775   - if (self.mouse_pressed):
776   - evt.Pan()
777   - evt.OnRightButtonDown()
778   -
779   - def OnPanClick(self, evt, obj):
780   - self.mouse_pressed = 1
781   - evt.StartPan()
782   -
783   - def OnReleasePanClick(self,evt,obj):
784   - self.mouse_pressed = 0
785   - evt.EndPan()
786   -
787   - def OnWindowLevelMove(self, obj, evt):
788   - if self.onclick and self.raycasting_volume:
789   - mouse_x, mouse_y = self.interactor.GetEventPosition()
790   - diff_x = mouse_x - self.last_x
791   - diff_y = mouse_y - self.last_y
792   - self.last_x, self.last_y = mouse_x, mouse_y
793   - Publisher.sendMessage('Set raycasting relative window and level',
794   - (diff_x, diff_y))
795   - Publisher.sendMessage('Refresh raycasting widget points', None)
796   - self.interactor.Render()
797   -
798   - def OnWindowLevelClick(self, obj, evt):
799   - if const.RAYCASTING_WWWL_BLUR:
800   - self.style.StartZoom()
801   - self.onclick = True
802   - mouse_x, mouse_y = self.interactor.GetEventPosition()
803   - self.last_x, self.last_y = mouse_x, mouse_y
804   -
805   - def OnWindowLevelRelease(self, obj, evt):
806   - self.onclick = False
807   - if const.RAYCASTING_WWWL_BLUR:
808   - self.style.EndZoom()
809   -
810   - def OnEnableStyle(self, pubsub_evt):
811   - state = pubsub_evt.data
812   - if (state in const.VOLUME_STYLES):
813   - new_state = self.interaction_style.AddState(state)
814   - self.SetInteractorStyle(new_state)
815   - else:
816   - new_state = self.interaction_style.RemoveState(state)
817   - self.SetInteractorStyle(new_state)
818   -
819   - def OnDisableStyle(self, pubsub_evt):
820   - state = pubsub_evt.data
821   - new_state = self.interaction_style.RemoveState(state)
822   - self.SetInteractorStyle(new_state)
823   -
824   - def ResetCamClippingRange(self, pubsub_evt):
825   - self.ren.ResetCamera()
826   - self.ren.ResetCameraClippingRange()
827   -
828   - def SetVolumeCamera(self, pubsub_evt):
829   -
830   - coord_camera = pubsub_evt.data
831   - coord_camera = numpy.array(bases.FlipX(coord_camera))
832   -
833   - cam = self.ren.GetActiveCamera()
834   -
835   - if self.initial_foco is None:
836   - self.initial_foco = numpy.array(cam.GetFocalPoint())
837   -
838   - cam_initialposition = numpy.array(cam.GetPosition())
839   - cam_initialfoco = numpy.array(cam.GetFocalPoint())
840   -
841   - cam_sub = cam_initialposition - cam_initialfoco
842   - cam_sub_norm = numpy.linalg.norm(cam_sub)
843   - vet1 = cam_sub/cam_sub_norm
844   -
845   - cam_sub_novo = coord_camera - self.initial_foco
846   - cam_sub_novo_norm = numpy.linalg.norm(cam_sub_novo)
847   - vet2 = cam_sub_novo/cam_sub_novo_norm
848   - vet2 = vet2*cam_sub_norm + coord_camera
849   -
850   - cam.SetFocalPoint(coord_camera)
851   - cam.SetPosition(vet2)
852   -
853   - def OnExportSurface(self, pubsub_evt):
854   - filename, filetype = pubsub_evt.data
855   - fileprefix = filename.split(".")[-2]
856   - renwin = self.interactor.GetRenderWindow()
857   -
858   - if filetype == const.FILETYPE_RIB:
859   - writer = vtk.vtkRIBExporter()
860   - writer.SetFilePrefix(fileprefix)
861   - writer.SetTexturePrefix(fileprefix)
862   - writer.SetInput(renwin)
863   - writer.Write()
864   - elif filetype == const.FILETYPE_VRML:
865   - writer = vtk.vtkVRMLExporter()
866   - writer.SetFileName(filename)
867   - writer.SetInput(renwin)
868   - writer.Write()
869   - elif filetype == const.FILETYPE_X3D:
870   - writer = vtk.vtkX3DExporter()
871   - writer.SetInput(renwin)
872   - writer.SetFileName(filename)
873   - writer.Update()
874   - writer.Write()
875   - elif filetype == const.FILETYPE_OBJ:
876   - writer = vtk.vtkOBJExporter()
877   - writer.SetFilePrefix(fileprefix)
878   - writer.SetInput(renwin)
879   - writer.Write()
880   - elif filetype == const.FILETYPE_IV:
881   - writer = vtk.vtkIVExporter()
882   - writer.SetFileName(filename)
883   - writer.SetInput(renwin)
884   - writer.Write()
885   -
886   - def OnEnableBrightContrast(self, pubsub_evt):
887   - style = self.style
888   - style.AddObserver("MouseMoveEvent", self.OnMove)
889   - style.AddObserver("LeftButtonPressEvent", self.OnClick)
890   - style.AddObserver("LeftButtonReleaseEvent", self.OnRelease)
891   -
892   - def OnDisableBrightContrast(self, pubsub_evt):
893   - style = vtk.vtkInteractorStyleTrackballCamera()
894   - self.interactor.SetInteractorStyle(style)
895   - self.style = style
896   -
897   - def OnSetWindowLevelText(self, pubsub_evt):
898   - if self.raycasting_volume:
899   - ww, wl = pubsub_evt.data
900   - self.text.SetValue("WL: %d WW: %d"%(wl, ww))
901   -
902   - def OnShowRaycasting(self, pubsub_evt):
903   - if not self.raycasting_volume:
904   - self.raycasting_volume = True
905   - self._to_show_ball += 1
906   - self._check_and_set_ball_visibility()
907   - if self.on_wl:
908   - self.text.Show()
909   -
910   - def OnHideRaycasting(self, pubsub_evt):
911   - self.raycasting_volume = False
912   - self.text.Hide()
913   - self._to_show_ball -= 1
914   - self._check_and_set_ball_visibility()
915   -
916   - def OnSize(self, evt):
917   - self.UpdateRender()
918   - self.Refresh()
919   - self.interactor.UpdateWindowUI()
920   - self.interactor.Update()
921   - evt.Skip()
922   -
923   - def ChangeBackgroundColour(self, pubsub_evt):
924   - colour = pubsub_evt.data
925   - self.ren.SetBackground(colour)
926   - self.UpdateRender()
927   -
928   - def LoadActor(self, pubsub_evt):
929   - actor = pubsub_evt.data
930   - self.added_actor = 1
931   - ren = self.ren
932   - ren.AddActor(actor)
933   -
934   - if not (self.view_angle):
935   - self.SetViewAngle(const.VOL_FRONT)
936   - self.view_angle = 1
937   - else:
938   - ren.ResetCamera()
939   - ren.ResetCameraClippingRange()
940   -
941   - #self.ShowOrientationCube()
942   - self.interactor.Render()
943   - self._to_show_ball += 1
944   - self._check_and_set_ball_visibility()
945   -
946   - def RemoveActor(self, pubsub_evt):
947   - utils.debug("RemoveActor")
948   - actor = pubsub_evt.data
949   - ren = self.ren
950   - ren.RemoveActor(actor)
951   - self.interactor.Render()
952   - self._to_show_ball -= 1
953   - self._check_and_set_ball_visibility()
954   -
955   - #=====aji==================================================================
956   - try:
957   - Publisher.sendMessage('Del actor volume')
958   - except:
959   - None
960   - #=======================================================================
961   -
962   - def RemoveAllActor(self, pubsub_evt):
963   - utils.debug("RemoveAllActor")
964   - self.ren.RemoveAllProps()
965   - Publisher.sendMessage('Render volume viewer')
966   -
967   -
968   - def LoadSlicePlane(self, pubsub_evt):
969   - self.slice_plane = SlicePlane()
970   -
971   - def LoadVolume(self, pubsub_evt):
972   - self.raycasting_volume = True
973   - #self._to_show_ball += 1
974   -
975   - volume = pubsub_evt.data[0]
976   - colour = pubsub_evt.data[1]
977   - ww, wl = pubsub_evt.data[2]
978   -
979   - self.light = self.ren.GetLights().GetNextItem()
980   -
981   - self.ren.AddVolume(volume)
982   - self.text.SetValue("WL: %d WW: %d"%(wl, ww))
983   -
984   - if self.on_wl:
985   - self.text.Show()
986   - else:
987   - self.text.Hide()
988   -
989   - self.ren.SetBackground(colour)
990   -
991   - if not (self.view_angle):
992   - self.SetViewAngle(const.VOL_FRONT)
993   - else:
994   - self.ren.ResetCamera()
995   - self.ren.ResetCameraClippingRange()
996   -
997   - self._check_and_set_ball_visibility()
998   - self.UpdateRender()
999   -
1000   - def UnloadVolume(self, pubsub_evt):
1001   - volume = pubsub_evt.data
1002   - self.ren.RemoveVolume(volume)
1003   - del volume
1004   - self.raycasting_volume = False
1005   - self._to_show_ball -= 1
1006   - self._check_and_set_ball_visibility()
1007   -
1008   - def OnSetViewAngle(self, evt_pubsub):
1009   - view = evt_pubsub.data
1010   - self.SetViewAngle(view)
1011   -
1012   - def SetViewAngle(self, view):
1013   - cam = self.ren.GetActiveCamera()
1014   - cam.SetFocalPoint(0,0,0)
1015   -
1016   - proj = prj.Project()
1017   - orig_orien = proj.original_orientation
1018   -
1019   - xv,yv,zv = const.VOLUME_POSITION[const.AXIAL][0][view]
1020   - xp,yp,zp = const.VOLUME_POSITION[const.AXIAL][1][view]
1021   -
1022   - cam.SetViewUp(xv,yv,zv)
1023   - cam.SetPosition(xp,yp,zp)
1024   -
1025   - self.ren.ResetCameraClippingRange()
1026   - self.ren.ResetCamera()
1027   - self.interactor.Render()
1028   -
1029   - def ShowOrientationCube(self):
1030   - cube = vtk.vtkAnnotatedCubeActor()
1031   - cube.GetXMinusFaceProperty().SetColor(1,0,0)
1032   - cube.GetXPlusFaceProperty().SetColor(1,0,0)
1033   - cube.GetYMinusFaceProperty().SetColor(0,1,0)
1034   - cube.GetYPlusFaceProperty().SetColor(0,1,0)
1035   - cube.GetZMinusFaceProperty().SetColor(0,0,1)
1036   - cube.GetZPlusFaceProperty().SetColor(0,0,1)
1037   - cube.GetTextEdgesProperty().SetColor(0,0,0)
1038   -
1039   - # anatomic labelling
1040   - cube.SetXPlusFaceText ("A")
1041   - cube.SetXMinusFaceText("P")
1042   - cube.SetYPlusFaceText ("L")
1043   - cube.SetYMinusFaceText("R")
1044   - cube.SetZPlusFaceText ("S")
1045   - cube.SetZMinusFaceText("I")
1046   -
1047   - axes = vtk.vtkAxesActor()
1048   - axes.SetShaftTypeToCylinder()
1049   - axes.SetTipTypeToCone()
1050   - axes.SetXAxisLabelText("X")
1051   - axes.SetYAxisLabelText("Y")
1052   - axes.SetZAxisLabelText("Z")
1053   - #axes.SetNormalizedLabelPosition(.5, .5, .5)
1054   -
1055   - orientation_widget = vtk.vtkOrientationMarkerWidget()
1056   - orientation_widget.SetOrientationMarker(cube)
1057   - orientation_widget.SetViewport(0.85,0.85,1.0,1.0)
1058   - #orientation_widget.SetOrientationMarker(axes)
1059   - orientation_widget.SetInteractor(self.interactor)
1060   - orientation_widget.SetEnabled(1)
1061   - orientation_widget.On()
1062   - orientation_widget.InteractiveOff()
1063   -
1064   - def UpdateRender(self, evt_pubsub=None):
1065   - self.interactor.Render()
1066   -
1067   - def SetWidgetInteractor(self, evt_pubsub=None):
1068   - evt_pubsub.data.SetInteractor(self.interactor._Iren)
1069   -
1070   - def AppendActor(self, evt_pubsub=None):
1071   - self.ren.AddActor(evt_pubsub.data)
1072   -
1073   - def OnInsertSeed(self, obj, evt):
1074   - x,y = self.interactor.GetEventPosition()
1075   - #x,y = obj.GetLastEventPosition()
1076   - self.picker.Pick(x, y, 0, self.ren)
1077   - point_id = self.picker.GetPointId()
1078   - self.seed_points.append(point_id)
1079   - self.interactor.Render()
1080   -
1081   - def OnInsertLinearMeasurePoint(self, obj, evt):
1082   - x,y = self.interactor.GetEventPosition()
1083   - self.measure_picker.Pick(x, y, 0, self.ren)
1084   - x, y, z = self.measure_picker.GetPickPosition()
1085   -
1086   - proj = prj.Project()
1087   - radius = min(proj.spacing) * PROP_MEASURE
1088   - if self.measure_picker.GetActor():
1089   - # if not self.measures or self.measures[-1].IsComplete():
1090   - # m = measures.LinearMeasure(self.ren)
1091   - # m.AddPoint(x, y, z)
1092   - # self.measures.append(m)
1093   - # else:
1094   - # m = self.measures[-1]
1095   - # m.AddPoint(x, y, z)
1096   - # if m.IsComplete():
1097   - # Publisher.sendMessage("Add measure to list",
1098   - # (u"3D", _(u"%.3f mm" % m.GetValue())))
1099   - Publisher.sendMessage("Add measurement point",
1100   - ((x, y,z), const.LINEAR, const.SURFACE, radius))
1101   - self.interactor.Render()
1102   -
1103   - def OnInsertAngularMeasurePoint(self, obj, evt):
1104   - x,y = self.interactor.GetEventPosition()
1105   - self.measure_picker.Pick(x, y, 0, self.ren)
1106   - x, y, z = self.measure_picker.GetPickPosition()
1107   -
1108   - proj = prj.Project()
1109   - radius = min(proj.spacing) * PROP_MEASURE
1110   - if self.measure_picker.GetActor():
1111   - # if not self.measures or self.measures[-1].IsComplete():
1112   - # m = measures.AngularMeasure(self.ren)
1113   - # m.AddPoint(x, y, z)
1114   - # self.measures.append(m)
1115   - # else:
1116   - # m = self.measures[-1]
1117   - # m.AddPoint(x, y, z)
1118   - # if m.IsComplete():
1119   - # index = len(self.measures) - 1
1120   - # name = "M"
1121   - # colour = m.colour
1122   - # type_ = _("Angular")
1123   - # location = u"3D"
1124   - # value = u"%.2f˚"% m.GetValue()
1125   - # msg = 'Update measurement info in GUI',
1126   - # Publisher.sendMessage(msg,
1127   - # (index, name, colour,
1128   - # type_, location,
1129   - # value))
1130   - Publisher.sendMessage("Add measurement point",
1131   - ((x, y,z), const.ANGULAR, const.SURFACE, radius))
1132   - self.interactor.Render()
1133   -
1134   - def Reposition3DPlane(self, evt_pubsub):
1135   - position = evt_pubsub.data
1136   - if not(self.added_actor) and not(self.raycasting_volume):
1137   - if not(self.repositioned_axial_plan) and (position == 'Axial'):
1138   - self.SetViewAngle(const.VOL_ISO)
1139   - self.repositioned_axial_plan = 1
1140   -
1141   - elif not(self.repositioned_sagital_plan) and (position == 'Sagital'):
1142   - self.SetViewAngle(const.VOL_ISO)
1143   - self.repositioned_sagital_plan = 1
1144   -
1145   - elif not(self.repositioned_coronal_plan) and (position == 'Coronal'):
1146   - self.SetViewAngle(const.VOL_ISO)
1147   - self.repositioned_coronal_plan = 1
1148   -
1149   - def _check_and_set_ball_visibility(self):
1150   - if self._mode_cross:
1151   - if self._to_show_ball > 0 and not self._ball_ref_visibility:
1152   - self.ActivateBallReference(None)
1153   - self.interactor.Render()
1154   - elif not self._to_show_ball and self._ball_ref_visibility:
1155   - self.RemoveBallReference()
1156   - self.interactor.Render()
1157   -
1158   -
1159   -class SlicePlane:
1160   - def __init__(self):
1161   - project = prj.Project()
1162   - self.original_orientation = project.original_orientation
1163   - self.Create()
1164   - self.enabled = False
1165   - self.__bind_evt()
1166   -
1167   - def __bind_evt(self):
1168   - Publisher.subscribe(self.Enable, 'Enable plane')
1169   - Publisher.subscribe(self.Disable, 'Disable plane')
1170   - Publisher.subscribe(self.ChangeSlice, 'Change slice from slice plane')
1171   - Publisher.subscribe(self.UpdateAllSlice, 'Update all slice')
1172   -
1173   - def Create(self):
1174   - plane_x = self.plane_x = vtk.vtkImagePlaneWidget()
1175   - plane_x.InteractionOff()
1176   - #Publisher.sendMessage('Input Image in the widget',
1177   - #(plane_x, 'SAGITAL'))
1178   - plane_x.SetPlaneOrientationToXAxes()
1179   - plane_x.TextureVisibilityOn()
1180   - plane_x.SetLeftButtonAction(0)
1181   - plane_x.SetRightButtonAction(0)
1182   - plane_x.SetMiddleButtonAction(0)
1183   - cursor_property = plane_x.GetCursorProperty()
1184   - cursor_property.SetOpacity(0)
1185   -
1186   - plane_y = self.plane_y = vtk.vtkImagePlaneWidget()
1187   - plane_y.DisplayTextOff()
1188   - #Publisher.sendMessage('Input Image in the widget',
1189   - #(plane_y, 'CORONAL'))
1190   - plane_y.SetPlaneOrientationToYAxes()
1191   - plane_y.TextureVisibilityOn()
1192   - plane_y.SetLeftButtonAction(0)
1193   - plane_y.SetRightButtonAction(0)
1194   - plane_y.SetMiddleButtonAction(0)
1195   - prop1 = plane_y.GetPlaneProperty()
1196   - cursor_property = plane_y.GetCursorProperty()
1197   - cursor_property.SetOpacity(0)
1198   -
1199   - plane_z = self.plane_z = vtk.vtkImagePlaneWidget()
1200   - plane_z.InteractionOff()
1201   - #Publisher.sendMessage('Input Image in the widget',
1202   - #(plane_z, 'AXIAL'))
1203   - plane_z.SetPlaneOrientationToZAxes()
1204   - plane_z.TextureVisibilityOn()
1205   - plane_z.SetLeftButtonAction(0)
1206   - plane_z.SetRightButtonAction(0)
1207   - plane_z.SetMiddleButtonAction(0)
1208   -
1209   - cursor_property = plane_z.GetCursorProperty()
1210   - cursor_property.SetOpacity(0)
1211   -
1212   -
1213   - prop3 = plane_z.GetPlaneProperty()
1214   - prop3.SetColor(1, 0, 0)
1215   -
1216   - selected_prop3 = plane_z.GetSelectedPlaneProperty()
1217   - selected_prop3.SetColor(1,0,0)
1218   -
1219   - prop1 = plane_x.GetPlaneProperty()
1220   - prop1.SetColor(0, 0, 1)
1221   -
1222   - selected_prop1 = plane_x.GetSelectedPlaneProperty()
1223   - selected_prop1.SetColor(0, 0, 1)
1224   -
1225   - prop2 = plane_y.GetPlaneProperty()
1226   - prop2.SetColor(0, 1, 0)
1227   -
1228   - selected_prop2 = plane_y.GetSelectedPlaneProperty()
1229   - selected_prop2.SetColor(0, 1, 0)
1230   -
1231   - Publisher.sendMessage('Set Widget Interactor', plane_x)
1232   - Publisher.sendMessage('Set Widget Interactor', plane_y)
1233   - Publisher.sendMessage('Set Widget Interactor', plane_z)
1234   -
1235   - self.Render()
1236   -
1237   - def Enable(self, evt_pubsub=None):
1238   - if (evt_pubsub):
1239   - label = evt_pubsub.data
1240   - if(label == "Axial"):
1241   - self.plane_z.On()
1242   - elif(label == "Coronal"):
1243   - self.plane_y.On()
1244   - elif(label == "Sagital"):
1245   - self.plane_x.On()
1246   -
1247   - Publisher.sendMessage('Reposition 3D Plane', label)
1248   -
1249   - else:
1250   - self.plane_z.On()
1251   - self.plane_x.On()
1252   - self.plane_y.On()
1253   - Publisher.sendMessage('Set volume view angle', const.VOL_ISO)
1254   - self.Render()
1255   -
1256   - def Disable(self, evt_pubsub=None):
1257   - if (evt_pubsub):
1258   - label = evt_pubsub.data
1259   - if(label == "Axial"):
1260   - self.plane_z.Off()
1261   - elif(label == "Coronal"):
1262   - self.plane_y.Off()
1263   - elif(label == "Sagital"):
1264   - self.plane_x.Off()
1265   - else:
1266   - self.plane_z.Off()
1267   - self.plane_x.Off()
1268   - self.plane_y.Off()
1269   -
1270   - self.Render()
1271   -
1272   - def Render(self):
1273   - Publisher.sendMessage('Render volume viewer')
1274   -
1275   - def ChangeSlice(self, pubsub_evt = None):
1276   - orientation, number = pubsub_evt.data
1277   -
1278   - if orientation == "CORONAL" and self.plane_y.GetEnabled():
1279   - Publisher.sendMessage('Update slice 3D', (self.plane_y,orientation))
1280   - self.Render()
1281   - elif orientation == "SAGITAL" and self.plane_x.GetEnabled():
1282   - Publisher.sendMessage('Update slice 3D', (self.plane_x,orientation))
1283   - self.Render()
1284   - elif orientation == 'AXIAL' and self.plane_z.GetEnabled() :
1285   - Publisher.sendMessage('Update slice 3D', (self.plane_z,orientation))
1286   - self.Render()
1287   -
1288   - def UpdateAllSlice(self, pubsub_evt):
1289   - Publisher.sendMessage('Update slice 3D', (self.plane_y,"CORONAL"))
1290   - Publisher.sendMessage('Update slice 3D', (self.plane_x,"SAGITAL"))
1291   - Publisher.sendMessage('Update slice 3D', (self.plane_z,"AXIAL"))
1292   -
1293   -
1294   - def DeletePlanes(self):
1295   - del self.plane_x
1296   - del self.plane_y
1297   - del self.plane_z
1298   -
1299   -
invesalius/tests/def_import.py
... ... @@ -1,10 +0,0 @@
1   -__author__ = 'Victor'
2   -
3   -import bases
4   -
5   -a = [1, 2, 3]
6   -b = [2, 5, 7]
7   -c = [6, 2, 8]
8   -
9   -# M, q, Minv = bases.Bases(a, b, c).Basecreation()
10   -M, q, inv = base_creation(a, b, c)