Buckets:
| """n = 14 variant: missing endpoint scores imputed with the neutral value 4 (appendix sensitivity analysis). Table 5 -> figure: three paired-bar panels (appropriateness, timeliness, annoyance) with participant points, paired lines, | |
| 95% participant-bootstrap CIs of each condition mean, and the paired Delta with its reported CI and Wilcoxon p. Paper palette.""" | |
| import re, numpy as np, matplotlib | |
| matplotlib.use("Agg") | |
| import matplotlib.pyplot as plt, matplotlib.font_manager as fm | |
| from matplotlib.lines import Line2D | |
| import glob | |
| for f in glob.glob("/usr/share/fonts/truetype/msttcorefonts/Times*.ttf"): fm.fontManager.addfont(f) | |
| plt.rcParams.update({"font.family":"Times New Roman","font.size":7,"axes.linewidth":0.5,"xtick.major.width":0.5,"ytick.major.width":0.5,"pdf.fonttype":42}) | |
| GREY="#8C8C8C"; LAV="#DDD6E5"; LAVL="#DFEDF2"; INK="#2B2B2B"; PEACHL="#F5D8BF"; LINE="#C8C8C8" | |
| # participant table (appendix H): ID, APP C, APP S, TIM C, TIM S, ANN C, ANN S | |
| rows="""P01 4.00 2.50 7 1 6 -- | |
| P02 6.33 4.00 7 1 2 2 | |
| P03 4.00 1.67 4 2 2 1 | |
| P04 6.33 1.67 6 -- 3 -- | |
| P05 6.00 5.00 7 2 4 4 | |
| P06 4.33 3.67 6 4 5 1 | |
| P07 4.00 4.00 4 4 1 1 | |
| P08 3.33 3.00 4 3 5 1 | |
| P09 6.67 1.67 6 1 1 1 | |
| P10 5.67 1.67 6 1 2 1 | |
| P11 7.00 7.00 7 7 1 1 | |
| P12 3.67 3.67 5 5 2 1 | |
| P13 6.00 6.67 6 6 1 1 | |
| P14 6.50 2.67 -- 3 5 2""".splitlines() | |
| def f(x): return 4.0 if x=="--" else float(x) # neutral imputation | |
| D=np.array([[f(v) for v in r.split()[1:]] for r in rows]) | |
| from scipy.stats import wilcoxon | |
| rng=np.random.default_rng(20260922) | |
| def stats(c,s): | |
| d=c-s; b=[rng.choice(d,len(d)).mean() for _ in range(2000)]; lo,hi=np.percentile(b,2.5),np.percentile(b,97.5); p=wilcoxon(c,s).pvalue | |
| return f"{d.mean():+.2f} [{lo:.2f}, {hi:.2f}]", ("p = "+f"{p:.3f}".lstrip("0")) | |
| # Delta / CI / p as reported in Appendix H (neutral imputation, 2,000 participant resamples, seed 20260922); computed values printed below for the check | |
| panels=[("Appropriateness",D[:,0],D[:,1],"+1.79 [0.86, 2.75]","p = .008",True), | |
| ("Timeliness",D[:,2],D[:,3],"+2.50 [1.36, 3.71]","p = .005",True), | |
| ("Annoyance",D[:,4],D[:,5],"+1.07 [0.36, 1.93]","p = .028",False)] | |
| def ci(v): | |
| b=[rng.choice(v,len(v)).mean() for _ in range(2000)]; return np.percentile(b,2.5),np.percentile(b,97.5) | |
| fig,axes=plt.subplots(1,3,figsize=(5.5,1.08),dpi=300,gridspec_kw=dict(wspace=0.5,left=0.065,right=0.995,top=0.69,bottom=0.26)) | |
| for ax,(name,c,s,dtxt,ptxt,higher_good) in zip(axes,panels): | |
| m=~np.isnan(c)&~np.isnan(s); c,s=c[m],s[m]; n=int(m.sum()) | |
| means=[s.mean(),c.mean()]; cis=[ci(s),ci(c)] | |
| x=[0,1] | |
| ax.bar(x,means,width=0.62,color=[GREY,LAV],edgecolor=[GREY,"#B9AFC9"],linewidth=0.5,zorder=1) | |
| for xi,(lo,hi) in zip(x,cis): ax.plot([xi,xi],[lo,hi],color=INK,lw=0.8,zorder=4); ax.plot([xi-0.08,xi+0.08],[lo,lo],color=INK,lw=0.6,zorder=4); ax.plot([xi-0.08,xi+0.08],[hi,hi],color=INK,lw=0.6,zorder=4) | |
| jit=rng.uniform(-0.13,0.13,n) | |
| for k in range(n): ax.plot([0+jit[k],1+jit[k]],[s[k],c[k]],color=LINE,lw=0.4,zorder=2) | |
| ax.scatter(0+jit,s,s=5,color="white",edgecolor=INK,linewidth=0.4,zorder=3); ax.scatter(1+jit,c,s=5,color="white",edgecolor=INK,linewidth=0.4,zorder=3) | |
| ax.set_xticks(x); ax.set_xticklabels([f"openpilot\n{means[0]:.2f}",f"TriDrive\n{means[1]:.2f}"],fontsize=6.5,linespacing=1.1); ax.set_xlim(-0.55,1.55) | |
| ax.set_ylim(0.5,7.6); ax.set_yticks([1,4,7]); ax.tick_params(length=2,pad=1.5) | |
| for sp in ("top","right"): ax.spines[sp].set_visible(False) | |
| ax.spines["left"].set_color(GREY); ax.spines["bottom"].set_color(GREY); ax.tick_params(colors=INK) | |
| ax.text(0.5,1.37,f"{name} (n = {n})",ha="center",va="bottom",fontsize=7.2,color=INK,transform=ax.transAxes,fontweight="bold") | |
| ax.text(0.5,1.09,f"$\\Delta$ {dtxt}, {ptxt}",ha="center",va="bottom",fontsize=6.3,color=INK,transform=ax.transAxes,bbox=dict(boxstyle="round,pad=0.2",fc=PEACHL,ec="none")) | |
| axes[0].set_ylabel("Rating (1–7)",fontsize=6.5,color=INK,labelpad=1) | |
| out="figures/user_study_bars_n14.pdf" | |
| fig.savefig(out); fig.savefig(out.replace(".pdf",".png"),dpi=300); print("saved",out) | |
| for name,c,s,dtxt,ptxt,_ in panels: print(name,len(c),"means C/S",round(c.mean(),2),round(s.mean(),2),"reported",dtxt,ptxt,"| computed",*stats(c,s)) | |
Xet Storage Details
- Size:
- 4.19 kB
- Xet hash:
- 06b2c9ab004816765755b80a6597fd4678c736977774064ab33465516d0b7404
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.