Commit cd0cef0954f13add478e94eb9795808562db9a0c

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent 8ba6ba8d
Exists in master

Remove vtkgdcm (#201)

* generating thumbs only using gdcm + numpy

* applying intercept slop

* generating thumbnails and slices without vtkgdcmreader

* Using numpy and gdcm in dicom_preview_panel

* loading multiframe dicom

* working with rgb dicoms

* little improvements

* removed all vtkgdcm importing

* getting spacing from gdcmimagereader
invesalius/control.py
@@ -824,7 +824,6 @@ class Controller(): @@ -824,7 +824,6 @@ class Controller():
824 self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, 824 self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size,
825 orientation, resolution_percentage) 825 orientation, resolution_percentage)
826 826
827 - print(xyspacing, zspacing)  
828 if orientation == 'AXIAL': 827 if orientation == 'AXIAL':
829 spacing = xyspacing[0], xyspacing[1], zspacing 828 spacing = xyspacing[0], xyspacing[1], zspacing
830 elif orientation == 'CORONAL': 829 elif orientation == 'CORONAL':
@@ -832,7 +831,10 @@ class Controller(): @@ -832,7 +831,10 @@ class Controller():
832 elif orientation == 'SAGITTAL': 831 elif orientation == 'SAGITTAL':
833 spacing = zspacing, xyspacing[1], xyspacing[0] 832 spacing = zspacing, xyspacing[1], xyspacing[0]
834 else: 833 else:
835 - self.matrix, spacing, scalar_range, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation) 834 + print(">>>>>> filelist", filelist)
  835 + self.matrix, scalar_range, spacing, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation)
  836 +
  837 + print(">>>>>> spacing", spacing)
836 838
837 self.Slice = sl.Slice() 839 self.Slice = sl.Slice()
838 self.Slice.matrix = self.matrix 840 self.Slice.matrix = self.matrix
invesalius/data/converters.py
@@ -17,10 +17,13 @@ @@ -17,10 +17,13 @@
17 # detalhes. 17 # detalhes.
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 19
20 -import numpy 20 +import gdcm
  21 +import numpy as np
21 import vtk 22 import vtk
  23 +
22 from vtk.util import numpy_support 24 from vtk.util import numpy_support
23 25
  26 +
24 def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)): 27 def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)):
25 28
26 if orientation == "SAGITTAL": 29 if orientation == "SAGITTAL":
@@ -84,3 +87,40 @@ def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)): @@ -84,3 +87,40 @@ def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)):
84 image.GetPointData().SetScalars(v_image) 87 image.GetPointData().SetScalars(v_image)
85 88
86 return image 89 return image
  90 +
  91 +
  92 +# Based on http://gdcm.sourceforge.net/html/ConvertNumpy_8py-example.html
  93 +def gdcm_to_numpy(image, apply_intercep_scale=True):
  94 + map_gdcm_np = {
  95 + gdcm.PixelFormat.UINT8 :np.uint8,
  96 + gdcm.PixelFormat.INT8 :np.int8,
  97 + #gdcm.PixelFormat.UINT12 :np.uint12,
  98 + #gdcm.PixelFormat.INT12 :np.int12,
  99 + gdcm.PixelFormat.UINT16 :np.uint16,
  100 + gdcm.PixelFormat.INT16 :np.int16,
  101 + gdcm.PixelFormat.UINT32 :np.uint32,
  102 + gdcm.PixelFormat.INT32 :np.int32,
  103 + #gdcm.PixelFormat.FLOAT16:np.float16,
  104 + gdcm.PixelFormat.FLOAT32:np.float32,
  105 + gdcm.PixelFormat.FLOAT64:np.float64,
  106 + }
  107 +
  108 + pf = image.GetPixelFormat()
  109 + if image.GetNumberOfDimensions() == 3:
  110 + shape = image.GetDimension(2), image.GetDimension(1), image.GetDimension(0), pf.GetSamplesPerPixel()
  111 + else:
  112 + shape = image.GetDimension(1), image.GetDimension(0), pf.GetSamplesPerPixel()
  113 + dtype = map_gdcm_np[pf.GetScalarType()]
  114 + gdcm_array = image.GetBuffer()
  115 + np_array = np.frombuffer(gdcm_array.encode('utf-8', errors="surrogateescape"), dtype=dtype)
  116 + np_array.shape = shape
  117 + np_array = np_array.squeeze()
  118 +
  119 + if apply_intercep_scale:
  120 + shift = image.GetIntercept()
  121 + scale = image.GetSlope()
  122 + output = np.empty_like(np_array, np.int16)
  123 + output[:] = scale * np_array + shift
  124 + return output
  125 + else:
  126 + return np_array
