-
Notifications
You must be signed in to change notification settings - Fork 0
Add a DTO for usage with the Django app. #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
…DICOM metadata models for various imaging modalities
…ance UIDs for improved type safety
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a Django idiomatic DTO (Data Transfer Object) architecture to the bfd9000_dicom package, with major refactoring and reorganization of the codebase. The changes introduce a clean separation of concerns with specialized converter classes, core utilities, and Django-style metadata models for various imaging modalities.
Key changes:
- Introduced Django-style DTO models for DICOM metadata with multiple imaging modalities support
- Restructured the package into logical modules: converters/, core/, and models.py
- Added comprehensive test coverage and documentation for the new architecture
Reviewed Changes
Copilot reviewed 28 out of 35 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| bfd9000_dicom/bfd9000_dicom/models.py | Implements Django-style DTO classes for DICOM metadata across multiple modalities |
| bfd9000_dicom/bfd9000_dicom/converters/ | New package containing specialized converters for different imaging types |
| bfd9000_dicom/bfd9000_dicom/core/ | Core utilities for DICOM building and compression, refactored from existing modules |
| bfd9000_dicom/tests/ | Comprehensive test suite for the new architecture and existing functionality |
| bfd9000_dicom/examples/basic_usage.py | Example code demonstrating the new DTO and converter APIs |
| bfd9000_dicom/docs/ | Architecture documentation and planning documents |
| bfd9000_dicom/pyproject.toml | Project configuration with updated dependencies and metadata |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| import os | ||
| import json | ||
| import pydicom | ||
| import argparse | ||
| from pydicom.dataset import Dataset | ||
| from pydicom.uid import SecondaryCaptureImageStorage, generate_uid |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of the import pydicom line may indicate incomplete refactoring. Verify that all pydicom functionality is accessed through specific imports rather than the general module import.
bfd9000_dicom/plan.md
Outdated
| f"{self.nominal_scanned_pixel_spacing[0]}", | ||
| f"{self.nominal_scanned_pixel_spacing[1]}" | ||
| ] | ||
| ds.PixelSpacing No newline at end of file |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete code line - the assignment to ds.PixelSpacing is missing its value. This appears to be truncated code that should be completed or removed.
| ds.PixelSpacing | |
| ds.PixelSpacing = [ | |
| f"{self.nominal_scanned_pixel_spacing[0]}", | |
| f"{self.nominal_scanned_pixel_spacing[1]}" | |
| ] |
bfd9000_dicom/plan.md
Outdated
| f"{self.nominal_scanned_pixel_spacing[0]}", | ||
| f"{self.nominal_scanned_pixel_spacing[1]}" | ||
| ] | ||
| ds.PixelSpacing No newline at end of file |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate incomplete code line - the assignment to ds.PixelSpacing is missing its value. This appears to be duplicated truncated code that should be completed or removed.
| ds.PixelSpacing | |
| ds.PixelSpacing = [ | |
| f"{self.nominal_scanned_pixel_spacing[0]}", | |
| f"{self.nominal_scanned_pixel_spacing[1]}" | |
| ] |
…update usage examples
- Remove obsolete DocumentConverter and Converter classes. - Introduce new JPEGConverter, PNGConverter, PDFConverter, STLConverter, and TIFFConverter classes for handling respective formats. - Implement a router system to automatically select the appropriate converter based on file type. - Add example usage scripts demonstrating the new converter architecture and functionality. - Ensure proper handling of metadata and pixel data for each converter.
Relocated compression.py → compression.py Updated all import statements across the codebase (TIFF, JPEG, PNG converters, tests, etc.) Integrated DICOM tags logic from dicom_tags.py Added Bolton Brush specific attributes to RadiographMetadata class: is_bolton_brush_study flag Automatic setting of Bolton Brush device information when enabled Added orientation methods: set_orientation_ll(), set_orientation_pa(), set_orientation_hand() Integrated common Bolton Brush tags into the metadata DTO Integrated TIFF conversion logic from tiff2dcm.py Created utility functions in converters/utils.py: extract_bolton_brush_data_from_filename() - parses Bolton Brush filename format load_radiograph_metadata_from_json() - backward compatibility for JSON metadata Exported these utilities in the main package API Updated all imports and references Updated main package __init__.py to export new utility functions All compression imports now point to the new location No remaining active references to old modules 📁 File Changes: Moved: compression.py → compression.py Modified: models.py - Added Bolton Brush support to RadiographMetadata Created: converters/utils.py - Bolton Brush utilities Updated: All converter files, main __init__.py, test files 🗂️ Remaining Action: The old/ folder can now be safely removed since all its logic has been integrated into the new architecture:
- Moved exception imports to the base converter module. - Updated import paths in JPEG converter. - Removed unused compression imports from core module. - Improved README test structure and added categories. - Added unit tests for Bolton Brush utilities and DICOM metadata models. - Created integration tests for converter router functionality. - Enhanced TIFF converter tests and added edge case handling.
…ion and update filename parsing to include image type
…on calls and clean up whitespace
…action, and add new modality types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 38 out of 43 changed files in this pull request and generated 5 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| # Calculate PixelAspectRatio using original dpi values to avoid rounding errors | ||
| if dpi_horizontal == dpi_vertical: | ||
| pixel_aspect_ratio = [1, 1] | ||
| pixel_aspect_ratio = ["1", "1"] |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent return type for pixel_aspect_ratio. The function returns a list [\"1\", \"1\"] for equal DPI but a list [f\"{int(dpi_vertical / gcd_ratio)}\", f\"{int(dpi_horizontal / gcd_ratio)}\"] for unequal DPI. The original function returned tuples but this has been changed to lists for string formatting, which should be consistent throughout.
| class ConversionType(Enum): | ||
| """DICOM Conversion Type values (0008,0064).""" | ||
| DF = "DF" # Digitized Film | ||
| SI = "SI" # Digital Interface |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected 'DI' to 'SI' in the enum value comment. The enum value 'SI' stands for 'Synthetic Image' but the comment incorrectly references 'Digital Interface'.
| SI = "SI" # Digital Interface | |
| SI = "SI" # Synthetic Image |
| # Create metadata | ||
| metadata = RadiographMetadata( | ||
| patient_id=patient_id, | ||
| patient_sex=PatientSex[sex], | ||
| patient_age=age_months, # This might not be the correct format for the DTO. |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment indicates uncertainty about the correct format for patient_age. Based on the DTO definition, patient_age should be a string in DICOM format (e.g., '217M' for months), not the raw age_months value returned from extract_metadata_from_filename.
| # Create metadata | |
| metadata = RadiographMetadata( | |
| patient_id=patient_id, | |
| patient_sex=PatientSex[sex], | |
| patient_age=age_months, # This might not be the correct format for the DTO. | |
| def months_to_dicom_age(months): | |
| """Convert integer months to DICOM age string (e.g., '217M').""" | |
| return f"{int(months):03d}M" | |
| # Create metadata | |
| metadata = RadiographMetadata( | |
| patient_id=patient_id, | |
| patient_sex=PatientSex[sex], | |
| patient_age=months_to_dicom_age(age_months), |
| from pydicom.uid import ExplicitVRLittleEndian, JPEG2000Lossless | ||
|
|
||
| from bfd9000_dicom.models import BaseDICOMMetadata | ||
| from .compression import get_encapsulated_jpeg2k_pixel_data |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect relative import path. Should import from bfd9000_dicom.converters.compression instead of .compression since the compression module is in the same converters package.
| from .compression import get_encapsulated_jpeg2k_pixel_data | |
| from bfd9000_dicom.converters.compression import get_encapsulated_jpeg2k_pixel_data |
| class ConversionType(Enum): | ||
| """DICOM Conversion Type values (0008,0064).""" | ||
| DF = "DF" # Digitized Film | ||
| SI = "SI" # Digital Interface |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect comment for enum value. 'SI' in DICOM Conversion Type should be 'Synthetic Image', not 'Digital Interface'. The correct value for Digital Interface would be 'DI'.
| SI = "SI" # Digital Interface | |
| SI = "SI" # Synthetic Image |
…t in metadata, and improve utility function usage
…h new extractor, update examples and tests accordingly
…olton Brush limits
Adds a Django idiomatic model to the bfd9000_dicom package. Major refactoring and re-organization.