HARPgroup / HARParchive

This repo houses HARP code development items, resources, and intermediate work products.
1 stars 0 forks source link

Unreliability of knitr::include_graphics #1183

Open glenncampagna opened 4 months ago

glenncampagna commented 4 months ago
rburghol commented 4 months ago

@COBrogan - if the only difference is to remove the message() calls, seems like an easy fix, but I thought I'd ping you in case you had experience with understanding the why of this.

COBrogan commented 4 months ago

I've just opened a pull request with my recommended fix. See pr #1186 . I'll merge this in later today once you've all had a chance to take a look.

As with all things markdown, this is a complicated issue because of the translation from R to pandoc to word. After messing around for a bit, I confirmed @glenncampagna's suspicions. The include_graphics() call always fails if it is wrapped in an if statement (or likely a loop) if there is something below it it in the same statement. After doing some digging, I found this post by Yihui Xie (who wrote all of R markdown, knitr, etc.). He confirms that include_graphics() must be a "top-level expression". I was a little unfamiliar with what this meant, but found a second post by Yihui that cleared it up.

Essentially, if statements in R always return and print the last piece of code passed to them. So, the following displays fine since it is return and printed by the if statement.

if(show_map){
  knitr::include_graphics("JL6_7430_7320_facils_wsp2020_2040_mgy.png") #display map(s) PNG -- not functional inside
}

However, the code in question below, does not as the nested if statement (which occurs after the include_graphics() call) returns nothing and thus the entire statement returns and prints nothing, blocking the inclusion of the map.

if(show_map){
  knitr::include_graphics("JL6_7430_7320_facils_wsp2020_2040_mgy.png") #display map(s) PNG -- not functional inside loop
  if (mapMessage) {
    message("The metric requested does not exist for this map.")
    message("Check your syntax/spelling. If correct, then this data has not been measured/modeled")
  }
}

But, the following code would work since the include_graphics() call is returned by the if statement:

if(show_map){
  if (mapMessage) {
    message("The metric requested does not exist for this map.")
    message("Check your syntax/spelling. If correct, then this data has not been measured/modeled")
  }
  knitr::include_graphics("JL6_7430_7320_facils_wsp2020_2040_mgy.png") #display map(s) PNG -- not functional inside loop
}

To prevent this, we need to use include_graphics() in top-level expressions only and avoid using it in nested if statements or for loops. The use of apply functions can get us around the loop issues (with the benefit of being more executionally efficient) and we can avoid nesting if by making better use of the eval chunk option (as I did in my pull request)