Skip to content

Commit be50d48

Browse files
committed
Merge remote-tracking branch 'origin/main' into docs/improve-parametric-survival-models-8996973743991643553
Co-authored-by: d-morrison <2474437+d-morrison@users.noreply.github.com>
2 parents 336520e + 976a412 commit be50d48

5 files changed

Lines changed: 135 additions & 53 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Quarto Preview Build (Bypass)
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
permissions: {}
10+
steps:
11+
- name: Bypass render for infra-only PRs
12+
run: echo "No render required for this PR. Status check bypassed."

.github/workflows/claude-code-review.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ jobs:
3232
issues: write
3333
id-token: write
3434
actions: read # lets the reviewer read CI status (github_ci MCP server)
35+
# gha's reusable review job requests `checks: read` as of v2
36+
# (Morrison-Lab/gha#830) so it can call
37+
# /repos/{owner}/{repo}/commits/{ref}/check-runs. A called workflow
38+
# cannot request a permission its caller withheld, so omitting this
39+
# fails the whole run at startup, before any job exists -- which
40+
# produces no check run and so looks identical to no review being
41+
# due (rme#1142).
42+
checks: read
3543
uses: Morrison-Lab/gha/.github/workflows/claude-code-review.yml@v2
3644
secrets:
3745
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

.github/workflows/preview.yml

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Build half of the PR-preview family, delegated to the reusable workflow in
22
# Morrison-Lab/gha. Renders the Quarto site in the (possibly fork) PR context and
33
# uploads it + PR metadata as an artifact; the deploy half (preview-deploy.yml)
4-
# publishes it to gh-pages. This job is read-only (contents: read) — it must
5-
# never write to the base repo.
4+
# publishes it to gh-pages. Every job here is read-only — the workflow-level
5+
# `permissions:` block below grants `pull-requests: read` (needed by the
6+
# `filter` job's paths-filter API call) and the render job re-narrows itself
7+
# to `contents: read`. Nothing here may write to the base repo.
68
#
79
# IMPORTANT: keep this workflow's `name:` in sync with the `workflows:` list in
810
# preview-deploy.yml — that is how the deploy half finds this run.
@@ -21,42 +23,83 @@ name: Quarto Preview Build
2123
on:
2224
pull_request:
2325
types: [opened, reopened, synchronize, labeled, closed]
24-
paths:
25-
- 'man/**'
26-
- 'pkgdown/**'
27-
- 'vignettes/**'
28-
- '_extensions/**'
29-
- '_quarto*.yml'
30-
- '.github/workflows/preview.yml'
31-
- '*.qmd'
32-
- 'chapters/**/*.qmd'
33-
- '_subfiles/**'
34-
- '*.scss'
35-
- 'latex-macros'
36-
- 'references.bib'
37-
# Dependency changes are the changes most likely to alter rendered
38-
# output, yet without these two entries a version-only PR got no
39-
# render at all: this is the only workflow that runs quarto render,
40-
# and it has no workflow_dispatch. The first render against new
41-
# package versions therefore happened post-merge on main, where a
42-
# failure breaks the published site instead of a PR check (rme#1075).
43-
#
44-
# Caveat worth knowing when reading a green build on such a PR: the
45-
# freeze cache does NOT isolate dependency changes. gha's preview
46-
# composite restores _freeze through a restore-keys chain whose last
47-
# entry, `quarto-freezer-<os>-`, omits the renv.lock hash entirely,
48-
# so a version-only PR restores a freeze computed under the OLD
49-
# versions and may serve those cached results instead of re-running
50-
# anything. Add the `clear freezer` label to a dependency PR when the
51-
# point is to exercise the new versions -- the composite skips the
52-
# restore when it is present.
53-
- 'renv.lock'
54-
- 'DESCRIPTION'
26+
27+
permissions:
28+
pull-requests: read
29+
contents: read
5530

