Find any fracture or dislocation of bone in give x ray
No obvious fracture or dislocation is identified on this AP view of the right shoulder.
⚠️ This AI analysis is for educational reference only and does not replace an official radiologist report or clinical evaluation.
Generate a PDF summary of shoulder X-ray interpretation
ls -la /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace && echo "created"
mkdir -p /tmp/workspace/shoulder-xray-report && python3 << 'EOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm, mm from reportlab.platypus import ( SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, KeepTogether ) from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY from reportlab.platypus import Frame, PageTemplate from reportlab.pdfgen import canvas from datetime import datetime OUTPUT = "/tmp/workspace/shoulder-xray-report/Shoulder_Xray_Interpretation_Report.pdf" # ── Page setup ────────────────────────────────────────────────────────────── doc = SimpleDocTemplate( OUTPUT, pagesize=A4, leftMargin=2*cm, rightMargin=2*cm, topMargin=2.5*cm, bottomMargin=2*cm ) W, H = A4 # ── Colour palette ─────────────────────────────────────────────────────────── DARK_BLUE = colors.HexColor("#1a3a5c") MED_BLUE = colors.HexColor("#2563a8") LIGHT_BLUE = colors.HexColor("#dbeafe") ACCENT = colors.HexColor("#e74c3c") GREEN = colors.HexColor("#27ae60") AMBER = colors.HexColor("#f39c12") LIGHT_GREY = colors.HexColor("#f4f6f9") MID_GREY = colors.HexColor("#cbd5e1") TEXT_DARK = colors.HexColor("#1e293b") TEXT_MID = colors.HexColor("#475569") # ── Styles ─────────────────────────────────────────────────────────────────── styles = getSampleStyleSheet() title_style = ParagraphStyle( "Title", fontSize=20, fontName="Helvetica-Bold", textColor=colors.white, alignment=TA_CENTER, spaceAfter=4 ) subtitle_style = ParagraphStyle( "Subtitle", fontSize=11, fontName="Helvetica", textColor=colors.HexColor("#bfdbfe"), alignment=TA_CENTER, spaceAfter=2 ) section_header = ParagraphStyle( "SectionHeader", fontSize=13, fontName="Helvetica-Bold", textColor=DARK_BLUE, spaceBefore=14, spaceAfter=6, borderPadding=(0,0,3,0) ) body_style = ParagraphStyle( "Body", fontSize=10, fontName="Helvetica", textColor=TEXT_DARK, spaceAfter=5, leading=15, alignment=TA_JUSTIFY ) body_bold = ParagraphStyle( "BodyBold", fontSize=10, fontName="Helvetica-Bold", textColor=TEXT_DARK, spaceAfter=4, leading=15 ) bullet_style = ParagraphStyle( "Bullet", fontSize=10, fontName="Helvetica", textColor=TEXT_DARK, spaceAfter=4, leading=15, leftIndent=14, bulletIndent=0 ) finding_ok = ParagraphStyle( "FindingOK", fontSize=10, fontName="Helvetica", textColor=colors.HexColor("#166534"), spaceAfter=4, leading=14, leftIndent=14 ) finding_warn = ParagraphStyle( "FindingWarn", fontSize=10, fontName="Helvetica", textColor=colors.HexColor("#92400e"), spaceAfter=4, leading=14, leftIndent=14 ) caption_style = ParagraphStyle( "Caption", fontSize=8, fontName="Helvetica-Oblique", textColor=TEXT_MID, alignment=TA_CENTER, spaceAfter=4 ) disclaimer_style = ParagraphStyle( "Disclaimer", fontSize=8.5, fontName="Helvetica-Oblique", textColor=colors.HexColor("#64748b"), alignment=TA_CENTER, spaceBefore=8, spaceAfter=4, leading=13 ) # ── Header / Footer callbacks ──────────────────────────────────────────────── def header_footer(canvas_obj, doc_obj): canvas_obj.saveState() pw = doc_obj.pagesize[0] ph = doc_obj.pagesize[1] # Top banner canvas_obj.setFillColor(DARK_BLUE) canvas_obj.rect(0, ph - 2.2*cm, pw, 2.2*cm, fill=1, stroke=0) # Banner text canvas_obj.setFillColor(colors.white) canvas_obj.setFont("Helvetica-Bold", 14) canvas_obj.drawCentredString(pw/2, ph - 1.3*cm, "RADIOLOGY REPORT - RIGHT SHOULDER") canvas_obj.setFont("Helvetica", 9) canvas_obj.setFillColor(colors.HexColor("#bfdbfe")) canvas_obj.drawCentredString(pw/2, ph - 1.85*cm, "Govt. Head Quarters Hospital, Tambaram | AP View | 26 July 2023") # Thin accent line below banner canvas_obj.setStrokeColor(MED_BLUE) canvas_obj.setLineWidth(2) canvas_obj.line(0, ph - 2.25*cm, pw, ph - 2.25*cm) # Footer canvas_obj.setFillColor(DARK_BLUE) canvas_obj.rect(0, 0, pw, 1.1*cm, fill=1, stroke=0) canvas_obj.setFillColor(colors.white) canvas_obj.setFont("Helvetica", 7.5) canvas_obj.drawString(2*cm, 0.45*cm, "Generated: " + datetime.now().strftime("%d %B %Y %H:%M")) canvas_obj.drawCentredString(pw/2, 0.45*cm, "AI-assisted analysis | For educational reference only | Not a substitute for official radiologist report") canvas_obj.drawRightString(pw - 2*cm, 0.45*cm, f"Page {doc_obj.page}") canvas_obj.restoreState() # ── Story elements ──────────────────────────────────────────────────────────── story = [] # ── Patient info card ──────────────────────────────────────────────────────── patient_data = [ [Paragraph("<b>Patient Name</b>", body_bold), Paragraph("Naveen Kumar", body_style), Paragraph("<b>Age / Sex</b>", body_bold), Paragraph("21 years / Male", body_style)], [Paragraph("<b>Date of Study</b>", body_bold), Paragraph("26 July 2023", body_style), Paragraph("<b>Study Time</b>", body_bold), Paragraph("14:23", body_style)], [Paragraph("<b>View</b>", body_bold), Paragraph("Shoulder AP - Right", body_style), Paragraph("<b>Exposure</b>", body_bold), Paragraph("kV: 65 | mAs: 15 | Mag: 130%", body_style)], [Paragraph("<b>Referring Hospital</b>", body_bold), Paragraph("Govt. Head Quarters Hospital, Tambaram", body_style), Paragraph("<b>Accession No.</b>", body_bold), Paragraph("DR25966-26", body_style)], ] pt_table = Table(patient_data, colWidths=[3.8*cm, 5.2*cm, 3.8*cm, 4.2*cm]) pt_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), LIGHT_GREY), ("BACKGROUND", (0,0), (0,-1), LIGHT_BLUE), ("BACKGROUND", (2,0), (2,-1), LIGHT_BLUE), ("BOX", (0,0), (-1,-1), 1, MID_GREY), ("INNERGRID", (0,0), (-1,-1), 0.5, MID_GREY), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 8), ("RIGHTPADDING", (0,0), (-1,-1), 8), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_GREY, colors.white]), ])) story.append(Spacer(1, 0.4*cm)) story.append(Paragraph("PATIENT INFORMATION", section_header)) story.append(HRFlowable(width="100%", thickness=2, color=MED_BLUE, spaceAfter=6)) story.append(pt_table) story.append(Spacer(1, 0.5*cm)) # ── Impression banner ──────────────────────────────────────────────────────── impression_data = [[ Paragraph( "<b>OVERALL IMPRESSION:</b> No obvious fracture or dislocation identified " "on this AP view of the right shoulder. Bones and joints appear grossly normal.", ParagraphStyle("imp", fontSize=11, fontName="Helvetica-Bold", textColor=colors.HexColor("#14532d"), alignment=TA_CENTER, leading=17) ) ]] imp_table = Table(impression_data, colWidths=[17*cm]) imp_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#dcfce7")), ("BOX", (0,0), (-1,-1), 2, GREEN), ("TOPPADDING", (0,0), (-1,-1), 10), ("BOTTOMPADDING", (0,0), (-1,-1), 10), ("LEFTPADDING", (0,0), (-1,-1), 14), ("RIGHTPADDING", (0,0), (-1,-1), 14), ])) story.append(imp_table) story.append(Spacer(1, 0.5*cm)) # ── Detailed findings ──────────────────────────────────────────────────────── story.append(Paragraph("DETAILED RADIOLOGICAL FINDINGS", section_header)) story.append(HRFlowable(width="100%", thickness=2, color=MED_BLUE, spaceAfter=8)) findings = [ ("Glenohumeral Joint", [ ("Normal", "Humeral head is well-centred within the glenoid fossa on AP view."), ("Normal", "No anterior, posterior, or inferior dislocation identified."), ("Normal", "Glenohumeral joint space is preserved and symmetric."), ("Normal", "Contour of humeral head is smooth and rounded; no cortical step-off."), ("Normal", "Greater and lesser tuberosities appear intact - no avulsion fragment."), ("Normal", "Surgical neck and anatomical neck of humerus show no fracture line."), ]), ("Clavicle & Acromioclavicular (AC) Joint", [ ("Normal", "Clavicle appears intact - no cortical break, angulation, or displacement."), ("Normal", "AC joint is well-aligned; no superior step-off suggesting AC separation."), ("Normal", "Coracoclavicular distance appears within normal limits."), ("Normal", "Distal clavicle shows no osteolytic lesion or erosion."), ]), ("Scapula", [ ("Normal", "Acromion process is intact with no fracture or os acromiale noted."), ("Normal", "Coracoid process is intact and normally positioned."), ("Normal", "Glenoid rim appears smooth with no bony Bankart lesion."), ("Normal", "Scapular neck and body: no obvious fracture lines visible."), ]), ("Ribs & Thoracic Structures", [ ("Normal", "Visible upper ribs (1st-6th) appear grossly intact, no displaced rib fractures."), ("Normal", "Lung apex visible on this view appears clear; no obvious pneumothorax."), ("Normal", "No pleural effusion or haemothorax noted in the visible lung field."), ]), ("Bone Density & Soft Tissues", [ ("Normal", "Bone density appears appropriate for a 21-year-old male."), ("Normal", "No lytic or sclerotic bone lesions identified."), ("Caution", "Soft tissue injuries (rotator cuff, labrum) are NOT visible on plain X-ray."), ]), ] for structure, items in findings: # Sub-header row sub_data = [[Paragraph(structure.upper(), ParagraphStyle( "SubH", fontSize=10, fontName="Helvetica-Bold", textColor=colors.white ))]] sub_tbl = Table(sub_data, colWidths=[17*cm]) sub_tbl.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), MED_BLUE), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 10), ])) story.append(sub_tbl) rows = [] for status, text in items: if status == "Normal": icon = "✓" bg = colors.HexColor("#f0fdf4") fg = colors.HexColor("#166534") else: icon = "!" bg = colors.HexColor("#fffbeb") fg = colors.HexColor("#92400e") rows.append([ Paragraph(f"<b><font color='{fg.hexval()}'>{icon}</font></b>", ParagraphStyle("Icon", fontSize=12, fontName="Helvetica-Bold", alignment=TA_CENTER)), Paragraph(f"<font color='{fg.hexval()}'><b>{status}</b></font>", ParagraphStyle("Status", fontSize=9, fontName="Helvetica-Bold", alignment=TA_CENTER)), Paragraph(text, ParagraphStyle("Row", fontSize=9.5, fontName="Helvetica", textColor=TEXT_DARK, leading=14)), ]) tbl = Table(rows, colWidths=[0.8*cm, 1.8*cm, 14.4*cm]) # Alternating row colours row_styles = [ ("GRID", (0,0), (-1,-1), 0.4, MID_GREY), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 6), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ("ALIGN", (0,0), (1,-1), "CENTER"), ] for i in range(len(rows)): bg = colors.HexColor("#f0fdf4") if rows[i][1].text.startswith("<font") and "Normal" in rows[i][1].text else colors.HexColor("#fffbeb") # simpler approach: set per-row bg c = colors.HexColor("#f8fafc") if i % 2 == 0 else colors.white row_styles.append(("BACKGROUND", (0,i), (-1,i), c)) tbl.setStyle(TableStyle(row_styles)) story.append(tbl) story.append(Spacer(1, 0.25*cm)) story.append(Spacer(1, 0.3*cm)) # ── Limitations ─────────────────────────────────────────────────────────────── story.append(Paragraph("INTERPRETATION LIMITATIONS", section_header)) story.append(HRFlowable(width="100%", thickness=2, color=AMBER, spaceAfter=8)) limits = [ ("Single AP View Only", "An AP view alone cannot exclude all shoulder injuries. Posterior dislocation of " "the shoulder - a classically 'missed' diagnosis - can appear normal on AP. " "Axillary lateral or scapular Y-view are essential complementary projections."), ("Subtle / Non-Displaced Fractures", "Hairline fractures of the surgical neck, greater tuberosity microfractures, " "and Hill-Sachs lesions may be invisible on plain X-ray. CT scan provides superior " "bony detail; MRI is preferred for occult fractures."), ("Soft Tissue Injuries Not Visible", "Rotator cuff tears, labral tears (Bankart, SLAP), biceps tendon pathology, " "capsular injuries, and ligamentous sprains cannot be assessed on X-ray. MRI " "with or without arthrogram is required if these are clinically suspected."), ("Cartilage and Joint Fluid", "Articular cartilage loss and joint effusions are poorly assessed on plain " "radiographs. Ultrasound or MRI should be used for these assessments."), ] lim_rows = [] for i, (title, text) in enumerate(limits): lim_rows.append([ Paragraph(f"<b>{i+1}</b>", ParagraphStyle("Num", fontSize=13, fontName="Helvetica-Bold", textColor=colors.white, alignment=TA_CENTER)), Paragraph(f"<b>{title}</b><br/>{text}", ParagraphStyle("LimText", fontSize=9.5, fontName="Helvetica", textColor=TEXT_DARK, leading=14)) ]) lim_tbl = Table(lim_rows, colWidths=[1.2*cm, 15.8*cm]) lim_styles = [ ("GRID", (0,0), (-1,-1), 0.5, MID_GREY), ("TOPPADDING", (0,0), (-1,-1), 7), ("BOTTOMPADDING", (0,0), (-1,-1), 7), ("LEFTPADDING", (0,0), (-1,-1), 8), ("RIGHTPADDING", (0,0), (-1,-1), 8), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ("ALIGN", (0,0), (0,-1), "CENTER"), ] for i in range(len(lim_rows)): lim_styles.append(("BACKGROUND", (0,i), (0,i), AMBER)) lim_styles.append(("BACKGROUND", (1,i), (1,i), colors.HexColor("#fffbeb") if i%2==0 else colors.HexColor("#fef9ec"))) lim_tbl.setStyle(TableStyle(lim_styles)) story.append(lim_tbl) story.append(Spacer(1, 0.4*cm)) # ── Recommendations ─────────────────────────────────────────────────────────── story.append(Paragraph("CLINICAL RECOMMENDATIONS", section_header)) story.append(HRFlowable(width="100%", thickness=2, color=MED_BLUE, spaceAfter=8)) recs = [ ("Additional Imaging Views", "Obtain Axillary Lateral and Scapular Y-views to complete the shoulder X-ray series " "and exclude posterior dislocation."), ("CT Scan", "Indicated if there is high clinical suspicion of fracture not seen on X-ray, " "bony Bankart lesion, or pre-operative planning for complex injuries."), ("MRI Shoulder", "Recommended if soft tissue pathology (rotator cuff tear, labral lesion, " "biceps pathology) is suspected based on clinical examination."), ("Orthopedic Referral", "If the patient has persistent pain, limited range of motion, instability symptoms, " "or a significant mechanism of injury, formal orthopedic assessment is recommended."), ] for title, text in recs: rec_data = [[ Paragraph(f"<b>► {title}</b>", ParagraphStyle("RecTitle", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_BLUE)), Paragraph(text, ParagraphStyle("RecText", fontSize=9.5, fontName="Helvetica", textColor=TEXT_DARK, leading=14)) ]] rec_tbl = Table(rec_data, colWidths=[4.5*cm, 12.5*cm]) rec_tbl.setStyle(TableStyle([ ("BACKGROUND", (0,0), (0,0), LIGHT_BLUE), ("BACKGROUND", (1,0), (1,0), colors.white), ("BOX", (0,0), (-1,-1), 0.5, MID_GREY), ("TOPPADDING", (0,0), (-1,-1), 7), ("BOTTOMPADDING", (0,0), (-1,-1), 7), ("LEFTPADDING", (0,0), (-1,-1), 8), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ("LINEAFTER", (0,0), (0,-1), 1.5, MED_BLUE), ])) story.append(rec_tbl) story.append(Spacer(1, 0.2*cm)) story.append(Spacer(1, 0.4*cm)) # ── Differential diagnosis note ─────────────────────────────────────────────── story.append(Paragraph("DIFFERENTIAL DIAGNOSIS TO CONSIDER (Clinical Context)", section_header)) story.append(HRFlowable(width="100%", thickness=2, color=MED_BLUE, spaceAfter=8)) dd_data = [ ["Condition", "Key X-ray Finding", "Additional Workup"], ["Anterior Shoulder Dislocation", "Humeral head displaced antero-inferiorly; loss of \"light bulb\" sign", "Axillary / Y-view; Reduction under sedation"], ["Posterior Shoulder Dislocation", "\"Light bulb\" sign on AP (internal rotation); may look normal", "Axillary view / CT - easily missed"], ["Hill-Sachs Lesion", "Cortical impaction defect posterolateral humeral head", "MRI / CT for sizing"], ["Proximal Humerus Fracture", "Cortical break at surgical neck, greater/lesser tuberosity", "CT for fragment displacement"], ["Clavicle Fracture", "Cortical disruption, angulation or overlap at fracture site", "Additional clavicle views"], ["AC Joint Separation", "Superior step-off at AC joint; coracoclavicular widening", "Stress views (weights)"], ["Bankart Lesion (Bony)", "Chip fracture anterior glenoid rim", "CT arthrogram / MRI"], ] dd_tbl = Table(dd_data, colWidths=[4*cm, 6*cm, 7*cm]) dd_styles = [ ("BACKGROUND", (0,0), (-1,0), DARK_BLUE), ("TEXTCOLOR", (0,0), (-1,0), colors.white), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("FONTSIZE", (0,0), (-1,-1), 9), ("GRID", (0,0), (-1,-1), 0.5, MID_GREY), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 7), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ] for i in range(1, len(dd_data)): bg = LIGHT_GREY if i % 2 == 0 else colors.white dd_styles.append(("BACKGROUND", (0,i), (-1,i), bg)) dd_tbl.setStyle(TableStyle(dd_styles)) story.append(dd_tbl) story.append(Spacer(1, 0.5*cm)) # ── Disclaimer ──────────────────────────────────────────────────────────────── disc_data = [[Paragraph( "<b>DISCLAIMER:</b> This report is generated by an AI-assisted system for educational " "and reference purposes only. It does NOT constitute an official radiological diagnosis " "and must NOT be used as a sole basis for clinical decision-making. All findings should " "be correlated with clinical history, physical examination, and reviewed by a qualified " "radiologist or treating physician.", disclaimer_style )]] disc_tbl = Table(disc_data, colWidths=[17*cm]) disc_tbl.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#fef2f2")), ("BOX", (0,0), (-1,-1), 1.5, ACCENT), ("TOPPADDING", (0,0), (-1,-1), 10), ("BOTTOMPADDING", (0,0), (-1,-1), 10), ("LEFTPADDING", (0,0), (-1,-1), 12), ("RIGHTPADDING", (0,0), (-1,-1), 12), ])) story.append(disc_tbl) # ── Build ──────────────────────────────────────────────────────────────────── doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer) print("PDF generated successfully:", OUTPUT) EOF
Shoulder Xray Interpretation Report
PDF Document · PDF
| Section | Content |
|---|---|
| Patient Information | Name, age, sex, date, exposure parameters, hospital |
| Overall Impression | Highlighted banner - no fracture/dislocation identified |
| Detailed Findings | Structure-by-structure table (Glenohumeral joint, Clavicle/AC, Scapula, Ribs, Bone density) with Normal / Caution status icons |
| Interpretation Limitations | 4 key limitations of a single AP view |
| Clinical Recommendations | Additional views, CT, MRI, and orthopedic referral guidance |
| Differential Diagnosis Table | 7 conditions to consider with X-ray features and workup |
| Disclaimer | AI-generated, educational use only |
What is the treatment for muscle or ligament injury at the shoulder region treatment for it what sling we use in it
| Injury Type | Structure Involved |
|---|---|
| Rotator cuff tear/strain | Supraspinatus, infraspinatus, teres minor, subscapularis |
| AC joint sprain / separation | Acromioclavicular & coracoclavicular ligaments |
| Glenohumeral ligament sprain | Capsule, inferior glenohumeral ligament |
| Muscle contusion/strain | Deltoid, trapezius, biceps |
| Shoulder dislocation (post-reduction) | Capsule + labrum |
| Drug | Use | Notes |
|---|---|---|
| NSAIDs (ibuprofen, diclofenac, naproxen) | Pain + inflammation | First-line for 5-7 days |
| Paracetamol | Mild-moderate pain | Adjunct, safe with NSAIDs |
| Topical NSAID gel | Localised pain | Apply over deltoid/AC area |
| Corticosteroid injection | Persistent pain >4-6 weeks | Subacromial space injection for rotator cuff |


| Injury | Recommended Immobilization |
|---|---|
| Mild rotator cuff strain / muscle contusion | Simple arm sling (2-3 weeks) |
| Significant rotator cuff tear | Shoulder immobilizer or sling-and-swathe |
| AC joint separation (Grade I-II) | Shoulder immobilizer or sling-and-swathe |
| Post-reduction shoulder dislocation | Shoulder immobilizer (arm adducted, internally rotated) |
| Clavicle fracture | Simple arm sling or shoulder immobilizer |
| Proximal humerus fracture (undisplaced) | Sling-and-swathe or shoulder immobilizer |
| Glenohumeral ligament sprain | Simple arm sling (short term, early mobilization) |
Clinical note: Duration of sling use matters - prolonged immobilization beyond 3-6 weeks without early mobilization increases the risk of adhesive capsulitis (frozen shoulder), especially in patients over 40. Early supervised physiotherapy is key.