PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::services::validation::mg_iod_validator Class Reference

#include <mg_iod_validator.h>

Collaboration diagram for kcenon::pacs::services::validation::mg_iod_validator:
Collaboration graph

Public Member Functions

 mg_iod_validator ()=default
 Construct validator with default options.
 
 mg_iod_validator (const mg_validation_options &options)
 Construct validator with custom options.
 
validation_result validate (const core::dicom_dataset &dataset) const
 Validate a DICOM dataset against Mammography IOD.
 
validation_result validate_for_presentation (const core::dicom_dataset &dataset) const
 Validate a For Presentation mammography dataset.
 
validation_result validate_for_processing (const core::dicom_dataset &dataset) const
 Validate a For Processing mammography dataset.
 
validation_result validate_laterality (const core::dicom_dataset &dataset) const
 Validate breast laterality attribute.
 
validation_result validate_view_position (const core::dicom_dataset &dataset) const
 Validate mammography view position.
 
validation_result validate_compression_force (const core::dicom_dataset &dataset) const
 Validate compression force.
 
bool quick_check (const core::dicom_dataset &dataset) const
 Quick check if dataset has minimum required attributes.
 
const mg_validation_optionsoptions () const noexcept
 Get the validation options.
 
void set_options (const mg_validation_options &options)
 Set validation options.
 

Private Member Functions

