There are lots of cases where I want to use some pictures generated by TeX in my TeXmacs document. However, it is very difficult to match the text sizes, both to the TeXmacs font size, and also between pictures. This ends up looking really bad/janky. Is there some way to scale TeX pictures based on an intrinsic metric (i.e., make 1cm in TeX match up to 1cm in TeXmacs)?
Matching TeX font size to TeXmacs font size
As far as I know it is necessary to calculate it.
This StackExchange post may help with that. You can use \the\ht0
for the height of the box.
I found a message on the TeXmacs mailing list with some suggestions for image inclusion, it has a pdf file attached (second link)
https://lists.texmacs.org/wws/arc/texmacs-users/2013-05/msg00073.html
The thing in the pdf relevant to your question, I think, is to inquire pdf dimensions with
pdfinfo <filename>.pdf
which will give the dimensions in points.
I would also be curious to know more detail about what you see. In the quick test I did with TikZ in the standalone class, TeXmacs automatically set the dimensions of the figure to the dimensions of the pdf.
Said this, let’s see if there are better answers.
To give a sensible answer we would need to know a bit more how you get these pictures in TeXmacs. If they are images you can anyway scale them to be real-size, I think, so that measurements match. Can you provide an example?
I’m not sure if this is what @olynch meant, but it would be nice to have a way to pass information on the font type, for example, to plugins. This way the style of the plot could be unified.
I’ve tried passing TeXmacs variables and output of <extern>
tags into a plugin session, but they get scrubbed somewhere before they reach the plugin. I haven’t yet figured out where this happens exactly.
@jeroen, I’m not sure the environment variables have defined values when the plugin is run. I think they get their values during the macros evaluation phase of the typesetting. But again I’m not certain of that, just trying to guess the reason of the problem.
I do not see the whole “map”, said this: there are “preferences” which maybe plugins can access and extern procedures can set. Perhaps it is a way to get the information about environment variables to plugins.
EDIT - still guessing, one needs a way to execute the setting of the preference before launching the plugin
A complicating matter to an approach with shared preferences is that the process for the plugin is shared among documents. If you start a Python session in one document and define x=3
, then open a new document (from within TeXmacs, not opening a new process), add a Python session to that document and type x
, you will get 3
.
Can this 2006 discussion in the mailing list help?
https://lists.texmacs.org/wws/arc/texmacs-users/2006-02/msg00000.html
I did not understand it but it seems relevant
Edit
It seems that the guile function get-env
gets values of TeXmacs environment variables (the name is similar to getenv
, which gets the value of a shell environment variable).
You can customise this behaviour and have independent sessions. Each session has a name but if you do not provide one then it will be “default” and will share the state of the other “default” session tags.
I think I have found a way to do this. Say I want to pass the value of font-base-size
to a plugin. I can enter <value|font-base-size>
in the document to get e.g. the value 10
, but if this is copied into the session it is lost.
The transformation from a tree to a string to be passed to the plugin happens in the “serializer” function for that plugin. E.g. init-python.scm
contains the python-serialize
function. Some debugging has shown that this is where the <value|...>
tag is lost.
While investigating bug #59435 I happened to come across the html-expand
function which basically forces the evaluation of trees as it would happen during typesetting. So, applying this before the tree is serialized turns the <value|...>
tag into a number 10
just before it is passed to Python
Long story short, for Python I changed the serializer to
(define (python-serialize lan t)
(with u (pre-serialize lan (html-expand t))
(with s (texmacs->code (stree->tree u) "SourceCode")
(string-append s "\n<EOF>\n"))))
Looks very attractive—to use it, one needs to keep in mind that to apply tags at the plugin prompt one should press \ tab, not only \ like in text.
The plots that Python embeds in TeXmacs with pdf_out(plt.gcf())
are though not displayed at the same size as in TeXmacs itself. With plt.show()
maybe they are, I did not yet try with the same font.
I assume that one needs a different pdf_out
function to make the Python output faithful to the input size.
Thanks for the “\ tab” hint, I was copying tags over from the main document
As for the image size, in sessions I get figures that are automatically set to width 0.618par
, which scales with the page, but this can be set to a multiple of w
such that they scale with the image size.
Very nice, now I need to figure out how to automate this (I do not yet know what w means—but it works, and it works even with empty size argument)
I have set the to font of a text to TeX Gyre Pagella (like in the document), the font size to <value|font-base-size> and issued a command for setting an axis title and in my sight this gives the same font/same font size as in the document:
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot()
csfont = {'fontname':'TeX Gyre Pagella'}
ax.set_title('axes title',**csfont, fontsize=<value|font-base-size>)
pdf_out(plt.gcf())
(where for <value|font-base-size>
we need to enter the TeXmacs tag)
I think this is worth to be nicely documented and written up in a blog post.
Small addition to the post:
setting the font to TeX Gyre Pagella gives a warning ('texgyrepagella-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.
), which appears in the output of a plugin session but not in the output of an executable fold. Perhaps one can also set an option to exclude errors from the output of a session as well.
Very nice!
It seems you can also get the “full” font name using this:
(car (logical-font-public (get-env "font") (get-env "font-family")))
so I think csfont
could be filled in automatically as well using an <extern>
.
Can I suggest that maybe a cleaner solution is to make available in a Python session an object which contains informations about the typesetting environment? In this way we avoid that the user of the plugin has to know the internals of TeXmacs. Also I’m quite scared about mixing TeXmacs document format and python code, I’m not sure it can work properly in any situation. With my proposal there will be only a very controlled and limited “injection” of information which is under the control of the programmer of the plugin. I would also avoid that any python code is evaluated with the expand_html
procedure.
Also this seems quite problematic: the whole pagella font is 144kb and is maybe not optimal that is included with every image generated by the plugin. However I do not have any solution for this problem at the moment.
Anyway, very interesting developments!
This seems to be a problem specific to the matplotlib+pdf combination. There’s not much we can do about it. One could presumably use svg instead (or generate plots with other tools…).
Interesting idea. One disadvantage I think this approach would have is that the user would need to know the plugin-dependent implementation. E.g., one plugin developer may inject a “tm-font” variable, while another may call it “texmacs-font”, say.
Obviously using html-expand
is quite an ugly hack, but I don’t see much harm in the general mechanism. At the time the code is presented to the serializer, it is a full TeXmacs tree, so even if you happen to have the string “<value|font-base-size>” in your Python code, it doesn’t get evaluated. The only way I see to get Python code evaluated in html-eval
is if the user would enter a <extern|...>
tag with plugin-eval
inside of it.
I may of course be missing some cases.
So, to limit any risks, a possibility would be to make a minimal version of html-eval
which only expands <value|...>
tags and use that.