5631
jobs:
57-
build:
32+
filter:
33+
runs-on: ubuntu-latest
34+
outputs:
35+
render: ${{ steps.filter.outputs.render }}
36+
steps:
37+
- uses: dorny/paths-filter@v3
38+
id: filter
39+
with:
40+
filters: |
41+
render:
42+
- 'man/**'
43+
- 'pkgdown/**'
44+
- 'vignettes/**'
45+
- '_extensions/**'
46+
- '_quarto*.yml'
47+
- '.github/workflows/preview.yml'
48+
- '*.qmd'
49+
- 'chapters/**/*.qmd'
50+
- '_subfiles/**'
51+
- '*.scss'
52+
- 'latex-macros'
53+
- 'references.bib'
54+
# Dependency changes are the changes most likely to alter rendered
55+
# output, yet without these two entries a version-only PR got no
56+
# render at all: this is the only workflow that runs quarto render,
57+
# and it has no workflow_dispatch. The first render against new
58+
# package versions therefore happened post-merge on main, where a
59+
# failure breaks the published site instead of a PR check (rme#1075).
60+
#
61+
# Caveat worth knowing when reading a green build on such a PR: the
62+
# freeze cache does NOT isolate dependency changes. gha's preview
63+
# composite restores _freeze through a restore-keys chain whose last
64+
# entry, `quarto-freezer-<os>-`, omits the renv.lock hash entirely,
65+
# so a version-only PR restores a freeze computed under the OLD
66+
# versions and may serve those cached results instead of re-running
67+
# anything. Add the `clear freezer` label to a dependency PR when the
68+
# point is to exercise the new versions -- the composite skips the
69+
# restore when it is present.
70+
- 'renv.lock'
71+
- 'DESCRIPTION'
72+
# The reusable workflow installs this package before rendering,
73+
# so a broken R source breaks the render even though no .qmd
74+
# calls into R/ today. Under the old trigger-level `paths:`
75+
# filter an R-only PR got no render at all and stalled, which
76+
# was at least visible; routing it to `bypass` instead would
77+
# report a green `build / build` over an unbuilt package.
78+
- 'R/**'
79+
- 'NAMESPACE'
80+
81+
render:
82+
name: build
83+
needs: filter
84+
# Fail toward doing the real render. If the `filter` job itself fails or
85+
# errors (a dorny/paths-filter bug, a transient API error), its `render`
86+
# output is empty rather than 'false', so this job still runs: `build /
87+
# build` is reported on every PR regardless of paths touched (rme#1108),
88+
# and it is reported by the job that actually verifies the render rather
89+
# than by the no-op. `!cancelled()` rather than `always()` so a cancelled
90+
# run does not start a full render.
91+
if: ${{ !cancelled() && needs.filter.outputs.render != 'false' }}
92+
# Re-narrow to the scope this job had before `pull-requests: read` was
93+
# added at workflow level for `filter`: the render must not inherit it.
5894
permissions:
5995
contents: read
6096
uses: Morrison-Lab/gha/.github/workflows/preview.yml@v2
6197
with:
6298
r-version: '4.6.0'
99+
100+
bypass:
101+
name: build
102+
needs: filter
103+
if: needs.filter.outputs.render == 'false'
104+
# zizmor suggests $/... for self-repository calls, but we use explicit paths for consistency with other repos
105+
uses: ./.github/workflows/_preview-bypass-reusable.yml # zizmor: ignore[self-repository]

chapters/glms.qmd

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,53 @@ by Annette J. Dobson and Adrian G. Barnett:
2525

2626
# Choosing a model
2727

28-
The type of predictive model one uses depends on several issues; one is the type of response.
28+
The choice of statistical model depends on several considerations,
29+
primary among which is the type of response variable.
2930

30-
* Measured values such as quantity of a protein, age, weight usually can be handled in an ordinary linear regression model, possibly after a log transformation.
31+
* Measured continuous values such as protein level, age, or weight can usually be modeled using linear regression,
32+
possibly after applying a logarithmic transformation.
3133

32-
* Patient survival, which may be censored, calls for a different method (survival analysis, Cox regression).
34+
* Patient survival times, which may be right-censored, call for time-to-event methods
35+
such as Kaplan-Meier estimation or Cox proportional hazards regression.
3336