invesalius/data/imagedata_utils.py
@@ -23,9 +23,10 @@ import sys @@ -23,9 +23,10 @@ import sys
23 import tempfile 23 import tempfile
24 24
25 import gdcm 25 import gdcm
  26 +import imageio
26 import numpy 27 import numpy
  28 +import numpy as np
27 import vtk 29 import vtk
28 -import vtkgdcm  
29 from wx.lib.pubsub import pub as Publisher 30 from wx.lib.pubsub import pub as Publisher
30 31
31 from scipy.ndimage import shift, zoom 32 from scipy.ndimage import shift, zoom
@@ -124,20 +125,15 @@ def resize_slice(im_array, resolution_percentage): @@ -124,20 +125,15 @@ def resize_slice(im_array, resolution_percentage):
124 return out 125 return out
125 126
126 127
127 -def read_dcm_slice_as_np(filename, resolution_percentage=1.0):  
128 - """  
129 - read a dicom slice file and return the slice as numpy ndarray  
130 - """  
131 - dcm_reader = vtkgdcm.vtkGDCMImageReader()  
132 - dcm_reader.SetFileName(filename)  
133 - dcm_reader.Update()  
134 - image = dcm_reader.GetOutput() 128 +def read_dcm_slice_as_np2(filename, resolution_percentage=1.0):
  129 + reader = gdcm.ImageReader()
  130 + reader.SetFileName(filename)
  131 + reader.Read()
  132 + image = reader.GetImage()
  133 + output = converters.gdcm_to_numpy(image)
135 if resolution_percentage < 1.0: 134 if resolution_percentage < 1.0:
136 - image = ResampleImage2D(image, resolution_percentage=resolution_percentage)  
137 - dx, dy, dz = image.GetDimensions()  
138 - im_array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())  
139 - im_array.shape = dy, dx  
140 - return im_array 135 + output = zoom(output, resolution_percentage)
  136 + return output
141 137
142 138
143 def FixGantryTilt(matrix, spacing, tilt): 139 def FixGantryTilt(matrix, spacing, tilt):
@@ -240,17 +236,6 @@ def View(imagedata): @@ -240,17 +236,6 @@ def View(imagedata):
240 import time 236 import time
241 time.sleep(10) 237 time.sleep(10)
242 238
243 -def ViewGDCM(imagedata):  
244 - viewer = vtkgdcm.vtkImageColorViewer()  
245 - viewer.SetInput(reader.GetOutput())  
246 - viewer.SetColorWindow(500.)  
247 - viewer.SetColorLevel(50.)  
248 - viewer.Render()  
249 -  
250 - import time  
251 - time.sleep(5)  
252 -  
253 -  
254 239
255 def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): 240 def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf):
256 """ 241 """
@@ -265,267 +250,33 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): @@ -265,267 +250,33 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf):
265 return voi.GetOutput() 250 return voi.GetOutput()
266 251
267 252
268 -def create_dicom_thumbnails(filename, window=None, level=None):  
269 - rvtk = vtkgdcm.vtkGDCMImageReader()  
270 - rvtk.SetFileName(utils.encode(filename, const.FS_ENCODE))  
271 - rvtk.Update()  
272 -  
273 - img = rvtk.GetOutput() 253 +def create_dicom_thumbnails(image, window=None, level=None):
  254 + pf = image.GetPixelFormat()
  255 + np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1)
