Make a flowchart for management of acquired upper lid entropion, lower lid entropion and ectropion

Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Searching PubMed

"entropion" AND surgery

Searching PubMed

"ectropion" AND surgery

Running Command

python3 -c "import graphviz; print(graphviz.__version__)"; which dot

Writing File

~/entropion-ectropion-flowchart/build_flowcharts.py

import graphviz

COMMON_ATTRS = dict(
    fontname="Helvetica",
    fontsize="11",
)

def new_graph(name, label):
    g = graphviz.Digraph(name, format="png")
    g.attr(rankdir="TB", splines="ortho", nodesep="0.35", ranksep="0.45", bgcolor="white")
    g.attr(label=label, labelloc="t", fontsize="18", fontname="Helvetica-Bold")
    g.attr("node", fontname="Helvetica", fontsize="11")
    g.attr("edge", fontname="Helvetica", fontsize="10")
    return g

def box(g, name, text, shape="box", fill="#EAF2FB", color="#2E5C8A"):
    g.node(name, text, shape=shape, style="filled,rounded" if shape == "box" else "filled",
           fillcolor=fill, color=color, penwidth="1.4")

def diamond(g, name, text, fill="#FDF3D0", color="#B8860B"):
    g.node(name, text, shape="diamond", style="filled", fillcolor=fill, color=color, penwidth="1.4")

def start(g, name, text, fill="#DCEFE1", color="#2E7D46"):
    g.node(name, text, shape="oval", style="filled", fillcolor=fill, color=color, penwidth="1.6")

def end(g, name, text, fill="#F6D6D6", color="#B23A48"):
    g.node(name, text, shape="oval", style="filled", fillcolor=fill, color=color, penwidth="1.6")

# ============================================================
# 1. ACQUIRED UPPER LID ENTROPION
# ============================================================
g1 = new_graph("upper_lid_entropion", "Management of Acquired Upper Lid Entropion")

start(g1, "s", "Acquired Upper Lid Entropion\n(lashes/lid margin rotated onto globe)")
box(g1, "hx", "History & exam:\ncicatrizing conjunctivitis, trachoma,\nchemical/thermal burn, trauma,\nOCP / Stevens-Johnson syndrome\nSlit-lamp: corneal staining, tarsal scarring")
diamond(g1, "cause", "Identify cause\n(almost always cicatricial\nin acquired upper lid disease)")
box(g1, "treat_underlying", "Treat/control underlying disease\n(e.g. systemic immunosuppression for\nmucous membrane pemphigoid,\nstop offending agent)")
box(g1, "temp", "Temporising measures\nLubricants, bandage contact lens,\nepilation / electrolysis / cryotherapy\nof aberrant lashes")
diamond(g1, "severity", "Severity of tarsal\nscarring / lid rotation?")
box(g1, "mild", "MILD\nTarsal fracture (transverse tarsotomy)\nwith anterior rotation of lid margin\n(as for marginal entropion)")
box(g1, "severe", "SEVERE\nComposite grafting:\nreplace keratinized conjunctiva +\nscarred/contracted tarsus\n(mucous membrane / hard palate /\namniotic membrane graft)")
diamond(g1, "laxity1", "Horizontal lid laxity\nalso present?")
box(g1, "sling1", "Add lateral tarsal strip\n(canthal tendon tightening)")
end(g1, "resolved1", "Lid margin realigned,\ncornea protected\n(follow up for recurrence)")

g1.edge("s", "hx")
g1.edge("hx", "cause")
g1.edge("cause", "treat_underlying")
g1.edge("treat_underlying", "temp")
g1.edge("temp", "severity")
g1.edge("severity", "mild", label="mild")
g1.edge("severity", "severe", label="severe / recurrent")
g1.edge("mild", "laxity1")
g1.edge("severe", "laxity1")
g1.edge("laxity1", "sling1", label="yes")
g1.edge("sling1", "resolved1")
g1.edge("laxity1", "resolved1", label="no")