void validate_patient_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_general_study_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_general_series_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_mammography_series_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_mammography_image_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_dx_anatomy_imaged_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_dx_detector_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_acquisition_dose_module (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 validate_voi_lut_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_sop_common_module (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void validate_breast_implant_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 check_type2_attribute (const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const
 
void check_modality (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void check_laterality_consistency (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void check_view_position_validity (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 
void check_compression_force_range (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 check_photometric_interpretation (const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
 

Private Attributes

mg_validation_options options_
 

Detailed Description

Definition at line 162 of file mg_iod_validator.h.

Constructor & Destructor Documentation

◆ mg_iod_validator() [1/2]

kcenon::pacs::services::validation::mg_iod_validator::mg_iod_validator ( )
default

◆ mg_iod_validator() [2/2]

kcenon::pacs::services::validation::mg_iod_validator::mg_iod_validator ( const mg_validation_options & options)
explicit

Construct validator with custom options.

Parameters
optionsValidation options

Definition at line 87 of file mg_iod_validator.cpp.

Member Function Documentation

◆ check_compression_force_range()

void kcenon::pacs::services::validation::mg_iod_validator::check_compression_force_range ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 866 of file mg_iod_validator.cpp.

868 {
869
870 if (!dataset.contains(mg_tags::compression_force)) {
871 // Compression force is Type 3 but important for mammography QC
872 findings.push_back({
875 "Compression Force (0018,11A2) is not present. "
876 "This information is valuable for quality control and patient safety.",
877 "MG-INFO-008"
878 });
879 return;
880 }
881
882 auto force = dataset.get_numeric<double>(mg_tags::compression_force);
883 if (!force) {
884 findings.push_back({
887 "Compression Force is present but could not be parsed as a number.",
888 "MG-WARN-012"
889 });
890 return;
891 }
892
893 auto [min_typical, max_typical] = get_typical_compression_force_range();
894
895 if (!is_valid_compression_force(*force)) {
896 findings.push_back({
899 "Compression Force (" + std::to_string(*force) +
900 " N) is outside the typical range (20-300 N). "
901 "This may indicate a measurement error or non-standard technique.",
902 "MG-WARN-013"
903 });
904 } else if (*force < min_typical || *force > max_typical) {
905 findings.push_back({
908 "Compression Force (" + std::to_string(*force) +
909 " N) is outside the typical screening range (" +
910 std::to_string(min_typical) + "-" + std::to_string(max_typical) + " N).",
911 "MG-INFO-009"
912 });
913 }
914}
std::pair< double, double > get_typical_compression_force_range() noexcept
Get typical compression force range.
bool is_valid_compression_force(double force_n) noexcept
Validate compression force value.
@ warning
Non-critical - IOD may have issues.
@ info
Informational - suggestion for improvement.

References kcenon::pacs::services::validation::mg_tags::compression_force, kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_numeric(), kcenon::pacs::services::sop_classes::get_typical_compression_force_range(), kcenon::pacs::services::validation::info, kcenon::pacs::services::sop_classes::is_valid_compression_force(), and kcenon::pacs::services::validation::warning.

Referenced by validate_acquisition_dose_module(), and validate_compression_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_laterality_consistency()

void kcenon::pacs::services::validation::mg_iod_validator::check_laterality_consistency ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 734 of file mg_iod_validator.cpp.

736 {
737
738 // Check Laterality (0020,0060) - Series level
739 bool has_series_laterality = dataset.contains(mg_tags::laterality);
740 // Check Image Laterality (0020,0062) - Image level
741 bool has_image_laterality = dataset.contains(mg_tags::image_laterality);
742
743 // At least one should be present for mammography
744 if (!has_series_laterality && !has_image_laterality) {
745 findings.push_back({
748 "Neither Laterality (0020,0060) nor Image Laterality (0020,0062) is present. "
749 "Breast laterality must be specified for mammography images.",
750 "MG-ERR-003"
751 });
752 return;
753 }
754
755 // Validate Laterality value if present
756 if (has_series_laterality) {
757 auto lat = dataset.get_string(mg_tags::laterality);
758 if (!is_valid_breast_laterality(lat)) {
759 findings.push_back({
762 "Invalid Laterality value: '" + lat +
763 "'. Must be 'L' (left), 'R' (right), or 'B' (bilateral).",
764 "MG-ERR-004"
765 });
766 }
767 }
768
769 // Validate Image Laterality value if present
770 if (has_image_laterality) {
771 auto img_lat = dataset.get_string(mg_tags::image_laterality);
772 if (!is_valid_breast_laterality(img_lat)) {
773 findings.push_back({
776 "Invalid Image Laterality value: '" + img_lat +
777 "'. Must be 'L' (left), 'R' (right), or 'B' (bilateral).",
778 "MG-ERR-005"
779 });
780 }
781 }
782
783 // Check consistency between series and image laterality if both present
784 if (has_series_laterality && has_image_laterality) {
785 auto series_lat = dataset.get_string(mg_tags::laterality);
786 auto image_lat = dataset.get_string(mg_tags::image_laterality);
787
788 if (series_lat != image_lat) {
789 findings.push_back({
792 "Laterality mismatch: Series Laterality is '" + series_lat +
793 "' but Image Laterality is '" + image_lat + "'.",
794 "MG-WARN-001"
795 });
796 }
797 }
798}
bool is_valid_breast_laterality(std::string_view value) noexcept
Check if a laterality value is valid for mammography.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::validation::mg_tags::image_laterality, kcenon::pacs::services::sop_classes::is_valid_breast_laterality(), kcenon::pacs::services::validation::mg_tags::laterality, and kcenon::pacs::services::validation::warning.

Referenced by validate_laterality(), and validate_mammography_image_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_modality()

void kcenon::pacs::services::validation::mg_iod_validator::check_modality ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 715 of file mg_iod_validator.cpp.

717 {
718
719 if (!dataset.contains(tags::modality)) {
720 return; // Already reported as Type 1 missing
721 }
722
723 auto modality = dataset.get_string(tags::modality);
724 if (modality != "MG") {
725 findings.push_back({
728 "Modality must be 'MG' for mammography images, found: " + modality,
729 "MG-ERR-002"
730 });
731 }
732}
constexpr dicom_tag modality
Modality.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), and kcenon::pacs::core::tags::modality.

Referenced by validate_general_series_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_photometric_interpretation()

void kcenon::pacs::services::validation::mg_iod_validator::check_photometric_interpretation ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 975 of file mg_iod_validator.cpp.

977 {
978
979 if (!dataset.contains(tags::photometric_interpretation)) {
980 return; // Already reported as missing
981 }
982
983 auto photometric = dataset.get_string(tags::photometric_interpretation);
984 if (photometric != "MONOCHROME1" && photometric != "MONOCHROME2") {
985 findings.push_back({
988 "Mammography images must use MONOCHROME1 or MONOCHROME2, found: " + photometric,
989 "MG-ERR-008"
990 });
991 }
992}
constexpr dicom_tag photometric_interpretation
Photometric Interpretation.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), and kcenon::pacs::core::tags::photometric_interpretation.

Referenced by validate_image_pixel_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_pixel_data_consistency()

void kcenon::pacs::services::validation::mg_iod_validator::check_pixel_data_consistency ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 916 of file mg_iod_validator.cpp.

918 {
919
920 // Check BitsStored <= BitsAllocated
921 auto bits_allocated = dataset.get_numeric<uint16_t>(tags::bits_allocated);
922 auto bits_stored = dataset.get_numeric<uint16_t>(tags::bits_stored);
923 auto high_bit = dataset.get_numeric<uint16_t>(tags::high_bit);
924
925 if (bits_allocated && bits_stored) {
926 if (*bits_stored > *bits_allocated) {
927 findings.push_back({
930 "BitsStored (" + std::to_string(*bits_stored) +
931 ") exceeds BitsAllocated (" + std::to_string(*bits_allocated) + ")",
932 "MG-ERR-006"
933 });
934 }
935
936 // Mammography typically uses 12-16 bits stored for high dynamic range
937 if (*bits_stored < 12 || *bits_stored > 16) {
938 findings.push_back({
941 "Mammography images typically use 12-16 bits, found: " +
942 std::to_string(*bits_stored),
943 "MG-INFO-010"
944 });
945 }
946 }
947
948 // Check HighBit == BitsStored - 1
949 if (bits_stored && high_bit) {
950 if (*high_bit != *bits_stored - 1) {
951 findings.push_back({
954 "HighBit (" + std::to_string(*high_bit) +
955 ") should typically be BitsStored - 1 (" +
956 std::to_string(*bits_stored - 1) + ")",
957 "MG-WARN-014"
958 });
959 }
960 }
961
962 // Mammography must be grayscale - check SamplesPerPixel
963 auto samples = dataset.get_numeric<uint16_t>(tags::samples_per_pixel);
964 if (samples && *samples != 1) {
965 findings.push_back({
968 "Mammography images must be grayscale (SamplesPerPixel = 1), found: " +
969 std::to_string(*samples),
970 "MG-ERR-007"
971 });
972 }
973}
constexpr dicom_tag high_bit
High Bit.
constexpr dicom_tag bits_allocated
Bits Allocated.
constexpr dicom_tag bits_stored
Bits Stored.
constexpr dicom_tag samples_per_pixel
Samples per Pixel.

References kcenon::pacs::core::tags::bits_allocated, kcenon::pacs::core::tags::bits_stored, kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_numeric(), kcenon::pacs::core::tags::high_bit, kcenon::pacs::services::validation::info, kcenon::pacs::core::tags::samples_per_pixel, and kcenon::pacs::services::validation::warning.

Referenced by validate_image_pixel_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_type1_attribute()

void kcenon::pacs::services::validation::mg_iod_validator::check_type1_attribute ( const core::dicom_dataset & dataset,
core::dicom_tag tag,
std::string_view name,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 668 of file mg_iod_validator.cpp.

672 {
673
674 if (!dataset.contains(tag)) {
675 findings.push_back({
677 tag,
678 std::string("Type 1 attribute missing: ") + std::string(name) +
679 " (" + tag.to_string() + ")",
680 "MG-TYPE1-MISSING"
681 });
682 } else {
683 // Type 1 must have a value (cannot be empty)
684 auto value = dataset.get_string(tag);
685 if (value.empty()) {
686 findings.push_back({
688 tag,
689 std::string("Type 1 attribute has empty value: ") +
690 std::string(name) + " (" + tag.to_string() + ")",
691 "MG-TYPE1-EMPTY"
692 });
693 }
694 }
695}
std::string_view name

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), name, and kcenon::pacs::core::dicom_tag::to_string().

Referenced by validate_dx_detector_module(), validate_general_series_module(), validate_general_study_module(), validate_image_pixel_module(), validate_mammography_image_module(), and validate_sop_common_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_type2_attribute()

void kcenon::pacs::services::validation::mg_iod_validator::check_type2_attribute ( const core::dicom_dataset & dataset,
core::dicom_tag tag,
std::string_view name,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 697 of file mg_iod_validator.cpp.

701 {
702
703 // Type 2 must be present but can be empty
704 if (!dataset.contains(tag)) {
705 findings.push_back({
707 tag,
708 std::string("Type 2 attribute missing: ") + std::string(name) +
709 " (" + tag.to_string() + ")",
710 "MG-TYPE2-MISSING"
711 });
712 }
713}

References kcenon::pacs::core::dicom_dataset::contains(), name, kcenon::pacs::core::dicom_tag::to_string(), and kcenon::pacs::services::validation::warning.

Referenced by validate_dx_anatomy_imaged_module(), validate_dx_detector_module(), validate_general_series_module(), validate_general_study_module(), and validate_patient_module().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_view_position_validity()

void kcenon::pacs::services::validation::mg_iod_validator::check_view_position_validity ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 800 of file mg_iod_validator.cpp.

802 {
803
804 // View Position (0018,5101) - Type 2 for mammography
805 if (!dataset.contains(mg_tags::view_position)) {
806 findings.push_back({
809 "View Position (0018,5101) is not present. "
810 "This attribute should be specified for mammography images.",
811 "MG-WARN-005"
812 });
813 return;
814 }
815
816 auto view_str = dataset.get_string(mg_tags::view_position);
817 if (view_str.empty()) {
818 findings.push_back({
821 "View Position is present but empty.",
822 "MG-WARN-006"
823 });
824 return;
825 }
826
827 // Parse and validate view position
828 auto view = parse_mg_view_position(view_str);
829 if (view == mg_view_position::other) {
830 // Check if it's a valid view we just don't recognize
831 auto valid_views = get_valid_mg_view_positions();
832 std::string valid_list;
833 for (size_t i = 0; i < valid_views.size(); ++i) {
834 if (i > 0) valid_list += ", ";
835 valid_list += std::string(valid_views[i]);
836 }
837
838 findings.push_back({
841 "Unrecognized View Position: '" + view_str +
842 "'. Common mammography views include: " + valid_list,
843 "MG-WARN-010"
844 });
845 }
846
847 // Additional validation: check laterality-view consistency
848 if (dataset.contains(mg_tags::laterality) || dataset.contains(mg_tags::image_laterality)) {
849 auto lat_str = dataset.contains(mg_tags::image_laterality)
850 ? dataset.get_string(mg_tags::image_laterality)
851 : dataset.get_string(mg_tags::laterality);
852
853 auto laterality = parse_breast_laterality(lat_str);
854
855 if (!is_valid_laterality_view_combination(laterality, view)) {
856 findings.push_back({
859 "Unusual laterality-view combination: " + lat_str + " / " + view_str,
860 "MG-WARN-011"
861 });
862 }
863 }
864}
mg_view_position parse_mg_view_position(std::string_view value) noexcept
Parse DICOM view position string to mammography view enum.
bool is_valid_laterality_view_combination(breast_laterality laterality, mg_view_position view) noexcept
Check if laterality and view position are consistent.
breast_laterality parse_breast_laterality(std::string_view value) noexcept
Parse DICOM laterality string to enum.
std::vector< std::string_view > get_valid_mg_view_positions() noexcept
Get all valid mammography view position strings.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::sop_classes::get_valid_mg_view_positions(), kcenon::pacs::services::validation::mg_tags::image_laterality, kcenon::pacs::services::sop_classes::is_valid_laterality_view_combination(), kcenon::pacs::services::validation::mg_tags::laterality, kcenon::pacs::services::sop_classes::parse_breast_laterality(), kcenon::pacs::services::sop_classes::parse_mg_view_position(), kcenon::pacs::services::validation::mg_tags::view_position, and kcenon::pacs::services::validation::warning.

Referenced by validate_mammography_image_module(), and validate_view_position().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ options()

const mg_validation_options & kcenon::pacs::services::validation::mg_iod_validator::options ( ) const
nodiscardnoexcept

Get the validation options.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 307 of file mg_iod_validator.cpp.

307 {
308 return options_;
309}

References options_.

Referenced by set_options().

Here is the caller graph for this function:

◆ quick_check()

bool kcenon::pacs::services::validation::mg_iod_validator::quick_check ( const core::dicom_dataset & dataset) const
nodiscard

Quick check if dataset has minimum required attributes.

Faster than full validation - only checks critical Type 1 attributes and mammography-specific requirements.

Parameters
datasetThe dataset to check
Returns
true if all critical attributes are present
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 269 of file mg_iod_validator.cpp.

269 {
270 // Check only critical Type 1 attributes for quick validation
271
272 // General Study Module Type 1
273 if (!dataset.contains(tags::study_instance_uid)) return false;
274
275 // General Series Module Type 1
276 if (!dataset.contains(tags::modality)) return false;
277 if (!dataset.contains(tags::series_instance_uid)) return false;
278
279 // Check modality is MG
280 auto modality = dataset.get_string(tags::modality);
281 if (modality != "MG") return false;
282
283 // Image Pixel Module Type 1
284 if (!dataset.contains(tags::samples_per_pixel)) return false;
285 if (!dataset.contains(tags::photometric_interpretation)) return false;
286 if (!dataset.contains(tags::rows)) return false;
287 if (!dataset.contains(tags::columns)) return false;
288 if (!dataset.contains(tags::bits_allocated)) return false;
289 if (!dataset.contains(tags::bits_stored)) return false;
290 if (!dataset.contains(tags::high_bit)) return false;
291 if (!dataset.contains(tags::pixel_representation)) return false;
292 if (!dataset.contains(tags::pixel_data)) return false;
293
294 // SOP Common Module Type 1
295 if (!dataset.contains(tags::sop_class_uid)) return false;
296 if (!dataset.contains(tags::sop_instance_uid)) return false;
297
298 // Mammography-specific: Laterality should be present
299 if (!dataset.contains(mg_tags::laterality) &&
300 !dataset.contains(mg_tags::image_laterality)) {
301 return false;
302 }
303
304 return true;
305}
constexpr dicom_tag rows
Rows.
constexpr dicom_tag columns
Columns.
constexpr dicom_tag sop_instance_uid
SOP Instance UID.
constexpr dicom_tag pixel_data
Pixel Data.
constexpr dicom_tag pixel_representation
Pixel Representation.
constexpr dicom_tag study_instance_uid
Study Instance UID.
constexpr dicom_tag sop_class_uid
SOP Class UID.
constexpr dicom_tag series_instance_uid
Series Instance UID.

References kcenon::pacs::core::tags::bits_allocated, kcenon::pacs::core::tags::bits_stored, kcenon::pacs::core::tags::columns, kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::core::tags::high_bit, kcenon::pacs::services::validation::mg_tags::image_laterality, kcenon::pacs::services::validation::mg_tags::laterality, kcenon::pacs::core::tags::modality, kcenon::pacs::core::tags::photometric_interpretation, kcenon::pacs::core::tags::pixel_data, kcenon::pacs::core::tags::pixel_representation, kcenon::pacs::core::tags::rows, kcenon::pacs::core::tags::samples_per_pixel, kcenon::pacs::core::tags::series_instance_uid, kcenon::pacs::core::tags::sop_class_uid, kcenon::pacs::core::tags::sop_instance_uid, and kcenon::pacs::core::tags::study_instance_uid.

Referenced by kcenon::pacs::services::validation::is_valid_mg_dataset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_options()

void kcenon::pacs::services::validation::mg_iod_validator::set_options ( const mg_validation_options & options)

Set validation options.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 311 of file mg_iod_validator.cpp.

311 {
313}
const mg_validation_options & options() const noexcept
Get the validation options.

References options(), and options_.

Here is the call graph for this function:

◆ validate()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate ( const core::dicom_dataset & dataset) const
nodiscard

Validate a DICOM dataset against Mammography IOD.

Performs comprehensive validation including patient, study, series, image, and mammography-specific modules.

Parameters
datasetThe dataset to validate
Returns
Validation result with all findings
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 90 of file mg_iod_validator.cpp.

90 {
91 validation_result result;
92 result.is_valid = true;
93
94 // Validate standard modules
96 validate_patient_module(dataset, result.findings);
97 validate_general_study_module(dataset, result.findings);
98 validate_general_series_module(dataset, result.findings);
99 validate_sop_common_module(dataset, result.findings);
100 }
101
102 // Validate mammography series module
103 validate_mammography_series_module(dataset, result.findings);
104
106 validate_image_pixel_module(dataset, result.findings);
107 }
108
110 validate_mammography_image_module(dataset, result.findings);
111 validate_dx_anatomy_imaged_module(dataset, result.findings);
112 validate_dx_detector_module(dataset, result.findings);
113 }
114
116 validate_acquisition_dose_module(dataset, result.findings);
117 }
118
120 validate_breast_implant_module(dataset, result.findings);
121 }
122
123 // Check for errors
124 for (const auto& finding : result.findings) {
125 if (finding.severity == validation_severity::error) {
126 result.is_valid = false;
127 break;
128 }
129 if (options_.strict_mode && finding.severity == validation_severity::warning) {
130 result.is_valid = false;
131 break;
132 }
133 }
134
135 return result;
136}
void validate_general_series_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_general_study_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_breast_implant_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_dx_anatomy_imaged_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_dx_detector_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_mammography_image_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_patient_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_mammography_series_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_sop_common_module(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 validate_acquisition_dose_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
bool validate_pixel_data
Validate pixel data consistency (rows, columns, bits)
bool validate_dose_parameters
Validate acquisition dose parameters.
bool validate_mg_specific
Validate mammography-specific attributes.
bool check_type1
Check Type 1 (required) attributes.
bool strict_mode
Strict mode - treat warnings as errors.
bool check_type2
Check Type 2 (required, can be empty) attributes.
bool validate_compression
Validate compression force (0018,11A2)
bool validate_implant_attributes
Validate breast implant attributes.

References kcenon::pacs::services::validation::mg_validation_options::check_type1, kcenon::pacs::services::validation::mg_validation_options::check_type2, kcenon::pacs::services::validation::error, kcenon::pacs::services::validation::validation_result::findings, kcenon::pacs::services::validation::validation_result::is_valid, options_, kcenon::pacs::services::validation::mg_validation_options::strict_mode, validate_acquisition_dose_module(), validate_breast_implant_module(), kcenon::pacs::services::validation::mg_validation_options::validate_compression, kcenon::pacs::services::validation::mg_validation_options::validate_dose_parameters, validate_dx_anatomy_imaged_module(), validate_dx_detector_module(), validate_general_series_module(), validate_general_study_module(), validate_image_pixel_module(), kcenon::pacs::services::validation::mg_validation_options::validate_implant_attributes, validate_mammography_image_module(), validate_mammography_series_module(), kcenon::pacs::services::validation::mg_validation_options::validate_mg_specific, validate_patient_module(), kcenon::pacs::services::validation::mg_validation_options::validate_pixel_data, validate_sop_common_module(), and kcenon::pacs::services::validation::warning.

Referenced by validate_for_presentation(), validate_for_processing(), and kcenon::pacs::services::validation::validate_mg_iod().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_acquisition_dose_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_acquisition_dose_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 507 of file mg_iod_validator.cpp.

509 {
510
511 // Compression Force (0018,11A2) - Type 3 but important for mammography
513 check_compression_force_range(dataset, findings);
514 }
515
516 // Body Part Thickness (0018,11A0) - Type 3
518 if (dataset.contains(mg_tags::body_part_thickness)) {
519 auto thickness = dataset.get_numeric<double>(mg_tags::body_part_thickness);
520 if (thickness && !is_valid_compressed_breast_thickness(*thickness)) {
521 findings.push_back({
524 "Compressed breast thickness outside typical range (10-150mm): " +
525 std::to_string(*thickness) + " mm",
526 "MG-WARN-007"
527 });
528 }
529 } else {
530 // Recommend including thickness for quality assessment
531 findings.push_back({
534 "Compressed breast thickness not documented - "
535 "recommended for dose assessment and quality control",
536 "MG-INFO-005"
537 });
538 }
539
540 // KVP (0018,0060) - Type 3 but important for dose
541 if (!dataset.contains(mg_tags::kvp)) {
542 findings.push_back({
545 "KVP not documented - recommended for dose assessment",
546 "MG-INFO-006"
547 });
548 }
549
550 // Entrance Dose (0040,0302) - Type 3
551 // Organ Dose (0040,0316) - Type 3 but important for breast dose tracking
552 }
553}
void check_compression_force_range(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
bool is_valid_compressed_breast_thickness(double thickness_mm) noexcept
Validate compressed breast thickness.

References kcenon::pacs::services::validation::mg_tags::body_part_thickness, check_compression_force_range(), kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_numeric(), kcenon::pacs::services::validation::info, kcenon::pacs::services::sop_classes::is_valid_compressed_breast_thickness(), kcenon::pacs::services::validation::mg_tags::kvp, options_, kcenon::pacs::services::validation::mg_validation_options::validate_compression, kcenon::pacs::services::validation::mg_validation_options::validate_dose_parameters, and kcenon::pacs::services::validation::warning.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_breast_implant_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_breast_implant_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 627 of file mg_iod_validator.cpp.

629 {
630
631 // Breast Implant Present (0028,1300) - Type 3
632 if (dataset.contains(mg_tags::breast_implant_present)) {
633 auto implant = dataset.get_string(mg_tags::breast_implant_present);
634 if (implant != "YES" && implant != "NO") {
635 findings.push_back({
638 "Breast Implant Present should be 'YES' or 'NO', found: " + implant,
639 "MG-WARN-009"
640 });
641 }
642
643 // If implant is present, check for implant displaced views
644 if (implant == "YES") {
645 // Informational: implant displacement technique (Eklund) may be needed
646 if (dataset.contains(mg_tags::view_position)) {
647 auto view = dataset.get_string(mg_tags::view_position);
648 auto parsed_view = parse_mg_view_position(view);
649 if (parsed_view != mg_view_position::implant &&
650 parsed_view != mg_view_position::id) {
651 findings.push_back({
654 "Breast implant present but view is not implant-displaced (ID). "
655 "Implant displacement technique (Eklund) may improve visualization.",
656 "MG-INFO-007"
657 });
658 }
659 }
660 }
661 }
662}
@ implant
Implant displaced view (Eklund technique)

References kcenon::pacs::services::validation::mg_tags::breast_implant_present, kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::sop_classes::implant, kcenon::pacs::services::validation::info, kcenon::pacs::services::sop_classes::parse_mg_view_position(), kcenon::pacs::services::validation::mg_tags::view_position, and kcenon::pacs::services::validation::warning.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_compression_force()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate_compression_force ( const core::dicom_dataset & dataset) const
nodiscard

Validate compression force.

Checks compression force is present and within typical range.

Parameters
datasetThe dataset to validate
Returns
Validation result for compression force
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 253 of file mg_iod_validator.cpp.

253 {
254 validation_result result;
255 result.is_valid = true;
256
257 check_compression_force_range(dataset, result.findings);
258
259 for (const auto& finding : result.findings) {
260 if (finding.severity == validation_severity::error) {
261 result.is_valid = false;
262 break;
263 }
264 }
265
266 return result;
267}

References check_compression_force_range(), kcenon::pacs::services::validation::error, kcenon::pacs::services::validation::validation_result::findings, and kcenon::pacs::services::validation::validation_result::is_valid.

Here is the call graph for this function:

◆ validate_dx_anatomy_imaged_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_dx_anatomy_imaged_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 438 of file mg_iod_validator.cpp.

440 {
441
442 // Body Part Examined (0018,0015) - Type 2
443 if (options_.check_type2) {
444 check_type2_attribute(dataset, mg_tags::body_part_examined, "BodyPartExamined", findings);
445
446 if (dataset.contains(mg_tags::body_part_examined)) {
447 auto body_part = dataset.get_string(mg_tags::body_part_examined);
448 if (body_part != "BREAST") {
449 findings.push_back({
452 "Body Part Examined should be 'BREAST' for mammography, found: " + body_part,
453 "MG-WARN-003"
454 });
455 }
456 }
457 }
458
459 // Anatomic Region Sequence (0008,2218) - Type 1C
461 if (!dataset.contains(mg_tags::body_part_examined) &&
462 !dataset.contains(mg_tags::anatomic_region_sequence)) {
463 findings.push_back({
466 "Neither Body Part Examined nor Anatomic Region Sequence present - "
467 "anatomy information may be insufficient for clinical use",
468 "MG-WARN-004"
469 });
470 }
471 }
472}
void check_type2_attribute(const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const
@ body_part
(0018,0015) Body Part Examined
bool check_conditional
Check Type 1C/2C (conditionally required) attributes.

References kcenon::pacs::services::validation::mg_tags::anatomic_region_sequence, kcenon::pacs::services::validation::mg_tags::body_part_examined, kcenon::pacs::services::validation::mg_validation_options::check_conditional, kcenon::pacs::services::validation::mg_validation_options::check_type2, check_type2_attribute(), kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_string(), options_, and kcenon::pacs::services::validation::warning.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_dx_detector_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_dx_detector_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 474 of file mg_iod_validator.cpp.

476 {
477
478 // Detector Type (0018,7004) - Type 2
479 if (options_.check_type2) {
480 check_type2_attribute(dataset, mg_tags::detector_type, "DetectorType", findings);
481
482 if (dataset.contains(mg_tags::detector_type)) {
483 auto type = dataset.get_string(mg_tags::detector_type);
484 // Mammography typically uses DIRECT (a-Se) or SCINTILLATOR (CsI)
485 if (type != "DIRECT" && type != "SCINTILLATOR" && type != "STORAGE") {
486 findings.push_back({
489 "Unusual Detector Type for mammography: " + type +
490 " (typical: DIRECT, SCINTILLATOR)",
491 "MG-INFO-004"
492 });
493 }
494 }
495 }
496
497 // Imager Pixel Spacing (0018,1164) - Type 1 for DX/MG
498 if (options_.check_type1) {
500 "ImagerPixelSpacing", findings);
501
502 // Mammography typically has very fine pixel spacing (< 0.1 mm)
503 // This is informational only
504 }
505}
void check_type1_attribute(const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const

References kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), kcenon::pacs::services::validation::mg_validation_options::check_type2, check_type2_attribute(), kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::mg_tags::detector_type, kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::validation::mg_tags::imager_pixel_spacing, kcenon::pacs::services::validation::info, and options_.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_for_presentation()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate_for_presentation ( const core::dicom_dataset & dataset) const
nodiscard

Validate a For Presentation mammography dataset.

Performs additional validation for For Presentation specific requirements including VOI LUT and display parameters.

Parameters
datasetThe dataset to validate
Returns
Validation result with all findings
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 139 of file mg_iod_validator.cpp.

139 {
140 auto result = validate(dataset);
141
142 // Additional For Presentation validation
144 validate_voi_lut_module(dataset, result.findings);
145
146 // Check Presentation Intent Type
147 if (dataset.contains(mg_tags::presentation_intent_type)) {
148 auto intent = dataset.get_string(mg_tags::presentation_intent_type);
149 if (intent != "FOR PRESENTATION") {
150 result.findings.push_back({
153 "Presentation Intent Type should be 'FOR PRESENTATION' "
154 "for this SOP Class, found: " + intent,
155 "MG-ERR-010"
156 });
157 }
158 }
159 }
160
161 // Re-check validity
162 for (const auto& finding : result.findings) {
163 if (finding.severity == validation_severity::error) {
164 result.is_valid = false;
165 break;
166 }
167 }
168
169 return result;
170}
validation_result validate(const core::dicom_dataset &dataset) const
Validate a DICOM dataset against Mammography IOD.
void validate_voi_lut_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
bool validate_presentation_requirements
Validate For Presentation specific requirements.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), options_, kcenon::pacs::services::validation::mg_tags::presentation_intent_type, validate(), kcenon::pacs::services::validation::mg_validation_options::validate_presentation_requirements, and validate_voi_lut_module().

