Making tikz graphcs consistent (svg vs pdf)

43 views
Skip to first unread message

Oscar Levin

unread,
Jul 28, 2016, 12:59:02 PM7/28/16
to MathBook XML Support
I am have a rough time getting images generated from my tikz to look right on the html side.  I believe the issue is with the scaling of the generated svg's, a topic that has been raised on this group before, but I was unable to find a helpful resolution.  

For an example of what I'm talking about see the first two examples here: http://discretetext.oscarlevin.com/draft/dmoi/sec_intro-functions.html.

You will notice that in the first example, the numbers in the arrow diagram are a little bigger than the surrounding text.  This is despite my setting the width of the image to 25%.  In the second example, all the text is way too small, but the width is set to 50%.  This is not a bug, I realize that the latter is due to the images being side-by-side, but if I decide to switch a pair of images to side-by-side, I don't want to have to refactor the width by trail and error.

That's what I find myself doing now quite a bit.  I smudge the widths over and over until I get it right.  This seems very counter to the mbx philosophy.

It is not just text though: in the solution to example 2, you will notice two diagrams with vertices.  The width on these is equal (set to 50%) but this causes the images to look like they are different sizes, as the vertices are different sizes.  Of course in the pdf, tikz does not have this problem and everything looks right.

Does anyone have any ideas here?  I am thinking that it would be nice to have the size of svg's default to the "natural" size (the size you would get if you generated a pdf).  I realize this might be technically difficult, so any work-around ideas to save me from this constant tinkering would be much appreciated.

Oscar.  

Bob Plantz

unread,
Jul 28, 2016, 1:35:31 PM7/28/16
to mathbook-x...@googlegroups.com

On Thu, Jul 28, 2016 at 9:59 AM, Oscar Levin <oscar...@gmail.com> wrote:
refactor the width by trail and error.


Having to do the same html adjustments myself, your typo (or perhaps it was intentional?) here created an appropriate pun. It is sort of like walking down a trail, not knowing exactly where it will take you next. :-)

--Bob

Alex Jordan

unread,
Jul 28, 2016, 1:44:18 PM7/28/16
to MathBook XML Support
Hi Oscar,

Your second image is not wrapped in a figure, and the first one is. I think the first thing to do is put the second image in a (captionless) figure.

There is an inherent flaw with with how we are making svgs from pdfs. Ideally, some elements of the pdf should be singled out (text, math content, arrow head size) and be coded into the svg with the appropriate css to make their sizes match the size of the ambient text. Perhaps in the future there will be a tex package that will allow us to go directly from the tikz source to such an svg. But not at present.

I take the following approach to this issue.
  • Do not put width= anywhere in the local code for individual images.
  • Put the following into docinfi/latex-image-preamble:
    \pgfplotsset{every axis/.append style={width = {ifthenelse(.9\linewidth>200pt,200pt,.9\linewidth)}}}

    What this does is, for the print output, pgfplots image aim to be 200pt wide. But when they are in a sidebyside that is too narrow for that, they will aim to be 90% of the \linewidth. I'm going for making the 200pt approximately match the 90% of a two-panel sidebyside. This way most images are the same size, and images in 3-panel sidebysides will be acceptably sized. You may want to play with the "200pt" and "90%" to meet your needs.
  • By doing this, all pdf images created by the mbx script will use the 200pt sizing, and so when the svgs looked at individually, they are all size-compatible.
  • For HTML, make it so that all your single-panel images have the same width as a two-panel sbs image. Now all images in both classes will be compatibly sized.
  • Lingering issues. They won't necessarily have font that is exactly the same size as the ambient text from the HTML. And for sbs with 3 or more panels, there will be shrinkage. I've found this not to be an issue.
  • As mentioned above, images like the ones you have that are not in a sbs probably should be in a figure, and then some of the automated size handling on figures helps.

Oscar Levin

unread,
Jul 28, 2016, 3:46:45 PM7/28/16
to MathBook XML Support
Hi Alex,

Thanks for the suggestions, but they are not working for me.  I tried removing widths on the individual images and enclosing all in figures.  Putting the "\pgfplotsset{every axis/.append style={width = {ifthenelse(.9\linewidth>200pt,200pt,.9\linewidth)}}}" in the latex-image-preamble had no effect though.  I don't really understand the command, but perhaps your images have "axis" elements that are getting scaled?  Mine do not.  Here for example is the tikz code from one of my pictures:

