w3c / hcls-fhir-rdf

Sketching out an RDF representation for FHIR
38 stars 15 forks source link

DICOM Private Data Elements in DICOM RDF #145

Open grittner-sohard opened 4 months ago

grittner-sohard commented 4 months ago

Private Data Elements in DICOM are defined in https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html

These elements cannot be simply described by their attribute number, it is necessary to decode the Private Creator first. Private Data Elements with the same attribute number could actually belong to different Private Creators and reference completely different data. Typically there is no specification available for Private Data Elements, so the VR must be determined from the data. Either the VR is explicitly mentioned or it falls back to UN (Unknown).

For example data could be encoded like this:

Attribute Tag Attribute Value Description
(0029,0010) private creator 1
(0029,1001) creator 1 data
(0029,0011) private creator 2 on the same odd group, but different elements
(0029,1101) creator 2 data
in an other DICOM object it would be legal to encode it like this with the same meaning: Attribute Tag Attribute Value Description
(0027,0010) private creator 1 on a different odd group now
(0027,1001) creator 1 data
(0029,0010) private creator 2 occupied by other creator now
(0029,1001) creator 2 data

The question is how to encode this in RDF so that the data is searchable?

grittner-sohard commented 3 months ago

The basic idea is that the encoding has to be agnostic to the actual attribute numbers.

One unique encoding is the Private Creator identifier. Looking at the attribute number (group, element) of an entry the following applies: The group of the attribute number is the same to which the private creator is stored and therefore is not fixed. The private creator is only allowed to appear once in the group. The first two digits of the attribute element depend on the attribute number to which the private creator is stored and are not fixed. The last two digits of the attribute element are fixed.

So the attribute number of an entry can be described like this: (gggg,bbXX), where the last two digits XX will be fixed to the specific entry.

The actual identification of the attribute would then be the Private Creator, the two digits XX and the UID of the entity that the attribute is assigned to. If there is no knowledge about the actual entity, then the attribute can be assigned to the SOP Instance (e.g. CT Image etc.). In the following examples the group number was used as a kind of hash, because the private creator can only appear once per group, but can appear in other groups.

A possible encoding might look like this:

urn:oid:{UID-SOP-Instance} dcm:hasPrivateElement {private-creator-id}_{gggg} . {private-creator-id}_{gggg} dcm:hasPrivateCreatorId "Private Creator ID"; dcm:hasElement [ dcm:id "XX" ; dcm:value "some arbitrary value" . ] ; dcm:hasElement [ ... other ids and values ... ] .

Alternatively the {gggg} part could be replaced with a {generated UUID}.

And the blank node for the element could be replaced with an actual IRI, for example:

{private-creator-id}_{gggg} dcm:hasElement urn:oid:2.25.{UUID} . urn:oid:2.25.{UUID} dcm:id "XX" ; dcm:value "some arbitrary value" .

Furthermore one could define a type for the resource of the private creator and its elements:

{private-creator-id}_{gggg} rdf:type xyz:SomePrivateEntry .

Which could be further defined in an ontology:

xyz:SomePrivateEntry rdf:subClassOf dcm:PrivateEntry .

And then one could include additional descriptions of the data elements linked to the private entry. The xyz:SomePrivateEntry class could be linked to another entity (Study, Series) than the SOP Instance as well.

ericprud commented 1 day ago

option: bnode label

design goal: Discourage people from inserting the attribute tag directly into SPARQL queries.

Sample Data

_:0029.0010 dicom:hasPrivateCreatorId extReg:private%20creator%201  .

<X> dicom:extensionElement [
  dicom:extensionLabel _:0029.0010 ;
  dicom:value 7
]

Query Use

SELECT ?val WHERE {
  ?tag dicom:hasPrivateCreatorId extReg:private%20creator%201 .
  ?x dicom:extensionElement [ dicom:extensionLabel ?tag ; dicom:value ?value ]
}

cost: