""" Constants for radiology app. Centralized choices and validators for consistency across models. """ from django.db import models from django.core.validators import RegexValidator class RadiologyChoices: """Centralized choices for radiology models.""" class Modality(models.TextChoices): CR = 'CR', 'Computed Radiography' CT = 'CT', 'Computed Tomography' MR = 'MR', 'Magnetic Resonance' US = 'US', 'Ultrasound' XA = 'XA', 'X-Ray Angiography' RF = 'RF', 'Radiofluoroscopy' DX = 'DX', 'Digital Radiography' MG = 'MG', 'Mammography' NM = 'NM', 'Nuclear Medicine' PT = 'PT', 'Positron Emission Tomography' OT = 'OT', 'Other' class BodyPart(models.TextChoices): HEAD = 'HEAD', 'Head' NECK = 'NECK', 'Neck' CHEST = 'CHEST', 'Chest' ABDOMEN = 'ABDOMEN', 'Abdomen' PELVIS = 'PELVIS', 'Pelvis' SPINE = 'SPINE', 'Spine' EXTREMITY = 'EXTREMITY', 'Extremity' BREAST = 'BREAST', 'Breast' HEART = 'HEART', 'Heart' BRAIN = 'BRAIN', 'Brain' WHOLE_BODY = 'WHOLE_BODY', 'Whole Body' OTHER = 'OTHER', 'Other' class Priority(models.TextChoices): ROUTINE = 'ROUTINE', 'Routine' URGENT = 'URGENT', 'Urgent' STAT = 'STAT', 'STAT' EMERGENCY = 'EMERGENCY', 'Emergency' class ImageQuality(models.TextChoices): EXCELLENT = 'EXCELLENT', 'Excellent' GOOD = 'GOOD', 'Good' ADEQUATE = 'ADEQUATE', 'Adequate' POOR = 'POOR', 'Poor' UNACCEPTABLE = 'UNACCEPTABLE', 'Unacceptable' class StudyStatus(models.TextChoices): SCHEDULED = 'SCHEDULED', 'Scheduled' ARRIVED = 'ARRIVED', 'Arrived' IN_PROGRESS = 'IN_PROGRESS', 'In Progress' COMPLETED = 'COMPLETED', 'Completed' INTERPRETED = 'INTERPRETED', 'Interpreted' FINALIZED = 'FINALIZED', 'Finalized' CANCELLED = 'CANCELLED', 'Cancelled' class OrderStatus(models.TextChoices): PENDING = 'PENDING', 'Pending' SCHEDULED = 'SCHEDULED', 'Scheduled' IN_PROGRESS = 'IN_PROGRESS', 'In Progress' COMPLETED = 'COMPLETED', 'Completed' CANCELLED = 'CANCELLED', 'Cancelled' ON_HOLD = 'ON_HOLD', 'On Hold' class ReportStatus(models.TextChoices): DRAFT = 'DRAFT', 'Draft' PRELIMINARY = 'PRELIMINARY', 'Preliminary' FINAL = 'FINAL', 'Final' AMENDED = 'AMENDED', 'Amended' CORRECTED = 'CORRECTED', 'Corrected' class CompletionStatus(models.TextChoices): COMPLETE = 'COMPLETE', 'Complete' PARTIAL = 'PARTIAL', 'Partial' INCOMPLETE = 'INCOMPLETE', 'Incomplete' class PatientPosition(models.TextChoices): HFP = 'HFP', 'Head First-Prone' HFS = 'HFS', 'Head First-Supine' HFDR = 'HFDR', 'Head First-Decubitus Right' HFDL = 'HFDL', 'Head First-Decubitus Left' FFP = 'FFP', 'Feet First-Prone' FFS = 'FFS', 'Feet First-Supine' FFDR = 'FFDR', 'Feet First-Decubitus Right' FFDL = 'FFDL', 'Feet First-Decubitus Left' class ContrastRoute(models.TextChoices): IV = 'IV', 'Intravenous' ORAL = 'ORAL', 'Oral' RECTAL = 'RECTAL', 'Rectal' INTRATHECAL = 'INTRATHECAL', 'Intrathecal' INTRA_ARTICULAR = 'INTRA_ARTICULAR', 'Intra-articular' OTHER = 'OTHER', 'Other' class RadiologyValidators: """Validators for radiology-specific fields.""" # DICOM UID validator - must be numeric with dots dicom_uid_validator = RegexValidator( regex=r'^[0-9]+(\.[0-9]+)*$', message='Invalid DICOM UID format. Must contain only numbers and dots.' ) # Accession number validator accession_number_validator = RegexValidator( regex=r'^[A-Z]{2,4}-\d{8}-\d{4}$', message='Invalid accession number format. Expected format: RAD-YYYYMMDD-NNNN' ) # Order number validator order_number_validator = RegexValidator( regex=r'^[A-Z]{3}-\d+-\d{6}$', message='Invalid order number format. Expected format: IMG-TENANT-NNNNNN' ) # DICOM Standard Constants class DICOMConstants: """DICOM standard constants and mappings.""" # Common SOP Class UIDs SOP_CLASS_UIDS = { 'CT_IMAGE': '1.2.840.10008.5.1.4.1.1.2', 'MR_IMAGE': '1.2.840.10008.5.1.4.1.1.4', 'US_IMAGE': '1.2.840.10008.5.1.4.1.1.6.1', 'CR_IMAGE': '1.2.840.10008.5.1.4.1.1.1', 'DX_IMAGE': '1.2.840.10008.5.1.4.1.1.1.1', } # Transfer Syntax UIDs TRANSFER_SYNTAX_UIDS = { 'IMPLICIT_VR_LITTLE_ENDIAN': '1.2.840.10008.1.2', 'EXPLICIT_VR_LITTLE_ENDIAN': '1.2.840.10008.1.2.1', 'EXPLICIT_VR_BIG_ENDIAN': '1.2.840.10008.1.2.2', 'JPEG_BASELINE': '1.2.840.10008.1.2.4.50', 'JPEG_LOSSLESS': '1.2.840.10008.1.2.4.70', } # Standard image types IMAGE_TYPES = { 'ORIGINAL': 'Original image', 'DERIVED': 'Derived image', 'SECONDARY': 'Secondary capture', } # Business Rules Constants class RadiologyBusinessRules: """Business rules and constraints for radiology workflow.""" # Status transition rules VALID_STATUS_TRANSITIONS = { 'SCHEDULED': ['ARRIVED', 'CANCELLED'], 'ARRIVED': ['IN_PROGRESS', 'CANCELLED'], 'IN_PROGRESS': ['COMPLETED', 'CANCELLED'], 'COMPLETED': ['INTERPRETED'], 'INTERPRETED': ['FINALIZED'], 'FINALIZED': ['AMENDED'], 'CANCELLED': [], # Terminal state } # Priority escalation rules PRIORITY_ESCALATION_HOURS = { 'ROUTINE': 24, 'URGENT': 4, 'STAT': 1, 'EMERGENCY': 0.5, } # Critical finding communication requirements CRITICAL_COMMUNICATION_TIMEFRAMES = { 'EMERGENCY': 15, # minutes 'STAT': 30, # minutes 'URGENT': 60, # minutes 'ROUTINE': 120, # minutes } # Quality thresholds QUALITY_THRESHOLDS = { 'MIN_ACCEPTABLE': 'ADEQUATE', 'PREFERRED': 'GOOD', 'EXCELLENT': 'EXCELLENT', }