274 if window is None or level is None: 256 if window is None or level is None:
275 - _min, _max = img.GetScalarRange() 257 + _min, _max = np_image.min(), np_image.max()
276 window = _max - _min 258 window = _max - _min
277 level = _min + window / 2 259 level = _min + window / 2
278 260
279 - dx, dy, dz = img.GetDimensions()  
280 -  
281 - if dz > 1: 261 + if image.GetNumberOfDimensions() >= 3:
282 thumbnail_paths = [] 262 thumbnail_paths = []
283 - for i in range(dz):  
284 - img_slice = ExtractVOI(img, 0, dx-1, 0, dy-1, i, i+1)  
285 -  
286 - colorer = vtk.vtkImageMapToWindowLevelColors()  
287 - colorer.SetInputData(img_slice)  
288 - colorer.SetWindow(window)  
289 - colorer.SetLevel(level)  
290 - colorer.SetOutputFormatToRGB()  
291 - colorer.Update()  
292 -  
293 - resample = vtk.vtkImageResample()  
294 - resample.SetInputData(colorer.GetOutput())  
295 - resample.SetAxisMagnificationFactor ( 0, 0.25 )  
296 - resample.SetAxisMagnificationFactor ( 1, 0.25 )  
297 - resample.SetAxisMagnificationFactor ( 2, 1 )  
298 - resample.Update()  
299 -  
300 - thumbnail_path = tempfile.mktemp()  
301 -  
302 - write_png = vtk.vtkPNGWriter()  
303 - write_png.SetInputData(resample.GetOutput())  
304 - write_png.SetFileName(thumbnail_path)  
305 - write_png.Write()  
306 - 263 + for i in range(np_image.shape[0]):
  264 + thumb_image = zoom(np_image[i], 0.25)
  265 + thumb_image = np.array(get_LUT_value_255(thumb_image, window, level), dtype=np.uint8)
  266 + thumbnail_path = tempfile.mktemp(prefix='thumb_', suffix='.png')
  267 + imageio.imsave(thumbnail_path, thumb_image)
