first commit
This commit is contained in:
948
create_presentation.py
Normal file
948
create_presentation.py
Normal file
@@ -0,0 +1,948 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Create PowerPoint presentation: "Every Test Has a Story"
|
||||
Safety Testing History for DTS
|
||||
"""
|
||||
|
||||
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
|
||||
from pptx.oxml.ns import nsmap
|
||||
from pptx.oxml import parse_xml
|
||||
|
||||
# Create presentation with widescreen dimensions
|
||||
prs = Presentation()
|
||||
prs.slide_width = Inches(13.333)
|
||||
prs.slide_height = Inches(7.5)
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
def add_title_slide(title, subtitle=""):
|
||||
"""Add a title slide"""
|
||||
slide_layout = prs.slide_layouts[6] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# Title
|
||||
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
|
||||
|
||||
# Subtitle
|
||||
if subtitle:
|
||||
sub_box = slide.shapes.add_textbox(
|
||||
Inches(0.5), Inches(4.2), Inches(12.333), Inches(1)
|
||||
)
|
||||
tf = sub_box.text_frame
|
||||
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] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# Add colored background bar
|
||||
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 on bar
|
||||
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 = RGBColor(255, 255, 255)
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
|
||||
# Subtitle below bar
|
||||
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=""):
|
||||
"""Add a content slide with title and bullets"""
|
||||
slide_layout = prs.slide_layouts[6] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# 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), Inches(12.333), Inches(5.5)
|
||||
)
|
||||
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()
|
||||
|
||||
# Handle sub-bullets (indented with -)
|
||||
if bullet.startswith(" -"):
|
||||
p.text = " • " + bullet.strip().lstrip("-").strip()
|
||||
p.font.size = Pt(20)
|
||||
p.level = 1
|
||||
else:
|
||||
p.text = "• " + bullet.strip().lstrip("-").strip()
|
||||
p.font.size = Pt(24)
|
||||
p.level = 0
|
||||
|
||||
p.font.color.rgb = DARK_GRAY
|
||||
p.space_after = Pt(12)
|
||||
|
||||
# Footnote
|
||||
if footnote:
|
||||
foot_box = slide.shapes.add_textbox(
|
||||
Inches(0.5), Inches(6.8), Inches(12.333), Inches(0.5)
|
||||
)
|
||||
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] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# Quote marks background (subtle)
|
||||
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
|
||||
|
||||
# Attribution
|
||||
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] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# Big number
|
||||
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
|
||||
|
||||
# Description
|
||||
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
|
||||
|
||||
# Context
|
||||
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] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# 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()
|
||||
|
||||
# Left column title
|
||||
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 column bullets
|
||||
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(20)
|
||||
p.font.color.rgb = DARK_GRAY
|
||||
p.space_after = Pt(8)
|
||||
|
||||
# Right column title
|
||||
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 column bullets
|
||||
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(20)
|
||||
p.font.color.rgb = DARK_GRAY
|
||||
p.space_after = Pt(8)
|
||||
|
||||
return slide
|
||||
|
||||
|
||||
def add_timeline_slide(title, events):
|
||||
"""Add a timeline slide with year-event pairs"""
|
||||
slide_layout = prs.slide_layouts[6] # Blank
|
||||
slide = prs.slides.add_slide(slide_layout)
|
||||
|
||||
# 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
|
||||
|
||||
# Events
|
||||
y_pos = 1.3
|
||||
for year, event in events:
|
||||
# Year
|
||||
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(22)
|
||||
p.font.bold = True
|
||||
p.font.color.rgb = ACCENT_BLUE
|
||||
|
||||
# Event
|
||||
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(20)
|
||||
p.font.color.rgb = DARK_GRAY
|
||||
|
||||
y_pos += 0.6
|
||||
|
||||
return slide
|
||||
|
||||
|
||||
# ============================================================
|
||||
# BUILD THE PRESENTATION
|
||||
# ============================================================
|
||||
|
||||
# SLIDE 1: Title
|
||||
add_title_slide(
|
||||
"Every Test Has a Story",
|
||||
"How Tragedy, Data, and Engineering Created Modern Crash Testing",
|
||||
)
|
||||
|
||||
# SLIDE 2: The Pattern
|
||||
add_content_slide(
|
||||
"The Pattern",
|
||||
[
|
||||
"Every crash test exists because people were dying in a specific way",
|
||||
"The pattern is always the same:",
|
||||
" - TRAGEDY: People die in a specific way we don't understand",
|
||||
" - INVESTIGATION: Researchers ask 'why?'",
|
||||
" - DATA: Testing reveals the mechanism",
|
||||
" - STANDARD: A test is created to measure it",
|
||||
" - ENGINEERING: Manufacturers design to pass",
|
||||
" - LIVES SAVED: The specific death mode decreases",
|
||||
"Then a new tragedy emerges... and the cycle repeats",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE 3: The Big Number
|
||||
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\n117,000 lives saved annually compared to 1970 rates",
|
||||
)
|
||||
|
||||
# SECTION: Chapter 1 - Frontal Impact
|
||||
add_section_slide("Chapter 1: Frontal Impact", "The crash everyone thinks about")
|
||||
|
||||
# SLIDE: The Dark Age
|
||||
add_content_slide(
|
||||
"Before 1968: The Dark Age",
|
||||
[
|
||||
"No federal safety requirements existed",
|
||||
"Seatbelts were optional accessories",
|
||||
"Dashboards were solid steel and chrome",
|
||||
"Steering columns were rigid metal shafts pointed at driver's chest",
|
||||
"Over 1 MILLION people were killed by steering columns alone",
|
||||
"Industry position: 'Crashes are caused by bad drivers, not bad cars'",
|
||||
"The problem? No one had data to prove otherwise",
|
||||
],
|
||||
"Fun fact: In 1937, death rate was 14.00 per 100M VMT — nearly 13x today's rate",
|
||||
)
|
||||
|
||||
# SLIDE: FMVSS 208
|
||||
add_content_slide(
|
||||
"FMVSS 208: Where It All Began (1968)",
|
||||
[
|
||||
"First Federal Motor Vehicle Safety Standard for occupant protection",
|
||||
"Initially required only seatbelt anchorages",
|
||||
"30 mph frontal barrier test added later",
|
||||
"This one standard drove development of:",
|
||||
" - Modern seatbelt systems",
|
||||
" - Frontal airbags",
|
||||
" - Advanced restraint systems",
|
||||
"But the road to airbags was not smooth...",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Airbag Wars Timeline
|
||||
add_timeline_slide(
|
||||
"The Airbag Wars: 28 Years of Fighting",
|
||||
[
|
||||
("1970", "NHTSA proposes airbag requirement"),
|
||||
("1972", "GM offers airbags on Oldsmobiles — few buyers"),
|
||||
("1976", "Industry lobbying delays requirement"),
|
||||
("1977", "Joan Claybrook pushes airbag mandate"),
|
||||
("1981", "Reagan administration RESCINDS mandate"),
|
||||
("1983", "Supreme Court rules rescission was arbitrary"),
|
||||
("1984", "Compromise: 'automatic restraint' required"),
|
||||
("1998", "FINALLY: Frontal airbags mandatory — 28 years later"),
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Airbag Crisis
|
||||
add_content_slide(
|
||||
"The Depowering Crisis (1990s)",
|
||||
[
|
||||
"Early airbags were designed for unbelted adult males",
|
||||
"Deployed with maximum force in all crashes",
|
||||
"1990: First airbag fatality — a child in front seat",
|
||||
"1997: 53 deaths from airbag deployment (peak year)",
|
||||
" - Victims: mostly children and small women sitting close to airbag",
|
||||
"The fix (1998-2000):",
|
||||
" - 'Depowered' airbags with lower inflation force",
|
||||
" - Weight sensors to detect occupant size",
|
||||
" - Suppression systems for small occupants",
|
||||
"Today: <10 airbag deaths/year vs. ~2,800 lives saved/year",
|
||||
],
|
||||
"The data showed the problem. Better data gave us the fix.",
|
||||
)
|
||||
|
||||
# SLIDE: NCAP Introduction
|
||||
add_content_slide(
|
||||
"NHTSA NCAP: Consumer Power (1979)",
|
||||
[
|
||||
"Joan Claybrook's innovation: Test ABOVE the minimum standard",
|
||||
"35 mph instead of 30 mph — more demanding",
|
||||
"Publish results as star ratings — let consumers decide",
|
||||
"Industry reaction: 'Unfair! Misleading! Will confuse consumers!'",
|
||||
"What actually happened:",
|
||||
" - '5-star safety rating' became marketing gold",
|
||||
" - Manufacturers competed for top ratings",
|
||||
" - Model for Euro NCAP, IIHS, and programs worldwide",
|
||||
"Public data created accountability",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: IIHS Moderate Overlap
|
||||
add_content_slide(
|
||||
"IIHS Moderate Overlap (1995)",
|
||||
[
|
||||
"The problem with full frontal: Only 25% of real crashes are 'full frontal'",
|
||||
"Most crashes are offset — hitting at an angle or with one side",
|
||||
"European research showed offset crashes were MORE deadly",
|
||||
"IIHS innovation: 40% overlap into deformable barrier at 40 mph",
|
||||
"Tests structural engagement on ONE side only",
|
||||
"Early results shocked the industry:",
|
||||
" - Some '5-star' NCAP vehicles performed poorly",
|
||||
" - A-pillars folded, footwells crushed",
|
||||
"Manufacturers redesigned front structures",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Small Overlap Introduction
|
||||
add_stat_slide(
|
||||
"25%",
|
||||
"The width that changed everything",
|
||||
"In 2012, IIHS introduced the small overlap test: only 25% of the vehicle hits a rigid barrier",
|
||||
)
|
||||
|
||||
# SLIDE: Small Overlap Results
|
||||
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",
|
||||
],
|
||||
"What Passed",
|
||||
[
|
||||
"Acura TL — GOOD",
|
||||
"Volvo S60 — GOOD",
|
||||
"Infiniti G — ACCEPTABLE",
|
||||
"",
|
||||
"These were luxury vehicles that",
|
||||
"earned top marks in every other test.",
|
||||
"",
|
||||
"The small overlap exposed a",
|
||||
"critical structural blind spot.",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Small Overlap Response
|
||||
add_content_slide(
|
||||
"The Industry Response",
|
||||
[
|
||||
"Initial reaction: 'The test isn't realistic!'",
|
||||
"Then: Rapid engineering response",
|
||||
"What had to change:",
|
||||
" - Structural members added outboard of frame rails",
|
||||
" - A-pillar connection reinforced",
|
||||
" - Firewall 'blocking' structures added",
|
||||
" - Footwell intrusion resistance improved",
|
||||
"Timeline:",
|
||||
" - 2012: Most vehicles Poor or Marginal",
|
||||
" - 2014: Mixed results — some improve",
|
||||
" - 2016: Most new designs earn Good",
|
||||
" - 2017: IIHS adds PASSENGER side test (prevent asymmetric gaming)",
|
||||
],
|
||||
"Five years. From widespread failure to widespread success.",
|
||||
)
|
||||
|
||||
# SECTION: Chapter 2 - Side Impact
|
||||
add_section_slide("Chapter 2: Side Impact", "The door that wasn't a barrier")
|
||||
|
||||
# SLIDE: Side Impact Stats
|
||||
add_two_column_slide(
|
||||
"Side Impact: The Neglected Crash",
|
||||
"The Statistics",
|
||||
[
|
||||
"25% of all crashes",
|
||||
"30% of all fatalities",
|
||||
"More deadly PER CRASH than frontal",
|
||||
"",
|
||||
"Why so deadly?",
|
||||
"• Minimal crush space",
|
||||
"• No crumple zone",
|
||||
"• Direct loading to torso and head",
|
||||
],
|
||||
"The History of Neglect",
|
||||
[
|
||||
"1968: FMVSS 208 (frontal) — nothing for side",
|
||||
"1979: NCAP ratings (frontal) — nothing for side",
|
||||
"1990: First dynamic side test (FMVSS 214)",
|
||||
"2003: IIHS side test",
|
||||
"",
|
||||
"Side got serious attention",
|
||||
"25 YEARS after frontal.",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Side Airbag Revolution
|
||||
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"),
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: 2021 Side Update
|
||||
add_content_slide(
|
||||
"IIHS Side Test Update (2021)",
|
||||
[
|
||||
"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:",
|
||||
" - 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.",
|
||||
)
|
||||
|
||||
# SECTION: Chapter 3 - Rollover & Roof
|
||||
add_section_slide("Chapter 3: Rollover & Roof", "When the sky falls")
|
||||
|
||||
# SLIDE: Rollover Stats
|
||||
add_stat_slide(
|
||||
"3% → 30%",
|
||||
"Rollovers: 3% of crashes, but 30% of fatalities",
|
||||
"Ejection in rollover is 77% fatal • SUVs had higher rollover rates due to high center of gravity",
|
||||
)
|
||||
|
||||
# SLIDE: Roof Strength
|
||||
add_two_column_slide(
|
||||
"Roof Crush Resistance (FMVSS 216)",
|
||||
"The Original Standard (1973)",
|
||||
[
|
||||
"Static test: plate pressed onto roof",
|
||||
"Required: 1.5× vehicle weight",
|
||||
"Only ONE side tested",
|
||||
"This standard was unchanged for 36 YEARS",
|
||||
"",
|
||||
"Advocates argued for decades:",
|
||||
"• 1.5× is far too weak",
|
||||
"• Roofs collapse in survivable crashes",
|
||||
"• Should be 4× or higher",
|
||||
],
|
||||
"The 2009 Upgrade",
|
||||
[
|
||||
"Standard DOUBLED to 3× vehicle weight",
|
||||
"BOTH sides must be tested",
|
||||
"",
|
||||
"What changed in vehicles:",
|
||||
"• Stronger B-pillars",
|
||||
"• Reinforced roof rails",
|
||||
"• Ultra-high-strength steel",
|
||||
"",
|
||||
"IIHS pushed further: 4× for 'Good' rating",
|
||||
"Many vehicles now achieve 5-6×",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: ESC
|
||||
add_content_slide(
|
||||
"The Other Solution: Electronic Stability Control",
|
||||
[
|
||||
"Roof strength protects IN rollovers",
|
||||
"ESC PREVENTS rollovers from happening",
|
||||
"How it works:",
|
||||
" - Detects loss of control (compares steering input to actual direction)",
|
||||
" - Applies individual brakes to correct",
|
||||
" - Acts in milliseconds — faster than human reaction",
|
||||
"Effectiveness: 75% reduction in fatal single-vehicle rollovers",
|
||||
"Required by FMVSS 126 (2012)",
|
||||
"Combined with side curtain airbags = dramatically fewer rollover deaths",
|
||||
],
|
||||
"You prevent the rollover with ESC. If one happens anyway, the strong roof protects you.",
|
||||
)
|
||||
|
||||
# SECTION: Chapter 4 - Hidden Killers
|
||||
add_section_slide("Chapter 4: Fire & Whiplash", "The hidden killers")
|
||||
|
||||
# SLIDE: Ford Pinto
|
||||
add_content_slide(
|
||||
"FMVSS 301: The Ford Pinto Scandal",
|
||||
[
|
||||
"Post-crash fires were killing people in survivable crashes",
|
||||
"Pinto's rear-mounted fuel tank could rupture in rear impacts",
|
||||
"The infamous internal memo (1973):",
|
||||
" - Fix cost: $11/car × 12.5 million cars = $137 million",
|
||||
" - 'Acceptable' deaths: 180 × $200,000 = $36 million",
|
||||
" - FORD CHOSE NOT TO FIX THE DESIGN",
|
||||
"The reckoning:",
|
||||
" - 1977: Mother Jones exposé 'Pinto Madness'",
|
||||
" - 1978: Recall of 1.5 million Pintos",
|
||||
" - 1978: First criminal prosecution of an automaker",
|
||||
" - FMVSS 301 strengthened in direct response",
|
||||
],
|
||||
"Estimated 27-180 deaths from this single design decision",
|
||||
)
|
||||
|
||||
# SLIDE: Whiplash
|
||||
add_content_slide(
|
||||
"IIHS Head Restraints: The Whiplash Epidemic",
|
||||
[
|
||||
"Over 1 MILLION whiplash injuries per year in US",
|
||||
"Most occur in low-speed rear impacts",
|
||||
"Chronic pain can persist for years",
|
||||
"The problem with early head restraints:",
|
||||
" - Set too low (didn't support head)",
|
||||
" - Too far back (head snapped backward before contact)",
|
||||
" - Often adjusted incorrectly or removed",
|
||||
"Swedish innovation: 'Active' head restraints",
|
||||
" - Move up and forward during crash",
|
||||
" - Engage head earlier, reduce relative motion",
|
||||
"IIHS dynamic test (2004): BioRID II dummy, rewards active systems",
|
||||
],
|
||||
)
|
||||
|
||||
# SECTION: Chapter 5 - Active Safety
|
||||
add_section_slide(
|
||||
"Chapter 5: Active Safety", "From surviving crashes to preventing them"
|
||||
)
|
||||
|
||||
# SLIDE: The Shift
|
||||
add_two_column_slide(
|
||||
"The Philosophy Shift",
|
||||
"The Old Model (Passive Safety)",
|
||||
[
|
||||
"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",
|
||||
],
|
||||
"The New Model (Active Safety)",
|
||||
[
|
||||
"Try to PREVENT the crash",
|
||||
"Warn driver, brake automatically",
|
||||
"• AEB (Autonomous Emergency Braking)",
|
||||
"• ESC (Electronic Stability Control)",
|
||||
"• Lane Keeping",
|
||||
"• Blind Spot Monitoring",
|
||||
"",
|
||||
"If crash unavoidable, passive kicks in",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: AEB
|
||||
add_content_slide(
|
||||
"IIHS Front Crash Prevention (2013)",
|
||||
[
|
||||
"Tests Autonomous Emergency Braking (AEB) systems",
|
||||
"Vehicle approaches stationary target at 12 mph and 25 mph",
|
||||
"Measures: Does it warn? Does it brake? How much speed reduction?",
|
||||
"Ratings: Superior / Advanced / Basic",
|
||||
"The 2016 Industry Agreement:",
|
||||
" - 20 automakers voluntarily committed to make AEB standard",
|
||||
" - No government mandate required",
|
||||
" - Achieved by 2022",
|
||||
"The fastest safety technology adoption in history",
|
||||
"AEB reduces rear-end crashes by 50%+",
|
||||
],
|
||||
"94% of crashes involve human error. AEB reacts in milliseconds.",
|
||||
)
|
||||
|
||||
# SLIDE: Pedestrians
|
||||
add_content_slide(
|
||||
"The Pedestrian Crisis",
|
||||
[
|
||||
"While occupant deaths have FALLEN, pedestrian deaths are RISING",
|
||||
" - 2009: 4,109 pedestrian deaths",
|
||||
" - 2022: 7,500+ pedestrian deaths",
|
||||
"Why?",
|
||||
" - Larger vehicles (SUVs, trucks) dominate sales",
|
||||
" - Higher front ends hit torso/head, not legs",
|
||||
" - Distracted driving and walking (phones)",
|
||||
"IIHS Pedestrian AEB testing (2019):",
|
||||
" - Adult pedestrian target crossing road",
|
||||
" - Child pedestrian target",
|
||||
" - Day and night scenarios",
|
||||
"This is an active area of development",
|
||||
],
|
||||
)
|
||||
|
||||
# SECTION: Chapter 6 - Pedestrian Protection
|
||||
add_section_slide("Chapter 6: Pedestrian Protection", "When the car hits you")
|
||||
|
||||
# SLIDE: Euro NCAP Pedestrian
|
||||
add_content_slide(
|
||||
"Euro NCAP Pedestrian Testing (Since 1997)",
|
||||
[
|
||||
"Europe has tested pedestrian protection for 25+ years",
|
||||
"Test methods use impactors (not full pedestrian dummies):",
|
||||
" - Headform fired at hood surface",
|
||||
" - Legform fired at bumper",
|
||||
" - Measures acceleration, force, bending",
|
||||
"What it drove:",
|
||||
" - Active hood hinges (pop up to create crush space)",
|
||||
" - Energy-absorbing bumper structures",
|
||||
" - External pedestrian airbags (Volvo)",
|
||||
"US has NO federal pedestrian crashworthiness standard",
|
||||
"We test if cars AVOID pedestrians (AEB), not what happens if they don't",
|
||||
],
|
||||
"Europe: 25 years ahead. US: Playing catch-up.",
|
||||
)
|
||||
|
||||
# SECTION: Chapter 7 - Sports/Helmets
|
||||
add_section_slide("Chapter 7: Beyond Automotive", "Same physics, different arena")
|
||||
|
||||
# SLIDE: Concussion Crisis
|
||||
add_content_slide(
|
||||
"The Concussion Crisis",
|
||||
[
|
||||
"2005: Dr. Bennet Omalu publishes first CTE case in NFL player",
|
||||
"2009: NFL finally acknowledges concussion problem",
|
||||
"2011: $765 million settlement with former players",
|
||||
"The science:",
|
||||
" - Concussion: Brain injury from rapid deceleration",
|
||||
" - CTE: Degenerative disease from repeated impacts",
|
||||
" - Even 'subconcussive' impacts accumulate",
|
||||
"The question: Can better helmets reduce brain injury?",
|
||||
"Same question we answer in automotive: How do we protect the head?",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: NOCSAE
|
||||
add_stat_slide(
|
||||
"90%",
|
||||
"Reduction in football fatalities since NOCSAE standards (1973)",
|
||||
"1960s: 26 deaths/year • 1970s: 15/year • 2010s: 3/year",
|
||||
)
|
||||
|
||||
# SLIDE: Helmet Testing
|
||||
add_two_column_slide(
|
||||
"Helmet Testing Methods",
|
||||
"Drop Tower Test",
|
||||
[
|
||||
"Classic certification test",
|
||||
"Helmet on headform dropped onto anvil",
|
||||
"Measure head deceleration",
|
||||
'NOCSAE: 60" drop, SI < 1200',
|
||||
"Multiple locations tested",
|
||||
"Hot, cold, wet conditions",
|
||||
"",
|
||||
"Simple, repeatable, historical baseline",
|
||||
],
|
||||
"Linear Impactor Test",
|
||||
[
|
||||
"Newer, more game-realistic",
|
||||
"Ram fired at helmet at various angles",
|
||||
"Higher speeds achievable (20+ mph)",
|
||||
"Measures rotation, not just linear",
|
||||
"NFL/NFLPA protocol uses both",
|
||||
"",
|
||||
"Concussions may be caused more by",
|
||||
"ROTATION than linear acceleration",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Same Physics
|
||||
add_content_slide(
|
||||
"The Automotive-Sports Connection",
|
||||
[
|
||||
"Same physics, same instrumentation:",
|
||||
" - What we protect: Head, brain",
|
||||
" - Mechanism: Deceleration, rotation",
|
||||
" - Measurement: Accelerometer",
|
||||
" - Metric: HIC (auto) ≈ SI (helmets)",
|
||||
"DTS products used in BOTH:",
|
||||
" - Same accelerometers in crash dummies and helmet headforms",
|
||||
" - Same data acquisition systems",
|
||||
" - Same calibration standards",
|
||||
"Injury thresholds from automotive cadaver research",
|
||||
"inform helmet certification standards",
|
||||
"It's the same science. Same data. Different application.",
|
||||
],
|
||||
)
|
||||
|
||||
# SECTION: Closing
|
||||
add_section_slide("The Pattern Continues", "What's next?")
|
||||
|
||||
# SLIDE: The Cycle
|
||||
add_content_slide(
|
||||
"Every Test Exposed What the Previous Tests Missed",
|
||||
[
|
||||
"1968: FMVSS 208 (frontal) → but side was neglected",
|
||||
"1990: FMVSS 214 (side) → but offset crashes were 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 → gaps remain...",
|
||||
"What's next?",
|
||||
" - Rear seat occupant protection",
|
||||
" - Far-side impacts",
|
||||
" - Vehicle compatibility (small cars vs. trucks)",
|
||||
" - EV-specific tests (batteries, mass distribution)",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: The Data Thread
|
||||
add_content_slide(
|
||||
"Every Test Requires Data",
|
||||
[
|
||||
"Frontal crash: Head, chest, femur loads — DTS instrumentation",
|
||||
"Side crash: Pelvis, thorax, head loads — DTS instrumentation",
|
||||
"Roof crush: Force vs. displacement — DTS load cells",
|
||||
"Sled tests: Dummy kinematics — DTS systems",
|
||||
"AEB tests: Vehicle dynamics, timing — expanding market",
|
||||
"Pedestrian impactors: Headform acceleration — DTS accelerometers",
|
||||
"Helmet testing: Same accelerometers, same DAQ",
|
||||
"",
|
||||
"Test methods evolve. Pass/fail thresholds change.",
|
||||
"Vehicles change. DATA REQUIREMENTS REMAIN.",
|
||||
"",
|
||||
"DTS provides the data that makes every test meaningful.",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Quote
|
||||
add_quote_slide(
|
||||
"A crashed car is gone forever. The data is what remains.", "Industry saying"
|
||||
)
|
||||
|
||||
# SLIDE: Bottom Line
|
||||
add_content_slide(
|
||||
"Why This Matters",
|
||||
[
|
||||
"77% reduction in fatality rate since 1970",
|
||||
"~117,000 lives saved per year compared to 1970 rates",
|
||||
"Each of those lives was saved by:",
|
||||
" - A tragedy that revealed a problem",
|
||||
" - Research that generated data",
|
||||
" - A test that measured the problem",
|
||||
" - Engineering that solved it",
|
||||
" - Data that validated the solution",
|
||||
"DTS is in the chain at steps 2, 3, and 5.",
|
||||
"We don't make cars safer directly.",
|
||||
"We capture the data that lets engineers make cars safer.",
|
||||
"THE DATA SAVES LIVES.",
|
||||
],
|
||||
)
|
||||
|
||||
# SLIDE: Q&A
|
||||
add_title_slide(
|
||||
"Questions?",
|
||||
"Every test has a story. Every story started with tragedy.\nEvery tragedy ended when we got the data to understand it.",
|
||||
)
|
||||
|
||||
# Save the presentation
|
||||
prs.save("Every_Test_Has_a_Story.pptx")
|
||||
print("Presentation created: Every_Test_Has_a_Story.pptx")
|
||||
print(f"Total slides: {len(prs.slides)}")
|
||||
Reference in New Issue
Block a user