\begin{tikzpicture}[scale=0.75]
      \draw[thin, gray!50] (0,0) grid (3.5, 3.5);
      \draw[->, thick] (0,0) -- (0,3.5);
     \draw[->, thick] (0,0) -- (3.5,0);
     \fill (1,2) circle (3pt) (2,1) circle (3pt) (3,3) circle (3pt);
    \end{tikzpicture}]

Of more general concern (and again, I'm just guessing at what your proposed command would do) is that I do not want all my images to be the same size, just have the same sized components.  For example, in my graph theory section I will have graphs with lots of vertices close to smaller graphs.  The larger graph will take up more width of the page than the smaller one, but the size of the each individual vertex should be (roughly) the same.  Does this make sense?

Another way to go perhaps: is it possible to tell the xsl script to look for png's instead of svg's?  I know these do not scale, but at this point this would be a benefit, accessibility not withstanding.

Oscar. 

Alex Jordan

unread,
Jul 28, 2016, 5:08:20 PM7/28/16
to MathBook XML Support
    ... had no effect though.


Before getting to the main issues, I want to check that you are re-generating the images. After making such changes, you have to re-run the mbx script to produce new image files, and then also make sure that they are uploaded to the right place. Re-running xsltproc alone won't change certain things (which I have been guilty of forgetting, so I wanted to check).



     I don't really understand the command, but perhaps your images have "axis" elements that are getting scaled?  Mine do not.  


Yes, you're right. Your first image made me think "Cartesian" and my mind went straight to pgfplots. A suggested approach for your situation outlined below.


    \begin{tikzpicture}[scale=0.75]
         
\draw[thin, gray!50] (0,0) grid (3.5, 3.5);
         
\draw[->, thick] (0,0) -- (0,3.5);
         
\draw[->, thick] (0,0) -- (3.5,0);
         
\fill (1,2) circle (3pt) (2,1) circle (3pt) (3,3) circle (3pt);
       
\end{tikzpicture}]





So I am assuming that you have not globally changed the length of x-units and y-units for tikz drawing, which is 1cm by default. When you say (0,3.5), that will be 3.5 cm upward from (0,0). Side note: if it will ultimately be more convenient, you can change this with something like
\tikzset{x=2cm,y=1.5cm}
in your docinfo/latex-image-preamble. I would recommend only setting these globally (if at all) to better control consistency in your project.

I recommend avoiding the scale=0.75 option for resizing a tikz image. If that 0.75 varies from image to image, this is one of the things that will make your dots vary in size from image to image. It simplifies the balancing act if you stop worrying about this. If you want a different sized image, you use one with a different range of x- and y-values. With these two images below in a .tex file, the latter will be 0.75 as big in both dimensions just by virtue of having all the coordinates scaled by 0.75. Note the circle radii are not rescaled by 0.75. [Using scale=0.75 does rescale those radii.]

\begin{tikzpicture}

     
\draw[thin, gray!50] (0,0) grid (3.5, 3.5);

     
\draw[->, thick] (0,0) -- (0,3.5) node{Hello};

     
\draw[->, thick] (0,0) -- (3.5,0);
     
\fill (1,2) circle (3pt) (2,1) circle (3pt) (3,3) circle (3pt);
   
\end{tikzpicture}

   
   
   
\begin{tikzpicture}
     
\draw[thin, gray!50] (0,0) grid (3.5*0.75, 3.5*0.75);
     
\draw[->, thick] (0,0) -- (0,3.5*0.75) node{Hello};
     
\draw[->, thick] (0,0) -- (3.5*0.75,0);
     
\fill (1*0.75,2*0.75) circle (3pt) (2*0.75,1) circle (3pt) (3*0.75,3*0.75) circle (3pt);
   
\end{tikzpicture}



I get it that all those *0.75 are irritating. So if you insists, keep using scale=0.75, but then you need to draw your dots (and maybe other things?) in a scale-independent way. Like:
\draw (1,2) node[fill,circle,minimum size=3pt] {};
This way the radius is not coordinate-based and so will be unaffected by scale=0.75. I'd even package this into a macro up in latex-image-preamble so that you could do something like:
\draw (1,2) soliddot;
But off the top of my head I don't recall how you define such a macro.

Anyway, for your book, I recommend mapping out coordinates of points  based on how they will land in the print edition, literally interpreting 3.5 as 3.5cm, etc. Always be able to tell from looking at your code what the width in cm will be in your print version. And stay conscious of things like the dot radii which you do not want to rescale with use of scale=.

Now, how to get the images to be properly sized in HTML? First, a primer: If you give the surrounding image a width attribute, and we are talking about an image with latex-image-code in it, then the tex output will completely ignore that width attribute. It is only used in the tex end to scale an existing external image that will be pulled in via \includegraphics.

But the width attribute will be used faithfully in the HTML. At present there is no requirement to use a percentage width here, but since your users may use small screens it's recommended you plan with percentages. So you could plan that "100%" width corresponds to what "10cm" would be in your print book. Note, I'm not saying that 100% will equal 10cm in the HTML. Just establishing a baseline.

The second of the above examples can be seen to pretty close to 3.5*0.75 cm =  2.625 cm wide. It's actually a tiny bit more because the arrowhead on the y-axis sticks out more to the left. But it is reasonable to ignore that. So if you gave that image the attribute width="26.25%", it will be scaled just so in the HTML. Following a scheme like this throughout all of your coordinate-based tikz diagrams should make them appear consistent.

If the image in a sidebyside, you'll know that it your MBX source, and you need to pump up the percentage accordingly. Ignoring margins, padding, etc for now, you'd use an image with width="26.25%" if it were inside a sidebyside figure whose width was 50%.

  • Remember to recompile and if necessary, reupload images.
  • I already mentioned making a macro for your dots. Similarly, I'd make a style in latex-image-preamble for the axes here instead of direclty using [->, thick] over and over. And the same for the grid style.

If this doesn't work out, please post minimal MBX code (including latex-image-code) for two images that are supposed to be of different sizes but have same-sized elements. And put a third such image in there inside a sidebyside.



 

    Of more general concern (and again, I'm just guessing at what your proposed command would do) is that I do not want all my images to be the same size, just have the same sized components.  For example, in my graph theory section I will have graphs with lots of vertices close to smaller graphs.  The larger graph will take up more width of the page than the smaller one, but the size of the each individual vertex should be (roughly) the same.  Does this make sense?


    Another way to go perhaps: is it possible to tell the xsl script to look for png's instead of svg's?  I know these do not scale, but at this point this would be a benefit, accessibility not withstanding.


I think you would have the same issue but you can try. The raw, unembedded png probably looks exactly the same as the unembedded svg. And then the HTML/CSS positioning will stretch them in the same manner.

Alex Jordan

unread,
Jul 28, 2016, 5:22:55 PM7/28/16
to MathBook XML Support
If the image in a sidebyside, you'll know that it your MBX source, and you need to pump up the percentage accordingly. Ignoring margins, padding, etc for now, you'd use an image with width="26.25%" if it were inside a sidebyside figure whose width was 50%.

Doh. What I meant was:

If the image in a sidebyside, you'll know that it your MBX source, and you need to pump up the percentage accordingly. Ignoring margins, padding, etc for now, you'd use an image with width="52.5%" if it were inside a sidebyside figure whose width was 50%.

Oscar Levin

unread,
Jul 28, 2016, 5:58:16 PM7/28/16
to MathBook XML Support
Alex,

I appreciate all your tips: I'm learning a lot.

Before getting to the main issues, I want to check that you are re-generating the images. After making such changes, you have to re-run the mbx script to produce new image files, and then also make sure that they are uploaded to the right place. Re-running xsltproc alone won't change certain things (which I have been guilty of forgetting, so I wanted to check).

Yes, I did remember to do that (but a reasonable thing to check on: I recently spent an hour scratching my head because I forgot to save the source file before recompiling).

I recommend avoiding the scale=0.75 option for resizing a tikz image. If that 0.75 varies from image to image, this is one of the things that will make your dots vary in size from image to image. It simplifies the balancing act if you stop worrying about this. If you want a different sized image, you use one with a different range of x- and y-values. With these two images below in a .tex file, the latter will be 0.75 as big in both dimensions just by virtue of having all the coordinates scaled by 0.75. Note the circle radii are not rescaled by 0.75. [Using scale=0.75 does rescale those radii.]
 
I get it that all those *0.75 are irritating. So if you insists, keep using scale=0.75, but then you need to draw your dots (and maybe other things?) in a scale-independent way. Like:

\draw (1,2) node[fill,circle,minimum size=3pt] {};

Most of the time I have used the node for vertices for this very reason.  Some of my images are from quite a while ago.
 
Anyway, for your book, I recommend mapping out coordinates of points  based on how they will land in the print edition, literally interpreting 3.5 as 3.5cm, etc. Always be able to tell from looking at your code what the width in cm will be in your print version. And stay conscious of things like the dot radii which you do not want to rescale with use of scale=.

Now, how to get the images to be properly sized in HTML? First, a primer: If you give the surrounding image a width attribute, and we are talking about an image with latex-image-code in it, then the tex output will completely ignore that width attribute. It is only used in the tex end to scale an existing external image that will be pulled in via \includegraphics.

But the width attribute will be used faithfully in the HTML. At present there is no requirement to use a percentage width here, but since your users may use small screens it's recommended you plan with percentages. So you could plan that "100%" width corresponds to what "10cm" would be in your print book. Note, I'm not saying that 100% will equal 10cm in the HTML. Just establishing a baseline.

The second of the above examples can be seen to pretty close to 3.5*0.75 cm =  2.625 cm wide. It's actually a tiny bit more because the arrowhead on the y-axis sticks out more to the left. But it is reasonable to ignore that. So if you gave that image the attribute width="26.25%", it will be scaled just so in the HTML. Following a scheme like this throughout all of your coordinate-based tikz diagrams should make them appear consistent.

If I'm understanding your suggestion correctly, you are giving me a fairly easy way to calculate the width percentage I should put on each image.  This is certainly better than my guess and check approach, but it still strikes me as something that should happen automatically, in fact....
 
    Another way to go perhaps: is it possible to tell the xsl script to look for png's instead of svg's?  I know these do not scale, but at this point this would be a benefit, accessibility not withstanding.


I think you would have the same issue but you can try. The raw, unembedded png probably looks exactly the same as the unembedded svg. And then the HTML/CSS positioning will stretch them in the same manner.

...if you just call an image in html without any styling, it will present the image in its native dimensions, right?  So if png images get scaled to stretch to 100%, can we just turn this off?

Oscar.

Oscar Levin

unread,
Jul 28, 2016, 6:21:05 PM7/28/16
to MathBook XML Support
Alex

I just tried fixing all the images in a section using your "mathy" suggestion and it worked really nicely.  Thanks for the help.

Oscar.

Alex Jordan

unread,
Jul 28, 2016, 8:24:13 PM7/28/16
to MathBook XML Support

I just tried fixing all the images in a section using your "mathy" suggestion and it worked really nicely.  Thanks for the help.

Great! If more things come up I'd like to hear abut them. I'm trying to catalog best practices for working with latex-image-code in an MBX document, to put somewhere in the documentation. I use pgfplots so I hadn't thought much about tikz until this, so having to think more about these issues is important.

...but it still strikes me as something that should happen automatically...

If you don't specify width, I believe 90% is used by default. I think we want this default for jpgs and other externally made images. But perhaps for images coming from latex-image-code (and asymptote and sage?) we should do something else that respects the native width? But then again the native width is an absolute width. Do we really want to respect that on a small screen?  I wonder if CSS that made max-width=native width would be good, and otherwise used width=100%. I don't know how to achieve "max-width=native-width" though.

 

Dave Rosoff

unread,
Jul 28, 2016, 9:25:11 PM7/28/16
to MathBook XML Support
On Thursday, July 28, 2016 at 3:58:16 PM UTC-6, Oscar Levin wrote:
Alex,

I appreciate all your tips: I'm learning a lot.

Before getting to the main issues, I want to check that you are re-generating the images. After making such changes, you have to re-run the mbx script to produce new image files, and then also make sure that they are uploaded to the right place. Re-running xsltproc alone won't change certain things (which I have been guilty of forgetting, so I wanted to check).

Yes, I did remember to do that (but a reasonable thing to check on: I recently spent an hour scratching my head because I forgot to save the source file before recompiling).

If you are using Sublime Text, you can change a user setting: add the line

        "save_on_focus_lost": true,

to your User Settings file. Then whatever modified file you have open will save itself whenever you switch into another window or even another sublime tab. About once a month this comes back to bite me because I start making changes to a file, realize I really want to modify a copy, and hit File...Save As, which opens a dialog and saves the file over the original. The solution is to Undo your way back to the original, Save As, and then Redo back to the bottom of the stack.

This is why I kept forgetting to save people's files at the workshop.

Dave

Oscar Levin

unread,
Jul 29, 2016, 1:12:19 PM7/29/16
to MathBook XML Support
If you are using Sublime Text, you can change a user setting: add the line

        "save_on_focus_lost": true,

to your User Settings file. Then whatever modified file you have open will save itself whenever you switch into another window or even another sublime tab. About once a month this comes back to bite me because I start making changes to a file, realize I really want to modify a copy, and hit File...Save As, which opens a dialog and saves the file over the original. The solution is to Undo your way back to the original, Save As, and then Redo back to the bottom of the stack.

Awesome tip!  I'm using Atom instead of Sublime Text, but there is an equivalent setting.  Already saving me lots of headaches. 

Oscar.
Reply all
Reply to author
Forward
0 new messages