From 362d00c9c15ecb281f611db9b31b1da015312404 Mon Sep 17 00:00:00 2001 From: Nicholas Karlson Date: Tue, 20 Jan 2026 19:43:19 -0800 Subject: [PATCH] Console: replace emoji status markers with ASCII --- docs/source/workbook/track_d_lab_ta_notes.rst | 2 +- docs/source/workbook/windows11_setup.rst | 2 +- ...lation_causation_controlled_comparisons.py | 4 ++-- scripts/d00_peek_data.py | 6 +++--- scripts/d00_setup_data.py | 3 ++- scripts/my_data_01_explore.py | 6 ++++-- src/pystatsv1/assets/workbook_track_d.zip | Bin 157221 -> 157288 bytes ...lation_causation_controlled_comparisons.py | 4 ++-- .../track_d_template/scripts/d00_peek_data.py | 7 ++++--- .../scripts/d00_setup_data.py | 3 ++- 10 files changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/source/workbook/track_d_lab_ta_notes.rst b/docs/source/workbook/track_d_lab_ta_notes.rst index da5bfbb..ebe9e3a 100644 --- a/docs/source/workbook/track_d_lab_ta_notes.rst +++ b/docs/source/workbook/track_d_lab_ta_notes.rst @@ -132,7 +132,7 @@ location. You now have a ready-to-run lab workspace.” Students should see a message like: -- “✅ Track D workbook starter created at …” +- “[OK] Track D workbook starter created at …” - “Datasets are pre-installed under ``data/synthetic/``, seed=123.” 4.2 Why seed=123 matters diff --git a/docs/source/workbook/windows11_setup.rst b/docs/source/workbook/windows11_setup.rst index b2e5815..fceb7b8 100644 --- a/docs/source/workbook/windows11_setup.rst +++ b/docs/source/workbook/windows11_setup.rst @@ -209,7 +209,7 @@ The ``[workbook]`` part is important: it means "include the workbook extras". ``pystatsv1 doctor`` runs a quick health check. If you see:: - ✅ Environment looks good. + [OK] Environment looks good. then your install is working. diff --git a/scripts/business_ch13_correlation_causation_controlled_comparisons.py b/scripts/business_ch13_correlation_causation_controlled_comparisons.py index 471d1fc..f452b51 100644 --- a/scripts/business_ch13_correlation_causation_controlled_comparisons.py +++ b/scripts/business_ch13_correlation_causation_controlled_comparisons.py @@ -185,8 +185,8 @@ def analyze_ch13(*, datadir: Path, outdir: Path, seed: int) -> Outputs: The controlled comparison (partial correlation) helps avoid a misleading story: “Revenue causes payroll taxes.” ## What we can and cannot claim -✅ We can say: Revenue and payroll taxes move together in this dataset, and payroll explains much of that relationship. -❌ We cannot say: Increasing revenue causes payroll taxes to rise (causal claim). +- OK: Revenue and payroll taxes move together in this dataset, and payroll explains much of that relationship. +- NOT OK: Increasing revenue causes payroll taxes to rise (a causal claim). ## Sensitivity check Leave-one-out naive correlation range: {loo_min:.3f} to {loo_max:.3f} diff --git a/scripts/d00_peek_data.py b/scripts/d00_peek_data.py index aca760a..9a360ef 100644 --- a/scripts/d00_peek_data.py +++ b/scripts/d00_peek_data.py @@ -40,7 +40,7 @@ def _preview_csv(path: Path, n: int = 5) -> str: def _peek_dataset(name: str, folder: Path, preview_rows: int) -> tuple[str, list[str]]: if not folder.exists(): msg = ( - f"⚠️ Missing dataset folder: {folder}\n" + f"[WARN] Missing dataset folder: {folder}\n" "If you just created this workbook, you may be on an older PyStatsV1 version.\n" "Update, then re-run workbook init:\n\n" " python -m pip install -U pystatsv1\n" @@ -51,7 +51,7 @@ def _peek_dataset(name: str, folder: Path, preview_rows: int) -> tuple[str, list csvs = sorted(folder.glob("*.csv")) if not csvs: msg = ( - f"⚠️ No CSV files found in: {folder}\n" + f"[WARN] No CSV files found in: {folder}\n" "This workbook expects canonical datasets to exist under data/synthetic/.\n" ) return msg, [msg] @@ -113,7 +113,7 @@ def main(argv: list[str] | None = None) -> int: report = outdir / "d00_peek_data_summary.md" report.write_text("\n".join(sections).rstrip() + "\n", encoding="utf-8") - print(f"\n✅ Wrote summary: {report}") + print(f"\n[OK] Wrote summary: {report}") print("Tip: If you edited data/synthetic, run: pystatsv1 workbook run d00_setup_data --force") return 0 diff --git a/scripts/d00_setup_data.py b/scripts/d00_setup_data.py index c7a9c25..2a805cd 100644 --- a/scripts/d00_setup_data.py +++ b/scripts/d00_setup_data.py @@ -92,7 +92,8 @@ def main(argv: list[str] | None = None) -> int: ], ) - print("\n✅ Datasets ready under:", root) + # ASCII-only status marker for Windows consoles that default to cp1252. + print("\n[OK] Datasets ready under:", root) print(" -", ledger_dir) print(" -", nso_dir) return 0 diff --git a/scripts/my_data_01_explore.py b/scripts/my_data_01_explore.py index 6ca3eae..2d016e9 100644 --- a/scripts/my_data_01_explore.py +++ b/scripts/my_data_01_explore.py @@ -171,7 +171,7 @@ def print_quick_report(df: pd.DataFrame) -> None: if ID_COL in df.columns: dup = df[ID_COL].duplicated().sum() if dup: - print(f"\n⚠️ Duplicate {ID_COL} values: {dup}") + print(f"\n[WARN] Duplicate {ID_COL} values: {dup}") if GROUP_COL in df.columns: k = df[GROUP_COL].nunique(dropna=False) @@ -182,7 +182,9 @@ def print_quick_report(df: pd.DataFrame) -> None: numeric = df.select_dtypes(include=["number"]).columns if len(numeric) == 0: - print("\n⚠️ No numeric columns detected. If numbers are stored as text, fix your CSV or edit the script.") + print( + "\n[WARN] No numeric columns detected. If numbers are stored as text, fix your CSV or edit the script." + ) else: print("\nnumeric columns:") for c in numeric: diff --git a/src/pystatsv1/assets/workbook_track_d.zip b/src/pystatsv1/assets/workbook_track_d.zip index 9c72423a7c6905ade2d5b6c694b48d169e31623e..560a866c1d4156024c7d09a6fd7ba6c46baf6803 100644 GIT binary patch delta 7258 zcmYj$Wl$W^wly=jyF+kycXxLW?he6%4#C|54DRlOOCU(F5Zpr0;5N7g%OmgByWe-J zx>oJAdau=|f9yV0UH$|4@CR}e)=w0~^Wa-IOcdkKQ2mScH9Le9qGB7OSln#;FsZRAr(@Umbyxr-_<{$gFItb^lV)TZ z53GYMH`=!}SA(;IUUDK;AlqtY)3XU9HPwsZIb~p0^RG$!pT_|vwkHU>6k9xE5~At> zQJ)JeGgu)P-7%p4^UwUQ|lvYc63eEfmOcEX?sz0 z<2BV>luCx})yg0vnP@p9XKg2Lh-(0wSjf0@!Tx)usxe<*H9OhilWS2Cuioj)dG7^R zx$X{VApta9Y-+CCq|AX|Z=%ymZZC(K2#@5#ysZ_jR@Y9iew%iZN8to*KV33Jc`RQ_ zdj^Izx2k(GGWS9jb&rK5jc{*qfxov-R@gSq9EC;jxd;?%Y+!|I$B_K`d~|J4*lU4G zkP=EYHeM)<9bx!tj2Cav{OQvP{oM~kSR*no{*-=)eR=)`C*6XS!!P=^N9%Ul7iPKZ zahu}V{j^45G}?s>geB-;&M7D2uXxTgH!Ys#&NKe;#4)wH4~GR&Y{ve&X#i9{w?z7K!EKYm!-y(8aI z(K_To>B_U^%Z2F1(TPi6Hv)0C`jPZw_|R^(Wx0r3JHq#lX=l8`bw&@FIsDPzc^4M9 ztgb+1yd2=b9lwPs+-$yMgnBzFuhGMk>?f3Q_Vt1Yqo}4>`8teR5KJ;~f}Kx`Em9&h z+E(X3z?+yHc$!r(oIKNBAi`I=K!{Xxxn0O>P%D1K!BDt;t@Je3cO`P{UO_3dhEyLf zHPyn8@zDJ=_uq(_E@QRrB&iz>MYre%OxeR{DTgpZ#EJw1cQBt4gGgmF|9qBo≤o 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�OzuyA-dFfcGkZx@xOyzbBT0yr3$4e-G!fEuLYzQd2zcVd9nO32i- zM=QsH@Sf5k0EvGRAs3G=1p$pM(RvVvDMc3t_T`d1tz_2#QjOXECo4O7Q}k>9(95m) zyopu`uV8PrrZEJk>fqvO(mJi;sC0i1q2agb(WG`YdL6`V-M@khBo~`w0@owYX`&>d zpRVaSfo`lrI}XaA5B}1Mu+i2;KxYWg!7*Qb>_T@lF(Iln^`+k>rEt-(x1`}uTE@wB zJh7zjiJ#ja95k!8&dz6KR`Vr?D{Dtbyg)DQ%g^g#LE#xU1N&9{x*!% zJCu+AK$XB}^v-vkA&bMChj9$CKK}=>)VpLG;sy#67#qDv<;v5_TK;N_Ua{Eedxug4a<}!a0OhHmH0+Jj=^3 zzV!2ZxAGR0aJ{Qx>dC%yTEB#4E@g##?T@>1IfzjBM&^;gwv~Ph;r#9F(s;rqRTl)r;KM^zmDM^E&aK6 zs|$W7bMXTcMs`lZQY;{=TjQcxSEhv`n7ma%dOqBeYLfiN-z=gzSh_-=XD&8|Dq@G& zCBs79CpiDKJN;nlp4Ec((jhStjaYfmpoVhP(0rKKAZ{8LR6UNIH_6nw)Z~7;aMbqv zki+Bl;$(7CSBYeLt$%^|m>@t#E~lCF6>q^}BazgMQOg0T+1btd=w3%H(DTo=E%q_Z zq#3`;-%O3oKJg(Rmsk@2HuU-Vyg@fsg_qz*f%2E35(r3G7u~Onsj4-?%juR0uPQ-l zqjSI!5}MAn{6MTCQ{}|&FcMg#g_XN09x?fBm~t@w_1_2s|1bxVbfjMb<{gm#`!fmb zVGN7_&L4oO41xHcu?{K0EG9r^pv}Yo5?~h-paKvB6^#8JNB~wv1(1OE{>iVD{}@-` zti*p5Oi2JQ`1|`eCC%tR%#0C$6D(@_##nlTrOe*C3%voX;F^DoMACnl;3NPO7~c%Y z3|It9ngN}F*CYQC2F-vPK#`4qPPkxtb07`rf6w9=Ffc@KQ~3W@JD?YAV-92?|L;&n zg@GadKlKgU0lTLFF!c28$w$oJlDfc`=0Fi3;x(Av0w@fy2Rm8-MF3;q@;AT~y$8T} zS$}Z!@b==c;p78r>AvMhJOHrXO#idm-went-wX&J!N!(v1}@-?w-WFRJo}FodIe)x zy|Hm%C95~~1RVJfw7~=apd0-15B9-A)^E3BB7l9Zfx?)Ah`|4s$tCcg%q}G0|DSmV zhQ74`O2AAuZ=JkoU^|<)kS=iXzfu|#yz#G`1QXi=MPP++fM5Xq+xvF41@gl((Eo2m X0Uow}+x!&x!WPJZFrW>5+s*#~J<*=+ delta 7157 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 Outputs: The controlled comparison (partial correlation) helps avoid a misleading story: “Revenue causes payroll taxes.” ## What we can and cannot claim -✅ We can say: Revenue and payroll taxes move together in this dataset, and payroll explains much of that relationship. -❌ We cannot say: Increasing revenue causes payroll taxes to rise (causal claim). +- OK: Revenue and payroll taxes move together in this dataset, and payroll explains much of that relationship. +- NOT OK: Increasing revenue causes payroll taxes to rise (a causal claim). ## Sensitivity check Leave-one-out naive correlation range: {loo_min:.3f} to {loo_max:.3f} diff --git a/workbooks/track_d_template/scripts/d00_peek_data.py b/workbooks/track_d_template/scripts/d00_peek_data.py index 2d442d8..3502e0f 100644 --- a/workbooks/track_d_template/scripts/d00_peek_data.py +++ b/workbooks/track_d_template/scripts/d00_peek_data.py @@ -43,7 +43,7 @@ def _preview_csv(path: Path, n: int = 5) -> str: def _peek_dataset(name: str, folder: Path, preview_rows: int) -> tuple[str, list[str]]: if not folder.exists(): msg = ( - f"⚠️ Missing dataset folder: {folder}\n" + f"[WARN] Missing dataset folder: {folder}\n" "If you just created this workbook, you may be on an older PyStatsV1 version.\n" "Update, then re-run workbook init:\n\n" " python -m pip install -U pystatsv1\n" @@ -54,7 +54,7 @@ def _peek_dataset(name: str, folder: Path, preview_rows: int) -> tuple[str, list csvs = sorted(folder.glob("*.csv")) if not csvs: msg = ( - f"⚠️ No CSV files found in: {folder}\n" + f"[WARN] No CSV files found in: {folder}\n" "This workbook expects canonical datasets to exist under data/synthetic/.\n" ) return msg, [msg] @@ -116,7 +116,8 @@ def main(argv: list[str] | None = None) -> int: report = outdir / "d00_peek_data_summary.md" report.write_text("\n".join(sections).rstrip() + "\n", encoding="utf-8") - print(f"\n✅ Wrote summary: {report}") + # ASCII-only status marker for Windows consoles that default to cp1252. + print(f"\n[OK] Wrote summary: {report}") print("Tip: If you edited data/synthetic, run: pystatsv1 workbook run d00_setup_data --force") return 0 diff --git a/workbooks/track_d_template/scripts/d00_setup_data.py b/workbooks/track_d_template/scripts/d00_setup_data.py index 3dbc7b4..9da52ca 100644 --- a/workbooks/track_d_template/scripts/d00_setup_data.py +++ b/workbooks/track_d_template/scripts/d00_setup_data.py @@ -97,7 +97,8 @@ def main(argv: list[str] | None = None) -> int: ], ) - print("\n✅ Datasets ready under:", root) + # ASCII-only status marker for Windows consoles that default to cp1252. + print("\n[OK] Datasets ready under:", root) print(" -", ledger_dir) print(" -", nso_dir) return 0