⚠️ Este é um site de tradução não oficial, sem relação com o DCMTK / OFFIS. Para informações oficiais, consulte a página original (https://support.dcmtk.org/docs/mod_dcmsr.html).

dcmsr: uma biblioteca de relatórios estruturados e aplicativos utilitários

Este módulo contém classes para ler, escrever, criar, modificar, acessar, imprimir e renderizar documentos DICOM de relatório estruturado (SR). A lista de classes SOP com suporte é fornecida em DSRTypes::E_DocumentType.

As principais classes de interface são:

Aqui estão mais algumas classes úteis para implementar templates SR:

Atualmente, os seguintes templates SR estão implementados (consulte as notas para mais detalhes):

Ferramentas

Este módulo contém as seguintes ferramentas de linha de comando:

Exemplos

O exemplo a seguir mostra como carregar um relatório estruturado DICOM e renderizar seu conteúdo em formato HTML:

DcmFileFormat fileformat;

OFCondition status = fileformat.loadFile("test.dcm");

if (status.good())

{

DSRDocument document;

status = document.read(*fileformat.getDataset());

if (status.good())

{

status = document.renderHTML(cout);

if (status.bad())

cerr << "Error: cannot render SR document (" << status.text() << ")" << endl;

} else

cerr << "Error: cannot read SR document (" << status.text() << ")" << endl;

} else

cerr << "Error: cannot load DICOM file (" << status.text() << ")" << endl;

O exemplo a seguir mostra como criar um relatório estruturado DICOM e salvá-lo em um arquivo (mais detalhes podem ser encontrados no arquivo-fonte mkreport):

DSRDocument document;

document.setPatientName("Doe^John");

/ ... /

DSRDocumentTree &tree = document.getTree();

tree.addContentItem(DSRTypes::RT_isRoot, DSRTypes::VT_Container);

tree.getCurrentContentItem().setConceptName(DSRCodedEntryValue(/ some code /));

tree.addChildContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_Code, CODE_DCM_ObserverType);

tree.getCurrentContentItem().setCodeValue(CODE_DCM_Person);

/ ... /

DcmFileFormat fileformat;

OFCondition status = document.write(*fileformat.getDataset())

if (status.good())

{

status = fileformat.saveFile("test.dcm", EXS_LittleEndianExplicit);

if (status.bad())

cerr << "Error: cannot save DICOM file (" << status.text() << ")" << endl;

} else

cerr << "Error: cannot write SR document (" << status.text() << ")" << endl;

Como alternativa, muitas propriedades da árvore do documento podem ser acessadas e modificadas diretamente, como mostra o exemplo a seguir:

DSRDocument document(DSRTypes::DT_KeyObjectSelectionDocument);

/ ... /

DSRDocumentTree &tree = document.getTree();

tree.addContentItem(DSRTypes::RT_isRoot, DSRTypes::VT_Container);

DSRCodedEntryValue *codePtr = tree.getCurrentContentItem().getConceptNamePtr();

if (codePtr != NULL)

codePtr->setCode("113000", "DCM", "Of Interest");

/ ... /

tree.addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Image);

DSRImageReferenceValue *imagePtr = tree.getCurrentContentItem().getImageReferencePtr();

if (imagePtr != NULL)

{

imagePtr->setValue(DSRImageReferenceValue(UID_UltrasoundMultiframeImageStorage, / image UID /));

imagePtr->setPresentationState(DSRCompositeReferenceValue(UID_GrayscaleSoftcopyPresentationStateStorage, / GSPS UID /));

imagePtr->getFrameList().addItem(2);

imagePtr->getFrameList().addItem(5);

}

/ ... /

Além disso, existem métodos específicos DSRDocumentTree::addContentItem() e DSRDocumentTree::addChildContentItem() que esperam um ponteiro para uma instância recém-criada de DSRDocumentTreeNode.

Percorrer uma árvore de documento e buscar itens de conteúdo que atendam a determinados critérios pode ser feito de várias maneiras. Aqui estão duas delas:

DSRDocument document;

/ ... /

DSRDocumentTree &tree = document.getTree();

/ #1: search for content items with a certain concept name /

if (tree.gotoNamedNode(CODE_DCM_ProcedureReported))

{

do {

const DSRDocumentTreeNode *node = tree.getNode();

/ and check for expected value type /

if ((node != NULL) && (node->getValueType() == DSRTypes::VT_Code))

{

/ do something useful with the CODE content item /

}

} while (tree.gotoNextNamedNode(CODE_DCM_ProcedureReported, OFFalse /searchIntoSub/));

}

/ #2: search for content items using a more complex filter /

DSRDocumentTreeNodeAndFilter filter;

filter.addFilter(new DSRDocumentTreeNodeValueTypeFilter(DSRTypes::VT_Code));

filter.addFilter(new DSRDocumentTreeNodeRelationshipTypeFilter(DSRTypes::RT_hasConceptMod));

filter.addFilter(new DSRDocumentTreeNodeHasChildrenFilter());

if (tree.gotoMatchingNode(filter))

{

/ found first "has concept mod CODE" content item that has children /

}

O último exemplo mostra como lidar com templates SR, por exemplo, ao criar um relatório estruturado DICOM baseado no TID 1500 (Measurement Report):

TID1500_MeasurementReport report(CMR_CID7021::ImagingMeasurementReport);

report.setLanguage(CID5000_Language::English);

report.getObservationContext().addPersonObserver("Doe^Jane", "Some Organization");

/ ... /

CMR_TID1411_in_TID1500 &volumetric = report.getVolumetricROIMeasurements();

volumetric.setActivitySession("1");

volumetric.setTrackingIdentifier("aorta reference region");

/ ... /

CMR_TID1419_in_TID1411_in_TID1500 &measurement = volumetric.getMeasurement();

measurement.createNewMeasurement(CMR_CID7469::Volume, CMR_TID1419_in_TID1411_in_TID1500::MeasurementValue("15", CMR_CID7181::CubicMillimeter));

measurement.setDerivation(CMR_CID7464::StandardDeviation);

/ ... /

DSRDocument document;

document.setPatientName("Last Name^First Name");

/ ... /

if (document.setTreeFromRootTemplate(report).good())

document.print(cout, DSRTypes::PF_printTemplateIdentification);

else

cerr << "Error: cannot set template content as document tree" << endl;