How can I remove or update a private tag using fo-DICOM?

2.3k views Asked by At

I have a lot of DICOM data sets that have a private tag in them that contain information that I do not want to keep in the header. The value for this tag changes for each dataset, so I do not know the value. Here is an example of the PRIVATE CREATOR and the Private Tag I want to be updated or removed.

0033,0010  ---: MITRA OBJECT UTF8 ATTRIBUTES 1.0
0033,1016  ---: Dummy^Data^G^

I want to be able to either completely remove 0033,1016 or update it with a new value. Everything I have tried either does nothing or will add another 0033,1016 tag, creating two 0033,1016 tag. One is the original and one that was added when I tried to update the original.

0033,0010  ---: MITRA OBJECT UTF8 ATTRIBUTES 1.0
0033,1016  ---: Dummy^Data^G^
0033,1016  ---: FOO

If I run the code again, I can update the 0033,1016 that has the value FOO, but I can never change the 0033,1016 tag with the value Dummy^Data^G^.

Following is my code:

string main_path = @"C:\Users\pthalken\Desktop\foo";

DirectoryInfo foo = new DirectoryInfo(main_path);
FileInfo[] dicomFiles = foo.GetFiles();

foreach(FileInfo files in dicomFiles)
{
    DicomFile openedDicom = DicomFile.Open(files.FullName, FileReadOption.ReadAll);

    //getting the private tag that I want to change or remove
    var remove = DicomTag.Parse("0033,1016");
    var test = DicomTag.Parse("0010,0010");

    //this method will work for public tags as expected, but with private tags it will juist add another tag
    //it will not update the orignial tag. If ran again it will change the recently inputted tag but still not touch the original
    openedDicom.Dataset.AddOrUpdate(remove, "FOO");

    //Does not update original tag, will add another 0033,1016 tag with value HOT
    openedDicom.Dataset.AddOrUpdate(new DicomCodeString(openedDicom.Dataset.GetPrivateTag(new DicomTag(0x0033, 0x1016)), "HOT"));

    //Does not update original tag, will add another 0033,1016 tag with value HOT CHEETO
    openedDicom.Dataset.AddOrUpdate(new DicomCodeString(openedDicom.Dataset.GetPrivateTag(remove), "HOT CHEETO"));

    //does not remove the orignial tag
    openedDicom.Dataset.Remove(remove);
    openedDicom.Save(files.FullName);
}
2

There are 2 answers

4
Amit Joshi On

With version 4.0.7 of fo-DICOM, following code does properly remove and update the private tag from the dataset:

string dirPath = @"C:\.....";
string filePath = Path.Combine(dirPath, "Test.dcm");
DicomFile openedDicom = DicomFile.Open(filePath, FileReadOption.ReadAll);

var remove = DicomTag.Parse("0019,0010");
openedDicom.Dataset.Remove(remove);
openedDicom.Save(Path.Combine(dirPath, "Removed.dcm"));

var edit = DicomTag.Parse("0043,0010");
openedDicom.Dataset.AddOrUpdate(edit, "EDITED");
openedDicom.Save(Path.Combine(dirPath, "Edited.dcm"));

I do not have dataset with the private tags you mentioned in question; the tags I used are different but that should not matter.

But, there is a catch. If VR of the private tag is [UN - Unknown], both Remove and AddOrUpdate does not work. It appears that this has something to do with unknown value representation.

I tried to read the value of element whose VR is UN as below:

var read = DicomTag.Parse("0019,1002");
string value = openedDicom.Dataset.GetString(read);

The GetString failed with following exception:

Tag: (0019,1002) not found in dataset

In Visual Studio, if you Quick Watch the openedDicom.Dataset to find the elements with UN VR, you will observe strange results.

It seems that fo-DICOM have an issues reading elements with UN VR.


You said in question:

Everything I have tried either does nothing or will add another 0033,1016 tag, creating two 0033,1016 tag.

It creates new tag because it could not locate existing tag. Check the VR of the newly created tag; I guess it will be something other than UN. That is why, you are able to edit that newly created tag but not the original one.

0
LoCUBUS On

I managed to access private DICOM tags. But I noticed that it is necessary to not only specify the group and element number but also the private creator. Additionally I used a customized private dictionary.

  1. I specified the private tags in the private dictionary.
    Here it makes sense to specify the value representation. The keyword is optional.
    <dictionary creator="UIS_IMAGE_PRESENTATION">
        <tag group="0019" element="xx10" vr="SQ" vm="1" keyword="TechnicalPresentationState">Technical Presentation State</tag>
        <tag group="0019" element="xx20" vr="CS" vm="1" keyword="UISExportMode">UIS Export Mode</tag>
        <tag group="0019" element="xx41" vr="CS" vm="1" keyword="PreHorizontalFlip">Pre Horizontal Flip</tag>
        <tag group="0019" element="xx42" vr="DS" vm="1" keyword="PreRotationAngle">Pre Rotation Angle</tag>
        <tag group="0019" element="xx43" vr="CS" vm="1" keyword="CPStepHorizontalFlip">CP Step Horizontal Flip</tag>
        <tag group="0019" element="xx44" vr="CS" vm="1" keyword="CPStepVerticalFlip">CP Step Vertical Flip</tag>
        <tag group="0019" element="xx45" vr="DS" vm="1" keyword="CPStepRotationAngle">CP Step Rotation Angle</tag>
    </dictionary>
  1. To acces the tags I created a new instance of DicomTag
private DicomTag Dicom_Private_UisImagePresentation_PreHorizontalFlip { get; set; }
public string Dicom_Private_UisImagePresentation_PreHorizontalFlip_value { get; set; }
...
Dicom_Private_UisImagePresentation_PreHorizontalFlip = new DicomTag(0x0019, 0x1041, "UIS_IMAGE_PRESENTATION");
  1. To get the value I used the GetSingleValue<string> method.
Dicom_Private_UisImagePresentation_PreHorizontalFlip_value = DicomFile.Dataset.GetSingleValue<string>(Dicom_Private_UisImagePresentation_PreHorizontalFlip);

To handle VR="UN" is a little tricky. Therefore you need to know what was put into the tag. I recommend to check, if there is a better VR which could be used instead of "UN".