34-
* If the response is binary, then can we use logistic regression models
37+
* If the outcome is binary (0/1),
38+
we can use logistic regression models.
3539

36-
* If the response is a count, we can use Poisson regression
40+
* If the outcome is a count,
41+
we can use Poisson regression.
3742

38-
* If the count has a higher variance than is consistent with the Poisson, we can use a negative binomial or over-dispersed Poisson
43+
* If count data exhibit greater variance than assumed under the Poisson model,
44+
we can use negative binomial regression or overdispersed Poisson models.
3945

40-
* Other forms of response can generate other types of generalized linear models
46+
* Other outcome structures correspond to other families within the generalized linear model framework.
4147

42-
We need a linear predictor of the same form as in linear regression $\beta x$. In theory, such a linear predictor can generate any type of number as a prediction, positive, negative, or zero
48+
In generalized linear modeling, we specify a linear predictor $\eta \eqdef \reglincomb$ of the same form as in linear regression.
49+
In principle, a linear predictor can yield any real value,
50+
whether positive, negative, or zero.
4351

44-
We choose a suitable distribution for the type of data we are predicting
45-
(normal for any number, gamma for positive numbers, binomial for binary responses, Poisson for counts)
52+
We then select an appropriate outcome distribution matched to the data type
53+
(for example, Gaussian for unbounded continuous values,
54+
gamma for positive continuous quantities,
55+
binomial for binary outcomes,
56+
and Poisson for counts).
4657

47-
We create a link function
48-
which maps the mean of the distribution
49-
onto the set of all possible linear prediction results,
50-
which is the whole real line ($-\infty, \infty$).
51-
The inverse of the link function takes the linear predictor to the actual prediction.
58+
Finally, we specify a link function $g(\cdot)$
59+
that maps the expected outcome $\mu \eqdef \E{Y \mid \vX = \vx}$
60+
onto the real line $(-\infty, \infty)$ of the linear predictor.
61+
The inverse link function $g^{-1}(\cdot)$
62+
transforms the linear predictor back to the scale of the expected outcome.
5263

53-
* Ordinary linear regression has identity link (no transformation by the link function) and uses the normal distribution
64+
* Standard linear regression uses the identity link function $g(\mu) \eqdef \mu$
65+
and assumes a Gaussian response distribution.
5466

55-
* If one is predicting an inherently positive quantity, one may want to use the log link since ex is always positive.
67+
* When predicting an inherently positive outcome,
68+
a log link function $g(\mu) \eqdef \logf{\mu}$ is often appropriate,
69+
since $\expf{\eta} > 0$ for all real $\eta$.
5670

57-
* An alternative to using a generalized linear model with a log link is to transform the outcome using the log transformation. This outcome transformation works well with positive measurement data and may be usable in other continuous cases, but it cannot be used directly for 0/1 binary data or for count data that may be 0.
71+
* An alternative to fitting a generalized linear model with a log link
72+
is to apply a log transformation directly to the outcome.
73+
While log-transforming the outcome works well for positive continuous measurements,
74+
it cannot be applied directly to binary outcomes or to count outcomes that can equal zero.
5875

5976
Family | Links
6077
------ | ------

chapters/time-to-event-models.qmd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ In many health sciences applications, binary outcomes are *incompletely observed
1515
For example, if we are studying whether cancer patients experience a relapse after an initial remission,
1616
we may not be able to follow patients to the end of their lives;
1717
instead, we may only know whether each patient has relapsed before the end of the study.
18-
If a patient has not relapsed by that point, we might not know if they will relapse at some other date or if they will stay cancer-free for the rest of their lives.
18+
If a patient has not relapsed by that point,
19+
we might not know if they will relapse at some other date
20+
or if they will stay cancer-free for the rest of their lives.
1921
^[Binary outcomes are typically defined *for a specific time-point*.
2022
It is important to clearly define whether we are interested in outcome status at end of study, at end of life, or at some other time.]
2123
Their recurrence status at end-of-life is *missing data*.

0 commit comments

Comments
 (0)