TrackChain / ml /scripts /final_demo.py
PRiyanshu0-1's picture
Add ml/ codebase and configs
2adb41a verified
Raw History Blame Contribute Delete
5.48 kB
"""
ml/scripts/final_demo.py
TrackChain Capstone End-to-End Demo Walkthrough (Phase 2.7 tc.v1 SOTA).
Demonstrates the full 5-model multi-modal intelligence stack running in real-time across a 100-meter railway inspection run.
"""
import sys
import time
import json
from pathlib import Path
import numpy as np
# Add repo root to path
repo_root = Path(__file__).resolve().parent.parent.parent
if str(repo_root) not in sys.path:
sys.path.insert(0, str(repo_root))
from ml.core.schema import (
TrackSegment,
DecisionType,
SeverityLevel,
SignalType,
DefectClass,
)
from ml.inference.pipeline import TrackChainMLPipeline
from ml.fusion.rules import TrackChainFusionEngine
def run_capstone_demo(n_segments: int = 5):
print("=" * 80)
print("🚂 TrackChain Multi-Modal Edge Intelligence Stack — Live Capstone Demo")
print(" Architecture: 5-Model Triad (YOLOv8 + PatchCore + EN13848 + Bi-LSTM + Seq-VAE)")
print(" Contract: tc.v1 Unified [0.0, 1.0] Calibration & Cross-Modal Rule Engine")
print("=" * 80)
print("\n[1/4] Initializing ML Pipeline and loading models...")
start_init = time.time()
pipeline = TrackChainMLPipeline(
fusion_engine=TrackChainFusionEngine(persistence_window=2, known_threshold=0.50, novel_threshold=0.50),
conditional_typing=False,
)
print(f" Pipeline initialized in {(time.time() - start_init):.2f}s")
print("\n[2/4] Generating synthetic 100m railway inspection run (5 segments)...")
segments = []
scenarios = [
("Clean Track", False, 0.0, "mainline_standard"),
("Missing Fastener (Visual Known)", True, 0.0, "mainline_standard"),
("Clean Track (Post-Repair)", False, 0.0, "mainline_standard"),
("Track Twist Exceedance (Geometry Known)", False, 9.5, "mainline_standard"),
("Compound Defect: Crack + Gauge Spread (Dual Stream)", True, 14.0, "mainline_high_speed"),
]
for idx, (scenario_name, has_visual_defect, vert_dip_mm, sec_type) in enumerate(scenarios):
start_m = idx * 20.0
end_m = (idx + 1) * 20.0
n_bins = 80
# Frame
frame = np.zeros((480, 640, 3), dtype=np.uint8)
frame[200:280, :] = 120
if has_visual_defect:
frame[220:260, 300:340] = 255 # Defect
# Telemetry
vertical = np.random.normal(0.0, 0.2, n_bins)
if vert_dip_mm > 0:
vertical[30:50] = vert_dip_mm
gauge = np.full(n_bins, 1676.0)
if idx == 4:
gauge[35:45] = 1684.0 # Gauge widening +8mm
telemetry = {
"roll_rad": np.zeros(n_bins),
"lateral_pos_mm": np.random.normal(0.0, 0.3, n_bins),
"vertical_pos_mm": vertical,
"gauge_mm": gauge,
}
seg = TrackSegment(
segment_id=f"seg-{int(start_m):04d}-{int(end_m):04d}",
chainage_start_m=start_m,
chainage_end_m=end_m,
frames=[frame],
telemetry=telemetry,
section_type=sec_type,
)
segments.append((scenario_name, seg))
print(f" Created {len(segments)} test segments.")
print("\n[3/4] Processing live inspection stream across all 5 models & fusion...")
print("-" * 80)
print(f"{'Chainage (m)':<15} | {'Scenario':<25} | {'Decision':<14} | {'Severity':<9} | {'Latency':<8}")
print("-" * 80)
demo_results = []
total_time = 0.0
for scenario_name, seg in segments:
t0 = time.perf_counter()
decision, signals = pipeline.process_segment(seg)
dt_ms = (time.perf_counter() - t0) * 1000.0
total_time += dt_ms
chainage_str = f"{seg.chainage_start_m:.1f}m - {seg.chainage_end_m:.1f}m"
print(f"{chainage_str:<15} | {scenario_name:<25} | {decision.decision.value:<14} | {decision.severity.value:<9} | {dt_ms:>5.1f} ms")
prim_def = decision.primary_defect
prim_def_str = prim_def.value if hasattr(prim_def, "value") else str(prim_def or "none")
demo_results.append({
"chainage": chainage_str,
"scenario": scenario_name,
"decision": decision.decision.value if hasattr(decision.decision, "value") else str(decision.decision),
"severity": decision.severity.value if hasattr(decision.severity, "value") else str(decision.severity),
"confidence": round(float(decision.confidence), 4),
"primary_defect": prim_def_str,
"action": getattr(decision, "action", "Routine inspection cycle maintained."),
"latency_ms": round(dt_ms, 2),
})
avg_ms = total_time / len(segments)
fps = 1000.0 / avg_ms if avg_ms > 0 else 0.0
print("-" * 80)
print(f"[4/4] Demo Summary: Average Pipeline Latency = {avg_ms:.1f} ms ({fps:.1f} FPS, Target >= 15 FPS)")
print("=" * 80)
# Save summary
out_dir = repo_root / "artifacts"
out_dir.mkdir(parents=True, exist_ok=True)
summary_path = out_dir / "demo_run_summary.json"
with open(summary_path, "w", encoding="utf-8") as f:
json.dump({
"schema_version": "tc.v1",
"average_latency_ms": round(avg_ms, 2),
"fps": round(fps, 1),
"segments": demo_results,
"status": "PASSED",
}, f, indent=2)
print(f"\n[OK] Capstone Demo completed successfully. Report saved to: {summary_path}")
return 0
if __name__ == "__main__":
sys.exit(run_capstone_demo())