import os.path from pprint import pprint # dicom.debug() if __name__ == "__main__": print("------------------------------------------------------------") print("Example program showing DICOMDIR contents, assuming standard") print("Patient -> Study -> Series -> Images hierarchy") print("------------------------------------------------------------") print() if len(sys.argv) > 1: filepath = sys.argv[1] if os.path.isdir(filepath): # only gave directory, add standard name filepath = os.path.join(filepath, "DICOMDIR") dcmdir = dicom.read_dicomdir(filepath) base_dir = os.path.dirname(filepath) else: # Read standard "DICOMDIR" filename from current directory dcmdir = dicom.read_dicomdir() base_dir = "." for patrec in dcmdir.patient_records: print("Patient: {0.PatientID}: {0.PatientsName}".format(patrec)) studies = patrec.children for study in studies: print((" Study {0.StudyID}: {0.StudyDate}:" " {0.StudyDescription}".format(study))) all_series = study.children for series in all_series: image_count = len(series.children)
print "Patient -> Study -> Series -> Images hierarchy" print "------------------------------------------------------------" print if len(sys.argv) > 1: filepath = sys.argv[1] if os.path.isdir(filepath): # only gave directory, add standard name filepath = os.path.join(filepath, "DICOMDIR") dcmdir = dicom.read_dicomdir(filepath) base_dir = os.path.dirname(filepath) else: # Read standard "DICOMDIR" filename from current directory dcmdir = dicom.read_dicomdir() base_dir = "." for patrec in dcmdir.patient_records: print "Patient: {0.PatientID}: {0.PatientsName}".format(patrec)
# test.py """Temporary test file for pydicom development; will change over revisions as test various things """ # Copyright (c) 2013 Darcy Mason # This file is part of pydicom, relased under an MIT-style license. # See the file license.txt included with this distribution, also # available at http://pydicom.googlecode.com # import dicom # dicom.debug() if __name__ == "__main__": dcmdir = dicom.read_dicomdir() for patrec in dcmdir.patient_records: print("Patient: {0.PatientID}: {0.PatientsName}".format(patrec)) studies = patrec.children for study in studies: print(" Study {0.StudyID}: {0.StudyDate}:" " {0.StudyDescription}".format(study)) all_series = study.children for series in all_series: image_count = len(series.children) plural = ('', 's')[image_count > 1] print(" " * 8 + "Series {0.SeriesNumber}: {0.SeriesDescription}" " ({1} image{2})".format(series, image_count, plural))
# test.py """Temporary test file for pydicom development; will change over revisions as test various things """ # Copyright (c) 2013 Darcy Mason # This file is part of pydicom, relased under an MIT-style license. # See the file license.txt included with this distribution, also # available at http://pydicom.googlecode.com # import dicom # dicom.debug() if __name__ == "__main__": dcmdir = dicom.read_dicomdir() for patrec in dcmdir.patient_records: print "Patient: {0.PatientID}: {0.PatientsName}".format(patrec) studies = patrec.children for study in studies: print (" Study {0.StudyID}: {0.StudyDate}:" " {0.StudyDescription}".format(study)) all_series = study.children for series in all_series: image_count = len(series.children) plural = ('', 's')[image_count > 1] print (" " * 8 + "Series {0.SeriesNumber}: {0.SeriesDescription}" " ({1} image{2})".format(series, image_count, plural))
def main(argv=None): if argv is None: argv = sys.argv[1:] # parse input from command line args = create_parser().parse_args(argv) if os.path.isdir(args.filepath): # only gave directory, add standard name filepath = os.path.join(args.filepath, "DICOMDIR") dcmdir = dicom.read_dicomdir(args.filepath) base_dir = os.path.dirname(args.filepath) for patrec in dcmdir.patient_records: print "Patient: {0.PatientID}: {0.PatientsName}".format(patrec) studies = patrec.children for study in studies: print( " Study {0.StudyID}: {0.StudyDate}: " "{0.StudyDescription} ({0.StudyInstanceUID})".format(study)) all_series = study.children for series in all_series: image_count = len(series.children) plural = ('', 's')[image_count > 1] # Write basic series info and image count # Put N/A in if no Series Description if 'SeriesDescription' not in series: series.SeriesDescription = "N/A" print( " " * 4 + "Series {0.SeriesNumber}: {0.Modality}: {0.SeriesDescription}" " ({0.SeriesInstanceUID}, {1} image{2})".format( series, image_count, plural)) if args.verbosity > 0: # Open and read something from each image, for demonstration purposes # For simple quick overview of DICOMDIR, leave the following out print " " * 8 + "Reading images..." image_records = series.children image_filenames = [ os.path.join(base_dir, *image_rec.ReferencedFileID) for image_rec in image_records ] # slice_locations = [dicom.read_file(image_filename).SliceLocation # for image_filename in image_filenames] datasets = [ dicom.read_file(image_filename) for image_filename in image_filenames ] patient_names = set(ds.PatientName for ds in datasets) patient_IDs = set(ds.PatientID for ds in datasets) # List the image filenames print "\n" + " " * 8 + "Image filenames:" print " " * 8, pprint(image_filenames, indent=8) # Expect all images to have same patient name, id # Show the set of all names, IDs found (should each have one) print( " " * 8 + "Patient Names in images..: " "{0:s}".format(patient_names)) print( " " * 8 + "Patient IDs in images..:" "{0:s}".format(patient_IDs))
def __init__(self, parent, path=None, main=None): wx.Panel.__init__(self, parent, -1) self.main = main self._last_filename = None self._ds = None self._search_filter = None self.Bind(wx.EVT_SIZE, self.OnSize) self.tree = gizmos.TreeListCtrl( self, -1, style=wx.TR_DEFAULT_STYLE #| wx.TR_HAS_BUTTONS #| wx.TR_TWIST_BUTTONS #| wx.TR_ROW_LINES # | wx.TR_COLUMN_LINES #| wx.TR_NO_LINES | wx.TR_FULL_ROW_HIGHLIGHT) self._column_widths = [0, 0, 0, 0, 0] # list of files to load self.filenames = [] # filename/title to give current selection self.filename = None self.canonical_series_name = 'DICOMDIR' isz = (16, 16) il = wx.ImageList(isz[0], isz[1]) fldridx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) fldropenidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) fileidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) self.tree.SetImageList(il) self.il = il # create some columns self.tree.AddColumn("Series ID") self.tree.AddColumn("Modality") self.tree.AddColumn("Description") self.tree.AddColumn("Acquisition") self.tree.AddColumn("Image Count") self.tree.SetMainColumn(0) # the one with the tree in it... self.tree.SetColumnWidth(1, wx.COL_WIDTH_AUTOSIZE) self.tree.SetColumnWidth(3, wx.COL_WIDTH_AUTOSIZE) self.tree.SetColumnWidth(4, wx.COL_WIDTH_AUTOSIZE) self.root = self.tree.AddRoot("Patient List") self.tree.SetItemImage(self.root, fldridx, which=wx.TreeItemIcon_Normal) self.tree.SetItemImage(self.root, fldropenidx, which=wx.TreeItemIcon_Expanded) if path is None: path = '/mnt/Users/jerem_000/Desktop/DICOM/DICOM/DICOMDIR' path = os.path.abspath(path) # Why is this path manipulation needed? if os.path.isdir(path): self.base_dir = os.path.abspath(os.path.join(path, '..')) else: self.base_dir = os.path.abspath(os.path.dirname(path)) with wx.BusyCursor(): try: self._full_ds = ds = dicom.read_dicomdir(path) except: logging.error("Unable to read '{}'".format(path)) return self.filename = path # copied from ImageInfo.py ++ encoding = ds.get('SpecificCharacterSet', 'utf-8') python_encoding = { '': 'iso8859', # default character set for DICOM 'ISO_IR 6': 'iso8859', # alias for latin_1 too 'ISO_IR 100': 'latin_1', 'ISO 2022 IR 87': 'iso2022_jp', # XXX this mapping does not work on chrH32.dcm test files (but # no others do either) 'ISO 2022 IR 13': 'iso2022_jp', # XXX chrI2.dcm -- does not quite work -- some chrs wrong. Need # iso_ir_149 python encoding 'ISO 2022 IR 149': 'euc_kr', # from Chinese example, 2008 PS3.5 Annex J p1-4 'ISO_IR 192': 'UTF8', 'GB18030': 'GB18030', 'ISO_IR 126': 'iso_ir_126', # Greek 'ISO_IR 127': 'iso_ir_127', # Arab 'ISO_IR 138': 'iso_ir_138', # Hebrew 'ISO_IR 144': 'iso_ir_144', # Russian } # copied from ImageInfo.py -- for patient in ds.patient_records: txt = patient.PatientName or '* No Patient Name *' self._column_widths[0] = max(self._column_widths[0], self.tree.GetTextExtent(txt)[0]) data = wx.TreeItemData() data.SetData((patient, -1)) child = self.tree.AppendItem(self.root, txt, data=data) self.tree.SetItemText(child, patient.PatientID, 1) studies = patient.children for study in studies: encoding = study.get('SpecificCharacterSet', 'utf-8') if encoding in python_encoding: encoding = python_encoding[encoding] txt = study.StudyID or '* No Study ID *' self._column_widths[1] = max( self._column_widths[1], self.tree.GetTextExtent(txt)[0]) data = wx.TreeItemData() data.SetData((study, -1)) child2 = self.tree.AppendItem(child, txt, data=data) self.tree.SetItemText(child2, study.get('StudyDate', '--'), 1) try: s = study.get('StudyDescription', '--').decode(encoding) except: s = '* Unprintable Study Description *' self.tree.SetItemText(child2, s, 2) all_series = study.children for series in all_series: image_records = series.children acquisitions = {} for rec in series.children: if rec.DirectoryRecordType == 'IMAGE': acq = rec.get('AcquisitionNumber', -1) if acq not in acquisitions: acquisitions[acq] = 0 acquisitions[acq] += 1 txt = str(series.SeriesNumber) series_desc = series.get('SeriesDescription', '* No Series Description *') # support multiple acquisitions if len(acquisitions) == 1 and -1 in acquisitions: data = wx.TreeItemData() data.SetData((series, -1)) child3 = self.tree.AppendItem( child2, series_desc.decode(encoding), data=data) modality = series.get('Modality', '--') self.tree.SetItemText(child3, modality, 1) self.tree.SetItemText(child3, series_desc.decode(encoding), 2) self.tree.SetItemText(child3, str(acquisitions[-1]), 4) else: for acq in acquisitions: data = wx.TreeItemData() data.SetData((series, acq)) child3 = self.tree.AppendItem(child2, txt, data=data) modality = series.get('Modality', '--') self.tree.SetItemText(child3, modality, 1) self.tree.SetItemText( child3, series_desc.decode(encoding), 2) self.tree.SetItemText(child3, str(acq), 3) self.tree.SetItemText(child3, str(acquisitions[acq]), 4) self.tree.Expand(self.root) self.tree.GetMainWindow().Bind(wx.EVT_RIGHT_UP, self.OnRightUp) self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate) self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged) self.tree.Bind(wx.EVT_SIZE, self._onResize) self.tree.Bind(wx.EVT_LIST_COL_END_DRAG, self._onResize, self)
def __init__(self, parent, path=None, main=None): wx.Panel.__init__(self, parent, -1) self.main = main self._last_filename = None self._ds = None self._search_filter = None self.Bind(wx.EVT_SIZE, self.OnSize) self.tree = gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE #| wx.TR_HAS_BUTTONS #| wx.TR_TWIST_BUTTONS #| wx.TR_ROW_LINES # | wx.TR_COLUMN_LINES #| wx.TR_NO_LINES | wx.TR_FULL_ROW_HIGHLIGHT ) self._column_widths = [0, 0, 0, 0, 0] # list of files to load self.filenames = [] # filename/title to give current selection self.filename = None self.canonical_series_name = 'DICOMDIR' isz = (16, 16) il = wx.ImageList(isz[0], isz[1]) fldridx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) fldropenidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) fileidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) self.tree.SetImageList(il) self.il = il # create some columns self.tree.AddColumn("Series ID") self.tree.AddColumn("Modality") self.tree.AddColumn("Description") self.tree.AddColumn("Acquisition") self.tree.AddColumn("Image Count") self.tree.SetMainColumn(0) # the one with the tree in it... self.tree.SetColumnWidth(1, wx.COL_WIDTH_AUTOSIZE) self.tree.SetColumnWidth(3, wx.COL_WIDTH_AUTOSIZE) self.tree.SetColumnWidth(4, wx.COL_WIDTH_AUTOSIZE) self.root = self.tree.AddRoot("Patient List") self.tree.SetItemImage( self.root, fldridx, which=wx.TreeItemIcon_Normal) self.tree.SetItemImage( self.root, fldropenidx, which=wx.TreeItemIcon_Expanded) if path is None: path = '/mnt/Users/jerem_000/Desktop/DICOM/DICOM/DICOMDIR' path = os.path.abspath(path) # Why is this path manipulation needed? if os.path.isdir(path): self.base_dir = os.path.abspath(os.path.join(path, '..')) else: self.base_dir = os.path.abspath(os.path.dirname(path)) with wx.BusyCursor(): try: self._full_ds = ds = dicom.read_dicomdir(path) except: logging.error("Unable to read '{}'".format(path)) return self.filename = path # copied from ImageInfo.py ++ encoding = ds.get('SpecificCharacterSet', 'utf-8') python_encoding = { '': 'iso8859', # default character set for DICOM 'ISO_IR 6': 'iso8859', # alias for latin_1 too 'ISO_IR 100': 'latin_1', 'ISO 2022 IR 87': 'iso2022_jp', # XXX this mapping does not work on chrH32.dcm test files (but # no others do either) 'ISO 2022 IR 13': 'iso2022_jp', # XXX chrI2.dcm -- does not quite work -- some chrs wrong. Need # iso_ir_149 python encoding 'ISO 2022 IR 149': 'euc_kr', # from Chinese example, 2008 PS3.5 Annex J p1-4 'ISO_IR 192': 'UTF8', 'GB18030': 'GB18030', 'ISO_IR 126': 'iso_ir_126', # Greek 'ISO_IR 127': 'iso_ir_127', # Arab 'ISO_IR 138': 'iso_ir_138', # Hebrew 'ISO_IR 144': 'iso_ir_144', # Russian } # copied from ImageInfo.py -- for patient in ds.patient_records: txt = patient.PatientName or '* No Patient Name *' self._column_widths[0] = max( self._column_widths[0], self.tree.GetTextExtent(txt)[0]) data = wx.TreeItemData() data.SetData((patient, -1)) child = self.tree.AppendItem(self.root, txt, data=data) self.tree.SetItemText(child, patient.PatientID, 1) studies = patient.children for study in studies: encoding = study.get('SpecificCharacterSet', 'utf-8') if encoding in python_encoding: encoding = python_encoding[encoding] txt = study.StudyID or '* No Study ID *' self._column_widths[1] = max( self._column_widths[1], self.tree.GetTextExtent(txt)[0]) data = wx.TreeItemData() data.SetData((study, -1)) child2 = self.tree.AppendItem(child, txt, data=data) self.tree.SetItemText( child2, study.get('StudyDate', '--'), 1) try: s = study.get( 'StudyDescription', '--').decode(encoding) except: s = '* Unprintable Study Description *' self.tree.SetItemText(child2, s, 2) all_series = study.children for series in all_series: image_records = series.children acquisitions = {} for rec in series.children: if rec.DirectoryRecordType == 'IMAGE': acq = rec.get('AcquisitionNumber', -1) if acq not in acquisitions: acquisitions[acq] = 0 acquisitions[acq] += 1 txt = str(series.SeriesNumber) series_desc = series.get( 'SeriesDescription', '* No Series Description *') # support multiple acquisitions if len(acquisitions) == 1 and -1 in acquisitions: data = wx.TreeItemData() data.SetData((series, -1)) child3 = self.tree.AppendItem( child2, series_desc.decode(encoding), data=data) modality = series.get('Modality', '--') self.tree.SetItemText(child3, modality, 1) self.tree.SetItemText( child3, series_desc.decode(encoding), 2) self.tree.SetItemText( child3, str(acquisitions[-1]), 4) else: for acq in acquisitions: data = wx.TreeItemData() data.SetData((series, acq)) child3 = self.tree.AppendItem( child2, txt, data=data) modality = series.get('Modality', '--') self.tree.SetItemText(child3, modality, 1) self.tree.SetItemText( child3, series_desc.decode(encoding), 2) self.tree.SetItemText(child3, str(acq), 3) self.tree.SetItemText( child3, str(acquisitions[acq]), 4) self.tree.Expand(self.root) self.tree.GetMainWindow().Bind(wx.EVT_RIGHT_UP, self.OnRightUp) self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate) self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged) self.tree.Bind(wx.EVT_SIZE, self._onResize) self.tree.Bind(wx.EVT_LIST_COL_END_DRAG, self._onResize, self)