g1.render("/tmp/workspace/entropion-ectropion-flowchart/1_upper_lid_entropion", cleanup=True)

# ============================================================
# 2. ACQUIRED LOWER LID ENTROPION
# ============================================================
g2 = new_graph("lower_lid_entropion", "Management of Acquired Lower Lid Entropion")

start(g2, "s", "Acquired Lower Lid Entropion\n(lid margin/lashes rotated onto globe,\npseudotrichiasis)")
box(g2, "hx", "History & exam: prior surgery/trauma,\nchemical burn, infection (trachoma, HSV/VZV)\nAssess: horizontal lid laxity, retractor\ndisinsertion, orbicularis override,\nblepharospasm, conjunctival/tarsal scarring")
diamond(g2, "etiology", "Predominant\nmechanism?")
box(g2, "involutional", "INVOLUTIONAL (most common)\nHorizontal lid laxity +/- lower lid\nretractor disinsertion +/- preseptal\norbicularis override")
box(g2, "cicatricial", "CICATRICIAL\nConjunctival scarring: OCP,\nStevens-Johnson, chemical burn,\ntrachoma, trauma")
box(g2, "spastic", "SPASTIC\nSustained orbicularis contraction:\npost-surgical irritation, blepharospasm")
box(g2, "temp", "Temporising measures (all types)\nLubrication + antibiotic ointment,\ntaping/lateral traction,\nQuickert suture (office/bedside),\nbotulinum toxin chemodenervation\nof orbicularis")

# involutional branch
diamond(g2, "mech", "Predominant mechanism:\noverride/disinsertion\nvs horizontal laxity?")
box(g2, "everting", "Everting sutures (transient) OR\nWies procedure (lid split + everting\nsutures) OR lower lid retractor\nreinsertion (more precise; primary\nor for recurrence)")
box(g2, "tarsalstrip", "Lateral tarsal strip\n(canthal sling) or pentagon excision\nfor horizontal laxity")
box(g2, "combo", "Combine retractor/override repair\nWITH lateral tarsal strip\nif both present (common)")

# cicatricial branch
diamond(g2, "cicseverity", "Severity of\ntarsal/conjunctival scarring?")
box(g2, "cicmild", "MILD: tarsal fracture\n(transverse tarsotomy) with\nanterior lid margin rotation")
box(g2, "cicsevere", "SEVERE: composite/mucous\nmembrane graft to replace\nscarred tarsus + keratinized\nconjunctiva; add lateral tarsal\nstrip if lax")

# spastic branch
box(g2, "spasticmgmt", "Treat underlying irritant/blepharospasm\n+ Quickert suture; botulinum toxin\nfor blepharospasm if recurrent")

end(g2, "resolved2", "Lid apposed to globe,\ncornea protected\n(surgery definitive; monitor for recurrence)")

g2.edge("s", "hx")
g2.edge("hx", "etiology")
g2.edge("etiology", "involutional")
g2.edge("etiology", "cicatricial")
g2.edge("etiology", "spastic")
g2.edge("involutional", "temp")
g2.edge("cicatricial", "temp")
g2.edge("spastic", "temp")

g2.edge("temp", "mech", label="involutional")
g2.edge("mech", "everting", label="override/\ndisinsertion")
g2.edge("mech", "tarsalstrip", label="horizontal\nlaxity")
g2.edge("everting", "combo")
g2.edge("tarsalstrip", "combo")
g2.edge("combo", "resolved2")

g2.edge("temp", "cicseverity", label="cicatricial")
g2.edge("cicseverity", "cicmild", label="mild")
g2.edge("cicseverity", "cicsevere", label="severe")
g2.edge("cicmild", "resolved2")
g2.edge("cicsevere", "resolved2")

g2.edge("temp", "spasticmgmt", label="spastic")
g2.edge("spasticmgmt", "resolved2")

g2.render("/tmp/workspace/entropion-ectropion-flowchart/2_lower_lid_entropion", cleanup=True)

# ============================================================
# 3. ECTROPION (acquired, lower lid)
# ============================================================
g3 = new_graph("ectropion", "Management of Acquired Ectropion")

