The question is: where do you get these figures?
Prepared figures
If you have prepared figures and want to customize their rendering in the document, the best way is just to copy and paste (sorry) the code for their inclusion, and adjust parameters in place. I find it better for the reasons of
simplicity. What is the purpose of separating the "width" in one place and using that value in another one? It looks like an over-complication.
flexibility. What if for one figure you want to specify not only the width, but also another parameter? Functions are good for repeated things, but not so much for unique ones.
As I read pgfmanual for version 3.1.5b, Section 99.6, Attributes says:
Attributes can be set and read only inside methods, it is not possible to do so using an object handle.
Spoken in terms of traditional object-oriented programming, attributes are always private. You need to
define getter and setter methods if you wish to read or modify attributes.
Reading and writing attributes is not done using the “dot-notation” that is used for method calls. This
is mostly due to efficiency reasons. Instead, a set of special macros is used, all of which can only be used
inside methods.
So it looks a bit complicated (as the manual goes, TeX was not created with OOP in mind). If we return to the example by @marczellm above, I would note these lines:
\begin{tikzpicture}
\mystamp.apply(1,2)
\mystamp.apply(3,4)
\end{tikzpicture}
The problem for me is that there are no names of the attributes (like mystamp.apply(x=1,y=2)). For two coordinates one may guess, but if you have a bunch of properties of a figure, it will be very difficult to remember the order of all these parameters, and there will be many bugs if you decide to change them (e.g. add new ones). The same problem I can see with a solution by @schtandard
\setfigurestruct{testfig}{example-image-a}{A test image.}[fig:test]
- even though you can guess the meaning of different arguments, this is not evident from the first sight.
The code by @Phelype Oleinik looks great in this regard:
\newobj{Figure}
\addtoobj{Figure}{url}{example-image}
\addtoobj{Figure}{caption}{This is a figure.}
\addtoobj{Figure}{width}{0.5\linewidth}
\addtoobj{Figure}{label}{a_nice_label}
\plotfigure{\Figure}
See figure \ref{\Figure.label }
But a problem remains: are these 6 lines of code any better than a simple (and, as I said, more flexible) inclusion of a figure in 7 lines?
\begin{\figure}[hbtp]
\begin{center}
\includegraphics[width=0.5\linewidth]{example-image}
\caption{This is a figure.}
\label{a_nice_label}
\end{center}
\end{figure}
See figure \ref{a_nice_label}.
The OOP code would be better only if you plan to insert one figure several times. Othewise I'd use other solutions:
- if you want to reuse an attribute of one figure (probably you don't need to copy all its attributes?), create a variable and use that in the figure and in other places,
- if you want to reuse an attribute in all figures (say, the width), create a variable and use that for all figures (for example, if you decide later to adjust the width of all figures).
Generated figures
By generated I mean figures, attributes of which (data points on a plot, axis labels, etc.) were produced by a program. I do data analysis and create a lot of figures. I render them in TeX because of the resulting quality. However, TeX is not a language for general programming, so I have to pass computed parameters to its engine.
First I tried to input parameters to TeX during its run, but found that too complicated as their number grew. Then I went to rendering templates, and found that great.
In the very developed area of Web programming templates are used to render html pages with specific data from the program (see e.g. Django tutorials).
The same is possible with LaTeX (or any other text data).
I copy an example from a tutorial on a data analysis framework Lena (which I develop):
% histogram_1d.tex
\documentclass{standalone}
%%% include tikz, pgfplots, etc.
\begin{tikzpicture}
\begin{axis}[]
\addplot [
const plot,
]
table [col sep=comma, header=false] {\VAR{ output.filepath }};
\end{axis}
\end{tikzpicture}
%%%
The variable to be rendered here is \VAR{ output.filepath } (where output.filepath you provide through the context, which is a simple Python dictionary). A dictionary is an object and in jinja templates its keys (and subkeys) can be accessed as attributes.
Of course, more complicated examples are possible:
\BLOCK{ set var = variable if variable else '' }
\begin{tikzpicture}
\begin{axis}[
\BLOCK{ if var.latex_name }
xlabel = { $\VAR{ var.latex_name }$
\BLOCK{ if var.unit }
[$\mathrm{\VAR{ var.unit }}$]
\BLOCK{ endif }
},
\BLOCK{ endif }
]
...
The syntax \BLOCK or \VAR looks a bit verbose. It is easier-to-read for html templates, but for LaTeX it had to be changed so that it didn't mess with LaTeX code. However, I very rarely edit and see my templates: once they are general enough, you don't need to add something else.
Even though new constructs complicate LaTeX code, it still looks pretty explicit. Context attributes are read clearly (var.unit), and they won't be confused one for another (as could be with positional arguments).
It is fairly surprising that I didn't have to create any other templates for my 1-dimensional histograms. Even in more complicated cases when I want to add something (like a line) to the plot, I edit that single template: I can conditionally turn on some rendering only for specific plots (which is defined through the context, which I control easily). For 2d plots I use a separate template (because the code for rendering is somewhat different).
For more details about template rendering refer to Jinja 2 documentation or to Lena tutorial.
With all that said, even though I generate many figures in a program, I still do all other stuff manually. I select figures to be included in my documents. I write every caption myself. I also tune their attributes in the final document when needed. For an automatically generated report it would be different, but I would still write pretty much code to customize it, to make it better and more interesting to the reader (even if an occasional one).
labelon a second use of the data object. – remco Mar 29 '18 at 13:47\begin{figure}..., without creating a function that takes ~20 input arguments.In the example I gave it concerns a plot, but if something like this exists I would use it for many other things as well (tables being a particular example).
– ComboCosmo Mar 29 '18 at 14:06