Skip to main content

qualia_core_db/specialized_libs/medical_computing/
imaging.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5/// Medical imaging
6pub struct MedicalImaging {
7    image_acquisition: ImageAcquisition,
8    image_processing: ImageProcessing,
9    image_analysis: ImageAnalysis,
10    image_storage: ImageStorage,
11}
12
13/// Image acquisition
14pub struct ImageAcquisition {
15    acquisition_protocols: HashMap<String, AcquisitionProtocol>,
16    quality_control: QualityControl,
17}
18
19/// Acquisition protocols
20#[derive(Debug, Clone)]
21pub struct AcquisitionProtocol {
22    pub protocol_id: String,
23    pub protocol_name: String,
24    pub imaging_modality: ImagingModality,
25    pub parameters: AcquisitionParameters,
26}
27
28/// Imaging modalities
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30pub enum ImagingModality {
31    XRay,
32    CT,
33    MRI,
34    Ultrasound,
35    PET,
36    SPECT,
37    Mammography,
38}
39
40/// Acquisition parameters
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct AcquisitionParameters {
43    pub resolution: String,
44    pub slice_thickness: f64,
45    pub field_of_view: String,
46    pub acquisition_time: u32,
47}
48
49/// Quality control
50pub struct QualityControl {
51    quality_metrics: HashMap<String, QualityMetric>,
52    quality_standards: HashMap<String, QualityStandard>,
53}
54
55/// Quality metrics
56#[derive(Debug, Clone)]
57pub struct QualityMetric {
58    pub metric_id: String,
59    pub metric_name: String,
60    pub metric_type: QualityMetricType,
61    pub acceptable_range: (f64, f64),
62}
63
64/// Quality metric types
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub enum QualityMetricType {
67    SignalToNoise,
68    Contrast,
69    Resolution,
70    ArtifactLevel,
71}
72
73/// Quality standards
74#[derive(Debug, Clone)]
75pub struct QualityStandard {
76    pub standard_id: String,
77    pub standard_name: String,
78    pub standard_type: QualityStandardType,
79    pub requirements: Vec<QualityRequirement>,
80}
81
82/// Quality standard types
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84pub enum QualityStandardType {
85    ACR,
86    FDA,
87    CE,
88    ISO,
89}
90
91/// Quality requirements
92#[derive(Debug, Clone)]
93pub struct QualityRequirement {
94    pub requirement_id: String,
95    pub requirement_name: String,
96    pub requirement_value: f64,
97    pub tolerance: f64,
98}
99
100/// Image processing
101pub struct ImageProcessing {
102    preprocessing_algorithms: HashMap<String, PreprocessingAlgorithm>,
103    enhancement_techniques: HashMap<String, EnhancementTechnique>,
104}
105
106/// Preprocessing algorithms
107#[derive(Debug, Clone)]
108pub struct PreprocessingAlgorithm {
109    pub algorithm_id: String,
110    pub algorithm_name: String,
111    pub algorithm_type: PreprocessingAlgorithmType,
112}
113
114/// Preprocessing algorithm types
115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116pub enum PreprocessingAlgorithmType {
117    NoiseReduction,
118    Normalization,
119    Registration,
120    Segmentation,
121}
122
123/// Enhancement techniques
124#[derive(Debug, Clone)]
125pub struct EnhancementTechnique {
126    pub technique_id: String,
127    pub technique_name: String,
128    pub technique_type: EnhancementTechniqueType,
129}
130
131/// Enhancement technique types
132#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub enum EnhancementTechniqueType {
134    ContrastEnhancement,
135    EdgeEnhancement,
136    Sharpening,
137    Filtering,
138}
139
140/// Image analysis
141pub struct ImageAnalysis {
142    analysis_algorithms: HashMap<String, AnalysisAlgorithm>,
143    detection_methods: HashMap<String, DetectionMethod>,
144}
145
146/// Analysis algorithms
147#[derive(Debug, Clone)]
148pub struct AnalysisAlgorithm {
149    pub algorithm_id: String,
150    pub algorithm_name: String,
151    pub algorithm_type: AnalysisAlgorithmType,
152}
153
154/// Analysis algorithm types
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
156pub enum AnalysisAlgorithmType {
157    PatternRecognition,
158    FeatureExtraction,
159    Classification,
160    Segmentation,
161}
162
163/// Detection methods
164#[derive(Debug, Clone)]
165pub struct DetectionMethod {
166    pub method_id: String,
167    pub method_name: String,
168    pub method_type: DetectionMethodType,
169}
170
171/// Detection method types
172#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub enum DetectionMethodType {
174    AnomalyDetection,
175    LesionDetection,
176    TumorDetection,
177    FractureDetection,
178}
179
180/// Image storage
181pub struct ImageStorage {
182    storage_systems: HashMap<String, StorageSystem>,
183    compression_methods: HashMap<String, CompressionMethod>,
184}
185
186/// Storage systems
187#[derive(Debug, Clone)]
188pub struct StorageSystem {
189    pub system_id: String,
190    pub system_name: String,
191    pub system_type: StorageSystemType,
192    pub capacity: u64,
193}
194
195/// Storage system types
196#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
197pub enum StorageSystemType {
198    Local,
199    Network,
200    Cloud,
201    Archive,
202}
203
204/// Compression methods
205#[derive(Debug, Clone)]
206pub struct CompressionMethod {
207    pub method_id: String,
208    pub method_name: String,
209    pub method_type: CompressionMethodType,
210}
211
212/// Compression method types
213#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
214pub enum CompressionMethodType {
215    Lossless,
216    Lossy,
217    Hybrid,
218}
219
220impl MedicalImaging {
221    pub fn new() -> Self {
222        Self {
223            image_acquisition: ImageAcquisition::new(),
224            image_processing: ImageProcessing::new(),
225            image_analysis: ImageAnalysis::new(),
226            image_storage: ImageStorage::new(),
227        }
228    }
229
230    pub fn initialize(&mut self) -> Result<(), MedicalError> {
231        self.image_acquisition.initialize()?;
232        self.image_processing.initialize()?;
233        self.image_analysis.initialize()?;
234        self.image_storage.initialize()?;
235        Ok(())
236    }
237
238    pub fn validate_image(&self, image: &MedicalImage) -> Result<(), MedicalError> {
239        if image.image_id.is_empty() {
240            return Err(MedicalError::ValidationError(
241                "Image ID cannot be empty".to_string(),
242            ));
243        }
244        Ok(())
245    }
246
247    /// Real 2-D DSP over a caller-provided intensity grid (delegates to
248    /// [`super::analyze_intensity_grid`]). Returns metrics + masks + Sobel map, each
249    /// honestly labeled as signal processing, never a diagnosis.
250    pub fn analyze_grid(
251        &self,
252        data: &[f64],
253        width: usize,
254        height: usize,
255        bins: usize,
256        threshold: super::SegmentationThreshold,
257        window: Option<(f64, f64)>,
258    ) -> Result<super::ImageAnalysisResult, MedicalError> {
259        super::analyze_intensity_grid(data, width, height, bins, threshold, window)
260    }
261
262    /// Process a `MedicalImage` by real DSP. The raw `image_data` bytes are decoded as
263    /// row-major grayscale intensities; the grid dimensions are inferred as a square
264    /// (`sqrt(len)`), since `MedicalImage` carries no width/height metadata. If the byte
265    /// count is not a perfect square this fails closed with `InsufficientData` rather than
266    /// guessing. The returned `ProcessedImage` carries the window/level-normalized bytes
267    /// plus honestly-labeled DSP metrics in `processing_metadata` — it is NOT a diagnosis.
268    pub fn process_image(
269        &mut self,
270        image: &MedicalImage,
271        processing_type: ImageProcessingType,
272    ) -> Result<ProcessedImage, MedicalError> {
273        let n = image.image_data.len();
274        if n == 0 {
275            return Err(MedicalError::ValidationError(
276                "process_image: image_data is empty".to_string(),
277            ));
278        }
279        let side = (n as f64).sqrt() as usize;
280        if side * side != n {
281            return Err(MedicalError::InsufficientData(format!(
282                "process_image: image_data length {n} is not a perfect square and MedicalImage \
283                 carries no width/height metadata; use analyze_grid(data,width,height,..) with \
284                 explicit dimensions"
285            )));
286        }
287        let data: Vec<f64> = image.image_data.iter().map(|&b| b as f64).collect();
288        let result = super::analyze_intensity_grid(
289            &data,
290            side,
291            side,
292            64,
293            super::SegmentationThreshold::Otsu,
294            None,
295        )?;
296
297        // Window/level-normalized bytes (real processed output, not the input echoed back).
298        let processed_data: Vec<u8> = result
299            .windowed
300            .iter()
301            .map(|&w| (w * 255.0).round().clamp(0.0, 255.0) as u8)
302            .collect();
303
304        let mut processing_metadata = HashMap::new();
305        processing_metadata.insert(
306            "epistemic_status".to_string(),
307            result.epistemic_status.to_string(),
308        );
309        processing_metadata.insert("width".to_string(), side.to_string());
310        processing_metadata.insert("height".to_string(), side.to_string());
311        processing_metadata.insert("min".to_string(), result.min.to_string());
312        processing_metadata.insert("max".to_string(), result.max.to_string());
313        processing_metadata.insert("mean".to_string(), result.mean.to_string());
314        processing_metadata.insert("std_dev".to_string(), result.std_dev.to_string());
315        processing_metadata.insert("otsu_threshold".to_string(), result.threshold.to_string());
316        processing_metadata.insert(
317            "segmented_area".to_string(),
318            result.segmented_area.to_string(),
319        );
320        processing_metadata.insert(
321            "segmented_mean_intensity".to_string(),
322            result.segmented_mean_intensity.to_string(),
323        );
324
325        Ok(ProcessedImage {
326            processed_image_id: format!("processed_{}", image.image_id),
327            original_image_id: image.image_id.clone(),
328            processing_type,
329            processed_data,
330            processing_metadata,
331        })
332    }
333}
334
335impl ImageAcquisition {
336    pub fn new() -> Self {
337        Self {
338            acquisition_protocols: HashMap::new(),
339            quality_control: QualityControl::new(),
340        }
341    }
342
343    pub fn initialize(&mut self) -> Result<(), MedicalError> {
344        Ok(())
345    }
346
347    pub fn add_acquisition_protocol(&mut self, protocol: AcquisitionProtocol) {
348        self.acquisition_protocols
349            .insert(protocol.protocol_id.clone(), protocol);
350    }
351
352    pub fn get_acquisition_protocol(&self, protocol_id: &str) -> Option<&AcquisitionProtocol> {
353        self.acquisition_protocols.get(protocol_id)
354    }
355
356    pub fn quality_control(&self) -> &QualityControl {
357        &self.quality_control
358    }
359}
360
361impl QualityControl {
362    pub fn new() -> Self {
363        Self {
364            quality_metrics: HashMap::new(),
365            quality_standards: HashMap::new(),
366        }
367    }
368
369    pub fn add_quality_metric(&mut self, metric: QualityMetric) {
370        self.quality_metrics
371            .insert(metric.metric_id.clone(), metric);
372    }
373
374    pub fn get_quality_metric(&self, metric_id: &str) -> Option<&QualityMetric> {
375        self.quality_metrics.get(metric_id)
376    }
377
378    pub fn add_quality_standard(&mut self, standard: QualityStandard) {
379        self.quality_standards
380            .insert(standard.standard_id.clone(), standard);
381    }
382
383    pub fn get_quality_standard(&self, standard_id: &str) -> Option<&QualityStandard> {
384        self.quality_standards.get(standard_id)
385    }
386}
387
388impl ImageProcessing {
389    pub fn new() -> Self {
390        Self {
391            preprocessing_algorithms: HashMap::new(),
392            enhancement_techniques: HashMap::new(),
393        }
394    }
395
396    pub fn initialize(&mut self) -> Result<(), MedicalError> {
397        Ok(())
398    }
399
400    pub fn add_preprocessing_algorithm(&mut self, algorithm: PreprocessingAlgorithm) {
401        self.preprocessing_algorithms
402            .insert(algorithm.algorithm_id.clone(), algorithm);
403    }
404
405    pub fn get_preprocessing_algorithm(
406        &self,
407        algorithm_id: &str,
408    ) -> Option<&PreprocessingAlgorithm> {
409        self.preprocessing_algorithms.get(algorithm_id)
410    }
411
412    pub fn add_enhancement_technique(&mut self, technique: EnhancementTechnique) {
413        self.enhancement_techniques
414            .insert(technique.technique_id.clone(), technique);
415    }
416
417    pub fn get_enhancement_technique(&self, technique_id: &str) -> Option<&EnhancementTechnique> {
418        self.enhancement_techniques.get(technique_id)
419    }
420}
421
422impl ImageAnalysis {
423    pub fn new() -> Self {
424        Self {
425            analysis_algorithms: HashMap::new(),
426            detection_methods: HashMap::new(),
427        }
428    }
429
430    pub fn initialize(&mut self) -> Result<(), MedicalError> {
431        Ok(())
432    }
433
434    pub fn add_analysis_algorithm(&mut self, algorithm: AnalysisAlgorithm) {
435        self.analysis_algorithms
436            .insert(algorithm.algorithm_id.clone(), algorithm);
437    }
438
439    pub fn get_analysis_algorithm(&self, algorithm_id: &str) -> Option<&AnalysisAlgorithm> {
440        self.analysis_algorithms.get(algorithm_id)
441    }
442
443    pub fn add_detection_method(&mut self, method: DetectionMethod) {
444        self.detection_methods
445            .insert(method.method_id.clone(), method);
446    }
447
448    pub fn get_detection_method(&self, method_id: &str) -> Option<&DetectionMethod> {
449        self.detection_methods.get(method_id)
450    }
451}
452
453impl ImageStorage {
454    pub fn new() -> Self {
455        Self {
456            storage_systems: HashMap::new(),
457            compression_methods: HashMap::new(),
458        }
459    }
460
461    pub fn initialize(&mut self) -> Result<(), MedicalError> {
462        Ok(())
463    }
464
465    pub fn add_storage_system(&mut self, system: StorageSystem) {
466        self.storage_systems
467            .insert(system.system_id.clone(), system);
468    }
469
470    pub fn get_storage_system(&self, system_id: &str) -> Option<&StorageSystem> {
471        self.storage_systems.get(system_id)
472    }
473
474    pub fn add_compression_method(&mut self, method: CompressionMethod) {
475        self.compression_methods
476            .insert(method.method_id.clone(), method);
477    }
478
479    pub fn get_compression_method(&self, method_id: &str) -> Option<&CompressionMethod> {
480        self.compression_methods.get(method_id)
481    }
482}