comparison Framework/Toolbox/DicomInstanceParameters.cpp @ 1141:7681f3943748

Changed handling of DoseGridScaling: before this commit, rescaleSlope was set to the DoseGridScaling value if rescale* tags weren't present AND in the case of a dose. This caused issues in dose files where all three tags (DoseGridScaling, RescaleSlope and RescaleIntercept) were present, which previously led to the DoseGridScaling tag to be ignored. Now, the rescale* tags are *ignored* in dose files and DoseGridScaling is always taken into account.
author Benjamin Golinvaux <bgo@osimis.io>
date Fri, 08 Nov 2019 14:25:35 +0100
parents 5a18e6a395bc
children acb399643945 c93a6218f0cd
comparison
equal deleted inserted replaced
1123:45df56448b2a 1141:7681f3943748
113 113
114 static const Orthanc::DicomTag DICOM_TAG_DOSE_UNITS(0x3004, 0x0002); 114 static const Orthanc::DicomTag DICOM_TAG_DOSE_UNITS(0x3004, 0x0002);
115 115
116 if (!dicom.LookupStringValue(doseUnits_, DICOM_TAG_DOSE_UNITS, false)) 116 if (!dicom.LookupStringValue(doseUnits_, DICOM_TAG_DOSE_UNITS, false))
117 { 117 {
118 LOG(WARNING) << "Tag DoseUnits (0x3004, 0x0002) is missing in " << sopInstanceUid_; 118 LOG(ERROR) << "Tag DoseUnits (0x3004, 0x0002) is missing in " << sopInstanceUid_;
119 doseUnits_ = ""; 119 doseUnits_ = "";
120 } 120 }
121
122 } 121 }
123 122
124 isColor_ = (imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome1 && 123 isColor_ = (imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome1 &&
125 imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome2); 124 imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome2);
126 125
127 double doseGridScaling;
128
129 if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && 126 if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) &&
130 dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) 127 dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE))
131 { 128 {
132 hasRescale_ = true; 129 if (sopClassUid_ == SopClassUid_RTDose)
133 } 130 {
134 else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) 131 LOG(INFO) << "DOSE HAS Rescale*: rescaleIntercept_ = " << rescaleIntercept_ << " rescaleSlope_ = " << rescaleSlope_;
135 { 132 // WE SHOULD NOT TAKE THE RESCALE VALUE INTO ACCOUNT IN THE CASE OF DOSES
136 hasRescale_ = true; 133 hasRescale_ = false;
137 rescaleIntercept_ = 0; 134 }
138 rescaleSlope_ = doseGridScaling; 135 else
136 {
137 hasRescale_ = true;
138 }
139
139 } 140 }
140 else 141 else
141 { 142 {
142 hasRescale_ = false; 143 hasRescale_ = false;
144 }
145
146 if (dicom.ParseDouble(doseGridScaling_, Orthanc::DICOM_TAG_DOSE_GRID_SCALING))
147 {
148 if (sopClassUid_ == SopClassUid_RTDose)
149 {
150 LOG(INFO) << "DOSE HAS DoseGridScaling: doseGridScaling_ = " << doseGridScaling_;
151 }
152 }
153 else
154 {
155 doseGridScaling_ = 1.0;
156 if (sopClassUid_ == SopClassUid_RTDose)
157 {
158 LOG(ERROR) << "Tag DoseGridScaling (0x3004, 0x000e) is missing in " << sopInstanceUid_ << " doseGridScaling_ will be set to 1.0";
159 }
143 } 160 }
144 161
145 Vector c, w; 162 Vector c, w;
146 if (LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && 163 if (LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) &&
147 LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && 164 LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) &&
153 defaultWindowingWidth_ = static_cast<float>(w[0]); 170 defaultWindowingWidth_ = static_cast<float>(w[0]);
154 } 171 }
155 else 172 else
156 { 173 {
157 hasDefaultWindowing_ = false; 174 hasDefaultWindowing_ = false;
175 defaultWindowingCenter_ = 0;
176 defaultWindowingWidth_ = 0;
158 } 177 }
159 178
160 if (sopClassUid_ == SopClassUid_RTDose) 179 if (sopClassUid_ == SopClassUid_RTDose)
161 { 180 {
162 switch (imageInformation_.GetBitsStored()) 181 switch (imageInformation_.GetBitsStored())
243 return (CoordinateSystem3D::ComputeDistance(distance, tmp, plane) && 262 return (CoordinateSystem3D::ComputeDistance(distance, tmp, plane) &&
244 distance <= thickness_ / 2.0); 263 distance <= thickness_ / 2.0);
245 } 264 }
246 265
247 266
248 void DicomInstanceParameters::Data::ApplyRescale(Orthanc::ImageAccessor& image, 267 void DicomInstanceParameters::Data::ApplyRescaleAndDoseScaling(Orthanc::ImageAccessor& image,
249 bool useDouble) const 268 bool useDouble) const
250 { 269 {
251 if (image.GetFormat() != Orthanc::PixelFormat_Float32) 270 if (image.GetFormat() != Orthanc::PixelFormat_Float32)
252 { 271 {
253 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); 272 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
254 } 273 }
255 274
275 double factor = doseGridScaling_;
276 double offset = 0.0;
277
256 if (hasRescale_) 278 if (hasRescale_)
279 {
280 factor *= rescaleSlope_;
281 offset = rescaleIntercept_;
282 }
283
284 if ( (factor != 1.0) || (offset != 0.0) )
257 { 285 {
258 const unsigned int width = image.GetWidth(); 286 const unsigned int width = image.GetWidth();
259 const unsigned int height = image.GetHeight(); 287 const unsigned int height = image.GetHeight();
260 288
261 for (unsigned int y = 0; y < height; y++) 289 for (unsigned int y = 0; y < height; y++)
266 { 294 {
267 // Slower, accurate implementation using double 295 // Slower, accurate implementation using double
268 for (unsigned int x = 0; x < width; x++, p++) 296 for (unsigned int x = 0; x < width; x++, p++)
269 { 297 {
270 double value = static_cast<double>(*p); 298 double value = static_cast<double>(*p);
271 *p = static_cast<float>(value * rescaleSlope_ + rescaleIntercept_); 299 *p = static_cast<float>(value * factor + offset);
272 } 300 }
273 } 301 }
274 else 302 else
275 { 303 {
276 // Fast, approximate implementation using float 304 // Fast, approximate implementation using float
277 for (unsigned int x = 0; x < width; x++, p++) 305 for (unsigned int x = 0; x < width; x++, p++)
278 { 306 {
279 *p = (*p) * static_cast<float>(rescaleSlope_) + static_cast<float>(rescaleIntercept_); 307 *p = (*p) * static_cast<float>(factor) + static_cast<float>(offset);
280 } 308 }
281 } 309 }
282 } 310 }
283 } 311 }
284 } 312 }
346 pixelData.GetHeight(), 374 pixelData.GetHeight(),
347 false)); 375 false));
348 Orthanc::ImageProcessing::Convert(*converted, pixelData); 376 Orthanc::ImageProcessing::Convert(*converted, pixelData);
349 377
350 // Correct rescale slope/intercept if need be 378 // Correct rescale slope/intercept if need be
351 //data_.ApplyRescale(*converted, (pixelData.GetFormat() == Orthanc::PixelFormat_Grayscale32)); 379 //data_.ApplyRescaleAndDoseScaling(*converted, (pixelData.GetFormat() == Orthanc::PixelFormat_Grayscale32));
352 data_.ApplyRescale(*converted, false); 380 data_.ApplyRescaleAndDoseScaling(*converted, false);
353 381
354 return converted.release(); 382 return converted.release();
355 } 383 }
356 384
357 385