daqana / tikzDevice

A R package for producing graphics output as PGF/TikZ code for use in TeX documents.
https://daqana.github.io/tikzDevice
132 stars 26 forks source link

Problems when using custom class #197

Closed jarauh closed 4 years ago

jarauh commented 4 years ago

I am working with a knitr document (.Rnw) that uses a class file (svjour3.cls) that lies in the same directory as the main file. According to tikzDevice.pdf (page 34), when tikzDevice computes the font metrics, it works in a temporary directory. For this it tries to look for the class file, which, of course, it cannot find.

Workaround number one: I change the class using tikzDocumentDeclaration.

But that's not enough: Apparently, tikzDevice or knitr also copies the preamble from my file. But this preamble contains commands that only make sense with the correct class.

Workaround number two: I use tikzDocumentDeclaration to also define some bogus commands that I don't really need.

In total: options(tikzDocumentDeclaration = "\\documentclass{article}\n\\newcommand{\\smartqed}{}\n\\newcommand{\\journalname}[1]{}")

For the first problem, it would probably be good if I could specify manually a working directory in which I could put a copy of the class file. I guess the second problem is more of a knitr problem?

rstub commented 4 years ago

Have you tried to install the class file into a location where TeX will find it? The precise details for this will depend on the OS and TeX distribution you are using (c.f. TeX SE). For me (Linux with TeX Live) this would mean placing the file in a (sub-directory of) ~/texmf/tex/latex. I think most (all?) TeX distributions know the concept of a personal TEXMF tree (TEXMFHOME) that can be used for things like this.

For measuring the font dimensions it is crucial to use the exact same fonts that are also used for typesetting. It is easiest to assure this by using the same class and preamble.

jarauh commented 4 years ago

Thanks for the comment. This should probably work.

However, I am working on the file in a repository together with coauthors. Thus, to make this workaround work completely, I would need to tell all my coauthors how to install the style file.

I would prefer to have a solution within tikzDevice, e.g. an option to specify a directory in which to work. (But I could understand if that would not be a top priority for the tikzDevice-team).

jarauh commented 4 years ago

One more question: could you please tell how the preamble gets copied to the output? While the documentation tells how to set the document class, it does not tell how to control the preamble. Or did I miss it? How does knitr inject the preamble?

rstub commented 4 years ago

I am not sure right now where that happens. Can you provide a minimal example for this issue?

tdhock commented 4 years ago

I am having the same issue, which could be fixed if there was an easy way (option) to tell tikzDevice to do the compilation of the metrics.tex file in the current directory (where I have my custom style file) instead of the temporary directory. Would that be possible/easy to implement?

rstub commented 4 years ago

@tdhock Can you provide a minimal example? The solution for #198 might help here as well.

tdhock commented 4 years ago

Hi @rstub thanks for the quick feedback. I tried setting the TEXINPUTS environment variable as mentioned in that other issue. In principle that should solve my issue, and it does result in latex finding my custom class file, but it also causes another problem (can't find standard article.cls file). Here is the code I used:

setwd(tempdir())
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jsslogo.jpg", "jsslogo.jpg")
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jss.cls", "jss.cls")
options(tikzDocumentDeclaration="\\documentclass{jss}")
Sys.setenv(TEXINPUTS=getwd()) 
tikzDevice::tikzTest() 

Here is the output I got:

tdhock@maude-MacBookPro:~/projects$ R --vanilla < tikzDevice-bug.R

R version 3.6.2 (2019-12-12) -- "Dark and Stormy Night"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> setwd(tempdir())
> download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jsslogo.jpg", "jsslogo.jpg")
trying URL 'https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jsslogo.jpg'
Content type 'image/jpeg' length 22731 bytes (22 KB)
==================================================
downloaded 22 KB

> download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jss.cls", "jss.cls")
trying URL 'https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jss.cls'
Content type 'text/plain; charset=utf-8' length 15426 bytes (15 KB)
==================================================
downloaded 15 KB

> options(tikzDocumentDeclaration="\\documentclass{jss}")
> Sys.setenv(TEXINPUTS=getwd()) 
> tikzDevice::tikzTest() 

Active compiler:
    /usr/bin/pdflatex
    pdfTeX 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian)
    kpathsea version 6.2.3