Here is the call graph for this function:

◆ validate_for_processing()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate_for_processing ( const core::dicom_dataset & dataset) const
nodiscard

Validate a For Processing mammography dataset.

Performs validation for For Processing specific requirements including raw data attributes.

Parameters
datasetThe dataset to validate
Returns
Validation result with all findings
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 173 of file mg_iod_validator.cpp.

173 {
174 auto result = validate(dataset);
175
176 // Additional For Processing validation
178 // Check Presentation Intent Type
179 if (dataset.contains(mg_tags::presentation_intent_type)) {
180 auto intent = dataset.get_string(mg_tags::presentation_intent_type);
181 if (intent != "FOR PROCESSING") {
182 result.findings.push_back({
185 "Presentation Intent Type should be 'FOR PROCESSING' "
186 "for this SOP Class, found: " + intent,
187 "MG-ERR-011"
188 });
189 }
190 }
191
192 // For Processing images should have linear pixel intensity relationship
193 if (dataset.contains(mg_tags::pixel_intensity_relationship)) {
194 auto relationship = dataset.get_string(mg_tags::pixel_intensity_relationship);
195 if (relationship != "LIN") {
196 result.findings.push_back({
199 "For Processing mammography images typically have linear (LIN) "
200 "pixel intensity relationship, found: " + relationship,
201 "MG-INFO-002"
202 });
203 }
204 }
205 }
206
207 // Re-check validity
208 for (const auto& finding : result.findings) {
209 if (finding.severity == validation_severity::error) {
210 result.is_valid = false;
211 break;
212 }
213 }
214
215 return result;
216}
bool validate_processing_requirements
Validate For Processing specific requirements.

References kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::validation::info, options_, kcenon::pacs::services::validation::mg_tags::pixel_intensity_relationship, kcenon::pacs::services::validation::mg_tags::presentation_intent_type, validate(), and kcenon::pacs::services::validation::mg_validation_options::validate_processing_requirements.

Here is the call graph for this function:

◆ validate_general_series_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_general_series_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 351 of file mg_iod_validator.cpp.

353 {
354
355 // Type 1
356 if (options_.check_type1) {
357 check_type1_attribute(dataset, tags::modality, "Modality", findings);
358 check_type1_attribute(dataset, tags::series_instance_uid, "SeriesInstanceUID", findings);
359
360 // Special check: Modality must be "MG"
361 check_modality(dataset, findings);
362 }
363
364 // Type 2
365 if (options_.check_type2) {
366 check_type2_attribute(dataset, tags::series_number, "SeriesNumber", findings);
367 }
368}
void check_modality(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
constexpr dicom_tag series_number
Series Number.

References check_modality(), kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), kcenon::pacs::services::validation::mg_validation_options::check_type2, check_type2_attribute(), kcenon::pacs::core::tags::modality, options_, kcenon::pacs::core::tags::series_instance_uid, and kcenon::pacs::core::tags::series_number.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_general_study_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_general_study_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 332 of file mg_iod_validator.cpp.

334 {
335
336 // Type 1
337 if (options_.check_type1) {
338 check_type1_attribute(dataset, tags::study_instance_uid, "StudyInstanceUID", findings);
339 }
340
341 // Type 2
342 if (options_.check_type2) {
343 check_type2_attribute(dataset, tags::study_date, "StudyDate", findings);
344 check_type2_attribute(dataset, tags::study_time, "StudyTime", findings);
345 check_type2_attribute(dataset, tags::referring_physician_name, "ReferringPhysicianName", findings);
346 check_type2_attribute(dataset, tags::study_id, "StudyID", findings);
347 check_type2_attribute(dataset, tags::accession_number, "AccessionNumber", findings);
348 }
349}
constexpr dicom_tag referring_physician_name
Referring Physician's Name.
constexpr dicom_tag accession_number
Accession Number.
constexpr dicom_tag study_time
Study Time.
constexpr dicom_tag study_id
Study ID.
constexpr dicom_tag study_date
Study Date.

References kcenon::pacs::core::tags::accession_number, kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), kcenon::pacs::services::validation::mg_validation_options::check_type2, check_type2_attribute(), options_, kcenon::pacs::core::tags::referring_physician_name, kcenon::pacs::core::tags::study_date, kcenon::pacs::core::tags::study_id, kcenon::pacs::core::tags::study_instance_uid, and kcenon::pacs::core::tags::study_time.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_image_pixel_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_image_pixel_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 555 of file mg_iod_validator.cpp.

