Commit afdb3ce1763e0e37fb385d31236baefa4de23fcd
Committed by
GitHub
1 parent
9a7e323e
Exists in
master
Open Multiframe dicom (#133)
* Loading multiframe dicom using the import gui * Showing multiframe thumbnails * Showing the thumbnail in the slice viewer from preview * Set slide to the number of slices or numberofframes
Showing
7 changed files
with
254 additions
and
104 deletions
Show diff stats
invesalius/control.py
| ... | ... | @@ -404,8 +404,9 @@ class Controller(): |
| 404 | 404 | Publisher.sendMessage('Begin busy cursor') |
| 405 | 405 | else: |
| 406 | 406 | #Is None if user canceled the load |
| 407 | - self.progress_dialog.Close() | |
| 408 | - self.progress_dialog = None | |
| 407 | + if self.progress_dialog is not None: | |
| 408 | + self.progress_dialog.Close() | |
| 409 | + self.progress_dialog = None | |
| 409 | 410 | |
| 410 | 411 | def OnLoadImportPanel(self, evt): |
| 411 | 412 | patient_series = evt.data |
| ... | ... | @@ -795,47 +796,53 @@ class Controller(): |
| 795 | 796 | xyspacing = dicom.image.spacing |
| 796 | 797 | orientation = dicom.image.orientation_label |
| 797 | 798 | |
| 799 | + wl = float(dicom.image.level) | |
| 800 | + ww = float(dicom.image.window) | |
| 801 | + | |
| 798 | 802 | if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage |
| 799 | 803 | use_dcmspacing = 1 |
| 800 | 804 | else: |
| 801 | 805 | use_dcmspacing = 0 |
| 802 | 806 | |
| 803 | 807 | imagedata = None |
| 804 | - | |
| 805 | - sx, sy = size | |
| 806 | - n_slices = len(filelist) | |
| 807 | - resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8) | |
| 808 | - | |
| 809 | - if resolution_percentage < 1.0 and gui: | |
| 810 | - re_dialog = dialog.ResizeImageDialog() | |
| 811 | - re_dialog.SetValue(int(resolution_percentage*100)) | |
| 812 | - re_dialog_value = re_dialog.ShowModal() | |
| 813 | - re_dialog.Close() | |
| 814 | - | |
| 815 | - if re_dialog_value == wx.ID_OK: | |
| 816 | - percentage = re_dialog.GetValue() | |
| 817 | - resolution_percentage = percentage / 100.0 | |
| 818 | - else: | |
| 819 | - return | |
| 820 | 808 | |
| 821 | - xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage | |
| 822 | - | |
| 823 | - | |
| 824 | - wl = float(dicom.image.level) | |
| 825 | - ww = float(dicom.image.window) | |
| 826 | - self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, | |
| 827 | - orientation, resolution_percentage) | |
| 809 | + if dicom.image.number_of_frames == 1: | |
| 810 | + sx, sy = size | |
| 811 | + n_slices = len(filelist) | |
| 812 | + resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8) | |
| 813 | + | |
| 814 | + if resolution_percentage < 1.0 and gui: | |
| 815 | + re_dialog = dialog.ResizeImageDialog() | |
| 816 | + re_dialog.SetValue(int(resolution_percentage*100)) | |
| 817 | + re_dialog_value = re_dialog.ShowModal() | |
| 818 | + re_dialog.Close() | |
| 819 | + | |
| 820 | + if re_dialog_value == wx.ID_OK: | |
| 821 | + percentage = re_dialog.GetValue() | |
| 822 | + resolution_percentage = percentage / 100.0 | |
| 823 | + else: | |
| 824 | + return | |
| 825 | + | |
| 826 | + xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage | |
| 827 | + | |
| 828 | + self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size, | |
| 829 | + orientation, resolution_percentage) | |
| 830 | + | |
| 831 | + print xyspacing, zspacing | |
| 832 | + if orientation == 'AXIAL': | |
| 833 | + spacing = xyspacing[0], xyspacing[1], zspacing | |
| 834 | + elif orientation == 'CORONAL': | |
| 835 | + spacing = xyspacing[0], zspacing, xyspacing[1] | |
| 836 | + elif orientation == 'SAGITTAL': | |
| 837 | + spacing = zspacing, xyspacing[1], xyspacing[0] | |
| 838 | + else: | |
| 839 | + self.matrix, spacing, scalar_range, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation) | |
| 828 | 840 | |
| 829 | 841 | self.Slice = sl.Slice() |
| 830 | 842 | self.Slice.matrix = self.matrix |
| 831 | 843 | self.Slice.matrix_filename = self.filename |
| 832 | 844 | |
| 833 | - if orientation == 'AXIAL': | |
| 834 | - self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing | |
| 835 | - elif orientation == 'CORONAL': | |
| 836 | - self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1] | |
| 837 | - elif orientation == 'SAGITTAL': | |
| 838 | - self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0] | |
| 845 | + self.Slice.spacing = spacing | |
| 839 | 846 | |
| 840 | 847 | # 1(a): Fix gantry tilt, if any |
| 841 | 848 | tilt_value = dicom.acquisition.tilt | ... | ... |
invesalius/data/imagedata_utils.py
| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | |
| 20 | 20 | import math |
| 21 | 21 | import os |
| 22 | +import sys | |
| 22 | 23 | import tempfile |
| 23 | 24 | |
| 24 | 25 | import gdcm |
| ... | ... | @@ -35,6 +36,16 @@ from invesalius.data import vtk_utils as vtk_utils |
| 35 | 36 | import invesalius.reader.bitmap_reader as bitmap_reader |
| 36 | 37 | import invesalius.utils as utils |
| 37 | 38 | import invesalius.data.converters as converters |
| 39 | + | |
| 40 | +if sys.platform == 'win32': | |
| 41 | + try: | |
| 42 | + import win32api | |
| 43 | + _has_win32api = True | |
| 44 | + except ImportError: | |
| 45 | + _has_win32api = False | |
| 46 | +else: | |
| 47 | + _has_win32api = False | |
| 48 | + | |
| 38 | 49 | # TODO: Test cases which are originally in sagittal/coronal orientation |
| 39 | 50 | # and have gantry |
| 40 | 51 | |
| ... | ... | @@ -246,11 +257,79 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): |
| 246 | 257 | """ |
| 247 | 258 | voi = vtk.vtkExtractVOI() |
| 248 | 259 | voi.SetVOI(xi,xf,yi,yf,zi,zf) |
| 249 | - voi.SetInput(imagedata) | |
| 260 | + voi.SetInputData(imagedata) | |
| 250 | 261 | voi.SetSampleRate(1, 1, 1) |
| 251 | 262 | voi.Update() |
| 252 | 263 | return voi.GetOutput() |
| 253 | 264 | |
| 265 | + | |
| 266 | +def create_dicom_thumbnails(filename, window=None, level=None): | |
| 267 | + rvtk = vtkgdcm.vtkGDCMImageReader() | |
| 268 | + rvtk.SetFileName(filename) | |
| 269 | + rvtk.Update() | |
| 270 | + | |
| 271 | + img = rvtk.GetOutput() | |
| 272 | + if window is None or level is None: | |
| 273 | + _min, _max = img.GetScalarRange() | |
| 274 | + window = _max - _min | |
| 275 | + level = _min + window / 2 | |
| 276 | + | |
| 277 | + dx, dy, dz = img.GetDimensions() | |
| 278 | + | |
| 279 | + if dz > 1: | |
| 280 | + thumbnail_paths = [] | |
| 281 | + for i in xrange(dz): | |
| 282 | + img_slice = ExtractVOI(img, 0, dx-1, 0, dy-1, i, i+1) | |
| 283 | + | |
| 284 | + colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 285 | + colorer.SetInputData(img_slice) | |
| 286 | + colorer.SetWindow(window) | |
| 287 | + colorer.SetLevel(level) | |
| 288 | + colorer.SetOutputFormatToRGB() | |
| 289 | + colorer.Update() | |
| 290 | + | |
| 291 | + resample = vtk.vtkImageResample() | |
| 292 | + resample.SetInputData(colorer.GetOutput()) | |
| 293 | + resample.SetAxisMagnificationFactor ( 0, 0.25 ) | |
| 294 | + resample.SetAxisMagnificationFactor ( 1, 0.25 ) | |
| 295 | + resample.SetAxisMagnificationFactor ( 2, 1 ) | |
| 296 | + resample.Update() | |
| 297 | + | |
| 298 | + thumbnail_path = tempfile.mktemp() | |
| 299 | + | |
| 300 | + write_png = vtk.vtkPNGWriter() | |
| 301 | + write_png.SetInputData(resample.GetOutput()) | |
| 302 | + write_png.SetFileName(thumbnail_path) | |
| 303 | + write_png.Write() | |
| 304 | + | |
| 305 | + thumbnail_paths.append(thumbnail_path) | |
| 306 | + | |
| 307 | + return thumbnail_paths | |
| 308 | + else: | |
| 309 | + colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 310 | + colorer.SetInputData(img) | |
| 311 | + colorer.SetWindow(window) | |
| 312 | + colorer.SetLevel(level) | |
| 313 | + colorer.SetOutputFormatToRGB() | |
| 314 | + colorer.Update() | |
| 315 | + | |
| 316 | + resample = vtk.vtkImageResample() | |
| 317 | + resample.SetInputData(colorer.GetOutput()) | |
| 318 | + resample.SetAxisMagnificationFactor ( 0, 0.25 ) | |
| 319 | + resample.SetAxisMagnificationFactor ( 1, 0.25 ) | |
| 320 | + resample.SetAxisMagnificationFactor ( 2, 1 ) | |
| 321 | + resample.Update() | |
| 322 | + | |
| 323 | + thumbnail_path = tempfile.mktemp() | |
| 324 | + | |
| 325 | + write_png = vtk.vtkPNGWriter() | |
| 326 | + write_png.SetInputData(resample.GetOutput()) | |
| 327 | + write_png.SetFileName(thumbnail_path) | |
| 328 | + write_png.Write() | |
| 329 | + | |
| 330 | + return thumbnail_path | |
| 331 | + | |
| 332 | + | |
| 254 | 333 | def CreateImageData(filelist, zspacing, xyspacing,size, |
| 255 | 334 | bits, use_dcmspacing): |
| 256 | 335 | message = _("Generating multiplanar visualization...") |
| ... | ... | @@ -587,6 +666,29 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): |
| 587 | 666 | return matrix, scalar_range, temp_file |
| 588 | 667 | |
| 589 | 668 | |
| 669 | +def dcmmf2memmap(dcm_file, orientation): | |
| 670 | + r = vtkgdcm.vtkGDCMImageReader() | |
| 671 | + r.SetFileName(dcm_file) | |
| 672 | + r.Update() | |
| 673 | + | |
| 674 | + temp_file = tempfile.mktemp() | |
| 675 | + | |
| 676 | + o = r.GetOutput() | |
| 677 | + x, y, z = o.GetDimensions() | |
| 678 | + spacing = o.GetSpacing() | |
| 679 | + | |
| 680 | + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=(z, y, x)) | |
| 681 | + | |
| 682 | + d = numpy_support.vtk_to_numpy(o.GetPointData().GetScalars()) | |
| 683 | + d.shape = z, y, x | |
| 684 | + matrix[:] = d | |
| 685 | + matrix.flush() | |
| 686 | + | |
| 687 | + scalar_range = matrix.min(), matrix.max() | |
| 688 | + | |
| 689 | + return matrix, spacing, scalar_range, temp_file | |
| 690 | + | |
| 691 | + | |
| 590 | 692 | def img2memmap(group): |
| 591 | 693 | """ |
| 592 | 694 | From a nibabel image data creates a memmap file in the temp folder and | ... | ... |
invesalius/data/vtk_utils.py
| ... | ... | @@ -52,6 +52,8 @@ def ShowProgress(number_of_filters = 1, |
| 52 | 52 | |
| 53 | 53 | # when the pipeline is larger than 1, we have to consider this object |
| 54 | 54 | # percentage |
| 55 | + if number_of_filters < 1: | |
| 56 | + number_of_filters = 1 | |
| 55 | 57 | ratio = (100.0 / number_of_filters) |
| 56 | 58 | |
| 57 | 59 | def UpdateProgress(obj, label=""): | ... | ... |
invesalius/gui/dicom_preview_panel.py
| ... | ... | @@ -115,7 +115,7 @@ class DicomInfo(object): |
| 115 | 115 | """ |
| 116 | 116 | Keep the informations and the image used by preview. |
| 117 | 117 | """ |
| 118 | - def __init__(self, id, dicom, title, subtitle): | |
| 118 | + def __init__(self, id, dicom, title, subtitle, n=0): | |
| 119 | 119 | self.id = id |
| 120 | 120 | self.dicom = dicom |
| 121 | 121 | self.title = title |
| ... | ... | @@ -123,12 +123,15 @@ class DicomInfo(object): |
| 123 | 123 | self._preview = None |
| 124 | 124 | self.selected = False |
| 125 | 125 | self.filename = "" |
| 126 | + self._slice = n | |
| 126 | 127 | |
| 127 | 128 | @property |
| 128 | 129 | def preview(self): |
| 129 | - | |
| 130 | 130 | if not self._preview: |
| 131 | - bmp = wx.Bitmap(self.dicom.image.thumbnail_path, wx.BITMAP_TYPE_PNG) | |
| 131 | + if isinstance(self.dicom.image.thumbnail_path, list): | |
| 132 | + bmp = wx.Bitmap(self.dicom.image.thumbnail_path[self._slice], wx.BITMAP_TYPE_PNG) | |
| 133 | + else: | |
| 134 | + bmp = wx.Bitmap(self.dicom.image.thumbnail_path, wx.BITMAP_TYPE_PNG) | |
| 132 | 135 | self._preview = bmp.ConvertToImage() |
| 133 | 136 | return self._preview |
| 134 | 137 | |
| ... | ... | @@ -539,11 +542,22 @@ class DicomPreviewSlice(wx.Panel): |
| 539 | 542 | dicom_files = group.GetHandSortedList() |
| 540 | 543 | n = 0 |
| 541 | 544 | for dicom in dicom_files: |
| 542 | - info = DicomInfo(n, dicom, | |
| 543 | - _("Image %d") % (dicom.image.number), | |
| 544 | - "%.2f" % (dicom.image.position[2])) | |
| 545 | - self.files.append(info) | |
| 546 | - n+=1 | |
| 545 | + if isinstance(dicom.image.thumbnail_path, list): | |
| 546 | + _slice = 0 | |
| 547 | + for thumbnail in dicom.image.thumbnail_path: | |
| 548 | + print thumbnail | |
| 549 | + info = DicomInfo(n, dicom, | |
| 550 | + _("Image %d") % (n), | |
| 551 | + "%.2f" % (dicom.image.position[2]), _slice) | |
| 552 | + self.files.append(info) | |
| 553 | + n+=1 | |
| 554 | + _slice += 1 | |
| 555 | + else: | |
| 556 | + info = DicomInfo(n, dicom, | |
| 557 | + _("Image %d") % (dicom.image.number), | |
| 558 | + "%.2f" % (dicom.image.position[2])) | |
| 559 | + self.files.append(info) | |
| 560 | + n+=1 | |
| 547 | 561 | |
| 548 | 562 | scroll_range = len(self.files)/NCOLS |
| 549 | 563 | if scroll_range * NCOLS < len(self.files): |
| ... | ... | @@ -560,12 +574,23 @@ class DicomPreviewSlice(wx.Panel): |
| 560 | 574 | dicom_files = group.GetHandSortedList() |
| 561 | 575 | n = 0 |
| 562 | 576 | for dicom in dicom_files: |
| 563 | - info = DicomInfo(n, dicom, | |
| 564 | - _("Image %d") % (dicom.image.number), | |
| 565 | - "%.2f" % (dicom.image.position[2]), | |
| 566 | - ) | |
| 567 | - self.files.append(info) | |
| 568 | - n+=1 | |
| 577 | + if isinstance(dicom.image.thumbnail_path, list): | |
| 578 | + _slice = 0 | |
| 579 | + for thumbnail in dicom.image.thumbnail_path: | |
| 580 | + print thumbnail | |
| 581 | + info = DicomInfo(n, dicom, | |
| 582 | + _("Image %d") % int(n), | |
| 583 | + "%.2f" % (dicom.image.position[2]), _slice) | |
| 584 | + self.files.append(info) | |
| 585 | + n+=1 | |
| 586 | + _slice += 1 | |
| 587 | + else: | |
| 588 | + info = DicomInfo(n, dicom, | |
| 589 | + _("Image %d") % int(dicom.image.number), | |
| 590 | + "%.2f" % (dicom.image.position[2]), | |
| 591 | + ) | |
| 592 | + self.files.append(info) | |
| 593 | + n+=1 | |
| 569 | 594 | |
| 570 | 595 | scroll_range = len(self.files)/NCOLS |
| 571 | 596 | if scroll_range * NCOLS < len(self.files): |
| ... | ... | @@ -803,14 +828,20 @@ class SingleImagePreview(wx.Panel): |
| 803 | 828 | def SetDicomGroup(self, group): |
| 804 | 829 | self.dicom_list = group.GetHandSortedList() |
| 805 | 830 | self.current_index = 0 |
| 806 | - self.nimages = len(self.dicom_list) | |
| 831 | + if len(self.dicom_list) > 1: | |
| 832 | + self.nimages = len(self.dicom_list) | |
| 833 | + else: | |
| 834 | + self.nimages = self.dicom_list[0].image.number_of_frames | |
| 807 | 835 | # GUI |
| 808 | 836 | self.slider.SetMax(self.nimages-1) |
| 809 | 837 | self.slider.SetValue(0) |
| 810 | 838 | self.ShowSlice() |
| 811 | 839 | |
| 812 | 840 | def ShowSlice(self, index = 0): |
| 813 | - dicom = self.dicom_list[index] | |
| 841 | + try: | |
| 842 | + dicom = self.dicom_list[index] | |
| 843 | + except IndexError: | |
| 844 | + dicom = self.dicom_list[0] | |
| 814 | 845 | |
| 815 | 846 | # UPDATE GUI |
| 816 | 847 | ## Text related to size |
| ... | ... | @@ -845,28 +876,41 @@ class SingleImagePreview(wx.Panel): |
| 845 | 876 | dicom.acquisition.time) |
| 846 | 877 | self.text_acquisition.SetValue(value) |
| 847 | 878 | |
| 848 | - rdicom = vtkgdcm.vtkGDCMImageReader() | |
| 849 | - if _has_win32api: | |
| 850 | - rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE)) | |
| 879 | + if isinstance(dicom.image.thumbnail_path, list): | |
| 880 | + reader = vtk.vtkPNGReader() | |
| 881 | + if _has_win32api: | |
| 882 | + reader.SetFileName(win32api.GetShortPathName(dicom.image.thumbnail_path[index]).encode(const.FS_ENCODE)) | |
| 883 | + else: | |
| 884 | + reader.SetFileName(dicom.image.thumbnail_path[index]) | |
| 885 | + reader.Update() | |
| 886 | + | |
| 887 | + image = reader.GetOutput() | |
| 888 | + | |
| 851 | 889 | else: |
| 852 | - rdicom.SetFileName(dicom.image.file) | |
| 853 | - rdicom.Update() | |
| 854 | - | |
| 855 | - # ADJUST CONTRAST | |
| 856 | - window_level = dicom.image.level | |
| 857 | - window_width = dicom.image.window | |
| 858 | - colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 859 | - colorer.SetInputConnection(rdicom.GetOutputPort()) | |
| 860 | - colorer.SetWindow(float(window_width)) | |
| 861 | - colorer.SetLevel(float(window_level)) | |
| 862 | - colorer.Update() | |
| 890 | + rdicom = vtkgdcm.vtkGDCMImageReader() | |
| 891 | + if _has_win32api: | |
| 892 | + rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE)) | |
| 893 | + else: | |
| 894 | + rdicom.SetFileName(dicom.image.file) | |
| 895 | + rdicom.Update() | |
| 896 | + | |
| 897 | + # ADJUST CONTRAST | |
| 898 | + window_level = dicom.image.level | |
| 899 | + window_width = dicom.image.window | |
| 900 | + colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 901 | + colorer.SetInputConnection(rdicom.GetOutputPort()) | |
| 902 | + colorer.SetWindow(float(window_width)) | |
| 903 | + colorer.SetLevel(float(window_level)) | |
| 904 | + colorer.Update() | |
| 905 | + | |
| 906 | + image = colorer.GetOutput() | |
| 863 | 907 | |
| 864 | 908 | if self.actor is None: |
| 865 | 909 | self.actor = vtk.vtkImageActor() |
| 866 | 910 | self.renderer.AddActor(self.actor) |
| 867 | 911 | |
| 868 | 912 | # PLOT IMAGE INTO VIEWER |
| 869 | - self.actor.SetInputData(colorer.GetOutput()) | |
| 913 | + self.actor.SetInputData(image) | |
| 870 | 914 | self.renderer.ResetCamera() |
| 871 | 915 | self.interactor.Render() |
| 872 | 916 | ... | ... |
invesalius/reader/dicom.py
| ... | ... | @@ -1154,8 +1154,20 @@ class Parser(): |
| 1154 | 1154 | if (data): |
| 1155 | 1155 | return int(data) |
| 1156 | 1156 | return "" |
| 1157 | - | |
| 1158 | - | |
| 1157 | + | |
| 1158 | + def GetNumberOfFrames(self): | |
| 1159 | + """ | |
| 1160 | + Number of frames in a multi-frame image. | |
| 1161 | + | |
| 1162 | + DICOM standard tag (0x0028, 0x0008) was used. | |
| 1163 | + """ | |
| 1164 | + try: | |
| 1165 | + data = self.data_image[str(0x028)][str(0x0008)] | |
| 1166 | + except KeyError: | |
| 1167 | + return 1 | |
| 1168 | + return int(data) | |
| 1169 | + | |
| 1170 | + | |
| 1159 | 1171 | def GetPatientBirthDate(self): |
| 1160 | 1172 | """ |
| 1161 | 1173 | Return string containing the patient's birth date using the |
| ... | ... | @@ -1498,11 +1510,11 @@ class Parser(): |
| 1498 | 1510 | try: |
| 1499 | 1511 | data = self.data_image[str(0x0020)][str(0x0013)] |
| 1500 | 1512 | except(KeyError): |
| 1501 | - return "" | |
| 1513 | + return 0 | |
| 1502 | 1514 | |
| 1503 | 1515 | if (data): |
| 1504 | 1516 | return int(data) |
| 1505 | - return "" | |
| 1517 | + return 0 | |
| 1506 | 1518 | |
| 1507 | 1519 | def GetStudyDescription(self): |
| 1508 | 1520 | """ |
| ... | ... | @@ -1954,6 +1966,8 @@ class Image(object): |
| 1954 | 1966 | self.bits_allocad = parser._GetBitsAllocated() |
| 1955 | 1967 | self.thumbnail_path = parser.thumbnail_path |
| 1956 | 1968 | |
| 1969 | + self.number_of_frames = parser.GetNumberOfFrames() | |
| 1970 | + | |
| 1957 | 1971 | if (parser.GetImageThickness()): |
| 1958 | 1972 | try: |
| 1959 | 1973 | spacing.append(parser.GetImageThickness()) | ... | ... |
invesalius/reader/dicom_grouper.py
| ... | ... | @@ -94,22 +94,22 @@ class DicomGroup: |
| 94 | 94 | if not self.dicom: |
| 95 | 95 | self.dicom = dicom |
| 96 | 96 | |
| 97 | - pos = tuple(dicom.image.position) | |
| 98 | - | |
| 97 | + pos = tuple(dicom.image.position) | |
| 98 | + | |
| 99 | 99 | #Case to test: \other\higroma |
| 100 | - #condition created, if any dicom with the same | |
| 100 | + #condition created, if any dicom with the same | |
| 101 | 101 | #position, but 3D, leaving the same series. |
| 102 | 102 | if not "DERIVED" in dicom.image.type: |
| 103 | 103 | #if any dicom with the same position |
| 104 | 104 | if pos not in self.slices_dict.keys(): |
| 105 | 105 | self.slices_dict[pos] = dicom |
| 106 | - self.nslices += 1 | |
| 106 | + self.nslices += dicom.image.number_of_frames | |
| 107 | 107 | return True |
| 108 | 108 | else: |
| 109 | 109 | return False |
| 110 | 110 | else: |
| 111 | 111 | self.slices_dict[dicom.image.number] = dicom |
| 112 | - self.nslices += 1 | |
| 112 | + self.nslices += dicom.image.number_of_frames | |
| 113 | 113 | return True |
| 114 | 114 | |
| 115 | 115 | def GetList(self): | ... | ... |
invesalius/reader/dicom_reader.py
| ... | ... | @@ -36,6 +36,8 @@ import invesalius.session as session |
| 36 | 36 | import glob |
| 37 | 37 | import invesalius.utils as utils |
| 38 | 38 | |
| 39 | +from invesalius.data import imagedata_utils | |
| 40 | + | |
| 39 | 41 | import plistlib |
| 40 | 42 | |
| 41 | 43 | if sys.platform == 'win32': |
| ... | ... | @@ -187,45 +189,22 @@ class LoadDicom: |
| 187 | 189 | |
| 188 | 190 | |
| 189 | 191 | # -------------- To Create DICOM Thumbnail ----------- |
| 190 | - rvtk = vtkgdcm.vtkGDCMImageReader() | |
| 191 | 192 | |
| 192 | - if _has_win32api: | |
| 193 | - print 'dicom', win32api.GetShortPathName(self.filepath) | |
| 194 | - rvtk.SetFileName(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE)) | |
| 195 | - else: | |
| 196 | - rvtk.SetFileName(self.filepath) | |
| 197 | - rvtk.Update() | |
| 198 | - | |
| 193 | + | |
| 199 | 194 | try: |
| 200 | 195 | data = data_dict[str(0x028)][str(0x1050)] |
| 201 | 196 | level = [float(value) for value in data.split('\\')][0] |
| 202 | 197 | data = data_dict[str(0x028)][str(0x1051)] |
| 203 | 198 | window = [float(value) for value in data.split('\\')][0] |
| 204 | 199 | except(KeyError, ValueError): |
| 205 | - level = 300.0 | |
| 206 | - window = 2000.0 | |
| 207 | - | |
| 208 | - colorer = vtk.vtkImageMapToWindowLevelColors() | |
| 209 | - colorer.SetInputConnection(rvtk.GetOutputPort()) | |
| 210 | - colorer.SetWindow(float(window)) | |
| 211 | - colorer.SetLevel(float(level)) | |
| 212 | - colorer.SetOutputFormatToRGB() | |
| 213 | - colorer.Update() | |
| 214 | - | |
| 215 | - resample = vtk.vtkImageResample() | |
| 216 | - resample.SetInputConnection(colorer.GetOutputPort()) | |
| 217 | - resample.SetAxisMagnificationFactor ( 0, 0.25 ) | |
| 218 | - resample.SetAxisMagnificationFactor ( 1, 0.25 ) | |
| 219 | - resample.SetAxisMagnificationFactor ( 2, 1 ) | |
| 220 | - resample.Update() | |
| 221 | - | |
| 222 | - thumbnail_path = tempfile.mktemp() | |
| 223 | - | |
| 224 | - write_png = vtk.vtkPNGWriter() | |
| 225 | - write_png.SetInputConnection(resample.GetOutputPort()) | |
| 226 | - write_png.SetFileName(thumbnail_path) | |
| 227 | - write_png.Write() | |
| 228 | - | |
| 200 | + level = None | |
| 201 | + window = None | |
| 202 | + | |
| 203 | + if _has_win32api: | |
| 204 | + thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE), window, level) | |
| 205 | + else: | |
| 206 | + thumbnail_path = imagedata_utils.create_dicom_thumbnails(self.filepath, window, level) | |
| 207 | + | |
| 229 | 208 | #------ Verify the orientation -------------------------------- |
| 230 | 209 | |
| 231 | 210 | img = reader.GetImage() |
| ... | ... | @@ -362,12 +341,14 @@ class ProgressDicomReader: |
| 362 | 341 | |
| 363 | 342 | y = yGetDicomGroups(path, recursive) |
| 364 | 343 | for value_progress in y: |
| 344 | + print ">>>>", value_progress | |
| 365 | 345 | if not self.running: |
| 366 | 346 | break |
| 367 | 347 | if isinstance(value_progress, tuple): |
| 368 | 348 | self.UpdateLoadFileProgress(value_progress) |
| 369 | 349 | else: |
| 370 | 350 | self.EndLoadFile(value_progress) |
| 351 | + self.UpdateLoadFileProgress(None) | |
| 371 | 352 | |
| 372 | 353 | #Is necessary in the case user cancel |
| 373 | 354 | #the load, ensure that dicomdialog is closed | ... | ... |