307 thumbnail_paths.append(thumbnail_path) 268 thumbnail_paths.append(thumbnail_path)
308 -  
309 return thumbnail_paths 269 return thumbnail_paths
310 else: 270 else:
311 - colorer = vtk.vtkImageMapToWindowLevelColors()  
312 - colorer.SetInputData(img)  
313 - colorer.SetWindow(window)  
314 - colorer.SetLevel(level)  
315 - colorer.SetOutputFormatToRGB()  
316 - colorer.Update()  
317 -  
318 - resample = vtk.vtkImageResample()  
319 - resample.SetInputData(colorer.GetOutput())  
320 - resample.SetAxisMagnificationFactor ( 0, 0.25 )  
321 - resample.SetAxisMagnificationFactor ( 1, 0.25 )  
322 - resample.SetAxisMagnificationFactor ( 2, 1 )  
323 - resample.Update()  
324 -  
325 - thumbnail_path = tempfile.mktemp()  
326 -  
327 - write_png = vtk.vtkPNGWriter()  
328 - write_png.SetInputData(resample.GetOutput())  
329 - write_png.SetFileName(thumbnail_path)  
330 - write_png.Write()  
331 -  
332 - return thumbnail_path  
333 -  
334 -  
335 -def CreateImageData(filelist, zspacing, xyspacing,size,  
336 - bits, use_dcmspacing):  
337 - message = _("Generating multiplanar visualization...")  
338 -  
339 - if not const.VTK_WARNING:  
340 - log_path = os.path.join(inv_paths.USER_LOG_DIR, 'vtkoutput.txt')  
341 - fow = vtk.vtkFileOutputWindow()  
342 - fow.SetFileName(log_path)  
343 - ow = vtk.vtkOutputWindow()  
344 - ow.SetInstance(fow)  
345 -  
346 - x,y = size  
347 - px, py = utils.predict_memory(len(filelist), x, y, bits)  
348 -  
349 - utils.debug("Image Resized to >>> %f x %f" % (px, py))  
350 -  
351 - if (x == px) and (y == py):  
352 - const.REDUCE_IMAGEDATA_QUALITY = 0  
353 - else:  
354 - const.REDUCE_IMAGEDATA_QUALITY = 1  
355 -  
356 - if not(const.REDUCE_IMAGEDATA_QUALITY):  
357 - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog")  
358 -  
359 - array = vtk.vtkStringArray()  
360 - for x in range(len(filelist)):  
361 - array.InsertValue(x,filelist[x])  
362 -  
363 - reader = vtkgdcm.vtkGDCMImageReader()  
364 - reader.SetFileNames(array)  
365 - reader.AddObserver("ProgressEvent", lambda obj,evt:  
366 - update_progress(reader,message))  
367 - reader.Update()  
368 -  
369 - # The zpacing is a DicomGroup property, so we need to set it  
370 - imagedata = vtk.vtkImageData()  
371 - imagedata.DeepCopy(reader.GetOutput())  
372 - if (use_dcmspacing):  
373 - spacing = xyspacing  
374 - spacing[2] = zspacing  
375 - else:  
376 - spacing = imagedata.GetSpacing()  
377 -  
378 - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)  
379 - else:  
380 -  
381 - update_progress= vtk_utils.ShowProgress(2*len(filelist),  
382 - dialog_type = "ProgressDialog")  
383 -  
384 - # Reformat each slice and future append them  
385 - appender = vtk.vtkImageAppend()  
386 - appender.SetAppendAxis(2) #Define Stack in Z  
387 -  
388 -  
389 - # Reformat each slice  
390 - for x in range(len(filelist)):  
391 - # TODO: We need to check this automatically according  
392 - # to each computer's architecture  
393 - # If the resolution of the matrix is too large  
394 - reader = vtkgdcm.vtkGDCMImageReader()  
395 - reader.SetFileName(filelist[x])  
396 - reader.AddObserver("ProgressEvent", lambda obj,evt:  
397 - update_progress(reader,message))  
398 - reader.Update()  
399 -  
400 - if (use_dcmspacing):  
401 - spacing = xyspacing  
402 - spacing[2] = zspacing  
403 - else:  
404 - spacing = reader.GetOutput().GetSpacing()  
405 -  
406 - tmp_image = vtk.vtkImageData()  
407 - tmp_image.DeepCopy(reader.GetOutput())  
408 - tmp_image.SetSpacing(spacing[0], spacing[1], zspacing)  
409 - tmp_image.Update()  
410 -  
411 - #Resample image in x,y dimension  
412 - slice_imagedata = ResampleImage2D(tmp_image, px, py, update_progress)  
413 - #Stack images in Z axes  
414 - appender.AddInput(slice_imagedata)  
415 - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender))  
416 - appender.Update()  
417 -  
418 - spacing = appender.GetOutput().GetSpacing()  
419 -  
420 - # The zpacing is a DicomGroup property, so we need to set it  
421 - imagedata = vtk.vtkImageData()  
422 - imagedata.DeepCopy(appender.GetOutput())  
423 - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)  
424 -  
425 - imagedata.AddObserver("ProgressEvent", lambda obj,evt:  
426 - update_progress(imagedata,message))  
427 - imagedata.Update()  
428 -  
429 - return imagedata  
430 -  
431 -  
432 -class ImageCreator:  
433 - def __init__(self):  
434 - self.running = True  
435 - Publisher.subscribe(self.CancelImageDataLoad, "Cancel DICOM load")  
436 -  
437 - def CancelImageDataLoad(self, evt_pusub):  
438 - utils.debug("Canceling")  
439 - self.running = False  
440 -  
441 - def CreateImageData(self, filelist, zspacing, size, bits):  
442 - message = _("Generating multiplanar visualization...")  
443 -  
444 - if not const.VTK_WARNING:  
445 - log_path = os.path.join(inv_paths.USER_LOG_DIR, 'vtkoutput.txt')  
446 - fow = vtk.vtkFileOutputWindow()  
447 - fow.SetFileName(log_path)  
448 - ow = vtk.vtkOutputWindow()  
449 - ow.SetInstance(fow)  
450 -  
451 - x,y = size  
452 - px, py = utils.predict_memory(len(filelist), x, y, bits)  
453 - utils.debug("Image Resized to >>> %f x %f" % (px, py))  
454 -  
455 - if (x == px) and (y == py):  
456 - const.REDUCE_IMAGEDATA_QUALITY = 0 271 + thumbnail_path = tempfile.mktemp(prefix='thumb_', suffix='.png')
  272 + if pf.GetSamplesPerPixel() == 1:
  273 + thumb_image = zoom(np_image, 0.25)
  274 + thumb_image = np.array(get_LUT_value_255(thumb_image, window, level), dtype=np.uint8)
