Files
rustytorch/crates/specialized/rtx-digital-twin/examples/liver_ablation_planning.rs
T
2026-03-04 00:08:42 +00:00

219 lines
7.4 KiB
Rust

//! # Liver Tumor Ablation Planning Example
//!
//! This example demonstrates using the Medical Digital Twin Platform to plan
//! radiofrequency ablation (RFA) treatment for a liver tumor.
//!
//! ## Workflow
//! 1. Create patient-specific liver geometry with tumor
//! 2. Create digital twin
//! 3. Run baseline simulation (no treatment)
//! 4. Plan RFA intervention
//! 5. Perform what-if analysis for different ablation parameters
//! 6. Select optimal treatment strategy
//!
//! ## Run
//! ```bash
//! cargo run --example liver_ablation_planning
//! ```
use rtx_digital_twin::{
AblationProbe, DigitalTwin, InterventionType, OrganGeometry, TissueLabel, TissueType,
};
fn main() {
println!("======================================");
println!(" Liver Tumor Ablation Planning");
println!("======================================\n");
// Step 1: Create patient-specific geometry
println!("[Step 1] Creating patient-specific liver geometry...");
let shape = [60, 60, 60];
let spacing = [1.0, 1.0, 1.0]; // 1mm voxel resolution
let n = shape[0] * shape[1] * shape[2];
let mut labels = vec![0u8; n]; // Start with air
// Create liver parenchyma (realistic organ shape)
for z in 10..50 {
for y in 10..50 {
for x in 10..50 {
// Ellipsoidal liver shape
let dx = (x as f32 - 30.0) / 20.0;
let dy = (y as f32 - 30.0) / 20.0;
let dz = (z as f32 - 30.0) / 20.0;
let dist = dx * dx + dy * dy + dz * dz;
if dist <= 1.0 {
let idx = z * shape[0] * shape[1] + y * shape[0] + x;
labels[idx] = TissueType::Liver.label();
}
}
}
}
// Add tumor (3cm diameter at specific location)
let tumor_center = [35, 30, 30];
let tumor_radius = 8; // 8mm radius = 16mm diameter
for z in 0..shape[2] {
for y in 0..shape[1] {
for x in 0..shape[0] {
let dx = x as i32 - tumor_center[0] as i32;
let dy = y as i32 - tumor_center[1] as i32;
let dz = z as i32 - tumor_center[2] as i32;
let dist_sq = dx * dx + dy * dy + dz * dz;
if dist_sq <= tumor_radius * tumor_radius {
let idx = z * shape[0] * shape[1] + y * shape[0] + x;
if labels[idx] != 0 {
// Only replace liver, not air
labels[idx] = TissueType::Tumor.label();
}
}
}
}
}
let geometry =
OrganGeometry::from_labels(&labels, shape, spacing).expect("Failed to create geometry");
// Print geometry statistics
let histogram = geometry.tissue_histogram();
let liver_voxels = histogram.get(&TissueType::Liver).unwrap_or(&0);
let tumor_voxels = histogram.get(&TissueType::Tumor).unwrap_or(&0);
println!(" - Grid size: {}x{}x{}", shape[0], shape[1], shape[2]);
println!(" - Resolution: {:.1} mm", spacing[0]);
println!(
" - Liver volume: ~{:.1} cm³",
*liver_voxels as f32 / 1000.0
);
println!(
" - Tumor volume: ~{:.1} cm³",
*tumor_voxels as f32 / 1000.0
);
println!();
// Step 2: Create digital twin
println!("[Step 2] Initializing digital twin...");
let mut twin = DigitalTwin::new(geometry);
let summary = twin.geometry_summary();
println!(" - Total voxels: {}", summary.total_voxels);
println!(" - Tissue voxels: {}", summary.tissue_voxels);
println!(
" - Physical size: {:.1}x{:.1}x{:.1} mm",
summary.dimensions[0], summary.dimensions[1], summary.dimensions[2]
);
println!();
// Step 3: Baseline simulation
println!("[Step 3] Running baseline simulation (no treatment)...");
let baseline = twin
.simulate_baseline()
.expect("Baseline simulation failed");
println!(" - Iterations: {}", baseline.iterations);
println!(" - Max temperature: {:.1}°C", baseline.max_temperature);
println!(" - Residual: {:.2e}", baseline.residual);
println!();
// Step 4: Plan RFA intervention
println!("[Step 4] Planning RFA intervention...");
println!(
" Target: Tumor center at ({}, {}, {})",
tumor_center[0], tumor_center[1], tumor_center[2]
);
println!();
// Step 5: What-if analysis for different power settings
println!("[Step 5] What-if analysis: Comparing ablation strategies");
println!(" Testing different power levels...\n");
let power_levels = vec![30.0, 50.0, 70.0];
let mut best_strategy = None;
let mut best_score = f32::NEG_INFINITY;
for (i, &power) in power_levels.iter().enumerate() {
println!(" Scenario {}: {} W, 10 minutes", i + 1, power);
// Reset between scenarios
twin.reset_temperature();
// Create probe
let probe = AblationProbe::new(
[
tumor_center[0] as f32,
tumor_center[1] as f32,
tumor_center[2] as f32,
],
power,
)
.with_type(InterventionType::RadiofrequencyAblation)
.with_active_length(20.0) // 2cm active tip
.with_diameter(3.0); // 3mm diameter
// Run what-if analysis (10 minutes = 600 seconds)
let result = twin
.what_if(&probe, 600.0)
.expect("What-if analysis failed");
println!(" Max temp: {:.1}°C", result.max_temperature);
println!(
" Damaged volume: {:.1} mm³ ({:.2} cm³)",
result.total_damaged_volume,
result.total_damaged_volume / 1000.0
);
println!(" Severe damage: {:.1} mm³", result.severe_damage_volume);
println!(
" Safety OK: {}",
if result.safety_margin_ok { "Yes" } else { "NO" }
);
println!(" Iterations: {}", result.iterations);
// Simple scoring: want sufficient ablation but safe boundaries
let tumor_volume_mm3 = *tumor_voxels as f32;
let coverage = result.total_damaged_volume / tumor_volume_mm3;
let safety_score = if result.safety_margin_ok { 1.0 } else { 0.0 };
let score = coverage * 0.7 + safety_score * 0.3;
println!(" Coverage: {:.1}%", coverage * 100.0);
println!(" Score: {:.3}", score);
println!();
if score > best_score {
best_score = score;
best_strategy = Some((i + 1, power, result));
}
}
// Step 6: Recommend optimal strategy
println!("[Step 6] Treatment Recommendation");
if let Some((scenario, power, result)) = best_strategy {
println!(" Recommended: Scenario {} ({} W)", scenario, power);
println!(" Expected outcomes:");
println!(" - Max temperature: {:.1}°C", result.max_temperature);
println!(
" - Ablation volume: {:.1} cm³",
result.total_damaged_volume / 1000.0
);
println!(
" - Safety margin: {}",
if result.safety_margin_ok {
"Adequate"
} else {
"Review required"
}
);
println!();
// Generate clinical report
println!(" Clinical Report:");
println!("{}", result.report());
}
println!("======================================");
println!(" Analysis Complete");
println!("======================================");
}