# Create association lines between characters

I intend to create "association lines" between characters, where the start of the line is one or more characters inside a word, and the end of the line is a single character. Something like this (created in MS Word):

I'm trying to mimic/replicate something from a book, where it looks like this:

It doesn't matter much for my purposes whether the lines are underneath or above the words (but it would be nice if I knew how to do either). I think it would be best to have these drawings as figures (i.e. inside a figure environment or something similar).

I'm sure there are lots of different ways one can accomplish this, but I have (as of yet) no reasons to prefer one way or another (simply because I have no idea how to do this). I'm open to all suggestions.

EDIT: Questions about pst-asr based on Alan Munn's suggestion.

MWE:

\documentclass{article}
\usepackage{pst-asr, fontspec}
\setmainfont{Linux Libertine O}
\begin{document}
\psset{
reptype = nots, % representation type = no timing slots
xgap = 0.5em, % set width of space between each character (how can this be set to the 'normal' space between characters?)
sysym = L, % what does this do? I changed it to 'H', but the output is the same
syB = 2em, % set the distance between the top of the phoneme tier and the bottom of the syllable tier?
everyph = \normalfont % the format of every character on the phoneme tier
}
\asr[syB = 2em] asa| % why does syB need to be set independently for this one?
\tierput(1,sy){H} % put what's in {} in character position 1 on the syllable tier
\assoc(1,sy)(1,ts) % draw association line from the bottom of character position 1 on the syllable tier to the bottom of character position 1 on the time slot tier
\endasr
\hspace{3em}
\asr asta|
\tierput(1,sy){H}
\assoc(1,sy)(1,ts)
\assoc(1,sy)(2,ts)
\endasr
\end{document}


If you need to do a lot of these, the pst-asr package is extremely powerful, but somewhat complicated. Compile the following with XeLaTeX. (Since it uses pstricks it can't be compiled with pdfLaTeX directly, and either needs XeLaTeX (as in this example) or LaTeX+dvips (in which case you would use the tipa package and not load fontspec, etc.) The spacing between the elements on a tier are determined by the xgap parameter. Setting it to .5em seems to produce reasonable spacing.

\documentclass[png,convert,border=4pt]{standalone}
\usepackage{pst-asr}
\usepackage{fontspec}
\newfontfamily\IPAfont{Doulos SIL}
\begin{document}
\psset{reptype=nots,xgap=.5em,sysym=L,syB=2.5em,everyph=\IPAfont}
\asr[syB=2.5em] asa|
\tierput(1,sy){H}\assoc(1,sy)(1,ts)
\endasr
\hspace{3em}
\asr asta|
\tierput(1,sy){H}\assoc(1,sy)(1,ts)\assoc(1,sy)(2,ts)
\endasr
\hspace{3em}
\asr /h{ɛ̆}s.tʏr/|
\tierput(4,sy){H}\assoc(4,sy)(2,ts)\assoc(4,sy)(6,ts)|
\endasr
\end{document}


If you only have to do a few of these, it might not be worth your while to learn the pst-asr package, in which case, you can do them fairly easily by hand using TikZ and its matrix library. By setting the inner and outer sep of the nodes, we can reduce the spacing between them adequately.

\documentclass[png,border=4pt]{standalone}
\usepackage{fontspec}
\setmainfont{Doulos SIL}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}
\begin{tikzpicture}
\matrix (A) [matrix of nodes,nodes={inner sep=0pt,outer sep=1pt}] {
& H &\\[3ex]
a & s & a\\
};
\draw (A-1-2) -- (A-2-2);
\begin{scope}[xshift=4cm]
\matrix (B) [matrix of nodes, nodes={inner sep=0pt,outer sep=1pt}]{
/ & h & ɛ̆ & s &. & t & ʏ & r &/\\[3ex]
& & & & H & & & & \\
};
\draw (B-2-5.north) -- (B-1-3.south);
\draw (B-2-5.north) -- (B-1-7.south);
\end{scope}

\end{tikzpicture}
\end{document}


• Wow, yeah, I'm gonna need some time to go through and understand all of these settings ... btw, the H is a "color" which can associate to both vowels (giving a high tone) and to consonants (giving aspiration). It's something called 'Dependency Phonology' ... not a theory I'm using, so don't ask me about details :P – Sverre Oct 20 '13 at 12:33
• Is there a way to do this (with either pst-asr or TikZ) that doesn't create these huge spaces between the characters inside the words (in order to replicate what the book does)? – Sverre Oct 20 '13 at 12:36
• I read through the pst-asr manual and understood almost nothing. I've edited my question with a MWE containing some questions about the settings in Alan's pst-asr MWE. – Sverre Oct 20 '13 at 14:00
• @sverre I don't use the pst-asr package myself, and its author is a Plain TeX person, which is why the documentation is not very easy to understand. I've added some adjustments to the spacing in both of the examples. – Alan Munn Oct 21 '13 at 1:42

that are simple node connection which can be done by a tabular and \rnode:

\documentclass[12pt]{article}
\usepackage{libertine}
\usepackage{pst-node}
\newcommand\rNode[3][c]{\rnode[#1]{#2}{\strut#3}}%Use \strut to get the same height for every node
\newcommand\expl[2]{{\def\arraystretch{1.7}\tabular{@{}c@{}}\strut#1\strut\endtabular%
#2}}% stretch the tabular and execute the connections #2
\begin{document}

\expl{\rNode[b]{A}{H} \\ a\rNode[t]{a}{s}a}%  [b] bottom, [t] top node
{\ncline{A}{a}}
\expl{\rNode[b]{A}{H} \\ a\rNode[t]{a}{s}\rNode[t]{b}{t}a}%
{\ncline{A}{a}\ncline{A}{b}}

\expl{/h{ɛ̆}\rNode[b]{A}{s}.\rNode[b]{B}{t}ʏr/ \\ \rNode[t]{a}{H}}%
{\ncline{A}{a}\ncline{B}{a}}
\end{document}


• see my edited answer. – user2478 Oct 20 '13 at 16:24
• What does the [3][c] refer to? – Sverre Oct 20 '13 at 17:55
• 3 parameter, the first one is optional and if not set it is c – user2478 Oct 20 '13 at 17:58
• c is the default setting. In your example it is not used. You can set it to [b] then it is the default and you need only the [t] to set. – user2478 Oct 20 '13 at 18:12
• download mirrors.ctan.org/info/latex2e-reference.tar.gz, unzip it and look for \newcommand – user2478 Oct 20 '13 at 18:53

Essentially the same as Alan Munn's TikZ answer only with the specification of the text made a bit easier and every letter is typeset using the tipa package. Note that characters are typeset separately so no kerning or ligatures, and characters that involve macros (e.g., \v{E}) have to be fully contained within braces (e.g., {\v{E}}) otherwise havoc will ensue.

\documentclass[12pt]{standalone}
\usepackage{tipa}
\usepackage{tikz}
\usetikzlibrary{matrix}

% These macro's just iterate over every character in the
% string passed as a macro and executes \dochar{<character>}\inchar
% for each character.
%
% Try:
%
% \def\dochar#1{#1}\dorow{ABCDEF}
%
% Result:
%
% A&B&C&D&E&F
%
\def\dorow#1{\expandafter\DoRow#1\dorow}
\def\DoRow#1{\ifx#1\dorow\else\dochar{#1}\inchar\expandafter\DoRow\fi}

% Inside a matrix \& shifts to the next cell
\def\inchar{\&}
% Inside a matrix \dochar adds a node with the character inside it
\def\dochar#1{\node[every asr node/.try]{\strut\textipa{#1}};}

\tikzset{%
% This style is executed for every asr node.
% Every asr node contains a single character, and is
% named according to \asrprefix and the current matrix column.
%
% If \asrprefix is A, then the characters are named A-1, A-2, A-3... etc
every asr node/.style={
inner sep=0pt,
anchor=base,
name=\asrprefix-\the\pgfmatrixcurrentcolumn,
},
asr/.style={/tikz/asr/.cd, #1,
/tikz/.cd,
insert path={%
node [matrix, column sep=0pt, ampersand replacement=\&] {\dorow{\asrtext}\\}
}
},
asr/.cd,
% The next for the association
text/.store in=\asrtext,
text=,
% The prefix for every node.
prefix/.store in=\asrprefix,
prefix=,
}

\begin{document}

\begin{tikzpicture}

% Draw the H node
\node (H) {H};

% Draw the asr matrix below the H node
\path (H)++(0,1) [asr={prefix=A, text=/h{\v{E}}s.tYr/}];
\draw (H) -- (A-4) (H) -- (A-6);

\node (H) at (1,0) {H};
\path (H)++(0,-1) [asr={prefix=B, text=asa}];
\draw (H) -- (B-2);

\path (2, -1) [asr={prefix=C, text=asta}];
% Align the H node above the third character
\node [above of=C-3] (H) {H};
\draw (H.south) -- (C-2)
(H.south) -- (C-3);

\end{tikzpicture}

\end{document}


• The problem is that I wouldn't even know where to begin in order to wrap my head around this ... :-/ – Sverre Oct 20 '13 at 16:35

Here is a method using nothing else than LaTeX's picture as enhanced by pict2e.

The command \Alines has also a starred variant.

\documentclass {article}
\usepackage{pict2e}

\newlength{\dima}
\newlength{\dimb}
\newlength{\dimc}
\newlength{\dimd}

\makeatletter
\newcommand{\Alines}{\@ifstar{\Alinesb}{\Alinesa}}
\makeatother

\newcommand{\Alinesa}[1]{\xxx #1\xxx }
\newcommand{\Alinesb}[1]{\yyy #1\yyy }

\def\xxx #1\al #2#3\AL#4#5\xxx
{\settowidth{\dima}{#2}%
\settowidth{\dimb}{#3}%
\settowidth{\dimc}{#4}%
\setlength{\dimd}{\ht\strutbox}%
\setlength{\unitlength}{1sp}%
#1%
\begin{picture}(\numexpr \dima+\dimb+\dimc,\numexpr 3*\dimd)
\put (0,0){#2#3#4}
\moveto(\numexpr \dima/2,\numexpr 9*\dimd/10)
\lineto(\numexpr 3*\dima/4+\dimb/2+\dimc/4,\numexpr 18*\dimd/10)
\lineto(\numexpr \dima+\dimb+\dimc/2,\numexpr 9*\dimd/10)
\strokepath
\put (\numexpr 3*\dima/4+\dimb/2+\dimc/4,\numexpr 2*\dimd)
{\makebox[0pt]{H}}
\end{picture}%
#5%
}

\def\yyy #1\al #2#3\AL#4#5\yyy
{\settowidth{\dima}{#2}%
\settowidth{\dimb}{#3}%
\settowidth{\dimc}{#4}%
\setlength{\dimd}{\ht\strutbox}%
\setlength{\unitlength}{1sp}%
#1%
\begin{picture}(\numexpr \dima+\dimb+\dimc,\numexpr 3*\dimd)
\put (0,0){#2#3#4}
\moveto(\numexpr \dima/2,\numexpr 9*\dimd/10)
\lineto(\numexpr \dima+\dimb+\dimc/2,\numexpr 18*\dimd/10)
\lineto(\numexpr \dima+\dimb+\dimc/2,\numexpr 9*\dimd/10)
\strokepath
\put (\numexpr \dima+\dimb+\dimc/2,\numexpr 2*\dimd)
{\makebox[0pt]{H}}
\end{picture}%
#5%
}

\begin{document}\thispagestyle{empty}

\Alines {\al{/h{\v{E}}}s.t\AL Yr/}

\Alines {abced\al{duisu}dsiudu\AL Yqodo}

\Alines {\al{as}\AL sa}

\Alines* {\al{/h{\v{E}}}s.t\AL Yr/}

\Alines* {abced\al{duisu}dsiudu\AL Yqodo}

\Alines* {\al{as}\AL sa}

\end{document}


This is certainly not perfect, but I think the code is simple enough to be very easily customized. Output:

• As I'm sure you'll understand based on my comments to the other suggestions here, I cannot understand code of this complexity (unless it is "commented for dummies"). Which means I won't be able to customize it ... :-/ My own comments to the pst-asr solution (in the edited MWE in my original question) are an indication at what level it needs to be for me to understand the code. – Sverre Oct 20 '13 at 18:27
• @Sverre I use the picture environment as described in Lamport's book, with the \lineto, \moveto and \strokepath extensions of package pict2e. \moveto puts the pen at a point of given coordinates, and \lineto draws a line from there to the new coordinates. The \strokepath draws the path. I use a unit length of 1sp=1/65536 pt, the advantage being that \number\dima converts a dimension to an integer giving its value in sp's, and it is then easy to manipulate these dimensions within a \numexpr...\relax. That's pretty all there is to it plus macros with delimited parameters – user4686 Oct 20 '13 at 18:39
• forgot to say that a peculiarity of the picture thing is that it insists on being given coordinates as integers; and also the specified (width,height) must be integers. This is why I put the dimensions in a \numexpr (texdoc etex) which converts them to such integers, but as multiple of the smallest unit the sp. When I said my proposed answer was simple, it was to say that it didn't need some specific package but only the tools of LaTeX (suitably extended in more recent years). – user4686 Oct 20 '13 at 18:44

To get the right space in the last asr you can use the juncture character '.

\documentclass[png,convert,border=4pt]{standalone}
\usepackage{pst-asr}
\psset{everyasr=\tiershortcuts} % this allows you to use \@ and \- instead of \tierput and \assoc
\usepackage{fontspec}
\newfontfamily\IPAfont{Doulos SIL}
\begin{document}
\psset{reptype=nots,xgap=.5em,sysym=L,syB=2.5em,everyph=\IPAfont}
\asr[syB=2.5em] asa|
\@(1,sy){H}\-(1,ts)
\endasr
\hspace{3em}
\asr asta|
\@(1,sy){H}\-(1,ts)\-(2,ts)
\endasr
\hspace{3em}
\asr /h{ɛ̆}s'.tʏr/| % here is the juncture trick
\@(3.5,sy){H}\-(2,ts)\-(5,ts)|
\endasr
\end{document}


This is the result.

With simpler code:

\psset{reptype=nots,xgap=.4em,sysym=H,syB=2.5em,everyph=\IPAfont}
\asr a\1sa  \endasr
\hspace{3em}
\asr a\2sta  \endasr
\hspace{3em}
\asr /h{ɛ̆}s'.tʏr/|
\@(3.5,sy){H}\-(2,ts)\-(5,ts)|
\endasr

• Do you know if there is a way to get "normal" character space between the characters on the bottom tier? – Sverre Oct 21 '13 at 12:03
• If I understand correctly, you can change the xgap setting to 0.4; this will be almost as normal gap between characters. – Stefano Oct 21 '13 at 12:24
• Sure, I set it to 0.5em. But this is, of course, a magic number, which I ideally would like to avoid. – Sverre Oct 21 '13 at 14:27
• The distance of units in the tiers is set with that option, so you have to manage working with it. Anyway, if you put the asr in a example enviroment (which I suggest) you don't have to worry about the space to be "normal". As for the sysym option, it changes the symbol that the parser uses: you can see the result of changing this only if you use the command for syllable parsing (like \asr \2pa\2ne \endasr which will typeset two L's instead of the sigma). – Stefano Oct 21 '13 at 16:11
• @Sverre it is if you use the first code block, not if you use the "simpler" code below it in this answer. This is because the symbol is used if you use \1, \2, \n in your asr. I am working on a short guide, I can email you the first draft if you want. – Stefano Oct 22 '13 at 20:33

I have a "clean" option for you (less code).

I often use the tikz-dependencypackage for this kind of thing. It was not designed for it, but I think it is easier than some of the other tikz methods, because it is a nice wrapper for tikz. You still have access to most of tikz's functions, but with less code. I use it all the time for linguistic purposes.

The following is a sample, which routes arrows to words, as intended for the package.

\documentclass[12pt]{standalone}
\usepackage{fontspec}
\usepackage{tikz-dependency}

\begin{document}

\begin{dependency}[theme=night]
\begin{deptext}
My \& idea \& was \& to \& use \& the \& tikz-dependency \& package! \\
\end{deptext}

\depedge[<->]{1}{2}{Test}
\end{dependency}

\end{document}


This could easily be modified to produce the desired effect:

\documentclass[12pt]{standalone}
\usepackage{fontspec}
\usepackage{tikz-dependency}

\begin{document}

\begin{dependency}[theme=night]
\begin{deptext}
M \& y \&  \& i \& d \& e \& a \&  \& w \& a \& s \&  \& t \& o \&  \& u \& s \& e \&  \& t \& h \& e \&  \& ... \\
\end{deptext}

\depedge[<->]{1}{2}{Test}
\end{dependency}

\end{document}


HINT:

1. If you are using TeXShop on a mac, you can even use my AppleScript and give it a key binding (mine is command+d). To use it, put it in your macros (under AppleScripts would be a good idea) and select the text between \begin{deptext} and \end{deptext} and run the macro. I will put in the \& appropriately as the delimiter and \\ to close the string. Just FYI, it does not support selecting multiple lines yet, but I usually have a maximum of three lines, so it is not hard to select three lines one at a time.
2. You can add [column sep=-.5ex], for example after \begin{deptext} to change the width between delimiters.

--Applescript
tell application "TeXShop" to get content of selection of the front document
set newText to (replacement of " " by " \\& " for the result)
my trim_2(newText, "\\&")

tell application "TeXShop"
--get the front document
set thisDoc to the front document
--get the current selection text, offset, and length
set selContent to content of selection of thisDoc
--set selOffset to offset of selection of thisDoc
--set selLength to length of selection of thisDoc
set content of selection of thisDoc to newText & " \\\\"
end tell

on replacement of oldDelim by newDelim for sourceString
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to oldDelim
set strtoks to text items of sourceString
set text item delimiters of AppleScript to newDelim
set joinedString to strtoks as string
set text item delimiters of AppleScript to oldTIDs
joinedString
end replacement

on trim_2(strg, trim_characters)
set trim_list to every character of trim_characters

-- do the right trim
set right_counter to -1
repeat with J from 1 to length of strg
if (character right_counter of strg) is in trim_list then
set right_counter to right_counter - 1
else
exit repeat
end if
end repeat
try
set strg to text 1 through right_counter of strg
on error
set strg to ""
end try
-- end right trim
return strg
end trim_2

• You could just use \def\torow#1{\ToRow#1\torow}\def\ToRow#1{\ifx#1\torow\else#1\&\expandafter\ToRow\fi} which will loop through the argument character by character adding \& as necessary (it actually provides one too many). Then just do \torow{My\ idea\ was\ this!}. – Mark Wibrow Oct 21 '13 at 10:32
• @macmadness That's clearly a much simpler code to understand, but as you can see, the black box with arrows pointing down to the words doesn't correspond very well to what I am trying to accomplish ... – Sverre Oct 21 '13 at 12:04
• @Sverre Perhaps changing the theme to [theme=simple] would help. The lines would still not be straight as you requested, rather curved. I will consider how to accomplish this... – Jonathan Komar Oct 21 '13 at 21:07
• @macmadness86 solution with tikz-dependency is intriguing, however I need a variant, in which the characters are not spaced, i.e. like in normal words. I tried to achieve that with [column sep=0], but this does not give the desired result. Moreover, I am looking for a way create manyfold dependencies between characters, in order to point out alliterations and assonances. Does anyone habe an idea how this can be achieved? The result should look like the nodes with text and arrow pointers in the tikz-dependency package. – Oli Oct 17 '15 at 19:52