457 else: 275 else:
458 - const.REDUCE_IMAGEDATA_QUALITY = 1  
459 -  
460 - if not(const.REDUCE_IMAGEDATA_QUALITY):  
461 - update_progress= vtk_utils.ShowProgress(1, dialog_type = "ProgressDialog")  
462 -  
463 - array = vtk.vtkStringArray()  
464 - for x in range(len(filelist)):  
465 - if not self.running:  
466 - return False  
467 - array.InsertValue(x,filelist[x])  
468 -  
469 - if not self.running:  
470 - return False  
471 - reader = vtkgdcm.vtkGDCMImageReader()  
472 - reader.SetFileNames(array)  
473 - reader.AddObserver("ProgressEvent", lambda obj,evt:  
474 - update_progress(reader,message))  
475 - reader.Update()  
476 -  
477 - if not self.running:  
478 - reader.AbortExecuteOn()  
479 - return False  
480 - # The zpacing is a DicomGroup property, so we need to set it  
481 - imagedata = vtk.vtkImageData()  
482 - imagedata.DeepCopy(reader.GetOutput())  
483 - spacing = imagedata.GetSpacing()  
484 - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)  
485 - else:  
486 -  
487 - update_progress= vtk_utils.ShowProgress(2*len(filelist),  
488 - dialog_type = "ProgressDialog")  
489 -  
490 - # Reformat each slice and future append them  
491 - appender = vtk.vtkImageAppend()  
492 - appender.SetAppendAxis(2) #Define Stack in Z  
493 -  
494 -  
495 - # Reformat each slice  
496 - for x in range(len(filelist)):  
497 - # TODO: We need to check this automatically according  
498 - # to each computer's architecture  
499 - # If the resolution of the matrix is too large  
500 - if not self.running:  
501 - return False  
502 - reader = vtkgdcm.vtkGDCMImageReader()  
503 - reader.SetFileName(filelist[x])  
504 - reader.AddObserver("ProgressEvent", lambda obj,evt:  
505 - update_progress(reader,message))  
506 - reader.Update()  
507 -  
508 - #Resample image in x,y dimension  
509 - slice_imagedata = ResampleImage2D(reader.GetOutput(), px, py, update_progress)  
510 - #Stack images in Z axes  
511 - appender.AddInput(slice_imagedata)  
512 - #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender))  
513 - appender.Update()  
514 -  
515 - # The zpacing is a DicomGroup property, so we need to set it  
516 - if not self.running:  
517 - return False  
518 - imagedata = vtk.vtkImageData()  
519 - imagedata.DeepCopy(appender.GetOutput())  
520 - spacing = imagedata.GetSpacing()  
521 -  
522 - imagedata.SetSpacing(spacing[0], spacing[1], zspacing)  
523 -  
524 - imagedata.AddObserver("ProgressEvent", lambda obj,evt:  
525 - update_progress(imagedata,message))  
526 - imagedata.Update() 276 + thumb_image = zoom(np_image, (0.25, 0.25, 1))
  277 + imageio.imsave(thumbnail_path, thumb_image)
  278 + return thumbnail_path
