//! # rtx-medical-core //! //! Unified medical imaging super-crate consolidating I/O formats and volume handling. //! //! This crate provides a comprehensive foundation for medical imaging applications, //! supporting various formats (NIfTI, DICOM) and volume processing operations. //! //! ## Features //! //! - `volume`: Core volume data structure (enabled by default) //! - `nifti`: NIfTI file format support (enabled by default) //! - `dicom`: DICOM file format support //! - `gpu`: GPU acceleration support via rtx-tensor //! - `full`: All features enabled //! //! ## Example //! //! ```rust //! use rtx_medical_core::{ //! Volume, //! MedicalMetadata, //! VoxelSpacing, //! }; //! //! // Create voxel spacing //! let spacing = VoxelSpacing::isotropic(1.0); //! //! // Create a volume filled with zeros //! let volume = Volume::zeros([256, 256, 128]); //! //! // Access volume properties //! println!("Volume shape: {:?}", volume.shape()); //! println!("Number of voxels: {}", volume.num_voxels()); //! ``` #![deny(missing_docs)] // Note: unsafe_code is allowed in specific modules (volume) for performance-critical operations // Core modules (always available) mod error; mod metadata; // Re-export core types pub use error::{MedicalError, MedicalResult}; pub use metadata::{MedicalMetadata, Orientation, VoxelSpacing}; // Feature-gated modules #[cfg(feature = "volume")] #[allow(unsafe_code)] mod volume; #[cfg(feature = "volume")] pub use volume::Volume; #[cfg(feature = "nifti")] /// NIfTI file format support pub mod nifti; #[cfg(feature = "nifti")] pub use nifti::{NiftiDataType, NiftiHeader, NiftiVolume, read_nifti, write_nifti}; #[cfg(feature = "dicom")] /// DICOM file format support pub mod dicom; #[cfg(feature = "dicom")] pub use dicom::{DicomMetadata, Modality, TransferSyntax}; #[cfg(test)] mod tests { use super::*; #[test] fn test_core_exports_available() { let spacing = VoxelSpacing::isotropic(1.0); let metadata = MedicalMetadata::new((10, 10, 10), spacing); assert_eq!(metadata.dimensions, (10, 10, 10)); } #[test] fn test_error_export_available() { let err = MedicalError::Volume("test".to_string()); assert!(err.to_string().contains("test")); } #[cfg(feature = "volume")] #[test] fn test_volume_export_available() { let volume = Volume::zeros([10, 10, 10]); assert_eq!(volume.shape(), [10, 10, 10]); assert_eq!(volume.num_voxels(), 1000); } #[cfg(feature = "nifti")] #[test] fn test_nifti_exports_available() { // Test NiftiDataType is accessible and works let datatype = NiftiDataType::Int16; assert_eq!(datatype.bytes_per_voxel(), 2); // Test NiftiDataType conversion let float_type = NiftiDataType::Float32; assert_eq!(float_type.bytes_per_voxel(), 4); // Test Affine4 type is accessible let affine = nifti::identity(); assert_eq!(affine[0][0], 1.0); } #[cfg(feature = "dicom")] #[test] fn test_dicom_exports_available() { let modality = Modality::CT; assert_eq!(modality.code(), "CT"); let transfer_syntax = TransferSyntax::ExplicitVRLittleEndian; assert_eq!(transfer_syntax.uid(), "1.2.840.10008.1.2.1"); let metadata = DicomMetadata::new(modality, transfer_syntax); assert_eq!(metadata.modality, Modality::CT); } #[test] fn test_medical_result_propagation() { fn test_function() -> MedicalResult { Err(MedicalError::Volume("test error".to_string())) } let result = test_function(); assert!(result.is_err()); } #[test] fn test_medical_result_ok_propagation() { fn test_function() -> MedicalResult { Ok(42) } let result = test_function(); assert_eq!(result.unwrap(), 42); } #[cfg(feature = "volume")] #[test] fn test_integration_volume_with_metadata() { let volume = Volume::filled([64, 64, 32], 100.0); assert_eq!(volume.shape(), [64, 64, 32]); assert_eq!(volume.num_voxels(), 64 * 64 * 32); assert_eq!(volume.spacing(), [1.0, 1.0, 1.0]); } #[cfg(all(feature = "volume", feature = "nifti"))] #[test] fn test_integration_volume_with_nifti() { // Test that volume and nifti types work together let volume = Volume::zeros([128, 128, 64]); assert_eq!(volume.num_voxels(), 128 * 128 * 64); assert_eq!(volume.shape(), [128, 128, 64]); // NiftiDataType is accessible let dtype = NiftiDataType::Float64; assert_eq!(dtype.bytes_per_voxel(), 8); } }