11

I'm using booktabs to display some profiling data. I would like to add bars to each row to visually indicate the quantities in one column.

I would like to use a table instead of a barchart since there are additional columns that don't require visualisation.

Screenshot

Screenshot from vtune illustrating what I am looking for.

Could I maybe draw inside a cell using tikz? Or do I need to abandon the table and wrangle a pgfplots barchart to look like a table?

  • 2
    just use \colorbox{\strut\hspace{1.14cm}} ... \colorbox{\strut\hspace{3.42cm}} – David Carlisle Apr 23 '14 at 13:38
  • You could also format a PGFPlots plot to neatly fit into the table. Compared to David's suggestion, this has the advantage of taking care of the scaling automatically. – Jake Apr 23 '14 at 15:17
14

How about something like this:

\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{array}
\usepackage{xcolor}
\def\mybar#1{%%
  #1s & {\color{red}\rule{#1cm}{8pt}}}

\pagestyle{empty}
\begin{document}

\begin{tabular}{>{$\rhd$ }lrl}
Loop at line 151 in divergence  & \mybar{3.420}\\
Loop at line 1071 in radiation  & \mybar{3.270}\\
scalar face value               & \mybar{3.090}\\
Loop at line 102 in get         & \mybar{1.700}\\
get sensible enthalpy           & \mybar{1.250}\\
\end{tabular}

\end{document}

enter image description here

  • Awesome. I ended up adding some scaling. \pgfmathsetmacro{\len}{#1*0.04} – John Apr 25 '14 at 14:09
  • Where should I put \pgfmathsetmacro{\len}{#1*0.04} to add scale? – user3573959 May 14 '15 at 12:47
11

Example using TikZ:

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{lmodern}

\usepackage{url}
\DeclareUrlCommand\function{\urlstyle{sf}}

\usepackage{xcolor}
\usepackage{tikz}
\usepackage{booktabs}
\usepackage{array}
\usepackage{multirow}
\usepackage{siunitx}

\definecolor{chart Idle}{gray}{.6}
\definecolor{chart Poor}{RGB}{242,28,28}
\definecolor{chart Ok}{RGB}{248,172,37}
\definecolor{chart Ideal}{RGB}{1,151,0}
\definecolor{chart Over}{RGB}{0,125,234}

\newdimen\tempdim
\newcommand*{\Triangle}{%
  \settoheight{\tempdim}{L}%
  \tikz[x=\tempdim, y=\tempdim]\draw(0,0) -- (.5,.5) -- (0,1) --cycle;%
}
\newcommand*{\ChartLegend}[1]{%
  \ifdim\lastkern=1sp %
    \hspace{1em}%
  \fi
  \ChartBox{0.75em}{#1}%
  \,#1%
  \kern-1sp\kern1sp\ignorespaces
}
\newcommand*{\ChartBox}[2]{%
  \begingroup
    \settoheight{\tempdim}{L}%
    \edef\tempheight{\the\tempdim}%
    \settodepth{\tempdim}{g}%
    \edef\tempdepth{\the\tempdim}%
    \tikz[
      baseline=0pt,
      inner sep=0pt,
    ]
    \node[
      fill={chart #2},
      draw,
      rounded corners=1pt,
      anchor=base,
    ]{%
      \vphantom{g\"A}%
      \pgfmathsetlength{\tempdim}{#1}%
      \kern\tempdim\relax
    };%
  \endgroup
}

\begin{document}
\sffamily
\renewcommand*{\arraystretch}{1.2}
\newcommand*{\chart}[2]{%
  #1 & \ChartBox{55mm/3.420*#1}{#2}%
}
\noindent
\begin{tabular}{>{\Triangle\,}lS[mode=text,detect-family,table-format=1.3]@{\,s~}l}
\toprule
\multicolumn{1}{c}{%
  \multirow{2}{*}{Source Function\,/\,Function\,/\,Call Stack}%
}&
  \multicolumn{2}{c}{CPU Time by Utilization}\\
\multicolumn{1}{c}{}& \multicolumn{2}{l}{%
  \ChartLegend{Idle}
  \ChartLegend{Poor}
  \ChartLegend{Ok}
  \ChartLegend{Ideal}
  \ChartLegend{Over}
}\\
\midrule
\relax[Loop at line 151 in \function{divergence_part_1}] &
  \chart{3.420}{Poor} \\
\relax[Loop at line 1071 in \function{radiation_fvm}] &
  \chart{3.270}{Poor} \\
\function{scalar_face_value} &
  \chart{3.090}{Poor} \\
\relax[Loop at line 102 in \function{get_match}] &
  \chart{1.700}{Poor} \\
\function{get_sensible_enthalpy_diff} &
  \chart{1.250}{Poor} \\
\function{compare_vec3} &
  \chart{1.140}{Poor} \\
\bottomrule
\end{tabular}
\end{document}

Result

  • I am utterly amazed at this faithful and beautiful reproduction. But I'm accepting the simpler solution. – John Apr 25 '14 at 14:10
5

Example using PGFPlots (adapted from Pgfplots: plot graph inside table) , which takes care of the scaling and lets you generate the table and graph from a datafile:

\documentclass{article}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{pgfplotstable}
\usepackage{filecontents}

% The data file
% In a real application, this would be a text file in your file system
\begin{filecontents}{data.txt}
function,cpu time
Loop at line 151,3.42
Loop at line 107,3.27
Scalar face value,3.09
Loop at line 102,1.7
Get sensible enthalpy,1.25
Compare vec3,1.14
\end{filecontents}


\pgfplotstableread[col sep=comma]{data.txt}\data

% Define the command for the plot
\newcommand{\errplot}{%
\begin{tikzpicture}[trim axis right]
\begin{axis}[y=-\baselineskip,
  scale only axis,
  width=5cm,
  enlarge y limits={abs=0.5},
  axis y line*=middle,
  ytick=\empty,
  axis x line*=bottom,
  xbar,
  bar width=1.5ex,
  xmin=0,
  visualization depends on=x \as \rawx,
  nodes near coords,
  every node near coord/.style={
    anchor=east,
    shift={(axis direction cs:-\rawx,0)}
  }
 ]
% 

\addplot [draw=black, fill=red]
table [x=cpu time,y expr=\coordindex]{\data};
\end{axis}
\end{tikzpicture}%
}

\begin{document}

% Get number of rows in datafile
\pgfplotstablegetrowsof{\data}
\let\numberofrows=\pgfplotsretval

% Print the table
\pgfplotstabletypeset[columns={function, cpu time},
  % Booktabs rules
  every head row/.style={before row=\toprule,after row=\midrule},
  every last row/.style={after row=[3ex]\bottomrule},
  % Set header name
  columns/function/.style={string type,column type=l,column name=Function},
  columns/cpu time/.style={
    column name={CPU Time},
    assign cell content/.code={% use \multirow for Z column:
    \ifnum\pgfplotstablerow=0
    \pgfkeyssetvalue{/pgfplots/table/@cell content}
    {\multirow{\numberofrows}{6.5cm}{\errplot}}%
    \else
    \pgfkeyssetvalue{/pgfplots/table/@cell content}{}%
    \fi
    }
  },
]{\data}
%Done!
\end{document}

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.