Some TeX Developments

Coding in the TeX world

Exploring ChemFig: Customising appearance

with 10 comments

In my previous post, I looked at the basics of using the ChemFig package to create chemical structures. I finished that post with a structure that is complete but which I think does not look great compared with the reference version I created in ChemDraw. (There’s a MyChemistry entry that looks at similar customisation: worth a look!)

Atom placement

The first issue to tackle is the placement of atom labels. ChemFig ‘detects’ atoms, so that the labels are correctly centred relative to bonds. However, that does not work with numbered R-groups, as the numbers need to be ‘ignored’ for alignment purposes. This is a pretty common requirement, so ChemFig provides a way to ‘split’ labels, using |:

\chemfig{
  *6(-(-R|^2)=-
    (-=[::-60]N-*6(=(-R|^3)-=(-R|^4)-=(-R|^3)-))
  =(-OH)-(-R|^1)=)
}

which gives the output

To see the difference here, look at for example R2 here compared to the version in the previous post: it’s subtle, but it is there!

Atom spacing and bond width

The standard settings for ChemFig share a ‘feature’ with those for ChemDraw: they don’t look very good! As I said in the previous post, I use the Royal Society of Chemistry’s template for my structures, as I think they look much better. The template uses 7 pt text, and so the lengths, etc. all match that size. For use in LaTeX, I want things to be more flexible so wanted to convert the values into em (i.e. relative dimensions based on font size).

There are three key dimensions used by both ChemDraw and ChemFig to set how bonds look: the bond length, the line width and the gap between lines when drawing double bonds. There is also a ‘margin’ used between atom labels and bonds, so the two don’t touch. After a bit of work doing the calculation (using to the LaTeX3 FPU), I found that

\setdoublesep{0.35700 em}  % 'Bond Spacing'
\setatomsep{1.78500 em}    % 'Fixed Length'
\setbondoffset{0.18265 em} % 'Margin Width'
\newcommand{\bondwidth}{0.06642 em} % 'Line Width'
\setbondstyle{line width = \bondwidth}

was the right set up. The comments are the ChemDraw names for settings, and I’ve set the line width as a command as it turns out I’ll want it again for some more advanced things to be covered in the next post.

The central double bond

Changing the bond spacing shows up another issue: the central double bond is not right. Rather than bond to the ‘middle’ of the double bond, we want the chain to choose one ‘side’. That can be done using either _ or ^, depending on which side is required. I decided to match the ChemDraw version using

\chemfig{
  *6(-(-R|^2)=-
    (-=^[::-60]N-*6(=(-R|^3)-=(-R|^4)-=(-R|^3)-))
  =(-OH)-(-R|^1)=)
}

Atom font

The final thing to adjust to get this example right is the font used for atom labels: the convention is to use sanserif. ChemFig prints text using the \printatom command, which is set up to ensure math mode and \mathrm. Thus the simplest approach is