557 {
558
559 // Type 1 attributes
560 if (options_.check_type1) {
561 check_type1_attribute(dataset, tags::samples_per_pixel, "SamplesPerPixel", findings);
562 check_type1_attribute(dataset, tags::photometric_interpretation, "PhotometricInterpretation", findings);
563 check_type1_attribute(dataset, tags::rows, "Rows", findings);
564 check_type1_attribute(dataset, tags::columns, "Columns", findings);
565 check_type1_attribute(dataset, tags::bits_allocated, "BitsAllocated", findings);
566 check_type1_attribute(dataset, tags::bits_stored, "BitsStored", findings);
567 check_type1_attribute(dataset, tags::high_bit, "HighBit", findings);
568 check_type1_attribute(dataset, tags::pixel_representation, "PixelRepresentation", findings);
569 check_type1_attribute(dataset, tags::pixel_data, "PixelData", findings);
570 }
571
572 // Validate pixel data consistency
574 check_pixel_data_consistency(dataset, findings);
575 check_photometric_interpretation(dataset, findings);
576 }
577}
void check_photometric_interpretation(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

References kcenon::pacs::core::tags::bits_allocated, kcenon::pacs::core::tags::bits_stored, check_photometric_interpretation(), check_pixel_data_consistency(), kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), kcenon::pacs::core::tags::columns, kcenon::pacs::core::tags::high_bit, options_, kcenon::pacs::core::tags::photometric_interpretation, kcenon::pacs::core::tags::pixel_data, kcenon::pacs::core::tags::pixel_representation, kcenon::pacs::core::tags::rows, kcenon::pacs::core::tags::samples_per_pixel, and kcenon::pacs::services::validation::mg_validation_options::validate_pixel_data.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_laterality()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate_laterality ( const core::dicom_dataset & dataset) const
nodiscard

