PQLI in a simplified way according to park in systematic way to write in exam
PQLI physical quality of life index Park's textbook community medicine simplified
| # | Indicator |
|---|---|
| 1 | Infant Mortality Rate (IMR) |
| 2 | Life Expectancy at age 1 (not at birth) |
| 3 | Literacy rate (basic literacy) |
Memory tip: "I L L" - IMR, Life expectancy at age 1, Literacy
PQLI = (IMR score + Life Expectancy score + Literacy score) / 3
| Feature | PQLI | HDI |
|---|---|---|
| Developed by | Morris D. Morris (1979) | UNDP (1990) |
| Components | IMR, Life expectancy at age 1, Literacy | Life expectancy at birth, Education (mean + expected years of schooling), GNI per capita |
| GNP/Income included? | No | Yes |
| Scale | 0 to 100 | 0 to 1 |
| Calculation | Simple average | Geometric mean |
PQLI is a composite index developed by Morris D. Morris (1979) that consolidates three indicators - infant mortality, life expectancy at age one, and literacy - each scored 0-100 and averaged equally, with the ultimate objective of attaining a PQLI of 100.
Create a summary PDF with PQLI formula and comparison with other indices
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"
mkdir -p /home/daytona/workspace/pqli-summary && echo "done"
~/pqli-summary/generate_pdf.py
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_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/pqli-summary/PQLI_Summary.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm,
leftMargin=2*cm,
topMargin=2*cm,
bottomMargin=2*cm,
title="PQLI - Physical Quality of Life Index",
author="Park's Textbook of Preventive & Social Medicine"
)
# ── Color palette ──────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#1d7a8a")
LIGHT_BG = colors.HexColor("#eaf4f7")
YELLOW_HL = colors.HexColor("#fff8e1")
ORANGE = colors.HexColor("#e67e22")
GREEN = colors.HexColor("#27ae60")
RED_SOFT = colors.HexColor("#c0392b")
GREY_BG = colors.HexColor("#f4f4f4")
WHITE = colors.white
DARK_TEXT = colors.HexColor("#1a1a1a")
styles = getSampleStyleSheet()
# Custom styles
title_style = ParagraphStyle(
"MainTitle",
fontName="Helvetica-Bold",
fontSize=22,
textColor=WHITE,
alignment=TA_CENTER,
spaceAfter=4,
leading=28,
)
subtitle_style = ParagraphStyle(
"SubTitle",
fontName="Helvetica",
fontSize=11,
textColor=colors.HexColor("#cde8f0"),
alignment=TA_CENTER,
spaceAfter=2,
)
section_heading = ParagraphStyle(
"SectionHeading",
fontName="Helvetica-Bold",
fontSize=13,
textColor=WHITE,
spaceBefore=8,
spaceAfter=4,
leftIndent=0,
leading=18,
)
body_text = ParagraphStyle(
"BodyText",
fontName="Helvetica",
fontSize=10,
textColor=DARK_TEXT,
spaceAfter=4,
leading=15,
alignment=TA_JUSTIFY,
)
bullet_style = ParagraphStyle(
"Bullet",
fontName="Helvetica",
fontSize=10,
textColor=DARK_TEXT,
spaceAfter=3,
leading=14,
leftIndent=14,
bulletIndent=4,
)
bold_label = ParagraphStyle(
"BoldLabel",
fontName="Helvetica-Bold",
fontSize=10,
textColor=NAVY,
spaceAfter=2,
leading=14,
)
note_style = ParagraphStyle(
"Note",
fontName="Helvetica-Oblique",
fontSize=9,
textColor=colors.HexColor("#555555"),
spaceAfter=2,
leading=13,
alignment=TA_CENTER,
)
formula_style = ParagraphStyle(
"Formula",
fontName="Helvetica-Bold",
fontSize=13,
textColor=NAVY,
alignment=TA_CENTER,
spaceAfter=4,
leading=20,
)
footer_style = ParagraphStyle(
"Footer",
fontName="Helvetica-Oblique",
fontSize=8,
textColor=colors.HexColor("#888888"),
alignment=TA_CENTER,
)
# ── Helper: section banner ─────────────────────────────────────────────────────
def section_banner(text, bg=NAVY):
data = [[Paragraph(text, section_heading)]]
t = Table(data, colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("ROUNDEDCORNERS", [6, 6, 6, 6]),
]))
return t
def highlight_box(text, bg=YELLOW_HL, text_color=NAVY):
p = Paragraph(text, ParagraphStyle(
"HlBox", fontName="Helvetica-Bold", fontSize=10,
textColor=text_color, leading=15, alignment=TA_CENTER
))
t = Table([[p]], colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("BOX", (0,0), (-1,-1), 1.2, ORANGE),
]))
return t
# ── Build story ────────────────────────────────────────────────────────────────
story = []
# ── TITLE BLOCK ────────────────────────────────────────────────────────────────
title_data = [[
Paragraph("PQLI", title_style),
""
], [
Paragraph("Physical Quality of Life Index", title_style),
""
], [
Paragraph("Park's Textbook of Preventive & Social Medicine", subtitle_style),
""
], [
Paragraph("Exam-Ready Summary | Community Medicine", subtitle_style),
""
]]
title_table = Table([[
Paragraph("PQLI", title_style),
]], colWidths=[17*cm])
title_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(title_table)
subtitle_table = Table([[
Paragraph("Physical Quality of Life Index", ParagraphStyle(
"ST2", fontName="Helvetica-Bold", fontSize=16, textColor=WHITE,
alignment=TA_CENTER, leading=22
)),
]], colWidths=[17*cm])
subtitle_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(subtitle_table)
source_table = Table([[
Paragraph("Park's Textbook of Preventive & Social Medicine | Exam-Ready Summary", subtitle_style),
]], colWidths=[17*cm])
source_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#0f2940")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(source_table)
story.append(Spacer(1, 0.4*cm))
# ── 1. DEFINITION ──────────────────────────────────────────────────────────────
story.append(section_banner("1. Definition & Background"))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"PQLI is a <b>composite index</b> developed by <b>Morris D. Morris in 1979</b> to measure the "
"<b>quality of life / well-being</b> of a country's population. It was designed specifically "
"to compare 23 developing nations and to show that <i>\"money is not everything\"</i> when "
"assessing human welfare.",
body_text
))
story.append(Paragraph(
"Quality of life is difficult to <b>define</b> and even more difficult to <b>measure</b>. "
"PQLI is one attempt to provide a single, meaningful composite score from multiple health indicators.",
body_text
))
story.append(Spacer(1, 0.3*cm))
# ── 2. COMPONENTS ─────────────────────────────────────────────────────────────
story.append(section_banner("2. Three Components of PQLI", bg=TEAL))
story.append(Spacer(1, 0.2*cm))
comp_data = [
[
Paragraph("<b>#</b>", ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)),
Paragraph("<b>Indicator</b>", ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)),
Paragraph("<b>What it Measures</b>", ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)),
],
[
Paragraph("1", body_text),
Paragraph("<b>Infant Mortality Rate (IMR)</b>", body_text),
Paragraph("Deaths of children under 1 year per 1000 live births", body_text),
],
[
Paragraph("2", body_text),
Paragraph("<b>Life Expectancy at Age 1</b>", body_text),
Paragraph("Expected years of life from age 1 (NOT from birth)", body_text),
],
[
Paragraph("3", body_text),
Paragraph("<b>Basic Literacy Rate</b>", body_text),
Paragraph("Proportion of population that can read & write", body_text),
],
]
comp_table = Table(comp_data, colWidths=[1.5*cm, 7*cm, 8.5*cm])
comp_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("BACKGROUND", (0,1), (-1,1), LIGHT_BG),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), LIGHT_BG),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ALIGN", (0,0), (0,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#cccccc")),
("BOX", (0,0), (-1,-1), 1, TEAL),
]))
story.append(comp_table)
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
"Memory Aid: I - L - L (IMR | Life expectancy at age 1 | Literacy)",
bg=colors.HexColor("#e8f8f5"), text_color=GREEN
))
story.append(Paragraph(
"Note: These three components measure <b>results</b> rather than <b>inputs</b>, "
"making them suitable for international and national comparison.",
ParagraphStyle("Note2", fontName="Helvetica-Oblique", fontSize=9,
textColor=colors.HexColor("#555"), leading=13, spaceAfter=6)
))
story.append(Spacer(1, 0.3*cm))
# ── 3. SCORING & FORMULA ──────────────────────────────────────────────────────
story.append(section_banner("3. Scoring System & Formula", bg=colors.HexColor("#6c3483")))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("<b>Scoring each component:</b>", bold_label))
scoring_data = [
[
Paragraph("<b>Score</b>", ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)),
Paragraph("<b>Meaning</b>", ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)),
],
[Paragraph("<b>0</b>", ParagraphStyle("S", fontName="Helvetica-Bold", fontSize=11, textColor=RED_SOFT, alignment=TA_CENTER)),
Paragraph("Absolutely defined <b>WORST</b> performance", body_text)],
[Paragraph("<b>100</b>", ParagraphStyle("S", fontName="Helvetica-Bold", fontSize=11, textColor=GREEN, alignment=TA_CENTER)),
Paragraph("Absolutely defined <b>BEST</b> performance", body_text)],
]
scoring_t = Table(scoring_data, colWidths=[3*cm, 14*cm])
scoring_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#6c3483")),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#fde8e8")),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#e8fde8")),
("ALIGN", (0,0), (0,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#cccccc")),
("BOX", (0,0), (-1,-1), 1, colors.HexColor("#6c3483")),
]))
story.append(scoring_t)
story.append(Spacer(1, 0.3*cm))
# Formula box
formula_bg = colors.HexColor("#fff3cd")
formula_data = [[
Paragraph(
"PQLI = (IMR Score + Life Expectancy Score + Literacy Score) ÷ 3",
formula_style
)
]]
formula_table = Table(formula_data, colWidths=[17*cm])
formula_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), formula_bg),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING", (0,0), (-1,-1), 12),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 2, ORANGE),
]))
story.append(formula_table)
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(
"Equal weight is given to each indicator. The resulting PQLI is also scaled 0 to 100.",
note_style
))
story.append(Paragraph(
"<b>Ultimate objective:</b> To attain a PQLI of <b>100</b>.",
ParagraphStyle("Goal", fontName="Helvetica-Bold", fontSize=10,
textColor=RED_SOFT, alignment=TA_CENTER, spaceAfter=6)
))
story.append(Spacer(1, 0.3*cm))
# ── 4. KEY POINTS ─────────────────────────────────────────────────────────────
story.append(section_banner("4. Key / Examiner-Favourite Points", bg=colors.HexColor("#1e8449")))
story.append(Spacer(1, 0.2*cm))
key_points = [
("<b>GNP excluded</b>", "PQLI does NOT include per capita GNP, showing that <i>\"money is not everything.\"</i>"),
("<b>Classic example</b>", "Oil-rich <b>Middle East countries</b> have high per capita income but NOT very high PQLI."),
("<b>Classic counter-example</b>", "<b>Sri Lanka</b> and <b>Kerala (India)</b> have low per capita incomes but <b>high PQLI</b> - showing social development matters more."),
("<b>What PQLI measures</b>", "It measures <b>results of social, economic & political policies</b>, NOT economic growth."),
("<b>Relationship with GNP</b>", "PQLI is intended to <b>complement, not replace</b> GNP."),
("<b>Result-based</b>", "Components measure <b>results</b> rather than inputs - suitable for international comparison."),
]
for label, text in key_points:
row_data = [[
Paragraph(label, ParagraphStyle("KL", fontName="Helvetica-Bold", fontSize=10,
textColor=WHITE, leading=14)),
Paragraph(text, ParagraphStyle("KT", fontName="Helvetica", fontSize=10,
textColor=DARK_TEXT, leading=14)),
]]
row_t = Table(row_data, colWidths=[4.5*cm, 12.5*cm])
row_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), colors.HexColor("#1e8449")),
("BACKGROUND", (1,0), (1,0), GREY_BG),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#bbbbbb")),
]))
story.append(row_t)
story.append(Spacer(1, 0.1*cm))
story.append(Spacer(1, 0.3*cm))
# ── 5. COMPARISON TABLE ───────────────────────────────────────────────────────
story.append(section_banner("5. Comparison: PQLI vs HDI vs GNP / Per Capita Income"))
story.append(Spacer(1, 0.2*cm))
cmp_headers = ["Feature", "PQLI", "HDI", "GNP / Per Capita Income"]
cmp_rows = [
["Developed by", "Morris D. Morris\n(1979)", "UNDP\n(1990, Mahbub ul Haq)", "National Accounts"],
["Components", "IMR, Life expectancy at age 1, Basic literacy",
"Life expectancy at birth,\nEducation (mean + expected years of schooling),\nGNI per capita (PPP USD)",
"Total national income\n÷ population"],
["Income included?", "NO", "YES (GNI per capita)", "YES - primary measure"],
["Scale", "0 to 100", "0 to 1", "Currency (USD, INR, etc.)"],
["Calculation", "Simple average of 3 indicators", "Geometric mean of\n3 dimension indices", "GDP or GNP ÷ population"],
["Measures", "Results of social &\npolitical policies",
"Multi-dimensional\nhuman development",
"Economic output only"],
["Limitation", "Ignores income,\nhousing, political rights",
"Ignores inequality,\npoverty within country",
"Ignores health, education,\nquality of life"],
["Classic\nexample", "Kerala (low income,\nhigh PQLI)",
"Norway - consistently\ntop HDI",
"Middle East (high income,\nlower quality of life)"],
]
def make_cell(txt, is_header=False, align=TA_CENTER):
style = ParagraphStyle(
"CT",
fontName="Helvetica-Bold" if is_header else "Helvetica",
fontSize=9,
textColor=WHITE if is_header else DARK_TEXT,
alignment=align,
leading=12,
)
return Paragraph(txt, style)
cmp_data = [[make_cell(h, is_header=True) for h in cmp_headers]]
for i, row in enumerate(cmp_rows):
cmp_data.append([make_cell(row[0], is_header=True, align=TA_LEFT)] +
[make_cell(c) for c in row[1:]])
cmp_t = Table(cmp_data, colWidths=[3.5*cm, 4.2*cm, 5.3*cm, 4*cm], repeatRows=1)
cmp_style = [
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("BACKGROUND", (0,1), (0,-1), colors.HexColor("#2c5f8a")),
("TEXTCOLOR", (0,1), (0,-1), WHITE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#aaaaaa")),
("BOX", (0,0), (-1,-1), 1.2, NAVY),
# Alternating row colours
*[("BACKGROUND", (1, r), (-1, r), LIGHT_BG if r % 2 == 0 else WHITE)
for r in range(1, len(cmp_data))],
# PQLI column highlight
("BACKGROUND", (1,1), (1,-1), colors.HexColor("#d6eaf8")),
]
cmp_t.setStyle(TableStyle(cmp_style))
story.append(cmp_t)
story.append(Spacer(1, 0.3*cm))
# ── 6. QUICK REVISION BOX ─────────────────────────────────────────────────────
story.append(section_banner("6. Quick Revision - One-Liners for Exam", bg=ORANGE))
story.append(Spacer(1, 0.15*cm))
one_liners = [
"PQLI = IMR + Life expectancy at age 1 + Literacy (each scored 0-100, averaged equally).",
"Developed by Morris D. Morris, 1979, for 23 developing countries.",
"Measures <b>results</b> of policies, not economic inputs like GNP.",
"Middle East: high GNP, lower PQLI. Kerala/Sri Lanka: low GNP, high PQLI.",
"PQLI complements GNP - does not replace it.",
"Ultimate goal: PQLI score of 100.",
"HDI scale is 0-1; PQLI scale is 0-100.",
"HDI uses life expectancy at <b>birth</b>; PQLI uses life expectancy at <b>age 1</b>.",
]
for ol in one_liners:
story.append(Paragraph(
f"➤ {ol}",
ParagraphStyle("OL", fontName="Helvetica", fontSize=10,
textColor=DARK_TEXT, leading=15, spaceAfter=3,
leftIndent=10)
))
story.append(Spacer(1, 0.4*cm))
# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=1, color=TEAL))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(
"Source: Park's Textbook of Preventive and Social Medicine | Community Medicine Summary | Orris AI",
footer_style
))
# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
cd /home/daytona/workspace/pqli-summary && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/pqli-summary/PQLI_Summary.pdf
PQLI Summary
PDF Document · PDF
| Section | Content |
|---|---|
| 1. Definition & Background | Morris D. Morris (1979), purpose, origin |
| 2. Three Components | IMR, Life Expectancy at age 1, Literacy - with memory aid "I-L-L" |
| 3. Scoring & Formula | 0-100 scale, formula box, ultimate goal = 100 |
| 4. Key / Examiner Points | GNP excluded, Kerala/Sri Lanka example, Middle East counter-example |
| 5. Comparison Table | PQLI vs HDI vs GNP/Per Capita Income (side-by-side, 8 features) |
| 6. Quick Revision One-Liners | 8 bullet points for last-minute revision |