Skip to content

Commit

Permalink
feat: Add getDICOMTags method to NBIAClient class
Browse files Browse the repository at this point in the history
  • Loading branch information
jjjermiah committed Feb 6, 2024
1 parent 1082e47 commit 18b6625
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 2 deletions.
108 changes: 108 additions & 0 deletions src/nbiatoolkit/dicomsort/dcm_qt_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# dcm_qt_tree.py
"""View DICOM files in a tree using Qt and PySide2"""
# Copyright (c) 2013 Padraig Looney
# This file is released under the
# pydicom (https://github.com/pydicom/pydicom)
# license, see the file LICENSE available at
# (https://github.com/pydicom/pydicom)

import pydicom
import sys
from PySide2 import QtGui
import collections


# # dcm_qt_tree.py
# """View DICOM files in a tree using Qt and PySide"""
# # Copyright (c) 2013 Padraig Looney
# # This file is released under the
# # pydicom (https://github.com/pydicom/pydicom)
# # license, see the file LICENSE available at
# # (https://github.com/pydicom/pydicom)

# import pydicom
# import sys
# from PySide import QtGui
# import collections


# class DicomTree(object):
# def __init__(self, filename):
# self.filename = filename
# def show_tree(self):
# ds = self.dicom_to_dataset(self.filename)
# dic = self.dataset_to_dic(ds)
# model = self.dic_to_model(dic)
# self.display(model)
# def array_to_model(self, array):
# model = QtGui.QStandardItemModel()
# parentItem = model.invisibleRootItem()
# for ntuple in array:
# tag = ntuple[0]
# value = ntuple[1]
# if isinstance(value, dict):
# self.recurse_dic_to_item(value, parentItem)
# else:
# item = QtGui.QStandardItem(tag + str(value))
# parentItem.appendRow(item)
# return parentItem
# def dic_to_model(self, dic):
# model = QtGui.QStandardItemModel()
# parentItem = model.invisibleRootItem()
# self.recurse_dic_to_item(dic, parentItem)
# return model
# def dataset_to_array(self, dataset):
# array = []
# for data_element in dataset:
# array.append(self.data_element_to_dic(data_element))
# return array
# def recurse_dic_to_item(self, dic, parent):
# for k in dic:
# v = dic[k]
# if isinstance(v, dict):
# item = QtGui.QStandardItem(k + ':' + str(v))
# parent.appendRow(self.recurse_dic_to_item(v, item))
# else:
# item = QtGui.QStandardItem(k + ': ' + str(v))
# parent.appendRow(item)
# return parent
# def dicom_to_dataset(self, filename):
# dataset = pydicom.dcmread(filename, force=True)
# return dataset
# def data_element_to_dic(self, data_element):
# dic = collections.OrderedDict()
# if data_element.VR == "SQ":
# items = collections.OrderedDict()
# dic[data_element.name] = items
# i = 0
# for dataset_item in data_element:
# items['item ' + str(i)] = self.dataset_to_dic(dataset_item)
# i += 1
# elif data_element.name != 'Pixel Data':
# dic[data_element.name] = data_element.value
# return dic
# def dataset_to_dic(self, dataset):
# dic = collections.OrderedDict()
# for data_element in dataset:
# dic.update(self.data_element_to_dic(data_element))
# return dic
# def display(self, model):
# app = QtGui.QApplication.instance()
# # create QApplication if it doesnt exist
# if not app:
# app = QtGui.QApplication(sys.argv)
# tree = QtGui.QTreeView()
# tree.setModel(model)
# tree.show()
# app.exec_()
# return tree


# def main():
# filename = sys.argv[1]
# dicomTree = DicomTree(filename)
# dicomTree.show_tree()


# if __name__ == "__main__":
# main()
139 changes: 139 additions & 0 deletions src/nbiatoolkit/dicomsort/test_dicom_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@


import pydicom
from dataclasses import dataclass
from typing import Optional

@dataclass
class DicomData:
study_instance_uid: Optional[str] = None
series_instance_uid: Optional[str] = None
sop_instance_uid: Optional[str] = None
image_type: Optional[str] = None
study_id: Optional[str] = None
series_number: Optional[int] = None
acquisition_number: Optional[int] = None
instance_number: Optional[int] = None
image_position_patient: Optional[str] = None
image_orientation_patient: Optional[str] = None
frame_of_reference_uid: Optional[str] = None
position_reference_indicator: Optional[str] = None
slice_location: Optional[str] = None
samples_per_pixel: Optional[int] = None
rows: Optional[int] = None
columns: Optional[int] = None
pixel_spacing: Optional[str] = None
study_date: Optional[str] = None
series_date: Optional[str] = None
modality: Optional[str] = None
study_description: Optional[str] = None
series_description: Optional[str] = None
patient_name: Optional[str] = None
patient_id: Optional[str] = None
patient_birth_date: Optional[str] = None
patient_sex: Optional[str] = None
patient_age: Optional[str] = None
instance_creation_date: Optional[str] = None
instance_creation_time: Optional[str] = None

