62 : options_(options) {}
97 for (
const auto& finding : result.
findings) {
123 if (modality !=
"PT")
return false;
160 std::vector<validation_finding>& findings)
const {
173 std::vector<validation_finding>& findings)
const {
192 std::vector<validation_finding>& findings)
const {
211 std::vector<validation_finding>& findings)
const {
223 if (units !=
"CNTS" && units !=
"BQML" && units !=
"GML" &&
224 units !=
"PROPCNTS" && units !=
"NONE") {
228 "Unusual Units value for PET: " + units +
229 " (expected CNTS, BQML, or GML)",
239 if (series_type.find(
'\\') == std::string::npos) {
243 "SeriesType should contain backslash separator (e.g., STATIC\\IMAGE)",
252 std::vector<validation_finding>& findings)
const {
257 "FrameOfReferenceUID", findings);
263 "PositionReferenceIndicator", findings);
269 std::vector<validation_finding>& findings)
const {
275 "FrameReferenceTime", findings);
282 if (units ==
"BQML") {
287 "DecayCorrection is required when Units = BQML",
298 if (decay !=
"NONE" && decay !=
"START" && decay !=
"ADMIN") {
302 "Invalid DecayCorrection value: " + decay +
303 " (expected NONE, START, or ADMIN)",
312 std::vector<validation_finding>& findings)
const {
318 "PhotometricInterpretation", findings);
336 std::vector<validation_finding>& findings)
const {
342 "ImageOrientationPatient", findings);
344 "ImagePositionPatient", findings);
355 std::vector<validation_finding>& findings)
const {
370 "SOPClassUID is not a recognized PET Storage SOP Class: " + sop_class,
383 std::vector<validation_finding>& findings)
const {
388 "RadiopharmaceuticalInformationSequence", findings);
396 if (units ==
"BQML" || units ==
"GML") {
402 "RadionuclideTotalDose recommended for quantitative PET",
410 "RadionuclideHalfLife recommended for quantitative PET",
421 std::vector<validation_finding>& findings)
const {
428 if (units ==
"BQML" || units ==
"GML") {
433 "RescaleSlope recommended for accurate SUV calculation",
440 if (units ==
"BQML") {
445 "DecayFactor recommended for quantitative analysis",
455 std::vector<validation_finding>& findings)
const {
462 "ReconstructionMethod not specified - helps with interpretation",
470 std::vector<validation_finding>& findings)
const {
477 "AttenuationCorrectionMethod not specified",
485 if (units ==
"BQML" || units ==
"GML") {
491 "RandomsCorrectionMethod recommended for quantitative PET",
506 std::string_view
name,
507 std::vector<validation_finding>& findings)
const {
513 std::string(
"Type 1 attribute missing: ") + std::string(
name) +
524 std::string(
"Type 1 attribute has empty value: ") +
535 std::string_view
name,
536 std::vector<validation_finding>& findings)
const {
543 std::string(
"Type 2 attribute missing: ") + std::string(
name) +
552 std::vector<validation_finding>& findings)
const {
559 if (modality !=
"PT") {
563 "Modality must be 'PT' for PET images, found: " + modality,
571 std::vector<validation_finding>& findings)
const {
578 if (bits_allocated && bits_stored) {
579 if (*bits_stored > *bits_allocated) {
583 "BitsStored (" + std::to_string(*bits_stored) +
584 ") exceeds BitsAllocated (" + std::to_string(*bits_allocated) +
")",
591 if (bits_stored && high_bit) {
592 if (*high_bit != *bits_stored - 1) {
596 "HighBit (" + std::to_string(*high_bit) +
597 ") should typically be BitsStored - 1 (" +
598 std::to_string(*bits_stored - 1) +
")",
611 "Unusual photometric interpretation for PET: " + photometric +
612 " (expected MONOCHROME2)",
620 if (samples && *samples != 1) {
624 "PET images should have SamplesPerPixel = 1, found: " +
625 std::to_string(*samples),
auto get_numeric(dicom_tag tag) const -> std::optional< T >
Get the numeric value of an element.
auto contains(dicom_tag tag) const noexcept -> bool
Check if the dataset contains an element with the given tag.
auto get_string(dicom_tag tag, std::string_view default_value="") const -> std::string
Get the string value of an element.
auto to_string() const -> std::string
Convert to string representation.
void validate_general_series_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void check_modality(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_image_plane_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void check_type2_attribute(const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const
void validate_general_study_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_pet_series_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void check_type1_attribute(const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const
void set_options(const pet_validation_options &options)
Set validation options.
void validate_corrections(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
validation_result validate(const core::dicom_dataset &dataset) const
Validate a DICOM dataset against PET IOD.
pet_validation_options options_
void validate_frame_of_reference_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
bool quick_check(const core::dicom_dataset &dataset) const
Quick check if dataset has minimum required attributes.
const pet_validation_options & options() const noexcept
Get the validation options.
void validate_sop_common_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_reconstruction_info(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_image_pixel_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void check_pixel_data_consistency(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_radiopharmaceutical_info(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_suv_parameters(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_pet_image_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
pet_iod_validator()=default
Construct validator with default options.
void validate_patient_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
Compile-time constants for commonly used DICOM tags.
bool is_pet_storage_sop_class(std::string_view uid) noexcept
Check if a SOP Class UID is a PET Storage SOP Class.
bool is_valid_pet_photometric(std::string_view value) noexcept
Check if photometric interpretation is valid for PET.
bool is_valid_pet_dataset(const core::dicom_dataset &dataset)
Quick check if a dataset is a valid PET image.
@ warning
Non-critical - IOD may have issues.
@ info
Informational - suggestion for improvement.
@ error
Critical - IOD is non-compliant.
validation_result validate_pet_iod(const core::dicom_dataset &dataset)
Validate a PET dataset with default options.
PET (Positron Emission Tomography) Image IOD Validator.
Positron Emission Tomography (PET) Image Storage SOP Classes.
Options for PET IOD validation.
bool check_conditional
Check Type 1C/2C (conditionally required) attributes.
bool validate_corrections
Validate attenuation and scatter correction.
bool check_type1
Check Type 1 (required) attributes.
bool validate_pet_specific
Validate PET-specific attributes (SUV, reconstruction, etc.)
bool strict_mode
Strict mode - treat warnings as errors.
bool check_type2
Check Type 2 (required, can be empty) attributes.
bool validate_pixel_data
Validate pixel data consistency (rows, columns, bits)
bool validate_radiopharmaceutical
Validate radiopharmaceutical information.
Result of IOD validation.
std::vector< validation_finding > findings
All findings during validation.
bool is_valid
Overall validation status.