1use super::*;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5pub struct MedicalImaging {
7 image_acquisition: ImageAcquisition,
8 image_processing: ImageProcessing,
9 image_analysis: ImageAnalysis,
10 image_storage: ImageStorage,
11}
12
13pub struct ImageAcquisition {
15 acquisition_protocols: HashMap<String, AcquisitionProtocol>,
16 quality_control: QualityControl,
17}
18
19#[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#[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#[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
49pub struct QualityControl {
51 quality_metrics: HashMap<String, QualityMetric>,
52 quality_standards: HashMap<String, QualityStandard>,
53}
54
55#[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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub enum QualityMetricType {
67 SignalToNoise,
68 Contrast,
69 Resolution,
70 ArtifactLevel,
71}
72
73#[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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84pub enum QualityStandardType {
85 ACR,
86 FDA,
87 CE,
88 ISO,
89}
90
91#[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
100pub struct ImageProcessing {
102 preprocessing_algorithms: HashMap<String, PreprocessingAlgorithm>,
103 enhancement_techniques: HashMap<String, EnhancementTechnique>,
104}
105
106#[derive(Debug, Clone)]
108pub struct PreprocessingAlgorithm {
109 pub algorithm_id: String,
110 pub algorithm_name: String,
111 pub algorithm_type: PreprocessingAlgorithmType,
112}
113
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116pub enum PreprocessingAlgorithmType {
117 NoiseReduction,
118 Normalization,
119 Registration,
120 Segmentation,
121}
122
123#[derive(Debug, Clone)]
125pub struct EnhancementTechnique {
126 pub technique_id: String,
127 pub technique_name: String,
128 pub technique_type: EnhancementTechniqueType,
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub enum EnhancementTechniqueType {
134 ContrastEnhancement,
135 EdgeEnhancement,
136 Sharpening,
137 Filtering,
138}
139
140pub struct ImageAnalysis {
142 analysis_algorithms: HashMap<String, AnalysisAlgorithm>,
143 detection_methods: HashMap<String, DetectionMethod>,
144}
145
146#[derive(Debug, Clone)]
148pub struct AnalysisAlgorithm {
149 pub algorithm_id: String,
150 pub algorithm_name: String,
151 pub algorithm_type: AnalysisAlgorithmType,
152}
153
154#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
156pub enum AnalysisAlgorithmType {
157 PatternRecognition,
158 FeatureExtraction,
159 Classification,
160 Segmentation,
161}
162
163#[derive(Debug, Clone)]
165pub struct DetectionMethod {
166 pub method_id: String,
167 pub method_name: String,
168 pub method_type: DetectionMethodType,
169}
170
171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub enum DetectionMethodType {
174 AnomalyDetection,
175 LesionDetection,
176 TumorDetection,
177 FractureDetection,
178}
179
180pub struct ImageStorage {
182 storage_systems: HashMap<String, StorageSystem>,
183 compression_methods: HashMap<String, CompressionMethod>,
184}
185
186#[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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
197pub enum StorageSystemType {
198 Local,
199 Network,
200 Cloud,
201 Archive,
202}
203
204#[derive(Debug, Clone)]
206pub struct CompressionMethod {
207 pub method_id: String,
208 pub method_name: String,
209 pub method_type: CompressionMethodType,
210}
211
212#[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 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 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 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}