Repository: comic/grand-challenge.org

Issue:
Feature request: adding Pixel Spacing and Photometric Interpretation as optional DICOM/MHA headers
**Is your feature request related to a problem? Please describe.**
Some time ago, I created an issue for preserving the (Imager) Pixel Spacing attribute in a DICOM file (x-ray) uploaded to Grand Challenge (https://github.com/comic/grand-challenge.org/issues/1216). Pixel spacing is the distance between adjacent pixels in the patient, whereas imager pixel spacing is the distance between adjacent pixels on the sensor. I use the pixel spacing information to resize images that are put into my deep learning algorithm. After realizing that the pixel spacing could still be accessed in the output MHA file using the GetSpacing function from the SimpleITK Python library, I closed the issue. However, I found that in quite some cases the pixel spacing does not match the imager pixel spacing, and GetSpacing only returns the imager pixel spacing. Since the Pixel Spacing attribute accounts for corrections or calibrations, I prefer this attribute over the Imager Pixel Spacing attribute (if available).

Besides the Pixel Spacing attribute, I use the Photometric Interpretation attribute to modify pixel intensity values. If the photometric interpretation is MONOCHROME1 (minimum pixel value should be displayed as white), then the pixel intensities need to be inverted. I saw that this attribute is not in the list of additional DICOM headers that are preserved by Grand Challenge, so I assume that this attribute will be lost after uploading the DICOM file.  

**Describe the solution you'd like**
If possible, I would like that the Pixel Spacing attribute (tag: 0028,0030) and Photometric Interpretation attribute (tag: 0028,0004) are added as additional headers to the output MHA file.

**Describe alternatives you've considered**
I have considered using the Imager Pixel Spacing attribute only and instructing users to upload MONOCHROME2 DICOM files.



Discussion:
Do you want to have a go at implementing this? See this PR for an example of how to add a tag: https://github.com/comic/grand-challenge.org/pull/1298
The only thing to be careful of is the data type, see here for another example https://github.com/comic/grand-challenge.org/pull/1399/
Hi James, thanks for your quick reply, sure! I am going to have a look at the examples and try to add the tags myself. 

Resolving patch:
diff --git a/app/grandchallenge/cases/image_builders/dicom.py b/app/grandchallenge/cases/image_builders/dicom.py
--- a/app/grandchallenge/cases/image_builders/dicom.py
+++ b/app/grandchallenge/cases/image_builders/dicom.py
@@ -27,6 +27,9 @@
 
 OPTIONAL_METADATA_FIELDS = (
     # These fields will be included in the output mha file
+    "PhotometricInterpretation",
+    "ImagerPixelSpacing",
+    "PixelSpacing",
     "Laterality",
     "PatientID",
     "PatientName",
diff --git a/app/grandchallenge/cases/image_builders/metaio_utils.py b/app/grandchallenge/cases/image_builders/metaio_utils.py
--- a/app/grandchallenge/cases/image_builders/metaio_utils.py
+++ b/app/grandchallenge/cases/image_builders/metaio_utils.py
@@ -55,7 +55,14 @@
 
 STUDYDATE_MATCH_REGEXP: Pattern = re.compile(r"^\d{4}\d{1,2}\d{1,2}$")
 
+PIXELSPACING_MATCH_REGEXP: Pattern = re.compile(
+    r"^[-+]?\d*\.?\d+([eE][-+]?\d+)?\\[-+]?\d*\.?\d+([eE][-+]?\d+)?$"
+)
+
 ADDITIONAL_HEADERS: Dict[str, Pattern] = {
+    "PhotometricInterpretation": LENGTH_LIMIT_MATCH_REGEXP,
+    "ImagerPixelSpacing": PIXELSPACING_MATCH_REGEXP,
+    "PixelSpacing": PIXELSPACING_MATCH_REGEXP,
     "Laterality": LENGTH_LIMIT_MATCH_REGEXP,
     "PatientID": LENGTH_LIMIT_MATCH_REGEXP,
     "PatientName": LENGTH_LIMIT_MATCH_REGEXP,


Test patch:
diff --git a/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd b/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
@@ -31,6 +31,9 @@ StudyDate = 20020304
 StudyInstanceUID = 1.2.3.4
 SeriesInstanceUID = 1.2.3.4
 Laterality = L
+PhotometricInterpretation = MONOCHROME2
+ImagerPixelSpacing = 0.144\0.144
+PixelSpacing = 0.144\0.144
 
 
 
diff --git a/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd b/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
@@ -25,6 +25,9 @@ PatientBirthDate = 20200101
 PatientAge = 001Y
 PatientSex = M
 Laterality = L
+PhotometricInterpretation = MONOCHROME2
+ImagerPixelSpacing = 0.144\0.144
+PixelSpacing = 0.144\0.144
 StudyDescription = super awesome study
 Bogus = nonsense 1234
 WindowCenter = 20
diff --git a/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd b/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
@@ -26,6 +26,9 @@ PatientBirthDate = 20200101
 PatientAge = 001Y
 PatientSex = M
 Laterality = R
+PhotometricInterpretation = MONOCHROME2
+ImagerPixelSpacing = 0.144\0.144
+PixelSpacing = 0.144\0.144
 StudyDescription = super awesome study
 SliceThickness = 2
 WindowCenter = 20.5