Validate breast laterality attribute.

Checks that laterality is present, valid, and consistent with related attributes.

Parameters
datasetThe dataset to validate
Returns
Validation result for laterality
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 219 of file mg_iod_validator.cpp.

219 {
220 validation_result result;
221 result.is_valid = true;
222
223 check_laterality_consistency(dataset, result.findings);
224
225 for (const auto& finding : result.findings) {
226 if (finding.severity == validation_severity::error) {
227 result.is_valid = false;
228 break;
229 }
230 }
231
232 return result;
233}
void check_laterality_consistency(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const

References check_laterality_consistency(), kcenon::pacs::services::validation::error, kcenon::pacs::services::validation::validation_result::findings, and kcenon::pacs::services::validation::validation_result::is_valid.

Here is the call graph for this function:

◆ validate_mammography_image_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_mammography_image_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 390 of file mg_iod_validator.cpp.

392 {
393
394 // Image Type (0008,0008) - Type 1
395 if (options_.check_type1) {
396 check_type1_attribute(dataset, mg_tags::image_type, "ImageType", findings);
397
398 if (dataset.contains(mg_tags::image_type)) {
399 auto image_type = dataset.get_string(mg_tags::image_type);
400 // First value should be ORIGINAL or DERIVED
401 if (image_type.find("ORIGINAL") == std::string::npos &&
402 image_type.find("DERIVED") == std::string::npos) {
403 findings.push_back({
406 "Image Type first value should be ORIGINAL or DERIVED",
407 "MG-WARN-002"
408 });
409 }
410 }
411 }
412
413 // Validate laterality if enabled
415 check_laterality_consistency(dataset, findings);
416 }
417
418 // Validate view position if enabled
420 check_view_position_validity(dataset, findings);
421 }
422
423 // Partial View (0028,1350) - Type 3
424 if (dataset.contains(mg_tags::partial_view)) {
425 auto partial = dataset.get_string(mg_tags::partial_view);
426 if (partial == "YES" && !dataset.contains(mg_tags::partial_view_description) &&
427 !dataset.contains(mg_tags::partial_view_code_sequence)) {
428 findings.push_back({
431 "Partial View is YES but no description or code sequence provided",
432 "MG-INFO-003"
433 });
434 }
435 }
436}
void check_view_position_validity(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
constexpr dicom_tag image_type
Image Type.
@ partial
PARTIAL - Document is not complete.
bool validate_view_position
Validate mammography view position (0018,5101)
bool validate_laterality
Validate breast laterality (0020,0060)

References check_laterality_consistency(), kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), check_view_position_validity(), kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::validation::mg_tags::image_type, kcenon::pacs::services::validation::info, options_, kcenon::pacs::services::sop_classes::partial, kcenon::pacs::services::validation::mg_tags::partial_view, kcenon::pacs::services::validation::mg_tags::partial_view_code_sequence, kcenon::pacs::services::validation::mg_tags::partial_view_description, kcenon::pacs::services::validation::mg_validation_options::validate_laterality, kcenon::pacs::services::validation::mg_validation_options::validate_view_position, and kcenon::pacs::services::validation::warning.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_mammography_series_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_mammography_series_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 370 of file mg_iod_validator.cpp.

