Commit 1b7ed2587b3a1688f9be4a0153784683e5042cb4
1 parent
ba1f3dd5
Exists in
usp-navegador
FIX: Fixing errors of git usage.
Showing
12 changed files
with
0 additions
and
9389 deletions
Show diff stats
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 | ||
52 | - print"q: ", q | |
53 | ||
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 | - |