Editing arbitrary nested DICOM tags

91 views
Skip to first unread message

Alan Chamberlain

unread,
Oct 24, 2023, 8:13:14 AM10/24/23
to pydicom
Hi

I am trying to edit nested DICOM tags in an RDSR file in python using pydicom. I have a Treeview of the RDSR file from which I can select the tag. I can get the path to the tag as a string by traversing the parents of the tree nodes. I can get the value of the tag by doing something like

path_to_tag = ''ds.ReferencedRequestSequence[0].RequestedProcedureDescription'
tag_value = eval(path_to_tag)

but apart from the security concerns of using eval it doesn't work the other way around to set the tag value.

I have tried using getattr and setattr iteratively on the string as below

def get_dot_attr(obj, att_name)->str:
path = att_name.split('.')
for part in path:
obj = getattr(obj, part)
return obj

but it fails on the sequence lists. I can probably programmatically handle the list in the above function but it feels like a bit of a kludge.

Have I missed something and is there an easier way of changing these nested tags?

Regards
Alan

Darcy Mason

unread,
Oct 24, 2023, 10:56:28 AM10/24/23
to pydicom
I don't know which Treeview library is being used, but they usually have a unique id for each node.  If you are adding the nodes with Python code, you could keep a dictionary mapping the tree node id to the pydicom object.  Even better, if the Treeview class lets you store extra information in the node, you could set a reference to the pydicom object.

If those are not possible, then looking at your code the one thing that comes to mind is that you would have to also split the square brackets out of the sequence parts.  Use the getattr for just the sequence name, and then use `operator.itemgetter(seq, i)` on the int i of the number inside.

Alan Chamberlain

unread,
Oct 25, 2023, 7:35:46 AM10/25/23
to pydicom
Thanks Darcy

I'm using a QTreeview so, yes I can map the nodes to the pydicom objects. This is probably the way to go in the long run, but it requires some under the hood changes which will take some time.

In the meantime I was thinking along the same lines as splitting out the number. What I came up with was:
def get_dot_attr(obj, att_name) -> str:

     path = att_name.split('.')
     for part in path:
         parts = part.split('[')
         if len(parts) > 1:
         sequence_str = parts[0]
         sequence_num = int(parts[1].replace(']', ""))
         sequence = getattr(obj, sequence_str)
         obj = sequence[sequence_num]
     else:

         obj = getattr(obj, part)
return obj

Thanks for your assistance.

Regards
Alan

Alan Chamberlain

unread,
Oct 25, 2023, 8:45:32 AM10/25/23
to pydicom
Just for completeness here is the sister function
def set_dot_attr(obj, att_name, value):

     path = att_name.split('.')
     tag_name = path[-1]
     del(path[-1])

     for part in path:
         parts = part.split('[')
         if len(parts) > 1:
         sequence_str = parts[0]
         sequence_num = int(parts[1].replace(']', ""))
         sequence = getattr(obj, sequence_str)
         obj = sequence[sequence_num]
     else:
         obj = getattr(obj, part)
     setattr(obj, tag_name, value)
     return
Reply all
Reply to author
Forward
0 new messages