8

In my thesis, I create numerous drawings using TikZ. In these drawings, I include pictures (e.g. icons of The Noun Project) using Creative Commons licenses. I thus have to acknowledge their authors.

Since my drawings can include up to a dozen of pictures, I cannot credit respective authors in the caption. I thus want to acknowledge them in a specific section in the appendix.

Question: How to conveniently store contributors name at the time I'm drawing the TikZ picture, to use them later in the appendix?

I'm expecting following behaviors:

  • Contributors name storage: use a macro that stores both Author and Picture Name - e.g. \mymacro{John Doe}{Sunrise}. If possible, I could use this macro several time in a picture (e.g. each time I load the icon) without multiple crediting author.
  • Acknowledgment generating: I would use a macro like \printacknowledgement and this would generate following list:

    Figure 1: 'Sunrise' by John Doe, 'Curry wurst' by Erika Mustermann.
    Figure 3: 'Sunrise' and 'Sunset' by John Doe.

Note that: Figure 2 is not displayed because no contributor has to be credited; in Figure 3, it should print «'Sunrise' and 'Sunset' by John Doe» and not «'Sunrise' by John Doe, 'Sunset' by John Doe»


N.B.: I do acknowledge this looks like a do-it-for-me question. I expressed requirements specification because I don't know how to achieve this, even what package I should look for. But I'm of course willing to contribute to solution development/to develop it by myself if one tells me which package/macro I should study.
Requirements are of course ideal. I'd be also happy with bulkier solutions as \mymacro{Figure number}{John Doe}{Sunrise} and «'Sunrise' by John Doe, 'Sunset' by John Doe» being printed.
Edit: the collect package mentioned in How to collect text for later usage in appendix? does not seems to enable to append a name at the end of the list.

  • For figure 3, would you have \mymacro{John Doe}{Sunrise}\mymacro{John Doe}{Sunset}? It may be slightly easier if you're willing to type \mymacro{Sunrise and Sunset by John Doe} (i.e., manually type out the acknowledgement, but leave it to TeX to put it in the right location). – Teepeemm Feb 3 '17 at 17:19
  • @Teepeemm I would have \mymacro{John Doe}{Sunrise}\mymacro{John Doe}{Sunset} (and might even have several \mymacro{John Doe}{Sunrise}): the point would be to credit authors at the time of loading the picture, so I'm sure I forget no one... but also that credits are updated if I eventually remove one picture. – ebosi Feb 3 '17 at 17:22
  • Sorry, I meant within a single figure. I'm assuming you wouldn't repeat the same macro with the same arguments within a figure. Would you be willing to do the manual editing? Or would the contents of Figure 3 be changing, so that you'd need to have separate macro calls? – Teepeemm Feb 3 '17 at 17:26
  • @Teepeemm Separate macro calls would be better (and the must would be to be able to use \mymacro{John Doe}{Sunrise} several times within the same picture - i.e. each time I load the Sunrise icon) – ebosi Feb 3 '17 at 17:29
  • 1
    Short outline: I'd try to have TeX maintain a database. Either via the commands of the datatool package for adding entries/rows to existing databases or by having TeX write an external CSV file containing a database via \addtocontents/\addcontentsline and a patched variant of the \@starttoc-macro . I would use the datatool package for sorting out and formatting and printing the single database entries entries. – Ulrich Diez Feb 3 '17 at 18:37
4

Here, I try to implement the syntax requested by the OP. \mymacro{Author}{Title} should be added inside each particular figure environment, as needed, and \printacknowledgement is to be invoked at the end.

The logic is set up to handle figures with one or more acknowledgements, and to handle author repitition if the repetitions within a given figure appear adjacently in the \mymacro invocations.

