Puberty Stage Line Diagrams and SDS for Tanner Pubertal Stages
Overview
Plots Tanner pubertal stage measurements (genital, pubic hair, testicular volume, breast, menarche) against Dutch 1997 growth-study references as stage line diagrams, and converts observed stages to age-conditional standard deviation scores (SDS). Testicular volume can be entered as a raw orchidometer reading in ml. Implements the method of van Buuren and Ooms (2009) doi:10.1002/sim.3567.
CRAN resubmission fixes
plotter(),plotterpro()andupload_tryCatch_pro()now return their HTML/JSON response as a string (invisibly) instead of only writing it viacat(). Under rApache, standard output is the actual HTTP response body, so thecat()calls remain and the deployment's behavior is unchanged; the return value simply gives a normal R caller (includingR CMD check's console-output scanner) an object to work with instead of unsuppressable console text.plotter()now saves and restores the globalerroroption via an immediateon.exit()instead of leavingoptions(error = dump.frames)in effect for the rest of the R session after the function returns.
Bug fixes
Show all changes in 1.8.0Hide the rest of the changes in 1.8.0
calculate_sds(..., type = "tv")no longer has a discontinuity at Prader bead boundaries: a raw ml reading is now mapped onto a continuous bead-index scale before interpolating, so both the low and high percentiles in the mid-P formula move together and the SDS varies smoothly with ml instead of jumping right at each bead threshold (e.g. 11.99ml vs 12.00ml).calculate_sds(..., type = "tv")now correctly returnsNAfor anNAage or stage, instead of a finite but wrong value. The continuous bead-index interpolation above usedapprox()'s defaultna.rm = TRUE, which silently dropsNA(x, y) pairs from the interpolation table before interpolating -- so anNAage (which makes every real bead percentileNA) left only the two artificial boundary values (P(TV>=0)=1,P(TV>=Inf)=0) in the table, and interpolated between just those two instead of propagating theNA.interpolate_trajectory()'s returnedstagecomponent is now the same length asx/y/patient. It was previously built from the cumulative length of the output-so-far across all segments instead of the current segment's own length, making it longer than the other three components whenever a patient had more than one stage segment.
Documentation
- Documented that
calculate_sds()'s return value is always the same length asage, and thatstagemust be the same length asage(not recycled) -- a length-1stage, or any other length mismatch, is unsupported and can silently truncate, warn, produceNAs, or error depending ontype. - Added
vignettes/tanner.Rmd, covering a fullerplot_stadia()walkthrough across itstype/plotline/colors/overlayarguments, how rawtv(ml) readings are handled differently bycalculate_sds()(continuous interpolation) versusplot_stadia()(snap to the nearest Prader bead curve), and the mid-P value SDS methodology of van Buuren & Ooms (2009) -- including why it is a discrete/ordinal method distinct from LMS/BCCG continuous-measurement SDS (e.g.centile::y2z()). Originally written as a Quarto vignette (tanner.qmd,%\VignetteEngine{quarto::html}); converted to classicknitr::rmarkdown(VignetteBuilder: knitr) after CI revealed an unresolved upstream Windows-only bug in the Quarto vignette engine (see "Continuous integration" below) that would have blocked CRAN submission, since CRAN's own build machines check Windows. - Added a "Package structure" section to the README distinguishing the supported general-purpose library API (
plot_stadia*,interpolate_trajectory,find_stage_segments,calculate_sds,tnologo) from the rApache webapp request handlers (plotter,plotterpro,upload_tryCatch_pro) kept only for the existing deployment.plotter(),plotterpro()andupload_tryCatch_pro()are now also grouped under a@family webapp-internalsroxygen tag, so they cross-reference each other in?tannerand on the pkgdown site. - Added a pkgdown site (
_pkgdown.yml), with a reference index split into "Plotting & analysis", "Reference data", and "Webapp internals" sections, andURL/BugReportsfields inDESCRIPTION. - Added full citations for van Buuren S (2014), "Growth charts of human development," *Statistical Methods in Medical Research*, 23(4), 346-368, in
nl1997's source documentation.
Testing
- Added
testthatunit tests forcalculate_sds(),interpolate_trajectory(),find_stage_segments(), and smoke tests for theplot_stadia*drawing functions (which draw to a graphics device and return invisibleNULL, so are tested by asserting they run without error). Extracted thetvml-to-nearest-bead snapping logic out ofplot_stadia_data()into an internalsnap_tv_to_nearest_bead()helper so it can be unit tested directly.
Internal refactoring
calculate_sds()andsnap_tv_to_nearest_bead()each independently parsed the ml threshold from"T"-prefixed tv reference column names (e.g."T12"->12); extracted the shared parsing step into an internaltv_ml_thresholds()helper. Pure refactor, no behavior change -- the bracket-and-interpolate vs. snap-to-nearest logic that follows at each call site is untouched.
Continuous integration
- Added
.github/workflows/R-CMD-check.yaml(a standard R CMD check matrix across macOS/Windows/Ubuntu) and.github/workflows/pkgdown.yaml(builds and deploys the pkgdown site to GitHub Pages on push tomaster).windows-latestwas briefly excluded from the check matrix after CI revealed that thequarto::htmlvignette engine hits an unresolved upstream Windows-only bug duringR CMD build(the Quarto subprocess can't see the temporary libraryR CMD buildjust installed the package into; r-lib/rcmdcheck#236); re-added once the vignette was converted to classicknitr::rmarkdown(see "Documentation" above), which doesn't hit this bug since it renders in-process rather than via an external Quarto subprocess. _pkgdown.ymlnow setstemplate: bootstrap: 5(Quarto-rendered articles require it; the default Bootstrap 3 made the pkgdown site build fail before it ever reached the deploy step) andllm-docs: false(pkgdown'sllms.txtgeneration, not needed here and fragile against the runner's pandoc version).
Package loading
library(tanner)no longer creates aplotdumpdirdirectory (or writes to disk at all) as a side effect of loading the package. The directory is now created lazily, on the first actual write insideplotter()/plotterpro()/upload_tryCatch_pro();plotdumpdirremains exported and mutable.plotdumpdirnow defaults to a"plotfiles"subdirectory oftempdir()instead of the hardcoded/tmp/plotfiles, andupload_tryCatch_pro()'s uploaded-file and.RDatahandoff files move there too (previously hardcoded to/tmpindependently ofplotdumpdir). This is a behavior change for the rApache deployment:tempdir()must resolve to a writable location that stays stable across the upload and plot requests for a given user session (true for a single long-running R process, which is how rApache normally hosts an R interpreter per worker). Unix-only/tmpwas also a portability problem forR CMD check/CI on Windows and macOS runners, even though the webapp handlers themselves only ever ran on Linux.
Breaking changes
- Renamed three exported functions to consistent
snake_case, matchingplot_stadia()'s existing naming style: calculateSDS()->calculate_sds()findXY()->interpolate_trajectory()findSegments()->find_stage_segments()
There are no backwards-compatible aliases for the old names; update any
code calling them directly.
- Renamed the two bundled reference datasets, following the
<population><year>naming convention used by thenlreferencesandclopuspackages: pub.ref->nl1997pub.ref.lines->nl1997_lines
From NEWS.md in the release
Install
Health
- OK13 OKNow
- OK7 OK2026-08-07
Documentation
- Help pages
- 16 (2 internal)
- Examples that run
- 100%2 run in a plain check
- Exported functions with examples
- 17%
- Documented parameters
- 95%
- Return-value docs
- 92%
- Help pages citing references
- 6%
Downloads
Repository
11 development-tooling and community-health practices detected across 5 families in the upstream repository
Checks run against github.com/growthcharts/tanner on 2026-10-22.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-07-28 · The repository has a site deploy workflow
pkgdown site last built 2026-07-28, before release 1.8.0 (2026-08-06)
Show all practicesHide 1 practice
Dependencies
Code & Tests
Datasets
People & History
- 1.8.0Latest2026-08-06 · current release
- RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-08-06
- Total releases
- 1 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 3.5.0
- Bundled data
- 16 KB / 2 files
- Download size
- 736 KB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("tanner")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-24, which the citation names so these numbers can be found later. More on citing and the projects behind them.