Measuring dimensions of: A
Running command: '/usr/bin/pdflatex' -interaction=batchmode -halt-on-error -output-directory '/tmp/RtmpAL8bwd/tikzDevice6b3655990c01' 'tikzStringWidthCalc.tex'
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode

TeX was unable to calculate metrics for:

    A

Contents of TeX file tikzStringWidthCalc.tex:

\documentclass{jss}
\usepackage{tikz}

\usepackage[active,tightpage,psfixbb]{preview}

\PreviewEnvironment{pgfpicture}

\setlength\PreviewBorder{0pt}

\usepackage[T1]{fontenc}

\usetikzlibrary{calc}

\batchmode
\begin{document}
\begin{tikzpicture}
\node[inner sep=0pt, outer sep=0pt, scale=1] (TeX) {A};
\path let \p1 = ($(TeX.east) - (TeX.west)$),
    \n1 = {veclen(\x1,\y1)} in (TeX.east) -- (TeX.west)
    node{ \typeout{tikzTeXWidth=\n1} };
\end{tikzpicture}
\end{document}
Contents of log file tikzStringWidthCalc.log:

This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex 2020.1.7)  8 JAN 2020 07:36
entering extended mode
 restricted \write18 enabled.
 %&-line parsing enabled.
**tikzStringWidthCalc.tex
(/tmp/RtmpAL8bwd/tikzDevice6b3655990c01/tikzStringWidthCalc.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/tmp/RtmpAL8bwd/jss.cls
Document Class: jss 2015/09/01 3.0 jss class by Achim Zeileis

! LaTeX Error: File `article.cls' not found.

Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: cls)

Enter file name: 
! Emergency stop.
<read *> 

l.74 \RequirePackage
                    {graphicx,color,ae,fancyvrb}^^M 
Here is how much of TeX's memory you used:
 60 strings out of 494847
 1032 string characters out of 6179081
 46917 words of memory out of 5000000
 3478 multiletter control sequences out of 15000+600000
 3640 words of font info for 14 fonts, out of 8000000 for 9000
 59 hyphenation exceptions out of 8191
 16i,0n,17p,137b,9s stack positions out of 5000i,500n,10000p,200000b,80000s

!  ==> Fatal error occurred, no output PDF file produced!
> 
tdhock@maude-MacBookPro:~/projects$ 

edit: correct terminal output.

tdhock commented 4 years ago

btw the workaround I am currently using is to copy these files to a user-specific directory (~/texmf/tex) but that is sub-optimal in the case where there are several users working on the same project. Would be nice if the TEXINPUTS=getwd() thing worked, or something similar.

rstub commented 4 years ago

TEXINPUTS = getwd() is not enough, indeed. In #198 I suggested to include the current value along these lines:

setwd(tempdir())
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jsslogo.jpg", "jsslogo.jpg")
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jss.cls", "jss.cls")
options(tikzDocumentDeclaration="\\documentclass{jss}")
tex_inputs <- Sys.getenv("TEXINPUTS")
Sys.setenv(TEXINPUTS = paste(getwd(), tex_inputs, sep = .Platform$path.sep))
tikzDevice::tikzTest() 

On my system this does work. The crucial thing is that even when TEXINPUTS is unset before this, the new value will have a trailing : which tells the kpsearch library to also look into system directories.

Anyway, I will try to package this up properly and make a CRAN release soon.

rstub commented 4 years ago

BTW, another workaround (as suggested on r-devel) would be to use \documentclass[nojss]{jss}:

setwd(tempdir())
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jsslogo.jpg", "jsslogo.jpg")
download.file("https://raw.githubusercontent.com/tdhock/PeakSegFPOP-paper/master/jss.cls", "jss.cls")
options(tikzDocumentDeclaration="\\documentclass[nojss]{jss}")
tikzDevice::tikzTest() 
tdhock commented 4 years ago

thanks for the clarification. it would be great if you could include this fix in the next CRAN release.

rstub commented 4 years ago

fixed in #203

jarauh commented 4 years ago

Thanks @tdhock for providing a minimal example and thanks @rstub for fixing this.