\renewcommand*{\printatom}[1]{\ensuremath{\mathsf{#1}}

Like many people, I use the excellent mhchem to write in-line chemical equations, so I wanted to use the \ce (or faster \cf) command for printing atoms. My intial attempt failed, with an internal error. A quick e-mail to the ChemFig author led to a fix

\makeatletter
\def\CF@node@content{%
  \expandafter\expandafter\expandafter
    \printatom\expandafter\expandafter\expandafter
      {\csname atom@\number\CF@cnt@atomnumber\endcsname}%
    \ensuremath{\CF@node@strut}%
}
\makeatother

followed by

 \renewcommand*{\printatom}[1]{{\sffamily\cf{#1}}}

leads to the final input

\documentclass{article}
\usepackage{chemfig}
\usepackage[version=3]{mhchem}
\makeatletter
\def\CF@node@content{%
  \expandafter\expandafter\expandafter
    \printatom\expandafter\expandafter\expandafter
      {\csname atom@\number\CF@cnt@atomnumber\endcsname}%
    \ensuremath{\CF@node@strut}%
}
\makeatother
\setdoublesep{0.35700 em}  % 'Bond Spacing'
\setatomsep{1.78500 em}    % 'Fixed Length'
\setbondoffset{0.18265 em} % 'Margin Width'
\newcommand{\bondwidth}{0.06642 em} % 'Line Width'
\setbondstyle{line width = \bondwidth}
\renewcommand*{\printatom}[1]{{\sffamily\cf{#1}}}
\begin{document}
\chemfig{
  *6(-(-R|^2)=-
    (-=^[::-60]N-*6(=(-R|^3)-=(-R|^4)-=(-R|^3)-))
  =(-OH)-(-R|^1)=)
}
\end{document}

and output

I’d say that is pretty good: I’d be happy to use this in a publication (although drawing the kind of structures I do my research with would be a challenge!).

In the final part of this series, I’m going to look at some other things that are needed for chemical structures but which don’t show up in the demo I’ve used. We’ll see that many can be done, but there will be one or two outstanding challenges.

Written by Joseph Wright

August 25th, 2012 at 5:18 pm

Posted in LaTeX

Tagged with , ,

10 Responses to 'Exploring ChemFig: Customising appearance'

Subscribe to comments with RSS or TrackBack to 'Exploring ChemFig: Customising appearance'.

  1. I’m still not seeing WHY I would ever want to do this much work. If someone makes a GUI for it, or allows me to input a name, or SMILES string or something, then it might be useful…

    Canageek

    25 Aug 12 at 6:31 pm

  2. I like the patch for “mhchem” (I wonder why that never occurred to me…)

    @Canageek: from my experience it is also a matter of practice/routine. Molecules like this one are easy enough and a matter of minutes. Other ones are quite more challenging (a way less comfortable!). :)

    Clemens

    25 Aug 12 at 7:09 pm

  3. @Canageek As I said at the start of part one, I’m not about to abandon ChemDraw: I’m trying out ChemFig to see what works and what doesn’t. I’ve wondered what would work as an input format: perhaps parsing .cdxml might work (SMILES or similar is no good as there is no layout information).

    Joseph Wright

    25 Aug 12 at 11:18 pm

  4. If you want to start with a SMILES string or a molfile, you might want to look at my mol2chemfig program (http://chimpsky.uwaterloo.ca/mol2chemfig/), which generates chemfig code from these formats.

    You could also save molfile from ChemDraw or similar and then run this through mol2chemfig.

    Mike

    12 Sep 12 at 8:25 pm

  5. @Canageek: a GUI approach usually includes some payment necessary (I haven’t found a free software that produces even near the quality). Nevertheless, as Joseph mentioned, ChemDraw is the tool for research (publication quality, acceptance, etc. and maybe most important: who does not cooperate with non-latex users?!). I am using ChemFig quite extensively for my lecture materials. The code is rather simple to write down… but debugging can be a pain. After a while and with good indentation it gets easier and for larger molecules the \definesubmol{}{} command is really helpful.

    @Joseph: Really like the wider bonds in your example. Much more readable on slides than my normal default \setatomsep{2em}\setcrambond{.25em}{}{}. Any idea how to reduce the “cracks” in bond corners?

    MaBu

    28 Nov 12 at 1:19 am

  6. @MaBu As you say, none of the free chemical drawing (GUI) packages can match the output of paid-for ChemDraw or ChemDoodle.

    The ‘cracks’ look very tricky to me: I suspect there’s quite a lot of maths in the GUI programs to get this right. Perhaps the author of ChemFig might have an idea: I’ll ask him!

    Joseph Wright

    28 Nov 12 at 9:48 am

  7. @Joseph: Checked the ChemFig manual and the only other parameter you could tweak is setbondoffset which cannot solve this. So I read in the TikZ manual and found a quick and dirty solution: appending the TikZ option “cap = round” to the bonds closes the gap (the output then looks quite similar to what ChemDoodle produces).

    TkiZ could close the gap automatically, but only if the bonds are defined in one path (with joint=miter with is default). Couldn’t find a way to do something similar to independent lines that intersect at one node.

    MaBu

    28 Nov 12 at 1:29 pm

  8. Anyone tried Chemaxon’s Marvinsketch? For me, seems quite good.

    r

    14 Jan 13 at 12:58 pm

  9. Please, could you show us the calculations you have performed for \setdoublesep etc?

    Paulo

    8 Feb 13 at 1:53 am

  10. @Paulo Nothing complicated: I looked up the values in ChemDraw, then used a simple conversion to em.

    @r I use MarvinSketch a look for online searches, but the output would not be any good for publication-quality schemes.

    Joseph Wright

    10 Feb 13 at 11:24 am

Leave a Reply