Skip to main content

The PreTeXt Guide

Subsection 4.14.3 Images Described by Source Code

There are various languages which may be used to describe diagrams, geometric objects, or data plots. A key strategy enabled by PreTeXt is to put these specifications of such images directly in your document’s source rather than losing track of them over time.
So we have various elements which are children of <image> that hold these source code descriptions. Then PreTeXt provides techniques for realizing these in the best formats for various devices and print. So if you are accustomed to the idea of a @source attribute pointing to a file, think of these elements as alternative specifications.

Subsubsection 4.14.3.1 Asymptote

Asymptote 1  is a vector graphics language that produces high-quality output in WebGL, SVG, PNG, and PDF formats. You can describe 2-D or 3-D objects, and the 3-D objects are interactive in online output as HTML WebGL files. may be used, and your macros are automatically available for use.
Authoring is straight-forward. Inside an <image> include a child <asymptote> to hold the code. For example:
<image xml:id="gaussian-histogram">
    <description>A histogram of Gaussian data.</description>
    <asymptote>
    import graph;
    import stats;

    size(400,200,IgnoreAspect);

    int n=10000;
    real[] a=new real[n];
    for(int i=0; i < n; ++i) a[i]=Gaussrand();

    draw(graph(Gaussian,min(a),max(a)),blue);

    // Optionally calculate "optimal" number
    // of bins a la Shimazaki and Shinomoto.
    int N=bins(a);

    histogram(a,min(a),max(a),N,normalize=true,low=0,lightred,black,bars=false);

    xaxis("$x$",BottomTop,LeftTicks);
    yaxis("$dP/dx$",LeftRight,RightTicks(trailingzero));
    </asymptote>
</image>
Here is the result. Look elsewhere for examples of 3-D output from Asymptote.
Notes:
  • Notice the necessity of escaping the less-than in the for-loop. See Subsubsection 4.1.4.2.
  • Setting a @xml:id is necessary to have a stable name for graphics files that will be generated.
  • The <description> is an important part of making your output accessible.
  • Notice the use of for the label on the vertical axis. All of your macros defined in docinfo are available for use, so you can keep notation consistent.
  • You need to produce PDF versions of your diagrams for use in a conversion to .
  • You need to produce HTML versions of your diagrams for use in a conversion to an electronic format based on HTML. For a 2-D diagram these are a thin wrapper around an SVG image. For a 3-D diagram these are interactive WebGL objects.
    It is very important to note that these HTML versions contain the height and width of the diagram and these are queried by a conversion of your document to HTML format in order to compute the aspect ratio. Therefore they need to be available with your other source files (typically in an images directory). So in a very real sense these files become part of your source.
  • You may want to produce SVG versions of your diagrams for conversion to EPUB, and PNG versions for conversion to the EPUB precursor for Kindle format.
  • PDF versions produced by the pretext script will not include the RPC extensions. So “rotatable” 3D images rendered by the proprietary viewer, Adobe Acrobat, are not created, consistent with our open source philosophy.
  • Colors in Asymptote can be hard-coded using rgb syntax. Colors can also be defined at the top of an Asymptote file, to be referred to later. You may wish to produce PDF in both color (electronic) and black and white (print on demand) formats, and you probably do not want to maintain parallel source for both versions. Rather than writing (for example) pen p=rgb(0,0,.7); in your Asymptote code, you can write pen p=curvepen1;. Then, in the <docinfo> section of your document, you can add an <asymptote-preamble> and include the line pen curvepen1=rgb(0,0,.7);. Once you are ready to produce your black and white version, you need only change the definition of curvepen1 in your <asymptote-preamble>.
    One note of caution: if your preamble includes Asymptote code that only works once certain libraries are loaded, you must include lines to import those libraries in your preamble. For example, to define a material you must first have the line import three;.
