Compiling SOM_PAK in Mac OS X 10.7 Lion

If you want to create some self-organizing maps on a Mac you’re going to need to compile some source code yourself. Assuming you have Apple’s Developer Tools installed, it should be fairly painless.

cd ~/Downloads
wget http://www.cis.hut.fi/research/som_pak/som_pak-3.1.tar
wget http://mike.eire.ca/wp-content/uploads/2012/02/som_pak.txt
tar xvf som_pak-3.1.tar
patch -bp0 < som_pak.txt
cd som_pak-3.1
cp makefile.unix makefile
make
make example
sudo make install
wget http://www.cis.hut.fi/research/som_pak/som_doc.ps
open som_doc.ps

That’s it. You should have these files in ~/Downloads/som_pak-3.1/ ready to crunch data:

  • lininit
  • mapinit
  • planes
  • qerror
  • randinit
  • sammon
  • umat
  • vcal
  • vfind
  • visual
  • vsom

This diff file – which is downloaded in the steps above – changes a couple of function names so they don’t conflict with existing function names (getline, getprogname, and setprogname.) It also changes the makefile to give us a usable build environment, places binaries into a subdirectory (bin/), and lets you make clean, make distclean, or make install.

--- som_pak-3.1/datafile.c	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/datafile.c	2012-01-31 22:26:41.000000000 -0800
@@ -122,7 +122,7 @@
 
   do 
     {
-      iline = getline(fi);
+      iline = getline_som(fi);
       row++;
       if (iline == NULL) {
 	fprintf(stderr, "Can't read file %s", fi->name);
@@ -157,7 +157,7 @@
   /* Currently all header information is on the first non-comment line, so 
      we just skip it. */
 
-  while ((iline = getline(fi)) != NULL)
+  while ((iline = getline_som(fi)) != NULL)
     if (iline[0] != '#')
       break;
 
@@ -608,7 +608,7 @@
   while (!line)
     {
       /* get line from file */
-      line = getline(fi);
+      line = getline_som(fi);
 
       /* The caller should check the entr->fi->error for errors or end
 	 of file */
--- som_pak-3.1/fileio.c	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/fileio.c	2012-01-31 22:26:46.000000000 -0800
@@ -276,10 +276,10 @@
 }    
 
 
-/* getline - get a line from file. Returns a char * to the line (a
+/* getline_som - get a line from file. Returns a char * to the line (a
    static buffer), NULL on error. */
 
-char *getline(struct file_info *fi)
+char *getline_som(struct file_info *fi)
 {
   static char *stre = NULL;
   static long strl = 0;
@@ -298,7 +298,7 @@
       stre = (char *) malloc(sizeof(char) * strl);
       if (stre == NULL)
 	{
-	  perror("getline");
+	  perror("getline_som");
 	  fi->error = ERR_NOMEM;
 	  return NULL;
 	}
@@ -319,14 +319,14 @@
 	  tstr = stre = realloc(stre, sizeof(char) * strl);
 	  if (stre == NULL)
 	    {
-	      perror("getline");
+	      perror("getline_som");
 	      fi->error = ERR_NOMEM;
 	      return NULL;
 	    }
 
 	  if (strl > ABS_STR_LNG) 
 	    {
-	      fprintf(stderr, "getline: Too long lines in file %s (max %d)\n",
+	      fprintf(stderr, "getline_som: Too long lines in file %s (max %d)\n",
 		      fi->name, ABS_STR_LNG);
 	      fi->error = ERR_LINETOOLONG;
 	      return NULL;
@@ -361,8 +361,8 @@
 	      /* read error */
 	      tstr = NULL;
 	      fi->error = ERR_FILEERR;
-	      fprintf(stderr, "getline: read error on line %d of file %s\n", fi->lineno, fi->name);
-	      perror("getline");
+	      fprintf(stderr, "getline_som: read error on line %d of file %s\n", fi->lineno, fi->name);
+	      perror("getline_som");
 	    }
 	  break;
 	}
@@ -377,7 +377,7 @@
 
 static char progname_real[512];
 
-char *setprogname(char *argv0)
+char *setprogname_som(char *argv0)
 {
   char *s, *s2;
   static char *progname = NULL;
--- som_pak-3.1/fileio.h	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/fileio.h	2012-01-31 22:26:52.000000000 -0800
@@ -66,10 +66,10 @@
 
 struct file_info *open_file(char *name, char *fmode);
 int close_file(struct file_info *fi);
-char *getline(struct file_info *fi);
+char *getline_som(struct file_info *fi);
 
 /* for getting the program name */
-char *setprogname(char *argv0);
-#define getprogname() setprogname(NULL);
+char *setprogname_som(char *argv0);
+#define getprogname_som() setprogname_som(NULL);
 
 #endif /* SOMPAK_FILEIO_H */
--- som_pak-3.1/lvq_pak.c	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/lvq_pak.c	2012-01-31 22:25:59.000000000 -0800
@@ -470,7 +470,7 @@
   char *s;
 
   /* set program name */
-  setprogname(argv[0]);
+  setprogname_som(argv[0]);
 
 #ifndef NO_PIPED_COMMANDS
   /* command for compressing */
--- som_pak-3.1/makefile.unix	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/makefile.unix	2012-02-29 16:39:52.000000000 -0800
@@ -1,10 +1,18 @@
-
-# 
-CC=cc
-CFLAGS=-O
-LDFLAGS=-s
+## Darwin (tested on OS X 10.7)
+## 
+CC=gcc
+CFLAGS=-O3
+LDFLAGS=
 LDLIBS=-lm
 LD=$(CC)
+BINDIR=bin/
+OUTDIR=output/
+# 
+#CC=cc
+#CFLAGS=-O
+#LDFLAGS=-s
+#LDLIBS=-lm
+#LD=$(CC)
 
 ## NetBSD-1.0 (tested on Amiga)
 ## 
@@ -59,46 +67,50 @@
 UMATOBJS=umat.o map.o median.o header.o
 OTHERFILES=header.ps
 
-all: vcal mapinit vsom qerror randinit lininit visual sammon planes vfind umat
+all: mkdirs vcal mapinit vsom qerror randinit lininit visual sammon planes vfind umat
+
+mkdirs:
+	mkdir -p $(BINDIR)
+	mkdir -p $(OUTDIR)
 
 vsom:	vsom.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ vsom.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ vsom.o $(OBJS) $(LDLIBS)
 
 vsomtest:	vsomtest.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ vsomtest.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ vsomtest.o $(OBJS) $(LDLIBS)
 
 qerror:	qerror.o $(OBJS) 
-	$(LD) $(LDFLAGS) -o $@ qerror.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ qerror.o $(OBJS) $(LDLIBS)
 
 mapinit:	mapinit.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ mapinit.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ mapinit.o $(OBJS) $(LDLIBS)
 
 randinit: mapinit
 	rm -f $@
-	ln mapinit $@
+	ln $(BINDIR)mapinit $(BINDIR)$@
 
 lininit: mapinit 
 	rm -f $@
-	ln mapinit $@
+	ln $(BINDIR)mapinit $(BINDIR)$@
 
 vcal:	vcal.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ vcal.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ vcal.o $(OBJS) $(LDLIBS)
 
 visual:	visual.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ visual.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ visual.o $(OBJS) $(LDLIBS)
 
 sammon:	sammon.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ sammon.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ sammon.o $(OBJS) $(LDLIBS)
 
 planes: planes.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ planes.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ planes.o $(OBJS) $(LDLIBS)
 
 vfind:	vfind.o $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ vfind.o $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ vfind.o $(OBJS) $(LDLIBS)
 
 # Umat
 umat:	$(UMATOBJS) $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ $(UMATOBJS) $(OBJS) $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $(BINDIR)$@ $(UMATOBJS) $(OBJS) $(LDLIBS)
 
 map.o umat.o:	umat.h fileio.h datafile.o lvq_pak.h labels.h
 median.o:	umat.h
@@ -117,16 +129,16 @@
 #BUFFER=-buffer 500
 
 example :
-	./randinit -din ex.dat -cout ex.cod -xdim 12 -ydim 8 -topol hexa \
+	./$(BINDIR)randinit -din ex.dat -cout $(OUTDIR)ex.cod -xdim 12 -ydim 8 -topol hexa \
   -neigh bubble -rand 123
-	./vsom  -din ex.dat -cin ex.cod  -cout ex.cod -rlen 1000 \
+	./$(BINDIR)vsom  -din ex.dat -cin $(OUTDIR)ex.cod  -cout $(OUTDIR)ex.cod -rlen 1000 \
   -alpha 0.05 -radius 10 $(TRAND) $(ALPHA_TYPE) $(BUFFER)
-	./vsom     -din ex.dat -cin ex.cod  -cout ex.cod -rlen 10000 \
+	./$(BINDIR)vsom     -din ex.dat -cin $(OUTDIR)ex.cod  -cout $(OUTDIR)ex.cod -rlen 10000 \
   -alpha 0.02 -radius 3 $(TRAND) $(ALPHA_TYPE) $(BUFFER)
-	./qerror   -din     ex.dat -cin ex.cod
-	./vcal     -din ex_fts.dat -cin ex.cod -cout ex.cod
-	./visual   -din ex_ndy.dat -cin ex.cod -dout ex.nvs
-	./visual   -din ex_fdy.dat -cin ex.cod -dout ex.fvs
+	./$(BINDIR)qerror   -din     ex.dat -cin $(OUTDIR)ex.cod
+	./$(BINDIR)vcal     -din ex_fts.dat -cin $(OUTDIR)ex.cod -cout $(OUTDIR)ex.cod
+	./$(BINDIR)visual   -din ex_ndy.dat -cin $(OUTDIR)ex.cod -dout $(OUTDIR)ex.nvs
+	./$(BINDIR)visual   -din ex_fdy.dat -cin $(OUTDIR)ex.cod -dout $(OUTDIR)ex.fvs
 
 fileio.o:	fileio.h
 datafile.o:	lvq_pak.h datafile.h fileio.h
@@ -137,3 +149,11 @@
 vcal.o mapinit.o vsom.o qerror.o visual.o sammon.o:\
 	lvq_pak.h datafile.h fileio.h labels.h som_rout.h 
 
+clean:
+	rm -f *.o
+
+distclean:
+	rm -rf *.o $(BINDIR)
+
+install:
+	cp $(BINDIR)* /usr/local/bin/
--- som_pak-3.1/map.c	1995-04-06 17:01:00.000000000 -0700
+++ som_pak-3.1/map.c	2012-01-31 22:27:01.000000000 -0800
@@ -1095,7 +1095,7 @@
 
   lask = -1;
   row = 1;
-  getline(in,s,maxline);
+  getline_som(in,s,maxline);
   do
     {
       ++lask;
@@ -1103,7 +1103,7 @@
       do
 	{
 	  ++row;
-	  getline(in,s,maxline);
+	  getline_som(in,s,maxline);
 	  /* if the row in the input file starts 
 	     with # or with newline, skip it     */
 	  if (strcmp(s,"")==NULL || s[0]=='#')
--- mapinit.c	1995-04-06 17:01:00.000000000 -0700
+++ mapinit.c	2012-04-16 20:18:28.000000000 -0700
@@ -68,7 +68,7 @@
       exit(0);
     }
 
-  progname = getprogname();
+  progname = getprogname_som();
 
   if (strcasecmp(progname, "lininit") == 0)
     init_type = IT_LIN;

3 Comments

  • Cheers for this Mike,

    it saved me a bit of time because I was having trouble with the redefinition of getline(), and there is not much else in the way of comments on the internet. In addition to your modifications I also had to modify the instance of getprogname() -> getprogname_som() in mapinit.c before running make, it threw an error otherwise.

    I also made a modification to fileio.h and extended the variable ABS_STR_LNG to 300000

    Cheers,

    • Glad to be of some help; I’ve made the update to the diff file to correct the omission in mapinit.c.

  • I had to add the “som_pak-3.1/” path to mapinit.c on lines 266-267, but other than that, it ran like a charm!

    Thanks for creating this and making it available, you’ve saved me a lot of time and frustration!
    Best

Leave a Reply

Your email address will not be published. Required fields are marked *

− one = 7

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>