
Ich schreibe einen Bericht, der Enzymbilder wie diese enthält:
Ich \caption
möchte einen Farbleitfaden einbinden, damit wichtige Komponenten/Atome farblich beschrieben werden können (dieser Bericht wird nicht veröffentlicht, daher ist dies im Hinblick auf Farbenblindheit kein Problem). Ich verwende derzeit einen Befehl wie diesen:
\newcommand\ColourGuide{%
Colour code: \textcolor{violet}{metal ion}, \textcolor{Green3}{residue}, \textcolor{teal}{ligand}, \textcolor{Yellow3}{substrate}, \textcolor{DarkOrange1}{phosphorus}, \textcolor{red}{oxygen} and \textcolor{RoyalBlue4}{nitrogen}%
}
Bei manchen Bildern sind jedoch nicht alle Farbkomponenten vorhanden, sodass es nicht sinnvoll wäre, redundante Farbcodes einzufügen. Wie kann ich einen Satz basierend auf Eingaben erstellen? Beispiel:
\ColourGuide{M}{R}{S}{O}{N}
würde ergeben:
Farbcode: Metallion, Rückstand, Substrat, Sauerstoff und Stickstoff.
in den angegebenen Farben. Ich verwende lualatex
und habe mir die Verwendung angesehen lua
(was nett wäre), aber ich weiß nicht, wie ich die beiden richtig (oder effizient) interagieren lassen soll, wie könnten die Argumente beispielsweise wie in Python mit extrahiert werden input[0]
? Ich würde mich über jeden Rat oder jede Lösung über jede Methode freuen, aber es lua
wäre nett, wenn ich anfangen könnte, es zu lernen und es auf andere Befehle anzuwenden, die ich lualatex
häufig verwende.
MWE:
\documentclass{book}
\usepackage[x11names]{xcolor}
\newcommand\ColourGuide{%
Colour code: \textcolor{violet}{metal ion}, \textcolor{Green3}{residue}, \textcolor{teal}{ligand}, \textcolor{Yellow3}{substrate}, \textcolor{DarkOrange1}{phosphorus}, \textcolor{red}{oxygen} and \textcolor{RoyalBlue4}{nitrogen}%
}
\begin{document}
\ColourGuide{}
\end{document}
Wie es aussieht:
(Ich bin nicht sicher, welche Tags ich hier anbringen soll)
Antwort1
Guter Versuch in Ihrer Antwort, aber …
\documentclass{book}
\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\ColourGuide}{m}
{
Color~code:~\jamest_colourguide:n { #1 }
}
\seq_new:N \l__jamest_colourguide_seq
\cs_new_protected:Nn \jamest_colourguide:n
{
\seq_clear:N \l__jamest_colourguide_seq
\tl_map_function:nN { #1 } \__jamest_colourguide_add:n
\seq_use:Nnnn \l__jamest_colourguide_seq { ~and~ } { ,~ } { ~and~}
}
\cs_new_protected:Nn \__jamest_colourguide_add:n
{
\seq_put_right:Nx \l__jamest_colourguide_seq
{
\str_case:nn { #1 }
{
{a}{\textcolor{red}{oxygen},~\textcolor{DarkOrange1}{phosphorus},~
\textcolor{Yellow3}{substrate},~\textcolor{Green3}{residue},~
\textcolor{RoyalBlue4}{nitrogen},~\textcolor{teal}{ligand}~
and~\textcolor{violet}{metal~ion}.}
{M}{\textcolor{violet}{metal~ion}}
{R}{\textcolor{Green3}{residue}}
{S}{\textcolor{Yellow3}{substrate}}
{O}{\textcolor{red}{oxygen}}
{N}{\textcolor{RoyalBlue4}{nitrogen}}
{L}{\textcolor{teal}{ligand}}
{P}{\textcolor{DarkOrange1}{phosphorus}}
}
}
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{a}
\end{document}
Es ist kein Zählen erforderlich: Das Argument wird Zeichen für Zeichen zugeordnet und der entsprechende Code wird der Sequenz hinzugefügt, die später mit den entsprechenden Trennzeichen verwendet werden kann.
Um eine Code-Duplikation zu vermeiden, ist es vielleicht besser, das Argument leer zu lassen, wenn Sie die vollständige Liste wünschen.
\documentclass{book}
\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\ColourGuide}{m}
{
Color~code:~
\jamest_colourguide:n { #1 }
}
\seq_new:N \l__jamest_colourguide_seq
\cs_new_protected:Nn \jamest_colourguide:n
{
\tl_if_empty:nTF { #1 }
{
\jamest_colourguide:n { OPSRNLM }
}
{
\seq_clear:N \l__jamest_colourguide_seq
\tl_map_function:nN { #1 } \__jamest_colourguide_add:n
\seq_use:Nnnn \l__jamest_colourguide_seq { ~and~ } { ,~ } { ~and~}
}
}
\cs_new_protected:Nn \__jamest_colourguide_add:n
{
\seq_put_right:Nx \l__jamest_colourguide_seq
{
\str_case:nn { #1 }
{
{M}{\textcolor{violet}{metal~ion}}
{R}{\textcolor{Green3}{residue}}
{S}{\textcolor{Yellow3}{substrate}}
{O}{\textcolor{red}{oxygen}}
{N}{\textcolor{RoyalBlue4}{nitrogen}}
{L}{\textcolor{teal}{ligand}}
{P}{\textcolor{DarkOrange1}{phosphorus}}
}
}
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{}
\end{document}
Die Ausgabe ist die gleiche.
Antwort2
Dank der Kommentare konnte ich eine Lösung zusammenstellen, die zwar nicht schön ist, aber wie gewünscht funktioniert. Hinzufügen einer Antwort von @egreg zuSo bestimmen Sie die Anzahl der Zeichen im Argument eines Befehlsund die verlinkte Antwort @John Kormylokommentiertergibt folgendes:
\documentclass{book}
\usepackage[x11names]{xcolor}
\usepackage{xstring}
\usepackage{xparse} % loads expl3
\ExplSyntaxOn
\newcounter{Chars}
\newcounter{CharsConstant}
\def\CharsCount#1{%
\setcounter{Chars}{\tl_count:n { #1 }}%
\setcounter{CharsConstant}{\tl_count:n { #1 }}%
}
\NewDocumentCommand{\punctOrAnd}{mm}
{
\int_compare:nTF { #1 > 1 }
{
\int_compare:nTF { #1 = \value{CharsConstant} }
{
#2
}
{
,~#2
}
}
{
\space and~#2.
}
}
\def\ColourGuide#1{\CharsCount{#1}Colour~code:~\scanA#1\end}
\def\scanA#1{%
\ifx\end#1\else
\IfStrEq{#1}{a}{\textcolor{red}{oxygen},~\textcolor{DarkOrange1}{phosphorus},~\textcolor{Yellow3}{substrate},~\textcolor{Green3}{residue},~\textcolor{RoyalBlue4}{nitrogen},~\textcolor{teal}{ligand}~and~\textcolor{violet}{metal~ion}.}{}%
%
\IfStrEq{#1}{M}{\punctOrAnd{\value{Chars}}{\textcolor{violet}{metal~ion}}}{}%
\IfStrEq{#1}{R}{\punctOrAnd{\value{Chars}}{\textcolor{Green3}{residue}}}{}%
\IfStrEq{#1}{S}{\punctOrAnd{\value{Chars}}{\textcolor{Yellow3}{substrate}}}{}%
\IfStrEq{#1}{O}{\punctOrAnd{\value{Chars}}{\textcolor{red}{oxygen}}}{}%
\IfStrEq{#1}{N}{\punctOrAnd{\value{Chars}}{\textcolor{RoyalBlue4}{nitrogen}}}{}%
\IfStrEq{#1}{L}{\punctOrAnd{\value{Chars}}{\textcolor{teal}{ligand}}}{}%
\IfStrEq{#1}{P}{\punctOrAnd{\value{Chars}}{\textcolor{DarkOrange1}{phosphorus}}}{}%
%
\addtocounter{Chars}{-1}%
\expandafter \scanA \fi
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{a}
\end{document}
Antwort3
Dies verwendet ein Semikolon als Abschlusszeichen. \def\CGparse#1#2;
fügt das erste Token (den Buchstaben) in #1
und alles vor dem Semikolon in ein #2
. Es ruft sich selbst rekursiv auf, bis #2
ist \empty
.
\documentclass{book}
\usepackage[x11names]{xcolor}
\newcommand\ColourGuide[1]{Colour code:{\count1=0\relax\CGparse#1;}}
\def\CGparse#1#2;{\def\A{#1}%
\def\B{#2}%
\ifnum\count1=0\relax
\space
\else
\ifx\B\empty\relax
{ and }%
\else
{, }%
\fi
\fi
\advance\count1 by 1
\def\C{M}\ifx\A\C\relax\textcolor{violet}{metal ion}\fi
\def\C{R}\ifx\A\C\relax\textcolor{Green3}{residue}\fi
\def\C{L}\ifx\A\C\relax\textcolor{teal}{ligand}\fi
\def\C{S}\ifx\A\C\relax\textcolor{Yellow3}{substrate}\fi
\def\C{P}\ifx\A\C\relax\textcolor{DarkOrange1}{phosphorus}\fi
\def\C{O}\ifx\A\C\relax\textcolor{red}{oxygen}\fi
\def\C{N}\ifx\A\C\relax\textcolor{RoyalBlue4}{nitrogen}\fi
\ifx\B\empty\relax
{. }%
\else
\CGparse#2;
\fi}
\begin{document}
\ColourGuide{MRSON}
\end{document}
Antwort4
Es gibt bereits viele gute Antworten, und meine Verwendung pgfkeys
ist wahrscheinlich viel zu kompliziert und umständlich, aber das ist, was mir eingefallen ist.
- Nicht erforderlich
lualatex
(was hier explizit angefragt wurde, aber vielleicht kann es jemand woanders gebrauchen). - Die Atome werden immer in der gleichen Reihenfolge aufgelistet, egal ob Sie
\ColourGuide[ligand,residue]
oder schreiben\ColourGuide[residue,ligand]
. Dies kann erwünscht sein oder nicht, aber ich denke, es ist ein guter Stil, die gleiche Reihenfolge beizubehalten.
Natürlich könnten die optionalen Argumente/Schlüssel \ColourGuide[L,R]
fast ohne Aufwand auf „zB“ gekürzt werden.
\documentclass{article}
% create 'if's for each atom
\newif\ifmetalion
\newif\ifresidue
\newif\ifligand
\newif\ifsubstrate
\newif\ifphosphorus
\newif\ifoxygen
\newif\ifnitrogen
% create two counters
\newcounter{numtrue} % total number of 'if's which are true
\newcounter{currval} % counter (for correctly putting 'and' at the last atom)
% colors
\usepackage[x11names]{xcolor}
% create pgfkeys
\usepackage{pgfkeys,xcolor}
\pgfkeys{
/colourguide/.is family, /colourguide/.cd,
default/.style={
metalion=false,
residue=false,
ligand=false,
substrate=false,
phosphorus=false,
oxygen=false,
nitrogen=false,
},
metalion/.is if=metalion,
residue/.is if=residue,
ligand/.is if=ligand,
substrate/.is if=substrate,
phosphorus/.is if=phosphorus,
oxygen/.is if=oxygen,
nitrogen/.is if=nitrogen
}
% this will produce the adequate delimiter between different atoms
\def\chooseDelimiter{%
\stepcounter{currval}% increment counter
\ifnum\value{currval}<\value{numtrue}\relax% if more than one atom remains ...
,\ % ... put ',' ...
\else%
\ifnum\value{currval}=\value{numtrue}\relax% ... if only one atom remains ...
\ and\ % ... put 'and' ...
\else% ... if no atom remains ...
.% ... put '.'
\fi%
\fi%
}
% main command: \ColorGuide
\newcommand\ColourGuide[1][]{%
% do pgfkeys magic
\pgfkeys{/colourguide, default, #1}%
% get number of requested atoms
\setcounter{currval}{1}%
\setcounter{numtrue}{0}%
\ifmetalion \stepcounter{numtrue}\fi%
\ifresidue \stepcounter{numtrue}\fi%
\ifligand \stepcounter{numtrue}\fi%
\ifsubstrate \stepcounter{numtrue}\fi%
\ifphosphorus\stepcounter{numtrue}\fi%
\ifoxygen \stepcounter{numtrue}\fi%
\ifnitrogen \stepcounter{numtrue}\fi%
% build sentence
Colour code:\ %
\ifmetalion\textcolor{violet}{metal ion}\chooseDelimiter\fi%
\ifresidue\textcolor{Green3}{residue}\chooseDelimiter\fi%
\ifligand\textcolor{teal}{ligand}\chooseDelimiter\fi%
\ifsubstrate\textcolor{Yellow3}{substrate}\chooseDelimiter\fi%
\ifphosphorus\textcolor{DarkOrange1}{phosphorus}\chooseDelimiter\fi%
\ifoxygen\textcolor{red}{oxygen}\chooseDelimiter\fi%
\ifnitrogen\textcolor{RoyalBlue4}{nitrogen}\chooseDelimiter\fi%
}
\begin{document}
\paragraph{Works with one atom:}
\ColourGuide[metalion]
\paragraph{Works with two atoms:}
\noindent\ColourGuide[residue,ligand]\\ % two atoms
\paragraph{Works with many atoms:}
\ColourGuide[metalion,residue,ligand,substrate,phosphorus,oxygen,nitrogen]\\ % many atoms
\paragraph{Keeps the given order, no matter what is the order in brackets:}
\ColourGuide[ligand, residue]
\end{document}