Monday 8 March 2010

LaTeX insect labels

No, not labels made out of the sap of Hevea brasiliensis, but labels typeset using the LaTeX typesetting language---a very versatile and powerful language that typesets rather nice looking documents. I wrote my thesis using it and found the experience to be very enjoyable and rewarding.

Up until now, I've printed labels for pinned insect specimens using a Word template. This has been adequate, however I find there are two really annoying aspects of this method. The first is that you've got to try and count how many carriage returns you enter to centre a single-lined habitat label, and if you get it wrong it messes up the rest of the document. The other is making duplicate labels, the only way which I know how being to copy the label data and "Ctrl-V" it as many times as required, once again ensuring there's neither too much or not enough space between labels.

So, with the thesis out of the way, I've turned my attention to creating a LaTeX template to create insect labels from an A4 sheet of paper. It is available here: labels.tex. Hopefully it is relatively straightforward to work out when you read the file and comments contained therein. The size of the labels is based on those in the classic New Zealand guide to insect curation (Walker and Crosby, 1988). I just found out that this very useful reference is freely available online here. Thanks Landcare Research!

The guts of the file is as follows:

To get a really small font suitable for insect labels, the following commands are made:

\def\supertiny{\font\supertinyfont = cmss10 at 3.75pt \relax \supertinyfont}

\def\supertinyitalic{\font\supertinyfont = cmssi10 at 3.75pt \relax \supertinyfont}