527 279
528 - return imagedata  
529 280
530 def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage): 281 def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage):
531 """ 282 """
@@ -626,7 +377,6 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage @@ -626,7 +377,6 @@ def bitmap2memmap(files, slice_size, orientation, spacing, resolution_percentage
626 return matrix, scalar_range, temp_file 377 return matrix, scalar_range, temp_file
627 378
628 379
629 -  
630 def dcm2memmap(files, slice_size, orientation, resolution_percentage): 380 def dcm2memmap(files, slice_size, orientation, resolution_percentage):
631 """ 381 """
632 From a list of dicom files it creates memmap file in the temp folder and 382 From a list of dicom files it creates memmap file in the temp folder and
@@ -635,7 +385,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): @@ -635,7 +385,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage):
635 message = _("Generating multiplanar visualization...") 385 message = _("Generating multiplanar visualization...")
636 update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog") 386 update_progress= vtk_utils.ShowProgress(len(files) - 1, dialog_type = "ProgressDialog")
637 387
638 - first_slice = read_dcm_slice_as_np(files[0], resolution_percentage) 388 + first_slice = read_dcm_slice_as_np2(files[0], resolution_percentage)
639 slice_size = first_slice.shape[::-1] 389 slice_size = first_slice.shape[::-1]
640 390
641 temp_file = tempfile.mktemp() 391 temp_file = tempfile.mktemp()
@@ -649,7 +399,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): @@ -649,7 +399,7 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage):
649 399
650 matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) 400 matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape)
651 for n, f in enumerate(files): 401 for n, f in enumerate(files):
652 - im_array = read_dcm_slice_as_np(f, resolution_percentage) 402 + im_array = read_dcm_slice_as_np2(f, resolution_percentage)[::-1]
653 403
654 if orientation == 'CORONAL': 404 if orientation == 'CORONAL':
655 matrix[:, shape[1] - n - 1, :] = im_array 405 matrix[:, shape[1] - n - 1, :] = im_array
@@ -669,37 +419,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): @@ -669,37 +419,35 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage):
669 419
670 420
671 def dcmmf2memmap(dcm_file, orientation): 421 def dcmmf2memmap(dcm_file, orientation):
672 - r = vtkgdcm.vtkGDCMImageReader()  
673 - r.SetFileName(dcm_file)  
674 - r.Update()  
675 - 422 + reader = gdcm.ImageReader()
  423 + reader.SetFileName(dcm_file)
  424 + reader.Read()
  425 + image = reader.GetImage()
  426 + xs, ys, zs = image.GetSpacing()
  427 + pf = image.GetPixelFormat()
  428 + np_image = converters.gdcm_to_numpy(image, pf.GetSamplesPerPixel() == 1)
676 temp_file = tempfile.mktemp() 429 temp_file = tempfile.mktemp()
677 -  
678 - o = r.GetOutput()  
679 - x, y, z = o.GetDimensions()  
680 - spacing = o.GetSpacing()  
681 -  
682 - matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=(z, y, x))  
683 -  
684 - d = numpy_support.vtk_to_numpy(o.GetPointData().GetScalars())  
685 - d.shape = z, y, x 430 + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=np_image.shape)
  431 + print("Number of dimensions", np_image.shape)
  432 + z, y, x = np_image.shape
686 if orientation == 'CORONAL': 433 if orientation == 'CORONAL':
  434 + spacing = xs, zs, ys
687 matrix.shape = y, z, x 435 matrix.shape = y, z, x
688 for n in range(z): 436 for n in range(z):
689 - matrix[:, n, :] = d[n] 437 + matrix[:, n, :] = np_image[n][::-1]
690 elif orientation == 'SAGITTAL': 438 elif orientation == 'SAGITTAL':
691 - matrix.shape = x, z, y 439 + spacing = zs, ys, xs
  440 + matrix.shape = y, x, z
692 for n in range(z): 441 for n in range(z):
693 - matrix[:, :, n] = d[n] 442 + matrix[:, :, n] = np_image[n][::-1]
694 else: 443 else:
695 - matrix[:] = d 444 + spacing = xs, ys, zs
  445 + matrix[:] = np_image[:, ::-1, :]
696 446
697 matrix.flush() 447 matrix.flush()
698 scalar_range = matrix.min(), matrix.max() 448 scalar_range = matrix.min(), matrix.max()
699 449
700 - print("ORIENTATION", orientation)  
701 -  
702 - return matrix, spacing, scalar_range, temp_file 450 + return matrix, scalar_range, spacing, temp_file
703 451
704 452
705 def img2memmap(group): 453 def img2memmap(group):
@@ -753,3 +501,14 @@ def imgnormalize(data, srange=(0, 255)): @@ -753,3 +501,14 @@ def imgnormalize(data, srange=(0, 255)):
753 datan = datan.astype(numpy.int16) 501 datan = datan.astype(numpy.int16)
754 502
755 return datan 503 return datan
  504 +
  505 +
  506 +def get_LUT_value_255(data, window, level):
  507 + shape = data.shape
  508 + data_ = data.ravel()
  509 + data = np.piecewise(data_,
  510 + [data_ <= (level - 0.5 - (window-1)/2),
  511 + data_ > (level - 0.5 + (window-1)/2)],
  512 + [0, 255, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(255)])
  513 + data.shape = shape
  514 + return data