\documentclass{article}
\usepackage{graphicx,ifthen}
\newcounter{myack}
\newcounter{ackx}
\newcommand\mymacro[2]{%e.g. \mymacro{Erika Mustermann}{Curry wurst}
    \stepcounter{myack}%
    \expandafter\xdef\csname ack\themyack icon\endcsname{#2}% defines e.g. \ack2icon = Curry wurst
    \expandafter\xdef\csname ack\themyack auth\endcsname{#1}% defines e.g. \ack2auth = Erika Mustermann
    \expandafter\xdef\csname ack\themyack fig\endcsname{\thefigure}% defines e.g. \ack2fig = I1
}
\def\priorfig{0}
\def\isnewfig{T}
\newcommand\printacknowledgement{%
    \section*{Acknowledgement}
        \whiledo{\value{ackx}<\value{myack}}{%                                  while nb of acknowledgment printed < nb of acknowledgment defined
        \stepcounter{ackx}%                                                          number of acknowledgment printed += 1
        \ifthenelse{
            \equal{\csname ack\theackx fig\endcsname}{\priorfig}
        }{%                                                                       if acknowledgment is about same fig as the previous one
            \def\isnewfig{F}%                                                            then \isnewfig = F
        }{%                                                                       else
            \def\isnewfig{T}%                                                            isnewfig = T (this is a new figure)
            \ifthenelse{%                                                                and thus print a dot (. - except for the very first figure)
                \equal{\priorfig}{0}%
            }{%
                %
            }{%
                .%
            }%
            \par%                                                                        and create a new paragraph
        }%
        %
        \if T\isnewfig%                                                                  ... and 
            \noindent\textit{Figure \csname ack\theackx fig\endcsname:} %                start a new line with 'Figure <name of the figure>: '
        \fi%
        \if T\isnewfig%
            %
        \else%                                                                        if its not a new figure
            \if T\showauth\relax%
                , %                                                                       add ', ' only if we're crediting a new author.
            \fi%
        \fi%
        \ifthenelse{%                                                                 
            \equal{\csname ack\theackx fig\endcsname}{\csname ack\the\numexpr\theackx+1\relax fig\endcsname}%
        }{%                                                                           if this credit and the next one are from the same picture
            \ifthenelse{%
                \equal{\csname ack\theackx auth\endcsname}{\csname ack\the\numexpr\theackx+1\relax auth\endcsname}%
            }{%                                                                           
                \def\showauth{F}%                                                         \showauth = F: don't print author name right now cuz we need to add more icone names before
            }{%
                \def\showauth{T}%                                                         else \showauth = T (need to credit author name now)
            }%
        }{%
            \def\showauth{T}%                                                         else \showauth = T (need to credit author name now)
        }%
        `\csname ack\theackx icon\endcsname' %                                        print '<Icon's name> '
        \if T\showauth%
            by \csname ack\theackx auth\endcsname%                                    print 'by <Author name>' if we've to print author name, 
        \else%
            and %                                                                     else print 'and ' (waiting for next icon's name)
        \fi
        %
        \edef\priorfig{\csname ack\theackx fig\endcsname}%                            redefine Fig. nb and author of prior acknowledment
        \edef\priorauth{\csname ack\theackx auth\endcsname}%
    }.%
}

\begin{document}
    \begin{figure}[ht]
        \centering
        \includegraphics[width=1in]{example-image}
        \caption{blah blah}%
        \mymacro{John Doe}{Sunrise}%
        \mymacro{Erika Mustermann}{Curry wurst}%
    \end{figure}
    \begin{figure}[ht]
        \centering
        \includegraphics[width=1in]{example-image}
        \caption{blah blah}%
        \mymacro{John Doe}{Sunrise}%
        \mymacro{John Doe}{Sunset}%
    \end{figure}
    \begin{figure}[ht]
        \centering
        \includegraphics[width=1in]{example-image}
        \caption{blah blah}%
        \mymacro{John Doe}{Sunrise}%
    \end{figure}
    \printacknowledgement
\end{document}

enter image description here

One less than ideal behavior that could be remedied with extra work is that if a given figure has 3 (or more) icons from a given author, the acknowledgement will appear as 'Sunrise' and 'Sunset' and 'Moonglow' by John Doe, rather than as 'Sunrise', 'Sunset', and 'Moonglow' by John Doe

  • Wow! MWE works like a charm, just need to figure out why I get a ! Missing = inserted for \ifnum. in my real case scenario (it's a good motivation to study LaTeX "dirty internals"). Anyway, many thanks! – ebosi Feb 3 '17 at 19:34
  • Raised error comes from my figure's numbering. Indeed, I redefined it as following in a scrbook document: \usepackage{chngcntr} \counterwithout{figure}{chapter} \counterwithin{figure}{part} \renewcommand\thefigure{\thepart.\arabic{figure}}. I'll try to work on your solution. – ebosi Feb 3 '17 at 19:41
  • Steven: I've felt free to edit your answer as following: I've replaced the \ifnum conditional testings with \ifthenelse{\equal{... ones, in order to handle the case where \thefigure is not an integer (e.g. within scrbook documents, \thefigure is formated as <chap. nb>.<img nb>). I've also added verbose comments and reshaped the structure, so that script structure appear obvious. (Writing a new answer did not appear necessary since change are minor compared to the work you did.) – ebosi Feb 4 '17 at 15:03
  • @ebo Since your edits were, I think, somewhat significant (more than just a typo), a better approach in the future, in such a case, would be to add your revised code as an addendum to my answer, while leaving my original code in place, for comparison. – Steven B. Segletes Feb 4 '17 at 17:21
  • Steven: Thank you for your feedback. I hope I did not unintentionally offend you. My primary intention was only to increment a little on your work and keep your answer concise. But I do can understand your point, and seeing a code that is not yours in your answer might indeed make you feel uncomfortable. My apologies. – ebosi Feb 4 '17 at 17:55
5

I know this sounds like magic, but, hey, it works!

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{enumitem}

\ExplSyntaxOn
\NewDocumentCommand{\addcredit}{mm}
 {
  \ebo_addcredit:nn { #1 } { #2 }
 }

\NewDocumentCommand{\printcredits}{}
 {
  \ebo_printcredits:
 }

\prop_new:N \g_ebo_credit_names_prop
\seq_new:N \g_ebo_credit_list_seq
\seq_new:N \l__ebo_credit_item_seq
\clist_new:N \l__ebo_credit_list_clist

\cs_new_protected:Nn \ebo_addcredit:nn
 {
  \prop_if_exist:cF { g_ebo_credit_ \thefigure _prop }
   {
    % create a property list and register it
    \prop_new:c { g_ebo_credit_ \thefigure _prop }
    \seq_gput_right:Nx \g_ebo_credit_list_seq { \thefigure }
   }
  \prop_if_in:cnTF { g_ebo_credit_ \thefigure _prop } { #1 }
   { % there's already credit for #1
     \prop_gput:cnx { g_ebo_credit_ \thefigure _prop }
      { #1 }
      { \prop_item:cn { g_ebo_credit_ \thefigure _prop } { #1 } , \exp_not:n { { `#2' } } }
   }
   { % no credit for #1
     \prop_gput:cnn { g_ebo_credit_ \thefigure _prop }
      { #1 }
      { { `#2' } }
   }
  \prop_gput:Nnn \g_ebo_credit_names_prop { #1 } { #1 }
 }

\cs_new_protected:Nn \ebo_printcredits:
 {
  \section{Acknowledgments}
  \begin{itemize}[align=left,leftmargin=*]
  \seq_map_inline:Nn \g_ebo_credit_list_seq
   {
    \item[\textit{Figure~##1}:] \__ebo_credit_print:n { ##1 }.
   }
  \end{itemize}
 }

\cs_new_protected:Nn \__ebo_credit_print:n
 {
  \seq_clear:N \l__ebo_credit_item_seq
  \prop_map_inline:cn { g_ebo_credit_ #1 _prop }
   {% ##1 is the author, ##2 is the list of credits
    \clist_set:Nn \l__ebo_credit_list_clist { ##2 }
    \seq_put_right:Nx \l__ebo_credit_item_seq
     {
      \clist_use:Nnnn \l__ebo_credit_list_clist { ~and~ } { ,~ } { ,~and~ }~by~
      \prop_item:Nn \g_ebo_credit_names_prop { ##1 }
     }
   }
   \seq_use:Nn \l__ebo_credit_item_seq { ;~ }
 }
\ExplSyntaxOff

\begin{document}

\begin{figure}[htp]
\caption{First figure}
\addcredit{John Doe}{Sunrise}
\addcredit{Erika Musterman}{Curry Wurst}
\end{figure}

\begin{figure}[!htp]
\caption{Second figure}
\end{figure}

\begin{figure}[!htp]
\caption{Third figure}
\addcredit{John Doe}{Sunrise}
\addcredit{John Doe}{Sunset}
\end{figure}

\begin{figure}[!htp]
\caption{Fourth figure}
\addcredit{\'Accented Aüthor}{Dawn}
\addcredit{John Doe}{Sunset}
\addcredit{John Doe}{Sunrise}
\addcredit{John Doe}{Evening}
\end{figure}

\printcredits

\end{document}

The \addcredit macro adds material to a property list linked to the figure number (so it must appear after \caption).

If the same author appears further in the same figure, the corresponding property is added the new title. The figure number is stored sequentially, so we can map through those that have \addcredit commands.

It is your responsibility that the author's name is the same in all \addcredit commands for the same figure.

The \printcredits command maps the sequence of figures with credits; for each one of them, the corresponding property list is mapped to form the required text: first the list of contributions, then the author name. If there are two contributions, they're separated by “and”; if more, there will be a comma, between two of them, except the last with “, and”. Remove the comma in the code, if you don't like the Oxford comma.

Use \addcredit for the same author in one figure one after the other, or the final order would be unpredictable.

enter image description here

  • Wouaou. Out of curiosity: do you have a program to produce all this magic, or do you append ebo to all variables names by hand? – Clément Feb 4 '17 at 18:25
  • 2
    @Clément The program is called egregbrains, I'll try getting it on GitHub one day. – egreg Feb 4 '17 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.