These are assignment written under heading 'xray age estimation" for page no 3,4,5 in pdf .taking this as example prepare xray age estimation for page 11,12,13 in pdf as my roll no is 98 and name is sariga m g for my forensic medicine assignment
cd /home/daytona/workspace/attachments/88faa994-4236-42bc-9fcd-edb52ec1450f/ && python3 -c " import pdfplumber with pdfplumber.open('DOC-20260611-WA0088..pdf') as pdf: print(f'Total pages: {len(pdf.pages)}') for pg_num in [10, 11, 12]: # 0-indexed for pages 11,12,13 page = pdf.pages[pg_num] print(f'\n\n========== PAGE {pg_num+1} ==========') text = page.extract_text() print(text if text else '[No text extracted - possibly image/scan]') "
python3 -c " from pypdf import PdfReader import base64, os reader = PdfReader('/home/daytona/workspace/attachments/88faa994-4236-42bc-9fcd-edb52ec1450f/DOC-20260611-WA0088..pdf') print(f'Total pages: {len(reader.pages)}') for pg_idx in [10, 11, 12]: page = reader.pages[pg_idx] print(f'\nPage {pg_idx+1} resources keys: {list(page.get(\"/Resources\", {}).keys()) if page.get(\"/Resources\") else \"none\"}') if '/XObject' in page.get('/Resources', {}): xobj = page['/Resources']['/XObject'] print(f' XObjects: {list(xobj.keys())}') "
python3 -c " from pypdf import PdfReader import os reader = PdfReader('/home/daytona/workspace/attachments/88faa994-4236-42bc-9fcd-edb52ec1450f/DOC-20260611-WA0088..pdf') os.makedirs('/home/daytona/workspace/xray_pages', exist_ok=True) for pg_idx, img_name in [(10, 'Image37'), (11, 'Image40'), (12, 'Image43')]: page = reader.pages[pg_idx] xobj = page['/Resources']['/XObject'] img = xobj[f'/{img_name}'] data = img._data # detect format if data[:4] == b'\xff\xd8\xff\xe0' or data[:2] == b'\xff\xd8': ext = 'jpg' elif data[:4] == b'\x89PNG': ext = 'png' else: ext = 'bin' out_path = f'/home/daytona/workspace/xray_pages/page{pg_idx+1}.{ext}' with open(out_path, 'wb') as f: f.write(data) print(f'Page {pg_idx+1}: saved {out_path} ({len(data)} bytes)') "
ls /home/daytona/skills/docx/scripts/office/
mkdir -p /home/daytona/workspace/xray-assignment && cat > /home/daytona/workspace/xray-assignment/create_assignment.js << 'EOF' const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, AlignmentType, WidthType, BorderStyle, HeadingLevel, PageBreak, ShadingType, VerticalAlign, UnderlineType } = require('docx'); const fs = require('fs'); // Helper: underlined bold text run const uBold = (text, size=24) => new TextRun({ text, bold: true, underline: { type: UnderlineType.SINGLE }, size }); const bold = (text, size=24) => new TextRun({ text, bold: true, size }); const normal = (text, size=24) => new TextRun({ text, size }); const tab = (size=24) => new TextRun({ text: '\t', size }); // Helper: blank line paragraph const blankLine = () => new Paragraph({ children: [new TextRun({ text: '', size: 24 })], spacing: { after: 0 } }); // Border style for table cells const cellBorder = { top: { style: BorderStyle.SINGLE, size: 6, color: "000000" }, bottom: { style: BorderStyle.SINGLE, size: 6, color: "000000" }, left: { style: BorderStyle.SINGLE, size: 6, color: "000000" }, right: { style: BorderStyle.SINGLE, size: 6, color: "000000" }, }; // Helper to make table cell with text const makeCell = (text, bold_=false, width=2500, italic=false) => new TableCell({ width: { size: width, type: WidthType.DXA }, borders: cellBorder, verticalAlign: VerticalAlign.CENTER, children: [new Paragraph({ children: [new TextRun({ text, bold: bold_, italic, size: 22 })], spacing: { before: 40, after: 40 }, indent: { left: 80 } })] }); // ======================================================= // PAGE 11 - ELBOW JOINT (AP view, Right, Age 12 years) // ======================================================= // Table for elbow joint ossification centers const elbowTable = new Table({ width: { size: 9000, type: WidthType.DXA }, rows: [ new TableRow({ children: [ makeCell('For Elbow Joint', true, 3200), makeCell('Appearance', true, 2400), makeCell('Fusion', true, 2400), ] }), new TableRow({ children: [ makeCell('1) Lower end of Humerus', true, 3200), makeCell('', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Capitulum', false, 3200), makeCell('2 years', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Trochlea', false, 3200), makeCell('11 years', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Lateral epicondyle', false, 3200), makeCell('12-13 years', false, 2400), makeCell('14-17 years - fusion with shaft', false, 2400), ]}), new TableRow({ children: [ makeCell(' Composite epiphysis', false, 3200), makeCell('14 years', false, 2400), makeCell('15-17 years', false, 2400), ]}), new TableRow({ children: [ makeCell(' Medial epicondyle', false, 3200), makeCell('5-8 years', false, 2400), makeCell('14-17 years', false, 2400), ]}), new TableRow({ children: [ makeCell('2) Upper end of Radius', true, 3200), makeCell('6 years', false, 2400), makeCell('14-17 years', false, 2400), ]}), new TableRow({ children: [ makeCell('3) Upper end of Ulna', true, 3200), makeCell('10 years', false, 2400), makeCell('14-17 years', false, 2400), ]}), ] }); // ======================================================= // PAGE 12 - SHOULDER JOINT (AP view, Right, <16 years) // ======================================================= const shoulderTable = new Table({ width: { size: 9000, type: WidthType.DXA }, rows: [ new TableRow({ children: [ makeCell('For Shoulder Joint', true, 3200), makeCell('Appearance', true, 2400), makeCell('Fusion', true, 2400), ]}), new TableRow({ children: [ makeCell('1) Upper end of Humerus', true, 3200), makeCell('', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Head', false, 3200), makeCell('1 year', false, 2400), makeCell('16-18 yrs - fusion with shaft', false, 2400), ]}), new TableRow({ children: [ makeCell(' Greater tubercle', false, 3200), makeCell('3 years', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Lesser tubercle', false, 3200), makeCell('5 years', false, 2400), makeCell('', false, 2400), ]}), new TableRow({ children: [ makeCell(' Composite Epiphysis', false, 3200), makeCell('6 years', false, 2400), makeCell('17-18 years', false, 2400), ]}), new TableRow({ children: [ makeCell('2) Acromial end (Clavicle)', true, 3200), makeCell('14 years', false, 2400), makeCell('16 years', false, 2400), ]}), new TableRow({ children: [ makeCell('3) Coracoid process', true, 3200), makeCell('10 years', false, 2400), makeCell('', false, 2400), ]}), ] }); // ======================================================= // PAGE 13 - PELVIS (AP view, <10 years) // ======================================================= const pelvisTable = new Table({ width: { size: 9000, type: WidthType.DXA }, rows: [ new TableRow({ children: [ makeCell('For Pelvis', true, 3200), makeCell('Appearance', true, 2400), makeCell('Fusion', true, 2400), ]}), new TableRow({ children: [ makeCell('~ Iliac crest', false, 3200), makeCell('14 years', false, 2400), makeCell('18 years', false, 2400), ]}), new TableRow({ children: [ makeCell('~ Ischial tuberosity', false, 3200), makeCell('16 years', false, 2400), makeCell('19 yrs (F) / 21 yrs (M)', false, 2400), ]}), new TableRow({ children: [ makeCell('~ Triradiate cartilage obliteration', false, 3200), makeCell('11-14 years', false, 2400), makeCell('', false, 2400), ]}), ] }); // ======================================================= // BUILD DOCUMENT // ======================================================= const doc = new Document({ sections: [{ properties: { page: { margin: { top: 720, right: 720, bottom: 720, left: 900 } } }, children: [ // ---- Header ---- new Paragraph({ children: [uBold('X-RAY AGE ESTIMATION', 28)], alignment: AlignmentType.CENTER, spacing: { after: 0 } }), new Paragraph({ children: [bold('Sariga M G', 24), tab(24), bold('Roll No: 98', 24)], alignment: AlignmentType.RIGHT, spacing: { after: 60 } }), new Paragraph({ children: [bold('Forensic Medicine Assignment', 22)], alignment: AlignmentType.CENTER, spacing: { after: 200 } }), // ============================================================ // QUESTION 4 - Elbow Joint AP view (Page 11) - Age 12 years // ============================================================ new Paragraph({ children: [bold('4) Given', 24)], spacing: { before: 100, after: 60 } }), new Paragraph({ children: [bold('X-ray of Elbow Joint', 24)], indent: { left: 360 }, spacing: { after: 60 } }), new Paragraph({ children: [normal('AP view of right elbow joint showing multiple ossification centers.', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('From the appearance and fusion of the various ossification centers, the age of a person can be determined.', 24)], indent: { left: 360 }, spacing: { after: 200 } }), elbowTable, blankLine(), new Paragraph({ children: [normal('In the given X-ray of elbow joint, shows appearance of:', 24)], spacing: { before: 120, after: 60 } }), new Paragraph({ children: [normal('~ Capitulum', 24), tab(), normal('- 2 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Trochlea', 24), tab(), normal('- 11 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Medial epicondyle', 24), tab(), normal('- 5-8 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Upper end of radius', 24), tab(), normal('- 6 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Upper end of ulna', 24), tab(), normal('- 10 yrs', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('But no appearance and fusion of Composite epiphysis, Lateral epicondyle.', 24)], spacing: { after: 120 } }), new Paragraph({ children: [normal('Thus, the age of the child is about ', 24), uBold('12 years', 24), normal('.', 24)], spacing: { after: 300 } }), // ============================================================ // QUESTION 5 - Shoulder Joint AP view (Page 12) - <16 years // ============================================================ new Paragraph({ children: [new PageBreak()] }), new Paragraph({ children: [bold('5) Given', 24)], spacing: { before: 100, after: 60 } }), new Paragraph({ children: [bold('X-ray of Shoulder Joint', 24)], indent: { left: 360 }, spacing: { after: 60 } }), new Paragraph({ children: [normal('AP view of right shoulder joint showing multiple ossification centers.', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('From the appearance and fusion of the various ossification centers, the age of a person can be determined.', 24)], indent: { left: 360 }, spacing: { after: 200 } }), shoulderTable, blankLine(), new Paragraph({ children: [normal('In the given X-ray of shoulder joint, shows appearance of:', 24)], spacing: { before: 120, after: 60 } }), new Paragraph({ children: [normal('~ Head', 24), tab(), normal('- 1 yr', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Greater tubercle', 24), tab(), normal('- 3 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Lesser tubercle', 24), tab(), normal('- 5 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Composite Epiphysis', 24), tab(), normal('- 6 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Acromial end (Clavicle)', 24), tab(), normal('- 14 yrs', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ Coracoid process', 24), tab(), normal('- 10 yrs', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('But no fusion takes place.', 24)], spacing: { after: 120 } }), new Paragraph({ children: [normal('Thus, the age of the individual is about ', 24), uBold('< 16 years', 24), normal('.', 24)], spacing: { after: 300 } }), // ============================================================ // QUESTION 6 - Pelvis AP view (Page 13) - <10 years // ============================================================ new Paragraph({ children: [new PageBreak()] }), new Paragraph({ children: [bold('6) Given', 24)], spacing: { before: 100, after: 60 } }), new Paragraph({ children: [bold('X-ray of Pelvis', 24)], indent: { left: 360 }, spacing: { after: 60 } }), new Paragraph({ children: [normal('AP view of pelvis showing ossification centers and cartilage status.', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('From the appearance and fusion of the various ossification centers, the age of a person can be determined.', 24)], indent: { left: 360 }, spacing: { after: 200 } }), pelvisTable, blankLine(), new Paragraph({ children: [normal('In the given X-ray of pelvis, shows:', 24)], spacing: { before: 120, after: 60 } }), new Paragraph({ children: [normal('~ No appearance of Iliac crest (appears at 14 yrs)', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ No appearance of Ischial tuberosity (appears at 16 yrs)', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ No obliteration of Triradiate cartilage (obliterates at 11-14 yrs)', 24)], indent: { left: 360 }, spacing: { after: 40 } }), new Paragraph({ children: [normal('~ No fusion of Iliac crest (fuses at 18 yrs)', 24)], indent: { left: 360 }, spacing: { after: 100 } }), new Paragraph({ children: [normal('Thus, the age of the individual is about ', 24), uBold('< 10 years', 24), normal('.', 24)], spacing: { after: 200 } }), ] }] }); Packer.toBuffer(doc).then(buf => { fs.writeFileSync('/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.docx', buf); console.log('Done: Xray_Age_Estimation_Sariga_MG_Roll98.docx'); }).catch(e => { console.error(e); process.exit(1); }); EOF node /home/daytona/workspace/xray-assignment/create_assignment.js
python3 /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.docx
# Quick check: can we open the file and count paragraphs? python3 -c " from pypdf import PdfReader # just verify the docx is a valid zip import zipfile z = zipfile.ZipFile('/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.docx') names = z.namelist() print('Files in docx:', names[:10]) print('Size:', len(open('/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.docx','rb').read()), 'bytes') "
python3 -c " import zipfile, re z = zipfile.ZipFile('/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.docx') xml = z.read('word/document.xml').decode('utf-8') # Extract plain text text = re.sub(r'<[^>]+>', ' ', xml) text = re.sub(r'\s+', ' ', text).strip() print(text[:3000]) "
Xray Age Estimation Sariga MG Roll98
Word Document · DOCX
Make it into a pdf file with word format like handwriting
fc-list | grep -i "handwrit\|caveat\|dancing\|pacifico\|satisfy\|schoolbell\|indie\|architects\|kalam\|Patrick\|Gloria\|Amatic\|Shadows\|Permanent\|Gochi\|Reenie\|Rock Salt\|Covered\|Just Me\|Handlee" 2>/dev/null | head -30
fc-list | grep -i "mono\|serif\|sans\|free\|ubuntu\|dejavu\|noto\|liberation" | head -20; echo "---"; fc-list 2>/dev/null | wc -l
mkdir -p /home/daytona/workspace/xray-assignment/fonts && cd /home/daytona/workspace/xray-assignment/fonts && curl -sL "https://github.com/google/fonts/raw/main/ofl/caveat/Caveat%5Bwght%5D.ttf" -o Caveat.ttf && ls -lh
python3 -c " from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont pdfmetrics.registerFont(TTFont('Caveat', '/home/daytona/workspace/xray-assignment/fonts/Caveat.ttf')) print('Font loaded OK') "
~/xray-assignment/make_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# Register handwriting font
pdfmetrics.registerFont(TTFont('Caveat', '/home/daytona/workspace/xray-assignment/fonts/Caveat.ttf'))
W, H = A4 # 595 x 842 pt
MARGIN_L = 25 * mm
MARGIN_R = 18 * mm
MARGIN_T = 20 * mm
MARGIN_B = 18 * mm
LINE_SPACING = 8.5 * mm # ruled-line spacing
FONT_NORMAL = 'Caveat'
SZ_NORMAL = 15
SZ_HEADING = 17
SZ_TITLE = 20
BLUE_INK = (0.08, 0.12, 0.55)
RULE_COLOR = (0.72, 0.82, 0.95)
RED_MARGIN = (0.85, 0.25, 0.25)
OUTPUT = '/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.pdf'
c = canvas.Canvas(OUTPUT, pagesize=A4)
# ── helpers ────────────────────────────────────────────────────────────────────
def draw_ruled_page(c):
"""Draw notebook lines and margin."""
# faint blue horizontal rules
c.setStrokeColorRGB(*RULE_COLOR)
c.setLineWidth(0.4)
y = H - MARGIN_T
while y > MARGIN_B:
c.line(MARGIN_L - 4*mm, y, W - MARGIN_R, y)
y -= LINE_SPACING
# red vertical margin line
c.setStrokeColorRGB(*RED_MARGIN)
c.setLineWidth(0.7)
c.line(MARGIN_L, MARGIN_B, MARGIN_L, H - MARGIN_T)
def snap(y):
"""Snap y to nearest ruled line."""
top = H - MARGIN_T
n = round((top - y) / LINE_SPACING)
return top - n * LINE_SPACING
class Writer:
"""Stateful cursor that writes on ruled lines."""
def __init__(self, c):
self.c = c
self.x = MARGIN_L + 3*mm
self.y = H - MARGIN_T
self._new_page()
def _new_page(self):
draw_ruled_page(self.c)
self.y = H - MARGIN_T
def advance(self, lines=1):
self.y -= LINE_SPACING * lines
if self.y < MARGIN_B + LINE_SPACING:
self.c.showPage()
self._new_page()
def write(self, text, size=SZ_NORMAL, bold=False, underline=False,
indent=0, align='left', color=BLUE_INK, extra_lines=0):
self.advance(1)
self.c.setFont(FONT_NORMAL, size)
self.c.setFillColorRGB(*color)
x = self.x + indent
self.c.drawString(x, self.y + 1.5, text)
if underline:
tw = self.c.stringWidth(text, FONT_NORMAL, size)
self.c.setStrokeColorRGB(*color)
self.c.setLineWidth(0.8)
self.c.line(x, self.y - 1, x + tw, self.y - 1)
if extra_lines:
self.advance(extra_lines)
def write_two_col(self, left, right, size=SZ_NORMAL, left_w=95*mm):
"""Write two-column line (label + value)."""
self.advance(1)
self.c.setFont(FONT_NORMAL, size)
self.c.setFillColorRGB(*BLUE_INK)
self.c.drawString(self.x, self.y + 1.5, left)
self.c.drawString(self.x + left_w, self.y + 1.5, right)
def blank(self, n=1):
self.advance(n)
def draw_table(self, headers, rows, col_widths):
"""Draw a simple hand-drawn-style table."""
col_x = [self.x]
for w in col_widths[:-1]:
col_x.append(col_x[-1] + w)
row_h = LINE_SPACING
total_w = sum(col_widths)
n_rows = len(rows) + 1 # +1 for header
# check space; if not enough, new page
needed = (n_rows + 1) * row_h
if self.y - needed < MARGIN_B:
self.c.showPage()
self._new_page()
self.advance(1)
# top line of table
top_y = self.y - 2
def draw_row_box(y_top, row_data, is_header=False):
sz = SZ_NORMAL - 1
self.c.setStrokeColorRGB(0.15, 0.15, 0.45)
self.c.setLineWidth(0.5)
# horizontal lines
self.c.line(self.x, y_top, self.x + total_w, y_top)
self.c.line(self.x, y_top - row_h, self.x + total_w, y_top - row_h)
# vertical lines
for cx in col_x:
self.c.line(cx, y_top, cx, y_top - row_h)
self.c.line(self.x + total_w, y_top, self.x + total_w, y_top - row_h)
# text
for i, cell in enumerate(row_data):
self.c.setFont(FONT_NORMAL, sz)
self.c.setFillColorRGB(*BLUE_INK)
self.c.drawString(col_x[i] + 2*mm, y_top - row_h + 2.5, str(cell) if cell else '')
# draw header
draw_row_box(top_y, headers, is_header=True)
cur_y = top_y - row_h
for row in rows:
draw_row_box(cur_y, row)
cur_y -= row_h
# advance cursor past table
steps = n_rows
self.y = cur_y
# make sure cursor is on a ruled line
self.blank(1)
# ── content data ───────────────────────────────────────────────────────────────
ELBOW_HEADERS = ['For Elbow Joint', 'Appearance', 'Fusion']
ELBOW_ROWS = [
['1) Lower end of Humerus', '', ''],
[' Capitulum', '2 years', ''],
[' Trochlea', '11 years', ''],
[' Lateral epicondyle', '12-13 years', '14-17 yrs - fusion with shaft'],
[' Composite epiphysis', '14 years', '15-17 years'],
[' Medial epicondyle', '5-8 years', '14-17 years'],
['2) Upper end of Radius', '6 years', '14-17 years'],
['3) Upper end of Ulna', '10 years', '14-17 years'],
]
ELBOW_COLS = [70*mm, 45*mm, 68*mm]
SHOULDER_HEADERS = ['For Shoulder Joint', 'Appearance', 'Fusion']
SHOULDER_ROWS = [
['1) Upper end of Humerus', '', ''],
[' Head', '1 year', '16-18 yrs - fusion with shaft'],
[' Greater tubercle', '3 years', ''],
[' Lesser tubercle', '5 years', ''],
[' Composite Epiphysis', '6 years', '17-18 years'],
['2) Acromial end (Clavicle)', '14 years', '16 years'],
['3) Coracoid process', '10 years', ''],
]
SHOULDER_COLS = [70*mm, 45*mm, 68*mm]
PELVIS_HEADERS = ['For Pelvis', 'Appearance', 'Fusion']
PELVIS_ROWS = [
['~ Iliac crest', '14 years', '18 years'],
['~ Ischial tuberosity', '16 years', '19 yrs (F) / 21 yrs (M)'],
['~ Triradiate cartilage obliteration', '11-14 years', ''],
]
PELVIS_COLS = [70*mm, 45*mm, 68*mm]
# ── build PDF ──────────────────────────────────────────────────────────────────
w = Writer(c)
# ---- Title block ----
w.write('X-RAY AGE ESTIMATION', size=SZ_TITLE, underline=True)
# Name & roll right-aligned
c.setFont(FONT_NORMAL, SZ_NORMAL)
c.setFillColorRGB(*BLUE_INK)
name_line = 'Sariga M G Roll No: 98'
c.drawRightString(W - MARGIN_R, w.y + 1.5, name_line)
w.advance(1)
c.setFont(FONT_NORMAL, SZ_NORMAL - 1)
c.drawRightString(W - MARGIN_R, w.y + 1.5, 'Forensic Medicine Assignment')
w.blank(1)
# ══════════════════════════════════════════════
# Q4 - Elbow Joint (Page 11 - age 12 years)
# ══════════════════════════════════════════════
w.write('4) Given', size=SZ_HEADING)
w.write(' X-ray of Elbow Joint', size=SZ_NORMAL)
w.write(' AP view of right elbow joint showing multiple ossification centers.', size=SZ_NORMAL)
w.write(' From the appearance and fusion of the various ossification centers,', size=SZ_NORMAL)
w.write(' the age of a person can be determined.', size=SZ_NORMAL)
w.blank(0.5)
w.draw_table(ELBOW_HEADERS, ELBOW_ROWS, ELBOW_COLS)
w.write('In the given X-ray of elbow joint, shows appearance of:', size=SZ_NORMAL)
w.write(' ~ Capitulum - 2 yrs', size=SZ_NORMAL)
w.write(' ~ Trochlea - 11 yrs', size=SZ_NORMAL)
w.write(' ~ Medial epicondyle - 5-8 yrs', size=SZ_NORMAL)
w.write(' ~ Upper end of radius - 6 yrs', size=SZ_NORMAL)
w.write(' ~ Upper end of ulna - 10 yrs', size=SZ_NORMAL)
w.blank(0.3)
w.write('But no appearance and fusion of Composite epiphysis and', size=SZ_NORMAL)
w.write('Lateral epicondyle.', size=SZ_NORMAL)
w.blank(0.3)
w.write('Thus, the age of the child is about 12 years.', size=SZ_HEADING, underline=False)
# draw underline under "12 years"
label = 'Thus, the age of the child is about '
prefix_w = c.stringWidth(label, FONT_NORMAL, SZ_HEADING)
val_text = '12 years.'
val_w = c.stringWidth(val_text, FONT_NORMAL, SZ_HEADING)
c.setStrokeColorRGB(*BLUE_INK)
c.setLineWidth(0.9)
c.line(w.x + prefix_w, w.y - 1, w.x + prefix_w + val_w, w.y - 1)
w.blank(1)
# ══════════════════════════════════════════════
# Q5 - Shoulder Joint (Page 12 - <16 years)
# ══════════════════════════════════════════════
# force new page for clean look
c.showPage()
w._new_page()
w.advance(1)
w.write('5) Given', size=SZ_HEADING)
w.write(' X-ray of Shoulder Joint', size=SZ_NORMAL)
w.write(' AP view of right shoulder joint showing multiple ossification centers.', size=SZ_NORMAL)
w.write(' From the appearance and fusion of the various ossification centers,', size=SZ_NORMAL)
w.write(' the age of a person can be determined.', size=SZ_NORMAL)
w.blank(0.5)
w.draw_table(SHOULDER_HEADERS, SHOULDER_ROWS, SHOULDER_COLS)
w.write('In the given X-ray of shoulder joint, shows appearance of:', size=SZ_NORMAL)
w.write(' ~ Head - 1 yr', size=SZ_NORMAL)
w.write(' ~ Greater tubercle - 3 yrs', size=SZ_NORMAL)
w.write(' ~ Lesser tubercle - 5 yrs', size=SZ_NORMAL)
w.write(' ~ Composite Epiphysis - 6 yrs', size=SZ_NORMAL)
w.write(' ~ Acromial end - 14 yrs', size=SZ_NORMAL)
w.write(' ~ Coracoid process - 10 yrs', size=SZ_NORMAL)
w.blank(0.3)
w.write('But no fusion takes place.', size=SZ_NORMAL)
w.blank(0.3)
w.write('Thus, the age of the individual is about < 16 years.', size=SZ_HEADING)
label2 = 'Thus, the age of the individual is about '
prefix_w2 = c.stringWidth(label2, FONT_NORMAL, SZ_HEADING)
val_text2 = '< 16 years.'
val_w2 = c.stringWidth(val_text2, FONT_NORMAL, SZ_HEADING)
c.setStrokeColorRGB(*BLUE_INK)
c.setLineWidth(0.9)
c.line(w.x + prefix_w2, w.y - 1, w.x + prefix_w2 + val_w2, w.y - 1)
w.blank(1)
# ══════════════════════════════════════════════
# Q6 - Pelvis (Page 13 - <10 years)
# ══════════════════════════════════════════════
c.showPage()
w._new_page()
w.advance(1)
w.write('6) Given', size=SZ_HEADING)
w.write(' X-ray of Pelvis', size=SZ_NORMAL)
w.write(' AP view of pelvis showing ossification centers and cartilage status.', size=SZ_NORMAL)
w.write(' From the appearance and fusion of the various ossification centers,', size=SZ_NORMAL)
w.write(' the age of a person can be determined.', size=SZ_NORMAL)
w.blank(0.5)
w.draw_table(PELVIS_HEADERS, PELVIS_ROWS, PELVIS_COLS)
w.write('In the given X-ray of pelvis, shows:', size=SZ_NORMAL)
w.write(' ~ No appearance of Iliac crest (appears at 14 yrs)', size=SZ_NORMAL)
w.write(' ~ No appearance of Ischial tuberosity (appears at 16 yrs)', size=SZ_NORMAL)
w.write(' ~ No obliteration of Triradiate cartilage (obliterates at 11-14 yrs)', size=SZ_NORMAL)
w.write(' ~ No fusion of Iliac crest (fuses at 18 yrs)', size=SZ_NORMAL)
w.blank(0.3)
w.write('Thus, the age of the individual is about < 10 years.', size=SZ_HEADING)
label3 = 'Thus, the age of the individual is about '
prefix_w3 = c.stringWidth(label3, FONT_NORMAL, SZ_HEADING)
val_text3 = '< 10 years.'
val_w3 = c.stringWidth(val_text3, FONT_NORMAL, SZ_HEADING)
c.setStrokeColorRGB(*BLUE_INK)
c.setLineWidth(0.9)
c.line(w.x + prefix_w3, w.y - 1, w.x + prefix_w3 + val_w3, w.y - 1)
c.save()
print('PDF saved:', OUTPUT)
python3 /home/daytona/workspace/xray-assignment/make_pdf.py
ls -lh /home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.pdf && python3 -c " from pypdf import PdfReader r = PdfReader('/home/daytona/workspace/xray-assignment/Xray_Age_Estimation_Sariga_MG_Roll98.pdf') print(f'Pages: {len(r.pages)}') for i, p in enumerate(r.pages): t = p.extract_text() print(f'Page {i+1} preview: {t[:80]}') "
Xray Age Estimation Sariga MG Roll98
PDF Document · PDF