invesalius/gui/bitmap_preview_panel.py
1 import wx 1 import wx
2 import vtk 2 import vtk
3 -import vtkgdcm  
4 import time 3 import time
5 import numpy 4 import numpy
6 5
invesalius/gui/dicom_preview_panel.py
@@ -35,7 +35,8 @@ import invesalius.constants as const @@ -35,7 +35,8 @@ import invesalius.constants as const
35 import invesalius.reader.dicom_reader as dicom_reader 35 import invesalius.reader.dicom_reader as dicom_reader
36 import invesalius.data.vtk_utils as vtku 36 import invesalius.data.vtk_utils as vtku
37 import invesalius.utils as utils 37 import invesalius.utils as utils
38 -import vtkgdcm 38 +from invesalius.data import imagedata_utils
  39 +from invesalius.data import converters
39 40
40 if sys.platform == 'win32': 41 if sys.platform == 'win32':
41 try: 42 try:
@@ -890,20 +891,20 @@ class SingleImagePreview(wx.Panel): @@ -890,20 +891,20 @@ class SingleImagePreview(wx.Panel):
890 reader.Update() 891 reader.Update()
891 892
892 image = reader.GetOutput() 893 image = reader.GetOutput()
893 -  
894 else: 894 else:
895 - rdicom = vtkgdcm.vtkGDCMImageReader() 895 + filename = dicom.image.file
896 if _has_win32api: 896 if _has_win32api:
897 - rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE))  
898 - else:  
899 - rdicom.SetFileName(dicom.image.file)  
900 - rdicom.Update() 897 + filename = win32api.GetShortPathName(filename).encode(const.FS_ENCODE)
  898 +
  899 + np_image = imagedata_utils.read_dcm_slice_as_np2(filename)
  900 + print(">>> spacing", dicom.image.spacing)
  901 + vtk_image = converters.to_vtk(np_image, dicom.image.spacing, 0, 'AXIAL')
901 902
902 # ADJUST CONTRAST 903 # ADJUST CONTRAST
903 window_level = dicom.image.level 904 window_level = dicom.image.level
904 window_width = dicom.image.window 905 window_width = dicom.image.window
905 colorer = vtk.vtkImageMapToWindowLevelColors() 906 colorer = vtk.vtkImageMapToWindowLevelColors()
906 - colorer.SetInputConnection(rdicom.GetOutputPort()) 907 + colorer.SetInputData(vtk_image)
907 colorer.SetWindow(float(window_width)) 908 colorer.SetWindow(float(window_width))
908 colorer.SetLevel(float(window_level)) 909 colorer.SetLevel(float(window_level))
909 colorer.Update() 910 colorer.Update()
invesalius/reader/dicom.py
@@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
19 #--------------------------------------------------------------------- 19 #---------------------------------------------------------------------
20 import time 20 import time
21 #import gdcm 21 #import gdcm
22 -#import vtkgdcm  
23 import sys 22 import sys
24 import invesalius.utils as utils 23 import invesalius.utils as utils
25 import invesalius.constants as const 24 import invesalius.constants as const
invesalius/reader/dicom_reader.py
@@ -24,7 +24,6 @@ import sys @@ -24,7 +24,6 @@ import sys
24 from multiprocessing import cpu_count 24 from multiprocessing import cpu_count
25 25
26 import vtk 26 import vtk
27 -import vtkgdcm  
28 import gdcm 27 import gdcm
29 from wx.lib.pubsub import pub as Publisher 28 from wx.lib.pubsub import pub as Publisher
30 29
@@ -202,14 +201,11 @@ class LoadDicom: @@ -202,14 +201,11 @@ class LoadDicom:
202 level = None 201 level = None
203 window = None 202 window = None
204 203
205 - if _has_win32api:  
206 - thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath), window, level)  
207 - else:  
208 - thumbnail_path = imagedata_utils.create_dicom_thumbnails(self.filepath, window, level) 204 + img = reader.GetImage()
  205 + thumbnail_path = imagedata_utils.create_dicom_thumbnails(img, window, level)
209 206
210 #------ Verify the orientation -------------------------------- 207 #------ Verify the orientation --------------------------------
211 208
212 - img = reader.GetImage()  
213 direc_cosines = img.GetDirectionCosines() 209 direc_cosines = img.GetDirectionCosines()
214 orientation = gdcm.Orientation() 210 orientation = gdcm.Orientation()
215 try: 211 try: