$$ % Define your custom commands here \newcommand{\bmat}[1]{\begin{bmatrix}#1\end{bmatrix}} \newcommand{\E}{\mathbb{E}} \newcommand{\P}{\mathbb{P}} \newcommand{\S}{\mathbb{S}} \newcommand{\R}{\mathbb{R}} \newcommand{\S}{\mathbb{S}} \newcommand{\norm}[2]{\|{#1}\|_{{}_{#2}}} \newcommand{\pd}[2]{\frac{\partial #1}{\partial #2}} \newcommand{\pdd}[2]{\frac{\partial^2 #1}{\partial #2^2}} \newcommand{\vectornorm}[1]{\left|\left|#1\right|\right|} \newcommand{\abs}[1]{\left|{#1}\right|} \newcommand{\mbf}[1]{\mathbf{#1}} \newcommand{\mc}[1]{\mathcal{#1}} \newcommand{\bm}[1]{\boldsymbol{#1}} \newcommand{\nicefrac}[2]{{}^{#1}\!/_{\!#2}} \newcommand{\argmin}{\operatorname*{arg\,min}} \newcommand{\argmax}{\operatorname*{arg\,max}} \newcommand{\dd}{\operatorname{d}\!} $$

daily

daily

The morning routine’s bookkeeping: record today’s readings, keep a plan log.

wdm daily is the whole daily obligation in one command (see wdm.cli.cmd_daily). This module holds the parts of it that touch files, kept apart so they can be tested without running the filter:

  • record writes values into a day’s row of the observations CSV: this morning’s weigh-in and waist, or yesterday’s food, creating the row if needed. Row k holds the morning readings of day k and the food eaten that day, so entering the weight first thing is exactly right; the food columns are filled in tomorrow.
  • log_plan archives every plan with the facts needed to reproduce it, which a plain plan.csv, overwritten daily, cannot do.

The CSV is edited through the csv module with every cell kept as the string it was, so nothing is reformatted: a line that was not touched is byte-for-byte what it was.

Functions

Name Description
add_column Add an empty column col (before before if present); False if it exists.
ask_number Prompt until the answer is a number or blank (None).
day_has_food Whether date’s row has an energy total or a full macro split.
day_totals The day’s logged totals for the prescribed quantities, zero where blank.
day_value The raw cell for col on date, or None if the row or cell is empty.
last_weight_lb The most recent weigh-in in the file, or None if there is none.
log_plan Archive plan as <start>.csv and append a row to log.csv.
prescription Today’s prescription: the latest logged plan that starts on date.
record Write values into date’s row; return what was done.
record_morning Write this morning’s readings into date’s row; return what was done.

add_column

daily.add_column(path, col, *, before='notes')

Add an empty column col (before before if present); False if it exists.

Every row gets an empty cell, so the file stays rectangular and nothing else in it changes.

ask_number

daily.ask_number(prompt, ask=input)

Prompt until the answer is a number or blank (None).

day_has_food

daily.day_has_food(path, date)

Whether date’s row has an energy total or a full macro split.

None when there is no row for that date at all.

day_totals

daily.day_totals(path, date)

The day’s logged totals for the prescribed quantities, zero where blank.

day_value

daily.day_value(path, date, col)

The raw cell for col on date, or None if the row or cell is empty.

last_weight_lb

daily.last_weight_lb(path)

The most recent weigh-in in the file, or None if there is none.

log_plan

daily.log_plan(
    log_dir,
    plan,
    *,
    write_plan_csv,
    target_weight_lb,
    target_date,
    trend_lb,
    maintenance_kcal,
    constraints_ok,
    command,
)

Archive plan as <start>.csv and append a row to log.csv.

A replan on the same day overwrites that day’s archived plan but adds a new log row, so the log records every prescription ever issued.

prescription

daily.prescription(log_dir, date)

Today’s prescription: the latest logged plan that starts on date.

record

daily.record(path, date, values, *, add=False, replace=False)

Write values into date’s row; return what was done.

An existing row keeps its episode and gets the values in its empty cells; a value that would overwrite a different one is refused, since a silent overwrite is how a typo becomes data. With add, values are summed into what is there instead: that is how a meal joins the day’s food totals. With replace, a new value overwrites the old one, for running totals such as a step count. A missing row is appended to the most recent episode, so a new diet attempt still needs its first row by hand. None values are skipped.

record_morning

daily.record_morning(path, date, *, weight_lb=None, waist_in=None)

Write this morning’s readings into date’s row; return what was done.