#!/usr/bin/env python3 """ Create PowerPoint: The Stories Our Data Tells How DTS Helps Save Lives - 45 minute internal presentation """ import os import sys # Add parent directory to path for shared assets sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 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) # Color scheme - DTS-inspired professional blue DARK_BLUE = RGBColor(0, 48, 87) # Deep navy ACCENT_BLUE = RGBColor(0, 120, 174) # Bright blue LIGHT_BLUE = RGBColor(173, 216, 230) # Light accent DARK_GRAY = RGBColor(51, 51, 51) LIGHT_GRAY = RGBColor(245, 245, 245) WHITE = RGBColor(255, 255, 255) ACCENT_ORANGE = RGBColor(230, 126, 34) HIGHLIGHT_RED = RGBColor(192, 57, 43) def add_title_slide(title, subtitle=""): """Full-bleed title slide""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Dark blue background bg = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, prs.slide_width, prs.slide_height ) bg.fill.solid() bg.fill.fore_color.rgb = DARK_BLUE bg.line.fill.background() # Title title_box = slide.shapes.add_textbox( Inches(0.5), Inches(2.8), Inches(12.333), Inches(1.5) ) tf = title_box.text_frame p = tf.paragraphs[0] p.text = title p.font.size = Pt(60) 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(4.5), Inches(12.333), Inches(0.8) ) tf = sub_box.text_frame p = tf.paragraphs[0] p.text = subtitle p.font.size = Pt(28) p.font.color.rgb = LIGHT_BLUE p.alignment = PP_ALIGN.CENTER return slide def add_section_slide(title, subtitle=""): """Section divider with accent bar""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Left accent bar bar = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, Inches(0.4), prs.slide_height ) bar.fill.solid() bar.fill.fore_color.rgb = ACCENT_BLUE bar.line.fill.background() # Section title title_box = slide.shapes.add_textbox(Inches(1), Inches(2.5), Inches(11), Inches(2)) tf = title_box.text_frame p = tf.paragraphs[0] p.text = title p.font.size = Pt(48) p.font.bold = True p.font.color.rgb = DARK_BLUE if subtitle: p = tf.add_paragraph() p.text = subtitle p.font.size = Pt(24) p.font.color.rgb = DARK_GRAY return slide def add_stat_slide(number, description, context=""): """Big number impact slide""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Number num_box = slide.shapes.add_textbox( Inches(0.5), Inches(2), Inches(12.333), Inches(2.5) ) tf = num_box.text_frame p = tf.paragraphs[0] p.text = number p.font.size = Pt(144) 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.5), Inches(12.333), Inches(1) ) tf = desc_box.text_frame p = tf.paragraphs[0] p.text = description p.font.size = Pt(32) p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER if context: ctx_box = slide.shapes.add_textbox( Inches(1), Inches(5.8), Inches(11.333), Inches(1) ) tf = ctx_box.text_frame p = tf.paragraphs[0] p.text = context p.font.size = Pt(18) p.font.italic = True p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER return slide def add_quote_slide(quote, attribution=""): """Quote slide with large text""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Quote 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(36) 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.5), Inches(11.333), Inches(0.5) ) tf = attr_box.text_frame p = tf.paragraphs[0] p.text = f"- {attribution}" p.font.size = Pt(20) p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER return slide def add_content_slide(title, bullets, subtitle=""): """Standard content slide with bullets""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Header bar header = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, prs.slide_width, Inches(1.2) ) header.fill.solid() header.fill.fore_color.rgb = DARK_BLUE header.line.fill.background() # Title title_box = slide.shapes.add_textbox( Inches(0.5), Inches(0.25), Inches(12), Inches(0.9) ) 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 = WHITE # Subtitle in header if subtitle: sub_box = slide.shapes.add_textbox( Inches(0.5), Inches(0.75), Inches(12), Inches(0.4) ) tf = sub_box.text_frame p = tf.paragraphs[0] p.text = subtitle p.font.size = Pt(16) p.font.color.rgb = LIGHT_BLUE # Bullets bullet_box = slide.shapes.add_textbox( Inches(0.8), Inches(1.6), Inches(11.5), Inches(5.5) ) tf = bullet_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() p.text = f" {bullet}" p.font.size = Pt(24) p.font.color.rgb = DARK_GRAY p.space_after = Pt(18) return slide def add_two_column_slide(title, left_title, left_items, right_title, right_items): """Two column comparison slide""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Header header = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, prs.slide_width, Inches(1.0) ) header.fill.solid() header.fill.fore_color.rgb = DARK_BLUE header.line.fill.background() title_box = slide.shapes.add_textbox( Inches(0.5), Inches(0.2), Inches(12), Inches(0.7) ) 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 = WHITE # Left column title left_title_box = slide.shapes.add_textbox( Inches(0.5), Inches(1.3), Inches(6), Inches(0.5) ) tf = left_title_box.text_frame p = tf.paragraphs[0] p.text = left_title p.font.size = Pt(22) p.font.bold = True p.font.color.rgb = ACCENT_BLUE # Left items left_box = slide.shapes.add_textbox( Inches(0.5), Inches(1.9), Inches(5.8), Inches(5) ) tf = left_box.text_frame tf.word_wrap = True for i, item in enumerate(left_items): if i == 0: p = tf.paragraphs[0] else: p = tf.add_paragraph() p.text = f" {item}" p.font.size = Pt(18) p.font.color.rgb = DARK_GRAY p.space_after = Pt(10) # Divider line divider = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, Inches(6.5), Inches(1.3), Inches(0.02), Inches(5.5) ) divider.fill.solid() divider.fill.fore_color.rgb = LIGHT_BLUE divider.line.fill.background() # Right column title right_title_box = slide.shapes.add_textbox( Inches(6.8), Inches(1.3), Inches(6), Inches(0.5) ) tf = right_title_box.text_frame p = tf.paragraphs[0] p.text = right_title p.font.size = Pt(22) p.font.bold = True p.font.color.rgb = ACCENT_BLUE # Right items right_box = slide.shapes.add_textbox(Inches(6.8), Inches(1.9), Inches(6), Inches(5)) tf = right_box.text_frame tf.word_wrap = True for i, item in enumerate(right_items): if i == 0: p = tf.paragraphs[0] else: p = tf.add_paragraph() p.text = f" {item}" p.font.size = Pt(18) p.font.color.rgb = DARK_GRAY p.space_after = Pt(10) return slide def add_story_headline_slide(headline, subtext=""): """Newspaper-style headline slide""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Light gray "newspaper" background bg = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, Inches(0.5), Inches(1.5), Inches(12.333), Inches(4.5) ) bg.fill.solid() bg.fill.fore_color.rgb = LIGHT_GRAY bg.line.color.rgb = DARK_GRAY # Headline headline_box = slide.shapes.add_textbox( Inches(1), Inches(2.5), Inches(11.333), Inches(2) ) tf = headline_box.text_frame tf.word_wrap = True p = tf.paragraphs[0] p.text = headline p.font.size = Pt(44) p.font.bold = True p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER if subtext: sub_box = slide.shapes.add_textbox( Inches(1), Inches(4.8), Inches(11.333), Inches(0.8) ) tf = sub_box.text_frame p = tf.paragraphs[0] p.text = subtext p.font.size = Pt(24) p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER return slide def add_graph_placeholder_slide(title, graph_description, caption=""): """Slide with placeholder for graph/chart""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Header header = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, prs.slide_width, Inches(1.0) ) header.fill.solid() header.fill.fore_color.rgb = DARK_BLUE header.line.fill.background() title_box = slide.shapes.add_textbox( Inches(0.5), Inches(0.2), Inches(12), Inches(0.7) ) 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 = WHITE # Graph placeholder graph = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, Inches(1), Inches(1.5), Inches(11.333), Inches(4.5) ) graph.fill.solid() graph.fill.fore_color.rgb = LIGHT_GRAY graph.line.color.rgb = ACCENT_BLUE # Graph description desc_box = slide.shapes.add_textbox( Inches(1), Inches(3.3), Inches(11.333), Inches(1) ) tf = desc_box.text_frame p = tf.paragraphs[0] p.text = f"[{graph_description}]" p.font.size = Pt(24) p.font.color.rgb = DARK_GRAY p.alignment = PP_ALIGN.CENTER if caption: cap_box = slide.shapes.add_textbox( Inches(1), Inches(6.3), Inches(11.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 def add_connection_slide(title, connections): """Show flow/connection between concepts""" slide = prs.slides.add_slide(prs.slide_layouts[6]) # Header header = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, 0, 0, prs.slide_width, Inches(1.0) ) header.fill.solid() header.fill.fore_color.rgb = DARK_BLUE header.line.fill.background() title_box = slide.shapes.add_textbox( Inches(0.5), Inches(0.2), Inches(12), Inches(0.7) ) 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 = WHITE # Connection boxes num_items = len(connections) box_width = Inches(2.2) spacing = (prs.slide_width - box_width * num_items) / (num_items + 1) for i, item in enumerate(connections): x = spacing + i * (box_width + spacing) # Box box = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, x, Inches(3), box_width, Inches(1.5) ) box.fill.solid() box.fill.fore_color.rgb = ACCENT_BLUE if i % 2 == 0 else DARK_BLUE box.line.fill.background() # Text text_box = slide.shapes.add_textbox(x, Inches(3.3), box_width, Inches(1)) tf = text_box.text_frame tf.word_wrap = True p = tf.paragraphs[0] p.text = item p.font.size = Pt(16) p.font.bold = True p.font.color.rgb = WHITE p.alignment = PP_ALIGN.CENTER # Arrow (except for last) if i < num_items - 1: arrow = slide.shapes.add_shape( MSO_SHAPE.RIGHT_ARROW, x + box_width + Inches(0.1), Inches(3.5), spacing - Inches(0.2), Inches(0.5), ) arrow.fill.solid() arrow.fill.fore_color.rgb = LIGHT_BLUE arrow.line.fill.background() return slide # ============================================================================ # BUILD THE PRESENTATION # ============================================================================ # Slide 1: Title add_title_slide("The Stories Our Data Tells", "How DTS Helps Save Lives") # Slide 2: The Number That Matters add_stat_slide( "117,000", "Lives saved every year in the U.S. alone", "Compared to 1970 fatality rates - a 77% reduction per mile driven", ) # Slide 3: Quote - Crashed Car add_quote_slide( "A crashed car is destroyed in milliseconds. The data is what remains.", "The foundation of safety engineering", ) # Slide 4: Section - Part 1 add_section_slide("PART 1", "The Data Behind the Headlines") # Slide 5: Story 1 - Airbag Headline add_story_headline_slide( "Airbag Kills Child in Minor Crash", "1990s Airbag Crisis - 175+ deaths from safety devices", ) # Slide 6: What the Data Revealed add_content_slide( "What the Data Revealed", [ "Early airbags designed for one scenario only:", " Unbelted 50th percentile male in 30 mph crash", "Inflation speed: ~200 mph", "Actual occupants hit: Children, small women, close-sitters", "Neck loads in small dummies: Off the charts", "Data from out-of-position testing showed fatal forces", ], "Instrumented testing exposed the deadly design flaw", ) # Slide 7: Engineering Response add_content_slide( "The Engineering Response", [ "1998: Immediate depowering (20-35% force reduction)", "Dual-stage inflators: Variable deployment force", "Occupant classification: Weight sensors in seats", "Suppression systems: Turn off for rear-facing child seats", "Multi-stage deployment: Match force to crash severity", "Result: Deaths dropped from 50+/year to near zero", ], "Every solution required new testing with instrumented dummies", ) # Slide 8: DTS Connection - Airbags add_content_slide( "The DTS Connection", [ "OOP testing requires precise measurements in small packages", "Forces on child dummy necks", "Acceleration of infant heads", "Chest deflection of 5th percentile female", "DTS accelerometers in CRABI infant dummy", "DTS DAQ captures millisecond-by-millisecond events", ], "Without this data: No depowering. No dual-stage. More dead children.", ) # Slide 9: Story 2 - Small Overlap add_story_headline_slide( "Luxury Cars Fail New Crash Test", "2012 Small Overlap Shock - Premium brands exposed", ) # Slide 10: The Results add_two_column_slide( "The 2012 Small Overlap Results", "FAILED (Marginal/Poor)", [ "BMW 5-Series: Marginal", "Mercedes C-Class: Marginal", "Audi A4: Marginal", "Lexus ES: Poor", "Volkswagen Passat: Marginal", "", "Only 3 of 13 midsize cars", "earned 'Good' rating", ], "WHY THEY FAILED", [ "Structure bypassed main rails", "Wheels pushed into footwell", "Firewalls collapsed", "Steering columns displaced", "Feet trapped in crushed metal", "", "The dummies told the story:", "HIC exceeded limits, leg loads critical", ], ) # Slide 11: Industry Response add_content_slide( "The Industry Response", [ "Fundamental redesign of front structures", "Small overlap-specific load paths added", "Extended bumper beams", "Reinforced A-pillars", "Modified wheel well geometry", "By 2015: Most vehicles earning 'Good' ratings", ], "Every redesign validated with crash testing and instrumented dummies", ) # Slide 12: Story 3 - Football add_story_headline_slide( "The Sport That Was Killing Players", "1960s-70s: 32 football deaths per year from head injuries", ) # Slide 13: NOCSAE Solution add_content_slide( "The NOCSAE Solution", [ "1969: National Operating Committee formed", "Developed the drop test: Helmeted headform from 60 inches", "Instrumented with accelerometers", "Metric: Severity Index (SI) < 1200", "Simple. Repeatable. Science-based.", "Standard mandated in 1980", ], "A measurement standard that would actually prevent deaths", ) # Slide 14: Football Results add_graph_placeholder_slide( "Football Fatalities: Before and After", "Graph: Deaths per year - 32 (1970) dropping to 8 (1980) to 3 (2020)", "90% reduction in fatalities - from helmets validated with instrumented testing", ) # Slide 15: Section - Part 2 add_section_slide("PART 2", "Customers You Didn't Know You Had") # Slide 16: Surprising Applications Overview add_content_slide( "DTS Equipment: Beyond Automotive", [ "Military: WIAMan dummy for IED underbody blast", "Space: Astronaut protection during landing", "Theme Parks: Roller coaster acceleration limits", "Medical Devices: Implant impact testing", "Sports: Helmet certification across all sports", "Research: University biomechanics labs worldwide", ], "Same measurement principles - different life-saving applications", ) # Slide 17: WIAMan add_content_slide( "Military: The WIAMan Dummy", [ "IEDs send blast forces up through vehicle floors", "Traditional dummies designed for horizontal impact", "WIAMan: Warrior Injury Assessment Manikin", "Specifically designed for underbody blast", "DTS partnership: Instrumentation for lumbar spine loads", "Protecting soldiers' backs from being broken", ], "Not automotive - but the same mission: Use data to save lives", ) # Slide 18: Common Thread add_connection_slide( "The Common Thread", [ "Dynamic Event", "Precise Measurement", "Data Analysis", "Engineering Decision", "Lives Saved", ], ) # Slide 19: Section - Part 3 add_section_slide("PART 3", "Good Data Enables Good Decisions") # Slide 20: Good vs Bad Data add_two_column_slide( "Data Quality: Why It Matters", "GOOD DATA", [ "Clean pre-trigger baseline", "Appropriate CFC filtering", "Clear signal, no saturation", "Proper sensor range", "No zero shift after impact", "No cable artifacts", "", "= Data you can trust", "= Good engineering decisions", ], "BAD DATA", [ "Saturated signal (overranged)", "Excessive noise/interference", "Zero shift (baseline moved)", "Cable yanked = false spike", "Resonance artifacts", "Missing channels", "", "= Data you cannot trust", "= Dangerous decisions", ], ) # Slide 21: Your Decisions Matter add_content_slide( "Why This Matters for Your Work", [ "Sensor range selection: Will customers saturate?", "Mounting design: Will they get resonance artifacts?", "Calibration procedures: What's the accuracy baseline?", "Cable design: Will it survive the test?", "Software algorithms: Is filtering correct?", "", "Your decisions affect every test run with our equipment", ], "These aren't abstract - they determine if engineers can trust the data", ) # Slide 22: Ripple Effect add_connection_slide( "The Ripple Effect of Your Work", [ "DTS Product", "Customer Test", "Vehicle Design", "1M Vehicles Built", "Millions Protected", ], ) # Slide 23: Section - Closing add_section_slide("CLOSING", "Remember the Why") # Slide 24: Real Customers add_content_slide( "The Real Customers", [ "Not the test lab", "Not the automotive OEM", "Not the government regulator", "", "The real customers are the people who will sit", "in vehicles designed using our data", "", "They don't know our name - but their lives depend on us", ], "Families. Children. Commuters. Soldiers. Athletes.", ) # Slide 25: Work Isn't Done add_content_slide( "The Work Isn't Done", [ "Electric vehicles: Battery integrity, high-voltage safety", "Autonomous vehicles: Active safety validation", "Pedestrians & cyclists: Rising fatalities need solutions", "Military: Evolving threats require new testing", "Sports: Brain injury mechanisms still being discovered", "", "Every challenge will require new instrumentation, new data", ], "New challenges for the next generation of DTS products", ) # Slide 26: Final Quote add_quote_slide( "Every channel of data tells a story. Make sure it's accurate enough to save a life." ) # Slide 27: Questions add_title_slide("Questions?", "Ben - Application Engineer | [email]") # ============================================================================ # Save the presentation # ============================================================================ output_file = "The_Stories_Our_Data_Tells.pptx" prs.save(output_file) print(f"Presentation created: {output_file}") print(f"Total slides: {len(prs.slides)}")