def to_dataset(self):
ds = pydicom.Dataset()
ds.StudyInstanceUID = self.study_instance_uid
ds.SeriesInstanceUID = self.series_instance_uid
ds.SOPInstanceUID = self.sop_instance_uid
ds.ImageType = self.image_type
ds.StudyID = self.study_id
ds.SeriesNumber = self.series_number
ds.AcquisitionNumber = self.acquisition_number
ds.InstanceNumber = self.instance_number
ds.ImagePositionPatient = self.image_position_patient
ds.ImageOrientationPatient = self.image_orientation_patient
ds.FrameOfReferenceUID = self.frame_of_reference_uid
ds.PositionReferenceIndicator = self.position_reference_indicator
ds.SliceLocation = self.slice_location
ds.SamplesPerPixel = self.samples_per_pixel
ds.Rows = self.rows
ds.Columns = self.columns
ds.PixelSpacing = self.pixel_spacing
ds.StudyDate = self.study_date
ds.SeriesDate = self.series_date
ds.Modality = self.modality
ds.StudyDescription = self.study_description
ds.SeriesDescription = self.series_description
ds.PatientName = self.patient_name
ds.PatientID = self.patient_id
ds.PatientBirthDate = self.patient_birth_date
ds.PatientSex = self.patient_sex
ds.PatientAge = self.patient_age
ds.InstanceCreationDate = self.instance_creation_date
ds.InstanceCreationTime = self.instance_creation_time

return ds

def read_subset_dicom(file_path):
ds = pydicom.dcmread(file_path)
dicom_data = DicomData(
study_instance_uid=ds.get("StudyInstanceUID"),
series_instance_uid=ds.get("SeriesInstanceUID"),
sop_instance_uid=ds.get("SOPInstanceUID"),
image_type=ds.get("ImageType"),
study_id=ds.get("StudyID"),
series_number=ds.get("SeriesNumber"),
acquisition_number=ds.get("AcquisitionNumber"),
instance_number=ds.get("InstanceNumber"),
image_position_patient=ds.get("ImagePositionPatient"),
image_orientation_patient=ds.get("ImageOrientationPatient"),
frame_of_reference_uid=ds.get("FrameOfReferenceUID"),
position_reference_indicator=ds.get("PositionReferenceIndicator"),
slice_location=ds.get("SliceLocation"),
samples_per_pixel=ds.get("SamplesPerPixel"),
rows=ds.get("Rows"),
columns=ds.get("Columns"),
pixel_spacing=ds.get("PixelSpacing"),
study_date=ds.get("StudyDate"),
series_date=ds.get("SeriesDate"),
modality=ds.get("Modality"),
study_description=ds.get("StudyDescription"),
series_description=ds.get("SeriesDescription"),
patient_name=ds.get("PatientName"),
patient_id=ds.get("PatientID"),
patient_birth_date=ds.get("PatientBirthDate"),
patient_sex=ds.get("PatientSex"),
patient_age=ds.get("PatientAge"),
instance_creation_date=ds.get("InstanceCreationDate"),
instance_creation_time=ds.get("InstanceCreationTime")
)
return dicom_data


def create_DicomData_from_DICT(data_list):
dicom_data = DicomData(
study_instance_uid=data_list.get("StudyInstanceUID"),
series_instance_uid=data_list.get("SeriesInstanceUID"),
sop_instance_uid=data_list.get("SOPInstance"),
image_type=data_list.get("ImageType"),
study_id=data_list.get("StudyID"),
series_number=data_list.get("SeriesNumber"),
acquisition_number=data_list.get("AcquisitionNumber"),
instance_number=data_list.get("InstanceNumber"),
image_position_patient=data_list.get("ImagePositionPatient"),
image_orientation_patient=data_list.get("ImageOrientationPatient"),
frame_of_reference_uid=data_list.get("FrameOfReferenceUID"),
position_reference_indicator=data_list.get("PositionReferenceIndicator"),
slice_location=data_list.get("SliceLocation"),
samples_per_pixel=data_list.get("SamplesPerPixel"),
rows=data_list.get("Rows"),
columns=data_list.get("Columns"),
pixel_spacing=data_list.get("PixelSpacing"),
study_date=data_list.get("StudyDate"),
series_date=data_list.get("SeriesDate"),
modality=data_list.get("Modality"),
study_description=data_list.get("StudyDescription"),
series_description=data_list.get("SeriesDescription"),
patient_name=data_list.get("PatientName"),
patient_id=data_list.get("PatientID"),
patient_birth_date=data_list.get("PatientBirthDate"),
patient_age=data_list.get("PatientAge"),
instance_creation_date=data_list.get("InstanceCreationDate"),
instance_creation_time=data_list.get("InstanceCreationTime")
)
132 changes: 132 additions & 0 deletions src/nbiatoolkit/dicomsort/test_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@