start(g3, "s", "Acquired Ectropion\n(outward turning of lid margin)")
box(g3, "hx", "History & exam: prior surgery/trauma/burn,\nCN VII palsy, skin disease, tumour\nCheck orbicularis function, horizontal\nlaxity, punctal position, exposed\nconjunctiva/skin, herniated fat/mass\nSlit lamp: exposure keratopathy")
diamond(g3, "keratopathy", "Significant exposure\nkeratopathy / corneal risk?")
box(g3, "medtreat", "Immediate medical treatment:\nlubricants (day) + ointment (night),\nwarm compresses + antibiotic\n(+/- short-course steroid) ointment\nfor inflamed margin,\ntaping as temporising measure")
diamond(g3, "etiology", "Identify cause")

box(g3, "involutional3", "INVOLUTIONAL (most common)\nHorizontal lid laxity +/-\nlateral/medial canthal tendon laxity")
box(g3, "cicatricial3", "CICATRICIAL\nAnterior lamellar shortening:\nburns, trauma, actinic damage,\nchronic inflammation, dermatoses")
box(g3, "paralytic3", "PARALYTIC\nCN VII palsy\n(+/- lagophthalmos, poor Bell's)")
box(g3, "mechanical3", "MECHANICAL\nHerniated orbital fat,\neyelid tumour")
box(g3, "allergic3", "ALLERGIC / CONTACT DERMATITIS")

box(g3, "gentarsal", "Generalized laxity: lateral tarsal\nstrip (canthal tendon tightening)\n+/- tarsoconjunctival pentagon excision")
box(g3, "medspindle", "Medial ectropion/punctal malposition:\nmedial spindle procedure,\noften + lateral tarsal strip")

diamond(g3, "cicextent", "Extent of scarring?")
box(g3, "ciclocal", "Localized/mild:\nexcise scar tissue + Z-plasty")
box(g3, "cicgen", "Generalized/severe:\nfull-thickness skin graft or\ntransposition flap\n(donor: upper lid, pre/post-auricular,\nsupraclavicular skin)")

diamond(g3, "recovery", "Recovery expected /\nirreversible palsy?")
box(g3, "paralytictemp", "Awaiting recovery (<6-12 mo):\nlubrication + taping at night,\nbotulinum toxin-induced ptosis,\ntemporary tarsorrhaphy\n(esp. if poor Bell's phenomenon)")
box(g3, "paralyticperm", "Irreversible / no improvement\nat 6-12 months:\nmedial canthoplasty +/- lateral tarsal\nstrip, lid-loading (platinum weight)\nfor lagophthalmos, brow ptosis repair")

box(g3, "mechmgmt", "Remove causative lesion\n(excise tumour / debulk fat)\n+ correct residual horizontal laxity")
box(g3, "allergicmgmt", "Remove/avoid allergen,\ntopical steroid;\nsurgery rarely needed")

end(g3, "resolved3", "Lid apposed to globe,\nexposure keratopathy resolved\n(follow up; steroid ointment users\nmonitored for side effects)")

g3.edge("s", "hx")
g3.edge("hx", "keratopathy")
g3.edge("keratopathy", "medtreat", label="yes")
g3.edge("keratopathy", "etiology", label="no / after\ntreating")
g3.edge("medtreat", "etiology")

g3.edge("etiology", "involutional3")
g3.edge("etiology", "cicatricial3")
g3.edge("etiology", "paralytic3")
g3.edge("etiology", "mechanical3")
g3.edge("etiology", "allergic3")

g3.edge("involutional3", "gentarsal", label="generalized")
g3.edge("involutional3", "medspindle", label="medial")
g3.edge("gentarsal", "resolved3")
g3.edge("medspindle", "resolved3")

g3.edge("cicatricial3", "cicextent")
g3.edge("cicextent", "ciclocal", label="localized")
g3.edge("cicextent", "cicgen", label="generalized")
g3.edge("ciclocal", "resolved3")
g3.edge("cicgen", "resolved3")

