3

This question is a little left-of-field. I'm looking to generate a custom figure using data of the form:

Source Type Target Type Time
S-A T-B 1.52
S-C T-C 11.18
S-B T-A 21.31
S-D T-A 12.63
S-C T-D 7.92
  • Each of the first two columns contains four labels, either as strings or integers.
  • The final column is numeric.
  • This file may contain several hundred rows.

I wish to generate a figure similar to the following (e.g. approximated from the table above):

The approximate figure generated from the Table shown above.

The figure shows that S-A goes to T-B quickly: in 1.52 minutes. The height of all T-X bars is the maximum value in the time column. The point at which the arc from S-A intersects T-B is at 1.52 minutes.

Is this possible in Latex or another software package/platform? Ideally, I would also be able to style the figure. Most importantly, change the colours of the boxes and arcs. I am open to alternative figure templates if they convey the same information without interaction.

I've done quite some research, finding the likes of Flourish, but cannot seem to find something suitable for this use case.

7
  • Welcome to TeX.SE! What you try so far?
    – Zarko
    Commented Sep 13, 2022 at 2:56
  • Thank you! In Latex, I don't even know where to start, sorry - not without explicitly typing each data point as an edge. Commented Sep 13, 2022 at 3:27
  • 1
    If I correctly understand your comment, than use of LaTeX is no way to go.
    – Zarko
    Commented Sep 13, 2022 at 3:29
  • I've been proven wrong before! Feel free to delete the question if it's not possible, though. Commented Sep 13, 2022 at 4:16
  • Well. that isonly my opinion, maybe someone else have different opinion and see a way how todo this with (Lua)LaTeX.
    – Zarko
    Commented Sep 13, 2022 at 5:46

1 Answer 1

2

A starting point could be the following, which can be probably automated even further:

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix, positioning}
\usepackage{etoolbox}

\newlength\targetmaxheight
\setlength{\targetmaxheight}{3cm}

\newcounter{targetmaxvalue}
\setcounter{targetmaxvalue}{25}

\newlength\targetxsep
\newlength\targetysep
\setlength{\targetxsep}{1.5cm}
\setlength{\targetysep}{-.25cm}

\begin{document}

\begin{tikzpicture}[
    source/.style={
        matrix of nodes,
        nodes={
            draw
        }
    },
    target/.style={
        draw,
        minimum width=1cm,
        minimum height=\targetmaxheight,
    }
]

\let\mymatrixcontent\empty
\foreach \s in {S-A,S-B,S-C,S-D}{%
    \xappto\mymatrixcontent{ \s \\ }
}%

\node[source] at (0,0) (s) { 
    \mymatrixcontent
};

\node[target, above left=\targetysep and \targetxsep of s] (t-1) { T-A };
\node[target, above right=\targetysep and \targetxsep of s] (t-2) { T-B };
\node[target, below right=\targetysep and \targetxsep of s] (t-3) { T-C };
\node[target, below left=\targetysep and \targetxsep of s] (t-4) { T-D };

\draw (s-2-1) to[in=0, out=180] ([yshift={\targetmaxheight*(21.31/\value{targetmaxvalue})}]t-1.south east);
\draw (s-1-1) to[in=180, out=0] ([yshift={\targetmaxheight*(1.52/\value{targetmaxvalue})}]t-2.south west);
\draw (s-3-1) to[in=180, out=0] ([yshift={\targetmaxheight*(11.18/\value{targetmaxvalue})}]t-3.south west);
\draw (s-4-1) to[in=0, out=180] ([yshift={\targetmaxheight*(12.63/\value{targetmaxvalue})}]t-1.south east);
\draw (s-3-1) to[in=0, out=180] ([yshift={\targetmaxheight*(7.92/\value{targetmaxvalue})}]t-4.south east);

\end{tikzpicture}

\end{document}

enter image description here


With a bit more automation (probably not the most elegant way to do this):

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix, positioning}
\usepackage{etoolbox}

\newlength\targetmaxheight
\setlength{\targetmaxheight}{3cm}

\newcounter{targetmaxvalue}
\setcounter{targetmaxvalue}{25}

\newlength\targetxsep
\newlength\targetysep
\setlength{\targetxsep}{1.5cm}
\setlength{\targetysep}{-.25cm}

\begin{document}

\begin{tikzpicture}[
    node distance={
        \targetysep and \targetxsep
    },
    source/.style={
        matrix of nodes,
        nodes={
            draw
        }
    },
    target/.style={
        draw,
        minimum width=1cm,
        minimum height=\targetmaxheight,
    },
    connect/.code args={(#1) to (#2) at #3}{
        \path (#1);
        \pgfgetlastxy{\tempsx}{\tempsy}
        \path (#2);
        \pgfgetlastxy{\temptx}{\tempty}
        \draw (#1) to[
            in={\ifdim\tempsx<\temptx 180\else 0\fi}, 
            out={\ifdim\tempsx<\temptx 0\else 180\fi}
        ] ([yshift={\targetmaxheight*(#3/\value{targetmaxvalue})}]#2.south \ifdim\tempsx<\temptx west\else east\fi);
    }
]

\let\mymatrixcontent\empty
\foreach \s in {S-A,S-B,S-C,S-D}{%
    \xappto\mymatrixcontent{ \s \\ }
}%

\node[source] at (0,0) (s) { 
    \mymatrixcontent
};

\node[target, above left=of s] (t-1) { T-A };
\node[target, above right=of s] (t-2) { T-B };
\node[target, below right=of s] (t-3) { T-C };
\node[target, below left=of s] (t-4) { T-D };

\path[connect={(s-2-1) to (t-1) at 21.31}];
\path[connect={(s-1-1) to (t-2) at 1.52}];
\path[connect={(s-3-1) to (t-3) at 11.18}];
\path[connect={(s-4-1) to (t-1) at 12.63}];
\path[connect={(s-3-1) to (t-4) at 7.92}];

\end{tikzpicture}

\end{document}

The result looks the same as above.

2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .