# Impakt -- Project Status **Date:** 2026-04-10 **Version:** 0.1.0 **Tests:** 181 passing **Source:** ~11,000 lines (py+js+css+html) | ~2,150 lines tests **Tooling:** uv (Python 3.12.12), hatchling build backend --- ## Quick Start ```bash cd /Users/noise/Code/impakt uv sync --dev # install all dependencies uv run pytest tests/ # run all 181 tests uv run impakt info tests/mme_data/3239 # show test metadata uv run impakt serve tests/mme_data/3239 # launch web UI on :8050 ``` Scripting: ```python from impakt import Session s = Session.open("tests/mme_data/3239") s.plot("11HEAD0000H3ACXP", "11HEAD0000H3ACYP", "11HEAD0000H3ACZP", cfc=1000) ``` --- ## Repository Layout ``` impakt/ pyproject.toml # PEP 621 + uv dependency-groups uv.lock # lockfile .gitignore README.md # Architecture docs with 16 Mermaid diagrams BRAINSTORM.md # 80+ feature ideas docs/ STATUS.md # <-- you are here src/impakt/ __init__.py # exports Session, Template channel/ # Data model layer code.py # ISO channel code parser (14-char + 16-char auto-detect) model.py # Channel, ChannelGroup, TestData, TestMetadata group.py # Auto-grouping utilities lookup.py # ISO naming lookup tables (150+ entries) io/ # I/O layer reader.py # ReaderProtocol, ReaderRegistry mme.py # MMEReader (real ISO 13499 + synthetic INI) transform/ # Signal processing base.py # Transform protocol, TransformChain cfc.py # SAE J211 CFC filter (60/180/600/1000) align.py # X-align (time-zero), Y-align (offset) resultant.py # Vector magnitude from X/Y/Z math_expr.py # Free-form math expressions resample.py # Trim, Resample criteria/ # Injury criteria base.py # CriterionResult, InjuryCriterion protocol hic.py # HIC15, HIC36 clip3ms.py # 3ms chest clip nij.py # Nij (4 modes, per-dummy intercepts) chest.py # Chest deflection, Viscous criterion femur.py # Femur load tibia.py # Tibia index protocol/ # Rating protocols base.py # ProtocolResult, BodyRegionScore, Color, Rating euro_ncap.py # Euro NCAP (color/points/stars, versioned) us_ncap.py # US NCAP (injury probability/stars) iihs.py # IIHS (G/A/M/P) plot/ # Visualization engine engine.py # PlotEngine (Plotly), cursor_values() spec.py # PlotSpec, ChannelRef, Corridor, CursorValues cursor.py # Dual X-cursor logic export.py # PNG/SVG/PDF/HTML export template/ # Templates & sessions model.py # TemplateSpec, SessionState (YAML serializable) library.py # TemplateLibrary (~/.impakt/templates/) session.py # SessionManager (.impakt/ per test) report/ # Report generation engine.py # PDF/HTML via WeasyPrint + Jinja2 templates/ # 3 Jinja2 HTML templates plot_sheet.html injury_summary.html protocol_report.html web/ # Dash web application app.py # App factory: create_app(), serve() state.py # AppState: multi-test state, templates, sessions, corridors layout.py # Top-level layout: Data tab + Analysis tab components/ # Reusable layout components header.py # Navbar, test info panel, open/overlay modals channel_grid.py # Flat sortable DataTable with wildcard filter + facets channel_values.py # Combined cursor + statistics table (live hover values) transforms.py # CFC/align/resultant controls + per-channel overrides plot_grid.py # Multi-pane plot area (1x1, 2x1, 1x2, 2x2, 3x1) criteria.py # Auto-compute criteria, protocol scoring, results display corridors.py # Corridor upload (CSV) and management templates.py # Template library browser, save/apply/delete math_builder.py # Math expression builder with variable binding report.py # Export panel (PNG/SVG/PDF, CSV, protocol report) callbacks/ # Feature-specific callback modules __init__.py # Registration hub: register_callbacks() channel_callbacks.py # Selection, filtering, badges, per-channel overrides plot_callbacks.py # Plot rendering, transform pipeline, corridor display cursor_callbacks.py # Channel values table (live hover + X1/X2) criteria_callbacks.py # Compute All button, protocol scoring template_callbacks.py # Apply/save/delete templates, session auto-save corridor_callbacks.py # CSV upload, corridor state management math_callbacks.py # Expression evaluation, derived channel injection file_callbacks.py # Open test / add overlay modals export_callbacks.py # CSV export, report generation assets/ # Browser-side static files style.css # Custom CSS (compact layout, splitter, scrollbars) splitter.js # Draggable panel splitter (pure JS, no deps) cursor_tracker.js # Live cursor tracking (mousemove -> pixel-to-data-X) plugin/ # Plugin system registry.py # PluginRegistry, discovery (entrypoints + dir) script/ # Scripting API + CLI api.py # Session, ChannelHandle, TransformProxy, Template cli.py # argparse CLI (serve/info/channels/evaluate) tests/ conftest.py # Synthetic channel fixtures test_integration.py # Full pipeline against synthetic MME fixture test_real_mme.py # 46 tests against 5 real ISO 13499 datasets test_channel/ # ChannelCode parser, Channel model, TestData test_criteria/ # HIC, Nij test_io/ # MMEReader test_protocol/ # Euro NCAP scoring test_transform/ # CFC filter, alignment test_web/ # AppState, app creation, channel grid, channel values, P2 features fixtures/ generate_mme.py # Synthetic MME generator (26 channels, half-sine) sample_mme/ # Generated synthetic test data mme_data/ # REAL ISO 13499 test data (5 datasets) 3239/ # NHTSA/Calspan, VW Passat frontal, 133 channels AK3T02FO/ # BASt, frontal 40% offset, 97 channels AK3T02SI/ # BASt, side impact, 97 channels VW1FGS15/ # Volkswagen, pedestrian headform, 10 channels 98_7707/ # UTAC, vehicle-to-vehicle (metadata only) *.pdf, *.doc # ISO/TS 13499 reference documents ``` --- ## What Works ### All modules fully implemented and tested: | Module | Status | Notes | |---|---|---| | **Channel code parser** | Complete | Auto-detects 14-char (no dummy) vs 16-char (with dummy H3/P3/PC). | | **Channel model** | Complete | Immutable channels, auto-grouping X/Y/Z, resultant computation. | | **MME reader** | Complete | Real ISO 13499 (.mme + .chn index + .NNN data files) + simplified INI. Tested against 5 real datasets. | | **CFC filtering** | Complete | SAE J211 compliant. 4th-order Butterworth, zero-phase. All 4 CFC classes. | | **Alignment transforms** | Complete | X-align (manual/threshold/trigger), Y-align (baseline window). | | **Resultant** | Complete | From ChannelGroup or arbitrary channels. | | **Math expressions** | Complete | Safe eval with numpy functions. | | **HIC** | Complete | HIC15/HIC36, cumulative integration, optimal window search. | | **3ms clip** | Complete | Cumulative exceedance method. | | **Nij** | Complete | 4 modes (NTE/NTF/NCE/NCF), per-dummy intercepts. | | **Chest deflection** | Complete | Peak sternal displacement with unit/sanity validation. | | **Viscous criterion** | Complete | V(t)*C(t) with chest depth per dummy type. | | **Femur load** | Complete | Left/right, unit conversion. | | **Tibia index** | Complete | M/Mc + F/Fc with intercepts. | | **Euro NCAP** | Complete | Sliding-scale color/points, percentage to stars. Versioned thresholds. | | **US NCAP** | Complete | Logistic injury risk functions, combined probability, star rating. | | **IIHS** | Complete | G/A/M/P per body region, worst-case overall. | | **Plot engine** | Complete | Plotly rendering, corridors, cursor values, export. | | **Template model** | Complete | YAML serialize/deserialize, library manager, session persistence. | | **Report engine** | Complete | HTML+WeasyPrint PDF, 3 Jinja2 templates. | | **Plugin registry** | Complete | Entry point + directory + API discovery. | | **CLI** | Complete | `impakt serve/info/channels/evaluate`. | | **Web UI** | **Functional** | See details below. | ### Web UI -- Current State Fully functional for daily crash test analysis: **Data Tab:** - **Left panel** (resizable via draggable splitter): channel grid + transform controls - **Channel grid**: flat sortable DataTable (#, ISO Code, Description, Unit, Min, Max), wildcard filter bar, facet dropdowns (body region, measurement, direction), multi-select with selection persisted across filtering, selected rows colored with plot trace colors (tinted background + left border) - **Transform controls**: global CFC filter, Y-align, X-align (manual/threshold), resultant toggle, per-channel CFC overrides - **Plot area** (fills remaining width): no legend (info in tables), tight margins, compact axis labels, X1/X2 vertical reference lines - **Channel Values table** (directly below plot, minimal gap): combined statistics + cursor in one table. Columns: #, ISO Code, Description, Unit, Min, @Time, Max, @Time, X1, X2, Cursor. `table-layout: fixed` with percentage widths — Description fills remaining space. Rows colored with same plot trace colors. Cursor column updates live on mouse hover via custom JS tracker. **Analysis Tab:** - **Injury Criteria**: auto-detect channels by ISO naming, compute HIC15/3ms clip/Nij/chest defl/femur/tibia, protocol scoring (Euro NCAP/US NCAP/IIHS) with color-coded results and star ratings - **Math Expression Builder**: formula input, 3 variable bindings (a/b/c mapped to channel dropdowns), result injected into test data and auto-plotted - **Template Management**: library browser, apply (resolves channel patterns + sets CFC), save current view as template, delete, session auto-save - **Corridors**: CSV upload (time/lower/upper), rendered as filled band on plot - **Export**: CSV of plotted data (with transforms), PNG/SVG/PDF buttons, protocol report generation **Consistent Color System:** Every selected channel has a stable color index (position in selection order). The same color appears in: - Plot traces - Channel grid rows (tinted background + solid left border) - Selected badges (colored dot) - Channel Values table rows (tinted background + solid left border) ### Key design decisions: 1. **Immutable channels** -- transforms return new Channel objects; raw data never modified. 2. **`.impakt/` subfolder** -- session state stored alongside test data. 3. **Template/session split** -- templates are global recipes; sessions are per-test instances. 4. **AppState is server-side** -- numpy arrays stay in Python memory; Dash stores hold only lightweight keys. 5. **Channel keys use `test_id::channel_name`** -- enables multi-test overlay. 6. **Custom JS cursor tracking** -- bypasses Plotly's hover system with raw mousemove + pixel-to-data conversion. 7. **table-layout: fixed** on Channel Values -- percentage widths respected, Description column fills remaining space. 8. **Browser cache prevention** -- meta tags with Cache-Control: no-cache to prevent stale layout issues during development. 9. **Separate single-output callbacks** for DataTable properties -- avoids Dash KeyError when DataTable internally requests individual properties. --- ## Next Steps (Priority 3) 1. **Annotations** -- text on plots, measurement lines, highlight regions 2. **Comparison mode** -- side-by-side tests, delta plots, synced cursors 3. **Report builder** -- drag-and-drop report composer, PDF preview 4. **Keyboard shortcuts** -- Ctrl+O, Ctrl+S, 1-9 pane switch, F fullscreen, R reset zoom 5. **Consider Python/WASM frontend** -- NiceGUI or Solara for pure-Python UI (no JS) --- ## Test Data Available | Dataset | Lab | Type | Channels | Good for testing | |---|---|---|---|---| | `fixtures/sample_mme/` | Synthetic | Frontal barrier | 26 | Unit tests, known values | | `mme_data/3239/` | NHTSA/Calspan | Frontal barrier (VW Passat) | 133 | Full pipeline, real data | | `mme_data/AK3T02FO/` | BASt | Frontal 40% offset | 97 | Multi-occupant | | `mme_data/AK3T02SI/` | BASt | Side impact | 97 | Side impact protocols | | `mme_data/VW1FGS15/` | Volkswagen | Pedestrian headform | 10 | Impactor codes (D0) | | `mme_data/98_7707/` | UTAC | Vehicle-to-vehicle | 0 | Metadata-only | --- ## Dependencies Core: numpy, scipy, plotly, dash, dash-bootstrap-components, pandas, pyyaml, jinja2, weasyprint, pydantic Dev: pytest, pytest-cov, ruff, mypy Optional: nptdms (for future TDMS reader plugin) --- ## Known Issues / Technical Debt 1. **VehicleInfo.year parsed as 0** for real MME data (.mme format embeds year in vehicle name string). 2. **Speed displayed as raw float** (55.900001530350906 km/h) -- should round. 3. **DataTable deprecation warning** -- Dash recommends migrating to dash-ag-grid. 4. **Cursor poll interval (80ms)** -- slight latency in cursor grid updates. 5. **Chest deflection auto-detect** skips DS channels with peak > 150mm to avoid steering column displacement. 6. **Dead files** -- `cursors.py` and `inspector.py` were replaced by `channel_values.py` and deleted; `inspector_callbacks.py` deleted. If old `.pyc` files cause issues, run `find src -name __pycache__ -type d | xargs rm -rf`.