Analysis
| Parameter | Finding |
|---|---|
| Rate | ~90-110 bpm (sinus tachycardia) |
| Rhythm | Regular - sinus rhythm |
| P waves | Upright in I, II - sinus origin |
| PR interval | Normal |
| QRS duration | Narrow (<120 ms) |
| QRS axis | Normal to left axis |
| Voltage | Increased - meets LVH criteria (likely) |
| ST-T changes | Possible LV strain pattern in lateral leads |
| Acute ischemia | No overt ST elevation; cannot fully exclude subtle changes |
Important disclaimer: This is an AI-assisted interpretation of a photographed ECG. Image angle, paper crease, and resolution limit precision. This analysis should not replace formal cardiologist review. If the patient has symptoms (chest pain, dyspnea, syncope, palpitations), urgent clinical correlation and formal ECG reporting is essential.
Is there Heart attack
| Sign | What It Means |
|---|---|
| ST elevation | Acute transmural injury (STEMI) |
| ST depression | Ischemia or NSTEMI |
| New Q waves | Old / evolving infarction |
| T-wave inversion | Ischemia or post-infarct change |
| Hyperacute T waves | Very early STEMI |
| Feature | LVH Strain | Acute MI |
|---|---|---|
| ST depression | Lateral leads (V5, V6, I, aVL) | Variable territory |
| T-wave inversion | Asymmetric, gradual | Often deeper, symmetric |
| ST elevation | None | Present in culprit territory |
| Q waves | Not typical | Often present |
| QRS voltage | Very tall | Normal or reduced |
No clear ECG evidence of an acute heart attack (STEMI) is seen on this tracing. The ST-T changes visible are most consistent with LVH strain pattern, which is a secondary effect of thickened heart muscle - commonly due to longstanding high blood pressure or valve disease.
Analysis report
ls -la /home/daytona/workspace/ && ls /home/daytona/skills/docx/
~/ecg-report/generate_report.js
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, HeadingLevel, BorderStyle, WidthType, VerticalAlign,
ShadingType, Header, Footer, PageNumber, NumberFormat
} = require('docx');
const fs = require('fs');
const COLORS = {
headerBg: "1a3c5e",
headerText: "FFFFFF",
sectionBg: "dce6f1",
altRow: "f2f7fc",
alertBg: "fff3cd",
alertBorder: "ffc107",
normalBg: "e8f5e9",
abnormalBg: "fdecea",
borderColor: "2c5f8a",
lightGray: "f5f5f5",
};
function makeCell(text, options = {}) {
const {
bold = false,
bg = null,
color = "000000",
width = null,
align = AlignmentType.LEFT,
size = 20,
} = options;
const cellChildren = [
new Paragraph({
alignment: align,
children: [
new TextRun({ text, bold, color, size, font: "Calibri" }),
],
}),
];
const cellOpts = {
children: cellChildren,
margins: { top: 100, bottom: 100, left: 120, right: 120 },
verticalAlign: VerticalAlign.CENTER,
};
if (bg) cellOpts.shading = { type: ShadingType.CLEAR, fill: bg };
if (width) cellOpts.width = { size: width, type: WidthType.DXA };
return new TableCell(cellOpts);
}
function headerRow(cells) {
return new TableRow({
children: cells.map(({ text, width }) =>
makeCell(text, { bold: true, bg: COLORS.headerBg, color: COLORS.headerText, width, align: AlignmentType.CENTER, size: 20 })
),
tableHeader: true,
});
}
function dataRow(cells, bgColor = null) {
return new TableRow({
children: cells.map(({ text, bold = false, align = AlignmentType.LEFT, bg = bgColor }) =>
makeCell(text, { bold, bg: bg || COLORS.lightGray, size: 19, align })
),
});
}
function sectionHeading(text) {
return new Paragraph({
spacing: { before: 300, after: 120 },
children: [
new TextRun({
text,
bold: true,
size: 26,
color: COLORS.headerBg,
font: "Calibri",
}),
],
border: {
bottom: { color: COLORS.borderColor, space: 1, style: BorderStyle.SINGLE, size: 6 },
},
});
}
function bodyPara(text, options = {}) {
const { bold = false, size = 20, spacing = { before: 80, after: 80 }, color = "000000" } = options;
return new Paragraph({
spacing,
children: [new TextRun({ text, bold, size, font: "Calibri", color })],
});
}
function alertBox(text) {
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
shading: { type: ShadingType.CLEAR, fill: COLORS.alertBg },
borders: {
top: { style: BorderStyle.SINGLE, size: 12, color: COLORS.alertBorder },
bottom: { style: BorderStyle.SINGLE, size: 12, color: COLORS.alertBorder },
left: { style: BorderStyle.THICK, size: 24, color: COLORS.alertBorder },
right: { style: BorderStyle.SINGLE, size: 12, color: COLORS.alertBorder },
},
margins: { top: 140, bottom: 140, left: 180, right: 180 },
children: [
new Paragraph({
children: [new TextRun({ text, bold: true, size: 20, font: "Calibri", color: "7d4e00" })],
}),
],
}),
],
}),
],
});
}
// ─── DOCUMENT ────────────────────────────────────────────────────────────────
const doc = new Document({
sections: [
{
properties: {
page: { margin: { top: 900, bottom: 900, left: 1080, right: 1080 } },
},
headers: {
default: new Header({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: "ECG ANALYSIS REPORT | CONFIDENTIAL MEDICAL DOCUMENT", bold: true, size: 18, color: "888888", font: "Calibri" }),
],
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: "Page ", size: 18, font: "Calibri", color: "888888" }),
new PageNumber({ type: NumberFormat.DECIMAL }),
new TextRun({ text: " | This report is for clinical reference only. Formal cardiologist review is mandatory.", size: 18, font: "Calibri", color: "888888" }),
],
}),
],
}),
},
children: [
// ── TITLE BLOCK ──────────────────────────────────────────────────────
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
shading: { type: ShadingType.CLEAR, fill: COLORS.headerBg },
margins: { top: 240, bottom: 240, left: 360, right: 360 },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "12-LEAD ECG ANALYSIS REPORT", bold: true, size: 40, color: "FFFFFF", font: "Calibri" })],
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "AI-Assisted Electrocardiographic Interpretation", size: 22, color: "aad4f5", font: "Calibri" })],
}),
],
}),
],
}),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── PATIENT & STUDY INFO ─────────────────────────────────────────────
sectionHeading("Patient & Study Information"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
dataRow([
{ text: "Patient Name", bold: true, bg: COLORS.sectionBg },
{ text: "Goutam (Gilvar)" },
{ text: "Report Date", bold: true, bg: COLORS.sectionBg },
{ text: "June 12, 2026" },
]),
dataRow([
{ text: "ECG Type", bold: true, bg: COLORS.sectionBg },
{ text: "Standard 12-Lead ECG" },
{ text: "Analysed By", bold: true, bg: COLORS.sectionBg },
{ text: "Orris AI (Preliminary)" },
]),
dataRow([
{ text: "Institution", bold: true, bg: COLORS.sectionBg },
{ text: "M.R. Hospitals" },
{ text: "Status", bold: true, bg: COLORS.sectionBg },
{ text: "Requires Formal Cardiologist Review" },
]),
],
}),
new Paragraph({ spacing: { after: 160 }, children: [] }),
// ── SYSTEMATIC FINDINGS ──────────────────────────────────────────────
sectionHeading("Systematic ECG Findings"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
headerRow([
{ text: "Parameter", width: 2200 },
{ text: "Finding", width: 3000 },
{ text: "Interpretation", width: 3800 },
{ text: "Status", width: 1400 },
]),
dataRow([
{ text: "Heart Rate", bold: true, bg: COLORS.sectionBg },
{ text: "~90-110 bpm" },
{ text: "Sinus tachycardia (mildly elevated)" },
{ text: "ABNORMAL", bold: true, bg: "fff3e0" },
]),
dataRow([
{ text: "Rhythm", bold: true, bg: COLORS.sectionBg },
{ text: "Regular" },
{ text: "Consistent RR intervals throughout all leads" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "P Waves", bold: true, bg: COLORS.sectionBg },
{ text: "Upright in I and II" },
{ text: "Sinus origin confirmed" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "PR Interval", bold: true, bg: COLORS.sectionBg },
{ text: "Normal (~0.12-0.20 s)" },
{ text: "No AV block detected" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "QRS Duration", bold: true, bg: COLORS.sectionBg },
{ text: "Narrow (<120 ms)" },
{ text: "No bundle branch block" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "QRS Axis", bold: true, bg: COLORS.sectionBg },
{ text: "Normal to left axis" },
{ text: "Within acceptable range" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "QRS Voltage", bold: true, bg: COLORS.sectionBg },
{ text: "Increased - tall R in V4-V6, deep S in V1-V2" },
{ text: "Meets LVH voltage criteria (SV1+RV5/V6 likely >35mm)" },
{ text: "ABNORMAL", bold: true, bg: COLORS.abnormalBg },
]),
dataRow([
{ text: "ST Segments", bold: true, bg: COLORS.sectionBg },
{ text: "ST depression in lateral leads (V5, V6, I, aVL)" },
{ text: "Consistent with LV strain pattern; no acute ST elevation" },
{ text: "ABNORMAL", bold: true, bg: "fff3e0" },
]),
dataRow([
{ text: "T Waves", bold: true, bg: COLORS.sectionBg },
{ text: "Asymmetric changes in lateral leads" },
{ text: "LVH strain morphology (gradual descent, abrupt return)" },
{ text: "ABNORMAL", bold: true, bg: "fff3e0" },
]),
dataRow([
{ text: "Q Waves", bold: true, bg: COLORS.sectionBg },
{ text: "No pathological Q waves seen" },
{ text: "No evidence of old infarction" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
dataRow([
{ text: "QT Interval", bold: true, bg: COLORS.sectionBg },
{ text: "Appears within normal limits" },
{ text: "No QTc prolongation identified" },
{ text: "NORMAL", bold: true, bg: COLORS.normalBg },
]),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── HEART ATTACK ASSESSMENT ──────────────────────────────────────────
sectionHeading("Heart Attack (MI) Assessment"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
headerRow([
{ text: "MI Territory", width: 2200 },
{ text: "Required ECG Findings", width: 4000 },
{ text: "Present on This ECG?", width: 3200 },
]),
dataRow([
{ text: "Anterior STEMI", bold: true, bg: COLORS.sectionBg },
{ text: "ST elevation in V1-V4" },
{ text: "NO - Not seen", bg: COLORS.normalBg },
]),
dataRow([
{ text: "Inferior STEMI", bold: true, bg: COLORS.sectionBg },
{ text: "ST elevation in II, III, aVF" },
{ text: "NO - Not seen", bg: COLORS.normalBg },
]),
dataRow([
{ text: "Lateral STEMI", bold: true, bg: COLORS.sectionBg },
{ text: "ST elevation in I, aVL, V5-V6" },
{ text: "NO - Not seen", bg: COLORS.normalBg },
]),
dataRow([
{ text: "Posterior MI", bold: true, bg: COLORS.sectionBg },
{ text: "Tall R, ST depression in V1-V2" },
{ text: "Not clearly identified", bg: "fff9c4" },
]),
dataRow([
{ text: "Old MI (Healed)", bold: true, bg: COLORS.sectionBg },
{ text: "Pathological Q waves (>40ms, >25% QRS)" },
{ text: "NO - Not seen", bg: COLORS.normalBg },
]),
],
}),
new Paragraph({ spacing: { after: 160 }, children: [] }),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
shading: { type: ShadingType.CLEAR, fill: "e8f5e9" },
borders: {
top: { style: BorderStyle.SINGLE, size: 12, color: "388e3c" },
bottom: { style: BorderStyle.SINGLE, size: 12, color: "388e3c" },
left: { style: BorderStyle.THICK, size: 24, color: "388e3c" },
right: { style: BorderStyle.SINGLE, size: 12, color: "388e3c" },
},
margins: { top: 140, bottom: 140, left: 180, right: 180 },
children: [
new Paragraph({
children: [new TextRun({ text: "CONCLUSION: No ECG evidence of acute ST-Elevation Myocardial Infarction (STEMI) detected on this tracing.", bold: true, size: 22, font: "Calibri", color: "1b5e20" })],
}),
new Paragraph({
spacing: { before: 80 },
children: [new TextRun({ text: "The ST-T changes observed are most consistent with Left Ventricular Hypertrophy (LVH) strain pattern - a secondary effect of pressure-overloaded myocardium, NOT an acute infarction.", size: 20, font: "Calibri", color: "2e7d32" })],
}),
],
}),
],
}),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── PRIMARY DIAGNOSIS ────────────────────────────────────────────────
sectionHeading("Primary ECG Diagnosis"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
headerRow([
{ text: "Finding", width: 3000 },
{ text: "Details", width: 7400 },
]),
dataRow([
{ text: "1. Sinus Tachycardia", bold: true, bg: COLORS.sectionBg },
{ text: "Heart rate 90-110 bpm with regular rhythm and normal P wave morphology. Common causes: fever, pain, anxiety, anaemia, thyrotoxicosis, dehydration." },
]),
dataRow([
{ text: "2. Left Ventricular Hypertrophy (LVH)", bold: true, bg: COLORS.sectionBg },
{ text: "Increased QRS voltage in precordial leads meeting standard voltage criteria (Sokolow-Lyon: SV1 + RV5/V6 >35mm). Most common aetiology: systemic hypertension, aortic stenosis, hypertrophic cardiomyopathy." },
]),
dataRow([
{ text: "3. LV Strain Pattern", bold: true, bg: COLORS.sectionBg },
{ text: "ST depression and asymmetric T-wave changes in lateral leads (I, aVL, V5-V6) - a repolarisation abnormality secondary to LVH. Represents chronic pressure/volume overload rather than acute ischaemia." },
]),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── DIFFERENTIAL DIAGNOSIS ───────────────────────────────────────────
sectionHeading("Differential Diagnosis"),
bodyPara("The following conditions can produce this ECG pattern and should be considered clinically:", { bold: false }),
new Paragraph({ spacing: { after: 60 }, children: [] }),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
headerRow([
{ text: "Diagnosis", width: 3000 },
{ text: "Likelihood", width: 1500 },
{ text: "Supporting Features", width: 5900 },
]),
dataRow([
{ text: "Hypertensive Heart Disease", bold: true, bg: COLORS.sectionBg },
{ text: "HIGH", bold: true, bg: "e3f2fd", align: AlignmentType.CENTER },
{ text: "Most common cause of LVH globally; LV strain pattern typical of longstanding hypertension" },
]),
dataRow([
{ text: "Hypertrophic Cardiomyopathy (HCM)", bold: true, bg: COLORS.sectionBg },
{ text: "MODERATE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Can show high voltage + diffuse ST-T changes; echocardiography required to differentiate" },
]),
dataRow([
{ text: "Aortic Stenosis", bold: true, bg: COLORS.sectionBg },
{ text: "MODERATE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Pressure overload LVH identical on ECG; clinical auscultation and echo needed" },
]),
dataRow([
{ text: "Athletic Heart Syndrome", bold: true, bg: COLORS.sectionBg },
{ text: "LOW-MOD", bold: true, bg: "f3e5f5", align: AlignmentType.CENTER },
{ text: "Physiological LVH with voltage but typically WITHOUT strain pattern; normal resting HR" },
]),
dataRow([
{ text: "NSTEMI / Subendocardial MI", bold: true, bg: COLORS.sectionBg },
{ text: "CANNOT EXCLUDE", bold: true, bg: COLORS.abnormalBg, align: AlignmentType.CENTER },
{ text: "NSTEMI may have non-diagnostic ECG; troponin blood test MANDATORY if symptoms present" },
]),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── RECOMMENDATIONS ──────────────────────────────────────────────────
sectionHeading("Clinical Recommendations"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
headerRow([
{ text: "Priority", width: 1400 },
{ text: "Investigation / Action", width: 3600 },
{ text: "Rationale", width: 5400 },
]),
dataRow([
{ text: "URGENT", bold: true, bg: COLORS.abnormalBg, align: AlignmentType.CENTER },
{ text: "Serial Troponin I/T (0h and 3h)", bold: true },
{ text: "Mandatory if chest pain, dyspnoea or acute symptoms present - to rule out NSTEMI" },
]),
dataRow([
{ text: "URGENT", bold: true, bg: COLORS.abnormalBg, align: AlignmentType.CENTER },
{ text: "Blood Pressure Measurement", bold: true },
{ text: "LVH strongly suggests hypertension; immediate BP check required" },
]),
dataRow([
{ text: "ROUTINE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Echocardiography (2D Echo)", bold: true },
{ text: "Confirm LVH, assess wall motion, valve disease, LVEF, diastolic dysfunction" },
]),
dataRow([
{ text: "ROUTINE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Fasting Lipid Profile & HbA1c", bold: true },
{ text: "Cardiovascular risk stratification" },
]),
dataRow([
{ text: "ROUTINE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Thyroid Function Tests (TSH)", bold: true },
{ text: "Exclude thyrotoxicosis as cause of tachycardia" },
]),
dataRow([
{ text: "ROUTINE", bold: true, bg: "fff9c4", align: AlignmentType.CENTER },
{ text: "Renal Function & Electrolytes", bold: true },
{ text: "Hypertensive nephropathy; electrolyte disturbances affect ECG" },
]),
dataRow([
{ text: "MANDATORY", bold: true, bg: COLORS.sectionBg, align: AlignmentType.CENTER },
{ text: "Formal Cardiologist Review of ECG", bold: true },
{ text: "This is an AI-assisted preliminary interpretation only" },
]),
],
}),
new Paragraph({ spacing: { after: 200 }, children: [] }),
// ── DISCLAIMER ───────────────────────────────────────────────────────
alertBox(
"IMPORTANT DISCLAIMER: This report is an AI-assisted preliminary analysis of a photographed 12-lead ECG. Image angle, paper creases, and photo resolution may limit accuracy. This report does NOT constitute a formal medical opinion and MUST NOT be used as the sole basis for clinical decisions. A qualified cardiologist must formally interpret the original ECG tracing. If the patient is symptomatic (chest pain, breathlessness, syncope, palpitations), seek IMMEDIATE emergency medical care."
),
new Paragraph({ spacing: { after: 120 }, children: [] }),
bodyPara("Reference: Tintinalli's Emergency Medicine 9E; Harrison's Principles of Internal Medicine 22E (2025)", { size: 17, color: "888888" }),
],
},
],
});
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync("/home/daytona/workspace/ecg-report/ECG_Analysis_Report_Goutam.docx", buffer);
console.log("Report generated successfully.");
});
cd /home/daytona/workspace/ecg-report && node generate_report.js
~/ecg-report/generate_report.js
Error: String not found in file: ' headers: {
default: new Header({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: "ECG ANALYSIS REPORT | CONFIDENTIAL MEDICAL DOCUMENT", bold: true, size: 18, color: "888888", font: "Calibri" }),
],
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: "Page ", size: 18, font: "Calibri", color: "888888" }),
new PageNumber({ type: NumberFormat.DECIMAL }),
new TextRun({ text: " | This report is for clinical reference only. Formal cardiologist review is mandatory.", size: 18, font: "Calibri", color: "888888" }),
],
}),
],
}),
},'grep -n "PageNumber\|NumberFormat\|new PageNumber" /home/daytona/workspace/ecg-report/generate_report.js
sed -i 's/PageNumber, NumberFormat//' /home/daytona/workspace/ecg-report/generate_report.js && sed -i '/new PageNumber({ type: NumberFormat.DECIMAL }),/d' /home/daytona/workspace/ecg-report/generate_report.js && sed -i 's/ ShadingType, Header, Footer,/ ShadingType, Header, Footer,/' /home/daytona/workspace/ecg-report/generate_report.js && node /home/daytona/workspace/ecg-report/generate_report.js
~/ecg-report/generate_report.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/ecg-report/generate_report.js'
~/ecg-report/generate_report.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/ecg-report/generate_report.js'
node /home/daytona/workspace/ecg-report/generate_report.js
python3 /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/workspace/ecg-report/ECG_Analysis_Report_Goutam.docx
ls -lh /home/daytona/workspace/ecg-report/ECG_Analysis_Report_Goutam.docx && python3 -c "import zipfile; z=zipfile.ZipFile('/home/daytona/workspace/ecg-report/ECG_Analysis_Report_Goutam.docx'); print('Valid ZIP/DOCX. Files:', z.namelist()[:5])"
ECG Analysis Report Goutam
Word Document · DOCX
| Section | Details |
|---|---|
| Patient & Study Info | Name, date, institution (M.R. Hospitals), report status |
| Systematic ECG Findings | All 11 parameters (rate, rhythm, P waves, PR, QRS, axis, voltage, ST, T waves, Q waves, QT) with colour-coded Normal/Abnormal status |
| Heart Attack Assessment | Territory-by-territory STEMI check (Anterior, Inferior, Lateral, Posterior, Old MI) |
| Primary ECG Diagnosis | Sinus tachycardia + LVH + LV strain pattern |
| Differential Diagnosis | 5 conditions with likelihood ratings |
| Clinical Recommendations | 7 investigations with Urgent/Routine/Mandatory priority labels |
| Disclaimer | Prominent AI-assisted analysis warning |