g3.edge("paralytic3", "recovery")
g3.edge("recovery", "paralytictemp", label="expected /\n<6-12 mo")
g3.edge("recovery", "paralyticperm", label="irreversible /\n>6-12 mo")
g3.edge("paralytictemp", "resolved3")
g3.edge("paralyticperm", "resolved3")

g3.edge("mechanical3", "mechmgmt")
g3.edge("mechmgmt", "resolved3")

g3.edge("allergic3", "allergicmgmt")
g3.edge("allergicmgmt", "resolved3")

g3.render("/tmp/workspace/entropion-ectropion-flowchart/3_ectropion", cleanup=True)

print("Done")
Running Command

mkdir -p /tmp/workspace/entropion-ectropion-flowchart && cd /tmp/workspace/entropion-ectropion-flowchart && python3 build_flowcharts.py && ls -la

The orthogonal splines crashed dot on the complex diagram. I'll switch to normal spline routing (the first chart rendered fine before the crash on chart 2).
Editing File

~/entropion-ectropion-flowchart/build_flowcharts.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/entropion-ectropion-flowchart/build_flowcharts.py'
Running Command

cd /tmp/workspace/entropion-ectropion-flowchart && rm -f *.png && python3 build_flowcharts.py && ls -la

All three flowcharts rendered successfully. Let me verify visually before delivering.
Reading File
Reading File
Both charts render clearly and accurately. Let me quickly check the first one too, then finalize.
Reading File
All three flowcharts are accurate and clean. Marking the task complete.I built three management flowcharts based on Kanski's Clinical Ophthalmology (10th ed.) and The Wills Eye Manual.
1. Acquired Upper Lid Entropion
Upper lid entropion
Acquired upper lid entropion is almost always cicatricial (trachoma, chemical/thermal burns, ocular cicatricial pemphigoid, Stevens-Johnson syndrome, trauma) - true involutional entropion is a lower-lid disease. Management: treat/control the underlying scarring disease first, temporize with lubricants/bandage lens/epilation, then correct surgically by severity - mild cases get tarsal fracture (transverse tarsotomy) with anterior lid margin rotation, severe cases need composite (mucous membrane/hard palate/amniotic membrane) grafting to replace scarred tarsus, adding a lateral tarsal strip if horizontal laxity coexists.
2. Acquired Lower Lid Entropion
Lower lid entropion
Three mechanisms: involutional (most common - horizontal laxity, retractor disinsertion, orbicularis override; treated with everting sutures/Wies procedure/retractor reinsertion, combined with a lateral tarsal strip if lax), cicatricial (tarsal fracture for mild, composite grafts for severe), and spastic (Quickert suture + treat the underlying irritant/blepharospasm, botulinum toxin if recurrent).
3. Acquired Ectropion
Ectropion
First address exposure keratopathy medically, then treat by cause: involutional (lateral tarsal strip for generalized laxity, medial spindle for medial/punctal ectropion), cicatricial (Z-plasty for localized scars, skin graft/flap for generalized), paralytic (temporize with taping/botulinum-induced ptosis/tarsorrhaphy while awaiting facial nerve recovery; medial canthoplasty, lid-loading, or lateral tarsal strip once irreversible or >6-12 months with no recovery), mechanical (excise the causative lesion), and allergic (remove allergen, topical steroid - surgery rarely needed).
Files:
  • 1 upper lid entropion

    Image · PNG

  • 2 lower lid entropion

    Image · PNG

  • 3 ectropion

    Image · PNG

Sources: - Kanski's Clinical Ophthalmology, 10th ed., p. 95-109 (Entropion/Ectropion chapters); - The Wills Eye Manual, 6.3 Ectropion and 6.4 Entropion, p. 384-388.
A targeted PubMed check for recent systematic reviews/meta-analyses on entropion or ectropion surgery (last 2 years) returned no directly relevant hits, so there's no recent evidence contradicting this standard textbook-based algorithm.
This is a shared conversation. Sign in to Orris to start your own chat.