\newcommand{\scinm}[1]{\supertinyitalic{#1}}
\supertiny is declared after \begin{document} to make the text of the entire document miniscule. Unfortunately, \emph doesn't work correctly when you've modified the size in this way, so \supertinyitalic is created and turned into a function \scinm which converts text (usually scientific names) into italics.

Next up is creating an environment to make duplicate labels:

\newcounter{speclabel@}
\newcounter{speclabel@@}
\newsavebox{\TMPspeclabel}
\newenvironment{speclabel}[1][1]{
\setcounter{speclabel@@}{#1}
\begin{lrbox}{\TMPspeclabel}
\begin{minipage}{\columnwidth}
\vspace{0.5ex}
\raggedright}
{
\end{minipage}
\end{lrbox}
\setcounter{speclabel@}{0}
\loop\ifnum \value{speclabel@} < \value{speclabel@@}
\stepcounter{speclabel@}
\usebox{\TMPspeclabel}
\endgraf\repeat}
The above code is modified from that available in etiketka.cls in the shipunov package. Each set of labels (both locality and habitat labels) are prefaced with \begin{speclabel}[5] where 5 in this case indicates that the contents of the environment should be duplicated five times.

Finally, we want to have each label of a consistent height. I achieved this by employing the tabularx package. However, the vagaries of the tabularx package made it easier to program it using two environments rather than working out how to make a single one do it all:

\newsavebox{\BoxB}

\sbox{\BoxB}{\begin{tabularx}{0.1mm}{Y}
\rule[-8mm]{0pt}{8mm}
\end{tabularx}
}

\newenvironment{lab_height}{\begin{tabular}{cc}}
{& \makebox{\usebox{\BoxB}}
\end{tabular}
}

\newenvironment{hablabel}{\tabularx{11.9mm}{@{}Y@{}}}
{\endtabularx}
This is a bit clunky, but it works. Reasonably well at least. BoxB creates a table of fixed width that contains a strut which fixes the height of the label. Currently this is 8 mm. When hablabel is nested within lab_height the contents of hablabel is put into a cell in a table the height of which is defined by BoxB. When the contents of hablabel takes up less height than BoxB, the result is a whole bunch of nicely spaced labels. When it takes up more height, things are pushed around a little, but it doesn't break labels.

Here's an example of a fully typeset label:

\begin{speclabel}[3]
\begin{lab_height}
\begin{hablabel}
NEW ZEALAND BR\\
Nina Valley Track\\
Lewis Pass\\
1 Jan 2009\\
SDJ Brown\\
\end{hablabel}
\end{lab_height}

\begin{lab_height}
\begin{hablabel}
{\scinm{Weinmannia}} leaves close to road.
\end{hablabel}
\end{lab_height}
\end{speclabel}


You can see the end results here.

I'm not much of a LaTeX programmer and undoubtedly there are more elegant, powerful and useful methods of programming the above. However, this provides for my needs adequately enough. Hopefully others might find it of use also.

While trying to figure how to do all this, a search on Google for "latex insect labels" gave this humble site as the first on the list. I figure that the least I can do is actually make sure that it delivers on its promise...

EDIT:
labels.tex is now available on gitHub. The PDF showing the results can be downloaded from Dropbox.

References:
Walker AK, Crosby TK. 1988. The preparation and curation of insects. DSIR Information Series 163. DSIR; Wellington.

11 comments:

Kirsty F. McGregor said...

Wow, you should show Rupert this stuff.

Matt Bowser said...

Dear Samuel Brown,

I found this post useful. I tried some of your code with good results, but then I ended up moving to XeTeX to take advantage the way it handles fonts.

We recently moved the small collection of the Kenai National Wildlife Refuge to Arctos. I had been trying to comply with the label standards of the Biological Survey of Canada.

Below is an example of TeX output from Arctos for insect labels. The Arctos developers also deserve credit for their help with this.

There is still plenty of room for improvement, but I am using these lables now.

\documentclass[10pt]{article}
\usepackage{xltxtra}
\usepackage{multicol}
\usepackage[margin=1cm]{geometry}

%% Font.
\setmainfont[Scale=0.3, PunctuationSpace=3, WordSpace = 0.3]{TeX Gyre Heros}
%% Inter-line spacing.
\linespread{0.25}

%% Commands for typesetting labels.
\renewcommand{\fboxsep}{0.2mm}
\newcommand{\insectlabel}[1]{\fbox{\parbox{16mm}{\raggedright #1}}\\}
\newcommand{\idlabel}[1]{\fbox{\parbox{4mm}{\centering\bfseries #1}}\\}
\setlength{\columnsep}{1mm}
\setlength{\parindent}{0mm}

\begin{document}
\begin{multicols}{10}

\insectlabel{USA: Alaska. Headquaters Lake 60.4627°N 151.0744°W ±6m. 24-Jun-2009. Matt~Bowser}\idlabel{KNWR 7000}
\insectlabel{USA: Alaska. Soldotna, Headquarters Lake 60.4627°N 151.0741°W ±50m. 02-May-2011. Matt~Bowser}\idlabel{KNWR 7003}
\insectlabel{USA: Alaska. Soldotna, Ski Hill Road. Kenai National Wildlife Refuge Headquarters 60.4647°N 151.0735°W ±50m. 01-Sep-2006. Todd~Eskelin}\idlabel{KNWR 7004}
\insectlabel{USA: Alaska. Finger Lake Road 60.6556°N 150.8756°W ±80m. 18-Jun-2004. Dominique~M.~Collet}\idlabel{KNWR 7005}
\insectlabel{USA: Alaska. Kenai, Beaver Loop Road 60.5485°N 151.1464°W ±50m. 22-May-2005. Todd~Eskelin}\idlabel{KNWR 7006}
\insectlabel{USA: Alaska. Headquaters Lake 60.4626°N 151.0771°W ±250m. 03-Jun-2005. Matt~Bowser}\idlabel{KNWR 7007}
\insectlabel{USA: Alaska. Black spruce forest by Swanson River southeast of Grus Lake 60.7648°N 150.6512°W ±2km. 25-Aug-2008. Matt~Bowser}\idlabel{KNWR 7008}
\insectlabel{USA: Alaska. Soldotna, Headquarters Lake 60.4619°N 151.0755°W ±50m. 23-May-2011. Matt~Bowser}\idlabel{KNWR 7017}
\insectlabel{USA: Alaska. Kasilof, Old Kasilof Road 60.3632°N 151.2699°W ±20m. 06-Jun-2011. Matt~Bowser}\idlabel{KNWR 7022}
\insectlabel{USA: Alaska. Kasilof. Old cabin access trail between north end of Old Kasilof Road and the Kasilof River. 60.3653°N 151.2814°W ±80m. 14-Jun-2011. Matt~Bowser}\idlabel{KNWR 7038}
\insectlabel{USA: Alaska. Kasilof. Kasilof River flats near north end of Old Kasilof Road. 60.3651°N 151.2859°W ±60m. 14-Jun-2011. Matt~Bowser}\idlabel{KNWR 7039}
\insectlabel{USA: Alaska. Kasilof. Kasilof River flats near north end of Old Kasilof Road. 60.3651°N 151.2859°W ±60m. 14-Jun-2011. Matt~Bowser}\idlabel{KNWR 7040}
\insectlabel{USA: Alaska. Kasilof. Kasilof River flats near north end of Old Kasilof Road. 60.3651°N 151.2859°W ±60m. 14-Jun-2011. Matt~Bowser}\idlabel{KNWR 7041}
\end{multicols}
\end{document}

Matt Bowser said...

The following ended up being a better font and better spacing.

%% Font.
\setmainfont[Scale=0.29, PunctuationSpace=0.5, WordSpace = 0.3]{Droid Sans}
%% Inter-line spacing.
\linespread{0.26}

Samuel Brown said...

Thanks Matt for letting me know about that and for giving me an incentive to try out XeTeX!

Unknown said...

Hi, I'd love to use your template, but I'm having problems connecting to the link. Could you please repost?

Samuel Brown said...

Hi Lue

I've moved the tex file to gitHub, while the PDF showing the results can be downloaded from Dropbox.

Thanks for the interest!

Matt Bowser said...

Below is the URI for a post on using XeTeX to generate insect labels with QR code labels.

http://www.akentsoc.org/archives/295

Samuel Brown said...

That's a really cool post that you've written Matt. Thanks for sharing!

I've used the combination of R and LaTeX for creating project labels with specimen numbers. However, the addition of a QR code steps up the sophistication significantly.

Rick said...

Hey Guys,

Thanks so much for doing this. Before I found this post I had modified the generic "mail labels" template from LaTex. I do have a question about how you are using the template as you have laid it out on this post. Are you manually entering the label information—or do you have an R script or something that writes to the file. Excuse my ignorance, I just can't quite figure that part out. What I have been doing is this where I have a file that R writes to and then the template just creates labels from whatever is in the data file. I'm a unclear on how to setup this up with the templates you have provided. Thanks!




\documentclass[legalpaper, 9pt]{memoir}
\usepackage[newdimens]{labels}
\usepackage{gensymb}
\LabelCols=6 % Number of columns of labels per page
\LabelRows=25 % Number of rows of labels per page

\LeftPageMargin=2mm % These four parameters give the
\RightPageMargin=2mm % page gutter sizes. The outer edges of
\TopPageMargin=2mm % the outer labels are the specified
\BottomPageMargin=2mm % distances from the edge of the paper.

\InterLabelColumn=1mm % Gap between columns of labels
\InterLabelRow=1mm % Gap between rows of labels

\LeftLabelBorder=1mm % These four parameters give the extra
\RightLabelBorder=1mm % space used around the text on each
\TopLabelBorder=0mm % actual label.
\BottomLabelBorder=0mm %

\begin{document} % End of preamble

\begin{miniscule}
\begin{labels}



\labelfile{pinned_label_data.txt}



\end{labels}
\end{miniscule}
\end{document}



Matt Bowser said...

Dear Unknown,

I download specimen data from Arctos (http://arctosdb.org/, http://arctos.database.museum/), our collection management system, then I run an R script that makes the QR code images and makes the TeX file. The barcodes are used in Arctos' container management system. I was focusing on just the TeX layout part for this post, but I would be happy to provide my script.

-Matt

Rick said...

Oh okay, thanks! That makes a lot of sense. I just wanted to make sure I wasn't missing something.