1use super::*;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5pub struct ClinicalAnalyzer {
7 diagnostic_engine: DiagnosticEngine,
8 risk_assessment: ClinicalRiskAssessment,
9 treatment_planner: TreatmentPlanner,
10 outcome_predictor: OutcomePredictor,
11}
12
13pub struct DiagnosticEngine {
15 diagnostic_algorithms: HashMap<String, DiagnosticAlgorithm>,
16 symptom_analyzer: SymptomAnalyzer,
17 lab_interpreter: LabInterpreter,
18}
19
20#[derive(Debug, Clone)]
22pub struct DiagnosticAlgorithm {
23 pub algorithm_id: String,
24 pub algorithm_name: String,
25 pub algorithm_type: DiagnosticAlgorithmType,
26 pub accuracy: f64,
27}
28
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
31pub enum DiagnosticAlgorithmType {
32 RuleBased,
33 MachineLearning,
34 Bayesian,
35 NeuralNetwork,
36}
37
38pub struct SymptomAnalyzer {
40 symptom_patterns: HashMap<String, SymptomPattern>,
41 symptom_correlations: HashMap<String, SymptomCorrelation>,
42}
43
44#[derive(Debug, Clone)]
46pub struct SymptomPattern {
47 pub pattern_id: String,
48 pub pattern_name: String,
49 pub symptoms: Vec<String>,
50 pub associated_conditions: Vec<String>,
51}
52
53#[derive(Debug, Clone)]
55pub struct SymptomCorrelation {
56 pub correlation_id: String,
57 pub symptom1: String,
58 pub symptom2: String,
59 pub correlation_coefficient: f64,
60}
61
62pub struct LabInterpreter {
64 reference_ranges: HashMap<String, ReferenceRange>,
65 abnormality_detector: AbnormalityDetector,
66}
67
68#[derive(Debug, Clone)]
70pub struct AbnormalityDetector {
71 detection_algorithms: HashMap<String, DetectionAlgorithm>,
72 severity_assessment: SeverityAssessment,
73}
74
75#[derive(Debug, Clone)]
77pub struct SeverityAssessment {
78 assessment_criteria: HashMap<String, AssessmentCriterion>,
79 scoring_system: ScoringSystem,
80}
81
82#[derive(Debug, Clone)]
84pub struct AssessmentCriterion {
85 pub criterion_id: String,
86 pub criterion_name: String,
87 pub weight: f64,
88 pub threshold: f64,
89}
90
91#[derive(Debug, Clone)]
93pub struct ScoringSystem {
94 pub system_id: String,
95 pub system_name: String,
96 pub scoring_algorithm: ScoringAlgorithm,
97}
98
99#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
101pub enum ScoringAlgorithm {
102 WeightedSum,
103 Bayesian,
104 FuzzyLogic,
105 NeuralNetwork,
106}
107
108pub struct ClinicalRiskAssessment {
110 risk_models: HashMap<String, ClinicalRiskModel>,
111 risk_factors: HashMap<String, ClinicalRiskFactor>,
112}
113
114#[derive(Debug, Clone)]
116pub struct ClinicalRiskModel {
117 pub model_id: String,
118 pub model_name: String,
119 pub model_type: ClinicalRiskModelType,
120 pub validation_results: ValidationResults,
121}
122
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
125pub enum ClinicalRiskModelType {
126 Cardiovascular,
127 Cancer,
128 Diabetes,
129 Respiratory,
130 Custom(String),
131}
132
133#[derive(Debug, Clone)]
135pub struct ValidationResults {
136 pub accuracy: f64,
137 pub sensitivity: f64,
138 pub specificity: f64,
139 pub auc: f64,
140}
141
142#[derive(Debug, Clone)]
144pub struct ClinicalRiskFactor {
145 pub factor_id: String,
146 pub factor_name: String,
147 pub factor_category: FactorCategory,
148 pub factor_weight: f64,
149}
150
151#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
153pub enum FactorCategory {
154 Demographic,
155 Lifestyle,
156 Medical,
157 Genetic,
158 Environmental,
159}
160
161pub struct TreatmentPlanner {
163 treatment_guidelines: HashMap<String, TreatmentGuideline>,
164 decision_support: DecisionSupport,
165}
166
167#[derive(Debug, Clone)]
169pub struct TreatmentGuideline {
170 pub guideline_id: String,
171 pub guideline_name: String,
172 pub guideline_type: GuidelineType,
173 pub recommendations: Vec<TreatmentRecommendation>,
174}
175
176#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
178pub enum GuidelineType {
179 Clinical,
180 Protocol,
181 StandardOfCare,
182 BestPractice,
183}
184
185#[derive(Debug, Clone)]
187pub struct TreatmentRecommendation {
188 pub recommendation_id: String,
189 pub condition: String,
190 pub treatment: String,
191 pub evidence_level: EvidenceLevel,
192 pub strength: RecommendationStrength,
193}
194
195#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
197pub enum EvidenceLevel {
198 LevelA,
199 LevelB,
200 LevelC,
201 ExpertOpinion,
202}
203
204#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
206pub enum RecommendationStrength {
207 Strong,
208 Moderate,
209 Weak,
210 ExpertConsensus,
211}
212
213pub struct DecisionSupport {
215 decision_trees: HashMap<String, DecisionTree>,
216 scoring_systems: HashMap<String, ScoringSystem>,
217}
218
219#[derive(Debug, Clone)]
221pub struct DecisionTree {
222 pub tree_id: String,
223 pub tree_name: String,
224 pub root_node: DecisionNode,
225}
226
227#[derive(Debug, Clone)]
229pub struct DecisionNode {
230 pub node_id: String,
231 pub node_type: NodeType,
232 pub condition: Option<String>,
233 pub threshold: Option<f64>,
234 pub children: Vec<DecisionNode>,
235 pub outcome: Option<String>,
236}
237
238#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
240pub enum NodeType {
241 Root,
242 Decision,
243 Leaf,
244}
245
246pub struct OutcomePredictor {
248 prediction_models: HashMap<String, PredictionModel>,
249 outcome_metrics: HashMap<String, OutcomeMetric>,
250}
251
252#[derive(Debug, Clone)]
254pub struct PredictionModel {
255 pub model_id: String,
256 pub model_name: String,
257 pub model_type: PredictionModelType,
258 pub performance_metrics: ModelPerformanceMetrics,
259}
260
261#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
263pub enum PredictionModelType {
264 Survival,
265 Response,
266 Recurrence,
267 Complication,
268}
269
270#[derive(Debug, Clone)]
272pub struct ModelPerformanceMetrics {
273 pub accuracy: f64,
274 pub precision: f64,
275 pub recall: f64,
276 pub f1_score: f64,
277}
278
279#[derive(Debug, Clone)]
281pub struct OutcomeMetric {
282 pub metric_id: String,
283 pub metric_name: String,
284 pub metric_type: OutcomeMetricType,
285 pub measurement_method: MeasurementMethod,
286}
287
288#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
290pub enum OutcomeMetricType {
291 Mortality,
292 Morbidity,
293 QualityOfLife,
294 FunctionalStatus,
295}
296
297#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
299pub enum MeasurementMethod {
300 Scale,
301 Binary,
302 Continuous,
303 Categorical,
304}
305impl ClinicalAnalyzer {
306 pub fn new() -> Self {
307 Self {
308 diagnostic_engine: DiagnosticEngine::new(),
309 risk_assessment: ClinicalRiskAssessment::new(),
310 treatment_planner: TreatmentPlanner::new(),
311 outcome_predictor: OutcomePredictor::new(),
312 }
313 }
314
315 pub fn initialize(&mut self) -> Result<(), MedicalError> {
316 self.diagnostic_engine.initialize()?;
317 self.risk_assessment.initialize()?;
318 self.treatment_planner.initialize()?;
319 self.outcome_predictor.initialize()?;
320 Ok(())
321 }
322
323 pub fn analyze_data(
330 &mut self,
331 _patient: &Patient,
332 _data_type: ClinicalDataType,
333 ) -> Result<ClinicalAnalysis, MedicalError> {
334 Err(MedicalError::InsufficientData(
335 "clinical diagnostic analysis (analyze_clinical_data): no knowledge base was \
336 supplied through the patient-only path. Use analyze_differential(findings, \
337 knowledge_base) with a caller-supplied, non-authoritative KB to obtain a ranked \
338 epistemic proposal. Refusing to emit a fabricated diagnosis or confidence."
339 .to_string(),
340 ))
341 }
342
343 pub fn analyze_differential(
348 &self,
349 observed_findings: &[String],
350 kb: &super::DiagnosticKnowledgeBase,
351 ) -> Result<super::DifferentialProposal, MedicalError> {
352 super::analyze_differential(observed_findings, kb)
353 }
354}
355
356impl DiagnosticEngine {
357 pub fn new() -> Self {
358 Self {
359 diagnostic_algorithms: HashMap::new(),
360 symptom_analyzer: SymptomAnalyzer::new(),
361 lab_interpreter: LabInterpreter::new(),
362 }
363 }
364
365 pub fn initialize(&mut self) -> Result<(), MedicalError> {
366 Ok(())
367 }
368
369 pub fn add_diagnostic_algorithm(&mut self, algorithm: DiagnosticAlgorithm) {
370 self.diagnostic_algorithms
371 .insert(algorithm.algorithm_id.clone(), algorithm);
372 }
373
374 pub fn get_diagnostic_algorithm(&self, algorithm_id: &str) -> Option<&DiagnosticAlgorithm> {
375 self.diagnostic_algorithms.get(algorithm_id)
376 }
377
378 pub fn symptom_analyzer(&self) -> &SymptomAnalyzer {
379 &self.symptom_analyzer
380 }
381
382 pub fn lab_interpreter(&self) -> &LabInterpreter {
383 &self.lab_interpreter
384 }
385}
386
387impl SymptomAnalyzer {
388 pub fn new() -> Self {
389 Self {
390 symptom_patterns: HashMap::new(),
391 symptom_correlations: HashMap::new(),
392 }
393 }
394
395 pub fn add_symptom_pattern(&mut self, pattern: SymptomPattern) {
396 self.symptom_patterns
397 .insert(pattern.pattern_id.clone(), pattern);
398 }
399
400 pub fn get_symptom_pattern(&self, pattern_id: &str) -> Option<&SymptomPattern> {
401 self.symptom_patterns.get(pattern_id)
402 }
403
404 pub fn add_symptom_correlation(&mut self, correlation: SymptomCorrelation) {
405 self.symptom_correlations
406 .insert(correlation.correlation_id.clone(), correlation);
407 }
408
409 pub fn get_symptom_correlation(&self, correlation_id: &str) -> Option<&SymptomCorrelation> {
410 self.symptom_correlations.get(correlation_id)
411 }
412}
413
414impl LabInterpreter {
415 pub fn new() -> Self {
416 Self {
417 reference_ranges: HashMap::new(),
418 abnormality_detector: AbnormalityDetector::new(),
419 }
420 }
421
422 pub fn add_reference_range(&mut self, test_code: &str, range: ReferenceRange) {
423 self.reference_ranges.insert(test_code.to_string(), range);
424 }
425
426 pub fn get_reference_range(&self, test_code: &str) -> Option<&ReferenceRange> {
427 self.reference_ranges.get(test_code)
428 }
429
430 pub fn abnormality_detector(&self) -> &AbnormalityDetector {
431 &self.abnormality_detector
432 }
433
434 pub fn interpret_result(&self, result: &LabResult) -> ResultStatus {
435 if let Some(range) = self.reference_ranges.get(&result.test_code) {
436 if result.value < range.minimum || result.value > range.maximum {
437 ResultStatus::Abnormal
438 } else {
439 ResultStatus::Normal
440 }
441 } else {
442 result.status.clone()
443 }
444 }
445}
446
447impl AbnormalityDetector {
448 pub fn new() -> Self {
449 Self {
450 detection_algorithms: HashMap::new(),
451 severity_assessment: SeverityAssessment::new(),
452 }
453 }
454
455 pub fn add_detection_algorithm(&mut self, algorithm: DetectionAlgorithm) {
456 self.detection_algorithms
457 .insert(algorithm.algorithm_id.clone(), algorithm);
458 }
459
460 pub fn get_detection_algorithm(&self, algorithm_id: &str) -> Option<&DetectionAlgorithm> {
461 self.detection_algorithms.get(algorithm_id)
462 }
463
464 pub fn severity_assessment(&self) -> &SeverityAssessment {
465 &self.severity_assessment
466 }
467}
468
469impl SeverityAssessment {
470 pub fn new() -> Self {
471 Self {
472 assessment_criteria: HashMap::new(),
473 scoring_system: ScoringSystem::new(),
474 }
475 }
476
477 pub fn add_criterion(&mut self, criterion: AssessmentCriterion) {
478 self.assessment_criteria
479 .insert(criterion.criterion_id.clone(), criterion);
480 }
481
482 pub fn get_criterion(&self, criterion_id: &str) -> Option<&AssessmentCriterion> {
483 self.assessment_criteria.get(criterion_id)
484 }
485
486 pub fn scoring_system(&self) -> &ScoringSystem {
487 &self.scoring_system
488 }
489}
490
491impl ScoringSystem {
492 pub fn new() -> Self {
493 Self {
494 system_id: "system_1".to_string(),
495 system_name: "Clinical Scoring System".to_string(),
496 scoring_algorithm: ScoringAlgorithm::WeightedSum,
497 }
498 }
499}
500
501impl ClinicalRiskAssessment {
502 pub fn new() -> Self {
503 Self {
504 risk_models: HashMap::new(),
505 risk_factors: HashMap::new(),
506 }
507 }
508
509 pub fn initialize(&mut self) -> Result<(), MedicalError> {
510 Ok(())
511 }
512
513 pub fn add_risk_model(&mut self, model: ClinicalRiskModel) {
514 self.risk_models.insert(model.model_id.clone(), model);
515 }
516
517 pub fn get_risk_model(&self, model_id: &str) -> Option<&ClinicalRiskModel> {
518 self.risk_models.get(model_id)
519 }
520
521 pub fn add_risk_factor(&mut self, factor: ClinicalRiskFactor) {
522 self.risk_factors.insert(factor.factor_id.clone(), factor);
523 }
524
525 pub fn get_risk_factor(&self, factor_id: &str) -> Option<&ClinicalRiskFactor> {
526 self.risk_factors.get(factor_id)
527 }
528
529 pub fn compute_risk_score(&self, factor_ids: &[String]) -> f64 {
530 if factor_ids.is_empty() {
531 return 0.0;
532 }
533 let total_weight: f64 = factor_ids
534 .iter()
535 .filter_map(|id| self.risk_factors.get(id))
536 .map(|f| f.factor_weight)
537 .sum();
538 total_weight / factor_ids.len() as f64
539 }
540}
541
542impl TreatmentPlanner {
543 pub fn new() -> Self {
544 Self {
545 treatment_guidelines: HashMap::new(),
546 decision_support: DecisionSupport::new(),
547 }
548 }
549
550 pub fn initialize(&mut self) -> Result<(), MedicalError> {
551 Ok(())
552 }
553
554 pub fn add_treatment_guideline(&mut self, guideline: TreatmentGuideline) {
555 self.treatment_guidelines
556 .insert(guideline.guideline_id.clone(), guideline);
557 }
558
559 pub fn get_treatment_guideline(&self, guideline_id: &str) -> Option<&TreatmentGuideline> {
560 self.treatment_guidelines.get(guideline_id)
561 }
562
563 pub fn decision_support(&self) -> &DecisionSupport {
564 &self.decision_support
565 }
566}
567
568impl DecisionSupport {
569 pub fn new() -> Self {
570 Self {
571 decision_trees: HashMap::new(),
572 scoring_systems: HashMap::new(),
573 }
574 }
575
576 pub fn add_decision_tree(&mut self, tree: DecisionTree) {
577 self.decision_trees.insert(tree.tree_id.clone(), tree);
578 }
579
580 pub fn get_decision_tree(&self, tree_id: &str) -> Option<&DecisionTree> {
581 self.decision_trees.get(tree_id)
582 }
583
584 pub fn add_scoring_system(&mut self, system: ScoringSystem) {
585 self.scoring_systems
586 .insert(system.system_id.clone(), system);
587 }
588
589 pub fn get_scoring_system(&self, system_id: &str) -> Option<&ScoringSystem> {
590 self.scoring_systems.get(system_id)
591 }
592}
593
594impl OutcomePredictor {
595 pub fn new() -> Self {
596 Self {
597 prediction_models: HashMap::new(),
598 outcome_metrics: HashMap::new(),
599 }
600 }
601
602 pub fn initialize(&mut self) -> Result<(), MedicalError> {
603 Ok(())
604 }
605
606 pub fn add_prediction_model(&mut self, model_id: &str, model: PredictionModel) {
607 self.prediction_models.insert(model_id.to_string(), model);
608 }
609
610 pub fn get_prediction_model(&self, model_id: &str) -> Option<&PredictionModel> {
611 self.prediction_models.get(model_id)
612 }
613
614 pub fn add_outcome_metric(&mut self, metric_id: &str, value: OutcomeMetric) {
615 self.outcome_metrics.insert(metric_id.to_string(), value);
616 }
617
618 pub fn get_outcome_metric(&self, metric_id: &str) -> Option<&OutcomeMetric> {
619 self.outcome_metrics.get(metric_id)
620 }
621}