Index: /branches/tools-1-0/Ohana/src/tools/Makefile
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/Makefile	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/Makefile	(revision 13149)
@@ -0,0 +1,62 @@
+default: tools
+help:
+	@echo "make options: tools (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/tools
+SRC	=	$(HOME)/src
+LIB	= 	$(HOME)/lib
+MAN	=	$(HOME)/doc
+BIN	=	$(HOME)/bin
+INC	=	$(HOME)/include
+
+FULL_CFLAGS   =	$(CFLAGS)
+FULL_CPPFLAGS = $(CPPFLAGS) -I$(INC) -I$(DESTINC) $(INCDIRS) -D$(ARCH)
+FULL_LDFLAGS  = $(LDFLAGS) -L$(LIB) -L$(DESTLIB) $(LIBDIRS) -ldvo -lFITS -lohana $(LIBFLAGS)
+
+# these are all programs which just depend on a single c file: foo : foo.c
+# we use a special set of rules in this directory which expect this simplification
+
+PROGRAMS = gconfig fhead ftable fields list_astro glockfile \
+radec mktemp precess csystem fits_insert \
+medianfilter mefhead ckfits
+
+tools: $(PROGRAMS)
+
+$(PROGRAMS): % : $(BIN)/%.$(ARCH)
+
+# copied from Makefile.Common : use a single c file: foo : foo.c
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
+
+%.$(ARCH).o : %.c
+	$(CC) $(FULL_CFLAGS) $(FULL_CPPFLAGS) -c $< -o $@
+
+$(BIN)/%.$(ARCH) : $(SRC)/%.$(ARCH).o
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $(FULL_CFLAGS) -o $@ $^ $(FULL_LDFLAGS)
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(PROGRAMS); do make $$i.install || exit; done
+
+%.clean:
+	rm -f $(SRC)/$*.$(ARCH).o
+	rm -f $(BIN)/$*.$(ARCH)
+
+clean:
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -rf $(BIN)
+	rm -rf $(LIB)
Index: /branches/tools-1-0/Ohana/src/tools/bin/.cvsignore
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/bin/.cvsignore	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/bin/.cvsignore	(revision 13149)
@@ -0,0 +1,2 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
Index: /branches/tools-1-0/Ohana/src/tools/src/ckfits.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/ckfits.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/ckfits.c	(revision 13149)
@@ -0,0 +1,58 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int main (int argc, char **argv) {
+
+  int i, Nbytes, nbytes, Ndata, Ntotal, nskip, status;
+  Header header;
+  FILE *f;
+  char *buffer;
+
+  if (argc != 2) {
+    fprintf (stdout, "USAGE: ckfits (filename)\n");
+    exit (2);
+  }
+
+  status = gfits_read_header (argv[1], &header);
+  if (!status) { 
+    fprintf (stdout, "%s: header\n", argv[1]);
+    exit (1);
+  }
+
+  Ntotal = gfits_matrix_size (&header);
+
+  Ndata = abs(header.bitpix / 8);
+  for (i = 0; i < header.Naxes; i++) Ndata *= header.Naxis[i];
+
+  nbytes = Ntotal - Ndata;
+  nskip = Ndata + header.size;
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stdout, "%s: open\n", argv[1]);
+    exit (1);
+  }
+
+  ALLOCATE (buffer, char, MAX (nbytes, 1));
+  fseek (f, nskip, SEEK_SET);
+  Nbytes = fread (buffer, 1, nbytes, f);
+  fclose (f);
+
+  if (Nbytes != nbytes) {
+    fprintf (stdout, "%s: short\n", argv[1]);
+    exit (1);
+  }
+
+  for (i = 0; i < nbytes; i++) {
+    if (buffer[i]) {
+      fprintf (stdout, "%s: padding\n", argv[1]);
+      exit (1);
+    }
+  }
+
+  fprintf (stdout, "%s: ok\n", argv[1]);
+  exit (0);
+
+}
+
+
Index: /branches/tools-1-0/Ohana/src/tools/src/csystem.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/csystem.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/csystem.c	(revision 13149)
@@ -0,0 +1,98 @@
+# include <ohana.h>
+
+/* csystem: convert between celestial, galactic, ecliptic, and
+   hoziron systems */
+
+int main (int argc, char **argv) {
+
+  /* USAGE: csystem [C/G/E/H] [C/G/E/H] [epoch] */
+  double x, y, X, Y, Xo, xo, phi, T;
+  double sin_x, sin_y, cos_x, cos_y;
+  
+  if (((argc == 3) && ((argv[1][0] == 'E') || (argv[2][0] == 'E'))) || 
+      ((argc == 4) && ((argv[1][0] != 'E') && (argv[2][0] != 'E'))) ||
+      ((argc != 3) && (argc != 4))) {
+    fprintf (stderr, "USAGE: csystems [C/G/E/H] [C/G/E/H] [epoch]\n");
+    exit (2);
+  }
+
+  switch (argv[1][0]) {
+  case 'C':
+    switch (argv[2][0]) {
+    case 'C': 
+      phi = Xo = xo = 0.0;
+      break;
+    case 'G':
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      T = (atof (argv[3]) - 1900) / 100.0;
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'E':
+    switch (argv[2][0]) {
+    case 'C': 
+      T = (atof (argv[3]) - 1900) / 100.0;
+      phi = 23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T;
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    case 'G':
+      fprintf (stderr, "error: not working!\n");
+      exit (1);
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      phi = Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'G':
+    switch (argv[2][0]) {
+    case 'C': 
+      phi = 62.6*RAD_DEG;
+      Xo = 33;
+      xo = 282.25;
+      break;
+    case 'G':
+      phi = Xo = xo = 0.0;
+      break;
+    case 'E':
+      fprintf (stderr, "error: not working!\n");
+      exit (1);
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      Xo = xo = 0.0;
+      break;
+    }
+  }
+ 
+  Xo *= RAD_DEG;
+  for (; fscanf (stdin, "%lf %lf", &X, &Y) == 2;) {
+    
+    X *= RAD_DEG;
+    Y *= RAD_DEG;
+
+    sin_y = cos(Y)*sin(X - Xo)*sin(phi) + sin(Y)*cos(phi);
+    cos_y = sqrt (1 - sin_y*sin_y);
+    sin_x = (cos(Y)*sin(X - Xo)*cos(phi) - sin(Y)*sin(phi)) /  cos_y;
+    cos_x = cos(Y)*cos(X - Xo) / cos_y;
+/*    fprintf (stderr, "%f %f   %f %f   %f %f\n", X, Y, sin_x, cos_x, sin_y, cos_y); */
+    
+    x = (DEG_RAD * atan2 (sin_x, cos_x) + xo + 360);
+    
+    while (x >= 360.0)
+      x -= 360;
+    y = DEG_RAD * atan2 (sin_y, cos_y);
+    
+    fprintf (stdout, "%10.6f %10.6f\n", x, y);
+  }
+  exit (0);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/fhead.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/fhead.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/fhead.c	(revision 13149)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int main (int argc, char **argv) {
+
+  int N, Extend, Nextend, status;
+  int i, j, nbytes;
+  Header head;
+  char *p;
+
+  Extend = FALSE;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    Extend = TRUE;
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  for (i = 1; i < argc; i++) {
+    if (argc != 2) 
+      fprintf (stdout, "------> %s <------\n", argv[i]);
+    
+    if (Extend) {
+      status = gfits_read_Xheader (argv[i], &head, Nextend);
+    } else {
+      status = gfits_read_header (argv[i], &head);
+    }      
+
+    if (!status) continue;
+
+    for (j = 79; j < head.size; j+= 80) {
+      head.buffer[j] = 10;
+    }
+
+    p = gfits_header_field (&head, "END", 1);
+    nbytes = p - head.buffer;
+    fwrite (head.buffer, nbytes, 1, stdout);
+    gfits_free_header (&head);
+
+  }
+  exit (0);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/fields.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/fields.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/fields.c	(revision 13149)
@@ -0,0 +1,130 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <sys/types.h>
+# include <regex.h>
+
+int print_fields (char *filename, char *extname, Header *header, int argc, char **argv);
+
+int usage () {
+
+  fprintf (stderr, "USAGE: fields [options] [KEYWORD] [KEYWORD]...\n");
+  fprintf (stderr, " reads filenames from stdin, writes header values to stdout\n");
+  fprintf (stderr, " options:\n");
+  fprintf (stderr, " -x (extnum)  : PHU is -1, followed by 0,1,2...\n");
+  fprintf (stderr, " -n (extname) : name may include a regex for EXTNAME values\n");
+
+  exit (2);
+}
+
+int main (int argc, char **argv) {
+
+  int i;
+  FILE *f;
+  Header header;
+  char filename[1000], *Extname, extname[80];
+  int N, Nbytes, Extnum, Nextend, status, GotFile, GotField, GotExtension;
+
+  regex_t preg;
+
+  if (get_argument (argc, argv, "-h")) usage();
+  if (get_argument (argc, argv, "--help")) usage();
+
+  Extnum = FALSE;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    Extnum = TRUE;
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Extname = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    Extname = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    regcomp (&preg, Extname, REG_EXTENDED);
+  }
+
+  GotFile  = TRUE; 
+  GotField = TRUE;
+
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    if (!Extnum && !Extname) {
+      GotFile &= gfits_read_header (filename, &header);
+      GotField &= print_fields (filename, NULL, &header, argc, argv);
+      continue;
+    }
+    if (Extnum) {
+      GotFile  &= gfits_read_Xheader (filename, &header, Nextend);
+      GotField &= print_fields (filename, NULL, &header, argc, argv);
+      continue;
+    } 
+
+    if (Extname) {
+      /* keep reading headers, only parse fields for matching headers */
+      Nextend = 0;
+      GotExtension = FALSE;
+      f = fopen (filename, "r");
+      if (f == NULL) {
+	GotFile = FALSE;
+	continue;
+      }
+      while (gfits_fread_header (f, &header)) {
+	/* extract the EXTNAME for this component (set to PHU for 0th component) */
+	status = gfits_scan (&header, "EXTNAME", "%s", 1, extname);
+	if (!status) {
+	  if (Nextend == 0) {
+	    strcpy (extname, "PHU");
+	  } else {
+	    strcpy (extname, "UNKNOWN");
+	  }
+	}
+	if (!regexec (&preg, extname, 0, NULL, 0)) {
+	  GotField &= print_fields (filename, extname, &header, argc, argv);
+	  GotExtension = TRUE;
+	}   
+    
+	Nbytes = gfits_matrix_size (&header);
+	fseek (f, Nbytes, SEEK_CUR);
+	Nextend ++;
+
+	GotFile = gfits_read_Xheader (filename, &header, Nextend);
+	continue;
+      } 
+      fclose (f);
+      if (Nextend == 0) {
+	GotFile = FALSE;
+      }
+    }
+  }
+
+  if (Extname) regfree (&preg);
+
+  if (!GotFile) exit (1);
+  if (!GotField) exit (2);
+  if (!GotExtension) exit (3);
+  exit (0);
+}
+
+int print_fields (char *filename, char *extname, Header *header, int argc, char **argv) {
+
+  int i, status, GotField;
+  char buffer[1000];
+
+  GotField = TRUE;
+
+  if (extname) {
+    fprintf (stdout, "%s[%s]  ", filename, extname);
+  } else {
+    fprintf (stdout, "%s  ", filename);
+  }
+  for (i = 1; i < argc; i++) {
+    bzero (buffer, 1000);
+    GotField &= gfits_scan (header, argv[i], "%s", 1, buffer);
+    stripwhite (buffer);
+    fprintf (stdout, "%s  ", buffer);
+  }
+  fprintf (stdout, "\n");
+  gfits_free_header (header);
+  return (GotField);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/findexec.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/findexec.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/findexec.c	(revision 13149)
@@ -0,0 +1,121 @@
+# include <stdio.h>
+# include <strings.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <stdlib.h>
+
+# define TRUE 1
+# define FALSE 0
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+int _check_permissions (char *filename) {
+  
+  FILE *f;
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to exec file */
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IXUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IXGRP)) || 
+	(                            (filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IXOTH))) {
+      return (TRUE);
+    } else {
+      fprintf (stderr, "can't exec %s\n", filename);
+      return (FALSE);
+    }
+  }
+  fprintf (stderr, "no such file %s\n", filename);
+  return (FALSE);
+}
+
+char *pathname (char *name) {
+ 
+  char *c, *path;
+
+  ALLOCATE (path, char, strlen(name) + 1);
+  strcpy (path, name);
+  c = strrchr (path, '/');
+  if (c == (char *) NULL) {
+    strcpy (path, ".");
+  } else {
+    *c = 0;
+  }
+  
+  return (path);
+  
+}
+
+char *findexec (int argc, char **argv) {
+
+  int i, N, done, status;
+  char *c, *e, *dir, path[1024], name[1024];
+  struct stat state;
+
+  if (argv[0][0] == '/') {
+    status = _check_permissions (argv[0]);
+    if (status) {
+      realpath (argv[0], path);
+      dir = pathname (path);
+      return (dir);
+    }
+  }
+
+  N = 0;
+  for (i = argc+1; argv[i] != (char *) NULL; i++) {
+    if (!strncmp (argv[i], "PATH", 4)) {
+      N = i;
+      break;
+    }
+  }
+
+  if (N) {
+    c = &argv[N][5];
+    e = strchr (c, ':');
+    done = FALSE;
+    i = 0;
+    while (!done && (i < 50)) {
+      if (e == (char *) NULL) {
+	done = TRUE;
+	bzero (path, 256);
+	strncpy (path, c, strlen(c));
+      } else {
+	bzero (path, 256);
+	strncpy (path, c, e-c);
+	c = e+1;
+	e = strchr (c, ':');
+      }
+      sprintf (name, "%s/%s", path, argv[0]);
+      status = _check_permissions (name);
+
+      if (status) {
+	realpath (name, path);
+	dir = pathname (path);
+	return (dir);
+      }
+    }
+    i++;
+  }
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/fits_insert.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/fits_insert.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/fits_insert.c	(revision 13149)
@@ -0,0 +1,166 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+static char reserved[] =  "COMMENT  Reserved space.  This line can be used to add a new FITS card.         ";
+static char blankline[] = "                                                                                ";
+
+int main (int argc, char **argv) {
+
+  int i, N, status, EXTNUM, Nbytes, skip;
+  int Nreserved, start_size;
+  char *p, keyword[16], line[256];
+  FILE *f;
+  Header header;
+  int COMMENT, Cnumber;
+  char *Cline;
+
+  /* check for command line options */
+  COMMENT = FALSE;
+  if ((N = get_argument (argc, argv, "-comment"))) {
+    COMMENT = TRUE;
+    remove_argument (N, &argc, argv);
+    Cnumber = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Cline = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  EXTNUM = -1; /* -1 is primary header */
+  if ((N = get_argument (argc, argv, "-X"))) {
+    remove_argument (N, &argc, argv);
+    EXTNUM = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: gfits_insert (image.fits) (header.hdx) [-X N] [-comment N line]\n");
+    exit (2);
+  }
+  
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "can't open fits file %s\n", argv[1]);
+    exit (1);
+  }
+
+  /* load header from image file */
+  Nbytes = gfits_fread_Xheader (f, &header, EXTNUM);
+  if (!Nbytes) {
+      fprintf (stderr, "can't read extension %d\n", EXTNUM);
+      exit (1);
+  }
+  start_size = header.size;
+  skip = Nbytes - header.size;
+
+  /* open header data file */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open header data file %s\n", argv[2]);
+    exit (1);
+  }
+
+  /* wipe out COMMENT N and replace with given line */ 
+  if (COMMENT) {
+
+    /* create a pristine FITS line */
+    snprintf (line, 81, "COMMENT  %-71s", Cline);
+
+    p = gfits_header_field (&header, "COMMENT", Cnumber);
+    if (p != (char *) NULL) {
+      strncpy (p, line, 80);
+    }
+  }
+
+  /* run through the lines in the header data file */
+  while (scan_line (f, line) != EOF) {
+    
+    /* fill in end of line with blanks, force end at 80 */
+    for (N = strlen (line); N < 80; N++) {
+      line[N] = ' ';
+    }
+    line[80] = 0;
+    bzero (keyword, 10);
+    strncpy (keyword, line, 8);
+    
+    /* replace existing keywords, unless this is a COMMENT or HISTORY field */
+    if (strncmp (keyword, "COMMENT ", 8) && strncmp (keyword, "HISTORY ", 8)) {
+      p = gfits_header_field (&header, keyword, 1);
+      if (p != (char *) NULL) {
+	strncpy (p, line, 80);
+	continue;
+      }
+    }
+
+    /* check that the line does not already exist */
+    p = (char *) NULL;
+    for (i = 0; (i < header.size) && (p == (char *) NULL) ; i+= FT_LINE_LENGTH) {
+      if (!strncmp (&header.buffer[i], line, 80)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p != (char *) NULL) continue;
+
+    /* find first line with the reserved line */
+    p = (char *) NULL;
+    Nreserved = strlen (reserved);
+    for (i = 0; (i < header.size) && (p == (char *) NULL) ; i+= FT_LINE_LENGTH) {
+      if (!strncmp (&header.buffer[i], "END     ", 8)) break;
+      if (!strncmp (&header.buffer[i], reserved, Nreserved)) {
+	p = &header.buffer[i];
+      }
+      if (!strncmp (&header.buffer[i], blankline, Nreserved)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p == (char *) NULL) {
+      fprintf (stdout, "no more reserved spaces, trying for extra space in block\n");
+      p = gfits_header_field (&header, "END", 1);
+      if (p == (char *) NULL) {
+	fprintf (stderr, "header is missing END\n");
+	exit (1);
+      }
+      if (p - header.buffer + 80 == header.size) {
+	fprintf (stderr, "no free space in block, can't insert keyword\n");
+	exit (1);
+      }
+      strncpy (p+80, "END", 3);
+      for (i = 3; i < 80; i++) { p[80+i] = ' '; }
+    }
+    /* insert the new line here */
+    strncpy (p, line, 80);
+  }
+  if (fclose (f)) {
+    fprintf (stderr, "error reading new keywords\n");
+    exit (1);
+  }
+
+  /* now write the new header on top of the old one. 
+     check first that the header size has not changed.
+  */
+
+  if (header.size != start_size) {
+    fprintf (stderr, "header changed size: should not happen!\n");
+    exit (1);
+  }
+
+  f = fopen (argv[1], "r+");
+  if (f == NULL) {
+    fprintf (stderr, "can't open file for update %s\n", argv[1]);
+    exit (1);
+  }
+
+  fseek (f, skip, SEEK_SET);
+  status = fwrite (header.buffer, 1, header.size, f);
+  if (status != header.size) {
+    fprintf (stderr, "failed to write data to image header\n");
+    exit (1);
+  }
+  if (fclose (f)) {
+    fprintf (stderr, "error writing data to disk\n");
+    exit (1);
+  }
+
+  exit (0);
+}
+    
Index: /branches/tools-1-0/Ohana/src/tools/src/ftable.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/ftable.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/ftable.c	(revision 13149)
@@ -0,0 +1,408 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+char *print_table_row (char *row, Header *header);
+FILE *load_extension (char *file, int Nextend, char *Extname, Header *header);
+void print_column (FTable *table, int Column, char *Colname);
+void usage();
+void list_extnames (char *file);
+void print_layout (Header *header);
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int Binary;
+
+int main (int argc, char **argv) {
+
+  int i, N, Nx, Ny, Nbytes, Nread;
+  int Nextend, Column, Row, ListExtname, Layout;
+  char *Extname, *Colname, *line, ttype[80];
+  FTable table;
+  Header header;
+  FILE *f;
+
+  if (get_argument (argc, argv, "-h")) usage ();
+  if (get_argument (argc, argv, "--help")) usage ();
+
+  Nextend = 0;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Extname = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    if (Nextend) usage ();
+    remove_argument (N, &argc, argv);
+    Extname = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Row = 0;
+  if ((N = get_argument (argc, argv, "-row"))) {
+    remove_argument (N, &argc, argv);
+    Row = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Column = 0;
+  if ((N = get_argument (argc, argv, "-ncolumn"))) {
+    remove_argument (N, &argc, argv);
+    Column = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Colname = 0;
+  if ((N = get_argument (argc, argv, "-column"))) {
+    if (Column) usage ();
+    remove_argument (N, &argc, argv);
+    Colname = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  ListExtname = FALSE;
+  if ((N = get_argument (argc, argv, "-list"))) {
+    remove_argument (N, &argc, argv);
+    ListExtname = TRUE;
+  }
+
+  Layout = FALSE;
+  if ((N = get_argument (argc, argv, "-layout"))) {
+    remove_argument (N, &argc, argv);
+    Layout = TRUE;
+  }
+
+  if (argc != 2) usage ();
+
+  if (ListExtname) list_extnames (argv[1]);
+
+  /* load header */
+  table.header = &header;
+  f = load_extension (argv[1], Nextend, Extname, table.header);
+
+  if (Layout) print_layout (table.header);
+
+  Binary = FALSE;
+  gfits_scan (table.header, "XTENSION", "%s", 1, ttype);
+  if (!strcmp (ttype, "BINTABLE")) Binary = TRUE;
+
+  /* load table data array */
+  Nbytes = gfits_matrix_size (table.header);
+  ALLOCATE (table.buffer, char, Nbytes);
+  Nread = fread (table.buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    fprintf (stderr, "failed to read all table data\n");
+    exit (1);
+  }
+  table.size = Nbytes;
+
+  gfits_scan (table.header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (table.header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* print a column */
+  if (Column || (Colname != (char *) NULL)) print_column (&table, Column, Colname);
+
+  /* print a row */
+  if (Row) {
+    line = print_table_row (&table.buffer[Nx*Row], table.header);
+    fprintf (stdout, "%s\n", line);
+    free (line);
+    exit (0);
+  }
+
+  /* print complete table */
+  for (i = 0; i < Ny; i++) {
+    line = print_table_row (&table.buffer[Nx*i], table.header);
+    fprintf (stdout, "%s\n", line);
+    free (line);
+  }    
+  exit (0);
+}
+
+/* print an ASCII table to a row with single spaces separating value */
+char *print_table_row (char *row, Header *header) {
+  
+  int i, j, Nx, Nfields, Nbytes, Nvals, Oout, Oin;
+  char field[16], type[16], format[16], *line;
+
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+
+  /* assume we have one space per byte column */
+  ALLOCATE (line, char, 2*Nx + 1);
+
+  Oin = Oout = 0;
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format); /* get field format */
+    gfits_table_format (format, type, &Nvals, &Nbytes);    /* convert to c-style */
+    memcpy (&line[Oout], &row[Oin], Nvals*Nbytes);
+    for (j = 0; j < Nvals*Nbytes; j++) if (line[Oout+j] == 0) line[Oout+j] = ' ';
+    line[Oout+Nvals*Nbytes] = ' ';
+    Oout += Nvals*Nbytes + 1;
+    Oin += Nvals*Nbytes;
+  }
+
+  return (line);
+}
+
+void usage () {
+    fprintf (stderr, "USAGE: [-h] [-N N] (table.fits)\n");
+    fprintf (stderr, " -x N:       operate on extension N (0 is default)\n");
+    fprintf (stderr, " -n EXTNAME: operate on named extension (incompatible with -x)\n");
+    fprintf (stderr, " -row N:     print row number N\n");
+    fprintf (stderr, " -column n:  print column named n\n");
+    fprintf (stderr, " -ncolumn N: print column number N\n");
+    fprintf (stderr, " -list:      print extension names\n");
+    exit (2);
+}
+
+void list_extnames (char *file) {
+
+  FILE *f;
+  int i, Naxis, Nelem, Ncomp, extend, Nbytes, status;
+  char extname[82], exttype[82], axisname[32];
+  Header header;
+
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file %s\n", file);
+    exit (1);
+  }
+
+  /* 
+     if (!gfits_fread_header (f, &header)) {
+     fprintf (stderr, "can't read header from %s\n", file);
+     exit (1);
+     }
+     Nbytes = gfits_matrix_size (&header);
+     fseek (f, Nbytes, SEEK_CUR);
+  */
+
+  fprintf (stdout, "%-30s %-15s NAXIS NAXIS(i)...\n", "extname", "datatype"); 
+
+  Ncomp = 0;
+  while (gfits_fread_header (f, &header)) {
+    /* extract the EXTNAME for this component (set to PHU for 0th component) */
+    status = gfits_scan (&header, "EXTNAME", "%s", 1, extname);
+    if (!status) {
+      if (Ncomp == 0) {
+	strcpy (extname, "PHU");
+      } else {
+	strcpy (extname, "UNKNOWN");
+      }
+    }
+    fprintf (stdout, "%-30s ", extname);
+
+    /* extract the datatype for this component (IMAGE for 0th component) */
+    if (Ncomp == 0) {
+      strcpy (exttype, "IMAGE");
+    } else {
+      status = gfits_scan (&header, "XTENSION", "%s", 1, exttype);
+      if (!status) {
+	strcpy (exttype, "UNKNOWN");
+      }
+    }
+    fprintf (stdout, "%-15s ", exttype);
+
+    /* extract the rank of the component */
+    status = gfits_scan (&header, "NAXIS",  "%d", 1, &Naxis);
+    if (!status) {
+      fprintf (stderr, "component %d is missing Naxis!\n", Ncomp);
+      Ncomp ++;
+      continue;
+    }
+    fprintf (stdout, " %4d", Naxis);
+
+    /* extract the individual axes */
+    for (i = 0; i < Naxis; i++) {
+      sprintf (axisname, "NAXIS%d", i+1);
+      status = gfits_scan (&header, axisname,  "%d", 1, &Nelem);
+      if (!status) {
+	fprintf (stderr, "missing %s\n", axisname);
+      }
+      fprintf (stdout, " %7d", Nelem);
+    }
+    fprintf (stdout, "\n");
+
+    /* are extensions identified? (we will scan for them anyway) */
+    if (Ncomp == 0) {
+      extend = FALSE;
+      gfits_scan (&header, "EXTEND", "%t", 1, &extend);
+      if (!extend) {
+	fprintf (stderr, "no extensions listed in file\n");
+      }
+    }
+
+    Nbytes = gfits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+
+    Ncomp ++;
+  }
+  fclose (f);
+  exit (0);
+}
+
+FILE *load_extension (char *file, int Nextend, char *Extname, Header *header) {
+
+  int i, extend, Nbytes;
+  char extname[82];
+  FILE *f;
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file %s\n", file);
+    exit (1);
+  }
+
+  /* read PHU */
+  if (!gfits_fread_header (f, header)) {
+    fprintf (stderr, "can't read header from %s\n", file);
+    exit (1);
+  }
+
+  /* check for existence of extensions */
+  extend = FALSE;
+  gfits_scan (header, "EXTEND", "%t", 1, &extend);
+  if (!extend) {
+    fprintf (stderr, "no extensions listed in file\n");
+  }
+
+  /* skip first data array */
+  Nbytes = gfits_matrix_size (header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  /* search for extension of interest */
+  for (i = 0; gfits_fread_Theader (f, header); i++) {
+    if ((Extname == NULL) && (Nextend == i)) return (f);
+
+    gfits_scan (header, "EXTNAME", "%s", 1, extname);
+    if ((Extname != NULL) && (!strcmp (Extname, extname))) return (f);
+
+    Nbytes = gfits_matrix_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+    gfits_free_header (header);
+  }
+  fclose (f);
+
+  fprintf (stderr, "failed to load extension of interest\n");
+  exit (1);
+}
+
+void print_column (FTable *table, int Column, char *Colname) {
+  
+  int i, j, Nfields, Nstart, Nv, Nb, Nx, Ny;
+  Header *header;
+  char format[16], field[16], type[16], *line, *data;
+  int *Ti;
+  float *Tf;
+
+  header =  table[0].header;
+  data   =  table[0].buffer;
+
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  if (Colname != (char *) NULL) {
+    /* find matching column entry */
+    for (i = 1; i <= Nfields; i++) {
+      sprintf (field, "TTYPE%d", i);
+      gfits_scan (header, field, "%s", 1, type);
+      if (!strcmp (type, Colname)) {
+	Column = i;
+	break;
+      }
+    }
+    if (!Column) {
+      fprintf (stderr, "column %s not found\n", Colname);
+      exit (1);
+    }
+  } else {
+    /* check if Column is in range */
+    if (Column > Nfields) {
+      fprintf (stderr, "-ncolumn %d too large, only %d columns\n", Column, Nfields);
+      exit (1);
+    }
+  }
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < Column; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    if (Binary) 
+      gfits_table_format (format, type, &Nv, &Nb);
+    else 
+      gfits_bintable_format (format, type, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  sprintf (field, "TFORM%d", Column);
+  gfits_scan (header, field, "%s", 1, format);
+  if (Binary) 
+    gfits_bintable_format (format, type, &Nv, &Nb);    /* convert to c-style */
+  else 
+    gfits_table_format (format, type, &Nv, &Nb);    /* convert to c-style */
+
+  ALLOCATE (line, char, Nv*Nb + 1);
+
+  if (Binary) {
+    if (!gfits_get_bintable_column_type (header, Colname, type, &Nv)) return;
+    // if (!strcmp (type, "char")) return;
+    if (!gfits_get_bintable_column (header, table, Colname, (void **)&data)) return;
+    // this results in an array of Ny*Nv entries
+
+    for (i = 0; i < Ny; i++) {
+      if (!strcmp (type, "char")) {
+	memcpy (line, &data[i*Nx + Nstart], Nv*Nb);
+	fprintf (stdout, "%s\n", line);
+      } else {
+	for (j = 0; j < Nv; j++) {
+	  if (!strcmp (type, "int")) {
+	    memcpy (line, &data[i*Nv*Nb + Nb*j], Nb);
+	    fprintf (stdout, "%d ", *(int *)line);
+	  }
+	  if (!strcmp (type, "float")) {
+	    memcpy (line, &data[i*Nv*Nb + Nb*j], Nb);
+	    fprintf (stdout, "%e ", *(float *)line);
+	  }
+	}
+	fprintf (stdout, "\n");
+      }
+    }
+  } else {
+    for (i = 0; i < Ny; i++) {
+      memcpy (line, &data[i*Nx + Nstart], Nv*Nb);
+      sprintf (format, "%%%ds\n", Nv*Nb);
+      fprintf (stdout, format, line);
+    }
+  }
+  exit (0);
+}
+
+void print_layout (Header *header) {
+
+  int i, Nfields;
+  char field[16], type[80], comment[80], format[80], unit[80], null[80], nval[80];
+
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, type);
+    gfits_scan (header, field, "%C", 1, comment);
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    sprintf (field, "TUNIT%d", i);
+    gfits_scan (header, field, "%s", 1, unit);
+    sprintf (field, "TNULL%d", i);
+    if (!gfits_scan (header, field, "%s", 1, null)) strcpy (null, "none");
+    sprintf (field, "TNVAL%d", i);
+    if (!gfits_scan (header, field, "%s", 1, nval)) strcpy (nval, "none");
+
+    fprintf (stdout, "%-18s %-32s %-18s %-6s %-8s %-8s\n", 
+	  type, comment, unit, format, null, nval); 
+  }
+  exit (0);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/gconfig.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/gconfig.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/gconfig.c	(revision 13149)
@@ -0,0 +1,66 @@
+# include "ohana.h"
+void usage ();
+
+int main (int argc, char **argv) {
+
+  char *config, *file;
+  char word[256];
+  int i, N, VERBOSE, status;
+
+  if ((N = get_argument (argc, argv, "-h"))) { usage (); }
+  if ((N = get_argument (argc, argv, "-help"))) { usage (); }
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+
+  /* dump raw config file (no interpolation of input files */
+  if ((N = get_argument (argc, argv, "-raw"))) {
+    config = LoadRawConfigFile (file, TRUE);
+    fwrite (config, 1, strlen(config), stdout);
+    exit (0);
+  }
+
+  /* load complete config info from file(s) */
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-q"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = FALSE;
+  }
+
+  /* if no keywords, dump entire config file */
+  if (argc == 1) {
+    fwrite (config, 1, strlen(config), stdout);
+    exit (0);
+  }
+
+  status = 0;
+  for (i = 1; i < argc; i++) {
+    if (ScanConfig (config, argv[i], "%s", 0,  word) == (char *) NULL) {
+      strcpy (word, "not found");
+      status = 1;
+    }
+    if (VERBOSE) {
+      fprintf (stdout, "%s %s\n", argv[i], word);
+    } else {
+      fprintf (stdout, "%s\n", word);
+    }
+  }
+  exit (status);
+}
+
+void usage () {
+  fprintf (stderr, "gconfig: print elixir config information\n");
+  fprintf (stderr, " USAGE: gconfig [keywords...] [-c file] [-C config] [-D keyword value]\n");
+  exit (2);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/glockfile.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/glockfile.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/glockfile.c	(revision 13149)
@@ -0,0 +1,41 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  char *filename;
+  double timeout;
+  int holdtime, state, type;
+  FILE *f;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: glock (filename) (type) (holdtime)\n");
+    exit (1);
+  }
+
+  filename = argv[1];
+  timeout = 30.0;
+
+  holdtime = atoi (argv[3]);
+
+  type = 0;
+  if (!strcasecmp (argv[2], "hard")) {
+    type = LCK_HARD;
+  }
+  if (!strcasecmp (argv[2], "soft")) {
+    type = LCK_SOFT;
+  }
+  if (!strcasecmp (argv[2], "xcld")) {
+    type = LCK_XCLD;
+  }
+
+  f = fsetlockfile (filename, timeout, type, &state);
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't lock file %s\n", filename);
+    exit (1);
+  }
+
+  fprintf (stderr, "file is locked\n");
+  sleep (holdtime);
+  fclearlockfile (filename, f, type, &state);
+  exit (0);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/list_astro.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/list_astro.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/list_astro.c	(revision 13149)
@@ -0,0 +1,117 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  float *ra1, *ra2, *dec1, *dec2;
+  float x, y, x2, y2, xy, R, D, Rx, Ry, Dx, Dy, N;
+  float x3, x2y, x4, Rx2;
+  float DEC, RA, DX, DY, RX, RY, d2RA, d2DEC, dRA, dDEC;
+  float Sx2, Sy2, Sxy, Srx, Sry, Sdx, Sdy;
+  int i, Npairs, NPAIR;
+
+  NPAIR = 100;
+  ALLOCATE (ra1, float, NPAIR);
+  ALLOCATE (ra2, float, NPAIR);
+  ALLOCATE (dec1, float, NPAIR);
+  ALLOCATE (dec2, float, NPAIR);
+
+/*
+  ALLOCATE (a, double *, 3);
+  ALLOCATE (a[0], double, 3);
+  ALLOCATE (a[1], double, 3);
+  ALLOCATE (a[2], double, 3);
+  ALLOCATE (a[3], double, 4);
+  ALLOCATE (b, double *, 3);
+  ALLOCATE (b[0], double, 1);
+  ALLOCATE (b[1], double, 1);
+  ALLOCATE (b[2], double, 1);
+  ALLOCATE (b[3], double, 1);
+*/
+
+  if (argc > 1) {
+    fprintf (stderr, "USAGE: list_astro x\nTakes list from the stdin in the");
+    fprintf (stderr, " format:\n  X Y RA DEC\nReturns:\n  RA, RX, RY, dRA\n  DEC, DX, DY, dDEC\n");
+    exit(0);
+  }
+    
+  for (i = 0; fscanf (stdin, "%f %f %f %f", &ra1[i], &dec1[i], &ra2[i], &dec2[i]) != EOF; i++) {
+    if (i == NPAIR - 1) {
+      NPAIR += 50;
+      REALLOCATE (ra1, float, NPAIR);
+      REALLOCATE (ra2, float, NPAIR);
+      REALLOCATE (dec1, float, NPAIR);
+      REALLOCATE (dec2, float, NPAIR);
+    }
+  }
+
+  
+  
+  N = x = y = x2 = y2 = xy = R = D = Rx = Ry = Dx = Dy = 0;
+  Npairs = i;
+  for (i = 0; i < Npairs; i++) {
+    x  += ra1[i];
+    y  += dec1[i];
+    x2 += ra1[i]*ra1[i];
+    y2 += dec1[i]*dec1[i];
+    xy += ra1[i]*dec1[i];
+    x3 += ra1[i]*ra1[i]*ra1[i];
+    x2y += ra1[i]*ra1[i]*dec1[i];
+    x4 += ra1[i]*ra1[i]*ra1[i]*ra1[i];
+    R  += ra2[i];
+    D  += dec2[i];
+    Rx += ra2[i]*ra1[i];
+    Ry += ra2[i]*dec1[i];
+    Rx2 += ra2[i]*ra1[i]*ra1[i];
+    Dx += dec2[i]*ra1[i];
+    Dy += dec2[i]*dec1[i];
+    N  += 1.0;
+  }
+
+/*
+  a[0][0] = N;
+  a[0][1] = a[1][0] = x;
+  a[0][2] = a[2][0] = y;
+  a[0][3] = a[3][0] = x2;
+  a[1][1] = x2;
+  a[1][2] = a[2][1] = xy;
+  a[1][3] = a[3][1] = x3;
+  a[2][2] = y2;
+  a[2][3] = a[3][2] = x2y;
+  a[3][3] = x4;
+  b[0][0] = R;
+  b[1][0] = Rx;
+  b[2][0] = Ry;
+  b[1][0] = Rx2;
+*/
+
+  Sx2 = x2 - x*x/N;
+  Sy2 = y2 - y*y/N;
+  Sxy = xy - x*y/N;
+  Srx = Rx - R*x/N;
+  Sry = Ry - R*y/N;
+  Sdx = Dx - D*x/N;
+  Sdy = Dy - D*y/N;
+  
+  RX = (Srx*Sy2 - Sry*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  RY = (Sry*Sx2 - Srx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  RA = R/N - RX*x/N - RY*y/N;
+
+  DX  = (Sdx*Sy2 - Sdy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  DY  = (Sdy*Sx2 - Sdx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  DEC = D/N - DX*x/N - DY*y/N;
+
+  d2RA = d2DEC = N = 0;
+  N = x = y = x2 = y2 = xy = R = D = Rx = Ry = Dx = Dy = 0;
+  for (i = 0; i < Npairs; i++) {
+    d2RA += pow((ra2[i] - RA - RX*ra1[i] - RY*dec1[i]), 2.0);
+    d2DEC += pow((dec2[i] - DEC - DX*ra1[i] - DY*dec1[i]), 2.0);
+    N += 1.0;
+  }
+
+  dRA  = 3600.0*sqrt(d2RA / (N - 3.0));
+  dDEC = 3600.0*sqrt(d2DEC / (N - 3.0));
+
+  fprintf (stdout, " %12.9f %12.9e %12.9e %12.9f\n", RA, RX, RY, dRA);
+  fprintf (stdout, " %12.9f %12.9e %12.9e %12.9f\n", DEC, DX, DY, dDEC);
+  exit (0);
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/medianfilter.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/medianfilter.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/medianfilter.c	(revision 13149)
@@ -0,0 +1,147 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+# define D_NFILES 100
+
+void fsort (float *value, int N);
+
+int main (int argc, char **argv) {
+
+  int i, j, k, n, Npixels, Npixin, Npixrd, Npixlast, N;
+  int Npass, NFILES, Nfiles;
+
+  char **filename;
+  Header head, *tmphead;
+  Matrix out,  *tmpmatr;
+  float *list, *v, *O;
+  float fmin, fmax, Nval, sum;
+
+  if ((N = get_argument (argc, argv, "-unsign"))) {
+    remove_argument (N, &argc, argv);
+    gfits_set_unsign_mode (TRUE);
+  }
+
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: minmaxfilter outfile fmin fmax\n");
+    exit (0);
+  }
+  fmin = atof (argv[2]); 
+  fmax = atof (argv[3]); 
+
+  /* read in the filenames */
+  NFILES = D_NFILES;
+  ALLOCATE (filename, char *, NFILES);
+  ALLOCATE (filename[0], char, 1024);
+  for (i = 0; fscanf (stdin, "%s", filename[i]) != EOF; i++) {
+    if (i == NFILES - 1) {
+      NFILES += D_NFILES;
+      REALLOCATE (filename, char *, NFILES);
+    }
+    ALLOCATE (filename[i+1], char, 1024);
+  }
+  Nfiles = i;
+  REALLOCATE (filename, char *, Nfiles);
+
+  /* load a header, setup output header, matrix */
+  gfits_read_header (filename[0], &head);
+  gfits_create_matrix (&head, &out);
+  gfits_convert_format (&head, &out, -32, 1.0, 0.0, FALSE);
+
+  /* find size of temporary images */
+  Npixels = head.Naxis[0]*head.Naxis[1];
+  Npixin = Npixels / Nfiles;
+  Npixlast = Npixels - Npixin*Nfiles;
+  if (Npixlast == 0) {
+    Npass = Nfiles;
+    Npixlast = Npixin;
+    fprintf (stderr, "operating on %d pixels per pass\n", Npixin);
+  } else {
+    Npass = Nfiles + 1;
+    fprintf (stderr, "operating on %d pixels per pass, %d in last\n", Npixin, Npixlast);
+  }
+  
+  ALLOCATE (tmphead, Header, Nfiles);
+  ALLOCATE (tmpmatr, Matrix, Nfiles);
+  ALLOCATE (list, float, Nfiles);
+  Nval = 0;
+  for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+    Nval += 1.0;
+  }
+
+  O = (float *) out.buffer;
+  for (n = 0; n < Npass; n++) {
+    fprintf (stderr, "pass %d\n", n);
+    Npixrd = (n == Npass - 1) ? Npixlast : Npixin;
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ".");
+      if (!gfits_read_header  (filename[i], &tmphead[i])) {
+	fprintf (stderr, "trouble reading file %s\n", filename[i]);
+	exit (1);
+      }
+      gfits_read_portion (filename[i], &tmpmatr[i], n*Npixin, Npixrd);
+      tmphead[i].Naxis[0] = 1;
+      tmphead[i].Naxis[1] = Npixrd;
+      gfits_convert_format (&tmphead[i], &tmpmatr[i], -32, 1.0, 0.0, FALSE);
+    }
+    
+    fprintf (stderr, "starting sorts\n");
+    for (j = 0; j < Npixrd; j++, O++) {
+      for (k = 0; k < Nfiles; k++) {
+	v = (float *)tmpmatr[k].buffer;
+	list[k] = v[j];
+      }
+      fsort (list, Nfiles);
+      sum = 0;
+      for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+	sum += list[k];
+      }
+      *O = (sum / Nval);
+    }
+
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ",");
+      gfits_free_header (&tmphead[i]);
+      gfits_free_matrix (&tmpmatr[i]);
+    }
+    
+  }
+
+  gfits_write_header (argv[1], &head);
+  gfits_write_matrix (argv[1], &out);
+
+  return (0);
+
+}
+
+void fsort (float *value, int N) {
+
+  int l,j,ir,i;
+  float temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
Index: /branches/tools-1-0/Ohana/src/tools/src/mefhead.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/mefhead.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/mefhead.c	(revision 13149)
@@ -0,0 +1,98 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int main (int argc, char **argv) {
+
+  struct stat filestat;
+  int NEXTEND, Nextend, Nmatrix, status;
+  Header header;
+  FILE *f, *g;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: mefhead (input) (output)\n");
+    exit (2);
+  }
+
+  /* exit if file exists */
+  status = stat (argv[2], &filestat);
+  if (status != -1) {
+    fprintf (stderr, "error: output file exists\n");
+    exit (1);
+  } 
+  
+  /* open stream for input */
+  g = fopen (argv[1], "r");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "error: can't open input file\n");
+    exit (1);
+  } 
+
+  /* open stream for output */
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error: can't create output file\n");
+    exit (1);
+  } 
+
+  /* read PHU */
+  status = gfits_fread_header (g, &header);
+  if (!status) {
+    fprintf (stderr, "error: can't read primary header unit\n");
+    exit (1);
+  }
+  /* skip matrix */
+  Nmatrix = gfits_matrix_size (&header);
+  fseek (g, Nmatrix, SEEK_CUR);
+
+  /* write PHU */
+  gfits_modify (&header, "NAXIS", "%d", 1, 0);
+  status = gfits_fwrite_header (f, &header);
+  if (!status) {
+    fprintf (stderr, "error: can't write primary header unit\n");
+    exit (1);
+  }
+
+  /* check if NEXTEND is accurate */
+  gfits_scan (&header, "NEXTEND", "%d", 1, &NEXTEND);
+
+  Nextend = 0;
+  while (1) {
+    
+    /* read header */
+    status = gfits_fread_header (g, &header);
+    if (!status) break;
+
+    /* skip matrix */
+    Nmatrix = gfits_matrix_size (&header);
+    fseek (g, Nmatrix, SEEK_CUR);
+    
+    /* write header */
+    gfits_modify (&header, "NAXIS", "%d", 1, 0);
+    status = gfits_fwrite_header (f, &header);
+    if (!status) {
+      fprintf (stderr, "error: can't write header unit %d\n", Nextend);
+      exit (1);
+    }
+    Nextend ++;
+    gfits_free_header (&header);
+  }
+
+  if (Nextend != NEXTEND) { 
+    fprintf (stderr, "warning: mismatch in NEXTEND\n");
+  }
+
+  fclose (f);
+  fclose (g);
+  exit (0);
+
+}
+
+
+
+/* mefhead (input) (output) 
+   convert (input) MEF image file to (output) MEF header file:
+   read all headers
+   convert all lines NAXIS=2 to NAXIS=0 
+   write only headers
+
+*/
Index: /branches/tools-1-0/Ohana/src/tools/src/mktemp.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/mktemp.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/mktemp.c	(revision 13149)
@@ -0,0 +1,17 @@
+# include <stdio.h>
+# include <stdlib.h>
+
+int main (int argc, char **argv) {
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s (template)\n", argv[0]);
+    exit (1);
+  }
+
+  if (mkstemp (argv[1]) == -1) exit (1);
+
+  fprintf (stdout, "%s\n", argv[1]);
+
+  exit (0);
+}
+ 
Index: /branches/tools-1-0/Ohana/src/tools/src/precess.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/precess.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/precess.c	(revision 13149)
@@ -0,0 +1,150 @@
+# include <ohana.h>
+
+double BtoJ (double in_epoch);
+double get_epoch (char *in_epoch, char mode);
+
+int main (int argc, char **argv) {
+
+  double T, in_epoch, out_epoch;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  int Julian, Besselian;
+
+  Besselian = Julian = 0;
+  Besselian = get_argument (argc, argv, "B");
+  Julian    = get_argument (argc, argv, "J");
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE:  precess in_epoch out_epoch\n");
+    fprintf (stderr, "   you may use B for B1950.0 or J for J2000.0\n");
+    fprintf (stderr, "   Enter values in degrees\n");
+    exit (2);
+  }
+
+  if (!Julian && !Besselian) { /* assume Julian! */
+    in_epoch  = get_epoch (argv[1], 'J');
+    out_epoch = get_epoch (argv[2], 'J');
+  }
+
+  if ((Julian == 1) && !Besselian) {
+    in_epoch  = 2000.0;
+    out_epoch = get_epoch(argv[2], 'J');
+  }
+
+  if ((Julian == 2) && !Besselian) {
+    in_epoch  = get_epoch(argv[1], 'J');
+    out_epoch = 2000.0;
+  }
+
+  if ((Besselian == 1) && !Julian) {
+    in_epoch  = BtoJ(1950.0); 
+    out_epoch = get_epoch(argv[2], 'B'); 
+  }
+
+  if ((Besselian == 2) && !Julian) {
+    in_epoch  = get_epoch(argv[1], 'B'); 
+    out_epoch = BtoJ(1950.0); 
+  }
+  
+  if (Julian && Besselian) {
+    if (Julian > Besselian) {
+      in_epoch  = BtoJ(1950.0); 
+      out_epoch = 2000.0;
+    }
+    else {
+      in_epoch  = 2000.0;
+      out_epoch = BtoJ(1950.0); 
+    }
+  }
+
+  fprintf (stderr, "converting from J%f to J%f\n", in_epoch, out_epoch);
+
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+
+  while (fscanf (stdin, "%lf %lf", &A, &D) != EOF) {
+    SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+    CD = sqrt (1 - SD*SD);
+    SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+    CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+
+    DEC = DEG_RAD*asin(SD);
+    RA  = DEG_RAD*atan2(SA, CA) + z;
+
+    if (RA < 0)
+      RA += 360;
+    fprintf (stdout, "%f %f\n", RA, DEC);
+  }
+  exit (0);
+}  
+    
+
+double get_epoch (char *in_epoch, char mode) {
+
+  int done;
+  double epoch;
+
+  done = FALSE;
+  if (in_epoch[0] == 'B') {
+    epoch = BtoJ(atof(&in_epoch[1]));
+    done = TRUE;
+  }
+
+  if (in_epoch[0] == 'J') {
+    epoch = atof(&in_epoch[1]);
+    done = TRUE;
+  }
+
+  if (!done && (mode == 'B')) {
+    epoch = BtoJ(atof(in_epoch));
+    done = TRUE;
+  }
+    
+  if (!done && (mode == 'J')) {
+    epoch = atof(in_epoch);
+    done = TRUE;
+  }
+
+  if (!done) {
+    fprintf (stderr, "error finding epoch %s\n", in_epoch);
+    exit (1);
+  }
+  
+  return (epoch);
+}
+
+double BtoJ (double in_epoch) {
+
+  double JD, out_epoch;
+
+  JD = (in_epoch - 1900.0)*365.242198781 + 2415020.31352;
+  out_epoch = 2000.0 + (JD - 2451545.0)/365.25;
+
+  return (out_epoch);
+}
+
+/*
+  time =  (in_epoch - out_epoch) / 100.0;
+
+  fprintf (stderr, "precessing from %f to %f\n", in_epoch, out_epoch);
+  sinE = sin (epsilon*deg_to_rad);
+  cosE = cos (epsilon*deg_to_rad);
+  M = 1.281232*time + 0.0003879*(time*time);
+  N = 0.5567*time - 0.0001185*(time*time);
+
+  while (fscanf (stdin, "%lf %lf", &RA, &Dec) != EOF) {
+    RA = RA - M - N*sin(RA*deg_to_rad)*tan(Dec*deg_to_rad);
+    Dec = Dec - N*cos (RA*deg_to_rad);
+
+    Dec = Dec + time*thetaD*sinE*cos(RA*deg_to_rad);
+    RA = RA + time*thetaD*(cosE + sinE*sin(RA*deg_to_rad)*tan(Dec*deg_to_rad));
+
+    fprintf (stdout, "%f %f\n", RA, Dec);
+  }
+
+*/
+
+
Index: /branches/tools-1-0/Ohana/src/tools/src/radec.c
===================================================================
--- /branches/tools-1-0/Ohana/src/tools/src/radec.c	(revision 13149)
+++ /branches/tools-1-0/Ohana/src/tools/src/radec.c	(revision 13149)
@@ -0,0 +1,102 @@
+# include <ohana.h>
+
+int help ();
+int _hms_to_deg (double *h, double *d, char *string, char sep, int Nin);
+
+int main (int argc, char **argv) {
+
+  char line[1000];
+  char sep;
+  double ra, dec;
+  int status, h, m, flag;
+  double s, hh;
+
+  sep = ' ';
+  if (get_argument (argc, argv, "-hms")) {
+    while (scan_line (stdin, line) != EOF) {
+      status = _hms_to_deg (&ra, &dec, line, sep, 3);
+      if (status)
+	fprintf (stdout, "%10.6f %10.6f\n", ra, dec);
+    }
+    exit (0);
+  }
+    
+  if (get_argument (argc, argv, "-hh")) {
+    while (scan_line (stdin, line) != EOF) {
+      dparse (&hh, 1, line);
+      hh /= 15.0;  /* convert from degrees to hours */
+      flag = SIGN(hh);
+      hh *= flag;
+      h = hh;
+      m = 60.000001*(hh - h);
+      s = 3600*(hh - h - m / 60.0);
+      if (flag > 0)
+	fprintf (stdout, " %02d%c%02d%c%06.3f  ", h, sep, m, sep, s);
+      else
+	fprintf (stdout, "-%02d%c%02d%c%06.3f  ", h, sep, m, sep, s);
+      dparse (&hh, 2, line);
+      flag = SIGN(hh);
+      hh *= flag;
+      h = hh;
+      m = 60.000001*(hh - h);
+      s = 3600*(hh - h - m / 60.0);
+      if (flag > 0)
+	fprintf (stdout, " %02d%c%02d%c%06.3f\n", h, sep, m, sep, s);
+      else
+	fprintf (stdout, "-%02d%c%02d%c%06.3f\n", h, sep, m, sep, s);
+    }
+    exit (0);
+  }
+
+  fprintf (stderr, "USAGE: %s [-hh/-hms] \n", argv[0]);
+  fprintf (stderr, "  -hh:  convert from decimal ra,dec to hours, min sec\n");
+  fprintf (stderr, "  -hms: convert from hours, min sec to decimal ra,dec\n");
+  exit (2);
+}
+
+/**********/
+int _hms_to_deg (double *h, double *d, char *string, char sep, int Nin) {
+  
+  char *c;
+  int i, flag_d, flag_h, Nfields;
+  double tmp;
+  
+  *d = *h = 0;
+  stripwhite (string);
+  for (Nfields = 2, i = 0; i < 2*(Nin - 1); i++) {
+    if ((c = strchr (string, sep)) != NULL) {
+      Nfields ++;
+      *c = ' ';
+    }
+  }
+  if (Nfields != 2*Nin) {
+    fprintf (stderr, "warning -- line with too few entries, skipping:  %d != %d\n", Nfields, Nin);
+    return (FALSE);
+  }
+
+  Nfields /= 2;
+
+  flag_h = dparse (h, 1, string);
+  flag_d = dparse (d, Nfields + 1, string);
+  *h *= flag_h;
+  *d *= flag_d;
+
+  if (Nfields > 1) {
+    dparse (&tmp, 2, string);
+    *h += tmp/60.0;
+    dparse (&tmp, Nfields + 2, string);
+    *d += tmp/60.0;
+  }
+
+  if (Nfields > 2) {
+    dparse (&tmp, 3, string);
+    *h += tmp/3600.0;
+    dparse (&tmp, Nfields + 3, string);
+    *d += tmp/3600.0;
+  }
+  
+  *h *= 15*flag_h;
+  *d *= flag_d;
+
+  return (TRUE);
+}
