encapsulate cda in dicom

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

encapsulate cda in dicom

#1 Post by w.bahadoer »

I'm encapsulating a cda structured file in my dicom file, the file gets uploaded to my DICOM/PACS Orthanc server but how can I verify that the dicom file holds the cda file? I could view an encapsulated pdf document with the Osimis dicom viewer, but how to confirm the cda (xml) file?

Code: Select all

    OFCondition result;

    std::ifstream file("c:\\temp\\cdadocument.xml", std::ios::in | std::ios::binary);
    std::vector< char> data((std::istreambuf_iterator< char>(file)), std::istreambuf_iterator< char>());

    DcmDataset *dataset = new DcmDataset;

    dataset->putAndInsertUint8Array( DCM_EncapsulatedDocument, (uint8_t*)data.data(), data.size());
    dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "text/xml");

    dataset->putAndInsertString(DCM_Manufacturer, "MyCompany");
    dataset->putAndInsertString(DCM_SoftwareVersions, "1.1.0");
    dataset->putAndInsertString(DCM_DeviceID, "DEV-1234");


    dataset->putAndInsertString(DCM_PatientID, "BK123");
    dataset->putAndInsertString(DCM_PatientName, "DOE^JOHN");
    dataset->putAndInsertString(DCM_PatientSex, "M" );
    dataset->putAndInsertString(DCM_PatientBirthDate, "19780812");

    dataset->putAndInsertString(DCM_ReferringPhysicianName,"Dr Who");

//    dataset->putAndInsertString(DCM_Modality, "DOC");
//    dataset->putAndInsertString(DCM_ConversionType,"WSD");

    dataset->putAndInsertString(DCM_RequestedProcedureDescription, "Some procedure" );
    dataset->putAndInsertString(DCM_StudyDescription, "Some study" );
    dataset->putAndInsertString(DCM_StudyID, "001");
    dataset->putAndInsertString(DCM_StudyDate, "20200206" );
    dataset->putAndInsertString(DCM_StudyTime, "120211.345");
    dataset->putAndInsertString(DCM_StudyInstanceUID,  "1.3.6.1" );
    dataset->putAndInsertString(DCM_SeriesInstanceUID, "1.3.6.1.2" );
    dataset->putAndInsertString(DCM_InstanceNumber,    "1.3.6.1.1.1" );
    dataset->putAndInsertString(DCM_Status, "1");

    char uid[100];

    dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedCDAStorage);
    dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));

    T_ASC_Network* net;

    OFCondition cond = ASC_initializeNetwork ( NET_REQUESTOR, 0, 30, &net );

	......

    // list of transfer syntaxes, only a single entry here
    const char* ts[] = { UID_LittleEndianExplicitTransferSyntax };

    cond = ASC_addPresentationContext(params, 1, UID_LittleEndianExplicitTransferSyntax, ts, 1);

    T_ASC_Association *assoc;

    if( !ASC_requestAssociation(net, params, &assoc).good())
        return;

    DcmStorageSCU storageServer;
    storageServer.setAETitle( callingAPTitle );
    storageServer.setPeerHostName( DStorageServer );
    storageServer.setPeerPort( DStorageServerPort );
    storageServer.setPeerAETitle( calledAPTitle );
    storageServer.addDataset( dataset );

    OFList<OFString> pts;
    pts.push_back(UID_LittleEndianExplicitTransferSyntax);
    storageServer.addPresentationContext( UID_EncapsulatedCDAStorage, pts);

    if( !storageServer.isConnected())
        if( storageServer.initNetwork() != EC_Normal )
            return;

    if( storageServer.negotiateAssociation() != EC_Normal )
        return;


    T_ASC_PresentationContextID presID = storageServer.findPresentationContextID(UID_EncapsulatedCDAStorage, UID_LittleEndianExplicitTransferSyntax);

    OFFilename fileformat;
    Uint16 status;

    cond = storageServer.sendSTORERequest( presID, fileformat, dataset, status );