Asymptote may be run as a program installed locally, but the project also has an on-demand online server written by Supakorn Jamie Rassameemasmuang. By default, the pretext/pretext script (Chapter 47) will interface automatically with this server to create your diagrams. Furthermore, Asymptote provides a very useful web application 2  written by Pedram Emami. This is a great place to learn, experiment, and iterate as you become more skilled at building high-quality graphics to illustrate the concepts in your document.

Best Practice 4.14.3.1. Build 3-D Asymptote Figures.

If your project uses geometric or mathematical objects that are three-dimensional, invest some time in learning the Asymptote vector graphics language. The interactive diagrams for your HTML output produced by Asymptote, in WebGL format, are outstanding and will greatly enhance your project. (And the other static formats are similarly excellent.) The pretext/pretext script will create these diagrams, in the necessary formats, with no extra software by using an online server.

Subsubsection 4.14.3.2 Images in Syntax

There are a variety of packages for authoring a diagram, plot, or graph. Examples include: TikZ, PGF, Xy-pic, and PSTricks. Generally, the <latex-image> tag allows you to incorporate this code into your source and PreTeXt realizes these descriptions as images in your output.
For output the procedure is transparent—PreTeXt simply incorporates the preamble information and the image’s code in the correct places in the output, scaled to fit whatever space is described on the <image> element. Then traditional processing will do the right thing. For output to other non- formats, such as HTML or EPUB, we need some help from the CLI to generate other formats. This tool will isolate the image’s code and bundle it up with the necessary preamble to make a complete single-purpose file. Once converted by to a PDF version, other tools can convert the image into other formats, such as SVG. In this way, you can use packages for describing images, use mathematically-correct labels in syntax, and use your own macros for consistency in notation, yet also employ the resulting images in more modern output formats. Note that as of 2020-07-24, limited testing indicates that PSTricks needs to be processed with the xelatex engine, and the pstricks-add package might also be necessary. Any updates, especially using pdflatex would be appreciated. Finally, processing with xelatex might be necessary if your labels use Unicode characters.
Much like the <asymptote> tag, the <latex-image> tag is used as a child of <image> and can be thought of as an alternative to the @source attribute of <image>. The contents need to be a complete specification of the image. For example, a TikZ image will typically begin with \begin{tikzpicture}. Inside of your document’s <docinfo> you will likely need to employ a <latex-image-preamble> element to hold necessary \usepackage commands and any global settings, such as the style for tick-marks and labels on axes of graphs. The source code in this next example is greatly abbreviated and mildly edited, see the source for the complete example.
<docinfo>
    <latex-image-preamble>
    \usepackage{tikz}
    </latex-image-preamble>
</docinfo>
<figure>
    <caption>RNA Codons Table, by Florian Hollandt</caption>
    <image xml:id="rna-codons-table" width="100%">
        <description>A table of the RNA codons.</description>
        <latex-image>
        \begin{tikzpicture}
        \footnotesize
        \tikzstyle{every node}=[inner sep=1.7pt,anchor=center]
        % to_x and from_x styles denote bonds terminating
        % or starting in labeled nodes. x denotes the
        % number of letters in the node label.
        \tikzstyle{to_1}=[shorten >=5pt]
        \tikzstyle{to_1i}=[shorten >=6pt]
        \tikzstyle{to_2}=[shorten >=7pt]
        \tikzstyle{to_3}=[shorten >=8pt]
        ...
        \begin{scope}[scale=0.5]    % Asparagine
        \draw[ultra thick,shorten >=2pt,shorten &lt;=2pt] (90-2*5.625:8.2)
                        arc(90-2*5.625:90-4*5.625:8.2);
        \path (90-3.5*3.625-3:13.3) node (zero) {};
        \draw[to_2]  (zero.center)  -- ++(30:1) node (CO) {}
                        -- +(330:1) node [anchor=base] {O$^{\mbox{-}}$};
        \draw[to_1]  (CO.center)    -- +(90:1) node (Od) {O};
        \draw[to_1i] (CO.30)        -- +(90:1);
        \draw[to_3]  (zero.center)  -- ++(150:1) node {NH$_{\mbox{3}}^{\mbox{+}}$};
        \draw[to_2]  (zero.center)  -- ++(270:1) node(Cb){}
                        -- ++(330:1) node (Cc) {}
                        -- +(30:1) node (Cd) {NH$_{\mbox{2}}$};
        \draw[to_1i] (Cc.center)    -- +(270:1) node (O) {};
        \draw[to_1]  (Cc.210)       -- (O.150);
        \path (O.center) node {O};
        \end{scope}
        ...
        \node at (90-55*5.625:4.5) {C};
        \node at (90-58*5.625:4.5) {S};
        \node at (90-61*5.625:4.5) {L};
        \node at (90-63*5.625:4.5) {F};
        \end{tikzpicture}
        </latex-image>
    </image>
