Efficiently importing XPM matrix data into Mathematica

The XPM file format is an image file format. Although it is primarily intended for icon pixmaps, it can also be used to store matrix data. For example, the GROMACS chemical simulation package uses it in the program g_hbond to export hydrogen bond existence matrices.

A sample XPM file, generated by g_hbond is below:

/* XPM */
/* Generated by g_hbond_d */
/* This file can be converted to EPS by the GROMACS program xpm2ps */
/* title:   "Hydrogen Bond Existence Map" */
/* legend:  "Hydrogen Bonds" */
/* x-label: "Time (ps)" */
/* y-label: "Hydrogen Bond Index" */
/* type:    "Discrete" */
static char *gromacs_xpm[] = {
"201 2   2 1",
"   c #FFFFFF " /* "None" */,
"o  c #FF0000 " /* "Present" */,
/* x-axis:  0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 */
/* x-axis:  8 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 */
/* x-axis:  16 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20 0 */
/* y-axis:  0 1 0 */
"ooooooooooooooo oooooooooooooooooooo oo oooo ooooooooooo  oooooooooooooooooooooooooooooooooo   o oooooooooooooooo ooo oooooooooooooooooooooooooooooooooooooo ooooo ooo  oooooo  o oooooooo   ooooo oooooo",
"                                                                                                                                                                               o o                       "


This file is also available here, on Google Docs.

The last two lines provide the matrix data. If there is an "o" character, then that particular hydrogen bond (each line represents a different hydrogen bond) exists at that time.

Do you know if there are any functions or add-on packages for Mathematica that can read in XPM files? In particular, I would like to read in the last two lines:

"ooooooooooooooo oooooooooooooooooooo oo oooo ooooooooooo  oooooooooooooooooooooooooooooooooo   o oooooooooooooooo ooo oooooooooooooooooooooooooooooooooooooo ooooo ooo  oooooo  o oooooooo   ooooo oooooo",
"                                                                                                                                                                               o o                       "


and store the result as a List, Array, or SparseArray. Probably SparseArray would be desirable because the values in the matrix are binary -- a particular hydrogen bond either exists at a certain time or it doesn't. Also, it doesn't really matter what character we use to represent existence (in the above, they use "o") and absence (in the above, they use " ").

Do you have any advice on the best way to read in this data? The sample above is only very small; however, the files can get much larger, so I probably will not be able to import the entire file at once using Import. Probably I will have to read the file piecewise, perhaps using Stream.

-

Here is a string processing way of extracting the "x-axis" data from the XPM file that you gave. I'll assume that you have already imported the all of the file's records into the string text - e.g. using text = Import[filename,"String"], though I haven't tested this as I actually copied (then pasted into an empty string) the contents of the XPM file quoted in the OP's question.

text // StringCases[#,
"/* x-axis:" ~~ Whitespace ~~
s : Shortest[(NumberString ~~ Whitespace) ..] ~~
"*/" :> (ImportString[s, "Table"] // Flatten)] &


You can extract the "ooo..." line(s) as follows

text // StringCases[#, "\"" ~~ ("o" | Whitespace) .. ~~ "\""] &


String matching/processing tricks like this are very useful for importing structured data.

-