edit : the dicom file does not contain the cda file because the dicom file is 1 kb while the cda file is 2 kb :(

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#2 Post by w.bahadoer »

Based on J.Reismeier's comment and the link he supplied Encapsulated CDA IOD I have added all the mandatory dicom attributes ( by my best knowledge ) but still the dicom object is 1 kb. I can encapsulate a pdf though but not a CDA file. These where the missing tags

Code: Select all

    dataset->putAndInsertString(DCM_AcquisitionDateTime, "" );
    dataset->putAndInsertString(DCM_BurnedInAnnotation, "NO");

    dataset->putAndInsertString(DCM_CodingSchemeDesignator, "DCM");
    dataset->putAndInsertString(DCM_CodingSchemeURLType, "DOC");
    dataset->putAndInsertString(DCM_CodingSchemeURL, "DCM");

J. Riesmeier
DCMTK Developer
Posts: 2512
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: encapsulate cda in dicom

#3 Post by J. Riesmeier »

What does the textual dump of your Encapsulated CDA DICOM object look like?

By the way, DICOM attributes such as Coding Scheme Designator or Coding Scheme URL Type are certainly not present on the main dataset level (but nested in a Sequence of Items).

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#4 Post by w.bahadoer »

J.Reismeier,

Code: Select all

c:\Development\dcmtk\build\bin>dcmdump.exe +f c:\temp\test.dcm

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 182                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI =EncapsulatedCDAStorage                  #  30, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.276.0.7230010.3.1.4.3741632033.6840.1583739524.521] #  54, 1 MediaStorageSOPInstanceUID
(0002,0010) UI (no value available)                     #   0, 0 TransferSyntaxUID
(0002,0012) UI [1.2.276.0.7230010.3.0.3.6.5]            #  28, 1 ImplementationClassUID
(0002,0013) SH [OFFIS_DCMTK_365]                        #  16, 1 ImplementationVersionName

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Explicit

c:\Development\dcmtk\build\bin>
and the 2kb .cda file that I got from the net as an example

Code: Select all

<ClinicalDocument xmlns="urn:hl7-org:v3" xmlns:voc="urn:hl7-org:v3/voc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" templateId="2.16.840.1.113883.3.27.1776">
<!--
 
********************************************************
  CDA Header
********************************************************
-->
<id extension="c266" root="2.16.840.1.113883.3.933"/>
<code code="11488-4" codeSystem="2.16.840.1.113883.6.1" displayName="Consultation note"/>
<title>Good Health Clinic Consultation Note</title>
<effectiveTime value="20000407"/>
<confidentialityCode code="N" codeSystem="2.16.840.1.113883.5.25"/>
<setId extension="BB35" root="2.16.840.1.113883.3.933"/>
<versionNumber value="2"/>
<legalAuthenticator>
<time value="20000408"/>
<signatureCode code="S"/>
<assignedEntity>
<id extension="KP00017" root="2.16.840.1.113883.3.933"/>
<assignedPerson>
<name>
<given>Robert</given>
<family>Dolin</family>
<suffix>MD</suffix>
</name>
</assignedPerson>
<representedOrganization>
<id extension="M345" root="2.16.840.1.113883.3.933"/>
</representedOrganization>
</assignedEntity>
</legalAuthenticator>
<author>
<time value="20000407"/>
<assignedAuthor>
<id extension="KP00017" root="2.16.840.1.113883.3.933"/>
<assignedPerson>
<name>
<given>Robert</given>
<family>Dolin</family>
<suffix>MD</suffix>
</name>
</assignedPerson>
<representedOrganization>
<id extension="M345" root="2.16.840.1.113883.3.933"/>
</representedOrganization>
</assignedAuthor>
</author>
<custodian>
<assignedCustodian>
<representedCustodianOrganization>
<id extension="M345" root="2.16.840.1.113883.3.933"/>
<name>Good Health Clinic</name>
</representedCustodianOrganization>
</assignedCustodian>
</custodian>
<recordTarget>
<patientRole>
<id extension="12345" root="2.16.840.1.113883.3.933"/>
<patientPatient>
<name>
<given>Henry</given>
<family>Levin</family>
<suffix>the 7th</suffix>
</name>
.........

J. Riesmeier
DCMTK Developer
Posts: 2512
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: encapsulate cda in dicom

#5 Post by J. Riesmeier »

The last three lines of your dump show that the DICOM dataset is empty. How did you create the DICOM file?

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#6 Post by w.bahadoer »

I added my code in the first posting where I created a DcmDataset* in the beginning and the start populating DcmDataset. I save the dataset to a dicom file with this

Code: Select all

    DcmFileFormat _fileformat( dataset );
    E_TransferSyntax writeXfer;
    result = _fileformat.saveFile("c:\\temp\\test.dcm", writeXfer );

    if (result.bad())
      std::cout << "Error: cannot write DICOM file (" << result.text() << ")" << std::endl;

J. Riesmeier
DCMTK Developer
Posts: 2512
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: encapsulate cda in dicom

#7 Post by J. Riesmeier »

What do the various calls to putAndInsertString() return? What is the print() output of your dataset variable?

By the way, what's the purpose of passing an uninitialized instance of E_TransferSyntax to saveFile()?

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#8 Post by w.bahadoer »

J.Reismeier,

thank you very much, it's always good to have somebody else look at the code. I was too focused on the dataset side and adding the correct attributes that I didn't see the uninitialized transfersyntax. It works now

Code: Select all

 DcmFileFormat _fileformat( dataset );
 OFCondition result = _fileformat.saveFile("c:\\temp\\test.dcm", EXS_LittleEndianImplicit  );

Code: Select all

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0000,0900) US 1                                        #   2, 1 Status
(0008,0016) UI =EncapsulatedCDAStorage                  #  30, 1 SOPClassUID
(0008,0018) UI [1.2.276.0.7230010.3.1.4.3741632033.5756.1583759284.176] #  54, 1 SOPInstanceUID
(0008,0020) DA [20200206]                               #   8, 1 StudyDate
(0008,0023) DA [20200111]                               #   8, 1 ContentDate
(0008,002a) DT (no value available)                     #   0, 0 AcquisitionDateTime
(0008,0030) TM [120211.345]                             #  10, 1 StudyTime
(0008,0033) TM [100301.345]                             #  10, 1 ContentTime
(0008,0060) CS [DOC]                                    #   4, 1 Modality
(0008,0064) CS [SD]                                     #   2, 1 ConversionType
(0008,0070) LO [Cassini Technologies]                   #  20, 1 Manufacturer
(0008,0090) PN [Dr Who]                                 #   6, 1 ReferringPhysicianName
(0008,0102) SH [DCM]                                    #   4, 1 CodingSchemeDesignator
(0008,010a) CS [DOC]                                    #   4, 1 CodingSchemeURLType
(0008,010e) UR [DCM]                                    #   4, 1 CodingSchemeURL
(0008,1030) LO [Cassini Corneal Topograpy]              #  26, 1 StudyDescription
(0010,0010) PN [DOE^JOHN]                               #   8, 1 PatientName
(0010,0020) LO [BK666]                                  #   6, 1 PatientID
(0010,0030) DA [19740812]                               #   8, 1 PatientBirthDate
(0010,0040) CS [M]                                      #   2, 1 PatientSex
(0018,1003) LO [CA3013]                                 #   6, 1 DeviceID
(0018,1020) LO [3.2.0]                                  #   6, 1 SoftwareVersions
(0020,000d) UI [1.3.6.1]                                #   8, 1 StudyInstanceUID
(0020,000e) UI [1.3.6.1.2]                              #  10, 1 SeriesInstanceUID
(0020,0010) SH [001]                                    #   4, 1 StudyID
(0020,0013) IS [1.3.6.1.1.1]                            #  12, 1 InstanceNumber
(0028,0301) CS [NO]                                     #   2, 1 BurnedInAnnotation
(0032,1060) LO [Anterior Topography]                    #  20, 1 RequestedProcedureDescription
(0042,0011) OB 3c\43\6c\69\6e\69\63\61\6c\44\6f\63\75\6d\65\6e\74\20\78\6d\6c\6e... # 39208, 1 EncapsulatedDocument
(0042,0012) LO [text/xml]                               #   8, 1 MIMETypeOfEncapsulatedDocument
by the way all other calls to putAndInsertString() return OK, but you mentioned that DICOM attributes such as Coding Scheme Designator or Coding Scheme URL Type are not present on the main dataset level (but nested in a Sequence of Items). I didn't get that from the Encapsulated CDA IOD document .... or did I miss something again? :(

