Can you make ppt for poster presentation if I provide images content and template for the presentation of 10 slides
First I upload files with template then I will give images
/tmp/workspace
~/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea
Let me add more images
Few more images are there
Start
python3 -c "from docx import Document; import os; base='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea';\nfor f in ['1 Final Gastric_Emphysema_Poster_Abstract.docx','Gastric EMphysema.docx']:\n print('\\n===== '+f+' ====='); d=Document(os.path.join(base,f));\n [print(p.text) for p in d.paragraphs if p.text.strip()];\n [print(' | '.join(c.text for c in row.cells)) for t in d.tables for row in t.rows]"
python3 -c "from pptx import Presentation; p='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea/EPOSTER TEMPLATE - AP IRIA 2026_04-09-2026_v1.pptx'; prs=Presentation(p); print('SIZE',prs.slide_width,prs.slide_height,'slides',len(prs.slides));\nfor i,s in enumerate(prs.slides,1):\n print('\\n---SLIDE',i,'layout=',s.slide_layout.name);\n for sh in s.shapes:\n tx=sh.text if getattr(sh,'has_text_frame',False) else ''; print(sh.shape_type, sh.name, round(sh.left/914400,2),round(sh.top/914400,2),round(sh.width/914400,2),round(sh.height/914400,2),repr(tx[:300]))"
"gastric emphysema" AND "emphysematous gastritis"
gastric emphysema CT imaging differentiation emphysematous gastritis review
python3 -c "exec(\"from docx import Document\\nimport os\\nbase='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea'\\nfor f in ['1 Final Gastric_Emphysema_Poster_Abstract.docx','Gastric EMphysema.docx']:\\n print('===== '+f+' =====')\\n d=Document(os.path.join(base,f))\\n for p in d.paragraphs:\\n if p.text.strip(): print(p.text)\\n for t in d.tables:\\n for row in t.rows: print(' | '.join(c.text for c in row.cells))\")"
python3 -c "exec(\"from pptx import Presentation\\np='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea/EPOSTER TEMPLATE - AP IRIA 2026_04-09-2026_v1.pptx'\\nprs=Presentation(p)\\nprint('SIZE',prs.slide_width,prs.slide_height,'slides',len(prs.slides))\\nfor i,s in enumerate(prs.slides,1):\\n print('---SLIDE',i,'layout=',s.slide_layout.name)\\n for sh in s.shapes:\\n tx=sh.text if getattr(sh,'has_text_frame',False) else ''\\n print(sh.shape_type,sh.name,round(sh.left/914400,2),round(sh.top/914400,2),round(sh.width/914400,2),round(sh.height/914400,2),repr(tx[:200]))\")"
/tmp/workspace
~/build_poster.py
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR
from PIL import Image
import os, shutil
BASE='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea'
TEMPLATE=os.path.join(BASE,'EPOSTER TEMPLATE - AP IRIA 2026_04-09-2026_v1.pptx')
OUTDIR='/tmp/workspace/gastric-emphysema-poster/output'
os.makedirs(OUTDIR,exist_ok=True)
OUT=os.path.join(OUTDIR,'Gastric_Emphysema_AP_IRIA_2026_EPoster.pptx')
prs=Presentation(TEMPLATE)
# use branded blank slide as a base only for logo extraction, then clear all slides
logo_blob=None
if prs.slides and prs.slides[0].shapes:
for sh in prs.slides[0].shapes:
if hasattr(sh,'image'):
logo_blob=sh.image.blob
break
while len(prs.slides):
rId=prs.slides._sldIdLst[0].rId
prs.part.drop_rel(rId)
del prs.slides._sldIdLst[0]
W,H=prs.slide_width, prs.slide_height
NAVY=RGBColor(8,48,88); BLUE=RGBColor(11,93,150); TEAL=RGBColor(0,145,170); SKY=RGBColor(229,244,248)
DARK=RGBColor(30,39,48); MID=RGBColor(82,94,104); WHITE=RGBColor(255,255,255); LIGHT=RGBColor(244,247,249); RED=RGBColor(171,55,55); GREEN=RGBColor(33,120,83)
imgs={k:os.path.join(BASE,v) for k,v in {
'cor1':'IMG-0006-00001.jpeg','cor2':'IMG-0007-00001.jpeg','ax1':'IMG-0009-00001.jpeg','ax2':'IMG-0004-00001.jpeg','sag':'IMG-0012-00001 2.jpeg','ax3':'IMG-0011-00001.jpeg','ax4':'IMG-0003-00001.jpeg','cor3':'IMG-0002-00001.jpeg','ax5':'IMG-0005-00001.jpeg'}.items()}
def rect(s,x,y,w,h,fill,line=None,r=False):
sh=s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE if r else MSO_SHAPE.RECTANGLE, Inches(x),Inches(y),Inches(w),Inches(h))
sh.fill.solid(); sh.fill.fore_color.rgb=fill
sh.line.color.rgb=line if line else fill
if r: sh.adjustments[0]=0.08
return sh
def textbox(s,x,y,w,h,text,size=12,color=DARK,bold=False,align=PP_ALIGN.LEFT, font='Aptos', margin=0.04, valign=MSO_ANCHOR.TOP):
tb=s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf=tb.text_frame; tf.clear(); tf.word_wrap=True; tf.margin_left=Inches(margin); tf.margin_right=Inches(margin); tf.margin_top=Inches(margin); tf.margin_bottom=Inches(margin); tf.vertical_anchor=valign
for idx,line in enumerate(text.split('\n')):
p=tf.paragraphs[0] if idx==0 else tf.add_paragraph(); p.text=line; p.alignment=align
p.font.name=font; p.font.size=Pt(size); p.font.bold=bold; p.font.color.rgb=color
p.space_after=Pt(0)
return tb
def bullets(s,x,y,w,h,items,size=11.2,color=DARK):
tb=s.shapes.add_textbox(Inches(x),Inches(y),Inches(w),Inches(h)); tf=tb.text_frame; tf.clear(); tf.word_wrap=True
tf.margin_left=Inches(.08); tf.margin_right=Inches(.03); tf.margin_top=Inches(.03); tf.margin_bottom=Inches(.01)
for i,item in enumerate(items):
p=tf.paragraphs[0] if i==0 else tf.add_paragraph(); p.text=item; p.level=0; p.font.name='Aptos'; p.font.size=Pt(size); p.font.color.rgb=color; p.space_after=Pt(5); p.bullet=True
return tb
def add_image_cover(s,path,x,y,w,h):
im=Image.open(path); iw,ih=im.size; ar=iw/ih; box=w/h
if ar>box:
cropw=ih*box; left=(iw-cropw)/2; crop=(left,0,left+cropw,ih)
else:
croph=iw/box; top=(ih-croph)/2; crop=(0,top,iw,top+croph)
# crop to a temporary file
name=os.path.basename(path).replace('.jpeg','')+f'_{x}_{y}.jpg'; temp=os.path.join(OUTDIR,name)
im.crop(tuple(map(int,crop))).save(temp,quality=95)
s.shapes.add_picture(temp, Inches(x), Inches(y), width=Inches(w),height=Inches(h))
def image_panel(s,path,x,y,w,h,label):
rect(s,x-.025,y-.025,w+.05,h+.05,WHITE,TEAL)
add_image_cover(s,path,x,y,w,h)
textbox(s,x,y+h+.025,w,.19,label,7.3,MID,False,PP_ALIGN.CENTER,margin=0)
def base(title,num,subtitle=None):
s=prs.slides.add_slide(prs.slide_layouts[0])
rect(s,0,0,7.56,.47,NAVY)
rect(s,0,.47,7.56,.045,TEAL)
textbox(s,.28,.075,5.9,.26,title,18,WHITE,True,margin=0,valign=MSO_ANCHOR.MIDDLE)
if logo_blob:
import io
s.shapes.add_picture(io.BytesIO(logo_blob),Inches(4.70),Inches(0),width=Inches(2.86),height=Inches(.52))
if subtitle: textbox(s,.3,.57,6.85,.25,subtitle,8.5,MID,False,margin=0)
textbox(s,.28,4.03,6.6,.12,'AP IRIA 2026 | Gastrointestinal Tract and Hepatobiliary & Pancreatic Imaging',6.8,MID,False,margin=0)
textbox(s,7.04,4.01,.24,.14,f'{num}/10',7.2,MID,True,PP_ALIGN.RIGHT,margin=0)
return s
def section(s,x,y,w,title):
rect(s,x,y,w,.29,SKY,TEAL)
textbox(s,x+.08,y+.045,w-.14,.16,title.upper(),9,BLUE,True,margin=0)
def stat(s,x,y,w,h,value,label,color=BLUE):
rect(s,x,y,w,h,WHITE,RGBColor(204,220,230),True)
textbox(s,x+.05,y+.08,w-.1,.29,value,19,color,True,PP_ALIGN.CENTER,margin=0)
textbox(s,x+.05,y+.43,w-.1,.22,label,7.8,MID,False,PP_ALIGN.CENTER,margin=0)
# 1
s=base('DON\'T OPERATE ON AIR',1)
textbox(s,.36,.77,4.7,.58,'Gastric emphysema from pancreatic head adenocarcinoma',23,NAVY,True,margin=0)
textbox(s,.38,1.39,4.55,.32,'A case-based distinction from emphysematous gastritis',13,TEAL,True,margin=0)
rect(s,.36,1.91,3.65,.55,SKY,TEAL,True)
textbox(s,.51,2.02,3.35,.17,'75-year-old man | malignant gastric outlet obstruction',10,BLUE,True,margin=0)
textbox(s,.38,2.72,3.8,.54,'Dr. Namala Sri Ram Praveen Kumar\nDr. L. Peethamber | Dr. K.J.S.S. Raghu Teja',11,DARK,False,margin=0)
textbox(s,.38,3.36,3.8,.22,'GITAM Institute of Medical Science & Research',9,MID,False,margin=0)
image_panel(s,imgs['ax1'],4.78,.82,2.23,2.48,'Axial CECT: linear intramural gastric air')
textbox(s,4.79,3.47,2.15,.24,'Conference registration no. 705',7.8,MID,False,PP_ALIGN.CENTER,margin=0)
#2
s=base('BACKGROUND AND OBJECTIVE',2)
section(s,.32,.78,3.25,'Why this matters')
bullets(s,.39,1.16,3.1,1.37,["Intramural gastric air is uncommon but clinically consequential.","Gastric emphysema is mechanical or ischaemic mucosal disruption with dissection of air into the wall.","Emphysematous gastritis represents gas-forming infection and may be fulminant."],10.5)
section(s,.32,2.72,3.25,'Objective')
bullets(s,.39,3.10,3.1,.67,["Demonstrate CT features of gastric emphysema and pneumoperitoneum caused by malignant gastric outlet obstruction.","Highlight discriminators that prevent unnecessary surgery."],10.2)
image_panel(s,imgs['cor1'],4.05,.81,1.45,2.68,'Coronal CECT')
image_panel(s,imgs['ax5'],5.75,.81,1.45,2.68,'Axial CECT')
textbox(s,4.05,3.58,3.15,.24,'CT is highly sensitive for detection of gas within the gastric wall.',8.5,BLUE,True,PP_ALIGN.CENTER,margin=0)
#3
s=base('CASE PRESENTATION',3,'Painless jaundice, recurrent postprandial haematemesis and marked weight loss')
section(s,.34,.88,2.05,'Clinical profile')
bullets(s,.41,1.27,1.9,1.65,["75-year-old man", "Hypertension for 10 years", "No addictions", "ECOG performance status 3", "Icterus; tender abdomen with guarding"],10.2)
section(s,2.64,.88,2.22,'Symptoms')
bullets(s,2.71,1.27,2.05,1.68,["Brown, food-containing emesis after meals", "Frequency increased to 5-6 episodes/day", "Postprandial discomfort relieved by vomiting", "Unintentional weight loss >10 kg in 1 month"],10.2)
section(s,5.13,.88,2.05,'Diagnostic question')
textbox(s,5.27,1.35,1.75,.85,'Is mural gastric air a surgical emergency, or a mechanical consequence of obstruction?',14,NAVY,True,PP_ALIGN.CENTER,margin=0,valign=MSO_ANCHOR.MIDDLE)
rect(s,5.35,2.48,1.45,.45,TEAL,TEAL,True); textbox(s,5.45,2.60,1.25,.15,'CECT ABDOMEN',9,WHITE,True,PP_ALIGN.CENTER,margin=0)
#4
s=base('LABORATORY PROFILE',4,'Biochemistry supported obstructive jaundice in the setting of a pancreatic head lesion')
stat(s,.42,.95,1.35,.9,'16.7','Total bilirubin mg/dL',RED)
stat(s,1.95,.95,1.35,.9,'10.8','Direct bilirubin mg/dL',RED)
stat(s,3.48,.95,1.35,.9,'>10,000','CA 19-9 IU/mL',RED)
stat(s,5.01,.95,1.35,.9,'4.76','AFP IU/mL',GREEN)
section(s,.42,2.15,5.95,'Other relevant values')
rect(s,.43,2.55,5.93,.74,LIGHT,RGBColor(207,220,228),True)
textbox(s,.62,2.68,5.54,.20,'AST 324.2 IU/L • ALT 287.3 IU/L • Serum lipase 127.4 U/L',12,NAVY,True,PP_ALIGN.CENTER,margin=0)
textbox(s,.54,3.53,5.85,.23,'Pattern: cholestasis with elevated tumour marker, directing attention to pancreaticobiliary obstruction.',10,BLUE,False,PP_ALIGN.CENTER,margin=0)
#5
s=base('CECT: GASTRIC EMPHYSEMA AND PNEUMOPERITONEUM',5,'The decisive finding was a linear pattern of mural gas without gastric wall thickening')
image_panel(s,imgs['ax1'],.36,.85,2.05,2.25,'A. Axial: intramural air along gastric wall')
image_panel(s,imgs['ax2'],2.75,.85,2.05,2.25,'B. Axial: distended stomach with mural air')
image_panel(s,imgs['cor1'],5.14,.85,2.05,2.25,'C. Coronal: mural air and free intraperitoneal gas')
rect(s,.46,3.40,6.56,.38,SKY,TEAL,True)
textbox(s,.64,3.50,6.19,.16,'Linear intramural gas + no mural thickening + compatible mechanical context = gastric emphysema favoured.',10.1,NAVY,True,PP_ALIGN.CENTER,margin=0)
#6
s=base('UNDERLYING CAUSE: PANCREATIC HEAD ADENOCARCINOMA',6,'A pancreatic head mass produced gastric outlet obstruction and raised intragastric pressure')
image_panel(s,imgs['ax3'],.38,.82,2.03,2.28,'D. Axial: pancreatic head region')
image_panel(s,imgs['ax4'],2.77,.82,2.03,2.28,'E. Axial: gastroduodenal involvement')
image_panel(s,imgs['cor3'],5.16,.82,2.03,2.28,'F. Coronal: malignant obstruction')
section(s,.43,3.34,6.32,'Key CECT findings')
bullets(s,.54,3.70,6.08,.24,["Heterogeneously enhancing pancreatic head mass with abrupt main pancreatic duct cut-off, upstream dilatation and distal body/tail atrophy. Tumour encased the gastroduodenal junction and D1/D2, producing gastric outlet obstruction."],9.3)
#7
s=base('LOCAL EXTENT AND ASSOCIATED FINDINGS',7,'Staging features explained the patient’s obstructive symptoms and poor performance status')
section(s,.36,.82,3.12,'Vascular and biliary involvement')
bullets(s,.43,1.20,2.9,1.63,["Encasement of extrahepatic portal vein and splenoportal confluence", "Encasement of left hepatic artery and common bile duct", "Splenic vein thrombosis", "CBD and intrahepatic biliary dilatation; gallbladder hydrops"],10.0)
section(s,3.63,.82,3.16,'Additional disease burden')
bullets(s,3.70,1.20,2.94,1.63,["Diffuse oesophageal wall thickening attributed to repeated vomiting", "Hepatic metastases", "Solitary intrapulmonary mass in right lower lobe", "Replaced right hepatic artery and retro-aortic left renal vein"],10.0)
image_panel(s,imgs['sag'],.47,3.07,1.82,.66,'G. Sagittal overview')
image_panel(s,imgs['cor2'],2.84,3.07,1.82,.66,'H. Coronal overview')
image_panel(s,imgs['ax5'],5.21,3.07,1.45,.66,'I. Axial stomach')
#8
s=base('CT AND CLINICAL DIFFERENTIATION',8,'Gastric emphysema must be separated from emphysematous gastritis')
# table headers
rect(s,.37,.86,3.2,.39,TEAL,TEAL); rect(s,3.59,.86,1.45,.39,NAVY,NAVY); rect(s,5.06,.86,2.13,.39,RED,RED)
textbox(s,.48,.98,3.0,.14,'Feature',9,WHITE,True,margin=0); textbox(s,3.67,.98,1.28,.14,'Gastric emphysema',9,WHITE,True,PP_ALIGN.CENTER,margin=0); textbox(s,5.17,.98,1.9,.14,'Emphysematous gastritis',9,WHITE,True,PP_ALIGN.CENTER,margin=0)
rows=[('Mechanism','Mechanical mucosal disruption','Gas-forming infection'),('CT gas pattern','Typically linear / curvilinear','Often mottled or irregular'),('Gastric wall','Usually no thickening','Thickening and oedema common'),('Clinical context','Often mild or mechanical cause','Systemic toxicity / sepsis'),('Management direction','Treat underlying cause; conservative if appropriate','Urgent resuscitation, antibiotics, surgical assessment')]
for i,(a,b,c) in enumerate(rows):
y=1.27+i*.47; fill=LIGHT if i%2==0 else WHITE
for x,w in [( .37,3.2),(3.59,1.45),(5.06,2.13)]: rect(s,x,y,w,.45,fill,RGBColor(210,222,229))
textbox(s,.48,y+.10,2.96,.23,a,9,DARK,True,margin=0); textbox(s,3.66,y+.07,1.28,.28,b,8.3,DARK,False,PP_ALIGN.CENTER,margin=0); textbox(s,5.15,y+.07,1.93,.28,c,8.3,DARK,False,PP_ALIGN.CENTER,margin=0)
textbox(s,.47,3.78,6.7,.16,'In this case: linear mural gas, absent wall thickening, and a clear obstructive mechanism favoured gastric emphysema.',9.1,BLUE,True,PP_ALIGN.CENTER,margin=0)
#9
s=base('MANAGEMENT AND OUTCOME',9)
section(s,.37,.82,2.03,'Diagnosis')
textbox(s,.50,1.34,1.76,.82,'Gastric emphysema and pneumoperitoneum secondary to malignant gastric outlet obstruction.',13,NAVY,True,PP_ALIGN.CENTER,margin=0,valign=MSO_ANCHOR.MIDDLE)
section(s,2.76,.82,2.03,'Tissue confirmation')
textbox(s,2.89,1.34,1.76,.82,'Biopsy of pancreatic head lesion confirmed adenocarcinoma.',13,NAVY,True,PP_ALIGN.CENTER,margin=0,valign=MSO_ANCHOR.MIDDLE)
section(s,5.15,.82,2.03,'Management')
textbox(s,5.28,1.28,1.76,.94,'Conservative approach with feeding jejunostomy for nutritional support and palliative-care referral.',12.6,NAVY,True,PP_ALIGN.CENTER,margin=0,valign=MSO_ANCHOR.MIDDLE)
rect(s,.62,2.72,6.32,.57,SKY,TEAL,True)
textbox(s,.83,2.87,5.9,.18,'Why no surgery for gastric air? Imaging and clinical correlation favoured a non-infectious mechanical process.',10.4,BLUE,True,PP_ALIGN.CENTER,margin=0)
textbox(s,.77,3.61,6.05,.18,'Poor performance status (ECOG 3) precluded systemic therapy.',10.4,MID,False,PP_ALIGN.CENTER,margin=0)
#10
s=base('TAKE-HOME MESSAGES',10)
section(s,.38,.82,4.0,'Three points to remember')
bullets(s,.49,1.23,3.83,1.82,["Not all intramural gastric gas requires operation: integrate CT appearance with clinical context.","Linear mural air without gastric wall thickening, with a mechanical trigger such as outlet obstruction or severe vomiting, supports gastric emphysema.","Search for and treat the underlying cause. Here, pancreatic head adenocarcinoma produced gastric outlet obstruction and intragastric pressure rise."],11)
section(s,4.76,.82,2.2,'Selected references')
textbox(s,4.87,1.24,1.98,2.05,'1. Grainger & Allison’s Diagnostic Radiology. Gastric pneumatosis.\n\n2. Johnson PT et al. Emerg Radiol. 2011;18:65-73.\n\n3. Misro A, Sheth H. Ann R Coll Surg Engl. 2014;96:e11-e13.\n\n4. Agha F. Australas Radiol. 1984;28:346-52.',7.7,MID,False,margin=0)
rect(s,.49,3.39,6.35,.29,TEAL,TEAL,True); textbox(s,.56,3.47,6.17,.12,'Correct interpretation of gastric emphysema can prevent unwarranted surgery.',10,WHITE,True,PP_ALIGN.CENTER,margin=0)
prs.save(OUT)
print(OUT)
mkdir -p "/tmp/workspace/gastric-emphysema-poster/output" && python3 "/tmp/workspace/build_poster.py" && python3 -c "from pptx import Presentation; p='/tmp/workspace/gastric-emphysema-poster/output/Gastric_Emphysema_AP_IRIA_2026_EPoster.pptx'; prs=Presentation(p); print('slides',len(prs.slides),'size',prs.slide_width,prs.slide_height); [print(i+1,len(s.shapes)) for i,s in enumerate(prs.slides)]"
~/gastric-emphysema-poster/output
Gastric Emphysema AP IRIA 2026 EPoster
Presentation · PPTX
It’s messy do it properly
/tmp/workspace
gastric emphysema CT linear intramural gas no wall thickening gastric outlet obstruction
~/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea
python3 -c "from PIL import Image; import os; b='/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea'; fs=[f for f in os.listdir(b) if f.lower().endswith('.jpeg') and ' (1)' not in f];\nfor f in sorted(fs):\n im=Image.open(os.path.join(b,f)); print(f, im.size)"
~/gastric-emphysema-poster/src_rebuild.py
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.dml.color import RGBColor
from PIL import Image
from io import BytesIO
import os
BASE = '/tmp/workspace/attachments/8c6b0c9f-fd60-4b5e-97b8-7b0f3e6cbcea'
TEMPLATE = os.path.join(BASE, 'EPOSTER TEMPLATE - AP IRIA 2026_04-09-2026_v1.pptx')
OUTDIR = '/tmp/workspace/gastric-emphysema-poster/output'
os.makedirs(OUTDIR, exist_ok=True)
OUT = os.path.join(OUTDIR, 'Gastric_Emphysema_AP_IRIA_2026_EPoster_REVISED.pptx')
# Patient CT images, keeping only unique uploads.
I = {n: os.path.join(BASE, f) for n, f in {
'cor_air':'IMG-0006-00001.jpeg', 'cor_air2':'IMG-0007-00001.jpeg',
'ax_air':'IMG-0009-00001.jpeg', 'ax_air2':'IMG-0004-00001.jpeg',
'sag':'IMG-0012-00001 2.jpeg', 'ax_pancreas':'IMG-0011-00001.jpeg',
'ax_pancreas2':'IMG-0003-00001.jpeg', 'cor_pancreas':'IMG-0002-00001.jpeg',
'ax_air3':'IMG-0005-00001.jpeg'}.items()}
prs = Presentation(TEMPLATE)
# Retain logo from supplied template, and rebuild all slides cleanly.
logo = None
for sh in prs.slides[0].shapes:
if hasattr(sh, 'image'):
logo = sh.image.blob
break
while len(prs.slides):
rid = prs.slides._sldIdLst[0].rId
prs.part.drop_rel(rid)
del prs.slides._sldIdLst[0]
NAVY = RGBColor(10, 43, 73)
BLUE = RGBColor(25, 92, 140)
TEAL = RGBColor(0, 135, 145)
CYAN = RGBColor(224, 244, 245)
INK = RGBColor(25, 31, 36)
MUTED = RGBColor(88, 99, 108)
LIGHT = RGBColor(243, 247, 249)
WHITE = RGBColor(255, 255, 255)
LINE = RGBColor(206, 218, 224)
RED = RGBColor(167, 57, 52)
GREEN = RGBColor(30, 120, 80)
SW, SH = prs.slide_width, prs.slide_height
def shape(slide, x, y, w, h, color, rounded=False, line=None):
s = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE if rounded else MSO_SHAPE.RECTANGLE,
Inches(x), Inches(y), Inches(w), Inches(h))
s.fill.solid(); s.fill.fore_color.rgb = color
s.line.color.rgb = line or color
if rounded: s.adjustments[0] = 0.06
return s
def text(slide, x, y, w, h, value, size=12, color=INK, bold=False, align=PP_ALIGN.LEFT,
valign=MSO_ANCHOR.TOP, margin=0.04, font='Aptos'):
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = box.text_frame; tf.clear(); tf.word_wrap = True
tf.margin_left = tf.margin_right = Inches(margin)
tf.margin_top = tf.margin_bottom = Inches(margin)
tf.vertical_anchor = valign
lines = value.split('\n')
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.text = line; p.alignment = align
p.font.name = font; p.font.size = Pt(size); p.font.bold = bold; p.font.color.rgb = color
p.space_after = Pt(0)
return box
def rich_paragraphs(slide, x, y, w, h, items, size=11.5):
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = box.text_frame; tf.clear(); tf.word_wrap = True
tf.margin_left = Inches(0.10); tf.margin_right = Inches(0.06); tf.margin_top = Inches(0.08); tf.margin_bottom = Inches(0.06)
for idx, (head, body) in enumerate(items):
p = tf.paragraphs[0] if idx == 0 else tf.add_paragraph()
p.text = ''
p.level = 0; p.space_after = Pt(7)
p.font.name = 'Aptos'; p.font.size = Pt(size); p.font.color.rgb = INK
r = p.add_run(); r.text = head; r.font.bold = True; r.font.color.rgb = NAVY; r.font.size = Pt(size)
r = p.add_run(); r.text = body; r.font.size = Pt(size); r.font.color.rgb = INK
return box
def add_image(slide, path, x, y, w, h, caption=None):
# Fine grey border and crop-to-fill composition.
shape(slide, x-0.025, y-0.025, w+0.05, h+0.05, WHITE, line=LINE)
im = Image.open(path); iw, ih = im.size
ar = iw / ih; target = w / h
if ar > target:
crop_w = int(ih * target); left = (iw - crop_w)//2
im = im.crop((left, 0, left+crop_w, ih))
else:
crop_h = int(iw / target); top = (ih - crop_h)//2
im = im.crop((0, top, iw, top+crop_h))
bio = BytesIO(); im.save(bio, format='JPEG', quality=95); bio.seek(0)
slide.shapes.add_picture(bio, Inches(x), Inches(y), width=Inches(w), height=Inches(h))
if caption:
text(slide, x, y+h+0.04, w, 0.22, caption, 7.2, MUTED, align=PP_ALIGN.CENTER)
def base(title, subtitle='', n=1):
s = prs.slides.add_slide(prs.slide_layouts[0])
bg = s.background.fill; bg.solid(); bg.fore_color.rgb = WHITE
shape(s, 0, 0, 7.56, 0.52, NAVY)
shape(s, 0, 0.52, 7.56, 0.035, TEAL)
text(s, 0.34, 0.075, 6.25, 0.31, title, 20, WHITE, True)
if logo:
s.shapes.add_picture(BytesIO(logo), Inches(6.78), Inches(0.06), width=Inches(0.47), height=Inches(0.30))
if subtitle:
text(s, 0.38, 0.62, 6.8, 0.24, subtitle, 8.3, MUTED)
text(s, 0.36, 4.04, 5.3, 0.13, 'Gastric emphysema secondary to pancreatic head adenocarcinoma', 6.4, MUTED)
text(s, 6.82, 4.02, 0.38, 0.14, f'{n:02d}', 7.3, BLUE, True, PP_ALIGN.RIGHT)
return s
def section_label(slide, label, x=0.38, y=0.94, w=1.6):
shape(slide, x, y, w, 0.22, CYAN, rounded=True)
text(slide, x+0.05, y+0.027, w-0.1, 0.14, label.upper(), 6.6, TEAL, True, PP_ALIGN.CENTER, MSO_ANCHOR.MIDDLE)
def card(slide, x, y, w, h, title=None, tint=LIGHT):
shape(slide, x, y, w, h, tint, rounded=True, line=LINE)
if title:
text(slide, x+0.15, y+0.11, w-0.3, 0.22, title, 10, NAVY, True)
return (x+0.10, y+0.36, w-0.20, h-0.45)
# 1. title
s = prs.slides.add_slide(prs.slide_layouts[0]); bg=s.background.fill; bg.solid(); bg.fore_color.rgb=NAVY
shape(s, 0, 0, 0.13, 4.25, TEAL)
if logo: s.shapes.add_picture(BytesIO(logo), Inches(6.35), Inches(0.35), width=Inches(0.75), height=Inches(0.48))
text(s, 0.52, 0.56, 5.45, 1.23, "Don't Operate on Air", 33, WHITE, True)
text(s, 0.55, 1.73, 5.9, 0.72, 'Gastric emphysema from pancreatic head adenocarcinoma: a CT-based distinction from emphysematous gastritis', 16, RGBColor(210,235,241), True)
shape(s, 0.55, 2.65, 1.28, 0.04, TEAL)
text(s, 0.55, 2.88, 5.3, 0.25, 'Dr. Namala Sri Ram Praveen Kumar | Dr. L. Peethamber | Dr. K.J.S.S. Raghu Teja', 9.3, WHITE)
text(s, 0.55, 3.17, 5.1, 0.22, 'GITAM Institute of Medical Sciences & Research', 9.3, RGBColor(205,220,231))
text(s, 0.55, 3.57, 3.8, 0.17, 'AP IRIA 2026 | Registration No. 705', 7.2, RGBColor(175,205,220))
add_image(s, I['ax_air'], 5.96, 1.10, 1.18, 1.18)
text(s, 5.97, 2.38, 1.18, 0.35, 'Linear intramural\ngastric gas', 7.2, RGBColor(210,235,241), True, PP_ALIGN.CENTER)
# 2 clinical context
s=base('Clinical presentation', 'The diagnosis is a clinicoradiological decision, not an imaging sign alone.',2); section_label(s,'Case snapshot')
rich_paragraphs(s,0.45,1.26,3.18,2.25,[('75-year-old man ', 'with hypertension, painless jaundice, recurrent postprandial haematemesis and >10 kg weight loss.'),('Examination ', 'ECOG performance status 3; icterus; tender abdomen with guarding.'),('Biochemistry ', 'Total bilirubin 16.7 mg/dL, direct bilirubin 10.8 mg/dL, CA 19-9 >10,000 IU/mL.'),('Clinical question ', 'Is mural gastric gas a surgical emergency or a mechanical consequence of obstruction?')],11.5)
add_image(s,I['cor_air'],4.15,1.12,2.85,2.28,'Coronal CECT: distended stomach with mural gas')
# 3 aim
s=base('Aims and objectives','A focused CT poster for a rare but management-changing imaging distinction.',3); section_label(s,'Purpose')
for x,num,head,body in [(0.45,'01','Recognise','Linear intramural gastric air and associated upper abdominal free air.'),(2.73,'02','Explain','Malignant gastric outlet obstruction as the mechanical driver.'),(5.01,'03','Differentiate','Gastric emphysema from emphysematous gastritis to guide management.')]:
card(s,x,1.33,1.92,1.67,None,WHITE); shape(s,x+0.14,1.47,0.35,0.35,TEAL,rounded=True); text(s,x+0.14,1.54,0.35,0.12,num,8,WHITE,True,PP_ALIGN.CENTER); text(s,x+0.14,2.02,1.55,0.18,head,13,NAVY,True); text(s,x+0.14,2.34,1.58,0.42,body,9.4,MUTED)
shape(s,0.45,3.35,6.55,0.42,CYAN,rounded=True); text(s,0.62,3.47,6.2,0.15,'Key message: correct recognition of gastric emphysema can prevent unwarranted laparotomy.',10,TEAL,True,PP_ALIGN.CENTER)
# 4 CT gastric emphysema
s=base('CT findings: gastric emphysema','The most persuasive feature is the morphology of the intramural gas.',4); section_label(s,'Imaging finding')
add_image(s,I['ax_air'],0.42,1.24,2.02,1.66,'Axial CECT')
add_image(s,I['cor_air'],2.78,1.24,2.02,1.66,'Coronal CECT')
add_image(s,I['sag'],5.14,1.24,1.78,1.66,'Sagittal CECT')
shape(s,0.44,3.22,6.46,0.48,CYAN,rounded=True); text(s,0.63,3.32,6.08,0.20,'Fine linear/curvilinear gas tracks parallel to the gastric wall, without diffuse mural thickening.',11.3,NAVY,True,PP_ALIGN.CENTER)
# 5 mechanism
s=base('Why did gastric emphysema occur?','Mechanical mucosal disruption from malignant gastric outlet obstruction.',5); section_label(s,'Pathophysiology')
for x,head,body,col in [(0.48,'Pancreatic head mass','Encases gastroduodenal junction and D1/D2.',BLUE),(2.69,'Gastric outlet obstruction','Gastric distension and repeated vomiting raise intraluminal pressure.',TEAL),(4.90,'Mucosal micro-tears','Air dissects into the gastric wall: gastric emphysema.',GREEN)]:
shape(s,x,1.45,1.78,1.28,WHITE,rounded=True,line=LINE); shape(s,x,1.45,1.78,0.12,col,rounded=True); text(s,x+0.15,1.70,1.45,0.23,head,10.6,NAVY,True,PP_ALIGN.CENTER); text(s,x+0.16,2.12,1.43,0.34,body,8.4,MUTED,align=PP_ALIGN.CENTER)
for x in [2.32,4.53]: text(s,x,1.88,0.28,0.25,'→',19,TEAL,True,PP_ALIGN.CENTER)
shape(s,0.56,3.20,6.25,0.42,LIGHT,rounded=True); text(s,0.76,3.31,5.87,0.17,'The case had recurrent vomiting and obstruction, supporting a mechanical rather than infectious origin.',9.7,INK,align=PP_ALIGN.CENTER)
# 6 Pancreatic malignancy
s=base('CT findings: pancreatic head adenocarcinoma','The primary lesion establishes the cause of gastric outlet obstruction.',6); section_label(s,'Underlying disease')
add_image(s,I['ax_pancreas'],0.44,1.20,2.04,1.68,'Axial CECT')
add_image(s,I['ax_pancreas2'],2.78,1.20,2.04,1.68,'Axial CECT')
add_image(s,I['cor_pancreas'],5.12,1.20,1.78,1.68,'Coronal CECT')
rich_paragraphs(s,0.51,3.18,6.22,0.56,[('Findings: ', 'heterogeneously enhancing pancreatic head mass with abrupt MPD cut-off, upstream duct dilatation and distal pancreatic atrophy; encasement of the gastroduodenal junction.')],9.6)
# 7 staging
s=base('Associated staging findings','Locally advanced pancreatic malignancy with systemic disease.',7); section_label(s,'Extent of disease')
left=card(s,0.43,1.22,3.07,2.20,'LOCAL EXTENT',LIGHT); rich_paragraphs(s,*left,[('Vascular ', 'encasement of extrahepatic portal vein, splenoportal confluence and left hepatic artery.'),('Biliary ', 'CBD and intrahepatic biliary radicle dilatation with gallbladder hydrops.'),('Venous ', 'splenic vein thrombosis.')],10.3)
right=card(s,3.75,1.22,3.07,2.20,'DISTANT / OTHER',LIGHT); rich_paragraphs(s,*right,[('Metastatic ', 'hepatic metastases and solitary right lower-lobe pulmonary mass.'),('Oesophagus ', 'diffuse wall thickening, likely related to repeated vomiting.'),('Histology ', 'biopsy of the pancreatic head lesion confirmed adenocarcinoma.')],10.3)
# 8 critical distinction
s=base('Gastric emphysema vs emphysematous gastritis','A distinction that changes urgency, treatment and prognosis.',8); section_label(s,'Differential diagnosis')
# simple, uncluttered 2-column table
shape(s,0.42,1.18,3.05,2.30,RGBColor(235,249,242),rounded=True,line=RGBColor(164,208,181)); shape(s,3.69,1.18,3.05,2.30,RGBColor(253,238,237),rounded=True,line=RGBColor(227,178,175))
text(s,0.65,1.38,2.6,0.25,'GASTRIC EMPHYSEMA',13,GREEN,True,PP_ALIGN.CENTER); text(s,3.92,1.38,2.6,0.25,'EMPHYSEMATOUS GASTRITIS',13,RED,True,PP_ALIGN.CENTER)
rich_paragraphs(s,0.67,1.78,2.55,1.45,[('Gas ', 'thin linear/curvilinear mural streaks.'),('Wall ', 'often no significant thickening.'),('Context ', 'vomiting, obstruction, instrumentation or trauma.'),('Approach ', 'treat underlying mechanical cause; conservative care when appropriate.')],8.7)
rich_paragraphs(s,3.94,1.78,2.55,1.45,[('Gas ', 'more mottled or irregular intramural gas.'),('Wall ', 'thickening and inflammatory change are common.'),('Context ', 'toxic or septic presentation due to gas-forming infection.'),('Approach ', 'urgent resuscitation, broad-spectrum antibiotics and surgical assessment.')],8.7)
text(s,0.66,3.69,6.0,0.18,'Interpret CT in clinical context. Intramural air alone does not equal emphysematous gastritis.',9.7,NAVY,True,PP_ALIGN.CENTER)
# 9 treatment
s=base('Management and outcome','Correct classification avoided unnecessary surgery.',9); section_label(s,'Case management')
for y,tag,detail in [(1.27,'1','Conservative initial management, guided by stable vital signs and CT pattern favouring gastric emphysema.'),(1.93,'2','Feeding jejunostomy for nutritional support in the setting of gastric outlet obstruction.'),(2.59,'3','Biopsy-proven adenocarcinoma; ECOG 3 and advanced disease prompted referral for palliative care.')]:
shape(s,0.58,y,0.34,0.34,TEAL,rounded=True); text(s,0.58,y+0.08,0.34,0.12,tag,8,WHITE,True,PP_ALIGN.CENTER); text(s,1.10,y+0.03,5.75,0.30,detail,10.3,INK)
shape(s,0.55,3.45,6.25,0.30,CYAN,rounded=True); text(s,0.75,3.53,5.85,0.12,'Avoiding an incorrect diagnosis of emphysematous gastritis prevented an unwarranted operative pathway.',8.9,TEAL,True,PP_ALIGN.CENTER)
# 10 take home
s=base('Take-home points','A rare sign is safest when interpreted with morphology, mechanism and the patient’s condition.',10); section_label(s,'Conclusion')
for x,head,body in [(0.45,'1. Recognise','Linear intramural gastric air without marked wall thickening favours gastric emphysema.'),(2.77,'2. Seek the cause','In this case, pancreatic head adenocarcinoma produced gastric outlet obstruction and vomiting.'),(5.09,'3. Change management','Differentiate from emphysematous gastritis to avoid inappropriate emergency surgery.')]:
shape(s,x,1.30,1.91,1.48,WHITE,rounded=True,line=LINE); text(s,x+0.15,1.58,1.60,0.34,head,11,NAVY,True,PP_ALIGN.CENTER); text(s,x+0.16,2.09,1.58,0.40,body,8.6,MUTED,align=PP_ALIGN.CENTER)
shape(s,0.62,3.24,6.10,0.46,NAVY,rounded=True); text(s,0.84,3.36,5.66,0.17,"Don't operate on air: operate on the diagnosis.",13,WHITE,True,PP_ALIGN.CENTER)
text(s,0.52,3.86,6.3,0.12,'References: Misro & Sheth 2014; Johnson et al. 2011; Kussin et al. 1982; Grainger & Allison’s Diagnostic Radiology.',6.3,MUTED,align=PP_ALIGN.CENTER)
prs.save(OUT)
print(OUT)
python3 "/tmp/workspace/gastric-emphysema-poster/src_rebuild.py" && python3 -c "from pptx import Presentation; p='/tmp/workspace/gastric-emphysema-poster/output/Gastric_Emphysema_AP_IRIA_2026_EPoster_REVISED.pptx'; prs=Presentation(p); print('slides:',len(prs.slides));\nfor i,s in enumerate(prs.slides,1):\n print(i, 'shapes=',len(s.shapes), 'text_boxes=',sum(1 for x in s.shapes if getattr(x,'has_text_frame',False)), 'pictures=',sum(1 for x in s.shapes if x.shape_type==13))"
python3 -c "from pptx import Presentation; p='/tmp/workspace/gastric-emphysema-poster/output/Gastric_Emphysema_AP_IRIA_2026_EPoster_REVISED.pptx'; q=Presentation(p); print('slides',len(q.slides),'size',q.slide_width,q.slide_height); print([(i+1,len(s.shapes),sum(getattr(x,'shape_type',None)==13 for x in s.shapes)) for i,s in enumerate(q.slides)])"
No generations found in stream.
We encountered an error while processing your request. Please try again or reach out to us for help.
Try again
~/gastric-emphysema-poster/output
gastric emphysema CT linear intramural gas gastric outlet obstruction imaging
python3 -c "import zipfile; p='/tmp/workspace/gastric-emphysema-poster/output/Gastric_Emphysema_AP_IRIA_2026_EPoster_REVISED.pptx'; z=zipfile.ZipFile(p); bad=z.testzip(); print('zip_integrity=',bad or 'OK'); print('slide_xml=',len([n for n in z.namelist() if n.startswith('ppt/slides/slide') and n.endswith('.xml')]))" && ls -lh "/tmp/workspace/gastric-emphysema-poster/output/Gastric_Emphysema_AP_IRIA_2026_EPoster_REVISED.pptx"
Gastric Emphysema AP IRIA 2026 EPoster REVISED
Presentation · PPTX