26 : options_(options) {}
60 for (
const auto& finding : result.
findings) {
85 if (modality !=
"SM")
return false;
124 std::vector<validation_finding>& findings)
const {
133 "PatientBirthDate", findings);
141 std::vector<validation_finding>& findings)
const {
146 "StudyInstanceUID", findings);
156 "ReferringPhysicianName", findings);
159 "AccessionNumber", findings);
165 std::vector<validation_finding>& findings)
const {
171 "SeriesInstanceUID", findings);
186 std::vector<validation_finding>& findings)
const {
198 "TotalPixelMatrixColumns", findings);
200 "TotalPixelMatrixRows", findings);
205 "NumberOfFrames", findings);
214 "ImagedVolumeWidth (0048,0001) not present - physical "
215 "dimensions unavailable",
222 "ImagedVolumeHeight (0048,0002) not present - physical "
223 "dimensions unavailable",
233 "ImageOrientationSlide (0048,0102) missing - slide "
234 "orientation unknown",
242 std::vector<validation_finding>& findings)
const {
247 "OpticalPathIdentifier", findings);
256 "OpticalPathDescription (0048,0106) not present - optical "
257 "path details unavailable",
265 std::vector<validation_finding>& findings)
const {
269 "DimensionOrganizationType", findings);
275 if (org_type !=
"TILED_FULL" && org_type !=
"TILED_SPARSE") {
279 "DimensionOrganizationType must be 'TILED_FULL' or "
280 "'TILED_SPARSE' for WSI, found: " + org_type,
288 std::vector<validation_finding>& findings)
const {
293 "SamplesPerPixel", findings);
295 "PhotometricInterpretation", findings);
304 "PixelRepresentation", findings);
315 std::vector<validation_finding>& findings)
const {
323 "SpecimenIdentifier (0040,0551) not present - specimen "
324 "tracking unavailable",
331 "ContainerIdentifier (0040,0512) not present - container "
332 "tracking unavailable",
339 std::vector<validation_finding>& findings)
const {
346 "SOPInstanceUID", findings);
355 "SOPClassUID is not a recognized WSI Storage SOP Class: " +
368 std::vector<validation_finding>& findings)
const {
373 std::string(
"Type 1 attribute missing: ") + std::string(
name) +
375 "WSI-TYPE1-MISSING"});
382 std::string(
"Type 1 attribute has empty value: ") +
391 std::vector<validation_finding>& findings)
const {
397 std::string(
"Type 2 attribute missing: ") + std::string(
name) +
399 "WSI-TYPE2-MISSING"});
405 std::vector<validation_finding>& findings)
const {
412 if (modality !=
"SM") {
415 "Modality must be 'SM' for WSI images, found: " + modality,
422 std::vector<validation_finding>& findings)
const {
425 auto bits_allocated =
430 if (bits_allocated && bits_stored) {
431 if (*bits_stored > *bits_allocated) {
434 "BitsStored (" + std::to_string(*bits_stored) +
435 ") exceeds BitsAllocated (" +
436 std::to_string(*bits_allocated) +
")",
442 if (bits_stored && high_bit) {
443 if (*high_bit != *bits_stored - 1) {
446 "HighBit (" + std::to_string(*high_bit) +
447 ") should typically be BitsStored - 1 (" +
448 std::to_string(*bits_stored - 1) +
")",
461 "WSI images must use RGB, YBR_FULL_422, YBR_ICT, YBR_RCT, "
462 "or MONOCHROME2, found: " + photometric,
469 if (samples && *samples != 1 && *samples != 3) {
472 "WSI images require SamplesPerPixel of 1 or 3, found: " +
473 std::to_string(*samples),
480 if (pixel_rep && *pixel_rep != 0) {
483 "WSI images typically use unsigned pixel representation "
484 "(PixelRepresentation = 0)",
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_type2_attribute(const core::dicom_dataset &dataset, core::dicom_tag tag, std::string_view name, std::vector< validation_finding > &findings) const
void validate_sop_common_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_optical_path_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_specimen_module(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
void validate_multiframe_dimension_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 WSI attributes.
wsi_iod_validator()=default
Construct validator with default options.
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_modality(const core::dicom_dataset &dataset, std::vector< validation_finding > &findings) const
wsi_validation_options options_
void set_options(const wsi_validation_options &options)
Set validation options.
void validate_wsi_image_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
validation_result validate(const core::dicom_dataset &dataset) const
Validate a DICOM dataset against WSI IOD.
void validate_general_study_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
const wsi_validation_options & options() const noexcept
Get the validation options.
Compile-time constants for commonly used DICOM tags.
bool is_wsi_storage_sop_class(std::string_view uid) noexcept
Check if a SOP Class UID is a WSI Storage SOP Class.
bool is_valid_wsi_photometric(std::string_view value) noexcept
Check if photometric interpretation is valid for WSI.
@ warning
Non-critical - IOD may have issues.
@ info
Informational - suggestion for improvement.
@ error
Critical - IOD is non-compliant.
bool is_valid_wsi_dataset(const core::dicom_dataset &dataset)
Quick check if a dataset is a valid WSI image.
validation_result validate_wsi_iod(const core::dicom_dataset &dataset)
Validate a WSI dataset with default options.
Result of IOD validation.
std::vector< validation_finding > findings
All findings during validation.
bool is_valid
Overall validation status.
Options for WSI IOD validation.
bool strict_mode
Strict mode - treat warnings as errors.
bool validate_pixel_data
Validate pixel data consistency (rows, columns, bits)
bool check_type2
Check Type 2 (required, can be empty) attributes.
bool check_type1
Check Type 1 (required) attributes.
bool check_conditional
Check Type 1C/2C (conditionally required) attributes.
bool validate_optical_path
Validate optical path information.
bool validate_wsi_params
Validate WSI-specific image parameters.
VL Whole Slide Microscopy Image IOD Validator.
VL Whole Slide Microscopy Image Storage SOP Class.