J. Riesmeier
DCMTK Developer
Posts: 2512
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: encapsulate cda in dicom

#9 Post by J. Riesmeier »

but you mentioned that DICOM attributes such as Coding Scheme Designator or Coding Scheme URL Type are not present on the main dataset level (but nested in a Sequence of Items). I didn't get that from the Encapsulated CDA IOD document .... or did I miss something again? :(
Counter question: Where did you read that these attributes should be present?

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#10 Post by w.bahadoer »

In the link you provided earlier, I clicked on the "Encapsulated Document - SOP Common C12.1 " link which lead me to http://dicom.nema.org/medical/dicom/cur ... ect_C.12.1 and there I see that these attributes are of type 1 and those are mandatory, right??

J. Riesmeier
DCMTK Developer
Posts: 2512
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: encapsulate cda in dicom

#11 Post by J. Riesmeier »

They are mandatory but only if the surrounding sequence element is present (which is not the case in your dataset). The notation of Sequence of Items attributes is described here: http://dicom.nema.org/medical/dicom/cur ... t_5.2.html

w.bahadoer
Posts: 27
Joined: Mon, 2020-01-20, 11:36

Re: encapsulate cda in dicom

#12 Post by w.bahadoer »

Thank you very much for the info....greatly appreciated :)

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 0 guests