From 3174c58fe17f8eb04ad9817ad20cce8b8cde4896 Mon Sep 17 00:00:00 2001 From: tatiana Date: Fri, 16 Oct 2009 15:10:58 +0000 Subject: [PATCH] ADD: Preview DICOM in import panel (still working) --- invesalius/control.py | 106 ++++++---------------------------------------------------------------------------------------------------- invesalius/gui/dicom_preview_panel.py | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------- invesalius/gui/import_panel.py | 39 ++++++++++++++++++++++++++++++++++----- invesalius/invesalius.py | 2 +- 4 files changed, 151 insertions(+), 246 deletions(-) diff --git a/invesalius/control.py b/invesalius/control.py index 9bdb703..ee16b9f 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -39,9 +39,12 @@ class Controller(): # retrieve DICOM files splited into groups patient_series = dcm.GetDicomGroups(path) - ps.Publisher().sendMessage("Load import panel", patient_series) - first_patient = patient_series[0] - #ps.Publisher().sendMessage("Load dicom preview", first_patient) + if patient_series: + ps.Publisher().sendMessage("Load import panel", patient_series) + first_patient = patient_series[0] + ps.Publisher().sendMessage("Load dicom preview", first_patient) + else: + print "No DICOM files on directory" def OnImportMedicalImages(self, pubsub_evt): directory = pubsub_evt.data @@ -144,103 +147,6 @@ class Controller(): return imagedata, dicom - def ImportDirectory(self, pubsub_evt=None, dir_=None): - """ - Import medical images (if any) and generate vtkImageData, saving data - inside Project instance. - """ - - if not dir_: - dir_ = pubsub_evt.data - - # Select medical images from directory and generate vtkImageData - output = dcm.LoadImages(dir_) - proj = prj.Project() - proj.name = "Untitled" - - if output: - # In this case, there were DICOM files on the folder - imagedata, dicom = output - - # Set orientation - orientation = dicom.image.orientation_label - if (orientation == "CORONAL"): - orientation = const.CORONAL - elif(orientation == "SAGITTAL"): - orientation = const.SAGITAL - else: - orientation = const.AXIAL - - # Retrieve window, level, modalit - window = float(dicom.image.window) - level = float(dicom.image.level) - acquisition_modality = dicom.acquisition.modality - - # If there was gantry tilt, fix it: - tilt_value = dicom.acquisition.tilt - if (tilt_value): - # Tell user gantry tilt and fix, according to answer - message = "Fix gantry tilt applying the degrees bellow" - value = -1*tilt_value - tilt_value = dialog.ShowNumberDialog(message, value) - imagedata = utils.FixGantryTilt(imagedata, tilt_value) - else: - "No DICOM files were found. Trying to read with ITK..." - imagedata = analyze.ReadDirectory(dir_) - if imagedata: - acquisition_modality = "MRI" - - #TODO: Verify if all Analyse is AXIAL orientation - orientation = const.AXIAL - - proj.SetAcquisitionModality(acquisition_modality) - proj.imagedata = imagedata - proj.original_orientation = orientation - threshold_range = proj.imagedata.GetScalarRange() - proj.window = window = threshold_range[1] - threshold_range[0] - proj.level = level = (0.5 * (threshold_range[1] + threshold_range[0])) - - ps.Publisher().sendMessage('Update window level value',\ - (proj.window, proj.level)) - - if not imagedata: - print "Sorry, but there are no medical images supported on this dir." - else: - # Create new project - proj.SetAcquisitionModality(acquisition_modality) - proj.imagedata = imagedata - proj.original_orientation = orientation - proj.window = window - proj.level = level - - threshold_range = proj.imagedata.GetScalarRange() - - const.WINDOW_LEVEL['Default'] = (window, level) - const.WINDOW_LEVEL['Manual'] = (window, level) - - const.THRESHOLD_OUTVALUE = threshold_range[0] - const.THRESHOLD_INVALUE = threshold_range[1] - - # Based on imagedata, load data to GUI - ps.Publisher().sendMessage('Load slice to viewer', (imagedata)) - - # TODO: where to insert!!! - self.LoadImagedataInfo() - - #Initial Window and Level - ps.Publisher().sendMessage('Bright and contrast adjustment image',\ - (proj.window, proj.level)) - - ps.Publisher().sendMessage('Update window level value',\ - (proj.window, proj.level)) - - # Call frame so it shows slice and volume related panels - ps.Publisher().sendMessage('Show content panel') - - ps.Publisher().sendMessage('Update AUI') - - ps.Publisher().sendMessage('Load slice plane') - def LoadImagedataInfo(self): proj = prj.Project() diff --git a/invesalius/gui/dicom_preview_panel.py b/invesalius/gui/dicom_preview_panel.py index d7d5829..0a7c15e 100755 --- a/invesalius/gui/dicom_preview_panel.py +++ b/invesalius/gui/dicom_preview_panel.py @@ -1,12 +1,13 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- +#TODO: To create a beautiful API import wx import vtk import vtkgdcm from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor -#from reader import dicom_reader +from reader import dicom_reader myEVT_SELECT = wx.NewEventType() # This event occurs when the user select a preview @@ -31,66 +32,10 @@ class SerieEvent(PreviewEvent): def __init__(self , evtType, id): super(SerieEvent, self).__init__(evtType, id) -class DicomImageData(object): - def __init__(self): - pass - - def SetInput(self, dicom): - reader = vtkgdcm.vtkGDCMImageReader() - reader.SetFileName(dicom.image.file) - imagedata = reader.GetOutput() - - scale = imagedata.GetScalarRange() - - cast = vtk.vtkImageMapToWindowLevelColors() - cast.SetInput(imagedata) - cast.SetWindow(float(dicom.image.window)) - cast.SetLevel(float(dicom.image.level)) - - self.imagedata = cast.GetOutput() - - def GetOutput(self): - return self.imagedata - - -class DicomLoader(object): - """ - Responsible for load dicom files. A dictionary like behavior - """ - def __init__(self): - self.loaded_dicoms = {} - - def __getitem__(self, filename): - """ - Especial method to behave like dictionary - """ - try: - return self.loaded_dicoms[filename] - except KeyError: - #print "Except" - self._load_dicom_files(filename) - return self.loaded_dicoms[filename] - - def _load_dicom_files(self, filename, window=150, level=230): - reader = vtkgdcm.vtkGDCMImageReader() - reader.SetFileName(filename) - imagedata = reader.GetOutput() - - scale = imagedata.GetScalarRange() - - cast = vtk.vtkImageMapToWindowLevelColors() - cast.SetInput(imagedata) - cast.SetWindow(float(window)) - cast.SetLevel(float(level)) - - self.loaded_dicoms[filename] = cast.GetOutput() - - class Preview(wx.Panel): """ Where the images will be showed. """ - dicom_loader = DicomLoader() def __init__(self, parent): super(Preview, self).__init__(parent) # Will it be white? @@ -140,29 +85,40 @@ class Preview(wx.Panel): def SetSubtitle(self, subtitle): self.subtitle.SetLabel(subtitle) - def SetGroup(self, group): - self.SetTitle(group.title) - self.SetSubtitle("%d images"%(group.nslices)) - d = DicomImageData() - d.SetInput(group.dicom) - imagedata = d.GetOutput() - self.actor.SetInput(imagedata) - self.render.ResetCamera() - - def SetImage(self, image_data): + def SetImage(self, image_file): """ Set a Image to preview. """ - filename, window, level, title, subtitle = image_data - print image_data - self.SetTitle(title) - self.SetSubtitle(subtitle) - #self.ID = image_file[5] # todo: check if this is necessary + self.SetTitle(image_file[3]) + self.SetSubtitle(image_file[4]) + self.ID = image_file[5] + + image_reader = vtkgdcm.vtkGDCMImageReader() + image_reader.SetFileName(image_file[0]) + image = image_reader.GetOutput() + + scale = image.GetScalarRange() + + cast = vtk.vtkImageMapToWindowLevelColors() + #cast.SetShift(abs(scale[0])) + #cast.SetScale(255.0/(scale[1] - scale[0])) + #cast.ClampOverflowOn() + cast.SetInput(image) + #cast.SetOutputScalarTypeToUnsignedChar() + try: + window = float(image_file[1]) + level = float(image_file[2]) + except TypeError: + #TODO: These values are good? + level = 230 + window = 150 - # TODO: enhace interface - imagedata = Preview.dicom_loader[filename] - self.actor.SetInput(imagedata) + cast.SetWindow(window) + cast.SetLevel(level) + self.actor.SetInput(cast.GetOutput()) self.render.ResetCamera() + #self.interactor.Render() + class DicomPreviewSeries(wx.Panel): """A dicom series preview panel""" @@ -173,6 +129,7 @@ class DicomPreviewSeries(wx.Panel): self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.SetSizer(self.sizer) self.displayed_position = 0 + self.files = [] self._init_ui() def _init_ui(self): @@ -202,54 +159,59 @@ class DicomPreviewSeries(wx.Panel): my_evt.SetSelectedID(evt.GetSelectID()) self.GetEventHandler().ProcessEvent(my_evt) - def SetDicomDirectory(self, directory): - print "SetDicomDirectory" + def SetPatientGroups(self, patient): + group_list = patient.GetGroups() + n = 0 + for group in group_list: + info = (group.dicom.image.file, + float(group.dicom.image.window), + float(group.dicom.image.level), + group.title, + "%d Images" %(group.nslices), + n) + self.files.append(info) + n+=1 + + scroll_range = len(self.files)/5 + if scroll_range * 5 < len(self.files): + scroll_range +=1 + self.scroll.SetScrollbar(0, 3, scroll_range, 5) + + self._Display_Previews() + + + def SetDicomDirectoryOld(self, directory): + import time + a = time.time() self.directory = directory self.series = dicom_reader.GetSeries(directory)[0] - print "keys", [key[0] for key in self.series.keys()] - - s = self.series - for k in s.keys(): - print "------ PESSOA ---------" - print "%s (%d series)"%(k[0], len(s[k])-1) - for ns in range(1,len(s[k])): - print "------ SERIE ---------" - print "unnamed" - print "age %s" %(s[k][ns][8]) - print "date acquired %s %s" %(s[k][ns][0], s[k][ns][4]) - print "birthdate %s" %(s[k][ns][23]) - print "institution %s" %(s[k][ns][6]) - + b = time.time() # TODO: I need to improve this self.files = [(self.series[i][0][0][8], # Filename self.series[i][0][0][12], # Window Level self.series[i][0][0][13], # Window Width - "unnamed", #% (n + 1), # Title + "Serie %d" % (n + 1), # Title "%d Images" % len(self.series[i][0]), # Subtitle - i) for n, i in enumerate(self.series)] + n) for n, i in enumerate(self.series)] - def SetDicomSeries(self, patient): - #self.files = files - ngroups = patient.ngroups - self.groups = patient.GetGroups() - - scroll_range = ngroups/5 - if scroll_range * 5 < ngroups: + scroll_range = len(self.files)/5 + if scroll_range * 5 < len(self.files): scroll_range +=1 self.scroll.SetScrollbar(0, 3, scroll_range, 5) - self._display_previews() - def _display_previews(self): - begin = self.displayed_position * 5 - end = begin + 15 - for group, preview in zip(self.groups[begin:end], self.previews): - preview.SetGroup(group) - preview.Show() + self._Display_Previews() + + def _Display_Previews(self): + initial = self.displayed_position * 5 + final = initial + 15 + for f, p in zip(self.files[initial:final], self.previews): + p.SetImage(f) + p.Show() def OnScroll(self, evt): self.displayed_position = evt.GetPosition() [i.Hide() for i in self.previews] - self._display_previews() + self._Display_Previews() class DicomPreview(wx.Panel): @@ -261,7 +223,7 @@ class DicomPreview(wx.Panel): self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.SetSizer(self.sizer) self.displayed_position = 0 - self.nhidden_last_display = 0 + self.files = [] self._init_ui() def _init_ui(self): @@ -277,7 +239,7 @@ class DicomPreview(wx.Panel): for i in xrange(3): for j in xrange(5): p = Preview(self) - #p.Hide() + p.Hide() self.previews.append(p) self.grid.Add(p, i, j) @@ -289,47 +251,55 @@ class DicomPreview(wx.Panel): self.directory = directory self.series = dicom_reader.GetSeries(directory)[0] - def SetDicomSerie(self, serie): - k = serie + def SetPatientGroups(self, patient): + self.group_list = patient.GetGroups() + + def SetDicomSerie(self, pos): + group = self.group_list[pos] + #dicom_files = group.GetList() + dicom_files = group.GetHandSortedList() + n = 0 + for dicom in dicom_files: + info = (dicom.image.file, + dicom.image.window, + dicom.image.level, + "Image %d" % (dicom.image.number), + "%.2f" % (dicom.image.position[2]), + n) + self.files.append(info) + n+=1 + + scroll_range = len(self.files)/5 + if scroll_range * 5 < len(self.files): + scroll_range +=1 + self.scroll.SetScrollbar(0, 3, scroll_range, 5) + self._Display_Previews() + + def SetDicomSerieOld(self, serie): + k = self.series.keys()[serie] self.files = [(i[8], i[12], i[13], - "Image %d" % (n + 1), # Title - "%s"% str(i[3][2]), # Spacing - n)for n, i in enumerate(self.series[k][0])] + "Serie %d" % (n + 1), # Title + "%d Images" % n, # Subtitle + n)for n, i in enumerate(self.series[k][0])] scroll_range = len(self.files)/5 if scroll_range * 5 < len(self.files): scroll_range +=1 self.scroll.SetScrollbar(0, 3, scroll_range, 5) - self._display_previews() + self._Display_Previews() - def _display_previews(self): + def _Display_Previews(self): initial = self.displayed_position * 5 final = initial + 15 - - if len(self.files) < final: - for i in xrange(final-len(self.files)): - try: - self.previews[-i-1].Hide() - except IndexError: - #print "doesn't exist!" - pass - self.nhidden_last_display = final-len(self.files) - else: - if self.nhidden_last_display: - for i in xrange(self.nhidden_last_display): - try: - self.previews[-i-1].Show() - except IndexError: - #print "doesn't exist!" - pass - self.nhidden_last_display = 0 - for f, p in zip(self.files[initial:final], self.previews): p.SetImage(f) - p.interactor.Render() + p.Show() def OnScroll(self, evt): - if self.displayed_position != evt.GetPosition(): - self.displayed_position = evt.GetPosition() - self._display_previews() + self.displayed_position = evt.GetPosition() + [i.Hide() for i in self.previews] + self._Display_Previews() + self.Update() + self.Update() + diff --git a/invesalius/gui/import_panel.py b/invesalius/gui/import_panel.py index 99fbbe0..853a992 100644 --- a/invesalius/gui/import_panel.py +++ b/invesalius/gui/import_panel.py @@ -153,7 +153,7 @@ class TextPanel(wx.Panel): class ImagePanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) - self.SetBackgroundColour((0,255,0)) + #self.SetBackgroundColour((0,255,0)) splitter = spl.MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetOrientation(wx.HORIZONTAL) @@ -172,19 +172,48 @@ class ImagePanel(wx.Panel): class SeriesPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) - self.SetBackgroundColour((0,0,0)) + #self.SetBackgroundColour((0,0,0)) + self.serie_preview = dpp.DicomPreviewSeries(self) + self.dicom_preview = dpp.DicomPreview(self) + self.dicom_preview.Show(0) + + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.sizer.Add(self.serie_preview, 1, wx.EXPAND | wx.ALL, 5) + self.sizer.Add(self.dicom_preview, 1, wx.EXPAND | wx.ALL, 5) + self.sizer.Fit(self) + + self.SetSizer(self.sizer) + self.SetAutoLayout(True) + self.Show() + self.__bind_evt() + self._bind_gui_evt() def __bind_evt(self): ps.Publisher().subscribe(self.ShowDicomSeries, "Load dicom preview") + def _bind_gui_evt(self): + self.Bind(dpp.EVT_SELECT_SERIE, self.OnSelectSerie) + + def OnSelectSerie(self, evt): + serie = evt.GetSelectID() + self.dicom_preview.SetDicomSerie(serie) + + self.dicom_preview.Show(1) + #self.sizer.Detach(self.serie_preview) + self.serie_preview.Show(0) + self.sizer.Layout() + #self.Show() + self.Update() + + def ShowDicomSeries(self, pubsub_evt): print "---- ShowDicomSeries ----" - list_dicom = pubsub_evt.data - print list_dicom - self.serie_preview.SetDicomSeries(list_dicom) + first_patient = pubsub_evt.data + self.serie_preview.SetPatientGroups(first_patient) + self.dicom_preview.SetPatientGroups(first_patient) diff --git a/invesalius/invesalius.py b/invesalius/invesalius.py index cba0c98..3334c3a 100755 --- a/invesalius/invesalius.py +++ b/invesalius/invesalius.py @@ -43,7 +43,7 @@ class InVesalius(wx.App): def OnInit(self): self.main = Frame(None) self.control = Controller(self.main) - self.SetAppName("InVesalius 3.0") + self.SetAppName("InVesalius 3") return True def ShowFrame(self): -- libgit2 0.21.2