Skip to content

Restore y-axes for non-default plotting directions and fix the linear fixture padding - #191

Merged
whelena merged 2 commits into
mainfrom
hwinata-fix-axis-regression
Aug 17, 2026
Merged

Restore y-axes for non-default plotting directions and fix the linear fixture padding#191
whelena merged 2 commits into
mainfrom
hwinata-fix-axis-regression

Conversation

@whelena

@whelena whelena commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

main is currently red. devtools::test() on 9acc0c4 gives 310 pass / 2 fail / 1 error. This gets it to 337 pass / 0 fail / 0 error.

Why it broke

Commit db616d9 (PR #190) added a guard to add.axes():

if (plotting.direction != 'down') {
    message('Non-vertical plotting direction detected; skipping (nSNV) x-axis rendering.');
    yaxis.position <- 'none';
    }

Three problems:

  • The comment and message say x-axis, but the body sets yaxis.position, removing the y-axes. The x-axis is controlled separately by draw.xaxis on the line above.
  • It fires for every plotting.direction other than 'down', not just horizontal ones.
  • plotting.direction != 'down' compares numeric against character, so R coerces 30 to "30" and numeric angles trip it too.

Measured on a tree with two length columns:

direction before #190 after #190
down 2 axes 2
up / left / right 2 0
30 / 45 2 0

plotting.direction is a 3.0.0 feature, so every non-default orientation lost its scale. It also broke test-linear.R's 30-degree case with a subscript-out-of-bounds error, because compare.trees walks a grob list whose length had changed.

This was not caught because the R CMD check workflow has been disabled_inactivity since 2026-04-06, and PR #190 was opened 2026-05-18. It was never checked by CI. mergeable: clean only ever meant "no merge conflict".

What this PR does

e628e4a replaces the guard with the narrow behaviour that was intended. Adds is.horizontal.direction() to classify named and numeric directions without string coercion, threads add.polygons through from make.clone.tree.grobs so suppression is scoped to fish plots rather than orientation alone, and demotes yaxis.position from 'both' to 'left' so only the second (nSNV) scale is dropped.

test-axis-plotting-direction.R covers all six directions, numeric-vs-named equivalence, a horizontal fish plot keeping its first y-axis, and a non-fish horizontal tree keeping both. Note fish.data.Rda has no length columns (get.y.axis.position returns 'none'), so it cannot exercise the nSNV suppression — the test builds a tree with both CP and two length columns.

aac2e67 fixes the linear fixture. It used horizontal.padding = -1, which squeezed the plot until the gene annotations collapsed into unreadable specks and the tick labels crowded over the polygon — the "test plots are not right" symptom in #186. Sweeping the parameter: -1 and 0 crush the annotations, 1 and 2 render them cleanly, 3 pushes the axis titles off the edge. Uses 1, keeping the pre-#190 layout (PGA left, SNV right, ticks outside) with space between polygon and axes. TP53/CDKN2A/CSMD1/FHIT/TERT/MYC and NOTCH1/SOX2/TP63/PIK3CA/EGFR are legible again.

Snapshots regenerated. Comparing every stored grob against its predecessor with compare.trees confirms only two changed semantically: linear.example (this padding change) and fish.example (the CCF axis is now flush with the polygon instead of overhanging, which is what "make axes flush against polygon" in #190 set out to do). The other nine are unchanged, so the regeneration accepted nothing silently.

Two fixes to update-snapshots.R were needed to run it at all:

  • pkg.root used dirname(sys.frame(1)$ofile), which only resolves under source(). Invoked the documented way — Rscript tests/update-snapshots.Rsys.frame(1) raised not that many frames on the stack and the script died before loading the package. Now resolves --file= first, falling back to sys.frames()[[1]]$ofile, then getwd().
  • devtools::load_allpkgload::load_all. devtools is not in Suggests and only re-exports load_all from pkgload.

Verification

Run in a container built from ghcr.io/uclahs-cds/boutroslabplottinggeneral:7.1.0 plus testthat/pkgload/covr/knitr/rmarkdown/withr, since R CMD check is still disabled.

before (9acc0c4):  PASS 310 | FAIL 2 | ERROR 1
after  (aac2e67):  PASS 337 | FAIL 0 | ERROR 0

Not addressed here

Pre-existing, reproduces on pre-#190 ab3359f, out of scope:

  • plotting.direction = 'left' produces two grobs both named axis.left.
  • plotting.direction = 'up' silently loses its left y-axis with a No y-axis ticks to draw warning.
  • The CP x-axis label still overlaps its 0.53% tick — part of the Disproportionate y-axis2 to y-axis2 label spacing #183 cluster.

Suggest re-enabling the R CMD check workflow once this merges, so its first run lands green.

Refs #186

db616d9 added a guard to add.axes():

    if (plotting.direction != 'down') {
        message('Non-vertical plotting direction detected; skipping (nSNV) x-axis rendering.');
        yaxis.position <- 'none';
        }

Its stated goal was to drop the nSNV axis on horizontal fish plots, but it had
three problems:

  * The comment and message say "x-axis" while the body sets yaxis.position,
    which removes the Y-axes. The x-axis is controlled separately by
    draw.xaxis on the line above.
  * It fired for every plotting.direction other than 'down', not just
    horizontal ones.
  * `plotting.direction != 'down'` compares numeric against character, so R
    coerced 30 to "30" and numeric angles tripped it as well.

Measured on a tree with two length columns, axis count went from 2 to 0 for
'up', 'left', 'right', 30 and 45, leaving only 'down' with any y-axis at all.
plotting.direction is a 3.0.0 feature, so this removed the scale from every
non-default orientation. It also broke test-linear.R's 30-degree case with a
subscript-out-of-bounds error, because the comparison walks a grob list whose
length had changed.

Replace it with the narrow behaviour that was intended: when a fish plot is
drawn horizontally, demote yaxis.position from 'both' to 'left' so only the
second (nSNV) scale is dropped. Add is.horizontal.direction() to classify
named and numeric directions without string coercion, and thread add.polygons
through from make.clone.tree.grobs so the suppression is scoped to fish plots
rather than to orientation alone.

test-axis-plotting-direction.R covers all six directions, the numeric-vs-named
equivalence, the horizontal fish plot keeping its first y-axis, and a non-fish
horizontal tree keeping both.

Note: fish.data.Rda has no length columns, so it cannot exercise the nSNV
suppression; the test builds a tree that has both CP and two length columns.
test-linear.R built its plot with horizontal.padding = -1. That squeezed the
plot area until the gene annotations collapsed into unreadable coloured specks
and the axis tick labels crowded over the polygon -- the "test plots are not
right" symptom in issue #186. The fixture was the only place a negative
horizontal padding was exercised, so nothing else caught it.

Sweeping the parameter shows -1 and 0 both crush the annotations, 1 and 2
render them cleanly outside the polygon, and 3 pushes the axis titles off the
edge. Use 1, which keeps the pre-#190 layout (PGA left, SNV right, ticks
outside the plot) while leaving space between the polygon and the axes. The
gene labels TP53/CDKN2A/CSMD1/FHIT/TERT/MYC and NOTCH1/SOX2/TP63/PIK3CA/EGFR
are legible again.

Regenerate the snapshots. Comparing every stored grob against its predecessor
with compare.trees confirms only two changed: linear.example (this padding
change) and fish.example (the CCF axis is now flush with the polygon rather
than overhanging it, which is what "make axes flush against polygon" in #190
set out to do). The other nine are unchanged, so the regeneration accepted
nothing silently.

Two fixes to update-snapshots.R were needed to run it at all:

  * pkg.root used dirname(sys.frame(1)$ofile), which only resolves under
    source(). Invoked the documented way -- Rscript tests/update-snapshots.R --
    sys.frame(1) raised "not that many frames on the stack" and the script died
    before loading the package. Resolve the path from --file= first, fall back
    to sys.frames()[[1]]$ofile, then getwd().
  * Swap devtools::load_all for pkgload::load_all. devtools is not in Suggests
    and merely re-exports load_all from pkgload.
@whelena
whelena merged commit 9ba5dfb into main Aug 17, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant