Generating a SOPInstanceUID

Hi All,

I’m in the middle of a project where I’ve DICOM exported an RTPlan file from Eclipse, made some modifications to the plan parameters (e.g. gantry angles) and would like to import back into Eclipse.

As expected when trying to import the plan in again, Eclipse notices a duplication due to the modified plan having the same SOPInstanceUID.

So I’m looking for advice on the best way to change the SOPInstanceUID of the modified RTPlan, but still have Eclipse know which CT and structure set to link the plan to.

Apologies of this is a very simple solution, I’m still finding my feet in the DICOM world

Hi @poderj,

Certainly more than happy to help. @Darcy_Mason’s library pydicom is key for something like this. Also @sjswerdloff is quite the DICOM guru, so he might want to chime in for some pointers.

In any DICOM file UID changing you want to make sure to update that specific SOPInstanceUID, but then you also want to make sure to update all corresponding ReferencedSOPInstanceUID within the other DICOM files that point to the one you’re updating.

Here’s an example for changing the SOPInstanceUID for the following file:

rtplan.dcm (227.1 KB)

Download that file and save it in a directory on your machine and then run the following Python code in the same directory:

$ ipython
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import pydicom

In [2]: ds = pydicom.dcmread('rtplan.dcm', force=True)

In [3]: ds.SOPInstanceUID
Out[3]: '2.16.840.1.114337.1.1.1548043901.0'

In [4]: new_uid = pydicom.uid.generate_uid()

In [5]: new_uid
Out[5]: '1.2.826.0.1.3680043.8.498.20196977846728432314047549921909610688'

In [6]: ds.SOPInstanceUID = new_uid

In [7]: ds.SOPInstanceUID
Out[7]: '1.2.826.0.1.3680043.8.498.20196977846728432314047549921909610688'

In [8]: ds.save_as('new_uid.dcm')

That new UID you created is now saved in the variable new_uid. You can then use that to update the respective ReferencedSOPInstanceUID within the other DICOM files that reference it.

Hope that helps :slight_smile:
Cheers,
Simon

For this situation, where you have an existing set of references that legitimately should continue to point to the original plan, you are fine with just updating the SOP Instance UID of the RT Plan that you have hand modified. If you have a “set of data” that you are trying to “convert” and maintain relationships (e.g. pseudonymisation), then you need to update the references.

However… the system you are trying to import it back in to may have additional restrictions. It might not allow multiple RT Plans with the same Series Instance UID (but that should become evident pretty quickly if it has that restriction). Technically, because your modification is not the same application you really should not use the same Series Instance UID, because that implies the objects came from the same system that created the Series.
If the original RT Plan encodes creation or instance dates/times, you should either update those to “now” or whenever you did the modifications.

Perhaps more important is eliminating references to RT Dose objects.
If there is a Referenced RT Dose Sequence, you need to be careful with that. The reference is no longer valid and it’s dangerous to point to a dose that doesn’t represent your plan. You should delete it.
In the control point sequence there is the Referenced Dose Sequence as well as the Referenced Dose Reference Sequence (yeah, a bit confusing).
The Referenced Dose Sequence, if there, is no longer valid.
But the Referenced Dose Reference Sequence might be, as long as it isn’t pointing to a UID.
To be safe, I’d delete it, but it is pointing back in to the Dose Reference Sequence (note, doesn’t start with the word Reference… sigh…), so you will want to look through that and see if it’s just pointing to prescriptive data (i.e. no UID present).

You might also want to alter the
RT Plan Name
RT Plan Label
RT Plan Description
RT Plan Date
RT Plan Time

Also, to be polite, and make it relatively easy to track where things came from, you might want to put
the original RT Plan SOP Instance UID in the Referenced RT Plan Sequence → Referenced SOP Instance UID, and use PREDECESSOR for the RT Plan Relationship attribute.

See RT General Plan Module – DICOM Standard Browser for some useful reference information from the DICOM Standard (or get the standard itself, but I like innolitics for the convenience in browsing).

The modified RT Plan will still point to the same structures. (RT Structure Set), via the Referenced RT Structure Set sequence → SOP Instance UID, assuming you aren’t losing anything while modifying the plan. That RT Structure Set has the references to the CT.
You might want to inspect your modified plan to see if it is referencing the CT directly through some kind of “Referenced Image” sequence, but even so, you want that to stay the same for your use case.

The code involved isn’t much different than what @SimonBiggs has shown, but digging in to sequences or eliminating them is a bit more effort. pydicom has examples of that, and there are examples of this in pymedphys (I’m sure in many places, but certainly in the anonymisation code and in the pseudonymisation code).

P.S. Everyone has to start somewhere. There is a lot to DICOM, and it can take a fair amount of time to become proficient. Your use case is not uncommon, certainly not for creating sets of test data in non-clinical test environments. The solution/approach you are taking is quite common, but be very careful about utilising it in a clinical environment.