372 {
373
374 // Mammography Series Module includes Request Attributes Sequence (0040,0275)
375 // which is Type 3, so no validation required but informational
376
378 // The Request Attributes Sequence is useful for workflow integration
379 if (!dataset.contains(mg_tags::request_attributes_sequence)) {
380 findings.push_back({
383 "Request Attributes Sequence not present - may limit workflow integration",
384 "MG-INFO-001"
385 });
386 }
387 }
388}

References kcenon::pacs::services::validation::mg_validation_options::check_conditional, kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::info, options_, and kcenon::pacs::services::validation::mg_tags::request_attributes_sequence.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_patient_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_patient_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 319 of file mg_iod_validator.cpp.

321 {
322
323 // Patient Module - All attributes are Type 2
324 if (options_.check_type2) {
325 check_type2_attribute(dataset, tags::patient_name, "PatientName", findings);
326 check_type2_attribute(dataset, tags::patient_id, "PatientID", findings);
327 check_type2_attribute(dataset, tags::patient_birth_date, "PatientBirthDate", findings);
328 check_type2_attribute(dataset, tags::patient_sex, "PatientSex", findings);
329 }
330}
constexpr dicom_tag patient_id
Patient ID.
constexpr dicom_tag patient_birth_date
Patient's Birth Date.
constexpr dicom_tag patient_sex
Patient's Sex.
constexpr dicom_tag patient_name
Patient's Name.

References kcenon::pacs::services::validation::mg_validation_options::check_type2, check_type2_attribute(), options_, kcenon::pacs::core::tags::patient_birth_date, kcenon::pacs::core::tags::patient_id, kcenon::pacs::core::tags::patient_name, and kcenon::pacs::core::tags::patient_sex.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_sop_common_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_sop_common_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 603 of file mg_iod_validator.cpp.

605 {
606
607 // Type 1
608 if (options_.check_type1) {
609 check_type1_attribute(dataset, tags::sop_class_uid, "SOPClassUID", findings);
610 check_type1_attribute(dataset, tags::sop_instance_uid, "SOPInstanceUID", findings);
611 }
612
613 // Validate SOP Class UID is a mammography storage class
614 if (dataset.contains(tags::sop_class_uid)) {
615 auto sop_class = dataset.get_string(tags::sop_class_uid);
616 if (!is_mg_storage_sop_class(sop_class)) {
617 findings.push_back({
620 "SOPClassUID is not a recognized Mammography Storage SOP Class: " + sop_class,
621 "MG-ERR-001"
622 });
623 }
624 }
625}
bool is_mg_storage_sop_class(std::string_view uid) noexcept
Check if a SOP Class UID is a Mammography Storage SOP Class.

References kcenon::pacs::services::validation::mg_validation_options::check_type1, check_type1_attribute(), kcenon::pacs::core::dicom_dataset::contains(), kcenon::pacs::services::validation::error, kcenon::pacs::core::dicom_dataset::get_string(), kcenon::pacs::services::sop_classes::is_mg_storage_sop_class(), options_, kcenon::pacs::core::tags::sop_class_uid, and kcenon::pacs::core::tags::sop_instance_uid.

Referenced by validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_view_position()

validation_result kcenon::pacs::services::validation::mg_iod_validator::validate_view_position ( const core::dicom_dataset & dataset) const
nodiscard

Validate mammography view position.

Checks that view position is present and contains a valid mammography view code.

Parameters
datasetThe dataset to validate
Returns
Validation result for view position
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 236 of file mg_iod_validator.cpp.

236 {
237 validation_result result;
238 result.is_valid = true;
239
240 check_view_position_validity(dataset, result.findings);
241
242 for (const auto& finding : result.findings) {
243 if (finding.severity == validation_severity::error) {
244 result.is_valid = false;
245 break;
246 }
247 }
248
249 return result;
250}

References check_view_position_validity(), kcenon::pacs::services::validation::error, kcenon::pacs::services::validation::validation_result::findings, and kcenon::pacs::services::validation::validation_result::is_valid.

Here is the call graph for this function:

◆ validate_voi_lut_module()

void kcenon::pacs::services::validation::mg_iod_validator::validate_voi_lut_module ( const core::dicom_dataset & dataset,
std::vector< validation_finding > & findings ) const
private
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/services/validation/mg_iod_validator.h.

Definition at line 579 of file mg_iod_validator.cpp.

581 {
582
583 // Window Center (0028,1050) and Window Width (0028,1051) - Type 1C for For Presentation
585 bool has_window = dataset.contains(tags::window_center) &&
586 dataset.contains(tags::window_width);
587
588 constexpr dicom_tag voi_lut_sequence{0x0028, 0x3010};
589 bool has_voi_lut = dataset.contains(voi_lut_sequence);
590
591 if (!has_window && !has_voi_lut) {
592 findings.push_back({
595 "For Presentation mammography images should have Window Center/Width "
596 "or VOI LUT Sequence for proper display",
597 "MG-WARN-008"
598 });
599 }
600 }
601}
constexpr dicom_tag window_width
Window Width.
constexpr dicom_tag window_center
Window Center.

References kcenon::pacs::services::validation::mg_validation_options::check_conditional, kcenon::pacs::core::dicom_dataset::contains(), options_, kcenon::pacs::services::validation::warning, kcenon::pacs::core::tags::window_center, and kcenon::pacs::core::tags::window_width.

Referenced by validate_for_presentation().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ options_


The documentation for this class was generated from the following files: