i want reference article in introduction problem statement and data analysis
cd /home/daytona/workspace/attachments/e30b4f0d-9d1a-4bfe-a230-8156f5ee3526 && p…
grep -n "INTRODUCTION\|PROBLEM STATEMENT\|DATA ANALYSIS\|REVIEW\|METHODOLOGY\|in…
sed -n '435,715p' /home/daytona/workspace/attachments/e30b4f0d-9d1a-4bfe-a230-81…
sed -n '1178,1400p' /home/daytona/workspace/attachments/e30b4f0d-9d1a-4bfe-a230-…
metatarsalgia forefoot pain conservative treatment
ultrasound therapy metatarsalgia foot pain
metatarsalgia orthotic insole plantar pressure
ice therapy cryotherapy musculoskeletal pain inflammation
stretching exercises plantar fascia flexibility foot pain
prolonged standing occupational musculoskeletal disorder teachers foot
plantar fasciitis stretching calf muscle gastrocnemius exercise
prolonged standing occupational lower extremity pain prevalence
VAS FFI foot function index pain outcome measure validity
Cite here: "Metatarsalgia is not considered a disease itself but rather a clinical symptom..." and the prevalence statement (up to 31%).
Cite here: "Biomechanical factors explain 90% of all cases of metatarsalgia."
Cite here: description of pathophysiology, plantar pressure distribution, and forefoot pain.
Cite here: conservative physiotherapy options for metatarsalgia.
Cite here: "Occupational exposure to continuous standing is a major risk factor for developing forefoot pain."
Cite here: occupational standing leading to foot disorders (nurse population is analogous to teachers).
Cite here: "Orthotic support...helps in redistributing plantar pressure, reducing stress over the metatarsal heads."
Classic RCT; cite for orthotic mechanism of action.
Cite here: "Stretching exercises mainly focus on improving flexibility of the plantar fascia, gastrocnemius, soleus..."
Cite here: stretching improving functional mobility in foot conditions.
Cite here: reduced flexibility of calf muscles contributing to forefoot biomechanical problems.
Cite here: "Ice therapy is believed to control pain by inducing local analgesia through vasoconstriction, reduction of nerve conduction velocity..."
Cite here: effectiveness of cryotherapy depending on method, duration, and depth.
Cite here: orthotic metatarsal pad reducing pressure over metatarsal heads.
Cite here: pressure redistribution from orthotic use.
Cite here: validity and use of VAS and FFI as outcome measures in foot research.
Cite here: FFI as a validated tool for measuring functional ability in foot disorders.
data analysis in mean value, standed devision
Create an Excel sheet to organize and calculate all statistics and 2
ls /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/meta…
~/metatarsalgia-stats/build_stats.py
import openpyxl
from openpyxl.styles import (
Font, PatternFill, Alignment, Border, Side, numbers
)
from openpyxl.utils import get_column_letter
from openpyxl.chart import BarChart, Reference
from openpyxl.chart.series import DataPoint
import math
wb = openpyxl.Workbook()
# ── colour palette ──────────────────────────────────────────────────────────
BLUE_FILL = PatternFill("solid", fgColor="1F4E79")
LBLUE_FILL = PatternFill("solid", fgColor="BDD7EE")
GREEN_FILL = PatternFill("solid", fgColor="375623")
LGREEN_FILL = PatternFill("solid", fgColor="E2EFDA")
GREY_FILL = PatternFill("solid", fgColor="D9D9D9")
YELLOW_FILL = PatternFill("solid", fgColor="FFFF00")
WHITE_FILL = PatternFill("solid", fgColor="FFFFFF")
ORANGE_FILL = PatternFill("solid", fgColor="FCE4D6")
def thin_border():
s = Side(style="thin")
return Border(left=s, right=s, top=s, bottom=s)
def header_font(white=True, sz=11, bold=True):
color = "FFFFFF" if white else "000000"
return Font(name="Arial", size=sz, bold=bold, color=color)
def cell_font(sz=10, bold=False, color="000000"):
return Font(name="Arial", size=sz, bold=bold, color=color)
def set_cell(ws, row, col, value, fill=None, font=None, align=None, num_format=None, border=True):
c = ws.cell(row=row, column=col, value=value)
if fill: c.fill = fill
if font: c.font = font
if align: c.alignment = align
else: c.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
if num_format: c.number_format = num_format
if border: c.border = thin_border()
return c
CENTER = Alignment(horizontal="center", vertical="center", wrap_text=True)
LEFT = Alignment(horizontal="left", vertical="center", wrap_text=True)
# ============================================================
# SHEET 1 – DATA ENTRY
# ============================================================
ws1 = wb.active
ws1.title = "Data Entry"
ws1.column_dimensions["A"].width = 12
ws1.column_dimensions["B"].width = 14
ws1.column_dimensions["C"].width = 14
ws1.column_dimensions["D"].width = 14
ws1.column_dimensions["E"].width = 14
ws1.column_dimensions["F"].width = 3
ws1.column_dimensions["G"].width = 12
ws1.column_dimensions["H"].width = 14
ws1.column_dimensions["I"].width = 14
ws1.column_dimensions["J"].width = 14
ws1.column_dimensions["K"].width = 14
ws1.row_dimensions[1].height = 40
ws1.row_dimensions[2].height = 20
ws1.row_dimensions[3].height = 30
# Title
ws1.merge_cells("A1:K1")
set_cell(ws1, 1, 1,
"METATARSALGIA STUDY — RAW DATA ENTRY (VAS & FFI)\n"
"Group A = Ultrasound Therapy + Stretching + Orthotic | Group B = Ice Therapy + Stretching + Orthotic",
fill=BLUE_FILL, font=header_font(white=True, sz=12),
align=CENTER)
# Instruction row
ws1.merge_cells("A2:K2")
set_cell(ws1, 2, 1,
"⚠ Enter subject scores in the BLUE cells below. All statistics update automatically.",
fill=YELLOW_FILL, font=cell_font(sz=10, bold=True, color="000000"),
align=LEFT)
# ── Column headers row 3 ──
grp_headers = [
("GROUP A", 1, 5, BLUE_FILL),
("GROUP B", 7, 11, GREEN_FILL),
]
for title, c1, c2, fill in grp_headers:
ws1.merge_cells(start_row=3, start_column=c1, end_row=3, end_column=c2)
set_cell(ws1, 3, c1, title, fill=fill,
font=header_font(white=True, sz=11))
sub_headers_A = ["Subject No.", "VAS Pre", "VAS Post", "FFI Pre", "FFI Post"]
sub_headers_B = ["Subject No.", "VAS Pre", "VAS Post", "FFI Pre", "FFI Post"]
ws1.row_dimensions[4].height = 22
for i, h in enumerate(sub_headers_A, start=1):
set_cell(ws1, 4, i, h, fill=LBLUE_FILL, font=cell_font(bold=True))
for i, h in enumerate(sub_headers_B, start=7):
set_cell(ws1, 4, i, h, fill=LGREEN_FILL, font=cell_font(bold=True))
# ── 30 data rows per group (n=30 each, total 60) ──
INPUT_BLUE = PatternFill("solid", fgColor="DEEAF1")
INPUT_GRN = PatternFill("solid", fgColor="E2EFDA")
for r in range(5, 35): # rows 5–34 = subjects 1–30
s_num = r - 4
ws1.row_dimensions[r].height = 16
# Group A
set_cell(ws1, r, 1, s_num, fill=GREY_FILL, font=cell_font())
for c in range(2, 6):
set_cell(ws1, r, c, None, fill=INPUT_BLUE, font=cell_font(color="0000FF"))
# spacer col F — no border
ws1.cell(row=r, column=6).border = Border()
# Group B
set_cell(ws1, r, 7, s_num, fill=GREY_FILL, font=cell_font())
for c in range(8, 12):
set_cell(ws1, r, c, None, fill=INPUT_GRN, font=cell_font(color="006400"))
# note row
ws1.row_dimensions[35].height = 16
ws1.merge_cells("A35:K35")
set_cell(ws1, 35, 1,
"Note: VAS = Visual Analogue Scale (0–10) | FFI = Foot Function Index (0–100)",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
# ============================================================
# SHEET 2 – SUMMARY STATISTICS (auto-calculated)
# ============================================================
ws2 = wb.create_sheet("Summary Statistics")
for col, w in zip("ABCDEFGH", [22, 14, 14, 14, 14, 14, 14, 14]):
ws2.column_dimensions[col].width = w
ws2.row_dimensions[1].height = 40
ws2.merge_cells("A1:H1")
set_cell(ws2, 1, 1,
"SUMMARY STATISTICS — AUTO-CALCULATED FROM DATA ENTRY SHEET",
fill=BLUE_FILL, font=header_font(white=True, sz=12), align=CENTER)
# Helper: write a stat block
def stat_block(ws, start_row, group_label, fill_hdr, fill_data,
vas_pre_col, vas_post_col, ffi_pre_col, ffi_post_col,
n=30):
"""
vas_pre_col etc. are column letters in 'Data Entry' (e.g. 'B', 'C', 'D', 'E')
n = number of subjects (rows 5 to 5+n-1)
"""
data_range = f"'Data Entry'!{vas_pre_col}5:{vas_pre_col}{4+n}"
r = start_row
# Block title
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=8)
set_cell(ws, r, 1, group_label, fill=fill_hdr,
font=header_font(white=True, sz=11), align=CENTER)
r += 1
# Sub-header
hdrs = ["Measure", "Pre-test Mean", "Pre-test SD",
"Post-test Mean", "Post-test SD",
"Mean Diff (Pre–Post)", "SD of Diff", ""]
for ci, h in enumerate(hdrs, 1):
set_cell(ws, r, ci, h, fill=GREY_FILL, font=cell_font(bold=True))
r += 1
# VAS and FFI rows
measures = [
("VAS (0–10)", vas_pre_col, vas_post_col),
("FFI (0–100)", ffi_pre_col, ffi_post_col),
]
for label, pre_col, post_col in measures:
pre_range = f"'Data Entry'!{pre_col}5:{pre_col}{4+n}"
post_range = f"'Data Entry'!{post_col}5:{post_col}{4+n}"
set_cell(ws, r, 1, label, fill=fill_data, font=cell_font(bold=True), align=LEFT)
# Pre Mean
ws.cell(row=r, column=2).value = f"=IFERROR(AVERAGE({pre_range}),\"\")"
ws.cell(row=r, column=2).number_format = "0.00"
ws.cell(row=r, column=2).fill = fill_data
ws.cell(row=r, column=2).font = cell_font()
ws.cell(row=r, column=2).border = thin_border()
ws.cell(row=r, column=2).alignment = CENTER
# Pre SD
ws.cell(row=r, column=3).value = f"=IFERROR(STDEV({pre_range}),\"\")"
ws.cell(row=r, column=3).number_format = "0.00"
ws.cell(row=r, column=3).fill = fill_data
ws.cell(row=r, column=3).font = cell_font()
ws.cell(row=r, column=3).border = thin_border()
ws.cell(row=r, column=3).alignment = CENTER
# Post Mean
ws.cell(row=r, column=4).value = f"=IFERROR(AVERAGE({post_range}),\"\")"
ws.cell(row=r, column=4).number_format = "0.00"
ws.cell(row=r, column=4).fill = fill_data
ws.cell(row=r, column=4).font = cell_font()
ws.cell(row=r, column=4).border = thin_border()
ws.cell(row=r, column=4).alignment = CENTER
# Post SD
ws.cell(row=r, column=5).value = f"=IFERROR(STDEV({post_range}),\"\")"
ws.cell(row=r, column=5).number_format = "0.00"
ws.cell(row=r, column=5).fill = fill_data
ws.cell(row=r, column=5).font = cell_font()
ws.cell(row=r, column=5).border = thin_border()
ws.cell(row=r, column=5).alignment = CENTER
# Mean Difference (Pre - Post)
ws.cell(row=r, column=6).value = (
f"=IFERROR(AVERAGE({pre_range})-AVERAGE({post_range}),\"\")"
)
ws.cell(row=r, column=6).number_format = "0.00"
ws.cell(row=r, column=6).fill = fill_data
ws.cell(row=r, column=6).font = cell_font()
ws.cell(row=r, column=6).border = thin_border()
ws.cell(row=r, column=6).alignment = CENTER
# SD of individual differences (STDEV of pre-post for each subject)
diff_formula = (
f"=IFERROR(STDEV(IF(ISNUMBER({pre_range})*ISNUMBER({post_range}),"
f"{pre_range}-{post_range})),\"\")"
)
ws.cell(row=r, column=7).value = diff_formula
ws.cell(row=r, column=7).number_format = "0.00"
ws.cell(row=r, column=7).fill = fill_data
ws.cell(row=r, column=7).font = cell_font()
ws.cell(row=r, column=7).border = thin_border()
ws.cell(row=r, column=7).alignment = CENTER
ws.cell(row=r, column=7).data_type = 'f'
set_cell(ws, r, 8, "", fill=WHITE_FILL)
r += 1
return r + 1 # blank row after block
next_row = stat_block(ws2, 2,
"GROUP A — Ultrasound Therapy + Stretching + Orthotic (n=30)",
BLUE_FILL, LBLUE_FILL,
"B", "C", "D", "E", n=30)
next_row = stat_block(ws2, next_row,
"GROUP B — Ice Therapy + Stretching + Orthotic (n=30)",
GREEN_FILL, LGREEN_FILL,
"H", "I", "J", "K", n=30)
# ============================================================
# SHEET 3 – PAIRED t-TEST (within groups)
# ============================================================
ws3 = wb.create_sheet("Paired t-Test")
for col, w in zip("ABCDEFGHI", [24, 14, 14, 14, 14, 14, 16, 16, 20]):
ws3.column_dimensions[col].width = w
ws3.row_dimensions[1].height = 40
ws3.merge_cells("A1:I1")
set_cell(ws3, 1, 1,
"PAIRED t-TEST — WITHIN GROUP COMPARISON (Pre-test vs Post-test)",
fill=BLUE_FILL, font=header_font(white=True, sz=12), align=CENTER)
ws3.merge_cells("A2:I2")
set_cell(ws3, 2, 1,
"Formula: t = d̄ / (SD_diff / √n) where d̄ = mean of (Pre – Post) differences",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
def paired_block(ws, start_row, group_label, fill_hdr, fill_data,
pre_col_vas, post_col_vas, pre_col_ffi, post_col_ffi, n=30):
r = start_row
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=9)
set_cell(ws, r, 1, group_label, fill=fill_hdr,
font=header_font(white=True, sz=11), align=CENTER)
r += 1
hdrs = ["Measure", "n", "Pre Mean (d̄₁)", "Post Mean (d̄₂)",
"Mean Diff (d̄)", "SD of Diff", "Paired t-value", "P-value (2-tail)", "Significance"]
for ci, h in enumerate(hdrs, 1):
set_cell(ws, r, ci, h, fill=GREY_FILL, font=cell_font(bold=True))
r += 1
measures = [
("VAS (0–10)", pre_col_vas, post_col_vas),
("FFI (0–100)", pre_col_ffi, post_col_ffi),
]
for label, pre_col, post_col in measures:
pre_range = f"'Data Entry'!{pre_col}5:{pre_col}{4+n}"
post_range = f"'Data Entry'!{post_col}5:{post_col}{4+n}"
set_cell(ws, r, 1, label, fill=fill_data, font=cell_font(bold=True), align=LEFT)
# n
ws.cell(row=r, column=2).value = f"=IFERROR(COUNT({pre_range}),\"\")"
ws.cell(row=r, column=2).fill = fill_data; ws.cell(row=r, column=2).font = cell_font()
ws.cell(row=r, column=2).border = thin_border(); ws.cell(row=r, column=2).alignment = CENTER
# Pre Mean
ws.cell(row=r, column=3).value = f"=IFERROR(AVERAGE({pre_range}),\"\")"
ws.cell(row=r, column=3).number_format = "0.00"
ws.cell(row=r, column=3).fill = fill_data; ws.cell(row=r, column=3).font = cell_font()
ws.cell(row=r, column=3).border = thin_border(); ws.cell(row=r, column=3).alignment = CENTER
# Post Mean
ws.cell(row=r, column=4).value = f"=IFERROR(AVERAGE({post_range}),\"\")"
ws.cell(row=r, column=4).number_format = "0.00"
ws.cell(row=r, column=4).fill = fill_data; ws.cell(row=r, column=4).font = cell_font()
ws.cell(row=r, column=4).border = thin_border(); ws.cell(row=r, column=4).alignment = CENTER
# Mean Diff
ws.cell(row=r, column=5).value = (
f"=IFERROR(AVERAGE({pre_range})-AVERAGE({post_range}),\"\")"
)
ws.cell(row=r, column=5).number_format = "0.00"
ws.cell(row=r, column=5).fill = fill_data; ws.cell(row=r, column=5).font = cell_font()
ws.cell(row=r, column=5).border = thin_border(); ws.cell(row=r, column=5).alignment = CENTER
# SD of differences — using Excel array via helper columns
# We use T.TEST directly for p-value, and derive t from it
# P-value via T.TEST (paired, two-tailed)
p_formula = f"=IFERROR(T.TEST({pre_range},{post_range},2,1),\"\")"
# SD diff
# For paired t, SD_diff = STDEV of (pre_i - post_i)
# We'll approximate via: if arrays available
sd_formula = (
f"=IFERROR(SQRT(SUMPRODUCT(({pre_range}-{post_range}"
f"-AVERAGE({pre_range}-{post_range}))^2)/(COUNT({pre_range})-1)),\"\")"
)
ws.cell(row=r, column=6).value = sd_formula
ws.cell(row=r, column=6).number_format = "0.00"
ws.cell(row=r, column=6).fill = fill_data; ws.cell(row=r, column=6).font = cell_font()
ws.cell(row=r, column=6).border = thin_border(); ws.cell(row=r, column=6).alignment = CENTER
# Paired t-value = d_bar / (SD_diff / sqrt(n))
t_formula = (
f"=IFERROR((AVERAGE({pre_range})-AVERAGE({post_range}))"
f"/(SQRT(SUMPRODUCT(({pre_range}-{post_range}"
f"-AVERAGE({pre_range}-{post_range}))^2)/(COUNT({pre_range})-1))"
f"/SQRT(COUNT({pre_range}))),\"\")"
)
ws.cell(row=r, column=7).value = t_formula
ws.cell(row=r, column=7).number_format = "0.000"
ws.cell(row=r, column=7).fill = fill_data; ws.cell(row=r, column=7).font = cell_font(bold=True)
ws.cell(row=r, column=7).border = thin_border(); ws.cell(row=r, column=7).alignment = CENTER
# P-value
ws.cell(row=r, column=8).value = p_formula
ws.cell(row=r, column=8).number_format = "0.0000"
ws.cell(row=r, column=8).fill = fill_data; ws.cell(row=r, column=8).font = cell_font(bold=True)
ws.cell(row=r, column=8).border = thin_border(); ws.cell(row=r, column=8).alignment = CENTER
# Significance
sig_formula = (
f"=IFERROR(IF({ws.cell(row=r, column=8).column_letter}{r}<0.001,\"p<0.001 ***\","
f"IF({ws.cell(row=r, column=8).column_letter}{r}<0.01,\"p<0.01 **\","
f"IF({ws.cell(row=r, column=8).column_letter}{r}<0.05,\"p<0.05 *\","
f"\"Not Significant\"))),\"\")"
)
# simpler: reference by column number
p_cell = f"{get_column_letter(8)}{r}"
sig_formula = (
f'=IFERROR(IF({p_cell}<0.001,"p<0.001 ***",'
f'IF({p_cell}<0.01,"p<0.01 **",'
f'IF({p_cell}<0.05,"p<0.05 *","Not Significant"))),"--")'
)
ws.cell(row=r, column=9).value = sig_formula
ws.cell(row=r, column=9).fill = fill_data; ws.cell(row=r, column=9).font = cell_font(bold=True, color="1F4E79")
ws.cell(row=r, column=9).border = thin_border(); ws.cell(row=r, column=9).alignment = CENTER
r += 1
return r + 1
next_row = paired_block(ws3, 3,
"GROUP A — Ultrasound Therapy + Stretching + Orthotic (n=30)",
BLUE_FILL, LBLUE_FILL, "B", "C", "D", "E", n=30)
next_row = paired_block(ws3, next_row,
"GROUP B — Ice Therapy + Stretching + Orthotic (n=30)",
GREEN_FILL, LGREEN_FILL, "H", "I", "J", "K", n=30)
# interpretation note
ws3.row_dimensions[next_row].height = 30
ws3.merge_cells(start_row=next_row, start_column=1, end_row=next_row, end_column=9)
set_cell(ws3, next_row, 1,
"Significance levels: *** p<0.001 ** p<0.01 * p<0.05 (two-tailed paired t-test, df = n–1 = 29)",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
# ============================================================
# SHEET 4 – UNPAIRED t-TEST (between groups)
# ============================================================
ws4 = wb.create_sheet("Unpaired t-Test")
for col, w in zip("ABCDEFGHIJ", [24, 14, 14, 14, 14, 14, 16, 16, 14, 20]):
ws4.column_dimensions[col].width = w
ws4.row_dimensions[1].height = 40
ws4.merge_cells("A1:J1")
set_cell(ws4, 1, 1,
"UNPAIRED (INDEPENDENT) t-TEST — BETWEEN GROUP COMPARISON (Group A vs Group B Post-test)",
fill=BLUE_FILL, font=header_font(white=True, sz=12), align=CENTER)
ws4.merge_cells("A2:J2")
set_cell(ws4, 2, 1,
"Formula: t = (d̄₁ − d̄₂) / [ S_pooled × √(1/n₁ + 1/n₂) ] where d̄ = mean difference (pre−post) per group",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
# Headers
hdrs4 = ["Measure",
"Grp A Mean Diff", "Grp A SD",
"Grp B Mean Diff", "Grp B SD",
"Pooled SD", "Unpaired t-value", "P-value (2-tail)", "df", "Significance"]
ws4.row_dimensions[3].height = 22
for ci, h in enumerate(hdrs4, 1):
set_cell(ws4, 3, ci, h, fill=GREY_FILL, font=cell_font(bold=True))
n = 30
measures_u = [
("VAS (0–10)", "B", "C", "H", "I"),
("FFI (0–100)", "D", "E", "J", "K"),
]
for ri, (label, a_pre, a_post, b_pre, b_post) in enumerate(measures_u, start=4):
ws4.row_dimensions[ri].height = 20
ra_pre = f"'Data Entry'!{a_pre}5:{a_pre}{4+n}"
ra_post = f"'Data Entry'!{a_post}5:{a_post}{4+n}"
rb_pre = f"'Data Entry'!{b_pre}5:{b_pre}{4+n}"
rb_post = f"'Data Entry'!{b_post}5:{b_post}{4+n}"
fill = LBLUE_FILL if ri % 2 == 0 else LGREEN_FILL
set_cell(ws4, ri, 1, label, fill=fill, font=cell_font(bold=True), align=LEFT)
# Group A mean diff
ws4.cell(row=ri, column=2).value = f"=IFERROR(AVERAGE({ra_pre})-AVERAGE({ra_post}),\"\")"
ws4.cell(row=ri, column=2).number_format = "0.00"
ws4.cell(row=ri, column=2).fill = fill; ws4.cell(row=ri, column=2).font = cell_font()
ws4.cell(row=ri, column=2).border = thin_border(); ws4.cell(row=ri, column=2).alignment = CENTER
# Group A SD of diff
ws4.cell(row=ri, column=3).value = (
f"=IFERROR(SQRT(SUMPRODUCT(({ra_pre}-{ra_post}"
f"-AVERAGE({ra_pre}-{ra_post}))^2)/({n}-1)),\"\")"
)
ws4.cell(row=ri, column=3).number_format = "0.00"
ws4.cell(row=ri, column=3).fill = fill; ws4.cell(row=ri, column=3).font = cell_font()
ws4.cell(row=ri, column=3).border = thin_border(); ws4.cell(row=ri, column=3).alignment = CENTER
# Group B mean diff
ws4.cell(row=ri, column=4).value = f"=IFERROR(AVERAGE({rb_pre})-AVERAGE({rb_post}),\"\")"
ws4.cell(row=ri, column=4).number_format = "0.00"
ws4.cell(row=ri, column=4).fill = fill; ws4.cell(row=ri, column=4).font = cell_font()
ws4.cell(row=ri, column=4).border = thin_border(); ws4.cell(row=ri, column=4).alignment = CENTER
# Group B SD of diff
ws4.cell(row=ri, column=5).value = (
f"=IFERROR(SQRT(SUMPRODUCT(({rb_pre}-{rb_post}"
f"-AVERAGE({rb_pre}-{rb_post}))^2)/({n}-1)),\"\")"
)
ws4.cell(row=ri, column=5).number_format = "0.00"
ws4.cell(row=ri, column=5).fill = fill; ws4.cell(row=ri, column=5).font = cell_font()
ws4.cell(row=ri, column=5).border = thin_border(); ws4.cell(row=ri, column=5).alignment = CENTER
# Pooled SD = sqrt[ ((n1-1)*s1^2 + (n2-1)*s2^2) / (n1+n2-2) ]
c3 = get_column_letter(3); c5 = get_column_letter(5)
pooled_formula = (
f"=IFERROR(SQRT((({n}-1)*{c3}{ri}^2+({n}-1)*{c5}{ri}^2)/({n}+{n}-2)),\"\")"
)
ws4.cell(row=ri, column=6).value = pooled_formula
ws4.cell(row=ri, column=6).number_format = "0.00"
ws4.cell(row=ri, column=6).fill = fill; ws4.cell(row=ri, column=6).font = cell_font()
ws4.cell(row=ri, column=6).border = thin_border(); ws4.cell(row=ri, column=6).alignment = CENTER
# Unpaired t = (d1_bar - d2_bar) / (S_pooled * sqrt(1/n1 + 1/n2))
c2 = get_column_letter(2); c4 = get_column_letter(4); c6 = get_column_letter(6)
t_formula = (
f"=IFERROR(({c2}{ri}-{c4}{ri})/({c6}{ri}*SQRT(1/{n}+1/{n})),\"\")"
)
ws4.cell(row=ri, column=7).value = t_formula
ws4.cell(row=ri, column=7).number_format = "0.000"
ws4.cell(row=ri, column=7).fill = fill; ws4.cell(row=ri, column=7).font = cell_font(bold=True)
ws4.cell(row=ri, column=7).border = thin_border(); ws4.cell(row=ri, column=7).alignment = CENTER
# P-value using T.TEST on post-test scores between groups
# T.TEST(array1, array2, tails, type) type=2 = two-sample equal variance
p_formula = f"=IFERROR(T.TEST({ra_post},{rb_post},2,2),\"\")"
ws4.cell(row=ri, column=8).value = p_formula
ws4.cell(row=ri, column=8).number_format = "0.0000"
ws4.cell(row=ri, column=8).fill = fill; ws4.cell(row=ri, column=8).font = cell_font(bold=True)
ws4.cell(row=ri, column=8).border = thin_border(); ws4.cell(row=ri, column=8).alignment = CENTER
# df = n1 + n2 - 2
ws4.cell(row=ri, column=9).value = n + n - 2
ws4.cell(row=ri, column=9).fill = fill; ws4.cell(row=ri, column=9).font = cell_font()
ws4.cell(row=ri, column=9).border = thin_border(); ws4.cell(row=ri, column=9).alignment = CENTER
# Significance
p_cell = f"{get_column_letter(8)}{ri}"
sig_formula = (
f'=IFERROR(IF({p_cell}<0.001,"p<0.001 ***",'
f'IF({p_cell}<0.01,"p<0.01 **",'
f'IF({p_cell}<0.05,"p<0.05 *","Not Significant"))),"--")'
)
ws4.cell(row=ri, column=10).value = sig_formula
ws4.cell(row=ri, column=10).fill = fill; ws4.cell(row=ri, column=10).font = cell_font(bold=True, color="1F4E79")
ws4.cell(row=ri, column=10).border = thin_border(); ws4.cell(row=ri, column=10).alignment = CENTER
# note
ws4.row_dimensions[6].height = 30
ws4.merge_cells("A6:J6")
set_cell(ws4, 6, 1,
"Note: P-value for unpaired t-test is calculated using T.TEST on post-test scores (Group A vs Group B). df = 58.",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
ws4.row_dimensions[7].height = 24
ws4.merge_cells("A7:J7")
set_cell(ws4, 7, 1,
"Significance levels: *** p<0.001 ** p<0.01 * p<0.05 (two-tailed unpaired t-test)",
fill=GREY_FILL, font=cell_font(sz=9, color="595959"), align=LEFT)
# ============================================================
# SHEET 5 – PROJECT TABLES (formatted exactly as in project)
# ============================================================
ws5 = wb.create_sheet("Project Tables (Fill In)")
for col, w in zip("ABCDEFG", [20, 16, 16, 14, 12, 16, 5]):
ws5.column_dimensions[col].width = w
ws5.row_dimensions[1].height = 40
ws5.merge_cells("A1:F1")
set_cell(ws5, 1, 1,
"PROJECT TABLES 3–8 — Copy values from Summary Statistics & t-Test sheets into your project",
fill=BLUE_FILL, font=header_font(white=True, sz=12), align=CENTER)
def project_table(ws, start_row, title, group_a_b_label=None):
r = start_row
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=6)
set_cell(ws, r, 1, title, fill=BLUE_FILL,
font=header_font(white=True, sz=11), align=LEFT)
r += 1
hdrs = ["Measurement", "Mean", "Standard Deviation", "Paired/Unpaired t' value", "P value", "Mean Difference"]
for ci, h in enumerate(hdrs, 1):
set_cell(ws, r, ci, h, fill=GREY_FILL, font=cell_font(bold=True))
r += 1
rows = ["Pre-test", "Post-test"] if group_a_b_label is None else ["Group A", "Group B"]
for label in rows:
set_cell(ws, r, 1, label, fill=LBLUE_FILL if label in ("Pre-test","Group A") else LGREEN_FILL,
font=cell_font(bold=True))
for ci in range(2, 7):
set_cell(ws, r, ci, "", fill=YELLOW_FILL, font=cell_font(color="0000FF"))
r += 1
ws.row_dimensions[r].height = 10
r += 1
return r
r = 3
r = project_table(ws5, r, "TABLE 3: Pre & Post VAS — Group A (Ultrasound Therapy)")
r = project_table(ws5, r, "TABLE 4: Pre & Post FFI — Group A (Ultrasound Therapy)")
r = project_table(ws5, r, "TABLE 5: Pre & Post VAS — Group B (Ice Therapy)")
r = project_table(ws5, r, "TABLE 6: Pre & Post FFI — Group B (Ice Therapy)")
r = project_table(ws5, r, "TABLE 7: Independent t-value — VAS (Group A vs Group B)", "between")
r = project_table(ws5, r, "TABLE 8: Independent t-value — FFI (Group A vs Group B)", "between")
ws5.merge_cells(start_row=r, start_column=1, end_row=r, end_column=6)
set_cell(ws5, r, 1,
"⚠ Yellow cells = fill in values from 'Summary Statistics' and 't-Test' sheets, or paste calculated results.",
fill=YELLOW_FILL, font=cell_font(sz=10, bold=True, color="000000"), align=LEFT)
# ============================================================
# SHEET 6 – CHARTS
# ============================================================
ws6 = wb.create_sheet("Charts Guide")
ws6.merge_cells("A1:H1")
set_cell(ws6, 1, 1,
"CHARTS — Once you enter data, insert bar charts comparing Pre vs Post for VAS and FFI in both groups",
fill=BLUE_FILL, font=header_font(white=True, sz=12), align=CENTER)
guide_rows = [
("Chart 1", "Group A VAS: Pre vs Post mean scores — Bar chart to show pain reduction after Ultrasound Therapy"),
("Chart 2", "Group B VAS: Pre vs Post mean scores — Bar chart to show pain reduction after Ice Therapy"),
("Chart 3", "Group A FFI: Pre vs Post mean scores — Bar chart to show functional improvement after Ultrasound Therapy"),
("Chart 4", "Group B FFI: Pre vs Post mean scores — Bar chart to show functional improvement after Ice Therapy"),
("Chart 5", "Comparison: Post-test VAS Mean — Group A vs Group B (Unpaired t-test visual)"),
("Chart 6", "Comparison: Post-test FFI Mean — Group A vs Group B (Unpaired t-test visual)"),
]
ws6.row_dimensions[2].height = 22
for ci, h in enumerate(["Chart", "Description"], 1):
set_cell(ws6, 2, ci, h, fill=GREY_FILL, font=cell_font(bold=True))
for ri, (chart, desc) in enumerate(guide_rows, start=3):
ws6.row_dimensions[ri].height = 22
set_cell(ws6, ri, 1, chart, fill=LBLUE_FILL, font=cell_font(bold=True))
c = ws6.cell(row=ri, column=2, value=desc)
c.fill = WHITE_FILL; c.font = cell_font()
c.border = thin_border(); c.alignment = LEFT
# ── Save ────────────────────────────────────────────────────────────────────
out_path = "/home/daytona/workspace/metatarsalgia-stats/Metatarsalgia_Stats_Calculator.xlsx"
wb.save(out_path)
print(f"Saved: {out_path}")
cd /home/daytona/workspace/metatarsalgia-stats && python build_stats.py 2>&1
python3 -c " import openpyxl, os, tempfile wb = openpyxl.Workbook() ws = wb.acti…
ls -la /home/daytona/workspace/metatarsalgia-stats/ && echo "---" && ls -la /hom…
# Try using xlsxwriter instead python3 -c " import xlsxwriter, os wb = xlsxwrite…
# Try saving to BytesIO first, then write raw bytes python3 -c " import openpyxl…
~/metatarsalgia-stats/build_stats.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/metatarsalgia-stats/build_stats.py'
cd /home/daytona/workspace/metatarsalgia-stats && python3 build_stats.py 2>&1
ls -lh /home/daytona/workspace/metatarsalgia-stats/Metatarsalgia_Stats_Calculato…
Metatarsalgia Stats Calculator
Spreadsheet · XLSX
Do you have sample data I can fill in to show how the calculator works?
~/metatarsalgia-stats/fill_sample_data.py
"""
Fills the Metatarsalgia Stats Calculator with realistic sample data.
Clinical assumptions (based on typical metatarsalgia RCT findings):
Group A (Ultrasound): greater pain reduction and functional improvement
VAS Pre ~ 7.0 ± 0.8 VAS Post ~ 2.8 ± 0.7 (bigger reduction)
FFI Pre ~ 68 ± 8 FFI Post ~ 28 ± 7
Group B (Ice Therapy): moderate improvement
VAS Pre ~ 6.8 ± 0.9 VAS Post ~ 4.1 ± 0.8
FFI Pre ~ 67 ± 9 FFI Post ~ 42 ± 8
VAS scale: 0–10 (Visual Analogue Scale)
FFI scale: 0–100 (Foot Function Index, higher = worse)
"""
import random, io, openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side, numbers as xl_numbers
from openpyxl.utils import get_column_letter
random.seed(42) # reproducible
# ── generate subject scores ──────────────────────────────────────────────────
def clamp(val, lo, hi, decimals=1):
return round(max(lo, min(hi, val)), decimals)
def gen_scores(mean_pre, sd_pre, mean_post, sd_post, n=30, lo=0, hi=10, decimals=1):
rows = []
for _ in range(n):
pre = clamp(random.gauss(mean_pre, sd_pre), lo, hi, decimals)
post = clamp(random.gauss(mean_post, sd_post), lo, hi, decimals)
# ensure post < pre (treatment should improve)
if post >= pre:
post = clamp(pre - abs(random.gauss(0.5, 0.3)), lo, hi, decimals)
rows.append((pre, post))
return rows
grp_a_vas = gen_scores(7.0, 0.8, 2.8, 0.7, n=30, lo=0, hi=10, decimals=1)
grp_a_ffi = gen_scores(68, 8, 28, 7, n=30, lo=0, hi=100, decimals=0)
grp_b_vas = gen_scores(6.8, 0.9, 4.1, 0.8, n=30, lo=0, hi=10, decimals=1)
grp_b_ffi = gen_scores(67, 9, 42, 8, n=30, lo=0, hi=100, decimals=0)
# ── load the existing workbook ────────────────────────────────────────────────
src = "/home/daytona/workspace/metatarsalgia-stats/Metatarsalgia_Stats_Calculator.xlsx"
wb = openpyxl.load_workbook(src)
ws1 = wb["Data Entry"]
# helper styles
INPUT_BLUE = PatternFill("solid", fgColor="DEEAF1")
INPUT_GRN = PatternFill("solid", fgColor="E2EFDA")
thin = Side(style="thin")
bdr = Border(left=thin, right=thin, top=thin, bottom=thin)
ctr = Alignment(horizontal="center", vertical="center")
def write_val(ws, row, col, val, fill):
c = ws.cell(row=row, column=col, value=val)
c.fill = fill
c.font = Font(name="Arial", size=10)
c.border = bdr
c.alignment = ctr
# rows 5–34 = subjects 1–30
for i in range(30):
row = 5 + i
vas_a_pre, vas_a_post = grp_a_vas[i]
ffi_a_pre, ffi_a_post = grp_a_ffi[i]
vas_b_pre, vas_b_post = grp_b_vas[i]
ffi_b_pre, ffi_b_post = grp_b_ffi[i]
# Group A cols B C D E
write_val(ws1, row, 2, vas_a_pre, INPUT_BLUE)
write_val(ws1, row, 3, vas_a_post, INPUT_BLUE)
write_val(ws1, row, 4, ffi_a_pre, INPUT_BLUE)
write_val(ws1, row, 5, ffi_a_post, INPUT_BLUE)
# Group B cols H I J K
write_val(ws1, row, 8, vas_b_pre, INPUT_GRN)
write_val(ws1, row, 9, vas_b_post, INPUT_GRN)
write_val(ws1, row, 10, ffi_b_pre, INPUT_GRN)
write_val(ws1, row, 11, ffi_b_post,INPUT_GRN)
# ── add a "Sample Data" notice banner ────────────────────────────────────────
YELLOW = PatternFill("solid", fgColor="FFFF00")
ws1.merge_cells("A36:K36")
c = ws1.cell(row=36, column=1,
value="⚠ SAMPLE DATA ONLY — Replace with your actual subject scores before final analysis.")
c.fill = YELLOW
c.font = Font(name="Arial", size=10, bold=True, color="C00000")
c.alignment = Alignment(horizontal="left", vertical="center")
# ── save ─────────────────────────────────────────────────────────────────────
out = "/home/daytona/workspace/metatarsalgia-stats/Metatarsalgia_Stats_SAMPLE.xlsx"
buf = io.BytesIO()
wb.save(buf)
with open(out, "wb") as f:
f.write(buf.getvalue())
# ── print a quick summary of the generated data ──────────────────────────────
import statistics as st
def summarise(label, scores):
pre = [s[0] for s in scores]
post = [s[1] for s in scores]
diff = [a - b for a,b in zip(pre,post)]
print(f" {label}")
print(f" Pre Mean={st.mean(pre):.2f} SD={st.stdev(pre):.2f}")
print(f" Post Mean={st.mean(post):.2f} SD={st.stdev(post):.2f}")
print(f" MeanDiff={st.mean(diff):.2f} SD_diff={st.stdev(diff):.2f}")
print("=== SAMPLE DATA SUMMARY ===")
print("Group A (Ultrasound Therapy):")
summarise("VAS", grp_a_vas)
summarise("FFI", grp_a_ffi)
print("Group B (Ice Therapy):")
summarise("VAS", grp_b_vas)
summarise("FFI", grp_b_ffi)
print(f"\nSaved: {out}")
cd /home/daytona/workspace/metatarsalgia-stats && python3 fill_sample_data.py 2>…
Metatarsalgia Stats SAMPLE
Spreadsheet · XLSX
| Group A (Ultrasound) | Group B (Ice Therapy) | |
|---|---|---|
| VAS Pre-test | Mean = 7.03, SD = 0.58 | Mean = 7.03, SD = 0.90 |
| VAS Post-test | Mean = 2.78, SD = 0.68 | Mean = 4.28, SD = 0.72 |
| VAS Mean Diff | 4.25 | 2.75 |
| FFI Pre-test | Mean = 69.67, SD = 8.51 | Mean = 67.23, SD = 9.26 |
| FFI Post-test | Mean = 28.03, SD = 6.06 | Mean = 42.43, SD = 9.44 |
| FFI Mean Diff | 41.63 | 24.80 |
Generate the 8 result tables (Tables 3–8) as a formatted Word document
node --version && npm list -g docx 2>/dev/null | head -5
~/metatarsalgia-stats/build_tables.js
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, BorderStyle, WidthType, ShadingType, VerticalAlign,
HeadingLevel, PageBreak, SpacingType
} = require("docx");
const fs = require("fs");
// ── Colour palette ───────────────────────────────────────────────────────────
const DARK_BLUE = "1F4E79";
const MID_BLUE = "2E75B6";
const LIGHT_BLUE = "DEEAF1";
const DARK_GREEN = "375623";
const LIGHT_GRN = "E2EFDA";
const GREY = "D9D9D9";
const WHITE = "FFFFFF";
const DARK_GREY = "595959";
// ── Sample data (from the Excel sample we generated) ─────────────────────────
// Group A – Ultrasound Therapy + Stretching + Orthotic (n=30)
const GA_VAS = { pre_mean:7.03, pre_sd:0.58, post_mean:2.78, post_sd:0.68, mean_diff:4.25, paired_t:23.18, p_val:"<0.001" };
const GA_FFI = { pre_mean:69.67, pre_sd:8.51, post_mean:28.03, post_sd:6.06, mean_diff:41.63, paired_t:21.57, p_val:"<0.001" };
// Group B – Ice Therapy + Stretching + Orthotic (n=30)
const GB_VAS = { pre_mean:7.03, pre_sd:0.90, post_mean:4.28, post_sd:0.72, mean_diff:2.75, paired_t:11.97, p_val:"<0.001" };
const GB_FFI = { pre_mean:67.23, pre_sd:9.26, post_mean:42.43, post_sd:9.44, mean_diff:24.80, paired_t:9.98, p_val:"<0.001" };
// Unpaired (Group A vs Group B on post-test scores)
const UNP_VAS = { ga_mean_diff:4.25, ga_sd:0.89, gb_mean_diff:2.75, gb_sd:1.26, t_val:5.43, p_val:"<0.001" };
const UNP_FFI = { ga_mean_diff:41.63, ga_sd:10.58, gb_mean_diff:24.80, gb_sd:13.61, t_val:5.49, p_val:"<0.001" };
// ── Helper: thin border ───────────────────────────────────────────────────────
const THIN = { style: BorderStyle.SINGLE, size: 6, color: "000000" };
const allBorders = { top: THIN, bottom: THIN, left: THIN, right: THIN };
const noBorder = { style: BorderStyle.NONE, size: 0, color: "FFFFFF" };
// ── Helper: make a shaded cell ────────────────────────────────────────────────
function cell(text, opts = {}) {
const {
bold = false, color = "000000", bg = WHITE,
align = AlignmentType.CENTER, colspan = 1,
sz = 20, italic = false, topBorder = true
} = opts;
const borders = {
top: topBorder ? THIN : noBorder,
bottom: THIN, left: THIN, right: THIN
};
return new TableCell({
columnSpan: colspan,
shading: { fill: bg, type: ShadingType.CLEAR, color: "auto" },
borders,
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({
alignment: align,
spacing: { before: 40, after: 40 },
children: [
new TextRun({
text: String(text),
bold, italic,
size: sz,
color,
font: "Times New Roman"
})
]
})
]
});
}
// ── Helper: header row (dark background, white text) ─────────────────────────
function headerRow(cells_data, bg = DARK_BLUE) {
return new TableRow({
tableHeader: true,
children: cells_data.map(([text, colspan]) =>
cell(text, { bold: true, color: WHITE, bg, colspan: colspan || 1 })
)
});
}
// ── Helper: data row ──────────────────────────────────────────────────────────
function dataRow(label, mean, sd, t_val, p_val, mean_diff, rowBg = WHITE) {
return new TableRow({
children: [
cell(label, { bold: true, bg: rowBg, align: AlignmentType.LEFT }),
cell(mean, { bg: rowBg }),
cell(sd, { bg: rowBg }),
cell(t_val, { bg: rowBg, bold: true }),
cell(p_val, { bg: rowBg, bold: true, color: p_val === "<0.001" ? "C00000" : "000000" }),
cell(mean_diff, { bg: rowBg, bold: true }),
]
});
}
// ── Helper: sub-header row (column labels) ────────────────────────────────────
function subHeaderRow(bg = GREY) {
return new TableRow({
children: [
cell("Measurement", { bold: true, bg, align: AlignmentType.LEFT }),
cell("Mean", { bold: true, bg }),
cell("Standard Deviation", { bold: true, bg }),
cell("t-value", { bold: true, bg }),
cell("P value", { bold: true, bg }),
cell("Mean Difference", { bold: true, bg }),
]
});
}
// ── Helper: between-group sub-header ─────────────────────────────────────────
function btwnSubHeader(bg = GREY) {
return new TableRow({
children: [
cell("Measurement", { bold: true, bg, align: AlignmentType.LEFT }),
cell("Mean", { bold: true, bg }),
cell("Standard Deviation", { bold: true, bg }),
cell("Independent t-value",{ bold: true, bg }),
cell("P value", { bold: true, bg }),
cell("Mean Difference", { bold: true, bg }),
]
});
}
// ── Helper: section heading paragraph ────────────────────────────────────────
function sectionHead(text) {
return new Paragraph({
spacing: { before: 280, after: 120 },
children: [
new TextRun({
text,
bold: true,
size: 24,
color: DARK_BLUE,
font: "Times New Roman"
})
]
});
}
// ── Helper: table caption ─────────────────────────────────────────────────────
function caption(text) {
return new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 160, after: 80 },
children: [
new TextRun({
text,
bold: true,
size: 22,
font: "Times New Roman",
color: DARK_BLUE
})
]
});
}
// ── Helper: table note ────────────────────────────────────────────────────────
function tableNote(text) {
return new Paragraph({
spacing: { before: 60, after: 240 },
children: [
new TextRun({
text,
italic: true,
size: 18,
color: DARK_GREY,
font: "Times New Roman"
})
]
});
}
// ── Helper: blank line ────────────────────────────────────────────────────────
function blank() {
return new Paragraph({ spacing: { before: 0, after: 0 }, children: [new TextRun("")] });
}
// ── Build a within-group table (Tables 3–6) ───────────────────────────────────
function withinGroupTable(tableNum, title, groupLabel, groupBg, data) {
return [
caption(`TABLE ${tableNum}: ${title}`),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
// Title row spanning all 6 columns
new TableRow({
children: [cell(groupLabel, { bold: true, color: WHITE, bg: groupBg === LIGHT_BLUE ? MID_BLUE : DARK_GREEN, colspan: 6 })]
}),
subHeaderRow(),
dataRow("Pre-test", data.pre_mean.toFixed(2), data.pre_sd.toFixed(2),
data.paired_t.toFixed(3), data.p_val, "-", LIGHT_BLUE === groupBg ? LIGHT_BLUE : LIGHT_GRN),
dataRow("Post-test", data.post_mean.toFixed(2), data.post_sd.toFixed(2),
data.paired_t.toFixed(3), data.p_val, data.mean_diff.toFixed(2),
LIGHT_BLUE === groupBg ? "#EEF5FB" : "#F2F7EE"),
]
}),
tableNote(`Note: Paired t-test (2-tailed), df = 29, n = 30. ***p < 0.001.`)
];
}
// ── Build between-group table (Tables 7–8) ────────────────────────────────────
function betweenGroupTable(tableNum, title, data) {
return [
caption(`TABLE ${tableNum}: ${title}`),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [cell("Group A vs Group B — Post-test Comparison", { bold: true, color: WHITE, bg: DARK_BLUE, colspan: 6 })]
}),
btwnSubHeader(),
new TableRow({
children: [
cell("Group A\n(Ultrasound)", { bold: true, bg: LIGHT_BLUE, align: AlignmentType.LEFT }),
cell(data.ga_mean_diff.toFixed(2), { bg: LIGHT_BLUE }),
cell(data.ga_sd.toFixed(2), { bg: LIGHT_BLUE }),
cell(data.t_val.toFixed(3), { bold: true, bg: LIGHT_BLUE }),
cell(data.p_val, { bold: true, bg: LIGHT_BLUE, color: "C00000" }),
cell((data.ga_mean_diff - data.gb_mean_diff).toFixed(2), { bold: true, bg: LIGHT_BLUE }),
]
}),
new TableRow({
children: [
cell("Group B\n(Ice Therapy)", { bold: true, bg: LIGHT_GRN, align: AlignmentType.LEFT }),
cell(data.gb_mean_diff.toFixed(2), { bg: LIGHT_GRN }),
cell(data.gb_sd.toFixed(2), { bg: LIGHT_GRN }),
cell(data.t_val.toFixed(3), { bold: true, bg: LIGHT_GRN }),
cell(data.p_val, { bold: true, bg: LIGHT_GRN, color: "C00000" }),
cell("-", { bg: LIGHT_GRN }),
]
}),
]
}),
tableNote(`Note: Unpaired (independent) t-test (2-tailed), df = 58, n₁ = n₂ = 30. ***p < 0.001.`)
];
}
// ── DOCUMENT ─────────────────────────────────────────────────────────────────
const doc = new Document({
styles: {
default: {
document: {
run: { font: "Times New Roman", size: 22 }
}
}
},
sections: [{
properties: {
page: {
margin: { top: 1080, bottom: 1080, left: 1080, right: 1080 }
}
},
children: [
// ── Page title ──────────────────────────────────────────────────────────
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 200 },
children: [
new TextRun({
text: "CHAPTER IV — DATA ANALYSIS",
bold: true, size: 28, color: DARK_BLUE, font: "Times New Roman"
})
]
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 60 },
children: [
new TextRun({
text: "Effectiveness of Ultrasound Therapy versus Ice Therapy Combined with",
bold: true, size: 22, font: "Times New Roman"
})
]
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 300 },
children: [
new TextRun({
text: "Stretching Exercises and Orthotic Support in School Teachers with Metatarsalgia",
bold: true, size: 22, font: "Times New Roman"
})
]
}),
// ── Descriptive statistics note ─────────────────────────────────────────
new Paragraph({
spacing: { before: 0, after: 100 },
children: [
new TextRun({
text: "Statistical Analysis: ",
bold: true, size: 22, font: "Times New Roman"
}),
new TextRun({
text: "Data were analysed using Paired t-test (within-group comparison) and " +
"Unpaired (Independent) t-test (between-group comparison). " +
"Level of significance was set at p < 0.05. " +
"All values are expressed as Mean ± Standard Deviation.",
size: 22, font: "Times New Roman"
})
]
}),
// ── Legend ──────────────────────────────────────────────────────────────
new Paragraph({
spacing: { before: 0, after: 300 },
children: [
new TextRun({ text: "Group A", bold: true, size: 22, font: "Times New Roman", color: MID_BLUE }),
new TextRun({ text: " = Ultrasound Therapy + Stretching Exercises + Orthotic Support ", size: 22, font: "Times New Roman" }),
new TextRun({ text: "Group B", bold: true, size: 22, font: "Times New Roman", color: DARK_GREEN }),
new TextRun({ text: " = Ice Therapy + Stretching Exercises + Orthotic Support n = 30 per group", size: 22, font: "Times New Roman" }),
]
}),
// ════════════════════════════════════════════════════════════════════════
// TABLES 3 & 4 — GROUP A
// ════════════════════════════════════════════════════════════════════════
sectionHead("4.1 Within-Group Analysis — Group A (Ultrasound Therapy)"),
...withinGroupTable(
3,
"Pre-test and Post-test VAS Scores — Group A (Ultrasound Therapy)",
"Group A — Ultrasound Therapy + Stretching + Orthotic (n = 30)",
LIGHT_BLUE, GA_VAS
),
blank(),
...withinGroupTable(
4,
"Pre-test and Post-test FFI Scores — Group A (Ultrasound Therapy)",
"Group A — Ultrasound Therapy + Stretching + Orthotic (n = 30)",
LIGHT_BLUE, GA_FFI
),
// ════════════════════════════════════════════════════════════════════════
// TABLES 5 & 6 — GROUP B
// ════════════════════════════════════════════════════════════════════════
sectionHead("4.2 Within-Group Analysis — Group B (Ice Therapy)"),
...withinGroupTable(
5,
"Pre-test and Post-test VAS Scores — Group B (Ice Therapy)",
"Group B — Ice Therapy + Stretching + Orthotic (n = 30)",
LIGHT_GRN, GB_VAS
),
blank(),
...withinGroupTable(
6,
"Pre-test and Post-test FFI Scores — Group B (Ice Therapy)",
"Group B — Ice Therapy + Stretching + Orthotic (n = 30)",
LIGHT_GRN, GB_FFI
),
// ════════════════════════════════════════════════════════════════════════
// TABLES 7 & 8 — BETWEEN GROUPS
// ════════════════════════════════════════════════════════════════════════
sectionHead("4.3 Between-Group Analysis — Group A vs Group B"),
...betweenGroupTable(
7,
"Independent t-value of VAS Scores — Group A vs Group B",
UNP_VAS
),
blank(),
...betweenGroupTable(
8,
"Independent t-value of FFI Scores — Group A vs Group B",
UNP_FFI
),
// ════════════════════════════════════════════════════════════════════════
// INTERPRETATION SUMMARY
// ════════════════════════════════════════════════════════════════════════
sectionHead("4.4 Interpretation of Results"),
new Paragraph({
spacing: { before: 0, after: 140 },
children: [
new TextRun({
text: "Tables 3 and 4 ",
bold: true, size: 22, font: "Times New Roman"
}),
new TextRun({
text: `show that Group A demonstrated a statistically significant reduction in forefoot pain (VAS: ${GA_VAS.pre_mean.toFixed(2)} → ${GA_VAS.post_mean.toFixed(2)}, Mean Diff = ${GA_VAS.mean_diff.toFixed(2)}, t = ${GA_VAS.paired_t.toFixed(3)}, p${GA_VAS.p_val}) and improvement in functional ability (FFI: ${GA_FFI.pre_mean.toFixed(2)} → ${GA_FFI.post_mean.toFixed(2)}, Mean Diff = ${GA_FFI.mean_diff.toFixed(2)}, t = ${GA_FFI.paired_t.toFixed(3)}, p${GA_FFI.p_val}) following Ultrasound Therapy combined with Stretching Exercises and Orthotic Support.`,
size: 22, font: "Times New Roman"
})
]
}),
new Paragraph({
spacing: { before: 0, after: 140 },
children: [
new TextRun({
text: "Tables 5 and 6 ",
bold: true, size: 22, font: "Times New Roman"
}),
new TextRun({
text: `show that Group B also demonstrated a statistically significant improvement in forefoot pain (VAS: ${GB_VAS.pre_mean.toFixed(2)} → ${GB_VAS.post_mean.toFixed(2)}, Mean Diff = ${GB_VAS.mean_diff.toFixed(2)}, t = ${GB_VAS.paired_t.toFixed(3)}, p${GB_VAS.p_val}) and functional ability (FFI: ${GB_FFI.pre_mean.toFixed(2)} → ${GB_FFI.post_mean.toFixed(2)}, Mean Diff = ${GB_FFI.mean_diff.toFixed(2)}, t = ${GB_FFI.paired_t.toFixed(3)}, p${GB_FFI.p_val}) following Ice Therapy combined with Stretching Exercises and Orthotic Support.`,
size: 22, font: "Times New Roman"
})
]
}),
new Paragraph({
spacing: { before: 0, after: 140 },
children: [
new TextRun({
text: "Tables 7 and 8 ",
bold: true, size: 22, font: "Times New Roman"
}),
new TextRun({
text: `show the between-group comparison. Group A showed significantly greater improvement in VAS (Mean Diff = ${UNP_VAS.ga_mean_diff.toFixed(2)} vs ${UNP_VAS.gb_mean_diff.toFixed(2)}, t = ${UNP_VAS.t_val.toFixed(3)}, p${UNP_VAS.p_val}) and FFI (Mean Diff = ${UNP_FFI.ga_mean_diff.toFixed(2)} vs ${UNP_FFI.gb_mean_diff.toFixed(2)}, t = ${UNP_FFI.t_val.toFixed(3)}, p${UNP_FFI.p_val}) compared to Group B, indicating that Ultrasound Therapy was more effective than Ice Therapy when both were combined with Stretching Exercises and Orthotic Support.`,
size: 22, font: "Times New Roman"
})
]
}),
new Paragraph({
spacing: { before: 200, after: 60 },
children: [
new TextRun({
text: "Note: ",
bold: true, italic: true, size: 20, color: DARK_GREY, font: "Times New Roman"
}),
new TextRun({
text: "The above values are based on SAMPLE DATA for demonstration purposes. " +
"Replace with your actual collected data. " +
"VAS = Visual Analogue Scale (0–10); FFI = Foot Function Index (0–100). " +
"Higher FFI score = greater disability.",
italic: true, size: 20, color: DARK_GREY, font: "Times New Roman"
})
]
}),
]
}]
});
// ── Save ──────────────────────────────────────────────────────────────────────
const outPath = "/home/daytona/workspace/metatarsalgia-stats/Result_Tables_3_to_8.docx";
Packer.toBuffer(doc).then(buf => {
fs.writeFileSync(outPath, buf);
console.log("Saved:", outPath, `(${(buf.length/1024).toFixed(1)} KB)`);
});
cd /home/daytona/workspace/metatarsalgia-stats && node build_tables.js 2>&1
python3 /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/works…
# Manual validation: unzip and check key XML files exist and are non-empty pytho…
Result Tables 3 to 8
Word Document · DOCX
| Table | Group | Outcome | Pre Mean | Post Mean | Mean Diff | t-value | p-value |
|---|---|---|---|---|---|---|---|
| 3 | Group A (Ultrasound) | VAS | 7.03 | 2.78 | 4.25 | 23.183 | <0.001 *** |
| 4 | Group A (Ultrasound) | FFI | 69.67 | 28.03 | 41.63 | 21.573 | <0.001 *** |
| 5 | Group B (Ice Therapy) | VAS | 7.03 | 4.28 | 2.75 | 11.970 | <0.001 *** |
| 6 | Group B (Ice Therapy) | FFI | 67.23 | 42.43 | 24.80 | 9.980 | <0.001 *** |
| Table | Outcome | Group A Mean Diff | Group B Mean Diff | t-value | p-value |
|---|---|---|---|---|---|
| 7 | VAS | 4.25 | 2.75 | 5.430 | <0.001 *** |
| 8 | FFI | 41.63 | 24.80 | 5.490 | <0.001 *** |