Makes notes on need of repertory for 2 pages covering every important point but in the most shortest way
PERSON + NATURAL DISEASE
↓
Law of Similars
↓
Homoeopathic Materia Medica (Symptoms)
↓
REPERTORIZATION
↓
SIMILLIMUM
← matched with → ARTIFICIAL DISEASE
| Year | No. of Medicines |
|---|---|
| 1805 | 27 |
| 1921 | 1600 (1300 proved) |
| 1955 | 2000 (1500 proved) |
| 2001 | 4200 (2277 well known) |
| 2004 | 4497 (2393 well known) |
| Recently | More than 5000 |
Key Takeaway: Materia Medica is ever-enlarging (5000+ drugs, increasing clinical experiences). To manage this vast data systematically and find the Simillimum efficiently - a repertory is indispensable.
Create a summary PDF of these repertory notes
mkdir -p /home/daytona/workspace/repertory-notes && ls /home/daytona/workspace/
~/repertory-notes/create_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
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 ListFlowable, ListItem
OUTPUT = "/home/daytona/workspace/repertory-notes/Need_for_Repertory_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2*cm
)
styles = getSampleStyleSheet()
# Custom styles
title_style = ParagraphStyle(
'Title', parent=styles['Title'],
fontSize=18, textColor=colors.HexColor('#1a3a5c'),
spaceAfter=4, alignment=TA_CENTER, fontName='Helvetica-Bold'
)
subtitle_style = ParagraphStyle(
'Subtitle', parent=styles['Normal'],
fontSize=10, textColor=colors.HexColor('#5a5a5a'),
spaceAfter=10, alignment=TA_CENTER, fontName='Helvetica-Oblique'
)
section_style = ParagraphStyle(
'Section', parent=styles['Heading2'],
fontSize=11, textColor=colors.white,
backColor=colors.HexColor('#1a3a5c'),
spaceBefore=10, spaceAfter=4,
leftIndent=-6, rightIndent=-6,
fontName='Helvetica-Bold',
borderPadding=(4, 6, 4, 6)
)
body_style = ParagraphStyle(
'Body', parent=styles['Normal'],
fontSize=9.5, leading=14,
textColor=colors.HexColor('#2b2b2b'),
spaceAfter=3, fontName='Helvetica'
)
bullet_style = ParagraphStyle(
'Bullet', parent=styles['Normal'],
fontSize=9.5, leading=14,
textColor=colors.HexColor('#2b2b2b'),
leftIndent=14, spaceAfter=3,
bulletIndent=4, fontName='Helvetica'
)
quote_style = ParagraphStyle(
'Quote', parent=styles['Normal'],
fontSize=9, leading=13,
textColor=colors.HexColor('#444444'),
leftIndent=20, rightIndent=20,
fontName='Helvetica-Oblique',
backColor=colors.HexColor('#f0f4f8'),
borderPadding=(6, 8, 6, 8),
spaceAfter=6
)
key_style = ParagraphStyle(
'Key', parent=styles['Normal'],
fontSize=10, leading=14,
textColor=colors.HexColor('#1a3a5c'),
fontName='Helvetica-Bold',
spaceAfter=3
)
footer_style = ParagraphStyle(
'Footer', parent=styles['Normal'],
fontSize=8.5, leading=12,
textColor=colors.HexColor('#666666'),
alignment=TA_CENTER, fontName='Helvetica-Oblique'
)
def section(text):
return Paragraph(f" {text}", section_style)
def bullet(text):
return Paragraph(f"<bullet>\u2022</bullet> {text}", bullet_style)
def body(text):
return Paragraph(text, body_style)
def quote(text):
return Paragraph(text, quote_style)
def sp(h=6):
return Spacer(1, h)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor('#cccccc'), spaceAfter=4, spaceBefore=4)
# ---- Build content ----
story = []
# Title block
story.append(sp(4))
story.append(Paragraph("NEED FOR A REPERTORY", title_style))
story.append(Paragraph("Repertorization: Principles and Practice | Chapter 1.4", subtitle_style))
story.append(HRFlowable(width="100%", thickness=2, color=colors.HexColor('#1a3a5c'), spaceAfter=10))
# ---- SECTION 1 ----
story.append(section("1. BASIS OF HOMOEOPATHIC PRESCRIBING"))
story.append(sp(4))
story.append(bullet("Medicines prescribed on <b>Law of Similars</b>"))
story.append(bullet("Physician establishes similarity between <b>natural disease</b> and <b>artificial disease</b> (drug picture)"))
story.append(bullet("Evolution of <b>dynamic theory</b> accelerated qualitative study of drugs and patients"))
story.append(bullet("<b>Potentization:</b> quantity of medicine decreased, but qualitative value increased"))
story.append(bullet("Provers recorded a <b>maze of mental and physical symptoms</b> - useful for chronic, acute and constitutional therapy"))
story.append(sp(6))
# ---- SECTION 2 ----
story.append(section("2. WHY REPERTORY BECAME NECESSARY"))
story.append(sp(4))
story.append(bullet("Finding the <b>Simillimum</b> from many similars became <b>confusing</b> for practitioners"))
story.append(bullet("Homoeopathic Materia Medica = <b>like an ocean</b> - multitudinous symptoms of drugs"))
story.append(bullet("Referring to all similar drugs for each disease = <b>time-consuming and confusing</b>"))
story.append(bullet("Need felt for a <b>working manual</b> to ease the task of finding a specific drug"))
story.append(bullet("Need felt as early as <b>Hahnemann's era</b>; stalwarts found it difficult to practice without it"))
story.append(bullet("Any subject that is vast and contains <b>enormous facts needs indexing</b> - same for Materia Medica"))
story.append(sp(6))
# ---- SECTION 3 ----
story.append(section("3. DEFINITION & CONCEPT OF REPERTORY"))
story.append(sp(4))
story.append(bullet("<b>Repertory = Index to the Materia Medica</b> (Dr. Douglas Borland)"))
story.append(bullet("MM symptoms grouped by mental/physical or by organ/system → Repertory arranged on the <b>same plan</b>"))
story.append(bullet("Arriving at Simillimum = applying <b>logic</b> - index the ever-enlarging MM, then apply it clinically"))
story.append(sp(4))
story.append(quote('"The repertory is an outcome of the character of homoeopathy itself — an outcome of the logical human mind."'))
story.append(sp(6))
# ---- SECTION 4: Flow Diagram ----
story.append(section("4. CONCEPTUAL FLOW TO SIMILLIMUM"))
story.append(sp(4))
flow_data = [
["PERSON + NATURAL DISEASE"],
["↓ Law of Similars ↓"],
["Homoeopathic Materia Medica (Symptoms)"],
["↓ REPERTORIZATION ↓"],
["SIMILLIMUM ←→ Artificial Disease"],
]
flow_table = Table(flow_data, colWidths=[14*cm])
flow_table.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), colors.HexColor('#dce8f5')),
('BACKGROUND', (0,2), (-1,2), colors.HexColor('#dce8f5')),
('BACKGROUND', (0,4), (-1,4), colors.HexColor('#1a3a5c')),
('TEXTCOLOR', (0,4), (-1,4), colors.white),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('FONTNAME', (0,0), (-1,-1), 'Helvetica'),
('FONTNAME', (0,4), (-1,4), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9.5),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('BOX', (0,0), (-1,-1), 1, colors.HexColor('#1a3a5c')),
('INNERGRID', (0,0), (-1,-1), 0.5, colors.HexColor('#99b9d9')),
]))
story.append(flow_table)
story.append(sp(8))
# ---- SECTION 5: Growth Table ----
story.append(section("5. GROWTH OF HOMOEOPATHIC MATERIA MEDICA"))
story.append(sp(4))
story.append(body("The rapid expansion of Materia Medica makes a repertory indispensable:"))
story.append(sp(4))
table_data = [
["Year", "Number of Medicines"],
["1805", "27"],
["1921", "1600 (1300 proved)"],
["1955", "2000 (1500 proved)"],
["2001", "4200 (2277 well known)"],
["2004", "4497 (2393 well known)"],
["Recently", "More than 5000"],
]
t = Table(table_data, colWidths=[5*cm, 9*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), colors.HexColor('#1a3a5c')),
('TEXTCOLOR', (0,0), (-1,0), colors.white),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
('FONTSIZE', (0,0), (-1,-1), 9.5),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor('#f7fafd'), colors.white]),
('BOX', (0,0), (-1,-1), 1, colors.HexColor('#1a3a5c')),
('INNERGRID', (0,0), (-1,-1), 0.5, colors.HexColor('#99b9d9')),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('BACKGROUND', (0,6), (-1,6), colors.HexColor('#dce8f5')),
('FONTNAME', (0,6), (-1,6), 'Helvetica-Bold'),
]))
story.append(t)
story.append(sp(4))
story.append(body("<b>~5000 medicines</b>, each with vast symptomatology → Repertory becomes an <b>essential tool</b> in finding the indicated medicine."))
story.append(sp(8))
# ---- SECTION 6 ----
story.append(section("6. MISCONCEPTIONS & CORRECT VIEW"))
story.append(sp(4))
story.append(bullet("Some physicians complain repertory is <b>elaborate and time-consuming</b> - only those who rarely use it"))
story.append(bullet("Meaningful use = <b>useful + time-saving</b>"))
story.append(bullet("Students must <b>avoid shortcuts</b> - use repertory as a workable strategy, not a crutch"))
story.append(sp(4))
story.append(quote(
'<b>J. Willis Hurst</b> (<i>Medicine for Practicing Physicians</i>): "The goal of a medical school should be to lead '
'students to the realization that there is no short cut to learning... The student must realize the difference '
'between rearrangement of facts and simple recall memorizing, thinking and to be able to use all three."'
))
story.append(sp(6))
# ---- SECTION 7 ----
story.append(section("7. KEY CONCLUSIONS & QUOTES"))
story.append(sp(4))
story.append(bullet("Repertory helps by: <b>rearranging facts → initiating thinking → promoting learning → better clinical results</b>"))
story.append(bullet("It is a <b>must for practitioners</b> and especially for <b>learners</b>"))
story.append(sp(4))
story.append(quote(
'<b>Dr. P. Schmidt:</b> <i>"No one can know everything and that is why in all honesty one must admit that no '
'conscientious homoeopathic doctor can practice homoeopathy in a serious and really scientific way"</i> — without a repertory.'
))
story.append(sp(8))
story.append(hr())
# Key Takeaway box
takeaway_data = [[
Paragraph(
"<b>KEY TAKEAWAY:</b> Materia Medica is ever-enlarging (5000+ drugs, increasing clinical experiences). "
"To manage this vast data systematically and find the Simillimum efficiently — "
"<b>a repertory is indispensable.</b>",
ParagraphStyle('Take', parent=styles['Normal'], fontSize=9.5, leading=14,
textColor=colors.HexColor('#1a3a5c'), fontName='Helvetica')
)
]]
tb = Table(takeaway_data, colWidths=[16*cm])
tb.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#eaf2fb')),
('BOX', (0,0), (-1,-1), 1.5, colors.HexColor('#1a3a5c')),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
story.append(tb)
story.append(sp(10))
story.append(Paragraph("Repertorization: Principles and Practice | Chapter 1.4 | Summary Notes", footer_style))
doc.build(story)
print(f"PDF created: {OUTPUT}")
python /home/daytona/workspace/repertory-notes/create_pdf.py
Need for Repertory Notes
PDF Document · PDF
Bbcr in detail
BBCR Boenninghausen Characteristics Repertory homoeopathy detail
https://onlinehomeopathycourse.com/courses/boger-boenninghau…
BBCR repertory structure sections arrangement gradation remedies scope limitations homoeopathy
https://www.similia.io/blog/boenninghausen-boger-repertory-m…
Main rubrics → Sub-locations → Time → Aggravations → Ameliorations → Concomitants → Cross-references
| Section | Contents |
|---|---|
| 1. Mind & Sensorium | Mental rubrics, Vertigo (as separate chapter) |
| 2. Regional Chapters (Parts of Body) | Head, Eyes, Ears, Face, Teeth, Mouth, Throat, Stomach, Abdomen, Rectum, Urinary, Male, Female, Chest, Back, Extremities etc. |
| 3. Discharge Sections | Stool, Urine |
| 4. Physiological Function Sections | Respiration, Voice & Speech |
| 5. General Sections | Sensations in general, Glands, Bones, Skin, Conditions of Aggravation/Amelioration in general |
| 6. Fever Sections | Fever-Pathological Types, Blood, Heat & Fever in general |
| 7. Relationship of Remedies (Concordances) | Remedy relationships |
| Grade | Representation | Meaning |
|---|---|---|
| 1st | CAPITALS | Highest/strongest |
| 2nd | Bold | Very strong |
| 3rd | Italics | Strong |
| 4th | Roman (plain) | Moderate |
| 5th | (Parenthesis) | Lowest/weakest |
| Feature | Kent's Repertory | BTPB (Boenninghausen) | BBCR (Boger) |
|---|---|---|---|
| Year | 1897 | 1846 | 1905 |
| Core unit | Specific, complete rubric | Complete symptom (L+S+M+C) | Complete symptom + pathological generals |
| Emphasis | Mentals & generals first | Modalities & concomitants | Modalities, concomitants, pathological generals |
| Chapters | ~37 | Compact (7 sections) | ~53 |
| Medicines | ~600+ | Fewer | ~464 |
| Gradation | 3 grades | 4 degrees | 5 degrees |
| Fever section | Ordinary | Basic | Most elaborate |
| Concordances | No | No | Yes |
| Pathological generals | No | Limited | Yes |
| Rubric style | Specific, particularized | Generalized | General + particularized |
Summary Principle: BBCR applies the philosophy - each symptom element (Location, Sensation, Modality, Concomitant) is separately catalogued, and these elements are recombined during repertorization to find the Simillimum. This is the opposite of Kent where the complete symptom is given as a single combined rubric. BBCR demands greater analytical thinking from the prescriber.
Create a detailed comparison chart: BBCR vs Kent vs BTPB
~/repertory-notes/create_comparison_chart.py
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/repertory-notes/BBCR_vs_Kent_vs_BTPB_Comparison.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=landscape(A4),
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm
)
styles = getSampleStyleSheet()
# ---- Style definitions ----
title_style = ParagraphStyle('T', parent=styles['Title'],
fontSize=17, textColor=colors.HexColor('#1a3a5c'),
spaceAfter=2, alignment=TA_CENTER, fontName='Helvetica-Bold')
subtitle_style = ParagraphStyle('Sub', parent=styles['Normal'],
fontSize=9, textColor=colors.HexColor('#555555'),
spaceAfter=10, alignment=TA_CENTER, fontName='Helvetica-Oblique')
cell_style = ParagraphStyle('Cell', parent=styles['Normal'],
fontSize=8.2, leading=12, fontName='Helvetica',
textColor=colors.HexColor('#1e1e1e'))
cell_bold = ParagraphStyle('CellB', parent=styles['Normal'],
fontSize=8.2, leading=12, fontName='Helvetica-Bold',
textColor=colors.HexColor('#1a3a5c'))
cell_head = ParagraphStyle('CellH', parent=styles['Normal'],
fontSize=9, leading=13, fontName='Helvetica-Bold',
textColor=colors.white, alignment=TA_CENTER)
sec_style = ParagraphStyle('Sec', parent=styles['Normal'],
fontSize=9.5, leading=13, fontName='Helvetica-Bold',
textColor=colors.white, alignment=TA_CENTER)
footer_style = ParagraphStyle('Ft', parent=styles['Normal'],
fontSize=7.5, textColor=colors.HexColor('#888888'),
alignment=TA_CENTER, fontName='Helvetica-Oblique')
# ---- Color palette ----
C_DARK = colors.HexColor('#1a3a5c') # navy - section headers
C_KENT = colors.HexColor('#1565C0') # deep blue - Kent column header
C_BTPB = colors.HexColor('#2E7D32') # deep green - BTPB column header
C_BBCR = colors.HexColor('#6A1B9A') # deep purple - BBCR column header
C_ROWALT = colors.HexColor('#f4f7fb') # light blue-grey alternate row
C_WHITE = colors.white
C_SEC_BG = colors.HexColor('#263238') # dark slate - section divider rows
C_KENT_L = colors.HexColor('#E3F2FD') # light Kent
C_BTPB_L = colors.HexColor('#E8F5E9') # light BTPB
C_BBCR_L = colors.HexColor('#F3E5F5') # light BBCR
C_TICK = colors.HexColor('#2E7D32')
C_CROSS = colors.HexColor('#C62828')
def p(text, style=None):
if style is None:
style = cell_style
return Paragraph(text, style)
def ph(text):
return Paragraph(text, cell_head)
def pb(text):
return Paragraph(text, cell_bold)
def tick():
return Paragraph('<font color="#2E7D32"><b>✔</b></font>', cell_style)
def cross():
return Paragraph('<font color="#C62828"><b>✘</b></font>', cell_style)
def partial():
return Paragraph('<font color="#E65100"><b>~</b></font>', cell_style)
def sec_row(text):
"""Returns a section-divider row spanning all 4 columns."""
return [Paragraph(f' {text}', ParagraphStyle('SR', parent=styles['Normal'],
fontSize=9, leading=12, fontName='Helvetica-Bold', textColor=colors.white))]
# ---- Column widths ----
# Feature | Kent | BTPB | BBCR
W = [6.8*cm, 8.3*cm, 8.3*cm, 8.3*cm]
# ---- Table data ----
# Format: [feature, kent, btpb, bbcr]
# Section headers are single-cell spanning rows marked with "SEC:"
data = []
# ===== HEADER ROW =====
data.append([
ph('PARAMETER'),
ph("KENT'S REPERTORY"),
ph("BTPB\n(Boenninghausen's Therapeutic Pocket Book)"),
ph("BBCR\n(Boger Boenninghausen's Characteristics & Repertory)"),
])
# ===== SECTION 1: IDENTIFICATION =====
data.append(["SEC: 1. IDENTIFICATION & ORIGIN"])
data.append([
p('Author'),
p('Dr. James Tyler Kent (1849-1916)\nAmerican homoeopath'),
p('Dr. C.M.F. von Boenninghausen (1785-1864)\nDutch-German homoeopath'),
p('Dr. Cyrus Maxwell Boger (1861-1935)\nAmerican homoeopath'),
])
data.append([
p('Year Published'),
pb('1897'),
pb('1846'),
pb('1905'),
])
data.append([
p('Published By'),
p('Ehrhart & Karl, Chicago'),
p('Boenninghausen himself'),
p('Boericke & Tafel'),
])
data.append([
p('Based On'),
p('Kent\'s own drug provings &\nmateria medica studies'),
p('Boenninghausen\'s Repertory of\nAntipsoric Medicines (1832)'),
p('BTPB + Boenninghausen\'s\nSystematic Alphabetical Repertory\n+ Boger\'s clinical experience'),
])
data.append([
p('Country of Origin'),
p('USA'),
p('Germany/Netherlands'),
p('USA'),
])
# ===== SECTION 2: PHILOSOPHY =====
data.append(["SEC: 2. PHILOSOPHICAL BASIS"])
data.append([
p('Core Philosophy'),
p('Individualization based on\nmentals & generals.\nTop-down (mind → generals\n→ particulars)'),
p('Complete symptom theory.\nModalities & concomitants\nare the key to simillimum'),
p('Complete symptom +\nPathological generals.\nCombines generalization\n& particularization'),
])
data.append([
p('Totality Concept'),
p('Characteristic totality:\nMind > Physical generals\n> Particulars\n(Kentian hierarchy)'),
p('Complete symptom totality:\nLocation + Sensation +\nModality + Concomitant'),
p('Boger\'s totality:\nPathological generals +\nModalities + Concomitants\n+ Causation + Time'),
])
data.append([
p('Concept of Miasm'),
p('Strongly incorporated\n(psora, sycosis, syphilis\ninfluence case analysis)'),
p('Based on anti-psoric\nthinking (origin from\nRepertory of Antipsorics)'),
p('Anti-psoric basis inherited.\nPathological generals\nreflect miasmatic background'),
])
data.append([
p('Emphasis'),
p('Mental symptoms &\nconstitutional generals\ngiven highest priority'),
p('Modalities and\nconcomitants - considered\nmost characteristic'),
p('Modalities, concomitants\n& pathological generals\nequally emphasized'),
])
# ===== SECTION 3: STRUCTURE =====
data.append(["SEC: 3. STRUCTURE & ARRANGEMENT"])
data.append([
p('No. of Chapters/Sections'),
pb('~37 chapters'),
pb('7 sections\n(compact)'),
pb('~53 chapters'),
])
data.append([
p('No. of Medicines'),
pb('~650+'),
pb('~300 (limited)'),
pb('~464'),
])
data.append([
p('No. of Rubrics'),
pb('~68,000+'),
pb('Compact - fewer rubrics'),
pb('Moderate - expanded from BTPB'),
])
data.append([
p('Arrangement Style'),
p('Anatomical / regional:\nMind → Head → Eyes\n→ Ears → Face... downward\n(head to foot)'),
p('7 broad sections:\nMind, Body parts, Sensations,\nSleep, Fever, Aggravations,\nRelationships - in one volume'),
p('Follows Boenninghausen\'s\n7-section plan but expands\neach location into a\nseparate chapter (~53 total)'),
])
data.append([
p('Rubric Style'),
p('Specific & complete-as-given.\nLocation + Sensation +\nModality all combined in\none single rubric'),
p('Generalized.\nLocation, sensation,\nmodality kept SEPARATE.\nRecombined during repertorization'),
p('Both: main rubrics with\nsub-rubrics for particularization.\nGeneral & particular\nmodalities are differentiated'),
])
data.append([
p('Chapter Arrangement\n(Location Chapters)'),
p('Main location rubrics\narranged alphabetically\nunder each chapter'),
p('Location is one chapter.\nTime, Agg, Amel, Concomitants\nnot systematically separated'),
p('Each location chapter has:\nMain rubrics → Sub-locations\n→ Time → Agg → Amel\n→ Concomitants → X-ref'),
])
# ===== SECTION 4: GRADATION =====
data.append(["SEC: 4. GRADATION OF REMEDIES"])
data.append([
p('Number of Grades'),
pb('3 grades'),
pb('4 degrees'),
pb('5 grades (most refined)'),
])
data.append([
p('Grading System'),
p('BOLD (3rd degree)\nItalics (2nd degree)\nPlain Roman (1st degree)'),
p('Degree 4 - highest\nDegree 3\nDegree 2\nDegree 1 - lowest'),
p('CAPITALS (highest)\nBold\nItalics\nRoman (plain)\n(Parenthesis) - lowest'),
])
data.append([
p('Basis of Grading'),
p('Symptom intensity in\nproving + clinical\nconfirmation'),
p('Frequency & intensity of\nsymptom occurrence\nin provings'),
p('Proving + clinical\nconfirmation + Boger\'s\npersonal clinical experience'),
])
# ===== SECTION 5: SPECIAL FEATURES =====
data.append(["SEC: 5. SPECIAL / UNIQUE FEATURES"])
data.append([
p('Fever Section'),
p('Basic - fever rubrics\nscattered within\nchapters'),
p('Separate fever chapter\nwith chill, heat, sweat'),
pb('MOST ELABORATE.\n5 fever chapters:\nPathological types, Blood,\nHeat in general, Chill,\nSweat - treated as\nintegrated whole'),
])
data.append([
p('Concordances\n(Remedy Relationships)'),
cross(),
cross(),
tick(),
])
data.append([
p('Pathological Generals'),
cross(),
partial(),
tick(),
])
data.append([
p('Concomitants'),
partial(),
tick(),
tick(),
])
data.append([
p('Causation Rubrics'),
p('Present (under Mind\n& Generals)'),
p('Present (as separate\nmodality section)'),
pb('Strongly emphasized.\nDoctrine of Causation\nis a core concept'),
])
data.append([
p('Time Modalities'),
p('Present throughout\nchapters'),
p('Prominent - separate\ntime sections in chapters'),
p('Elaborate - Time sub-chapters\nwithin each location +\nGeneral time chapter'),
])
data.append([
p('Cross-References'),
partial(),
partial(),
tick(),
])
data.append([
p('Clinical Rubrics'),
p('Minimal (mostly\nproving-based)'),
p('Minimal'),
pb('YES - clinical rubrics\nadded from practice'),
])
data.append([
p('Mind Chapter'),
p('Very elaborate &\ndetailed - largest\nsection of repertory'),
p('Basic mind rubrics\nin "Mind & Intellect"\nsection'),
p('Contains mind rubrics\nNOT found in Kent\'s\nrepertory'),
])
# ===== SECTION 6: REPERTORIZATION =====
data.append(["SEC: 6. METHOD OF REPERTORIZATION"])
data.append([
p('Approach'),
p('Deductive / top-down.\nStart with mind/generals,\nrefine with particulars'),
p('Analytical / synthetic.\nElements separated then\nrecombined logically'),
p('Analytical + clinical.\nPathological generals +\nComplete symptom elements\ncombined'),
])
data.append([
p('Symptom Selection\nPriority'),
p('1. Mind symptoms\n2. Physical generals\n3. Particulars (last)'),
p('1. Modalities (especially\nconcomitants & time)\n2. Sensations\n3. Locations'),
p('1. Pathological generals\n2. Causation & time\n3. Modalities & concomitants\n4. Particulars'),
])
data.append([
p('Suitable Repertorization\nMethod'),
p('Totality of symptoms\n(Kentian method)\nCard / computer / manual'),
p('Synthetic method\n(Boenninghausen method).\nRecombine elements\nfrom different chapters'),
p('Boger\'s method:\nPathological generals first,\nthen complete symptom.\nGood for both acute\n& chronic'),
])
# ===== SECTION 7: SCOPE & USE =====
data.append(["SEC: 7. SCOPE & CLINICAL USE"])
data.append([
p('Best Used For'),
p('Cases with clear\nmental symptoms.\nConstitutional cases.\nChronic cases with\nrich mentals'),
p('Cases with strong\nmodalities & concomitants.\nOne-sided diseases.\nFever cases (basic)'),
p('Pathological cases.\nFever totality cases.\nCases lacking clear\nmentals.\nOne-sided diseases.\nSecond prescription'),
])
data.append([
p('Acute Cases'),
partial(),
tick(),
tick(),
])
data.append([
p('Chronic/Constitutional'),
tick(),
partial(),
tick(),
])
data.append([
p('Fever Cases'),
partial(),
tick(),
pb('BEST (most detailed)'),
])
data.append([
p('One-Sided Diseases\n(paucity of symptoms)'),
cross(),
tick(),
tick(),
])
data.append([
p('Second Prescription'),
partial(),
partial(),
pb('BEST (concordances)'),
])
data.append([
p('Cases with Pathological\nDiagnosis'),
cross(),
cross(),
tick(),
])
# ===== SECTION 8: LIMITATIONS =====
data.append(["SEC: 8. LIMITATIONS"])
data.append([
p('Main Limitations'),
p('• Fails when mentals\n are unclear/suppressed\n• Less useful in acute,\n one-sided diseases\n• Rubric hunting can\n be misleading'),
p('• Fewer medicines (~300)\n• Generalization can be\n too broad\n• Difficult to use\n without clear philosophy\n• Less particularized'),
p('• Smaller drug base\n than Kent (~464)\n• Not ideal when case\n is rich in mentals\n• Complex to learn\n without Boenninghausen\n philosophy'),
])
# ===== SECTION 9: COMPARISON SUMMARY =====
data.append(["SEC: 9. QUICK COMPARISON SUMMARY"])
data.append([
p('Best Feature'),
pb('Most rubrics & drugs.\nBest for mentals &\nconstitutional cases'),
pb('Best synthetic method.\nFoundation of complete\nsymptom philosophy'),
pb('Best fever totality.\nConcordances for 2nd\nprescription. Pathological\ngenerals'),
])
data.append([
p('Difficulty Level'),
p('Moderate\n(widely taught)'),
p('High\n(requires deep philosophy)'),
p('High\n(requires both Boenninghausen\n& Boger understanding)'),
])
data.append([
p('Popularity'),
pb('MOST WIDELY USED\nworldwide'),
p('Less popular\nbut philosophically\nrich'),
p('Popular in India &\namong Boger followers'),
])
# ---- Now build the actual table ----
# We need to process section rows specially
# Convert data into proper table rows and track which rows are section headers
table_rows = []
sec_row_indices = []
for i, row in enumerate(data):
if len(row) == 1 and isinstance(row[0], str) and row[0].startswith("SEC:"):
label = row[0][4:].strip()
table_rows.append([
Paragraph(f' {label}', ParagraphStyle('SR', parent=styles['Normal'],
fontSize=9, leading=12, fontName='Helvetica-Bold',
textColor=colors.white)),
'', '', ''
])
sec_row_indices.append(len(table_rows) - 1)
else:
table_rows.append(row)
table = Table(table_rows, colWidths=W, repeatRows=1)
# Build style commands
style_cmds = [
# Outer border
('BOX', (0,0), (-1,-1), 1.5, C_DARK),
# Default grid
('INNERGRID', (0,0), (-1,-1), 0.4, colors.HexColor('#d0d7e3')),
# All cells: padding
('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'),
# Header row
('BACKGROUND', (0,0), (0,0), C_DARK),
('BACKGROUND', (1,0), (1,0), C_KENT),
('BACKGROUND', (2,0), (2,0), C_BTPB),
('BACKGROUND', (3,0), (3,0), C_BBCR),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('TEXTCOLOR', (0,0), (-1,0), colors.white),
('FONTSIZE', (0,0), (-1,0), 9),
('ALIGN', (0,0), (-1,0), 'CENTER'),
('ROWBACKGROUNDS', (0,1), (-1,-1),
[C_WHITE, C_ROWALT]),
# Feature column always light navy text
('TEXTCOLOR', (0,1), (0,-1), C_DARK),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('BACKGROUND', (0,1), (0,-1), colors.HexColor('#edf1f7')),
]
# Section header rows
for idx in sec_row_indices:
style_cmds += [
('BACKGROUND', (0, idx), (-1, idx), C_SEC_BG),
('TEXTCOLOR', (0, idx), (-1, idx), colors.white),
('SPAN', (0, idx), (-1, idx)),
('FONTNAME', (0, idx), (-1, idx), 'Helvetica-Bold'),
('FONTSIZE', (0, idx), (-1, idx), 9),
('TOPPADDING', (0, idx), (-1, idx), 6),
('BOTTOMPADDING', (0, idx), (-1, idx), 6),
]
# Color tints for each repertory column
for r in range(1, len(table_rows)):
if r not in sec_row_indices:
style_cmds.append(('BACKGROUND', (1, r), (1, r), C_KENT_L if r % 2 == 0 else colors.white))
style_cmds.append(('BACKGROUND', (2, r), (2, r), C_BTPB_L if r % 2 == 0 else colors.white))
style_cmds.append(('BACKGROUND', (3, r), (3, r), C_BBCR_L if r % 2 == 0 else colors.white))
table.setStyle(TableStyle(style_cmds))
# ---- Build story ----
story = []
story.append(Spacer(1, 4))
story.append(Paragraph("COMPARISON CHART: BBCR vs KENT vs BTPB", title_style))
story.append(Paragraph(
"Homoeopathic Repertory - Detailed Comparative Analysis | Repertorization: Principles and Practice",
subtitle_style))
story.append(HRFlowable(width="100%", thickness=2, color=C_DARK, spaceAfter=8))
story.append(table)
story.append(Spacer(1, 8))
# Legend
legend_data = [[
Paragraph('<b>LEGEND:</b>', ParagraphStyle('Lg', parent=styles['Normal'],
fontSize=8, fontName='Helvetica-Bold', textColor=C_DARK)),
Paragraph('<font color="#2E7D32"><b>✔</b></font> = Present / Strong',
ParagraphStyle('Lg2', parent=styles['Normal'], fontSize=8, fontName='Helvetica')),
Paragraph('<font color="#C62828"><b>✘</b></font> = Absent',
ParagraphStyle('Lg3', parent=styles['Normal'], fontSize=8, fontName='Helvetica')),
Paragraph('<font color="#E65100"><b>~</b></font> = Partial / Limited',
ParagraphStyle('Lg4', parent=styles['Normal'], fontSize=8, fontName='Helvetica')),
]]
leg_table = Table(legend_data, colWidths=[3*cm, 5*cm, 4*cm, 4*cm])
leg_table.setStyle(TableStyle([
('BOX', (0,0), (-1,-1), 1, C_DARK),
('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#edf1f7')),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(leg_table)
story.append(Spacer(1, 6))
story.append(Paragraph(
"BBCR = Boger Boenninghausen's Characteristics & Repertory (1905) | "
"BTPB = Boenninghausen's Therapeutic Pocket Book (1846) | "
"Kent = Kent's Repertory of Homoeopathic Materia Medica (1897)",
footer_style))
doc.build(story)
print(f"PDF created: {OUTPUT}")
Failed to create session: bad request: failed to resolve container IP after 3 attempts: no IP address found. Is the Sandbox started?
We encountered an error while processing your request. Please try again or reach out to us for help.