</figure>
This will result in:
A table of the RNA codons, together with the amino acids they encode.
Figure 4.14.3.2. RNA Codons Table, by Florian Hollandt, from ample.net 3 

Subsubsection 4.14.3.3 Scaling TikZ Images

Images authored in TikZ 4  are the most popular. Text (nodes) in a TikZ picture are at whatever the current font size is. The other parts of the picture (lines, circles, rays, etc.; the “line art”) can be scaled as part of an overall scale factor. The point being, the scale factor will not scale the text simultaneously. It is not unlike a map application on your mobile device. The name of a road is too small to read, so you zoom in on the map, making the street bigger, but the name stays in the same font size and is still unreadable. This means some manual labor is involved when you place a TikZ picture into a PreTeXt document.
For many authors, the goal is to have the text in their TikZ picture have the same size as the surrounding text, both in a PDF and in HTML. We now explain how to accomplish this consistently.

Preparation.

Well before designing many TikZ images, answer the following questions.
  1. For your output, what will the overall font size be?
  2. For your output, what will the width of the text block be? Note that this will normally be computed by PreTeXt, dependent on your chosen font size. A larger font will mean a greater width. You can generate the source file and look early in the preamble to see what width is being used. It is also possible that you may be setting this with yourself (Section 30.6). The ratio of line width to font size is always \(34:1\text{.}\)

TikZ in .

Every image in PreTeXt may be constrained by width and/or margins, or may be restricted to a panel of a <sidebyside> with a certain width. So the TikZ code you author will create an image that is then scaled by PreTeXt to fit the constraints (much as any other image is scaled). Except this is done in a way that scales both the font and the line art. Your main goal is to have this scaling use a scale factor of \(1.0\text{.}\) Which, of course, sounds like a waste of effort, but it is critical for how the image behaves in HTML (next).
To accomplish this unit scaling, follow this procedure for each TikZ picture.
  1. Determine the width of the TikZ picture itself, in physical units of length. Typically, the lengths used for larger portions are described in centimeters. But note that an overall scale factor is sometimes applied for convenience (or as a result of poor planning!). Also, the default unit length (centimeters) can be changed. Note also, that text may “push out” to the right and left, defining the boundaries on the sides, and these lengths can be hard to compute or predict.
  2. Recall the width of your text (above). Recognize that list items will be indented (reducing width), and perhaps there are multiple indents if a list has multiple levels.
  3. Now you want the width of your picture as a percentage of the overall available width. By default, your overall width will be points, and your picture width will be in centimeters. You may be familiar with a “big point” (or “desktop publishing point”) which is \(72\) points to the inch. however uses \(72.27\) points to the inch, which makes a point equal to \(0.03514598\) centimeters. Convert to whatever common unit makes sense to you, since it is the dimension-less ratio you are after.
  4. Use this percentage as the @width attribute on the <image> (with a percent sign).
Now produce a PDF and you will find that the font in the surrounding text, and the font in image, will match identically. I like to check this carefully by zomming in on the PDF and using an on-screen pixel ruler to check the heights of identical letters. KRuler 5  is one such example for Linux, suggestions for other operating systems are welcome.
Note that in practice you will envision your picture as large or small, and you will begin with some overall physical width in mind, relative to the line width.

