So I want you to replace the template to pastel watercolor in mood disorders ppt
cd /home/daytona/skills/pptx && python scripts/thumbnail.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" && mv thumbnails.jpg /home/daytona/workspace/mood_thumbnails.jpg && python scripts/thumbnail.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/pastel-watercolor-mental-health-clinic.pptx" && mv thumbnails.jpg /home/daytona/workspace/pastel_thumbnails.jpg
ls /home/daytona/skills/pptx/thumbnails*.jpg && mv /home/daytona/skills/pptx/thumbnails-1.jpg /home/daytona/workspace/mood_thumbnails-1.jpg && mv /home/daytona/skills/pptx/thumbnails-2.jpg /home/daytona/workspace/mood_thumbnails-2.jpg && mv /home/daytona/skills/pptx/thumbnails-3.jpg /home/daytona/workspace/mood_thumbnails-3.jpg
cd /home/daytona/skills/pptx && python scripts/thumbnail.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/pastel-watercolor-mental-health-clinic.pptx" && ls thumbnails*.jpg
cd /home/daytona/skills/pptx && python -m markitdown "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" 2>/dev/null | head -300
# Unpack both files mkdir -p /home/daytona/workspace/mood_unpacked /home/daytona/workspace/pastel_unpacked cd /home/daytona/skills/pptx python scripts/office/unpack.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" /home/daytona/workspace/mood_unpacked/ python scripts/office/unpack.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/pastel-watercolor-mental-health-clinic.pptx" /home/daytona/workspace/pastel_unpacked/ echo "Done unpacking"
mkdir -p /home/daytona/workspace/mood_unpacked && cd /home/daytona/skills/pptx && python scripts/office/unpack.py "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" /home/daytona/workspace/mood_unpacked/ && echo "Done"
mkdir -p /home/daytona/workspace/mood_unpacked && unzip -q "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" -d /home/daytona/workspace/mood_unpacked/ && echo "Done" && ls /home/daytona/workspace/mood_unpacked/
ls -la "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/"
cp "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/MoodDisorders_MDD_Bipolar.pptx" /home/daytona/workspace/ && cp "/home/daytona/workspace/attachments/8823a4ad-12e2-4f3c-acd6-c51314f48f14/pastel-watercolor-mental-health-clinic.pptx" /home/daytona/workspace/ && echo "Copied"
mkdir -p /home/daytona/workspace/mood_unpacked && unzip -q /home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx -d /home/daytona/workspace/mood_unpacked/ && echo "Done" && ls /home/daytona/workspace/mood_unpacked/
python3 -c " import zipfile, os os.makedirs('/home/daytona/workspace/mood_unpacked', exist_ok=True) with zipfile.ZipFile('/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx', 'r') as z: z.extractall('/home/daytona/workspace/mood_unpacked/') print('Done') print(os.listdir('/home/daytona/workspace/mood_unpacked/')) "
python3 -c "import zipfile; z=zipfile.ZipFile('/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx'); print(z.namelist()[:20])"
python3 -c " from pptx import Presentation p = Presentation('/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx') print('Slides:', len(p.slides)) for i, slide in enumerate(p.slides): print(f'Slide {i+1}:', [sh.name for sh in slide.shapes]) "
# Try to extract just the slides and key XML files without extracting media (which is large) python3 -c " import zipfile, os, io mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' with zipfile.ZipFile(mood_path) as mz: # List slides slides = [n for n in mz.namelist() if n.startswith('ppt/slides/slide') and n.endswith('.xml')] print('Mood slides:', sorted(slides)) # Check slide masters/layouts masters = [n for n in mz.namelist() if 'slideMasters' in n and n.endswith('.xml')] layouts = [n for n in mz.namelist() if 'slideLayouts' in n and n.endswith('.xml')] print('Masters:', len(masters), 'Layouts:', len(layouts)) "
python3 << 'PYEOF' import zipfile, os, io, re mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' out_path = '/home/daytona/workspace/MoodDisorders_Pastel.pptx' # Read all files from both zips into memory def read_zip(path): files = {} with zipfile.ZipFile(path, 'r') as z: for name in z.namelist(): if not name.endswith('/'): files[name] = z.read(name) return files print("Reading mood pptx...") mood = read_zip(mood_path) print(f" {len(mood)} files") print("Reading pastel pptx...") pastel = read_zip(pastel_path) print(f" {len(pastel)} files") # Check pastel structure pastel_slides = sorted([k for k in pastel if re.match(r'ppt/slides/slide\d+\.xml$', k)]) pastel_masters = [k for k in pastel if re.match(r'ppt/slideMasters/slideMaster\d+\.xml$', k)] pastel_layouts = sorted([k for k in pastel if re.match(r'ppt/slideLayouts/slideLayout\d+\.xml$', k)]) pastel_themes = [k for k in pastel if re.match(r'ppt/theme/theme\d+\.xml$', k)] print(f"Pastel: {len(pastel_slides)} slides, {len(pastel_masters)} masters, {len(pastel_layouts)} layouts, {len(pastel_themes)} themes") mood_slides = sorted([k for k in mood if re.match(r'ppt/slides/slide\d+\.xml$', k)]) print(f"Mood: {len(mood_slides)} slides") PYEOF
python3 << 'PYEOF' import zipfile, os, io, re from xml.etree import ElementTree as ET mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' out_path = '/home/daytona/workspace/MoodDisorders_Pastel.pptx' def read_zip(path): files = {} with zipfile.ZipFile(path, 'r') as z: for name in z.namelist(): if not name.endswith('/'): files[name] = z.read(name) return files print("Reading files...") mood = read_zip(mood_path) pastel = read_zip(pastel_path) # Strategy: start from pastel pptx, replace the slide content (keeping mood slides) # but rewire the slide->layout relationships to use pastel's first master/layout # The output will use pastel as the base (for theme, master, media, layouts) # and insert mood slides into it # Parse pastel presentation.xml to understand its slide list import xml.etree.ElementTree as ET NS = { 'a': 'http://schemas.openxmlformats.org/drawingml/2006/main', 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'p': 'http://schemas.openxmlformats.org/presentationml/2006/main', } # We'll build the output as: pastel base + mood slides inserted # Simple approach: take ALL files from pastel, then overlay mood slide XMLs # and update presentation.xml slide list to only have mood slides (36 slides) # pointing to layout 1 of pastel's first master output = dict(pastel) # start with full pastel # Get pastel's slide list to understand the rId->slide mapping for first slide pres_xml = pastel['ppt/presentation.xml'].decode('utf-8') pres_rels = pastel['ppt/_rels/presentation.xml.rels'].decode('utf-8') # Parse rels to find slide rIds rels_root = ET.fromstring(pres_rels) slide_rels = {r.get('Id'): r.get('Target') for r in rels_root if 'slide' in r.get('Type','') and 'Layout' not in r.get('Type','') and 'Master' not in r.get('Type','')} print(f"Pastel slide rels: {len(slide_rels)}") # Find slideLayout1 relationship - we'll point all mood slides to pastel's first layout layout_rels = {r.get('Id'): r.get('Target') for r in rels_root if 'slideLayout' in r.get('Type','') or 'slideMaster' in r.get('Type','')} print("Layout/Master rels:", layout_rels) PYEOF
python3 << 'PYEOF' import zipfile, os, io, re import xml.etree.ElementTree as ET mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' out_path = '/home/daytona/workspace/MoodDisorders_Pastel.pptx' def read_zip(path): files = {} with zipfile.ZipFile(path, 'r') as z: for name in z.namelist(): if not name.endswith('/'): files[name] = z.read(name) return files print("Reading files...") mood = read_zip(mood_path) pastel = read_zip(pastel_path) # Register namespaces to avoid ns0: prefixes ET.register_namespace('', 'http://schemas.openxmlformats.org/drawingml/2006/main') ET.register_namespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships') ET.register_namespace('p', 'http://schemas.openxmlformats.org/presentationml/2006/main') # Get mood slide files (sorted properly) mood_slide_files = sorted( [k for k in mood if re.match(r'ppt/slides/slide\d+\.xml$', k)], key=lambda x: int(re.search(r'(\d+)', x.split('/')[-1]).group(1)) ) print(f"Mood slides: {len(mood_slide_files)}") # Get pastel slide layout rels - look inside a slide's _rels to understand layout ref format # Check what layout pastel slide1 uses pastel_slide1_rels = pastel.get('ppt/slides/_rels/slide1.xml.rels', b'').decode('utf-8') print("Pastel slide1 rels:", pastel_slide1_rels[:500]) PYEOF
Where's my plt
python3 << 'PYEOF' import zipfile, re, io import xml.etree.ElementTree as ET mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' out_path = '/home/daytona/workspace/MoodDisorders_Pastel.pptx' def read_zip(path): files = {} with zipfile.ZipFile(path, 'r') as z: for name in z.namelist(): if not name.endswith('/'): files[name] = z.read(name) return files print("Reading files...") mood = read_zip(mood_path) pastel = read_zip(pastel_path) # Sorted mood slide file keys mood_slide_files = sorted( [k for k in mood if re.match(r'ppt/slides/slide\d+\.xml$', k)], key=lambda x: int(re.search(r'(\d+)', x.split('/')[-1]).group(1)) ) print(f"Mood slides: {len(mood_slide_files)}") # Pastel slide rels template - points to slideLayout1 of pastel master SLIDE_RELS_TEMPLATE = ( '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" ' 'Target="../slideLayouts/slideLayout1.xml"/>' '</Relationships>' ) # Build output: start from pastel, remove pastel slides, insert mood slides output = {} # Copy everything from pastel EXCEPT slides and their rels/notes skip_prefixes = ('ppt/slides/slide', 'ppt/slides/_rels/slide', 'ppt/notesSlides/', 'ppt/notesSlides/_rels/') for k, v in pastel.items(): if not any(k.startswith(p) for p in skip_prefixes): output[k] = v # Also copy mood media into output (merge, mood media files use different names) for k, v in mood.items(): if k.startswith('ppt/media/'): # Rename to avoid collision: mood_<filename> fname = k.split('/')[-1] new_key = f'ppt/media/mood_{fname}' output[new_key] = v # Insert mood slides (keeping their original slide XMLs) # Update each slide's rels to point to pastel's slideLayout1 for i, mood_key in enumerate(mood_slide_files, start=1): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) # Read mood slide XML and fix any internal media refs to use mood_ prefix slide_xml = mood[mood_key].decode('utf-8') # Rewrite media refs: "../media/image" -> "../media/mood_image" # But first check what media refs exist in mood slides slide_xml = re.sub(r'Target="\.\./media/([^"]+)"', lambda m: f'Target="../media/mood_{m.group(1)}"', slide_xml) # Store slide under same name output[f'ppt/slides/slide{slide_num}.xml'] = slide_xml.encode('utf-8') # Get mood slide's original rels to find any image/chart/etc rels orig_rels_key = f'ppt/slides/_rels/slide{slide_num}.xml.rels' if orig_rels_key in mood: orig_rels = mood[orig_rels_key].decode('utf-8') # Replace slideLayout reference with pastel layout1 orig_rels = re.sub( r'<Relationship[^/]*/officeDocument/2006/relationships/slideLayout[^/]*/[^"]*"[^/]*/?>', '<Relationship Id="rId1000" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>', orig_rels ) # Also fix media refs in rels orig_rels = re.sub(r'Target="\.\./media/([^"]+)"', lambda m: f'Target="../media/mood_{m.group(1)}"', orig_rels) output[orig_rels_key] = orig_rels.encode('utf-8') else: output[orig_rels_key] = SLIDE_RELS_TEMPLATE.encode('utf-8') print(f"Output files: {len(output)}") # Now update presentation.xml to list only the mood slides # Parse pastel's presentation.xml pres_xml_str = pastel['ppt/presentation.xml'].decode('utf-8') # Parse pastel pres rels to get existing rId assignments pres_rels_str = pastel['ppt/_rels/presentation.xml.rels'].decode('utf-8') rels_root = ET.fromstring(pres_rels_str) # Remove all slide rels from pastel, keep master/other rels new_rels_items = [] existing_ids = set() for r in rels_root: t = r.get('Type', '') rid = r.get('Id', '') existing_ids.add(rid) if '/slide"' in t or t.endswith('/slide'): continue # skip pastel slide refs new_rels_items.append(ET.tostring(r, encoding='unicode')) # Add mood slide rels (rId100, rId101, ...) slide_id_map = {} # slide_num -> rId for i, mood_key in enumerate(mood_slide_files): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) rid = f'rId{200 + i}' slide_id_map[slide_num] = rid new_rels_items.append( f'<Relationship Id="{rid}" ' f'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" ' f'Target="slides/slide{slide_num}.xml"/>' ) new_pres_rels = ( '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' + ''.join(new_rels_items) + '</Relationships>' ) output['ppt/_rels/presentation.xml.rels'] = new_pres_rels.encode('utf-8') # Update presentation.xml sldIdLst # Remove existing sldId entries, add mood slides import xml.etree.ElementTree as ET ET.register_namespace('', 'http://schemas.openxmlformats.org/presentationml/2006/main') ET.register_namespace('a', 'http://schemas.openxmlformats.org/drawingml/2006/main') ET.register_namespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships') ET.register_namespace('p', 'http://schemas.openxmlformats.org/presentationml/2006/main') # Simple string-based replacement for sldIdLst # Find and replace the sldIdLst block pNS = 'http://schemas.openxmlformats.org/presentationml/2006/main' rNS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' # Build new sldIdLst entries sld_entries = [] for i, mood_key in enumerate(mood_slide_files): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) rid = slide_id_map[slide_num] sld_id = 256 + i # unique IDs starting from 256 sld_entries.append( f'<p:sldId id="{sld_id}" r:id="{rid}"/>' ) new_sldIdLst = '<p:sldIdLst>' + ''.join(sld_entries) + '</p:sldIdLst>' # Replace old sldIdLst block in presentation.xml pres_xml_str = re.sub( r'<p:sldIdLst>.*?</p:sldIdLst>', new_sldIdLst, pres_xml_str, flags=re.DOTALL ) output['ppt/presentation.xml'] = pres_xml_str.encode('utf-8') # Write output zip print("Writing output PPTX...") with zipfile.ZipFile(out_path, 'w', zipfile.ZIP_DEFLATED) as zout: for name, data in output.items(): zout.writestr(name, data) size = os.path.getsize(out_path) if __import__('os').path.exists(out_path) else 0 print(f"Done! Output: {out_path} ({size:,} bytes)") PYEOF
python3 << 'PYEOF' import zipfile, re, io, os import xml.etree.ElementTree as ET mood_path = '/home/daytona/workspace/MoodDisorders_MDD_Bipolar.pptx' pastel_path = '/home/daytona/workspace/pastel-watercolor-mental-health-clinic.pptx' out_path = '/home/daytona/workspace/MoodDisorders_Pastel.pptx' def read_zip(path): files = {} with zipfile.ZipFile(path, 'r') as z: for name in z.namelist(): if not name.endswith('/'): files[name] = z.read(name) return files print("Reading files...") mood = read_zip(mood_path) pastel = read_zip(pastel_path) mood_slide_files = sorted( [k for k in mood if re.match(r'ppt/slides/slide\d+\.xml$', k)], key=lambda x: int(re.search(r'(\d+)', x.split('/')[-1]).group(1)) ) print(f"Mood slides: {len(mood_slide_files)}") SLIDE_RELS_TEMPLATE = ( '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' '<Relationship Id="rId1000" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" ' 'Target="../slideLayouts/slideLayout1.xml"/>' '</Relationships>' ) output = {} skip_prefixes = ('ppt/slides/slide', 'ppt/slides/_rels/slide', 'ppt/notesSlides/', 'ppt/notesSlides/_rels/') for k, v in pastel.items(): if not any(k.startswith(p) for p in skip_prefixes): output[k] = v # Merge mood media for k, v in mood.items(): if k.startswith('ppt/media/'): fname = k.split('/')[-1] output[f'ppt/media/mood_{fname}'] = v # Insert mood slides with fixed rels for i, mood_key in enumerate(mood_slide_files, start=1): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) slide_xml = mood[mood_key].decode('utf-8') slide_xml = re.sub(r'Target="\.\./media/([^"]+)"', lambda m: f'Target="../media/mood_{m.group(1)}"', slide_xml) output[f'ppt/slides/slide{slide_num}.xml'] = slide_xml.encode('utf-8') orig_rels_key = f'ppt/slides/_rels/slide{slide_num}.xml.rels' if orig_rels_key in mood: orig_rels = mood[orig_rels_key].decode('utf-8') orig_rels = re.sub( r'<Relationship\s[^>]*officeDocument/2006/relationships/slideLayout[^>]*/?>', '<Relationship Id="rId1000" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>', orig_rels ) orig_rels = re.sub(r'Target="\.\./media/([^"]+)"', lambda m: f'Target="../media/mood_{m.group(1)}"', orig_rels) output[orig_rels_key] = orig_rels.encode('utf-8') else: output[orig_rels_key] = SLIDE_RELS_TEMPLATE.encode('utf-8') # Rebuild presentation rels pres_rels_str = pastel['ppt/_rels/presentation.xml.rels'].decode('utf-8') rels_root = ET.fromstring(pres_rels_str) new_rels_items = [] for r in rels_root: t = r.get('Type', '') if t.endswith('/slide'): continue new_rels_items.append(ET.tostring(r, encoding='unicode')) slide_id_map = {} for i, mood_key in enumerate(mood_slide_files): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) rid = f'rId{200 + i}' slide_id_map[slide_num] = rid new_rels_items.append( f'<Relationship Id="{rid}" ' f'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" ' f'Target="slides/slide{slide_num}.xml"/>' ) new_pres_rels = ( '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' + ''.join(new_rels_items) + '</Relationships>' ) output['ppt/_rels/presentation.xml.rels'] = new_pres_rels.encode('utf-8') # Rebuild presentation.xml sldIdLst pres_xml_str = pastel['ppt/presentation.xml'].decode('utf-8') sld_entries = [] for i, mood_key in enumerate(mood_slide_files): slide_num = re.search(r'(\d+)', mood_key.split('/')[-1]).group(1) rid = slide_id_map[slide_num] sld_id = 256 + i sld_entries.append(f'<p:sldId id="{sld_id}" r:id="{rid}"/>') new_sldIdLst = '<p:sldIdLst>' + ''.join(sld_entries) + '</p:sldIdLst>' pres_xml_str = re.sub(r'<p:sldIdLst>.*?</p:sldIdLst>', new_sldIdLst, pres_xml_str, flags=re.DOTALL) output['ppt/presentation.xml'] = pres_xml_str.encode('utf-8') print(f"Output files: {len(output)}") # Write to BytesIO first, then dump to disk print("Writing to buffer...") buf = io.BytesIO() with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zout: for name, data in output.items(): zout.writestr(name, data) print("Flushing to disk...") buf.seek(0) with open(out_path, 'wb') as f: f.write(buf.read()) size = os.path.getsize(out_path) print(f"Done! {out_path} ({size:,} bytes)") PYEOF
MoodDisorders Pastel
Presentation · PPTX