Category Archives: knitr

The Curious Case of the TeX That Could

I have had, for approximately the last nine months, an R Studio/knitr/LaTeX problem. After spending several hours looking at it I have discovered that it was a TeX issue, and no fault of the other two. However, neither offered me any clue as to what was going on. I will detail this problem and the solution (TLDR: removed MikTeX and replaced it with TeXLive).

The problem

I am (co-)authoring another book. This one, like my data analysis book, is comprised of a master document with multiple child documents. The data analysis book was written with Emacs and Sweave, whereas this one is being written with R Studio and knitr. The problem I was having was that the book would compile fine on my Mac OS X machines, but under Windows I would get a message like Running pdflatex.exe on chapter04.tex...failed, and the PDF viewer would not launch. I initially tracked this down to the inclusion of the \makeindex command in my master document. In fact, through the use of a minimal example, I discovered that even after I took this command back out of the document, it would not compile until I deleted the auxiliary files created by LaTeX–in particular, the .idx file for the document.

I started to write a post for stackoverflow and in doing so, I decided I really should make sure that all my software was up-to-date. This, in turn, broke everything! It was, however, obvious that what was broken was MikTeX.

MikTeX – why hast thou forsaken me?

I have been a big fan of MikTeX for a very long time. It traditionally has been, at least for me, a really robust TeX installation for Windows. One of the features I really like is its “Install packages on-the-fly” mechanism, whereby it can automatically install any package that is on CTAN that it detects is missing when it tries to compile a document. This means that the initial install is quite minimal, and usually very fast. At some point in 2020 (or maybe even 2019—I wasn’t paying too much attention) MikTeX changed the way it works. In particular, it seemed to become quite finicky about installing package updates as an Administrator or as a User, and no matter what I did, I couldn’t get it to have those two modes in sync with each other. That is, MikTeX would complain that there were different versions installed for the Administrator than those installed for the User, and vice versa.

TeXLive – what fresh hell is this?

Given MikTeX seemed to be broken, I decided I would try and setup TeXLive. I did this for a couple of reasons. Firstly, MikTeX was pissing me off, and secondly, given I was trying to synchronise behaviour, I thought perhaps having the same TeX distribution as I have on my Macs might help. I have traditionally avoided TeXLive because it doesn’t have the “install on-the-fly” feature, it used to require a huge initial download (not that that really matters anymore) and it was a pain to keep up to date. On the Mac you don’t have a lot of choice about using it. TeXLive does offer a internet installer these days, however, something is seriously wrong with it. I tried three different repositories in three different countries, but each was looking like it would take nearly 24 hours to download and install the software. I got fed up, and downloaded a 3.8GB ISO using a torrent in about five minutes. Windows 10 has a very nice feature which allows an ISO to be treated like a regular drive, and so I could run the installer straight off the ISO. Even so, the install took over 12 minutes which seems excessive on a core-i9 machine with 32GB of RAM, and an SSD but it worked. I then rather foolishly decided I should run the TeXLive Manager and update my installation. This process took 3 hours and 39 minutes!! I have no idea why it was so slow, but I have seen a lot of complaints about this on the net.

So it worked

So the problem was MikTeX. I still don’t know exactly what the issue was, but finally I can compile my book on my Windows machines again. I did have to install a custom class file for the book, but that was rather straightforward compared to the rest. And now I have wasted the rest of my day with writing a blog post. I do sincerely hope that it helps someone!

Share Button

F*ck you LaTeX

Some of you know that I have agreed to finish the textbook started by my good friend David Lucy who died far too young in 2018. After some heroic efforts by our publisher Taylor and Francis, I now have a set of LaTeX files that match the last coherent PDF file that David gave our editor, Rob Calver, before he was unable to work any more.

I set about converting this rather large, monolithic file into my normal workflow of a master knitr file, with child files for each of the chapters. As you might expect, when writing a book you often want to compile the chapter you are working on, rather than the whole document. This is especially true with this book, because I would like the JAGS code to be executed whilst the chapter is being compiled, and with nearly twenty chapters, this could take some time.

Again, this process is fairly straightforward. However, when compiling a chapter, the paths have to be relative to the folder the chapter is in, rather than to the master document. This means that if you provide paths for figures, code listings, or the bibliography, then these need to be changed when you only want to compile the chapter, or when you want to compile the whole book. After a bit of reading, I thought I should be able to do this in LaTeX itself as it is a programming language (or at least a macro language) of sorts—boy was I wrong!.

The basic solution to the problem is as follows:

  1. Define a logical variable to indicate whether you are working with the whole book or just the chapter in the master document and set it to TRUE or FALSE as needed.
  2. In each child document, set the paths so that they are relative to the chapter, or the book according to the value of the logical variable.

LaTeX does not have a logical type, but it does have a numeric type in the form of a counter. So step one can be done using the following commands:

%%%%% Are you working with individual chapters
\newcounter{local}
\setcounter{local}{1} %1 = TRUE 0 = FALSE

Step two, in theory is straightforward as well. Here is an example from my first chapter. This goes in my preamble:

\ifnum\value{local}=0{
  \graphicspath{{chapters/chapter01/figures/}}
  \lstset{inputpath=chapters/chapter01/R/}
}
\else{
  \graphicspath{{figures/}} 
  \lstset{inputpath=R/}
}\fi

and this appears at the end of the chapter

\ifnum\value{local}=1{
  \bibliography{../../bibliography/jags-references}
}\fi

We have to make sure that the bibliography is included if the whole book is compiled, so this gets added to the position where we would like the bibliography to appear in the master document:

\ifnum\value{local}=0{
  \bibliography{bibliography/jags-references}
}\fi

Seems fine right? Does it work? No. It seems to half work. Sometimes it works for the chapter, sometimes for the book, but the switching is never seamless.

James, you are an idiot

So remember how I said I was working with knitr? The solution of course is to use a well-defined (N.B. I am not going to argue the merits of R being a real programming language or not, but it is one used by real programmers!) programming language—R—and get knitr to print out the right LaTeX code. It took a tiny bit of fooling about to remember how to do this, but the essence is R chunks with chunk options echo=FALSE and results='asis' to make sure knitr does not try to mark up our LaTeX. So these two chunks appear in my master document:

<<R-master-chunk,echo=FALSE>>=
### Set this to true if compiling chapters only
compileChapterOnly = FALSE
@

and

<<R-set-bibpath-master,echo=FALSE,results='asis'>>=
cat("\\bibliography{bibliography/jags-references.bib}\n")
@

with the latter placed where I need the bibliography to appear.

And these two chunks are placed in each child document:

<<R-set-local-paths-ch01,echo=FALSE,results='asis'>>=
if(compileChapterOnly){
  cat("\\graphicspath{{figures/}}
                     \\lstset{inputpath=R/}\n")
}else{
  cat("\\graphicspath{{chapters/chapter01/figures/}}
  \\lstset{inputpath=chapters/chapter01/R/}\n")
}
@

and

<<R-set-local-bibpath-ch01,echo=FALSE,results='asis'>>=
if(compileChapterOnly){
  cat("\\bibliography{../../bibliography/jags-references}\n")
}
@

Note that each chunk in the child document has a chapter specific chunk tag, just to avoid duplicate tags when I compile the whole book.

I am pretty sure someone will point out my elementary LaTeX mistake, but then again there is not enough space in my head for understanding how all of LaTeX works. After all, I do have to get this book written (and not write blog posts).

Share Button