[Tex/LaTex] Automatically Generating Beamer Presentation Draft from Article

beamerconversion

I have a LaTeX paper with multiple sections, subsections, and figures. My slides to present the paper will mostly consist of the same sections, subsections, and figures. So I am interested in automatically generating the Beamer code for a draft presentation with the following features:

  • The sections and subsections from the paper are preserved in the slides.
  • When a figure is referenced within a subsection of the paper, the figure is inserted in a slide for the corresponding subsection.

I was wondering if something along those lines already exists. Otherwise it would be fairly simple to write a script which parses the paper and generates the Beamer draft.

To further clarify my question, I made the following example:

Paper:

\documentclass{article}
\usepackage[affil-it]{authblk}

\author[1]{Phill}
\author[1]{Bill}
\affil[1]{Instutite of LaTeX}
\title{Paper 1}
\begin{document}
\section{sec1}
\subsection{sec1.1}

See the data in \ref{fig:1}.

\section*{Figures}
\begin{figure}
    \includegraphics[scale = 0.5]{example-image}
    \label{fig:1}
\end{figure}
\end{document}

Resulting slides:

\documentclass{beamer}
\title{Paper 1}
\author{Phill and Bill}
\Institute{Instutite of LaTeX}
\begin{document}
\begin{frame}
 \titlepage
\end{frame}
\section{sec1}
\subsection{sec1.1}
\begin{frame}{\secname : \subsecname}
\begin{figure}
    \includegraphics[scale = 0.5]{example-image}
    \label{fig:1}
\end{figure}
\end{frame}

\end{document}

Best Answer

I went ahead and wrote a python script to solve the problem. Essentially the Beamer presentation will keep the format form the article (section subsections) and create a new slide for each figure, fitting the figure to the whole slide.

To use it you can simply run it in the same directory as your article file which should be named main.tex. The output presentation will be written to slides.tex.

import re
import os

def main():
    """
    Automatically generates a beamer presentation draft from an article
    Notes:
           - Some functionality has been disabled by comments.
    """

    article_file_path = 'main.tex'
    beamer_file_path = 'slides.tex'

    written_figures = []

    with open(article_file_path, 'r') as art:
        with open(beamer_file_path, 'w') as outf:
           # in_frame = False
            for line in art:

                # Preamble
                #(currently ignoring)

                # Copy header
                # Ignores unnumbered sections
                if line.startswith('\section{') or line.startswith(r'\subsection'):

                 #   if in_frame:
                  #      outf.write(r'\end{frame}'+'\n')
                   #     in_frame = False

                    outf.write(safe_line(line))

                if line.startswith(r'\subsubsection'):
                    outf.write('%' + safe_line(line))

                    # Create frame for subsections
               #     if line.startswith(r'\subsection'):
                #        outf.write(r'\begin{frame}{\secname: \subsecname}'+'\n')
                 #       in_frame = True

                # Insert figure
                fig_refs = re.findall(r'\\ref{fig:([\w\d -_]+)}', line)
                if fig_refs:
                    for fig_ref in fig_refs:
                        if fig_ref not in written_figures:
                            fig_frame = safe_line(find_fig_str(article_file_path, fig_ref))
                            outf.write(fig_frame)
                            written_figures.append(fig_ref)

            #if in_frame:
             #   outf.write(r'\end{frame}' + '\n')
              #  in_frame = False

def safe_line(line):
    """ Processes latex control sequences which cause beamer to break
     * Remove \label{}, \todo{}
     * Add \protect infront of \textit{}
    """
    sline = line
    sline = re.sub(r'\\label{[\w\d:\s]+}', '', sline)
    sline = re.sub(r'\\todo{[\w\d:\s]+}', '', sline)

    sline = re.sub(r'\\textit{', r'\\protect\\textit{', sline)
    return sline

def find_fig_str(text_file_path, fig_ref):
    """ Finds the figure floating environment based on label
    """
    with open(text_file_path, 'r') as tfile:
        envstr = ''
        in_fig = False
        for line in tfile:

            if line.startswith(r"\begin{figure}"):
                in_fig = True

            if in_fig:
                to_write = line
                # Remove placement specifications:
                if line.startswith(r"\begin{figure}"):
                    to_write = re.sub(r'\[([\w]+)\]', '', line)
                # ignore label
                if line.startswith(r'\label{'):
                    to_write = ''
                # replace figure width to make it fill the whole slide
                if re.match(r'[\t\s]?\\includegraphics',line):
                    to_write = re.sub(r'\[([\w=\d]+)\]', r'[width =\\textwidth, height = 0.6\\textheight, keepaspectratio]', line)

                envstr += to_write

            labelmatch = re.match(r'[\t\s]?\\label{fig:([\w\d -_]+)}',line)
            if labelmatch:
                if labelmatch.group(1) == fig_ref:
                    right_fig = True
                else:
                    right_fig = False

            if line.startswith(r"\end{figure}"):
                in_fig = False
                if right_fig: # Stop searching
                    break
                else:
                    envstr = ''

    # Make figure be in its own frame:
    if envstr:
        envstr = r'\begin{frame}{\subsecname}' + '\n' + envstr + r'\end{frame}' + '\n'

    return envstr

main()