Chemfig 亚分子接受一个参数

Chemfig 亚分子接受一个参数

我正在尝试重新创建一个具有许多分子的图形,它们中的大多数都像下面的结构:

在此处输入图片描述

只改变“X”和“Y”。因此,普通的子分子实际上没有帮助,因为我想改变 X 和 Y。然后我定义:

\newcommand*{\HOOC}[2]{HOOC-[1]-[2]-[1]*6(=-=(-#1)-(-#2)=-)}

效果很好如果的参数中只有“正常”文本\HOOC。如果我使用,比如说

\chemfig*{!{\HOOC{OH}{OSO_3}}}

它给了我Missing $ inserted。我该如何克服这个问题?如果有更正确或更聪明的方法,我愿意接受建议。

M(N)WE:

\documentclass{standalone}
\usepackage{chemfig,tikz}
\renewcommand*\printatom[1]{\ensuremath{\mathsf{#1}}}
\newcommand*{\HOOC}[2]{HOOC-[1]-[2]-[1]*6(=-=(-#1)-(-#2)=-)}
\setatomsep{2em}
\usetikzlibrary{positioning}
\begin{document}
  \begin{tikzpicture}[label position={below}]
    \node[label={Dihydrocaffeic acid-3-O-glucuronide}] (DA3OG) {\chemfig*{!{\HOOC{OH}{O-[:30](-[::25](-[:190]OH)-[:-15](-[:75]OH)-[:15]?-[:-15]OH)(-[::-15]O-[::-30]?-[0]COOH)}}}};
    \node[label={Dihydroferulic acid-4-O-sulfate}, below left=-1.5cm and 3cm of DA3OG] {5
    \chemfig*{%
        !{\HOOC{OCH_3}{OSO_3^{-}}}%
        }%
    };
  \end{tikzpicture}
\end{document}

期望输出

在此处输入图片描述

以上内容是通过复制/粘贴M(N)WE的内容\HOOC并用其对应的值替换#1和而获得的。#2

答案1

这里涉及两个问题,第一是如何得到分子中可变的部分,第二是如何在分子中使用公式tikzpicture

据我所知,分子中存在变量有两种可能性。

  • 定义亚分子。

    \definesubmol{X}{OCH_3}
    \definesubmol{Y}{OSO_3^{-}}
    \newcommand*\HOOC{HOOC-[1]-[2]-[1]*6(=-=(-!{X})-(-!{Y})=-)}
    \chemfig*{!\HOOC}
    

    您可以使用\redefinesubmol{X}{...}将名称设置为新的子分子,这样\chemfig*{!\HOOC}将产生不同的分子。

  • 定义\HOOC命令包括\chemfig

    \newcommand*{\cfHOOC}[2]{\chemfig*{HOOC-[1]-[2]-[1]*6(=-=(-#1)-(-#2)=-)}}
    \cfHOOC{OCH_3}{OSO_3^{-}}
    

似乎不可能有宏带有参数!

第二个问题与以下事实有关:\chemfigs 是 tikz 图片,并且 tikz 图片的嵌套可能不起作用。一种解决方案是将 tikz 图片外部的公式排版到一个框中,并在 tikz 图片内部使用此框。

\newsavebox\formulaA
\savebox\formulaA{\cfHOOC{OH}{O-[:30](-[::25](-[:190]OH)-[:-15](-[:75]OH)-[:15]?-[:-15]OH)(-[::-15]O-[::-30]?-[0]COOH)}}

\newsavebox\formulaB
\savebox\formulaB{\cfHOOC{OCH_3}{OSO_3^{-}}}

\begin{tikzpicture}
... \usebox\formulaA ... \usebox\formulaB ...
\end{tikzpicture}

这是文档和相应的代码。

在此处输入图片描述

\documentclass[border=1mm]{standalone}
\usepackage{chemfig}
\renewcommand*\printatom[1]{\ensuremath{\mathsf{#1}}}
\setatomsep{2em}
\usetikzlibrary{positioning}
\begin{document}
\newcommand*{\cfHOOC}[2]{\chemfig*{HOOC-[1]-[2]-[1]*6(=-=(-#1)-(-#2)=-)}}

\newsavebox\formulaA
\savebox\formulaA{\cfHOOC{OH}{O-[:30](-[::25](-[:190]OH)-[:-15](-[:75]OH)-[:15]?-[:-15]OH)(-[::-15]O-[::-30]?-[0]COOH)}}

\newsavebox\formulaB
\savebox\formulaB{\cfHOOC{OCH_3}{OSO_3^{-}}}

\begin{tikzpicture}[label position={below}]
    \node[label={Dihydrocaffeic acid-3-O-glucuronide}] (DA3OG) {\usebox\formulaA};
    \node[label={Dihydroferulic acid-4-O-sulfate}, below left=-1.5cm and 3cm of DA3OG] {5\usebox\formulaB};
 \end{tikzpicture}
\end{document}

编辑:看起来,这些特定的\chemfigs 在直接在 tikz-picture 中使用时也可以工作。请记住,遇到错误时,这可能是由于嵌套的 tikz-pictures 造成的。

答案2

我曾向 chemfig 软件包的作者 Christian Tellechea 提出过类似的问题,他很好心地为我提供了一些自定义代码来解决它。我将这段代码粘贴在下面的示例中。希望您不介意我使用我自己的一些示例分子,而不是您的分子。

\documentclass{article}

\usepackage{chemfig,xstring}

\makeatletter

% he sent me this later ... it seems this is simply a slight refactoring.

\newcommand*\if@csfirst[1]{%
    \csname @\ifcat\relax\expandafter\noexpand\@car#1\@nil first\else second\fi oftwo\endcsname
}

\newcommand*\derivesubmol[4]{%
    \saveexpandmode\saveexploremode\expandarg\exploregroups
    \if@csfirst{#2}
        {\expandafter\StrSubstitute\@car#2\@nil}
        {\expandafter\StrSubstitute\csname CF@@#2\endcsname}
    {\@empty#3}{\@empty#4}[\temp@]%
    \if@csfirst{#1}
        {\expandafter\let\@car#1\@nil}
        {\expandafter\let\csname CF@@#1\endcsname}\temp@
    \restoreexpandmode\restoreexploremode
}

\newcommand*\showsubmol[1]{%
    \if@csfirst{#1}%
        {\begingroup submol "\expandafter\showsubmol@i\string#1" = \ttfamily
        \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter#1%
            \expandafter\expandafter\expandafter{\expandafter\@gobble#1}%
        \expandafter\expandafter\expandafter\strip@prefix\expandafter\meaning\@car#1\@nil
        \endgroup}%
        {\expandafter\showsubmol\csname CF@@#1\endcsname}%
}

\def\showsubmol@i#1#2#3#4#5{}

\newcommand*\exp@addtomacro[2]{\expandafter\@xs@addtomacro\expandafter#1\expandafter{#2}}

\newcommand*\expandsubmol[1]{%
    \if@csfirst{#1}%
        {\saveexpandmode\saveexploremode\expandarg\noexploregroups
        \let\parsed@mol\@empty\let\remain@mol#1%
        \IfSubStr#1!%
            {\expandsubmol@i
            \let#1\parsed@mol
            }%
            \relax
        }%
        {\expandafter\expandsubmol\csname CF@@#1\endcsname}%
}

\newcommand*\expandsubmol@i{%
    \StrBefore\remain@mol![\temp@]%
    \exp@addtomacro\parsed@mol\temp@
    \StrBehind\remain@mol![\remain@mol]%
    \StrSplit\remain@mol\@ne\remain@mol\temp@
    \StrRemoveBraces\remain@mol[\remain@mol]%
    \expandafter\if@csfirst\expandafter{\remain@mol}%
        {\expandafter\let\expandafter\remain@mol\remain@mol}%
        {\expandafter\let\expandafter\remain@mol\csname CF@@\remain@mol\endcsname}%
    \StrGobbleLeft\remain@mol\@ne[\remain@mol]%
    \exp@addtomacro\remain@mol\temp@
    \IfSubStr\remain@mol!%
        \expandsubmol@i
        {\exp@addtomacro\parsed@mol\remain@mol
        \restoreexpandmode\restoreexploremode
        }%
}

\makeatother

% cosmetic enhancements for the example 
\setcrambond{1.75pt}{0.4pt}{1.0pt} % previously too crammed for print.
\setatomsep{18pt}
\renewcommand*\printatom[1]{\ensuremath{\mathsf{#1}}}

\tikzset{ % bond in the foreground
    fgbond/.style={% foreground bond - connecting two cram bonds.
        line width=1.6pt,
        shorten <=-.6pt,
        shorten >=-.6pt
   }
}

% define named substituent dummies. Not strictly necessary, but useful for 
% visual display of the template that contains them. 
\definesubmol{rt1}{-[:90]rt1}
\definesubmol{rt2}{-[:-90,0.6]rt2}


% define a template that contains named dummy substituents that can be replaced
\definesubmol{ribosetemplate}{%
        (
            -[:28,1.508]O
            -[:-28,1.508]
        )
    <[:-45]
        (
          -[0,1.25,,,fgbond]
              (!{rt2})
          >[:45]
              (!{rt1})
         )
}


% partially specialize the template by supplying a substituent for the ribose
\derivesubmol{ribonucleoside}{ribosetemplate}{!{rt2}}{-[6,0.9]OH}
\derivesubmol{deoxyribonucleoside}{ribosetemplate}{!{rt2}}{}


% define some more submols
\definesubmol{adenine}{N*5([::-18]-*6(-N=-N=(-NH_2)-)=-N=-)}
\redefinesubmol{guanine}{N*5([::-18]-*6(-N=(-NH_2)-NH-(=O)-)=-N=-)}

% put those into the second position
\derivesubmol{guanosine}{ribonucleoside}{!{rt1}}{-[2]!{guanine}}
\derivesubmol{deoxyadenosine}{deoxyribonucleoside}{!{rt1}}{-[2]!{adenine}}

\begin{document}

% display the template, so that we know what is where
\chemfig{entry-[6]!{ribosetemplate}-[6]exit}
\hspace{1in}
% put it all together
\chemfig{X-[6,2]!{guanosine}-[6,2]{stuff}-[6,2]!{deoxyadenosine}-[6,2]B}

\end{document}

这产生了

在此处输入图片描述

\makeatletter和之间的代码\makeatother由 Christian 编写,在我看来就像楔形文字一样清晰;不要问我。这取决于xstring同样由 Christian 编写的包。但是,它很容易使用。其想法是定义一个带有字符串占位符的模板分子,然后可以使用宏将其替换为不同的替代物\derivesubmol。我认为这个宏对(已经很棒的)包来说是一个有用的补充chemfig

答案3

按照@gernot 提出的方法(现在已知是手册的内容),但使用不带 es 的方法\savebox- 这可能会暗示未来的问题,但到目前为止还没有遇到过 - 可以定义依赖于其他子分子的子分子(宏形式):

\definesubmol{hooc}{HOOC-[1]-[2]-[1]*6(=-=(-!{\X})-(-!{\Y})=-)}

然后我们发出命令来根据需要更新这些\X\Y

\newcommand*{\radicals}[2]{\edef\X{#1}\edef\Y{#2}}

对独立子分子使用宏(而\edef不是)的原因是,这样我们就可以定义几个其他子分子并使用它们,例如,这个例子很愚蠢,但在下面的 MWE 中有一个更有说服力:\def\def\metil{CH_3}

\documentclass{standalone}
\usepackage{tikz,chemfig}

\renewcommand*\printatom[1]{\ensuremath{\mathsf{#1}}} % Uses sf font
\setatomsep{2em} % Sets atom separation
\usetikzlibrary{positioning}

\newcommand*{\radicals}[2]{\edef\X{#1}\edef\Y{#2}} % Macro that renews the radicals
\definesubmol{hooc}{HOOC-[1]-[2]-[1]*6(=-=(-!{\X})-(-!{\Y})=-)} % Dependent submol
\def\glucuronide{% Complex independent submol
 O-[:30](-[::25](-[:190]OH)-[:-15](-[:75]OH)-[:15]?-[:-15]OH)(-[::-15]O-[::-30]?-[0]COOH)
}

\begin{document}
  \begin{tikzpicture}[label position={below}]
    \node[label={Dihydrocaffeic acid-3-O-glucuronide}] (DA3OG)
         {\radicals{OH}{\glucuronide}\chemfig*{!{hooc}}};
    \node[label={Dihydroferulic acid-4-O-sulfate}, below left=-1.5cm and 3cm of DA3OG]
         {\radicals{OCH_3}{OSO_3^{-}}\chemfig*{!{hooc}}};
  \end{tikzpicture}
\end{document}

得到期望的输出

在此处输入图片描述

相关内容