How to solve "Error in proto(Geom, { : object 'Geom' not found"

516 views
Skip to first unread message

Brian Danielak

unread,
Jan 30, 2012, 10:17:46 AM1/30/12
to ggplo...@googlegroups.com
Hi Everyone,

In our package we introduce one new geom: an alternate rug-plot that puts the rug marks on the top and right sides of the graph (instead of the default bottom and left). Trouble is, right now when I try to run check() on my package it fails almost immediately with the following error:

Error in proto(Geom, { : object 'Geom' not found

Below is my current geom_rug_alt() code. Note that that's the geom code in its entirety. If there's code I need to put somewhere else in order to get this to work, please let me know:

geom_rug_alt <- function(mapping = NULL,
                         data = NULL,
                         stat = "identity",
                         position = "identity",
                         ...
                )
{
  GeomRugAlt$new(mapping = mapping,
              data = data,
              stat = stat,
              position = position,
              ...
  )
}

GeomRugAlt <- proto(
  Geom, {
    objname <- "rug_alt"

    draw <- function(., data, scales, coordinates, ...) {
      rugs <- list()
      data <- coordinates$transform(data, scales)
      if (!is.null(data$x)) {
        rugs$x <- with(data, segmentsGrob(
          x0 = unit(x, "native"), x1 = unit(x, "native"),
          y0 = unit(1 - 0.03, "npc"), y1 = unit(1, "npc"),
          gp = gpar(col = alpha(colour, alpha), lty = linetype, lwd = size * .pt)
        ))
      }

      if (!is.null(data$y)) {
        rugs$y <- with(data, segmentsGrob(
          y0 = unit(y, "native"), y1 = unit(y, "native"),
          x0 = unit(1, "npc"), x1 = unit(1 - 0.03, "npc"),
          gp = gpar(col = alpha(colour, alpha), lty = linetype, lwd = size * .pt)
        ))
      }

      gTree(children = do.call("gList", rugs))
    }

    default_stat <- function(.) StatIdentity
    default_aes <- function(.) aes(colour="black", size=0.5, linetype=1, alpha = 1)
    guide_geom <- function(.) "path"
  }
)


Hadley Wickham

unread,
Jan 30, 2012, 10:25:53 AM1/30/12
to ggplo...@googlegroups.com
Hi Brian,

In the short term, use ggplot2:::Geom. In the long term (at least a
year probably), all the proto is going away, and geoms will use S3.

Hadley

--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

Brian Danielak

unread,
Jan 31, 2012, 11:37:05 AM1/31/12
to ggplo...@googlegroups.com
Hi Hadley,

I made your suggested fix (see Line 38). Now my package successfully installs, but any call to my custom geom fails.

#Reproducible example assuming you have ggplot2 v0.9.0
library(devtools)
install_github(repo="granovaGG", username="briandk", branch="ggplot2-v0-9-fix")
library(granovaGG)
qplot(cty, hwy, data = mpg) + geom_rug_alt()

The above code yields the following error:
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  attempt to apply non-function

Not sure what I'm doing wrong or how to fix it.

Hadley Wickham

unread,
Jan 31, 2012, 11:48:04 AM1/31/12
to ggplo...@googlegroups.com
What does traceback give you? It may be that the internals have changed slightly.

Hadley
--
Sent from my iPhone

Hadley Wickham

unread,
Jan 31, 2012, 11:48:26 AM1/31/12
to ggplo...@googlegroups.com
Oh and does it work outside a package?

Hadley

On Tuesday, January 31, 2012, Brian Danielak <brian.d...@gmail.com> wrote:

Brian Danielak

unread,
Feb 2, 2012, 1:01:20 AM2/2/12
to ggplo...@googlegroups.com
I've done some testing, and here are the results. All tests were against this version of granovaGG.

Under ggplot2 v0.8.9
  • granovaGG passes R CMD check when using the check() function of devtools
  • load_all("granovaGG") works fine
  • after load_all("granovaGG") and library(ggplot2), I can call qplot(cty, hwy, data = mpg) + geom_rug_alt() which works fine
Under ggplot2 v 0.9.0

check("granovaGG") fails at the examples section:

* checking examples ... ERROR
Running examples in 'granovaGG-Ex.R' failed
The error most likely occurred in:

> ### Name: geom_rug_alt
> ### Title: Alternate Marginal Rug Plot Geom for ggplot2
> ### Aliases: geom_rug_alt
> ### ** Examples
> p <- ggplot(mtcars, aes(x=wt, y=mpg))
> p + geom_point() + geom_rug()     # traditional rug fringe placement
> p + geom_point() + geom_rug_alt() # alternate fringe placement
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  attempt to apply non-function
Calls: print ... <Anonymous> -> lapply -> FUN -> <Anonymous> -> <Anonymous>
Execution halted
Error: Command failed (1)

And, after load_all("granovaGG") or library(granovaGG), qplot(cty, hwy, data = mpg) + geom_rug_alt() also fails:

> qplot(cty, hwy, data = mpg) + geom_rug_alt()
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  attempt to apply non-function

Here's the backtrace:

> dsmall <- mpg[1:2, c("cty", "hwy")]
> qplot(cty, hwy, data = dsmall) + geom_rug_alt()
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  attempt to apply non-function
> traceback()
21: get(x, envir = this, inherits = inh)(this, ...)
20: .$draw(group, scales, coordinates, ...)
19: FUN(X[[1L]], ...)
18: lapply(groups, function(group) .$draw(group, scales, coordinates, 
        ...))
17: get(x, envir = this, inherits = inh)(this, ...)
16: function (...) 
    get(x, envir = this, inherits = inh)(this, ...)(data = data, 
        scales = scales, coordinates = cs)
15: do.call(.$geom$draw_groups, c(data = list(as.name("data")), scales = list(as.name("scales")), 
        coordinates = list(as.name("cs")), .$geom_params))
14: get(x, envir = this, inherits = inh)(this, ...)
13: layer$make_grob(df, scales = panel$ranges[[panel_i]], cs = plot$coord)
12: .fun(piece, ...)
11: function (i) 
    {
        piece <- pieces[[i]]
        if (.inform) {
            res <- try(.fun(piece, ...))
            if (inherits(res, "try-error")) {
                piece <- paste(capture.output(print(piece)), collapse = "\n")
                stop("with piece ", i, ": \n", piece, call. = FALSE)
            }
        }
        else {
            res <- .fun(piece, ...)
        }
        progress$step()
        res
    }(1L)
10: .Call("loop_apply", as.integer(n), f, env)
9: loop_apply(n, do.ply)
8: llply(.data = pieces, .fun = .fun, ..., .progress = .progress, 
       .parallel = .parallel)
7: dlply(layer_data, "PANEL", function(df) {
       panel_i <- match(df$PANEL[1], panel$layout$PANEL)
       layer$make_grob(df, scales = panel$ranges[[panel_i]], cs = plot$coord)
   }, .drop = FALSE)
6: function (layer, layer_data) 
   {
       if (nrow(layer_data) == 0) 
           return()
       dlply(layer_data, "PANEL", function(df) {
           panel_i <- match(df$PANEL[1], panel$layout$PANEL)
           layer$make_grob(df, scales = panel$ranges[[panel_i]], 
               cs = plot$coord)
       }, .drop = FALSE)
   }(dots[[1L]][[2L]], dots[[2L]][[2L]])
5: mapply(FUN = f, ..., SIMPLIFY = FALSE)
4: Map(build_grob, plot$layer, data)
3: ggplot_gtable(data)
2: print.ggplot(list(data = list(cty = c(18L, 21L), hwy = c(29L, 
   29L)), layers = list(<environment>, <environment>), scales = <S4 object of class "Scales">, 
       mapping = list(x = cty, y = hwy), options = list(labels = list(
           x = "cty", y = "hwy")), coordinates = list(limits = list(
           x = NULL, y = NULL), wise = FALSE), facet = list(shrink = TRUE), 
       plot_env = <environment>))
1: print(list(data = list(cty = c(18L, 21L), hwy = c(29L, 29L)), 
       layers = list(<environment>, <environment>), scales = <S4 object of class "Scales">, 
       mapping = list(x = cty, y = hwy), options = list(labels = list(
           x = "cty", y = "hwy")), coordinates = list(limits = list(
           x = NULL, y = NULL), wise = FALSE), facet = list(shrink = TRUE), 
       plot_env = <environment>))

Might it be something with the <environment>s in call 1?

Winston Chang

unread,
Feb 2, 2012, 1:45:05 AM2/2/12
to ggplo...@googlegroups.com
OK, I couldn't resist trying out a bisect script on this one.

Download this script and save it in your ggplot2 directory as granova_test.r:
The code at the top is a set of functions that's destined to go in devtools; the interesting stuff is at the bottom.
This script installs ggplot2 from your source tree time it's run, and then runs the test with geom_rug_alt.

The script assumes that, relative to your ggplot2 directory, your granovaGG directory is at ../granovaGG. If it isn't, edit the script to correct the path.

Then, in your ggplot2 directory, run this:
chmod +x granova_test.r
git bisect reset
git bisect start master remotes/origin/ggplot-0.8.9
git bisect run granova_test.r


It'll run a bisect on ggplot2, marking any commits that successfully print the graph as good, and any that throw an error as bad. It ended up with this result:
===========
6ba21aee4e99f6c1888d7c8732bbf5257749b160 is the first bad commit
commit 6ba21aee4e99f6c1888d7c8732bbf5257749b160
Author: hadley <h.wi...@gmail.com>
Date:   Fri May 20 07:35:40 2011 -0500

    Convert coord to S3
===========

You can view the changes made in this commit with:
  git diff 6ba21 6ba21^
... or of course you can look at it on Github


Once you're all done with this, make sure to re-install whatever version of ggplot2 you were using before.

I find it pretty amazing that, even though I know almost nothing about your problem, the script can track down where it came from.

-Winston

Winston Chang

unread,
Feb 2, 2012, 2:03:08 AM2/2/12
to ggplo...@googlegroups.com
Now for some more traditional debugging... If you run options(error=recover), you'll be able to enter into the call stack when an error comes up.

Run the following:
library(devtools)
dev_mode(TRUE)
options(error=recover)
load_all("../granovaGG")
library(ggplot2)
qplot(cty, hwy, data = mpg) + geom_rug_alt()   

At this point, you'll see stuff like this:
====================
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  attempt to apply non-function

Enter a frame number, or 0 to exit   

 1: print(list(data = list(manufacturer = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 2: print.ggplot(list(data = list(manufacturer = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 3: ggplot_gtable(data)
 4: Map(build_grob, plot$layer, data)
 5: mapply(FUN = f, ..., SIMPLIFY = FALSE)
 6: function (layer, layer_data) 
 7: dlply(layer_data, "PANEL", function(df) {
 8: llply(.data = pieces, .fun = .fun, ..., .progress = .progress, .parallel = 
 9: loop_apply(n, do.ply)
10: function (i) 
11: .fun(piece, ...)
12: layer$make_grob(df, scales = panel$ranges[[panel_i]], cs = plot$coord)
13: get(x, envir = this, inherits = inh)(this, ...)
14: do.call(.$geom$draw_groups, c(data = list(as.name("data")), scales = list(a
15: function (...) 
16: get(x, envir = this, inherits = inh)(this, ...)
17: lapply(groups, function(group) .$draw(group, scales, coordinates, ...))
18: FUN(X[[1]], ...)
19: .$draw(group, scales, coordinates, ...)
20: get(x, envir = this, inherits = inh)(this, ...)

Selection: 
====================

Type in 19 to enter at the call to .$draw. Then you can see what it's doing. The get(x, .....) function returns a function.
====================
Selection: 19
Called from: top level 
Browse[1]> get(x, envir = this, inherits = inh)
function(., data, scales, coordinates, ...) {  
      rugs <- list()
      data <- coordinates$transform(data, scales)    
      if (!is.null(data$x)) {
        rugs$x <- with(data, segmentsGrob(
          x0 = unit(x, "native"), x1 = unit(x, "native"), 
          y0 = unit(1 - 0.03, "npc"), y1 = unit(1, "npc"),
          gp = gpar(col = alpha(colour, alpha), lty = linetype, lwd = size * .pt)
        ))
      }  

      if (!is.null(data$y)) {
        rugs$y <- with(data, segmentsGrob(
          y0 = unit(y, "native"), y1 = unit(y, "native"), 
          x0 = unit(1, "npc"), x1 = unit(1 - 0.03, "npc"),
          gp = gpar(col = alpha(colour, alpha), lty = linetype, lwd = size * .pt)
        ))
      }  

      gTree(children = do.call("gList", rugs))
    }
<environment: 0x1033de0b0>
====================

You can also look at str(this) and str(list(...)). Anyway, it's somewhere within this function is where it dies. (And it looks like this function is in geom_rug_alt.r.)

If you exit to the browser selection thing again by pressing 'c' or just Enter, then you can go into 20, which is this function. Once you're in there, you can look around with ls() and other commands like that.

From a little exploration, it looks like it's dying on the second line:
data <- coordinates$transform(data, scales)

The problem is that coordinates$transform is NULL. That syntax, obj$blah, is the syntax used by proto. But, as noted in my other email, the commit that broke everything is the one where coord was converted from proto to S3.

If you take a look at the new version of geom-rug.r, you'll see the new syntax is:
data <- coord_transform(coordinates, data, scales)

You may want to examine the new geom-rug.r and see if there are any other changes that you need to copy over to geom_rug_alt.r.

Good luck!
-Winston
 

Winston Chang

unread,
Feb 2, 2012, 2:10:11 AM2/2/12
to ggplo...@googlegroups.com
One quick thing about the bisect testing. Once you're all done, make sure to run:
 git bisect reset

Otherwise git will probably be unhappy when you try to do other stuff.

Reply all
Reply to author
Forward
0 new messages