1734 lines
57 KiB
Python
1734 lines
57 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Create PowerPoint presentation: "Data Saves Lives" v3
|
|
WITH EMBEDDED IMAGES
|
|
|
|
The Story of Safety Testing: How We Decided to Do Better
|
|
"""
|
|
|
|
import os
|
|
from pptx import Presentation
|
|
from pptx.util import Inches, Pt
|
|
from pptx.dml.color import RGBColor
|
|
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
|
|
from pptx.enum.shapes import MSO_SHAPE
|
|
|
|
# Create presentation with widescreen dimensions
|
|
prs = Presentation()
|
|
prs.slide_width = Inches(13.333)
|
|
prs.slide_height = Inches(7.5)
|
|
|
|
# Asset directory
|
|
ASSET_DIR = "assets"
|
|
|
|
# Color scheme
|
|
DARK_BLUE = RGBColor(0, 51, 102)
|
|
ACCENT_BLUE = RGBColor(0, 112, 192)
|
|
ACCENT_RED = RGBColor(192, 0, 0)
|
|
DARK_GRAY = RGBColor(64, 64, 64)
|
|
LIGHT_GRAY = RGBColor(200, 200, 200)
|
|
WHITE = RGBColor(255, 255, 255)
|
|
LIGHT_BLUE_BG = RGBColor(240, 248, 255)
|
|
PLACEHOLDER_GRAY = RGBColor(220, 220, 220)
|
|
|
|
|
|
def get_asset_path(filename):
|
|
"""Return full path to asset if it exists, None otherwise"""
|
|
path = os.path.join(ASSET_DIR, filename)
|
|
if os.path.exists(path):
|
|
return path
|
|
return None
|
|
|
|
|
|
def add_image_to_slide(slide, image_path, left, top, width=None, height=None):
|
|
"""Add image to slide, return the shape or None if image doesn't exist"""
|
|
if image_path and os.path.exists(image_path):
|
|
try:
|
|
if width and height:
|
|
pic = slide.shapes.add_picture(image_path, left, top, width, height)
|
|
elif width:
|
|
pic = slide.shapes.add_picture(image_path, left, top, width=width)
|
|
elif height:
|
|
pic = slide.shapes.add_picture(image_path, left, top, height=height)
|
|
else:
|
|
pic = slide.shapes.add_picture(image_path, left, top)
|
|
return pic
|
|
except Exception as e:
|
|
print(f"Warning: Could not add image {image_path}: {e}")
|
|
return None
|
|
return None
|
|
|
|
|
|
def add_placeholder_box(slide, left, top, width, height, label="[Image]"):
|
|
"""Add a placeholder box for missing images"""
|
|
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
|
|
shape.fill.solid()
|
|
shape.fill.fore_color.rgb = PLACEHOLDER_GRAY
|
|
shape.line.color.rgb = LIGHT_GRAY
|
|
|
|
# Add label
|
|
text_frame = shape.text_frame
|
|
text_frame.paragraphs[0].text = label
|
|
text_frame.paragraphs[0].font.size = Pt(14)
|
|
text_frame.paragraphs[0].font.color.rgb = DARK_GRAY
|
|
text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
|
|
|
|
return shape
|
|
|
|
|
|
def add_title_slide(title, subtitle="", image_file=None):
|
|
"""Add a title slide with optional centered image"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(2.5), Inches(12.333), Inches(1.5)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(54)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
if subtitle:
|
|
sub_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(4.2), Inches(12.333), Inches(1.5)
|
|
)
|
|
tf = sub_box.text_frame
|
|
tf.word_wrap = True
|
|
p = tf.paragraphs[0]
|
|
p.text = subtitle
|
|
p.font.size = Pt(28)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
def add_section_slide(title, subtitle=""):
|
|
"""Add a section divider slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
shape = slide.shapes.add_shape(
|
|
MSO_SHAPE.RECTANGLE, Inches(0), Inches(2.8), Inches(13.333), Inches(2)
|
|
)
|
|
shape.fill.solid()
|
|
shape.fill.fore_color.rgb = DARK_BLUE
|
|
shape.line.fill.background()
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(3), Inches(12.333), Inches(1.2)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(44)
|
|
p.font.bold = True
|
|
p.font.color.rgb = WHITE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
if subtitle:
|
|
sub_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(5), Inches(12.333), Inches(0.8)
|
|
)
|
|
tf = sub_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = subtitle
|
|
p.font.size = Pt(24)
|
|
p.font.italic = True
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
def add_content_slide(title, bullets, footnote="", image_file=None, image_label=None):
|
|
"""Add a content slide with title, bullets, and optional right-side image"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
# Determine text width based on whether we have an image
|
|
text_width = Inches(7.5) if image_file else Inches(12.333)
|
|
|
|
# Title
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(1)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(36)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
|
|
# Underline
|
|
line = slide.shapes.add_shape(
|
|
MSO_SHAPE.RECTANGLE, Inches(0.5), Inches(1.1), Inches(12.333), Inches(0.03)
|
|
)
|
|
line.fill.solid()
|
|
line.fill.fore_color.rgb = ACCENT_BLUE
|
|
line.line.fill.background()
|
|
|
|
# Bullets
|
|
body_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(1.4), text_width, Inches(5.0)
|
|
)
|
|
tf = body_box.text_frame
|
|
tf.word_wrap = True
|
|
|
|
for i, bullet in enumerate(bullets):
|
|
if i == 0:
|
|
p = tf.paragraphs[0]
|
|
else:
|
|
p = tf.add_paragraph()
|
|
|
|
if bullet.startswith(" -"):
|
|
p.text = " " + bullet.strip().lstrip("-").strip()
|
|
p.font.size = Pt(18)
|
|
p.level = 1
|
|
elif bullet.startswith(">>"):
|
|
p.text = bullet.replace(">>", "").strip()
|
|
p.font.size = Pt(20)
|
|
p.font.bold = True
|
|
p.font.italic = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
else:
|
|
p.text = bullet.strip()
|
|
p.font.size = Pt(20)
|
|
|
|
if not bullet.startswith(">>"):
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.space_after = Pt(6)
|
|
|
|
# Image on right side
|
|
if image_file:
|
|
img_path = get_asset_path(image_file)
|
|
if img_path:
|
|
add_image_to_slide(
|
|
slide, img_path, Inches(8.3), Inches(1.5), width=Inches(4.5)
|
|
)
|
|
elif image_label:
|
|
add_placeholder_box(
|
|
slide, Inches(8.3), Inches(1.5), Inches(4.5), Inches(3.5), image_label
|
|
)
|
|
|
|
# Footnote
|
|
if footnote:
|
|
foot_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(6.9), Inches(12.333), Inches(0.4)
|
|
)
|
|
tf = foot_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = footnote
|
|
p.font.size = Pt(14)
|
|
p.font.italic = True
|
|
p.font.color.rgb = LIGHT_GRAY
|
|
|
|
return slide
|
|
|
|
|
|
def add_quote_slide(quote, attribution=""):
|
|
"""Add a quote slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
quote_box = slide.shapes.add_textbox(
|
|
Inches(1), Inches(2), Inches(11.333), Inches(3)
|
|
)
|
|
tf = quote_box.text_frame
|
|
tf.word_wrap = True
|
|
p = tf.paragraphs[0]
|
|
p.text = f'"{quote}"'
|
|
p.font.size = Pt(32)
|
|
p.font.italic = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
if attribution:
|
|
attr_box = slide.shapes.add_textbox(
|
|
Inches(1), Inches(5.2), Inches(11.333), Inches(0.8)
|
|
)
|
|
tf = attr_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = f"-- {attribution}"
|
|
p.font.size = Pt(24)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
def add_stat_slide(big_number, description, context=""):
|
|
"""Add a big statistic slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
num_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(1.5), Inches(12.333), Inches(2.5)
|
|
)
|
|
tf = num_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = big_number
|
|
p.font.size = Pt(120)
|
|
p.font.bold = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
desc_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(4), Inches(12.333), Inches(1)
|
|
)
|
|
tf = desc_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = description
|
|
p.font.size = Pt(36)
|
|
p.font.color.rgb = DARK_BLUE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
if context:
|
|
ctx_box = slide.shapes.add_textbox(
|
|
Inches(1), Inches(5.2), Inches(11.333), Inches(1.5)
|
|
)
|
|
tf = ctx_box.text_frame
|
|
tf.word_wrap = True
|
|
p = tf.paragraphs[0]
|
|
p.text = context
|
|
p.font.size = Pt(20)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
def add_two_column_slide(title, left_title, left_bullets, right_title, right_bullets):
|
|
"""Add a two-column comparison slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(1)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(36)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
|
|
line = slide.shapes.add_shape(
|
|
MSO_SHAPE.RECTANGLE, Inches(0.5), Inches(1.1), Inches(12.333), Inches(0.03)
|
|
)
|
|
line.fill.solid()
|
|
line.fill.fore_color.rgb = ACCENT_BLUE
|
|
line.line.fill.background()
|
|
|
|
# Left column
|
|
left_title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(1.4), Inches(5.9), Inches(0.6)
|
|
)
|
|
tf = left_title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = left_title
|
|
p.font.size = Pt(24)
|
|
p.font.bold = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
|
|
left_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(2), Inches(5.9), Inches(4.5)
|
|
)
|
|
tf = left_box.text_frame
|
|
tf.word_wrap = True
|
|
for i, bullet in enumerate(left_bullets):
|
|
if i == 0:
|
|
p = tf.paragraphs[0]
|
|
else:
|
|
p = tf.add_paragraph()
|
|
p.text = bullet
|
|
p.font.size = Pt(18)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.space_after = Pt(6)
|
|
|
|
# Right column
|
|
right_title_box = slide.shapes.add_textbox(
|
|
Inches(6.9), Inches(1.4), Inches(5.9), Inches(0.6)
|
|
)
|
|
tf = right_title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = right_title
|
|
p.font.size = Pt(24)
|
|
p.font.bold = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
|
|
right_box = slide.shapes.add_textbox(
|
|
Inches(6.9), Inches(2), Inches(5.9), Inches(4.5)
|
|
)
|
|
tf = right_box.text_frame
|
|
tf.word_wrap = True
|
|
for i, bullet in enumerate(right_bullets):
|
|
if i == 0:
|
|
p = tf.paragraphs[0]
|
|
else:
|
|
p = tf.add_paragraph()
|
|
p.text = bullet
|
|
p.font.size = Pt(18)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.space_after = Pt(6)
|
|
|
|
return slide
|
|
|
|
|
|
def add_timeline_slide(title, events):
|
|
"""Add a timeline slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(1)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(36)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
|
|
y_pos = 1.3
|
|
for year, event in events:
|
|
year_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(y_pos), Inches(1.5), Inches(0.5)
|
|
)
|
|
tf = year_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = str(year)
|
|
p.font.size = Pt(20)
|
|
p.font.bold = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
|
|
event_box = slide.shapes.add_textbox(
|
|
Inches(2.2), Inches(y_pos), Inches(10.5), Inches(0.5)
|
|
)
|
|
tf = event_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = event
|
|
p.font.size = Pt(18)
|
|
p.font.color.rgb = DARK_GRAY
|
|
|
|
y_pos += 0.55
|
|
|
|
return slide
|
|
|
|
|
|
def add_video_slide(title, video_description, video_url="", duration=""):
|
|
"""Add a video placeholder slide"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(1)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(36)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
|
|
video_shape = slide.shapes.add_shape(
|
|
MSO_SHAPE.RECTANGLE, Inches(1.5), Inches(1.5), Inches(10.333), Inches(4.5)
|
|
)
|
|
video_shape.fill.solid()
|
|
video_shape.fill.fore_color.rgb = RGBColor(30, 30, 30)
|
|
video_shape.line.color.rgb = ACCENT_BLUE
|
|
|
|
play_text = slide.shapes.add_textbox(
|
|
Inches(1.5), Inches(3), Inches(10.333), Inches(1.5)
|
|
)
|
|
tf = play_text.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = "VIDEO"
|
|
p.font.size = Pt(48)
|
|
p.font.bold = True
|
|
p.font.color.rgb = WHITE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
desc_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(6.2), Inches(12.333), Inches(1)
|
|
)
|
|
tf = desc_box.text_frame
|
|
tf.word_wrap = True
|
|
p = tf.paragraphs[0]
|
|
desc_text = video_description
|
|
if duration:
|
|
desc_text += f" ({duration})"
|
|
if video_url:
|
|
desc_text += f"\n{video_url}"
|
|
p.text = desc_text
|
|
p.font.size = Pt(16)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
def add_dts_connection_slide(title, content_bullets, products_mentioned=""):
|
|
"""Add a DTS connection slide with highlighted box"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(1)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(36)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
|
|
line = slide.shapes.add_shape(
|
|
MSO_SHAPE.RECTANGLE, Inches(0.5), Inches(1.1), Inches(12.333), Inches(0.03)
|
|
)
|
|
line.fill.solid()
|
|
line.fill.fore_color.rgb = ACCENT_BLUE
|
|
line.line.fill.background()
|
|
|
|
dts_shape = slide.shapes.add_shape(
|
|
MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.5), Inches(1.4), Inches(12.333), Inches(5)
|
|
)
|
|
dts_shape.fill.solid()
|
|
dts_shape.fill.fore_color.rgb = LIGHT_BLUE_BG
|
|
dts_shape.line.color.rgb = ACCENT_BLUE
|
|
|
|
content_box = slide.shapes.add_textbox(
|
|
Inches(0.7), Inches(1.6), Inches(12), Inches(4.5)
|
|
)
|
|
tf = content_box.text_frame
|
|
tf.word_wrap = True
|
|
|
|
for i, bullet in enumerate(content_bullets):
|
|
if i == 0:
|
|
p = tf.paragraphs[0]
|
|
else:
|
|
p = tf.add_paragraph()
|
|
p.text = bullet
|
|
p.font.size = Pt(20)
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.space_after = Pt(10)
|
|
|
|
if products_mentioned:
|
|
prod_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(6.6), Inches(12.333), Inches(0.5)
|
|
)
|
|
tf = prod_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = f"DTS Products: {products_mentioned}"
|
|
p.font.size = Pt(14)
|
|
p.font.bold = True
|
|
p.font.color.rgb = ACCENT_BLUE
|
|
|
|
return slide
|
|
|
|
|
|
def add_image_slide(title, image_file, caption="", image_label=None):
|
|
"""Add a slide with a large centered image"""
|
|
slide_layout = prs.slide_layouts[6]
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
# Title
|
|
title_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(0.3), Inches(12.333), Inches(0.8)
|
|
)
|
|
tf = title_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = title
|
|
p.font.size = Pt(32)
|
|
p.font.bold = True
|
|
p.font.color.rgb = DARK_BLUE
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
# Image
|
|
img_path = get_asset_path(image_file)
|
|
if img_path:
|
|
# Center the image
|
|
add_image_to_slide(slide, img_path, Inches(2), Inches(1.3), width=Inches(9.333))
|
|
elif image_label:
|
|
add_placeholder_box(
|
|
slide, Inches(2), Inches(1.3), Inches(9.333), Inches(5), image_label
|
|
)
|
|
|
|
# Caption
|
|
if caption:
|
|
cap_box = slide.shapes.add_textbox(
|
|
Inches(0.5), Inches(6.5), Inches(12.333), Inches(0.8)
|
|
)
|
|
tf = cap_box.text_frame
|
|
p = tf.paragraphs[0]
|
|
p.text = caption
|
|
p.font.size = Pt(18)
|
|
p.font.italic = True
|
|
p.font.color.rgb = DARK_GRAY
|
|
p.alignment = PP_ALIGN.CENTER
|
|
|
|
return slide
|
|
|
|
|
|
# ============================================================
|
|
# BUILD THE PRESENTATION
|
|
# ============================================================
|
|
|
|
# ============================================================
|
|
# OPENING
|
|
# ============================================================
|
|
|
|
add_title_slide(
|
|
"Data Saves Lives", "The Story of Safety Testing:\nHow We Decided to Do Better"
|
|
)
|
|
|
|
add_stat_slide(
|
|
"77%",
|
|
"Reduction in traffic fatality rate since 1970",
|
|
"1970: 4.74 deaths per 100M miles | Today: 1.10 deaths per 100M miles\nIf we still had 1970 rates: 153,000 deaths per year instead of 36,000",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Pattern: Every Test Has a Story",
|
|
[
|
|
"Every crash test exists because people were dying in a specific way",
|
|
"And at some point, we decided that was unacceptable.",
|
|
"",
|
|
"The cycle repeats throughout history:",
|
|
" - TRAGEDY: People die in ways we don't understand",
|
|
" - DECISION: We decide we need to do better",
|
|
" - DATA: Testing reveals the mechanism of injury",
|
|
" - STANDARD: A test is created to measure the problem",
|
|
" - ENGINEERING: Manufacturers design solutions",
|
|
" - LIVES SAVED: That specific death mode decreases",
|
|
"",
|
|
">> This presentation traces that cycle across 10 test modes.",
|
|
],
|
|
)
|
|
|
|
add_quote_slide(
|
|
"We chose to stop accepting preventable deaths as inevitable.",
|
|
"The philosophy shift that created modern safety testing",
|
|
)
|
|
|
|
# ============================================================
|
|
# SAE J211 / ISO 6487 - THE FOUNDATION
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"The Foundation: SAE J211",
|
|
"Before we could save lives, we had to agree on how to measure them",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Problem: Data Without Standards",
|
|
[
|
|
"In the early days of crash testing, every lab was an island:",
|
|
" - Different equipment, different filters, different sampling rates",
|
|
" - Data from GM couldn't be compared to data from Ford",
|
|
" - The same crash could produce wildly different numbers",
|
|
"",
|
|
"Raw accelerometer data is full of noise:",
|
|
" - Structural resonance from the vehicle",
|
|
" - Electrical interference",
|
|
" - High-frequency artifacts that don't represent human injury",
|
|
"",
|
|
"Without standards, crash test data was essentially meaningless.",
|
|
"",
|
|
">> We decided we needed a common language.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Solution: Channel Frequency Classes (CFC)",
|
|
[
|
|
"SAE J211 (1971) and ISO 6487 created the common language:",
|
|
"",
|
|
"CFC 1000 (1000 Hz): Head acceleration",
|
|
" - Brain injuries happen fast - need high bandwidth",
|
|
"",
|
|
"CFC 600 (600 Hz): Chest and pelvis acceleration",
|
|
" - Torso responds slower than head",
|
|
"",
|
|
"CFC 180 (180 Hz): Structural measurements",
|
|
" - Vehicle deformation, barrier loads",
|
|
"",
|
|
"4th-order Butterworth low-pass filter specification",
|
|
" - Removes noise without distorting the injury signal",
|
|
],
|
|
"SAE J211-1 Rev. 2014 | ISO 6487:2015 - technically equivalent standards",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: J211 Compliance",
|
|
[
|
|
"Every DTS data acquisition system is built to SAE J211 / ISO 6487 specs:",
|
|
"",
|
|
"Hardware anti-aliasing filters prevent signal contamination",
|
|
"",
|
|
"Software implements exact Butterworth filter specifications",
|
|
"",
|
|
"Calibration traceable to J211 requirements",
|
|
"",
|
|
"Sample rates exceed requirements: up to 100 kHz per channel",
|
|
"",
|
|
"Data from any DTS system is comparable to data from any other",
|
|
"DTS system worldwide - enabling global safety research collaboration",
|
|
],
|
|
"SLICE6, SLICE NANO, SLICE MICRO, TDAS G5",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 1: FMVSS 208 / AIRBAGS
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 1: FMVSS 208",
|
|
"The 28-year war: Industry fought airbags from 1970 until mandatory in 1998",
|
|
)
|
|
|
|
add_content_slide(
|
|
"Before 1968: The Dark Age",
|
|
[
|
|
"No federal safety requirements existed for occupant protection",
|
|
"",
|
|
"Seatbelts were optional accessories - rarely ordered",
|
|
"",
|
|
"Steering columns were rigid metal shafts pointed at driver's chest",
|
|
" - By 1964: over 1 MILLION cumulative steering column deaths",
|
|
"",
|
|
"Dashboards were solid steel with chrome protrusions",
|
|
"",
|
|
"Industry position: 'Crashes are caused by bad drivers, not bad cars'",
|
|
"",
|
|
">> At some point, we decided that 50,000 deaths per year",
|
|
">> was not acceptable.",
|
|
],
|
|
image_file="1957_buick_dashboard.jpg",
|
|
)
|
|
|
|
add_image_slide(
|
|
"Styling Over Safety: 1957",
|
|
"1957_chevy_styling.jpg",
|
|
"Chrome, steel, and style. No seatbelts, no airbags, no crumple zones.",
|
|
)
|
|
|
|
add_timeline_slide(
|
|
"The Airbag Wars: 28 Years of Fighting",
|
|
[
|
|
("1968", "FMVSS 208 takes effect - requires seatbelt anchorages only"),
|
|
("1970", "NHTSA proposes airbag requirement"),
|
|
("1972", "GM offers airbags on Oldsmobiles - few buyers"),
|
|
("1977", "Joan Claybrook (NHTSA) pushes airbag mandate"),
|
|
("1981", "Reagan administration RESCINDS airbag mandate"),
|
|
("1983", "Supreme Court rules rescission was arbitrary"),
|
|
("1984", "Compromise: 'automatic restraint' required"),
|
|
("1990", "First airbag fatality - a child in front seat"),
|
|
("1997", "53 deaths from airbag deployment - peak year"),
|
|
("1998", "FINALLY: Frontal airbags mandatory - 28 years later"),
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Depowering Crisis: When Airbags Killed",
|
|
[
|
|
"Early airbags were designed for one scenario:",
|
|
" - Unbelted adult male",
|
|
" - Maximum deployment force in every crash",
|
|
"",
|
|
"Problem: What about children? Small adults sitting close?",
|
|
"",
|
|
"1990: First airbag fatality - a child",
|
|
"1996-1997: 53 deaths from airbag deployment",
|
|
" - Victims: mostly children in front seats, small women",
|
|
"",
|
|
"The data showed the problem. Better data gave us the fix:",
|
|
" - 'Depowered' airbags with lower inflation force",
|
|
" - Weight sensors detect occupant size",
|
|
" - Suppression systems for small occupants",
|
|
"",
|
|
">> We decided that protecting one group couldn't mean killing another.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"FMVSS 208: Technical Specifications",
|
|
[
|
|
"Test Configuration:",
|
|
" - 30 mph full frontal barrier (compliance)",
|
|
" - 35 mph full frontal barrier (NCAP consumer rating)",
|
|
"",
|
|
"Dummies:",
|
|
" - Hybrid III 50th percentile male (driver)",
|
|
" - Hybrid III 5th percentile female (passenger)",
|
|
" - Total: ~94 channels (47 per dummy)",
|
|
"",
|
|
"Key Injury Criteria:",
|
|
" - HIC15 < 700 (head injury)",
|
|
" - Chest acceleration 3ms < 60g",
|
|
" - Chest deflection < 63mm (50th male)",
|
|
" - Femur load < 10 kN",
|
|
],
|
|
image_file="iihs_frontal_crash_test.jpg",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Hybrid III Family",
|
|
[
|
|
"Introduced 1976 - still the global standard for frontal impact",
|
|
"",
|
|
"Family of sizes representing different populations:",
|
|
" - 95th percentile male (6'2\", 220 lbs)",
|
|
" - 50th percentile male (5'9\", 172 lbs) - most common",
|
|
" - 5th percentile female (5'0\", 110 lbs)",
|
|
" - 10-year-old child",
|
|
" - 6-year-old child",
|
|
" - 3-year-old child",
|
|
"",
|
|
"Each dummy is a mechanical body.",
|
|
"DTS provides the 'nervous system' - the sensors that feel.",
|
|
],
|
|
image_file="hybrid_iii_family.jpg",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: FMVSS 208",
|
|
[
|
|
"Head: Triaxial accelerometer (CFC 1000)",
|
|
" - Measures peak deceleration for HIC calculation",
|
|
"",
|
|
"Chest: Accelerometer + deflection potentiometer (CFC 600)",
|
|
" - Chest compression indicates rib/organ injury risk",
|
|
"",
|
|
"Neck: 6-axis load cell",
|
|
" - Forces and moments for Nij calculation",
|
|
"",
|
|
"Femur: Uniaxial load cells (both legs)",
|
|
" - Dashboard/knee bolster loading",
|
|
"",
|
|
"Every channel matters - one sensor failure = repeat the $500K test",
|
|
],
|
|
"SLICE6, 6DX PRO-A (6 degrees of freedom), TDAS G5",
|
|
)
|
|
|
|
add_video_slide(
|
|
"Video: IIHS 1959 vs. 2009 Crash Test",
|
|
"IIHS 50th anniversary demonstration: 1959 Chevy Bel Air vs. 2009 Chevy Malibu at 40 mph. The most powerful demonstration of 50 years of safety progress.",
|
|
"https://www.youtube.com/watch?v=joMK1WZjP7g",
|
|
"1:43",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 2: IIHS SMALL OVERLAP
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 2: IIHS Small Overlap",
|
|
"When BMW, Mercedes, and Audi all failed: The test that humiliated luxury cars",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Gap: What Existing Tests Missed",
|
|
[
|
|
"By 2012, vehicles performed well in:",
|
|
" - NHTSA NCAP full frontal (100% overlap)",
|
|
" - IIHS moderate overlap (40% overlap)",
|
|
"",
|
|
"But IIHS researchers noticed something in real-world crash data:",
|
|
" - Fatal frontal crashes still occurring in 'safe' cars",
|
|
" - Many involved narrow overlap - trees, poles, vehicle corners",
|
|
"",
|
|
"The problem with 25% overlap:",
|
|
" - Main structural frame rails are NOT engaged",
|
|
" - Forces go through wheel and suspension into footwell",
|
|
" - Wheel can be pushed into occupant compartment",
|
|
"",
|
|
">> We decided that 'good enough' on existing tests wasn't good enough.",
|
|
],
|
|
image_file="iihs_small_overlap_barrier.jpg",
|
|
)
|
|
|
|
add_two_column_slide(
|
|
"Small Overlap Test (2012): The Shock",
|
|
"What Failed",
|
|
[
|
|
"BMW 3 Series - MARGINAL",
|
|
"Mercedes C-Class - MARGINAL",
|
|
"Audi A4 - MARGINAL",
|
|
"Lexus IS - MARGINAL",
|
|
"Lexus ES - MARGINAL",
|
|
"Lincoln MKZ - POOR",
|
|
"Buick Regal - POOR",
|
|
"Volkswagen CC - POOR",
|
|
"",
|
|
"These were LUXURY vehicles that",
|
|
"earned top marks in every other test.",
|
|
],
|
|
"What It Revealed",
|
|
[
|
|
"A-pillars folded on impact",
|
|
"Footwells crushed by wheel intrusion",
|
|
"Occupants slid toward the gap",
|
|
"Restraint systems couldn't compensate",
|
|
"",
|
|
"Structures had been optimized for",
|
|
"40% and 100% overlap tests.",
|
|
"",
|
|
"No one had tested 25%.",
|
|
"",
|
|
"The small overlap exposed a",
|
|
"critical structural blind spot.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Industry Response",
|
|
[
|
|
"Initial reaction: 'The test isn't realistic!'",
|
|
"",
|
|
"Then: Rapid engineering scramble",
|
|
" - Structural members added outboard of frame rails",
|
|
" - A-pillar and hinge pillar connections reinforced",
|
|
" - Firewall 'blocking' structures to redirect forces",
|
|
" - Wheel well reinforcement",
|
|
"",
|
|
"Timeline:",
|
|
" - 2012: Most vehicles Poor or Marginal",
|
|
" - 2014: Mixed results - some manufacturers improve",
|
|
" - 2016: Most new designs earn Good",
|
|
" - 2017: IIHS adds PASSENGER side test (prevent gaming)",
|
|
"",
|
|
">> Five years. From widespread failure to widespread success.",
|
|
],
|
|
image_file="small_overlap_test.jpg",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Small Overlap",
|
|
[
|
|
"The most demanding frontal test requires the most reliable data:",
|
|
"",
|
|
"Head trajectory tracking:",
|
|
" - Where does the occupant's head go during the crash?",
|
|
" - Critical for assessing curtain airbag effectiveness",
|
|
"",
|
|
"Chest kinematics:",
|
|
" - Did the restraint system keep occupant in position?",
|
|
" - Or did they slide toward the gap?",
|
|
"",
|
|
"Lower extremity loads:",
|
|
" - Wheel intrusion into footwell is a signature failure mode",
|
|
" - Tibia axial force and bending moment measurements",
|
|
"",
|
|
"Every channel tells part of the story.",
|
|
],
|
|
"SLICE6, SLICE NANO, ACC3 PRO-A accelerometers",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 3: FMVSS 301 / FORD PINTO
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 3: FMVSS 301",
|
|
"The $11 fix Ford refused to make: The memo that led to criminal prosecution",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Ford Pinto: A Design Decision",
|
|
[
|
|
"1970: Ford introduces the Pinto - subcompact to compete with imports",
|
|
"",
|
|
"The fuel tank design:",
|
|
" - Located behind rear axle, 6 inches from bumper",
|
|
" - Minimal protection from rear impact",
|
|
" - Bolts on differential could puncture tank in collision",
|
|
" - Fuel filler neck could separate, spilling fuel",
|
|
"",
|
|
"Ford engineers knew about the vulnerability",
|
|
" - Crash tests showed fuel leakage in rear impacts",
|
|
" - Design fixes were identified and costed",
|
|
"",
|
|
"But the Pinto was already in production...",
|
|
],
|
|
image_file="ford_pinto_rear.jpg",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Memo: Cost-Benefit Analysis (1973)",
|
|
[
|
|
"Ford's internal calculation:",
|
|
"",
|
|
"COST TO FIX:",
|
|
" - $11 per vehicle x 12.5 million vehicles = $137 million",
|
|
"",
|
|
"COST OF NOT FIXING (estimated):",
|
|
" - 180 deaths x $200,000 per death = $36 million",
|
|
" - 180 serious injuries x $67,000 = $12 million",
|
|
" - 2,100 burned vehicles x $700 = $1.5 million",
|
|
" - Total: $49.5 million",
|
|
"",
|
|
"FORD'S DECISION: Do not implement the fix.",
|
|
"",
|
|
">> We decided that corporate cost-benefit analysis",
|
|
">> could not override the value of human life.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Reckoning",
|
|
[
|
|
"1977: Mother Jones publishes 'Pinto Madness' expose",
|
|
" - Internal memo becomes public",
|
|
" - Public outrage follows",
|
|
"",
|
|
"1978: NHTSA investigation and recall",
|
|
" - 1.5 million Pintos recalled",
|
|
" - FMVSS 301 strengthened in direct response",
|
|
"",
|
|
"1978: Indiana v. Ford Motor Company",
|
|
" - First criminal prosecution of an automaker for defective design",
|
|
" - Ford acquitted, but reputation destroyed",
|
|
"",
|
|
"Estimated deaths from Pinto fuel system: 27-180",
|
|
"",
|
|
"The Pinto case created the template for product liability law.",
|
|
],
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: FMVSS 301",
|
|
[
|
|
"Vehicle structure accelerometers confirm impact severity",
|
|
" - Critical for validating that test conditions were met",
|
|
"",
|
|
"Barrier load cells measure impact force",
|
|
" - Ensures test is representative of real-world crashes",
|
|
"",
|
|
"While fuel leakage is measured directly (not with DTS sensors),",
|
|
"the crash event itself requires precise data acquisition",
|
|
"",
|
|
"This test ensures that the progress we've made in",
|
|
"occupant protection isn't undone by post-crash fire.",
|
|
],
|
|
"SLICE PRO, load cell interfaces",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 4: FMVSS 214 SIDE IMPACT
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 4: FMVSS 214 Side Impact",
|
|
"25% of crashes, 30% of deaths: The door that wasn't a barrier",
|
|
)
|
|
|
|
add_stat_slide(
|
|
"25% / 30%",
|
|
"Side impacts: 25% of crashes but 30% of fatalities",
|
|
"More deadly PER CRASH than frontal. Why? Minimal crush space, no crumple zone, direct loading to torso and head.",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Neglected Crash Mode",
|
|
[
|
|
"Timeline of neglect:",
|
|
" - 1968: FMVSS 208 (frontal protection) - nothing for side",
|
|
" - 1973: FMVSS 214 - static door strength only",
|
|
" - 1979: NCAP ratings (frontal) - nothing for side",
|
|
" - 1990: First DYNAMIC side test (22 years after frontal)",
|
|
" - 2003: IIHS side test",
|
|
" - 2007: Pole test added (head protection)",
|
|
"",
|
|
"Before side airbags, there was NOTHING between",
|
|
"your ribs and the door in a side crash.",
|
|
"",
|
|
">> We decided that side crash victims deserved the same",
|
|
">> engineering attention as frontal crash victims.",
|
|
],
|
|
image_file="iihs_side_barrier.jpg",
|
|
)
|
|
|
|
add_timeline_slide(
|
|
"The Side Airbag Revolution",
|
|
[
|
|
("Pre-1995", "Nothing between your ribs and the door"),
|
|
("1995", "Volvo introduces first side torso airbag"),
|
|
("1998", "First side curtain airbags (head protection)"),
|
|
("2003", "IIHS side test launched - accelerates adoption"),
|
|
("2007", "FMVSS 214 pole test requires head protection"),
|
|
("2010", "Side curtain airbags standard on most vehicles"),
|
|
("2021", "IIHS updates side test: heavier, taller, faster barrier"),
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"FMVSS 214: Technical Specifications",
|
|
[
|
|
"MDB Test (Moving Deformable Barrier):",
|
|
" - 33.5 mph (FMVSS) / 38.5 mph (NCAP)",
|
|
" - Barrier strikes stationary vehicle at 90 degrees",
|
|
" - ES-2re dummy (50th male, side impact design)",
|
|
"",
|
|
"Pole Test (added 2007):",
|
|
" - 20 mph into 254mm (10 inch) diameter pole",
|
|
" - Simulates tree strike, utility pole",
|
|
" - Specifically targets head protection",
|
|
"",
|
|
"Injury Criteria:",
|
|
" - Thoracic Trauma Index (TTI)",
|
|
" - Pelvis acceleration",
|
|
" - Rib deflection (Viscous Criterion)",
|
|
],
|
|
image_file="iihs_side_dummies.jpg",
|
|
)
|
|
|
|
add_content_slide(
|
|
"2021: The Updated Side Test",
|
|
[
|
|
"The vehicle fleet changed - tests must change too",
|
|
"",
|
|
"SUVs and trucks now dominate sales",
|
|
" - Old barrier simulated an average car",
|
|
" - New barrier simulates modern SUV/truck",
|
|
"",
|
|
"Updated barrier specifications:",
|
|
" - Weight: 4,200 lbs (was 3,300 lbs)",
|
|
" - Speed: 37 mph (was 31 mph)",
|
|
" - Profile: Taller to match SUV front ends",
|
|
"",
|
|
"Results: Many 'Good' vehicles dropped to lower ratings",
|
|
"Manufacturers redesigning structures AGAIN",
|
|
"",
|
|
">> The test evolved because the threat evolved.",
|
|
],
|
|
image_file="iihs_side_2021.jpg",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Side Impact",
|
|
[
|
|
"Side impact dummies are fundamentally different from frontal:",
|
|
" - Different rib structure (ribs that deflect laterally)",
|
|
" - Different instrumentation layout",
|
|
"",
|
|
"Rib deflection sensors (IR-TRACCs):",
|
|
" - Measure chest compression",
|
|
" - Critical for Viscous Criterion calculation",
|
|
"",
|
|
"Multiple accelerometer locations:",
|
|
" - Thorax (upper, middle, lower)",
|
|
" - Pelvis, Head (for pole test)",
|
|
"",
|
|
"The pole test head measurements drove universal adoption",
|
|
"of side curtain airbags - now standard equipment.",
|
|
],
|
|
"SLICE6, IR-TRACC interfaces, ES-2re integration",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 5: FMVSS 216 ROOF CRUSH
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 5: FMVSS 216 Roof Crush",
|
|
"36 years unchanged: The 1.5x standard that advocacy finally doubled",
|
|
)
|
|
|
|
add_stat_slide(
|
|
"3% / 30%",
|
|
"Rollovers: 3% of crashes but 30% of fatalities",
|
|
"Ejection in rollover is 77% fatal. The roof is the last line of defense.",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Long Fight for Stronger Roofs",
|
|
[
|
|
"1973: FMVSS 216 established",
|
|
" - Roof must withstand 1.5x vehicle weight",
|
|
" - Only ONE side tested (driver side)",
|
|
"",
|
|
"For 36 YEARS, this standard did not change.",
|
|
"",
|
|
"Consumer advocates argued:",
|
|
" - 1.5x is far too weak",
|
|
" - Real-world rollovers show roofs collapsing into survival space",
|
|
" - Should be 4x or higher",
|
|
"",
|
|
"2009: Standard FINALLY upgraded",
|
|
" - Doubled to 3x vehicle weight",
|
|
" - BOTH sides must be tested",
|
|
"",
|
|
">> IIHS pushed further: 4x required for 'Good' rating",
|
|
">> Many vehicles now achieve 5-6x.",
|
|
],
|
|
image_file="roof_strength_test.jpg",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Roof Crush",
|
|
[
|
|
"Unlike crash tests, roof strength is a static test:",
|
|
" - Controlled force application",
|
|
" - Force vs. displacement measurement",
|
|
"",
|
|
"DTS load cells measure applied force",
|
|
" - High accuracy for force-deflection curve",
|
|
"",
|
|
"Displacement sensors track crush distance",
|
|
" - Critical for determining when 127mm threshold is reached",
|
|
"",
|
|
"The test determines if occupants have survival space if",
|
|
"the vehicle rolls - the data validates the structure.",
|
|
],
|
|
"SLICE PRO LAB, load cell interfaces",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 6: IIHS HEAD RESTRAINT / WHIPLASH
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 6: IIHS Head Restraint",
|
|
"One million injuries per year: The epidemic hiding in low-speed crashes",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Whiplash Epidemic",
|
|
[
|
|
"Over 1 MILLION whiplash injuries per year in the US",
|
|
" - Most occur in low-speed rear impacts",
|
|
" - Not fatal, but chronic pain can persist for years",
|
|
" - Enormous economic cost: medical, lost work, disability",
|
|
"",
|
|
"Early head restraints were ineffective:",
|
|
" - Set too low (didn't support head)",
|
|
" - Too far back from head (head snapped backward before contact)",
|
|
" - Often adjusted incorrectly or removed entirely",
|
|
"",
|
|
"Swedish research (Volvo, Saab) led the way:",
|
|
" - 'Active' head restraints that move up/forward during crash",
|
|
" - Engage head earlier, reduce relative motion",
|
|
"",
|
|
">> We decided that non-fatal injuries still matter.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"IIHS Whiplash Test: Technical Specifications",
|
|
[
|
|
"Test Method:",
|
|
" - Dynamic sled test (not full vehicle crash)",
|
|
" - Simulates low-speed rear impact",
|
|
"",
|
|
"Dummy:",
|
|
" - BioRID II - specifically designed for rear impact",
|
|
" - 24 articulated vertebrae (highly flexible spine)",
|
|
"",
|
|
"Key Measurements:",
|
|
" - Neck Injury Criteria (NIC)",
|
|
" - Neck forces and moments",
|
|
" - Relative head-to-torso movement",
|
|
" - Seat strength (must not collapse backward)",
|
|
"",
|
|
"Active head restraints are now standard equipment",
|
|
"because of this test.",
|
|
],
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Whiplash Testing",
|
|
[
|
|
"BioRID II has a fundamentally different spine than Hybrid III:",
|
|
" - 24 articulated vertebrae vs. rigid lumbar/thoracic",
|
|
" - Requires different instrumentation approach",
|
|
"",
|
|
"Sensors along the articulated spine measure relative motion:",
|
|
" - How does each vertebra move relative to adjacent ones?",
|
|
" - This is the mechanism of whiplash injury",
|
|
"",
|
|
"Head and torso accelerometers (CFC 1000, CFC 600)",
|
|
"",
|
|
"Different dummy = different data acquisition configuration",
|
|
"DTS systems support both Hybrid III and BioRID configurations.",
|
|
],
|
|
"SLICE6, BioRID spine sensor interfaces",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 7: IIHS FRONT CRASH PREVENTION (AEB)
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 7: IIHS Front Crash Prevention",
|
|
"The voluntary revolution: 20 automakers agreed without a government mandate",
|
|
)
|
|
|
|
add_two_column_slide(
|
|
"The Philosophy Shift: Passive to Active",
|
|
"Passive Safety (1968-2000s)",
|
|
[
|
|
"Assume crash WILL happen",
|
|
"",
|
|
"Focus on protection DURING crash:",
|
|
" - Seatbelts",
|
|
" - Airbags",
|
|
" - Structure",
|
|
"",
|
|
"After 50 years, we've gotten very good",
|
|
"at protecting people in crashes.",
|
|
"",
|
|
"But 94% of crashes involve human error...",
|
|
],
|
|
"Active Safety (2000s-present)",
|
|
[
|
|
"Try to PREVENT the crash",
|
|
"",
|
|
"Warn driver, assist, brake automatically:",
|
|
" - AEB (Autonomous Emergency Braking)",
|
|
" - ESC (Electronic Stability Control)",
|
|
" - Lane Keeping Assist",
|
|
"",
|
|
"If crash is unavoidable, passive kicks in.",
|
|
"",
|
|
"Active + Passive = Maximum protection",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Voluntary Commitment (2016)",
|
|
[
|
|
"20 automakers voluntarily committed to make AEB standard by 2022:",
|
|
" - No government mandate required",
|
|
" - Driven by IIHS ratings and consumer demand",
|
|
" - The fastest safety technology adoption in history",
|
|
"",
|
|
"Effectiveness:",
|
|
" - AEB reduces rear-end crashes by 50%+",
|
|
" - Even basic forward collision warning reduces crashes 27%",
|
|
"",
|
|
"This is a fundamentally new type of safety test:",
|
|
" - Not measuring crash protection",
|
|
" - Measuring crash PREVENTION",
|
|
"",
|
|
">> We decided that preventing crashes is better than surviving them.",
|
|
],
|
|
image_file="iihs_fcp_car_target.png",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: AEB Testing",
|
|
[
|
|
"This is an expanding market for DTS:",
|
|
"",
|
|
"Vehicle dynamics measurement:",
|
|
" - Speed, deceleration, timing",
|
|
" - When did the system activate?",
|
|
" - How quickly did it respond?",
|
|
"",
|
|
"Not traditional dummy instrumentation, but related technology:",
|
|
" - High-speed data acquisition",
|
|
" - Precise timing synchronization",
|
|
"",
|
|
"The future of safety testing includes evaluating systems",
|
|
"that PREVENT crashes, not just systems that protect in crashes.",
|
|
],
|
|
"TSR AIR data logger, SLICE systems for vehicle dynamics",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 8: EURO NCAP PEDESTRIAN PROTECTION
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 8: Euro NCAP Pedestrian",
|
|
"Europe's 25-year head start: The US still has no federal standard",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Pedestrian Crisis",
|
|
[
|
|
"While occupant deaths have FALLEN, pedestrian deaths are RISING:",
|
|
" - 2009: 4,109 pedestrian deaths",
|
|
" - 2019: 6,205 pedestrian deaths",
|
|
" - 2022: 7,500+ pedestrian deaths (18% of all traffic deaths)",
|
|
"",
|
|
"Why?",
|
|
" - Larger vehicles (SUVs, trucks) dominate sales",
|
|
" - Higher front ends hit torso/head instead of legs",
|
|
" - Distracted driving and walking (phones)",
|
|
"",
|
|
"The US approach:",
|
|
" - Test if cars AVOID pedestrians (AEB)",
|
|
" - But NOT what happens if they don't",
|
|
"",
|
|
">> Europe decided 25 years ago that pedestrians deserved protection too.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"Euro NCAP Pedestrian Testing (Since 1997)",
|
|
[
|
|
"Europe has tested pedestrian protection for 25+ years:",
|
|
"",
|
|
"Headform Impactor Test:",
|
|
" - Adult and child headforms",
|
|
" - Fired at hood surface at 40 km/h",
|
|
" - HIC measurement - same physics as occupant head protection",
|
|
"",
|
|
"Legform Impactor Test:",
|
|
" - Upper legform: hip/pelvis injury",
|
|
" - Lower legform: knee bending, tibia fracture",
|
|
"",
|
|
"Design changes driven by this test:",
|
|
" - Active hood hinges (pop up to create crush space)",
|
|
" - Energy-absorbing bumper structures",
|
|
" - External pedestrian airbags (Volvo)",
|
|
],
|
|
image_file="euroncap_headform.png",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Pedestrian Protection",
|
|
[
|
|
"Headform impactor testing uses DTS accelerometers:",
|
|
" - Same basic technology as crash test dummies",
|
|
" - Triaxial accelerometer inside impactor headform",
|
|
" - CFC 1000 filtering (same as dummy head)",
|
|
"",
|
|
"The physics is identical:",
|
|
" - Protect the brain from rapid deceleration",
|
|
" - Whether the brain is inside a car or outside it",
|
|
"",
|
|
"Expanding market as US considers pedestrian protection requirements",
|
|
"",
|
|
"Same sensors, same data acquisition, different application.",
|
|
],
|
|
"SLICE NANO, ACC3 PRO-A accelerometers",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 9: NOCSAE FOOTBALL HELMET
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 9: NOCSAE Football Helmet",
|
|
"36 deaths in one year: The 1968 season that created helmet certification",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The 1968 Crisis",
|
|
[
|
|
"1968: 36 football players died",
|
|
" - Worst year on record for football fatalities",
|
|
" - Most from head and neck injuries",
|
|
"",
|
|
"The problem:",
|
|
" - No helmet standards existed",
|
|
" - Manufacturers made their own claims",
|
|
" - No way to verify protection level",
|
|
" - No consistent test method",
|
|
"",
|
|
"1969: NOCSAE founded",
|
|
" - National Operating Committee on Standards for Athletic Equipment",
|
|
" - Response to Congressional pressure after 36 deaths",
|
|
"",
|
|
">> We decided that athletes deserved the same scientific",
|
|
">> protection as drivers.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"NOCSAE Helmet Standard (1973)",
|
|
[
|
|
"First helmet certification standard:",
|
|
"",
|
|
"Drop Tower Test:",
|
|
" - Helmet on headform dropped from 60 inches onto anvils",
|
|
" - Multiple impact locations",
|
|
" - Hot, cold, wet conditions",
|
|
" - Severity Index must be below 1200",
|
|
"",
|
|
"Key insight: Same physics as automotive",
|
|
" - SI (Severity Index) closely related to HIC",
|
|
" - Both measure head acceleration over time",
|
|
" - Both derive from Wayne State cadaver research",
|
|
"",
|
|
"1978: NCAA mandates NOCSAE-certified helmets",
|
|
"1980: High school (NFHS) mandates NOCSAE helmets",
|
|
],
|
|
)
|
|
|
|
add_stat_slide(
|
|
"90%",
|
|
"Reduction in football fatalities since NOCSAE standards (1973)",
|
|
"1960s: 26 deaths/year | 1970s: 15 deaths/year | 2010s: 3 deaths/year",
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Helmet Testing",
|
|
[
|
|
"DTS accelerometers inside helmet headforms:",
|
|
" - Same sensors used in automotive crash test dummies",
|
|
" - Triaxial measurement for SI calculation",
|
|
"",
|
|
"The injury threshold (SI < 1200) derives from the same",
|
|
"human tolerance research as automotive HIC.",
|
|
"",
|
|
"Wayne State cadaver research from the 1950s-60s",
|
|
"informs both automotive and helmet standards.",
|
|
"",
|
|
"One technology, one data acquisition approach,",
|
|
"applied across automotive, football, hockey, cycling, equestrian.",
|
|
],
|
|
"SLICE NANO, SLICE MICRO for headform instrumentation",
|
|
)
|
|
|
|
# ============================================================
|
|
# TEST MODE 10: NFL / CTE
|
|
# ============================================================
|
|
|
|
add_section_slide(
|
|
"Test Mode 10: NFL Helmet / CTE",
|
|
"The league that denied brain damage: From Mike Webster to $765 million",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Denial",
|
|
[
|
|
"2002: Mike Webster dies at 50 - 'Iron Mike', Hall of Fame center",
|
|
" - Homeless, cognitively impaired, heart attack",
|
|
"",
|
|
"2005: Dr. Bennet Omalu publishes first CTE case in NFL player",
|
|
" - Chronic Traumatic Encephalopathy found in Webster's brain",
|
|
" - NFL's response: Demanded retraction, attacked Omalu",
|
|
"",
|
|
"2009: NFL finally acknowledges concussion problem",
|
|
"",
|
|
"2011: $765 million settlement with former players",
|
|
"",
|
|
"The science was clear: Repeated head impacts cause brain damage",
|
|
" - Even 'subconcussive' hits accumulate",
|
|
"",
|
|
">> We decided that athlete brain health couldn't be ignored for profit.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Evolution of Helmet Testing",
|
|
[
|
|
"Traditional NOCSAE drop test:",
|
|
" - Measures linear acceleration",
|
|
" - Pass/fail at SI < 1200",
|
|
"",
|
|
"Modern research suggests rotation matters more:",
|
|
" - Brain injury may be caused more by ROTATION than linear force",
|
|
" - Concussion mechanism involves brain twisting inside skull",
|
|
"",
|
|
"NFL/NFLPA Helmet Testing Protocol:",
|
|
" - Drop tower test (traditional)",
|
|
" - Linear impactor test (game-realistic, higher speeds)",
|
|
" - Pendulum impactor",
|
|
" - Rotational measurements (emerging)",
|
|
"",
|
|
"Annual helmet rankings published - creates market pressure",
|
|
],
|
|
)
|
|
|
|
add_dts_connection_slide(
|
|
"How DTS Helps: Concussion Research",
|
|
[
|
|
"Same accelerometers as automotive head measurement:",
|
|
" - Triaxial linear acceleration",
|
|
" - CFC 1000 filtering",
|
|
"",
|
|
"Angular rate sensors for rotational measurement:",
|
|
" - ARS PRO angular rate sensors",
|
|
" - 6DX PRO-A for 6 degrees of freedom",
|
|
"",
|
|
"The injury threshold science came from automotive research:",
|
|
" - Wayne State cadaver studies",
|
|
" - HIC development",
|
|
" - Human tolerance curves",
|
|
"",
|
|
"DTS instruments both domains with the same technology.",
|
|
],
|
|
"SLICE systems, ARS PRO, 6DX PRO-A, ACC3 PRO-A",
|
|
)
|
|
|
|
# ============================================================
|
|
# CLOSING
|
|
# ============================================================
|
|
|
|
add_section_slide("The Work Continues", "What gaps remain?")
|
|
|
|
add_content_slide(
|
|
"Every Test Exposed What Previous Tests Missed",
|
|
[
|
|
"1968: FMVSS 208 (frontal) - but side crashes were neglected",
|
|
"1990: FMVSS 214 (side) - but offset frontal was missed",
|
|
"1995: IIHS Moderate Overlap - but small overlap was missed",
|
|
"2012: IIHS Small Overlap - but passenger side was 'gamed'",
|
|
"2017: Small Overlap Passenger - but fleet changed (bigger SUVs)",
|
|
"2021: Updated Side Test - but gaps remain...",
|
|
"",
|
|
"What's NEXT?",
|
|
" - Rear seat occupant protection (currently neglected)",
|
|
" - Far-side impacts (opposite side from impact)",
|
|
" - Vehicle compatibility (small cars vs. large trucks)",
|
|
" - EV-specific tests (battery safety, mass distribution)",
|
|
"",
|
|
">> The cycle continues. We will keep deciding to do better.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Gender Gap in Crash Testing",
|
|
[
|
|
"Most crash tests use 50th percentile male dummy (5'9\", 175 lbs)",
|
|
"'Small female' dummy is just a SCALED-DOWN male",
|
|
"",
|
|
"The consequences:",
|
|
" - Women are 17% more likely to DIE in equivalent crashes",
|
|
" - Women are 73% more likely to be seriously injured",
|
|
"",
|
|
"Why?",
|
|
" - Female anatomy differs: hip structure, neck strength",
|
|
" - Women sit closer to steering wheel (shorter legs)",
|
|
" - Seatbelt geometry optimized for male torsos",
|
|
"",
|
|
"The solution (in progress):",
|
|
" - THOR-5F (2023): First 'true female' dummy",
|
|
" - Not a scaled male - different skeletal structure",
|
|
"",
|
|
">> We are deciding that 'average' can't mean 'male' anymore.",
|
|
],
|
|
image_file="thor_male_female.jpg",
|
|
)
|
|
|
|
add_content_slide(
|
|
"The ATD Evolution",
|
|
[
|
|
"1949: Sierra Sam - first crash test dummy (USAF ejection seats)",
|
|
"1976: Hybrid III - still the global standard, ~47 channels",
|
|
"2013: THOR-50M - 150+ channels, more biofidelic",
|
|
"2015: WIAMan - military blast dummy (DTS partnership)",
|
|
"2023: THOR-5F - first true female dummy",
|
|
"",
|
|
"The trend: More biofidelic, more instrumentation, more data",
|
|
"",
|
|
"Channel count matters:",
|
|
" - More channels = more data = better understanding",
|
|
" - Better understanding = smarter engineering = more lives saved",
|
|
"",
|
|
"DTS provides the nervous system that gives dummies their 'senses'.",
|
|
],
|
|
image_file="atd_family.png",
|
|
)
|
|
|
|
add_image_slide(
|
|
"WIAMan: DTS Partnership for Military Safety",
|
|
"wiaman_dummy.jpg",
|
|
"Warrior Injury Assessment Manikin - developed with DTS for underbody blast testing",
|
|
)
|
|
|
|
add_quote_slide(
|
|
"A crashed car is gone forever. The data is what remains.", "Industry saying"
|
|
)
|
|
|
|
add_content_slide(
|
|
"Why Data Quality Matters",
|
|
[
|
|
"A single crash test costs $50,000 - $500,000+:",
|
|
" - Test vehicle: $30,000 - $80,000 (destroyed)",
|
|
" - ATD (Hybrid III 50th): $200,000 - $400,000",
|
|
" - ATD (THOR): $500,000 - $800,000",
|
|
" - Facility, personnel, analysis",
|
|
"",
|
|
"The vehicle is destroyed in 100 milliseconds.",
|
|
"ALL VALUE is captured in the data.",
|
|
"",
|
|
"If a sensor fails, if a channel drops, if data is questionable:",
|
|
" - You might have to repeat the entire test",
|
|
" - $100K+ repeat cost, weeks of delay",
|
|
"",
|
|
"DTS data acquisition is a fraction of test cost",
|
|
"but captures 100% of the value.",
|
|
],
|
|
image_file="iihs_dummy_sensors.jpg",
|
|
)
|
|
|
|
add_stat_slide(
|
|
"117,000",
|
|
"Lives saved per year compared to 1970 rates",
|
|
"1970 rate applied to today's VMT: 153,000 deaths | Actual: 36,000 | Difference: 117,000",
|
|
)
|
|
|
|
add_content_slide(
|
|
"Each of Those Lives Was Saved By:",
|
|
[
|
|
"A TRAGEDY that revealed a problem",
|
|
" - Steering column deaths, Pinto fires, football fatalities",
|
|
"",
|
|
"A DECISION that we needed to do better",
|
|
" - Congress, NHTSA, IIHS, NOCSAE, consumers demanding change",
|
|
"",
|
|
"DATA that revealed the mechanism of injury",
|
|
" - Cadaver research, rocket sled tests, crash tests",
|
|
"",
|
|
"A TEST that measured the problem",
|
|
" - FMVSS 208, IIHS Small Overlap, NOCSAE drop test",
|
|
"",
|
|
"ENGINEERING that solved it",
|
|
" - Seatbelts, airbags, crumple zones, helmets",
|
|
"",
|
|
"DTS is in this chain - capturing the data that drives solutions.",
|
|
],
|
|
)
|
|
|
|
add_content_slide(
|
|
"The Culture DTS Was Built On",
|
|
[
|
|
"DTS was founded to serve this mission:",
|
|
" - Innovative solutions for crash test data acquisition",
|
|
" - Reliability when every data point matters",
|
|
" - Accuracy that engineers can trust",
|
|
"",
|
|
"This isn't just a business. It's life-saving work.",
|
|
"",
|
|
"When NHTSA runs a compliance test - DTS captures the data.",
|
|
"When IIHS rates a vehicle - DTS captures the data.",
|
|
"When a university studies injury biomechanics - DTS captures the data.",
|
|
"When the NFL tests helmet safety - DTS captures the data.",
|
|
"",
|
|
">> We help the people who decided to do better",
|
|
">> actually measure whether they succeeded.",
|
|
],
|
|
image_file="iihs_crash_hall.jpg",
|
|
)
|
|
|
|
add_title_slide(
|
|
"Data Saves Lives",
|
|
"Every test has a story. Every story started with tragedy.\nEvery tragedy ended when we got the data to understand it.",
|
|
)
|
|
|
|
add_title_slide("Questions?", "DTS: The data that makes safety testing possible.")
|
|
|
|
# Save the presentation
|
|
output_file = "Data_Saves_Lives_v3.pptx"
|
|
prs.save(output_file)
|
|
print(f"Presentation created: {output_file}")
|
|
print(f"Total slides: {len(prs.slides)}")
|
|
|
|
# Report on images used
|
|
print("\nImages embedded from assets/:")
|
|
for f in os.listdir(ASSET_DIR):
|
|
if f.endswith((".jpg", ".png", ".jpeg")):
|
|
size = os.path.getsize(os.path.join(ASSET_DIR, f))
|
|
if size > 10000: # Only count real images
|
|
print(f" - {f} ({size // 1024}KB)")
|