TikZ in HTML.

For HTML output, the goal is to not edit your source. In other words to not change the @width attributes that have been so carefully computed and to not edit the TikZ code. But you will want to maintain fidelity with the surrounding font.
HTML output is designed to behave very similarly (not identically) to how output behaves. In other words, the ratio of line width to font size is \(34:1\text{.}\) In this way, line length and font size are such that a long paragraph will usually have an identical number of lines in (at any font size) and in HTML.
Our tools produce Scalable Vector Graphics (SVG) versions of TikZ pictures for use in HTML output. Being scalable means a reader can zoom in without any pixelation of the images. This is helpful for those with low vision, or if some fine point of a picture needs to be examined closely. It also means an SVG can be scaled by any factor when placed in PreTeXt HTML. However, the work done for a unit scaling for output will continue to provide the correct scaling for HTML! (Provided the text width used for the PDF production is the one automatically computed from the font size via the \(34:1\) ratio.)
The PreTeXt source below describes a simple TikZ picture, nd is followed by the picture itself. The rectangle is 8 centimeters wide. The Guide is produced as a PDF with 10 point text and a text width of \(6.5\) inches. (This is too wide for comfortable reading, and contrary to our recommendations. See Best Practice 30.6.0.1.) Normally, a choice of 10 point text would result in a width of \(340\) point, or about \(4.7\) inches.
So we compute the fraction of the available width required, as a percentage:
\begin{equation*} \frac{8\text{ cm}}{6.5\text{ in}} = \frac{8\text{ cm}\left(\frac{1\text{ in}}{2.54\text{ cm}}\right)}{6.5\text{ in}} = 0.4846 = 48.46\% \end{equation*}
and we use that as the width of the image.
<image xml:id="scaling-tikz" width="48.46%">
    <latex-image>
    \begin{tikzpicture}
    % 1 cm is default unit of length
    % a rectangle: 8 cm wide, 6 cm tall
    \draw[draw=black, thick] (4,2) rectangle (-4,-2);

    \node at (-2,  1) {Foo};
    \node at ( 2,  1) {Bar};
    \node at (-2, -1) {Baz};
    \node at ( 2, -1) {Qux};
    \end{tikzpicture}
    </latex-image>
</image>
Some characters for comparison: Foo  Bar  Baz  Qux
In the PDF version, the text matches between the image and the surrounding text almost identically. We could slide the image right and left by adjusting the margins (the default is to be centered). But if we want the image bigger and smaller, we need to adjust the TikZ code and recompute the @width attribute.
Now for HTML we need to produce an SVG version that is a close match. The HTML version is a close match for built with a computed text width (for any font size). We do not want to change the percentage of the width devoted to the TikZ picture, and we do not want to change the TikZ code itself. If we had not chosen a different text width (the \(6.5\) inches, versus a computed \(340\) point), then we could generate the SVG by supplying the same publication file, so as to use the same font size. However, our text width is 38% larger in the version,
\begin{equation*} \frac{6.5\text{ in}}{340\text{ pt}} = \frac{6.5\text{ in}\left(\frac{72.27\text{ pt}}{1\text{ in}}\right)}{340\text{ pt}} = 1.3816 \end{equation*}
The font size needs to increase by a similar percentage,
\begin{equation*} 10\text{ pt}\times 1.3816 = 13.816\text{ pt}\approx 14\text{ pt} \end{equation*}
So we generate the SVG image with a different publication file, giving a font size of 14 point. The HTML font in the text may be very different from the font used in the TikZ picture, but their sizes are nearly identical. Note that our use of only supports 8 different font sizes, so it was fortuitous in this example that the 38% increase was so close to the supported 14 point font size. Note also, that since we used a different text width for the PDF, the resulting 40% increase in the font size for the SVG could play havoc with text that has been placed carefully not to overlap other components of the picture.
There are myriad ways to scale and transform a TikZ picture. You might choose to intentionally use a smaller font size than the surrounding text, as in Figure 4.14.3.2. Or, fidelity with the surrounding text might not be important to you. Or you might prefer that images perform better in HTML. But hopefully the above discussion and example provide enough insight into how the various constructions behave. The important points are:
  • TikZ uses physical units for the overall width of a picture, and nodes have text using the ambient font size of the PreTeXt file (unless prescribed otherwise).
  • PreTeXt scales a TikZ picture uniformly (text and line art) to fit into constraints given in the source.
  • The SVG version of a TikZ picture is also uniformly scalable and at the same width as the original will have text of the correct font size. However, when used in HTML output, it is scaled on the assumption that the ratio of the line width to the font size is 34:1. This is the default width computed by PreTeXt for all supported font sizes. Changes in this ratio for PDF production requires an equivalent change in font size during SVG construction, via the publication file.