import sys

import pydicom
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import (QApplication, QDesktopWidget, QTreeView,
QVBoxLayout, QWidget)


class DicomTree(QWidget):
def __init__(self, filename):
super().__init__()
self.filename = filename
self.setWindowTitle('DICOM Tree')
self.setGeometry(0, 0, 800, 600)
self.center()

self.create_model()
self.init_tree()
self.show()

def center(self):
# Get geometry of the main window
qr = self.frameGeometry()
# Get the center point of screen
cp = QDesktopWidget().availableGeometry().center()
# Move rectangle's center point to screen's center point
qr.moveCenter(cp)
# top left of rectangle becomes top left of window centering it
self.move(qr.topLeft())

def create_model(self):
model = QStandardItemModel(0, 5, self)
model.setHeaderData(0, Qt.Horizontal, "Name")
model.setHeaderData(1, Qt.Horizontal, "Value")
model.setHeaderData(2, Qt.Horizontal, "Tag")
model.setHeaderData(3, Qt.Horizontal, "VM")
model.setHeaderData(4, Qt.Horizontal, "VR")
parentItem = model.invisibleRootItem()

ds = pydicom.read_file(self.filename, force=True)
self.recurse_dicom_tree(ds, parentItem)
self.model = model

def init_tree(self):
self.tree = QTreeView()
self.tree.setModel(self.model)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.tree)
self.setLayout(mainLayout)
self.tree.setAlternatingRowColors(True)
[self.tree.resizeColumnToContents(x) for x in range(5)]

def recurse_dicom_tree(self, ds, parent, name=None):
for _, data_element in enumerate(ds):
# If this is non-sequence element, add directly to parent
# print('aa', data_element, 'bb')
if not (data_element.VR == 'SQ'):
self.add_item_to_tree(data_element, parent)
else:
# Create the parent sequence in tree
seq_parent = self.add_item_to_tree(data_element, parent)
# For each item in sequence create a child
for i, seq_ds in enumerate(data_element.value):
# break
seq_item_description = data_element.name.replace(
" Sequence", "")
name = "%s %d" % (seq_item_description, i+1)
seq_item = self.add_item_to_tree(seq_ds, seq_parent, name)
# Append the contents of each sequence item as a grandchild
self.recurse_dicom_tree(seq_ds, seq_item, name)
return parent

def add_item_to_tree(self, data_element, parent, element_name=None):
if element_name:
cols = [element_name, '', '', '', '']
else:
value = '' if data_element.VR == 'SQ' else data_element.value
if (data_element.name == 'Pixel Data'):
value = 'Array of ' + str(len(data_element.value)) + ' bytes'
cols = [data_element.name, str(value), str(data_element.tag), str(
data_element.VM), str(data_element.VR)]
parent.appendRow([QStandardItem(c) for c in cols])
last_parent = parent.child(parent.rowCount()-1)

return last_parent


def main():
app = QApplication(sys.argv)
filename = sys.argv[1]
dicomtree = DicomTree(filename)
sys.exit(app.exec_())


if __name__ == "__main__":
main()
# s to command line arguments
# import sys


# class DicomTree(object):

# def __init__(self, filename):
# self.filename = filename

# def show_tree(self):
# ds = self.dicom_to_dataset(self.filename)
# dic = self.dataset_to_dic(ds)
# # model = self.dic_to_model(dic)
# # self.display(model)

# def dicom_to_dataset(self, filename):
# dataset = pydicom.dcmread(filename, force=True, stop_before_pixels=True)
# return dataset

# def dataset_to_dic(self, dataset):
# dic = collections.OrderedDict()
# for data_element in dataset:
# dic[data_element.name] = data_element.value
# return dic

# if __name__ == '__main__':
# path1 = "/Users/bhklab/Documents/GitHub/NBIA-toolkit/sandbox/P_00038_LEFT_CC.dcm/96009/63992/91294.dcm"
# # dt = DicomTree(path1)
# app = QApplication(sys.argv)

# window = QPushButton("Push Me")
# window.show()

# app.exec_()

0 comments on commit 18b6625

Please sign in to comment.