|
21 | 21 | from isic_metadata.fields import ( |
22 | 22 | Age, |
23 | 23 | AnatomSiteGeneralEnum, |
| 24 | + AnatomSiteSpecialEnum, |
24 | 25 | BenignMalignantEnum, |
25 | 26 | ClinSizeLongDiamMm, |
26 | 27 | ColorTintEnum, |
@@ -206,6 +207,7 @@ class MetadataRow(BaseModel): |
206 | 207 | ) = None |
207 | 208 | sex: Literal["male", "female"] | None = None |
208 | 209 | anatom_site_general: AnatomSiteGeneralEnum | None = None |
| 210 | + anatom_site_special: AnatomSiteSpecialEnum | None = None |
209 | 211 | benign_malignant: BenignMalignantEnum | None = None |
210 | 212 | diagnosis: ( |
211 | 213 | Annotated[ |
@@ -442,6 +444,57 @@ def validate_dermoscopic_fields(self) -> MetadataRow: |
442 | 444 |
|
443 | 445 | return self |
444 | 446 |
|
| 447 | + @model_validator(mode="after") |
| 448 | + def validate_anatom_site_special(self) -> MetadataRow: |
| 449 | + if not self.anatom_site_special: |
| 450 | + return self |
| 451 | + |
| 452 | + if not self.anatom_site_general: |
| 453 | + raise error_missing_field("anatom_site_special", "anatom_site_general") |
| 454 | + |
| 455 | + valid_combinations = { |
| 456 | + AnatomSiteSpecialEnum.acral_nos: [ |
| 457 | + AnatomSiteGeneralEnum.upper_extremity, |
| 458 | + AnatomSiteGeneralEnum.lower_extremity, |
| 459 | + AnatomSiteGeneralEnum.palms_soles, |
| 460 | + ], |
| 461 | + AnatomSiteSpecialEnum.nail_nos: [ |
| 462 | + AnatomSiteGeneralEnum.upper_extremity, |
| 463 | + AnatomSiteGeneralEnum.lower_extremity, |
| 464 | + AnatomSiteGeneralEnum.palms_soles, |
| 465 | + ], |
| 466 | + AnatomSiteSpecialEnum.fingernail: [ |
| 467 | + AnatomSiteGeneralEnum.upper_extremity, |
| 468 | + AnatomSiteGeneralEnum.palms_soles, |
| 469 | + ], |
| 470 | + AnatomSiteSpecialEnum.toenail: [ |
| 471 | + AnatomSiteGeneralEnum.lower_extremity, |
| 472 | + AnatomSiteGeneralEnum.palms_soles, |
| 473 | + ], |
| 474 | + AnatomSiteSpecialEnum.acral_palms_soles: [ |
| 475 | + AnatomSiteGeneralEnum.upper_extremity, |
| 476 | + AnatomSiteGeneralEnum.lower_extremity, |
| 477 | + AnatomSiteGeneralEnum.palms_soles, |
| 478 | + ], |
| 479 | + AnatomSiteSpecialEnum.oral_genital: [ |
| 480 | + AnatomSiteGeneralEnum.head_neck, |
| 481 | + AnatomSiteGeneralEnum.oral_genital, |
| 482 | + ], |
| 483 | + } |
| 484 | + |
| 485 | + if self.anatom_site_special.value not in valid_combinations: |
| 486 | + return self |
| 487 | + |
| 488 | + if self.anatom_site_general.value not in valid_combinations[self.anatom_site_special.value]: |
| 489 | + raise error_incompatible_fields( |
| 490 | + "anatom_site_special", |
| 491 | + "anatom_site_general", |
| 492 | + self.anatom_site_special.value, |
| 493 | + self.anatom_site_general.value, |
| 494 | + ) |
| 495 | + |
| 496 | + return self |
| 497 | + |
445 | 498 | @model_validator(mode="after") |
446 | 499 | def validate_tbp_tile_fields(self) -> MetadataRow: |
447 | 500 | if not self.tbp_tile_type: |
|
0 commit comments