Subsubsection 4.14.3.4 Images in Sage Syntax

Sometimes the necessary computations for an image are not part of the capabilities of whatever system is actually realizing the image. We have good support for Sage in other parts of your document, and Sage has an extremely wide variety of computational capabilities, in addition to letting you program your own computations in Python syntax with the full support of the Sage library. Rather than translating Sage output as input to some other graphics program, we simply capture the graphics output from Sage. So if your graphics are derived from non-standard, or intensive, computation this might be your best avenue.
Use the <sageplot> element, in a manner entirely similar to the <asymptote> element and the <latex-image> element, as a child of <image>, and containing the necessary Sage code to construct the image. There is one very important twist. The last line of your Sage code must return a Sage Graphics object. The pretext/pretext script (Chapter 47) and PreTeXt-CLI (Section 5.2) will isolate this last line, use it as the right-hand side of an assignment statement, and the Sage .save() method will automatically be called to generate the image in a file. Note that there are four different file types, depending on if the graphic is 2D or 3D, and the output format of the conversion.
The @variant attribute of the <sageplot> element may be 2d or 3d, since PreTeXt is not capable of analyzing your Sage code. The default value is 3d so can be skipped for 2D plots. For technical reasons, it is also necessary to specify the aspect ratio of a graphic for the 3D case using the @aspect attribute. The value can be a positive real number (decimal) or a ratio of two positive integers separated by a colon. The default is a square (1.0 or 1:1).
Table 4.14.3.4. File formats for sageplot images
2D 3D
PDF PNG
HTML SVG HTML (for iframe)
Note that the PNG images in the 3D case are not very good. This needs help on the Sage side. And since 3D images in HTML output are inserted via an HTML iframe they can misbehave if you do not get the aspect ratio close to right. On the plus side, the 3D HTML images may be manipulated interactively with keyboard arrow keys, a mouse scroll wheel, and by dragging with a mouse using both a left and a right mouse press.
Pay very careful attention to the requirement that the last line of your code evaluates to be a graphics object. In particular, while show() might appear to do the right thing during testing, it evaluates to Python’s None object and that is just what you will get for your image. The example below illustrates creating two graphics objects and combining them into an expression on the last line that evaluates to the graphics object that will be created in the desired graphics files.
<figure>
    <caption>Negative multiple of a curve</caption>
    <image xml:id="negative-curve" width="65%">
        <description>Plot of x^4 - 1 and its negative.</description>
        <sageplot>
        f(x) = x^4 - 1
        g(x) = -x^4 + 1
        up = plot(f, (x, -1.5, 1.5), color='blue', thickness=2)
        down = plot(g, (x, -1.5, 1.5), color='red', thickness=2)
        up + down
        </sageplot>
    </image>
</figure>
This will result in:
Plot of x^4 - 1 and its negative.
Figure 4.14.3.5. Negative multiple of a curve
Note the necessity of using the pretext script (Chapter 47) to independently invoke Sage, no matter what sort of output is being created for your document.
asymptote.sourceforge.io/
asymptote.ualberta.ca/
texample.net/tikz/examples/rna-codons-table/
github.com/pgf-tikz/pgf
apps.kde.org/kruler/